using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Snxxz.UI { public class AlchemyModel : Model, IBeforePlayerDataInitialize, IPlayerLoginOk { Dictionary m_AlchemyTimes = new Dictionary(); Dictionary> m_AlchemyCounts = new Dictionary>(); Dictionary m_AlchemyQualityLucks = new Dictionary(); Dictionary> m_AlchemyMaterials = new Dictionary>(); Dictionary m_AlchemyDrugUseLimits = new Dictionary(); List m_AlchemyDrugs = new List(); List m_AlchemyDrugQualitys = new List(); List m_AssociationItems = new List(); public readonly Redpoint redpoint = new Redpoint(MainRedDot.RedPoint_key, 110); public readonly Redpoint alchemyDrugRedpoint1 = new Redpoint(110, 11001); public readonly Redpoint alchemyDrugRedpoint2 = new Redpoint(110, 11002); public readonly Redpoint alchemyDrugREdpoint3 = new Redpoint(110, 11003); Dictionary> alchemyQualityRedpoints = new Dictionary>(); Dictionary alchemyRedpoints = new Dictionary(); public static int redpointIndex = 110010000; int m_SelectQuality = 0; public int selectQuality { get { return m_SelectQuality; } set { if (m_SelectQuality != value) { m_SelectQuality = value; if (selectQualityRefresh != null) { selectQualityRefresh(); } } } } int m_SelectAlchemy = 0; public int selectAlchemy { get { return m_SelectAlchemy; } set { if (m_SelectAlchemy != value) { m_SelectAlchemy = value; if (selectAlchemyRefresh != null) { selectAlchemyRefresh(); } } } } public AlchemyType selectAlchemyType { get; set; } public int stoveLevel { get; private set; } public int stoveExp { get; private set; } public string alchemySuccRate { get; private set; } public int jumpAlchemy { get; set; } public bool isServerPrepare { get; private set; } Clock m_AlchemingClock = null; public event Action selectQualityRefresh; public event Action selectAlchemyRefresh; public event Action alchemyStateRefresh; public event Action alchemyDrugUseRefresh; PackModel packModel { get { return ModelCenter.Instance.GetModel(); } } public override void Init() { FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent; PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefreshEvent; packModel.refreshItemCountEvent += RefreshItemCountEvent; ParseConfig(); } public void OnBeforePlayerDataInitialize() { m_AlchemyTimes.Clear(); stoveLevel = 0; stoveExp = 0; foreach (var item in m_AlchemyDrugUseLimits.Values) { item.SetTimes(0, 0); } isServerPrepare = false; } public void OnPlayerLoginOk() { isServerPrepare = true; CheckRedpoint(); } public override void UnInit() { FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent; PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefreshEvent; packModel.refreshItemCountEvent -= RefreshItemCountEvent; } private void RefreshItemCountEvent(PackType packType, int arg2, int itemId) { if (m_AssociationItems.Contains(itemId)) { CheckRedpoint(); } if (m_AlchemyDrugs.Contains(itemId)) { RefreshUseDrugRedpoint(); } } private void PlayerDataRefreshEvent(PlayerDataType dataType) { if (dataType == PlayerDataType.LuckValue) { CheckRedpoint(); } } private void OnFuncStateChangeEvent(int id) { if (id == (int)FuncOpenEnum.BlastFurnace) { CheckRedpoint(); RefreshUseDrugRedpoint(); } } void ParseConfig() { { var configs = AlchemyCountConfig.GetValues(); foreach (var config in configs) { var intArray = LitJson.JsonMapper.ToObject(config.CntRateList); var min = intArray[0][1]; var max = intArray[intArray.Length - 1][1]; if (!m_AlchemyCounts.ContainsKey(config.AlchemyQuality)) { m_AlchemyCounts[config.AlchemyQuality] = new Dictionary(); } m_AlchemyCounts[config.AlchemyQuality].Add(config.LuckValue, new AlchemyCount() { min = min, max = max, }); } } { var funcConfig = FuncConfigConfig.Get("alchemySuccess"); alchemySuccRate = funcConfig.Numerical3; var json = LitJson.JsonMapper.ToObject(funcConfig.Numerical2); foreach (var key in json.Keys) { var quality = int.Parse(key); m_AlchemyQualityLucks.Add(quality, int.Parse(json[key].ToString())); } } { var configs = AlchemyConfig.GetValues(); foreach (var config in configs) { m_AlchemyMaterials.Add(config.ID, new List()); var dict = ConfigParse.GetDic(config.Material); foreach (var key in dict.Keys) { m_AlchemyMaterials[config.ID].Add(new Item() { id = key, count = dict[key], }); if (!m_AssociationItems.Contains(key)) { m_AssociationItems.Add(key); } } if (!m_AssociationItems.Contains(config.LearnNeedItemID)) { m_AssociationItems.Add(config.LearnNeedItemID); } } } { var configs = AttrFruitConfig.GetValues(); foreach (var config in configs) { if (config.FuncID == 2) { m_AlchemyDrugs.Add(config.ID); var itemConfig = ItemConfig.Get(config.ID); if (!m_AlchemyDrugQualitys.Contains(itemConfig.LV)) { m_AlchemyDrugQualitys.Add(itemConfig.LV); } m_AlchemyDrugUseLimits.Add(config.ID, new AlchemyDrugUseLimit(config.ID)); } } m_AlchemyDrugQualitys.Sort(); } var qualitys = AlchemyConfig.GetAlchemyQualities((int)AlchemyType.Normal); alchemyQualityRedpoints.Add((int)AlchemyType.Normal, new Dictionary()); foreach (var quality in qualitys) { var qualityRedpoint = new Redpoint(alchemyDrugRedpoint1.id, redpointIndex++); ; alchemyQualityRedpoints[(int)AlchemyType.Normal].Add(quality, qualityRedpoint); var alchemys = AlchemyConfig.GetAlchemies((int)AlchemyType.Normal, quality); foreach (var id in alchemys) { alchemyRedpoints.Add(id, new AlchemyRedpoint(qualityRedpoint.id)); } } qualitys = AlchemyConfig.GetAlchemyQualities((int)AlchemyType.Fairy); alchemyQualityRedpoints.Add((int)AlchemyType.Fairy, new Dictionary()); foreach (var quality in qualitys) { var qualityRedpoint = new Redpoint(alchemyDrugRedpoint2.id, redpointIndex++); ; alchemyQualityRedpoints[(int)AlchemyType.Fairy].Add(quality, qualityRedpoint); var alchemys = AlchemyConfig.GetAlchemies((int)AlchemyType.Fairy, quality); foreach (var id in alchemys) { alchemyRedpoints.Add(id, new AlchemyRedpoint(qualityRedpoint.id)); } } } public bool TryGetAlchemyStartTime(int alchemyId, out uint tick) { return m_AlchemyTimes.TryGetValue(alchemyId, out tick); } public bool TryGetAlchemyCount(int alchemyId, int luckValue, out AlchemyCount alchemyCount) { var config = AlchemyConfig.Get(alchemyId); alchemyCount = default(AlchemyCount); if (config == null) { return false; } if (config.AlchemType == (int)AlchemyType.Fairy) { alchemyCount = AlchemyCount.one; return true; } var dict = m_AlchemyCounts[config.AlchemyQuality]; foreach (var _luckValue in dict.Keys) { if (luckValue >= _luckValue) { alchemyCount = dict[_luckValue]; } } return !alchemyCount.Equals(default(AlchemyCount)); } public bool TryGetAlchemyMaterials(int alchemyId, out List items) { return m_AlchemyMaterials.TryGetValue(alchemyId, out items); } public bool TryGetAlchemyUseLimit(int id,out AlchemyDrugUseLimit drugUseLimit) { return m_AlchemyDrugUseLimits.TryGetValue(id, out drugUseLimit); } public int GetAlchemyRedpointId(int id) { return alchemyRedpoints.ContainsKey(id) ? alchemyRedpoints[id].redpoint.id : 0; } public int GetQualityRedpointId(int alchemyType, int quality) { if (alchemyQualityRedpoints.ContainsKey(alchemyType)) { if (alchemyQualityRedpoints[alchemyType].ContainsKey(quality)) { return alchemyQualityRedpoints[alchemyType][quality].id; } } return 0; } public float GetAlchemySuccRate(int alchemyId) { var config = AlchemyConfig.Get(alchemyId); if (config == null) { return 0f; } if (config.AlchemType == (int)AlchemyType.Fairy) { return 10000f; } var itemConfig = ItemConfig.Get(config.AlchemItemID); var luckValue = PlayerDatas.Instance.extersion.luckValue; return GetAlchemySuccRate(stoveLevel, itemConfig.LV, luckValue); } public float GetAlchemySuccRate(int stoveLevel, int itemLevel, int luck) { Equation.Instance.Clear(); Equation.Instance.AddKeyValue("alchemyLV", stoveLevel); Equation.Instance.AddKeyValue("alchemyQuality", itemLevel); Equation.Instance.AddKeyValue("curLuckValue", luck); var qualityNeedLuck = m_AlchemyQualityLucks.ContainsKey(itemLevel) ? m_AlchemyQualityLucks[itemLevel] : 0; Equation.Instance.AddKeyValue("qualityNeedLuck", qualityNeedLuck); return Equation.Instance.Eval(alchemySuccRate); } public int GetStoveState(int alchemyId) { uint tick = 0; if (TryGetAlchemyStartTime(alchemyId, out tick) && tick > 0) { var config = AlchemyConfig.Get(alchemyId); var startTime = TimeUtility.GetTime(tick); var seconds = (int)(config.NeedTime - (float)(TimeUtility.ServerNow - startTime).TotalSeconds); return seconds > 0 ? 1 : 2; } return 0; } public ICollection GetDrugQualitys() { return m_AlchemyDrugQualitys; } public ICollection GetAlchemyDrugs() { return m_AlchemyDrugs; } public int GetAlchemyDrugState(int id)//0-可服用丹药 1-达到上限 2-没有丹药 3-没有提升空间 { AlchemyDrugUseLimit drugUseLimit; if (TryGetAlchemyUseLimit(id, out drugUseLimit)) { if (!drugUseLimit.IsReachLimit()) { var count = packModel.GetItemCountByID(PackType.Item, id); return count > 0 ? 0 : 2; } else { return drugUseLimit.CanUpgradeLimit() ? 1 : 3; } } return int.MaxValue; } public int GetAlchemyDrugUseLimit(int id) { AlchemyDrugUseLimit drugUseLimit; if (TryGetAlchemyUseLimit(id, out drugUseLimit)) { return drugUseLimit.GetUseLimit(); } return 0; } public bool IsGraspRecipe(int alchemyId) { return m_AlchemyTimes.ContainsKey(alchemyId); } public bool IsAlchemyEnoughMaterial(int alchemyId, out Item item) { List materials; item = default(Item); if (TryGetAlchemyMaterials(alchemyId, out materials)) { for (int i = 0; i < materials.Count; i++) { var mat = materials[i]; var count = packModel.GetItemCountByID(PackType.Item, mat.id); if (count < mat.count) { item = mat; return false; } } } return true; } public bool IsStoveAlcheming(AlchemyType alchemyType, out Int2 alchemyPosition) { alchemyPosition = default(Int2); var qualities = AlchemyConfig.GetAlchemyQualities((int)alchemyType); foreach (var quality in qualities) { var alchemys = AlchemyConfig.GetAlchemies((int)alchemyType, quality); foreach (var alchemyId in alchemys) { var state = GetStoveState(alchemyId); if (state != 0) { alchemyPosition.x = quality; alchemyPosition.y = alchemyId; return true; } } } return false; } public void ReceivePackage(HA3BF_tagMCPlayerStoveMsg package) { var seconds = 0; for (int i = 0; i < package.StoveCnt; i++) { var data = package.InfoList[i]; m_AlchemyTimes[(int)data.AlchemyID] = data.StartTime; if (data.StartTime > 0) { var config = AlchemyConfig.Get((int)data.AlchemyID); var time = TimeUtility.GetTime(data.StartTime); var _seconds = (int)(TimeUtility.ServerNow - time).TotalSeconds; if (_seconds < config.NeedTime && config.NeedTime - _seconds > seconds) { seconds = config.NeedTime - _seconds; } } } if (m_AlchemingClock != null) { Clock.Stop(m_AlchemingClock); m_AlchemingClock = null; } if (seconds > 0) { m_AlchemingClock = Clock.AlarmAfter(seconds, CheckRedpoint); } stoveLevel = package.StoveLV; stoveExp = (int)package.StoveExp; if (package.ItemID != 0) { if (isServerPrepare) { if (!NewBieCenter.Instance.inGuiding && WindowCenter.Instance.IsOpen()) { AlchemyResultWin.displayItem = new Item() { id = (int)package.ItemID, count = package.ItemCnt, }; WindowCenter.Instance.Open(); } } } CheckRedpoint(); if (alchemyStateRefresh != null) { alchemyStateRefresh(); } } public void ReceivePackage(HA339_tagMCAttrFruitEatCntList vNetData) { for (int i = 0; i < vNetData.count; i++) { var data = vNetData.EatCntList[i]; AlchemyDrugUseLimit drugUseLimit; if (TryGetAlchemyUseLimit((int)data.ItemID, out drugUseLimit)) { drugUseLimit.SetTimes(data.EatCnt, (int)data.AddItemCnt); } } if (alchemyDrugUseRefresh != null) { alchemyDrugUseRefresh(); } } static List s_Endables = new List(); static List s_Studyables = new List(); static List s_Alchemyables = new List(); static Dictionary> s_SortQualitys = new Dictionary>(); public List GetSortQualitys(AlchemyType alchemyType) { if (!s_SortQualitys.ContainsKey(alchemyType)) { s_SortQualitys.Add(alchemyType, new List(AlchemyConfig.GetAlchemyQualities((int)alchemyType))); s_SortQualitys[alchemyType].Sort(QualityCompare); } return s_SortQualitys[alchemyType]; } private int QualityCompare(int x, int y) { return -x.CompareTo(y); } void CheckRedpoint() { s_Endables.Clear(); s_Studyables.Clear(); s_Alchemyables.Clear(); if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.BlastFurnace)) { RefreshRedpoint(); return; } CheckRedpoint(AlchemyType.Normal); CheckRedpoint(AlchemyType.Fairy); RefreshRedpoint(); } void CheckRedpoint(AlchemyType alchemyType) { Int2 position; if (IsStoveAlcheming(alchemyType, out position)) { var state = GetStoveState(position.y); if (state == 2) { s_Endables.Add(position.y); } } else { var qualitys = AlchemyConfig.GetAlchemyQualities((int)alchemyType); foreach (var quality in qualitys) { var alchemys = AlchemyConfig.GetAlchemies((int)alchemyType, quality); foreach (var id in alchemys) { if (!IsGraspRecipe(id)) { var config = AlchemyConfig.Get(id); var count = packModel.GetItemCountByID(PackType.Item, config.LearnNeedItemID); if (count <= 0 || stoveLevel < config.LearnNeedAlchemLV || PlayerDatas.Instance.extersion.luckValue < config.LearnNeedLuck) { continue; } s_Studyables.Add(id); } } } qualitys = GetSortQualitys(alchemyType); foreach (var quality in qualitys) { var alchemyable = false; var alchemys = AlchemyConfig.GetAlchemies((int)alchemyType, quality); foreach (var id in alchemys) { if (!IsGraspRecipe(id)) { continue; } Item item; if (IsAlchemyEnoughMaterial(id, out item)) { s_Alchemyables.Add(id); alchemyable = true; } } if (alchemyable) { break; } } } } void RefreshRedpoint() { var qualitys = AlchemyConfig.GetAlchemyQualities((int)AlchemyType.Normal); foreach (var quality in qualitys) { var alchemys = AlchemyConfig.GetAlchemies((int)AlchemyType.Normal, quality); foreach (var id in alchemys) { var redpoint = alchemyRedpoints[id]; redpoint.studyRedpoint.state = s_Studyables.Contains(id) ? RedPointState.Simple : RedPointState.None; redpoint.endRedpoint.state = s_Endables.Contains(id) ? RedPointState.Simple : RedPointState.None; redpoint.alchemyRedpoint.state = s_Alchemyables.Contains(id) ? RedPointState.Simple : RedPointState.None; } } qualitys = AlchemyConfig.GetAlchemyQualities((int)AlchemyType.Fairy); foreach (var quality in qualitys) { var alchemys = AlchemyConfig.GetAlchemies((int)AlchemyType.Fairy, quality); foreach (var id in alchemys) { var redpoint = alchemyRedpoints[id]; redpoint.studyRedpoint.state = s_Studyables.Contains(id) ? RedPointState.Simple : RedPointState.None; redpoint.endRedpoint.state = s_Endables.Contains(id) ? RedPointState.Simple : RedPointState.None; redpoint.alchemyRedpoint.state = s_Alchemyables.Contains(id) ? RedPointState.Simple : RedPointState.None; } } } void RefreshUseDrugRedpoint() { var useable = false; if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.BlastFurnace)) { foreach (var itemId in m_AlchemyDrugs) { if (GetAlchemyDrugState(itemId) == 0) { useable = true; break; } } } alchemyDrugREdpoint3.state = useable ? RedPointState.Simple : RedPointState.None; } } public enum AlchemyType { Normal = 1, Fairy = 2, } public struct AlchemyCount { public int min; public int max; public static readonly AlchemyCount one = new AlchemyCount() { min = 1, max = 1, }; } public class AlchemyDrugUseLimit { public readonly int id; public readonly Item addItem; public readonly int addLimitPerTimes; Dictionary realmLimits = new Dictionary(); public int addTimes { get; private set; } public int eatTimes { get; private set; } PackModel packModel { get { return ModelCenter.Instance.GetModel(); } } public AlchemyDrugUseLimit(int id) { this.id = id; var config = AttrFruitConfig.Get(id); foreach (var realmLimit in config.MaxUseCnt) { realmLimits.Add(realmLimit.x, realmLimit.y); } if (!string.IsNullOrEmpty(config.AddItemMaxCnt)) { var array = LitJson.JsonMapper.ToObject(config.AddItemMaxCnt); addItem = new Item() { id = array[0], count = array[1], }; addLimitPerTimes = array[2]; } } public void SetTimes(int eatTimes, int addTimes) { this.eatTimes = eatTimes; this.addTimes = addTimes / (addItem.count <= 0 ? 1 : addItem.count); } public int GetUseLimit() { var times = 0; var realmLevel = PlayerDatas.Instance.baseData.realmLevel; foreach (var level in realmLimits.Keys) { if (realmLevel >= level) { times = realmLimits[level]; } } if (addItem.id != 0) { times += addTimes * addLimitPerTimes; } return times; } public int GetRealmLimit(int realmLevel) { var limit = 0; foreach (var level in realmLimits.Keys) { if (realmLevel >= level) { limit = realmLimits[level]; } } return limit; } public bool IsReachLimit() { var limit = GetUseLimit(); return eatTimes >= limit; } public bool CanUpgradeLimit() { if (addItem.id != 0) { return true; } if (GetNextUpgradeRealm() > 0) { return true; } return false; } public int GetNextUpgradeRealm() { var realmLevel = PlayerDatas.Instance.baseData.realmLevel; foreach (var level in realmLimits.Keys) { if (realmLevel < level) { return level; } } return 0; } } public class AlchemyRedpoint { public readonly Redpoint redpoint; public readonly Redpoint studyRedpoint; public readonly Redpoint endRedpoint; public readonly Redpoint alchemyRedpoint; public AlchemyRedpoint(int baseId) { redpoint = new Redpoint(baseId, AlchemyModel.redpointIndex++); studyRedpoint = new Redpoint(redpoint.id, AlchemyModel.redpointIndex++); endRedpoint = new Redpoint(redpoint.id, AlchemyModel.redpointIndex++); alchemyRedpoint = new Redpoint(redpoint.id, AlchemyModel.redpointIndex++); } } }