using System; using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using UnityEngine; namespace vnxbqy.UI { public class ReikiRootModel : Model, IBeforePlayerDataInitialize, IPlayerLoginOk { Dictionary m_ReikiRootPoints = new Dictionary(); Dictionary m_ReikiRootFreePoints = new Dictionary(); Dictionary> m_RecommendReikiRoots = new Dictionary>(); Dictionary m_ReikiQualityMapColors; Dictionary m_CacheReikiRootPoints = new Dictionary(); Dictionary>> m_PromotePropertyValues = new Dictionary>>(); Dictionary m_ReikiPropertyValues = new Dictionary(); Dictionary>> m_ReikiPointPropertys = new Dictionary>>(); Dictionary> m_PreLimitReikiRoots = new Dictionary>(); Dictionary> m_AfterLimitReikiRoots = new Dictionary>(); public Dictionary lastReikiRootPoints = new Dictionary(); public Dictionary afterReikiRootPoints = new Dictionary(); public List reikiRoots = new List(); public Dictionary> qualityPropertySorts = new Dictionary>(); public int freePoint { get { return (int)PlayerDatas.Instance.baseData.FreePoint; } } int lastFreePoint = 0; int m_CacheFreePoint = 0; public int cacheFreePoint { get { return m_CacheFreePoint; } set { if (m_CacheFreePoint != value) { m_CacheFreePoint = value; if (onCacheFreePointRefresh != null) { onCacheFreePointRefresh(); } } } } public int maxQuality { get; private set; } private Int3 redpointRequirePoint; public int freeResetLevel { get; private set; } public int[] resetCostItemIds { get; private set; } public int[] reikiRootGetWays { get; private set; } public bool isServerPrepare { get; private set; } public bool displayOpenAnimation { get { return LocalSave.GetBool("ReikiRootOpenAnimation"); } set { LocalSave.SetBool("ReikiRootOpenAnimation", value); } } public bool resetReikiRootRecord { get; set; } public bool resetReikiRemind { get; set; } public int resetReikiLimitLevel { get; private set; } public int selectReikiRoot { get; set; } public bool openFromTreasureSkill { get; set; } public bool reikiPointPromoteSymbol { get; set; } public int effectLimitLevel { get; private set; } public int reikiPointAutoAddLevel { get; private set; } public int levelUpAddPoint { get; private set; } public int afterReikiRootLimitLevel { get; private set; } public TitleAddPoint titleAddPoint { get; private set; } public TreasureAddPoint treasureAddPoint { get; private set; } public readonly Redpoint redpoint = new Redpoint(101, 10103); public event Action onCacheFreePointRefresh; public event Action onReikiRootPointRefresh; public event Action onReikiRootPointReset; public event Action onReikiRootEffectRefresh; TreasureModel treasureModel { get { return ModelCenter.Instance.GetModel(); } } TreasureSkillModel treasureSkillModel { get { return ModelCenter.Instance.GetModel(); } } public override void Init() { ParseConfig(); PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefreshEvent; FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent; StageLoad.Instance.onStageLoadFinish += OnStageLoadFinish; WindowCenter.Instance.windowAfterCloseEvent += WindowAfterCloseEvent; } public void OnBeforePlayerDataInitialize() { m_ReikiRootPoints.Clear(); m_ReikiRootFreePoints.Clear(); isServerPrepare = false; resetReikiRootRecord = false; reikiPointPromoteSymbol = false; } public void OnPlayerLoginOk() { RefreshReikiRootPoint(); lastFreePoint = freePoint; isServerPrepare = true; } public override void UnInit() { PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefreshEvent; FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent; StageLoad.Instance.onStageLoadFinish -= OnStageLoadFinish; WindowCenter.Instance.windowAfterCloseEvent -= WindowAfterCloseEvent; } void ParseConfig() { var funcConfig = FuncConfigConfig.Get("RecommendPoint"); var json = LitJson.JsonMapper.ToObject(funcConfig.Numerical1); foreach (var jobKey in json.Keys) { var job = int.Parse(jobKey); m_RecommendReikiRoots.Add(job, new List(LitJson.JsonMapper.ToObject(json[jobKey].ToJson()))); } m_ReikiQualityMapColors = ConfigParse.GetDic(funcConfig.Numerical2); Int3.TryParse(funcConfig.Numerical3, out redpointRequirePoint); reikiRootGetWays = ConfigParse.GetMultipleStr(funcConfig.Numerical4); effectLimitLevel = int.Parse(funcConfig.Numerical5); funcConfig = FuncConfigConfig.Get("LVUPAddPoint"); var match = Regex.Match(funcConfig.Numerical1, @"\(([0-9]+)\,[0-9]+\):([0-9]+)"); if (match != null) { reikiPointAutoAddLevel = int.Parse(match.Groups[1].Value); levelUpAddPoint = int.Parse(match.Groups[2].Value); } freeResetLevel = int.Parse(funcConfig.Numerical4); resetCostItemIds = LitJson.JsonMapper.ToObject(funcConfig.Numerical5); funcConfig = FuncConfigConfig.Get("LimitAddPoint"); json = LitJson.JsonMapper.ToObject(funcConfig.Numerical1); foreach (var jobKey in json.Keys) { var job = int.Parse(jobKey); m_PreLimitReikiRoots.Add(job, new List(LitJson.JsonMapper.ToObject(json[jobKey].ToJson()))); } resetReikiLimitLevel = int.Parse(funcConfig.Numerical2); json = LitJson.JsonMapper.ToObject(funcConfig.Numerical3); foreach (var jobKey in json.Keys) { var job = int.Parse(jobKey); m_AfterLimitReikiRoots.Add(job, new List(LitJson.JsonMapper.ToObject(json[jobKey].ToJson()))); } afterReikiRootLimitLevel = int.Parse(funcConfig.Numerical4); funcConfig = FuncConfigConfig.Get("TitleAddPoint"); titleAddPoint = new TitleAddPoint() { titleId = int.Parse(funcConfig.Numerical1), point = int.Parse(funcConfig.Numerical2), }; funcConfig = FuncConfigConfig.Get("FabaoAddPoint"); treasureAddPoint = new TreasureAddPoint() { treasureId = int.Parse(funcConfig.Numerical1), point = int.Parse(funcConfig.Numerical2), }; var config = ReikiRootConfig.GetValues()[0]; maxQuality = config.qualityArea.Length; reikiRoots.Add((int)PropertyType.Mater); reikiRoots.Add((int)PropertyType.Wood); reikiRoots.Add((int)PropertyType.Water); reikiRoots.Add((int)PropertyType.Fire); reikiRoots.Add((int)PropertyType.Earth); var configs = ReikiRootConfig.GetValues(); foreach (var _config in configs) { m_PromotePropertyValues.Add(_config.id, new Dictionary>()); var _json = LitJson.JsonMapper.ToObject(_config.promoteProperty); foreach (var _jobKey in _json.Keys) { var job = int.Parse(_jobKey); m_PromotePropertyValues[_config.id].Add(job, new List()); if (!qualityPropertySorts.ContainsKey(job)) { qualityPropertySorts.Add(job, new List()); } foreach (var _propertyKey in _json[_jobKey].Keys) { var _property = int.Parse(_propertyKey); m_PromotePropertyValues[_config.id][job].Add(new ReikiQualityProperty() { property = _property, propertyValues = LitJson.JsonMapper.ToObject(_json[_jobKey][_propertyKey].ToJson()) } ); if (!qualityPropertySorts[job].Contains(_property)) { qualityPropertySorts[job].Add(_property); } } } _json = LitJson.JsonMapper.ToObject(_config.propertyPerPoint); m_ReikiPointPropertys.Add(_config.id, new Dictionary>()); foreach (var jobKey in _json.Keys) { var job = int.Parse(jobKey); m_ReikiPointPropertys[_config.id].Add(job, new List()); var array = LitJson.JsonMapper.ToObject(_json[jobKey].ToJson()); for (int i = 0; i < array.Length; i++) { m_ReikiPointPropertys[_config.id][job].Add(new ReikiPointProperty() { point = array[i][0], property = array[i][1], value = array[i][2], }); } } } foreach (var propertys in qualityPropertySorts.Values) { propertys.Sort((x, y) => { var lhs_atk = x == (int)PropertyType.ATK; var rhs_atk = y == (int)PropertyType.ATK; if (lhs_atk != rhs_atk) { return -lhs_atk.CompareTo(rhs_atk); } return x.CompareTo(y); }); } } private void OnStageLoadFinish() { if (!(StageLoad.Instance.currentStage is DungeonStage)) { resetReikiRemind = false; } } private void OnFuncStateChangeEvent(int id) { if (id == (int)FuncOpenEnum.ReikiRoot) { RefreshRedpoint(); if (isServerPrepare && FuncOpen.Instance.IsFuncOpen(id)) { displayOpenAnimation = true; } } } private void WindowAfterCloseEvent(Window window) { if (window is TreasureNewGotWin) { if (treasureModel.newGotTreasureId == treasureAddPoint.treasureId) { SnxxzGame.Instance.StartCoroutine(Co_OpenTreasureAddPointRemind()); } } } IEnumerator Co_OpenTreasureAddPointRemind() { yield return WaitingForSecondConst.WaitMS500; if (!NewBieCenter.Instance.inGuiding) { var reikiPoint = 0; if (PlayerDatas.Instance.baseData.LV >= reikiPointAutoAddLevel) { var levels = PlayerDatas.Instance.baseData.LV - reikiPointAutoAddLevel + 1; reikiPoint = levels * treasureAddPoint.point; } var treasureConfig = TreasureConfig.Get(treasureAddPoint.treasureId); ConfirmCancel.ShowRealmPopConfirm(Language.Get("Mail101"), Language.Get("ReikiRootAddPointRemind_1", treasureConfig.Name, reikiPoint), Language.Get("GotoAddPoint"), () => { WindowJumpMgr.Instance.WindowJumpTo(JumpUIType.RolePoint); }); } } public int GetReikiRootQuality(int id, int point) { var config = ReikiRootConfig.Get(id); if (config == null) { return 0; } var quality = 0; for (int i = 0; i < config.qualityArea.Length; i++) { if (point >= config.qualityArea[i]) { quality = i + 1; } else { break; } } return quality; } public int GetMaxReikiRootQuality(int id) { var config = ReikiRootConfig.Get(id); if (config == null) { return 0; } return config.qualityArea.Length; } public int GetReikiRootQuality(int id) { return GetReikiRootQuality(id, GetReikiRootPoint(id)); } public int GetReikiRootPoint(int id) { return m_ReikiRootPoints.ContainsKey(id) ? m_ReikiRootPoints[id] : 0; } public int GetReikiRootFreePoint(int id) { return m_ReikiRootFreePoints.ContainsKey(id) ? m_ReikiRootFreePoints[id] : 0; } int GetReikiRootCachePoint(int id) { return m_CacheReikiRootPoints.ContainsKey(id) ? m_CacheReikiRootPoints[id] : 0; } public int GetTotalWashPoint() { var totalPoint = 0; foreach (var point in m_ReikiRootFreePoints.Values) { totalPoint += point; } return totalPoint; } public int GetReikiRootTotalPoint() { var point = 0; foreach (var _point in m_ReikiRootPoints.Values) { point += _point; } return point; } public int GetReikiRootTotalPointWithFree() { return GetReikiRootTotalPoint() + freePoint; } public List GetReikiRootRecommendPoint(int point) { if (point == 0) { return null; } m_CacheReikiRootPoints.Clear(); foreach (var id in m_ReikiRootPoints.Keys) { m_CacheReikiRootPoints[id] = m_ReikiRootPoints[id]; } var recommends = new List(); var job = PlayerDatas.Instance.baseData.Job; if (m_RecommendReikiRoots.ContainsKey(job)) { var reikis = m_RecommendReikiRoots[job]; var surplusPoint = point; while (surplusPoint > 0) { reikis.Sort((int x, int y) => { var x_point = GetReikiRootCachePoint(x); var y_point = GetReikiRootCachePoint(y); if (x_point != y_point) { return x_point.CompareTo(y_point); } return x.CompareTo(y); }); var minpoint = GetReikiRootCachePoint(reikis[0]); var samepointIds = reikis.FindAll((x) => { return GetReikiRootCachePoint(x) == minpoint; }); var recommendPoint = 0; if (samepointIds.Count != reikis.Count) { var secondpointId = reikis.Find((x) => { return GetReikiRootCachePoint(x) > minpoint; }); var secondpoint = GetReikiRootCachePoint(secondpointId); recommendPoint = Mathf.Min((secondpoint - minpoint) * samepointIds.Count, surplusPoint) / samepointIds.Count; } else { recommendPoint = surplusPoint / samepointIds.Count; } if (recommendPoint > 0) { foreach (var id in samepointIds) { recommends.Add(new ReikiRootRecommend() { id = id, value = recommendPoint, }); surplusPoint -= recommendPoint; m_CacheReikiRootPoints[id] += recommendPoint; } } else { var id = samepointIds[0]; recommends.Add(new ReikiRootRecommend() { id = id, value = 1, }); surplusPoint -= 1; m_CacheReikiRootPoints[id] += 1; } } } return recommends; } int GetCacheQualityRequrePoint(int id,int quality) { var requirePoint = 0; var currebtQuality = GetReikiRootQuality(id, GetReikiRootCachePoint(id)); if (currebtQuality < quality) { var point = GetReikiRootCachePoint(id); requirePoint = GetQualityPoint(id, quality) - point; } return requirePoint; } public int GetQualityPoint(int id, int quality) { var config = ReikiRootConfig.Get(id); for (int i = 0; i < config.qualityArea.Length; i++) { if (quality == i + 1) { return config.qualityArea[i]; } } return 0; } public void GetReikiRootProperty(int id, int point, ref Dictionary propertyDict) { var config = ReikiRootConfig.Get(id); var job = PlayerDatas.Instance.baseData.Job; var reikiPointPropertys = m_ReikiPointPropertys[id][job]; for (int i = 0; i < reikiPointPropertys.Count; i++) { var reikiPointProperty = reikiPointPropertys[i]; if (!propertyDict.ContainsKey(reikiPointProperty.property)) { propertyDict.Add(reikiPointProperty.property, 0); } var step = point / reikiPointProperty.point; propertyDict[reikiPointProperty.property] += step * reikiPointProperty.value; } var qualityPropertys = m_PromotePropertyValues[id][job]; for (int i = 0; i < qualityPropertys.Count; i++) { var propertyId = qualityPropertys[i].property; if (!propertyDict.ContainsKey(propertyId)) { propertyDict.Add(propertyId, 0); } var quality = GetReikiRootQuality(id, point); propertyDict[propertyId] += GetQualityProperty(quality, qualityPropertys[i].propertyValues); } } public int GetReikiPropertyValue(int id) { if (m_ReikiPropertyValues.ContainsKey(id)) { return m_ReikiPropertyValues[id]; } return 0; } public List GetReikiQualityProperties(int id) { var job = PlayerDatas.Instance.baseData.Job; return m_PromotePropertyValues[id][job]; } public int GetQualityProperty(int quality, int[] values) { var value = 0; for (int i = 0; i < values.Length; i++) { if (quality > i) { value = values[i]; } else { break; } } return value; } public static string GetQualityLabel(int quality) { return Language.Get(StringUtility.Contact("ReikiRootQuality_", quality)); } public int GetQualityColor(int quality) { return m_ReikiQualityMapColors.ContainsKey(quality) ? m_ReikiQualityMapColors[quality] : 1; } public int GetUnLimitTimeResetItem() { var itemId = resetCostItemIds[0]; for (int i = 0; i < resetCostItemIds.Length; i++) { var config = ItemConfig.Get(resetCostItemIds[i]); if (config.ExpireTime == 0) { return resetCostItemIds[i]; } } return itemId; } public bool IsQualityProperty(int id, int property) { var propertys = GetReikiQualityProperties(id); foreach (var item in propertys) { if (item.property == property) { return true; } } return false; } public bool IsPreReikiRoot(int id) { if (PlayerDatas.Instance.baseData.LV >= resetReikiLimitLevel) { return true; } var job = PlayerDatas.Instance.baseData.Job; if (m_PreLimitReikiRoots.ContainsKey(job)) { return m_PreLimitReikiRoots[job].Contains(id); } return false; } public bool IsAfterReikiRoot(int id) { if (PlayerDatas.Instance.baseData.LV >= afterReikiRootLimitLevel) { return true; } var job = PlayerDatas.Instance.baseData.Job; if (m_AfterLimitReikiRoots.ContainsKey(job)) { return m_AfterLimitReikiRoots[job].Contains(id); } return false; } public bool IsSatisfyReikiRootCondition(int id, out int condition) { condition = 0; if (!IsAfterReikiRoot(id)) { condition = 2; return false; } if (!IsPreReikiRoot(id)) { condition = 1; return false; } return true; } public void ReceivePackage(HB107_tagMCRolePointInfo package) { var isReikiQualityChange = false; foreach (var id in reikiRoots) { lastReikiRootPoints[id] = GetReikiRootPoint(id); afterReikiRootPoints[id] = GetReikiRootPoint(id); } for (int i = 0; i < package.PointAttrIDCount; i++) { var id = package.PointAttrIDList[i]; var lastFreePoint = m_ReikiRootFreePoints.ContainsKey(id) ? m_ReikiRootFreePoints[id] : 0; var point = (int)package.PointValueList[i]; m_ReikiRootFreePoints[id] = point; afterReikiRootPoints[id] = m_ReikiRootPoints[id] - lastFreePoint + point; if (GetReikiRootQuality(id, lastReikiRootPoints[id]) < GetReikiRootQuality(id, afterReikiRootPoints[id])) { isReikiQualityChange = true; } if (isServerPrepare && lastFreePoint > 0 && point == 0) { if (onReikiRootPointReset != null) { onReikiRootPointReset(id); } } } if (isServerPrepare && isReikiQualityChange) { if (!WindowCenter.Instance.IsOpen()) { if (WindowCenter.Instance.IsOpen()) { WindowCenter.Instance.Open(); } } } } public void SendAddPoint(byte[] points, uint[] pointValues) { var pak = new CB206_tagCMAddPoint(); pak.PointAttrIDList = points; pak.PointValueList = pointValues; pak.PointAttrIDCount = (byte)points.Length; GameNetSystem.Instance.SendInfo(pak); } private void PlayerDataRefreshEvent(PlayerDataType dataType) { switch (dataType) { case PlayerDataType.CDBPlayerRefresh_Mater: case PlayerDataType.CDBPlayerRefresh_Wood: case PlayerDataType.CDBPlayerRefresh_Water: case PlayerDataType.CDBPlayerRefresh_Fire: case PlayerDataType.CDBPlayerRefresh_Earth: RefreshReikiRootPoint(); break; case PlayerDataType.FreePoint: RefreshRedpoint(); if (freePoint > lastFreePoint && isServerPrepare && WindowCenter.Instance.IsOpen() && reikiPointPromoteSymbol) { ReikiRootPointPromoteWin.point = new Int2(lastFreePoint, freePoint); WindowCenter.Instance.Open(); } lastFreePoint = freePoint; reikiPointPromoteSymbol = false; break; case PlayerDataType.LV: RefreshRedpoint(); break; } } public void RefreshReikiRootPoint() { m_ReikiPropertyValues.Clear(); foreach (var id in reikiRoots) { m_ReikiRootPoints[id] = (int)UIHelper.GetPropertyValue((PropertyType)id); GetReikiRootProperty(id, m_ReikiRootPoints[id], ref m_ReikiPropertyValues); } if (onReikiRootPointRefresh != null) { onReikiRootPointRefresh(); } } void RefreshRedpoint() { var existFreePoint = false; if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.ReikiRoot)) { if (PlayerDatas.Instance.baseData.LV < redpointRequirePoint.x) { existFreePoint = freePoint >= redpointRequirePoint.y; } else { existFreePoint = freePoint >= redpointRequirePoint.z; } } redpoint.state = existFreePoint ? RedPointState.Simple : RedPointState.None; } } public struct ReikiPointProperty { public int point; public int property; public int value; } public struct ReikiQualityProperty { public int property; public int[] propertyValues; } public struct ReikiRootRecommend { public int id; public int value; } public struct TitleAddPoint { public int titleId; public int point; } public struct TreasureAddPoint { public int treasureId; public int point; } }