using System; using System.Collections.Generic; using System.Linq; using UnityEngine.UI; public class HeroFatesManager : GameSystemManager { public readonly int rowCountMax = 5; public readonly int attrRowCountMax = 3; public override void Init() { DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin; DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk; HeroUIManager.Instance.OnHeroCollectEvent += OnHeroCollectEvent; HeroManager.Instance.onHeroChangeEvent += OnHeroChangeEvent; FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent; } public override void Release() { DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin; DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk; HeroUIManager.Instance.OnHeroCollectEvent -= OnHeroCollectEvent; HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent; FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent; } private void OnFuncStateChangeEvent(int obj) { if (obj == (int)FuncOpenEnum.Hero || obj == (int)FuncOpenEnum.HeroFatesUpgrade) { UpdateRedpoint(); } } private void OnBeforePlayerDataInitializeEventOnRelogin() { heroFatesInfos.Clear(); } private void OnPlayerLoginOk() { UpdateRedpoint(); RefreshAttr(); } private void OnHeroCollectEvent() { UpdateRedpoint(); } private void OnHeroChangeEvent(HeroInfo info) { UpdateRedpoint(); } List allFatesHeroID = new List(); public List GetAllFatesHeroID() { if (allFatesHeroID.IsNullOrEmpty()) { foreach (var info in HeroFatesConfig.GetValues()) { if (info.HeroIDList.IsNullOrEmpty()) { continue; } foreach (var HeroID in info.HeroIDList) { if (!allFatesHeroID.Contains(HeroID)) { allFatesHeroID.Add(HeroID); } } } } return allFatesHeroID; } Redpoint redpoint = new Redpoint(MainRedDot.MainHerosRedpoint, MainRedDot.HeroFatesRepoint); public void UpdateRedpoint() { redpoint.state = RedPointState.None; //武将没开不刷红点 if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Hero)) return; bool hasShowRedDotFates = HasShowRedDotFates(out int firstIndex); if (hasShowRedDotFates) { redpoint.state = RedPointState.Simple; } } //<宿缘ID,宿缘信息> public Dictionary heroFatesInfos = new Dictionary(); public bool TryGetHeroFates(int fatesID, out HeroFates info) { return heroFatesInfos.TryGetValue(fatesID, out info); } public event Action OnUpdateHeroFatesInfoEvent; public event Action OnUpgradeHeroFatesEvent; public void OnUpdateHeroFatesInfo(HB131_tagSCHeroFatesInfo vNetData) { if (vNetData == null || vNetData.FatesList.IsNullOrEmpty()) { return; } bool isUpgrade = false; foreach (var vInfo in vNetData.FatesList) { if (!heroFatesInfos.ContainsKey(vInfo.FatesID)) { heroFatesInfos[vInfo.FatesID] = new HeroFates(); } heroFatesInfos[vInfo.FatesID].FatesID = vInfo.FatesID; heroFatesInfos[vInfo.FatesID].State = vInfo.State; if (heroFatesInfos[vInfo.FatesID].FatesLV != vInfo.FatesLV) { isUpgrade = true; } heroFatesInfos[vInfo.FatesID].FatesLV = vInfo.FatesLV; } RefreshAttr(); UpdateRedpoint(); OnUpdateHeroFatesInfoEvent?.Invoke(); if (isUpgrade) { OnUpgradeHeroFatesEvent?.Invoke(); } } public ushort[] GetItemIndexList(List heroInfos) { return heroInfos.Select(heroInfo => (ushort)heroInfo.itemHero.gridIndex).ToArray(); } public void SendHeroFates(int fatesID, int opType, ushort[] itemIndexList = null) { CB241_tagCSHeroFates pack = new CB241_tagCSHeroFates(); pack.FatesID = (byte)fatesID; // 宿缘ID pack.OPType = (byte)opType; // 0-激活领奖;1-升级 // 升级时消耗的材料卡在武将背包索引列表,升级时才发 bool isNullOrEmpty = itemIndexList.IsNullOrEmpty(); pack.ItemIndexList = isNullOrEmpty ? null : itemIndexList; pack.IndexCnt = isNullOrEmpty ? (byte)0 : (byte)itemIndexList.Length; GameNetSystem.Instance.SendInfo(pack); } public HeroFatesState GetHeroFatesState(int fatesID) { //没有封包 if (!TryGetHeroFates(fatesID, out HeroFates info)) { return IsHeroIDListAllActive(fatesID) ? HeroFatesState.Activatable : HeroFatesState.Locked; } // 封包宿缘状态:0-未激活;1-已激活已领奖 if (info.State == 0) { //武将ID组合列表中的武将的图鉴有没解锁的?- 未解锁 return IsHeroIDListAllActive(fatesID) ? HeroFatesState.Activatable : HeroFatesState.Locked; } else if (info.State == 1) { // 宿缘升级功能没开时视为不可升级 if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.HeroFatesUpgrade)) { return HeroFatesState.ActiveNotUpgradable; } if (IsHeroFatesStarMax(fatesID)) { return HeroFatesState.MaxLevel; } return IsHeroFatesCanUp(fatesID, out int fromFatesLv, out int toFatesLv) ? HeroFatesState.ActiveUpgradable : HeroFatesState.ActiveNotUpgradable; } return HeroFatesState.Locked; } public bool IsHeroFatesCanUp(int fatesID, out int fromFatesLv, out int toFatesLv) { fromFatesLv = 0; toFatesLv = 0; if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config)) { return false; } if (!TryGetHeroFates(fatesID, out HeroFates info)) { return false; } fromFatesLv = info.FatesLV; toFatesLv = info.FatesLV + 1; int fatesQuality = config.FatesQuality; if (!HeroFatesQualityLVConfig.TryGetHeroFatesQualityLVConfig(fatesQuality, toFatesLv, out HeroFatesQualityLVConfig heroFatesQualityLVConfig)) { return false; } // 武将总星级是否满足升级需求 int needStarCnt = heroFatesQualityLVConfig.NeedStarTotal; int hasStarCnt = GetFatesNowStarCnt(fatesID); if (hasStarCnt < needStarCnt) { return false; } // 消耗武将数量是否满足需求 List consumableHeroInfos = GetConsumableHeroInfoList(heroFatesQualityLVConfig.NeedQuality); int hasHeroCnt = consumableHeroInfos == null ? 0 : consumableHeroInfos.Count; int needHeroCnt = heroFatesQualityLVConfig.NeedHeroCnt; if (hasHeroCnt < needHeroCnt) { return false; } return true; } // 获得背包中的所有指定品质的可消耗武将 宿缘品质就是武将品质 public List GetConsumableHeroInfoList(int fatesQuality) { List result = new List(); List allHeroesInBag = HeroManager.Instance.GetHeroList(); foreach (var item in allHeroesInBag) { if (item == null) continue; //不是所需品质 if (item.Quality != fatesQuality) continue; // 激活中的武将 if (item.isActive) continue; // 在任何阵容中上阵 bool isInAnyTeam = item.IsInAnyTeam(); if (isInAnyTeam) continue; // 锁定中 if (item.isLock) continue; // 升级过 if (item.heroLevel > 1) continue; // 生星过 if (item.heroStar > 0) continue; // 觉醒过 if (item.awakeLevel > 0) continue; result.Add(item); } result.Sort((a, b) => a.heroId.CompareTo(b.heroId)); return result; } // 当前宿缘的当前最高总星级是否已满级 public bool IsHeroFatesStarMax(int fatesID) { if (!TryGetHeroFates(fatesID, out HeroFates info)) return false; if (!TryGetMaxFatesLVConfigByFatesID(fatesID, out HeroFatesQualityLVConfig heroFatesQualityLVConfig)) return false; int maxLv = heroFatesQualityLVConfig.FatesLV; int nowLv = info.FatesLV; return nowLv >= maxLv; } // 武将ID组合列表中的武将的图鉴都解锁了? public bool IsHeroIDListAllActive(int fatesID) { if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config) || config.HeroIDList.IsNullOrEmpty()) return false; int activeHeroCnt = GetFateNeedHeroHasCnt(fatesID); return config.HeroIDList.Length <= activeHeroCnt; } public int GetFateNeedHeroHasCnt(int fatesID) { int res = 0; if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config) || config.HeroIDList.IsNullOrEmpty()) return 0; foreach (var heroID in config.HeroIDList) { if (!TryGetHeroConfig(heroID, out HeroConfig heroConfig)) continue; // heroBookState: 0未获得、1可激活、2常规、3突破升级、4星升级、5已满级 int heroBookState = HeroUIManager.Instance.GetHeroBookState(heroID, heroConfig.Quality); if (heroBookState > 0) res += 1; } return res; } public bool TryGetNowMaxStarHeroDict(out Dictionary nowMaxStarHeroDict) { nowMaxStarHeroDict = new Dictionary(); List allHeroesInBag = HeroManager.Instance.GetHeroList(); if (allHeroesInBag.IsNullOrEmpty()) return false; foreach (var item in allHeroesInBag) { if (item == null) continue; if (!nowMaxStarHeroDict.TryGetValue(item.heroId, out HeroInfo heroInfo)) { nowMaxStarHeroDict[item.heroId] = item; } else { if (item.heroStar > heroInfo.heroStar) nowMaxStarHeroDict[item.heroId] = item; } } return true; } public Dictionary GetFatesNowStarHeroInfoDict(int fatesID) { if (!IsHeroIDListAllActive(fatesID)) return null; if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config) || config.HeroIDList.IsNullOrEmpty()) return null; if (!TryGetNowMaxStarHeroDict(out Dictionary nowMaxStarHeroDict) || nowMaxStarHeroDict.IsNullOrEmpty()) return null; Dictionary heroInfoDict = new Dictionary(); foreach (var heroID in config.HeroIDList) { if (nowMaxStarHeroDict.ContainsKey(heroID)) { heroInfoDict[heroID] = nowMaxStarHeroDict[heroID]; } } return heroInfoDict; } // 获取当前宿缘的当前最高总星级 public int GetFatesNowStarCnt(int fatesID) { Dictionary dict = GetFatesNowStarHeroInfoDict(fatesID); if (dict.IsNullOrEmpty()) return 0; // 遍历宿缘配置中所需的武将ID,从maxStarsInBag中获取最高星级并累加 int res = 0; foreach (var item in dict.Values) { res += item.heroStar; } return res; } public void DisplayStars(List starImgList, int starCnt) { for (int i = 0; i < starImgList.Count; i++) { //不显示星级 if (starCnt == -1) { starImgList[i].SetActive(false); } else if (starCnt == 0 && i == 0) { // 无星级 特殊处理 starImgList[i].SetActive(true); starImgList[i].SetSprite("herostar" + starCnt); } else if ((starCnt - 1) % starImgList.Count >= i) { starImgList[i].SetActive(true); starImgList[i].SetSprite("herostar" + (((starCnt - 1) / starImgList.Count) + 1) * starImgList.Count); } else { starImgList[i].SetActive(false); } } } public bool IsShowRedDot(int fatesID) { HeroFatesState state = GetHeroFatesState(fatesID); return state == HeroFatesState.Activatable || state == HeroFatesState.ActiveUpgradable; } public bool HasShowRedDotFates(out int firstIndex) { firstIndex = 0; List list = GetFatesIDList(); if (list.IsNullOrEmpty()) return false; for (int i = 0; i < list.Count; i++) { int fatesID = list[i]; if (IsShowRedDot(fatesID)) { firstIndex = i; return true; } } return false; } public List GetPutPreviewHeroList(int fatesID) { if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config)) { return null; } int fatesQuality = config.FatesQuality; if (!TryGetNowLVAndNextLVConfig(fatesID, out int nowLv, out HeroFatesQualityLVConfig nowLVConfig, out HeroFatesQualityLVConfig nextLVConfig)) { return null; } int needHeroCnt = nextLVConfig.NeedHeroCnt; List consumableHeroInfoList = GetConsumableHeroInfoList(nextLVConfig.NeedQuality); if (consumableHeroInfoList.IsNullOrEmpty()) { return null; } List putPreviewHeroList = new List(); int count = Math.Min(needHeroCnt, consumableHeroInfoList.Count); for (int i = 0; i < count; i++) { putPreviewHeroList.Add(consumableHeroInfoList[i]); } return putPreviewHeroList; } #region 玩家选中内容 public int chooseHeroFatesId = 0; public HeroInfo chooseHeroInfo = null; // 给玩家操作选中的列表 public List chooseCostHeroInfos = new List(); // 玩家实际选中的列表 public List realCostHeroInfos = new List(); public event Action OnRealChooseChangeEvent; public event Action OnChooseChangeEvent; public void InitChooseList() { chooseCostHeroInfos.Clear(); foreach (var heroInfo in realCostHeroInfos) { chooseCostHeroInfos.Add(heroInfo); } chooseHeroInfo = null; } public void ChooseAdd(HeroInfo heroInfo) { if (chooseCostHeroInfos.Contains(heroInfo)) { chooseCostHeroInfos.Remove(heroInfo); chooseHeroInfo = null; } else { chooseCostHeroInfos.Add(heroInfo); chooseHeroInfo = heroInfo; } OnChooseChangeEvent?.Invoke(); } public void ClearAllList() { chooseCostHeroInfos.Clear(); realCostHeroInfos.Clear(); chooseHeroInfo = null; OnRealChooseChangeEvent?.Invoke(); } public void PutList() { realCostHeroInfos.Clear(); foreach (var heroInfo in chooseCostHeroInfos) { realCostHeroInfos.Add(heroInfo); } OnRealChooseChangeEvent?.Invoke(); } public void FastAddList(List heroInfos) { if (heroInfos.IsNullOrEmpty()) return; chooseCostHeroInfos.Clear(); realCostHeroInfos.Clear(); foreach (var heroInfo in heroInfos) { chooseCostHeroInfos.Add(heroInfo); realCostHeroInfos.Add(heroInfo); } OnRealChooseChangeEvent?.Invoke(); } #endregion #region 属性计算 public Dictionary attrDic = new Dictionary(); public Dictionary GetTotalAttr() { return attrDic; } public long GetAttrValue(int attrID) { attrDic.TryGetValue(attrID, out long value); return value; } public int GetAttrPer(int attrID) { if (PlayerPropertyConfig.baseAttr2perDict.ContainsKey(attrID)) { var pertype = PlayerPropertyConfig.baseAttr2perDict[attrID]; attrDic.TryGetValue(pertype, out long value); return (int)(value); } return 0; } public void RefreshAttr() { attrDic.Clear(); List allIds = HeroFatesConfig.GetKeys(); foreach (var fatesID in allIds) { HeroFatesState state = GetHeroFatesState(fatesID); if (!TryGetAttrIDListAndLVAttrValueList(fatesID, out int[] attrIDList, out int[] lvAttrValueList)) continue; for (int i = 0; i < attrIDList.Length; i++) { if (!attrDic.ContainsKey(attrIDList[i])) { attrDic[attrIDList[i]] = 0; } if (state == HeroFatesState.Locked || state == HeroFatesState.Activatable) continue; int value = GetNowAttrValue(fatesID, i); attrDic[attrIDList[i]] += value; } } } //最终属性 = 等级 * 每级属性值 public int GetNowAttrValue(int fatesID, int attrIndex) { if (!TryGetAttrIDListAndLVAttrValueList(fatesID, out int[] attrIDList, out int[] lvAttrValueList)) return 0; if (attrIndex < 0 || attrIndex > attrIDList.Length) return 0; if (!TryGetHeroFates(fatesID, out HeroFates info)) return 0; int lv = info.FatesLV; return lv * lvAttrValueList[attrIndex]; } //下一级属性 = (等级 + 1) * 每级属性值 public int GetNextAttrValue(int fatesID, int attrIndex) { if (!TryGetAttrIDListAndLVAttrValueList(fatesID, out int[] attrIDList, out int[] lvAttrValueList)) return 0; if (attrIndex < 0 || attrIndex > attrIDList.Length) return 0; if (!TryGetHeroFates(fatesID, out HeroFates info)) return 0; int lv = info.FatesLV + 1; return lv * lvAttrValueList[attrIndex]; } #endregion #region 读表 // 0级时,不返回nowLVConfig,只返回nowLVConfig public bool TryGetNowLVAndNextLVConfig(int fatesID, out int nowLv, out HeroFatesQualityLVConfig nowLVConfig, out HeroFatesQualityLVConfig nextLVConfig) { nowLv = 0; nowLVConfig = null; nextLVConfig = null; if (!TryGetHeroFates(fatesID, out HeroFates info)) return false; if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config)) return false; int quality = config.FatesQuality; nowLv = info.FatesLV; if (nowLv != 0) { if (!HeroFatesQualityLVConfig.TryGetHeroFatesQualityLVConfig(quality, nowLv, out nowLVConfig)) return false; } int nextLv = nowLv + 1; return HeroFatesQualityLVConfig.TryGetHeroFatesQualityLVConfig(quality, nextLv, out nextLVConfig); } public bool TryGetMaxFatesLVConfigByFatesID(int fatesID, out HeroFatesQualityLVConfig heroFatesQualityLVConfig) { heroFatesQualityLVConfig = null; if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config)) return false; int fatesQuality = config.FatesQuality; if (!HeroFatesQualityLVConfig.TryGetDictByFatesQuality(fatesQuality, out Dictionary dict) || dict.IsNullOrEmpty()) return false; int maxFatesLV = dict.Keys.Max(); if (!HeroFatesQualityLVConfig.TryGetHeroFatesQualityLVConfig(fatesQuality, maxFatesLV, out heroFatesQualityLVConfig)) return false; return true; } public bool TryGetHeroFatesConfig(int fatesID, out HeroFatesConfig config) { config = null; if (!HeroFatesConfig.HasKey(fatesID)) return false; config = HeroFatesConfig.Get(fatesID); return true; } public bool TryGetAttrIDListAndLVAttrValueList(int fatesID, out int[] attrIDList, out int[] lvAttrValueList) { attrIDList = null; lvAttrValueList = null; if (!TryGetHeroFatesConfig(fatesID, out HeroFatesConfig config)) return false; attrIDList = config.AttrIDList; lvAttrValueList = config.LVAttrValueList; if (attrIDList.IsNullOrEmpty() || lvAttrValueList.IsNullOrEmpty()) return false; return attrIDList.Length == lvAttrValueList.Length; } public bool TryGetHeroConfig(int heroID, out HeroConfig config) { config = null; if (!HeroConfig.HasKey(heroID)) return false; config = HeroConfig.Get(heroID); return true; } public bool TryGetHeroAndSkinConfigByHeroID(int heroID, out HeroConfig heroConfig, out HeroSkinConfig heroSkinConfig) { heroConfig = null; heroSkinConfig = null; if (!HeroConfig.HasKey(heroID)) return false; heroConfig = HeroConfig.Get(heroID); int[] skinIDList = heroConfig.SkinIDList; if (skinIDList.IsNullOrEmpty()) return false; int skinID = skinIDList[0]; if (!HeroSkinConfig.HasKey(skinID)) return false; heroSkinConfig = HeroSkinConfig.Get(skinID); return true; } List fatesIDList = null; public List GetFatesIDList() { if (fatesIDList.IsNullOrEmpty()) { fatesIDList = HeroFatesConfig.GetKeys(); // 按品质降序排序,相同品质按ID降序排序 fatesIDList.Sort((id1, id2) => { if (!TryGetHeroFatesConfig(id1, out HeroFatesConfig config1) || !TryGetHeroFatesConfig(id2, out HeroFatesConfig config2)) { return id1.CompareTo(id2); // 如果获取配置失败,按ID排序 } // 先比较品质 int qualityCompare = config2.BGQuality.CompareTo(config1.BGQuality); if (qualityCompare != 0) { return qualityCompare; // 品质不同,按品质排序 } // 品质相同,按ID排序 return id1.CompareTo(id2); }); } return fatesIDList; } public string GetCellBgByFatesQuality(int fatesQuality) { return StringUtility.Concat("HeroFatesQualityBG", fatesQuality.ToString()); } public string GetHeroFatesNameBGByFatesQuality(int fatesQuality) { return StringUtility.Concat("HeroFatesNameBG", fatesQuality.ToString()); } #endregion } public enum HeroFatesState { Locked, // 未激活 Activatable, // 可激活 (未激活但材料足够) ActiveNotUpgradable,// 已激活但不可升级 (材料不足或配置不支持) ActiveUpgradable, // 已激活且可升级 (材料足够升级下一档) MaxLevel, // 已升到满级 } public class HeroFates { public int FatesID; // 宿缘ID public int State; // 宿缘状态:0-未激活;1-已激活已领奖 public int FatesLV; // 宿缘等级,激活时为0级,升级后有升级属性 }