using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UI; public class OtherHeroDetailWin : UIBase { [SerializeField] ImageEx bgImage; [SerializeField] ImageEx iconImage; [SerializeField] SkillBaseCell normalSkillCell; [SerializeField] SkillBaseCell angerSkillCell; [SerializeField] HeroShowBaseCell heroShow; [SerializeField] ButtonEx btnTotalAttr; [SerializeField] TextEx[] attrs; [SerializeField] GiftBaseCell[] giftBaseCells; //天赋 [SerializeField] ScrollRect allAttrScroll; //培养属性 滚动区 [SerializeField] GameObject fetterGo; [SerializeField] Text[] fetterText; //羁绊 [SerializeField] Text[] fetterNameText; //羁绊 [SerializeField] Color32 nameCol; [SerializeField] Color32 descCol; [SerializeField] Color32 grayCol; [SerializeField] GameObject potential; [SerializeField] GameObject potentialCell; //潜能和觉醒用于创建 [SerializeField] Transform potentialCellParent; //潜能父节点 [SerializeField] Transform awakeCellParent; //潜能父节点 [SerializeField] GameObject awakeGo; Dictionary attrDict; OtherPlayerDetailManager manager { get { return OtherPlayerDetailManager.Instance; } } protected override void InitComponent() { awakeCellList = new List(); potentialCellList = new List(); btnTotalAttr.SetListener(() => { AttributeManager.Instance.OpenTotalAttributeWin(attrDict == null ? new Dictionary() : attrDict); }); } protected override void OnPreOpen() { // 重置所有滚动区到顶部 if (allAttrScroll != null) allAttrScroll.verticalNormalizedPosition = 1f; Display(); } protected override void OnPreClose() { } private bool TryGetHeroInfo(BattleClickHeroData data, out HeroInfo heroInfo) { heroInfo = null; if (!HeroManager.Instance.HasHero(data.heroID)) return false; heroInfo = HeroManager.Instance.GetHeroByID(data.heroID); return true; } private void Display() { attrDict = null; ViewHeroDetailData viewData = manager.viewHeroDetailData; if (viewData == null) return; switch (viewData.viewHeroType) { case 0: BattleClickHeroData data = manager.viewHeroDetailData.clickHeroData; bgImage.SetSprite(data.isMySide ? "OtherHeroDetailBGBlue" : "OtherHeroDetailBGRed"); iconImage.SetSprite(data.isMySide ? "OtherHeroDetailIconBlue" : "OtherHeroDetailIconRed"); if (data.isMySide) { if (!TryGetHeroInfo(data, out HeroInfo heroInfo)) { SysNotifyMgr.Instance.ShowTip("NoHeroFromBag"); DelayCloseWindow().Forget(); return; } heroInfo.CalculateFightPower(); attrDict = FightPowerManager.Instance.GetHeroTotalAttr(heroInfo); DisplayByMyPack(heroInfo, data); } else { if (BattleManager.Instance.IsPvpBattle(data.battleName)) { attrDict = viewData.heroData?.AttrDict; DiplayByViewOtherPlayer(viewData.heroData, viewData.heroDatas); } else { attrDict = viewData.viewNPCAttr?.AttrDict; DisplayByViewNPCAttr(viewData.viewNPCAttr); } } break; case 1: default: bgImage.SetSprite("OtherHeroDetailBGRed"); iconImage.SetSprite("OtherHeroDetailIconRed"); attrDict = viewData.heroData?.AttrDict; DiplayByViewOtherPlayer(viewData.heroData, viewData.heroDatas); break; } } void DisplayByMyPack(HeroInfo heroInfo, BattleClickHeroData data) { if (heroInfo == null) return; HeroConfig heroConfig = heroInfo?.heroConfig; if (heroConfig == null || data.teams == null || !data.isMySide) return; int heroID = heroConfig.HeroID; int skinID = heroConfig?.SkinIDList[0] ?? 0; int lv = heroInfo.heroLevel; int star = heroInfo.heroStar; int quality = heroConfig.Quality; int breakLevel = heroInfo.breakLevel; int awakeLevel = heroInfo.awakeLevel; int atkSkillID = heroConfig.AtkSkillID; int angerSkillID = heroConfig.AngerSkillID; List talentIDList = heroInfo.talentIDList; List talentLvList = heroInfo.talentLvList; int[] FetterIDList = heroConfig.FetterIDList; DisplaySkill(heroID, atkSkillID, angerSkillID); DisplayHeroShow(heroID, skinID, breakLevel, star, awakeLevel, lv); DisplayAttr(attrDict); DisplayGiftBaseCell(heroID, awakeLevel, talentIDList, talentLvList); DisplayFetter(data.teams, FetterIDList); DisplayPotential(heroID, breakLevel); RefreshAwake(heroID, quality, awakeLevel); ForceRefreshLayout(); } void DisplayByViewNPCAttr(ViewNPCAttr viewNPCAttr) { if (viewNPCAttr == null) return; int heroID = (int)viewNPCAttr.HeroID; if (!HeroConfig.HasKey(heroID)) return; HeroConfig heroConfig = HeroConfig.Get(heroID); int skinID = heroConfig?.SkinIDList[0] ?? 0; int lv = viewNPCAttr.LV; int star = viewNPCAttr.Star; int quality = heroConfig.Quality; int breakLevel = viewNPCAttr.BreakLV; int awakeLevel = viewNPCAttr.AwakeLV; int atkSkillID = heroConfig.AtkSkillID; int angerSkillID = heroConfig.AngerSkillID; List talentIDList = null; List talentLvList = null; int[] FetterIDList = heroConfig.FetterIDList; DisplaySkill(heroID, atkSkillID, angerSkillID); DisplayHeroShow(heroID, skinID, breakLevel, star, awakeLevel, lv); DisplayAttr(attrDict); DisplayGiftBaseCell(heroID, awakeLevel, talentIDList, talentLvList); DisplayFetter(teams: null, FetterIDList); DisplayPotential(heroID, breakLevel); RefreshAwake(heroID, quality, awakeLevel); ForceRefreshLayout(); } void DiplayByViewOtherPlayer(OtherPlayerDetailManager.RolePlusData.HeroData heroData, List heroDatas) { if (heroDatas.IsNullOrEmpty() || heroData == null) return; int heroID = heroData.HeroID; if (!HeroConfig.HasKey(heroID)) return; HeroConfig heroConfig = HeroConfig.Get(heroID); int skinID = heroData.SkinID; int lv = heroData.LV; int star = heroData.Star; int quality = heroConfig.Quality; int breakLevel = manager.GetBreakLevel(heroData); int awakeLevel = manager.GetAwakeLevel(heroData); int atkSkillID = heroConfig.AtkSkillID; int angerSkillID = heroConfig.AngerSkillID; List talentIDList = manager.GetTalentIDList(heroData); List talentLvList = manager.GetTalentLvList(heroData); int[] FetterIDList = heroConfig.FetterIDList; DisplaySkill(heroID, atkSkillID, angerSkillID); DisplayHeroShow(heroID, skinID, breakLevel, star, awakeLevel, lv); DisplayAttr(attrDict); DisplayGiftBaseCell(heroID, awakeLevel, talentIDList, talentLvList); DisplayFetter(heroDatas, FetterIDList); DisplayPotential(heroID, breakLevel); RefreshAwake(heroID, quality, awakeLevel); ForceRefreshLayout(); } List awakeCellList; //觉醒 void RefreshAwake(int heroID, int quality, int awakeLevel) { if (!HeroAwakeConfig.CanAwake(heroID, 1)) { awakeGo.SetActive(false); return; } awakeGo.SetActive(true); var maxLV = HeroAwakeConfig.GetMaxAwakeLV(heroID); var starCnt = HeroQualityConfig.Get(quality).InitStarUpper; for (int i = 1; i <= maxLV; i++) { if (i > awakeCellList.Count) { awakeCellList.Add(Instantiate(potentialCell, awakeCellParent)); } var go = awakeCellList[i - 1]; var descText = go.GetComponent(); var nameText = go.GetComponent("skillname"); go.SetActive(true); var config = HeroAwakeConfig.GetHeroAwakeConfig(heroID, i); int type = config.UnlockTalentSlot != 0 ? 1 : config.SkillID != 0 ? 2 : 3; var awakeStr = string.Empty; if (type == 1) { starCnt += config.AddStarUpper; awakeStr = Language.Get("HeroAwake8", config.UnlockTalentSlot, starCnt); } else if (type == 2) { var skill = SkillConfig.Get(config.SkillID); if (skill != null) { awakeStr = Language.Get("L1039", skill.SkillName) + skill.Description; } else { Debug.LogError($"heroId:{heroID} 觉醒技能ID:{config.SkillID} 配置错误技能不存在"); } } else { for (int k = 0; k < config.AttrIDList.Length; k++) { awakeStr += (string.IsNullOrEmpty(config.SkillIName) ? string.Empty : Language.Get("L1039", config.SkillIName)) + PlayerPropertyConfig.GetFullDescription(config.AttrIDList[k], config.AttrValueList[k], "{0}+" + UIHelper.AppendColor(TextColType.Green, "{1}")) + (k == config.AttrIDList.Length - 1 ? "" : "\n"); } } if (i - 1 < awakeLevel) { nameText.text = Language.Get("herocard12", i) + Language.Get("L1096"); descText.text = awakeStr; } else { //置灰 nameText.text = UIHelper.AppendColor(TextColType.NavyGray, Language.Get("herocard12", i) + Language.Get("L1096")); descText.text = UIHelper.AppendColor(TextColType.NavyGray, UIHelper.RemoveColor(awakeStr)); } } } List potentialCellList; //潜能 void DisplayPotential(int heroID, int breakLevel) { if (!HeroBreakConfig.configDics.ContainsKey(heroID)) { potential.SetActive(false); return; } potential.SetActive(true); var list = HeroBreakConfig.configDics[heroID].Keys.ToList(); list.Sort(); for (int i = 0; i < list.Count; i++) { var nextQualityBreakConfig = HeroBreakConfig.GetHeroBreakConfig(heroID, i + 1); if (nextQualityBreakConfig == null) break; List attrStrArr = new List(); for (int j = 0; j < nextQualityBreakConfig.AttrIDList.Length; j++) { if (nextQualityBreakConfig.AttrIDList[j] == 0) continue; string format = i < breakLevel ? "{0}" + UIHelper.AppendColor(TextColType.Green, "+{1}") : "{0}+{1}"; attrStrArr.Add((string.IsNullOrEmpty(nextQualityBreakConfig.SkillIName) ? string.Empty : Language.Get("L1039", nextQualityBreakConfig.SkillIName)) + PlayerPropertyConfig.GetFullDescription(nextQualityBreakConfig.AttrIDList[j], nextQualityBreakConfig.AttrValueList[j], format)); } if (nextQualityBreakConfig.SkillID != 0) { var skill = SkillConfig.Get(nextQualityBreakConfig.SkillID); if (skill != null) { attrStrArr.Add(Language.Get("L1039", skill.SkillName) + skill.Description); } else { Debug.LogError("未配置技能" + nextQualityBreakConfig.SkillID); } } if (i >= potentialCellList.Count) { potentialCellList.Add(Instantiate(potentialCell, potentialCellParent)); } var go = potentialCellList[i]; var descText = go.GetComponent(); var nameText = go.GetComponent("skillname"); go.SetActive(true); if (i < breakLevel) { nameText.text = Language.Get("herocard63", i + 1); descText.text = string.Join("\n", attrStrArr); } else { //置灰 nameText.text = UIHelper.AppendColor(TextColType.NavyGray, Language.Get("herocard63", i + 1)); descText.text = UIHelper.AppendColor(TextColType.NavyGray, UIHelper.RemoveColor(string.Join("\n", attrStrArr))); } } } private void DisplayAttr(Dictionary attrDict) { if (attrDict.IsNullOrEmpty()) return; var baseAttrIDList = PlayerPropertyConfig.playerPropertyDict[PlayerPropertyConfig.baseType]; var fightAttrIDList = PlayerPropertyConfig.playerPropertyDict[PlayerPropertyConfig.fightType]; var antiAttrIDList = PlayerPropertyConfig.playerPropertyDict[PlayerPropertyConfig.fightAntiType]; var totalAttrIDList = baseAttrIDList.Concat(fightAttrIDList).Concat(antiAttrIDList).ToList(); for (int i = 0; i < attrs.Length; i++) { if (i < totalAttrIDList.Count) { attrs[i].SetActive(true); int attrId = totalAttrIDList[i]; if (PlayerPropertyConfig.HasKey(attrId)) { PlayerPropertyConfig config = PlayerPropertyConfig.Get(attrId); long attrValue = attrDict.ContainsKey(attrId) ? attrDict[attrId] : 0; attrs[i].text = Language.Get("OtherPlayerDetail15", config.Name, PlayerPropertyConfig.GetValueDescription(attrId, attrValue)); } else { attrs[i].SetActive(false); } } else { attrs[i].SetActive(false); } } } private bool HasFetterHero(List teams, int heroID) { if (teams.IsNullOrEmpty()) { return false; } for (int i = 0; i < teams.Count; i++) { if (!(teams[i] is HeroBattleObject heroObj) || heroObj.teamHero == null) { continue; } if (heroObj.teamHero.heroId == heroID) { return true; } } return false; } private bool HasFetterHero(List heroDatas, int heroID) { if (heroDatas.IsNullOrEmpty()) { return false; } for (int i = 0; i < heroDatas.Count; i++) { if (heroDatas[i].HeroID == heroID) { return true; } } return false; } private void DisplayFetter(List teams, int[] FetterIDList) { if (FetterIDList.IsNullOrEmpty() || teams.IsNullOrEmpty()) { fetterGo.SetActive(false); return; } for (int i = 0; i < fetterText.Length; i++) { if (i < FetterIDList.Length) { fetterText[i].SetActive(true); var fetterID = FetterIDList[i]; HeroFetterConfig fetterConfig = HeroFetterConfig.Get(fetterID); List heroNames = new List(); bool isAllCollect = true; //是否全收集 foreach (var tmpHeroID in fetterConfig.HeroIDList) { heroNames.Add(HeroConfig.Get(tmpHeroID).Name); bool hasFetterHero = HasFetterHero(teams, tmpHeroID); if (!hasFetterHero) { isAllCollect = false; } } fetterGo.SetActive(isAllCollect); var attrStr = string.Join(Language.Get("SplitString1"), heroNames) + Language.Get("herocard38"); for (int j = 0; j < fetterConfig.AttrIDList.Length; j++) { string format = !isAllCollect ? "{0}+{1}" : "{0}+" + UIHelper.AppendColor(TextColType.Green, "{1}"); attrStr += Language.Get("L1112") + PlayerPropertyConfig.GetFullDescription(fetterConfig.AttrIDList[j], fetterConfig.AttrValueList[j], format); } fetterText[i].text = attrStr; fetterText[i].color = isAllCollect ? descCol : grayCol; fetterNameText[i].text = fetterConfig.FetterName; fetterNameText[i].color = isAllCollect ? nameCol : grayCol; } else { fetterText[i].SetActive(false); } } } private void DisplayFetter(List heroDatas, int[] FetterIDList) { if (FetterIDList.IsNullOrEmpty() || heroDatas.IsNullOrEmpty()) { fetterGo.SetActive(false); return; } for (int i = 0; i < fetterText.Length; i++) { if (i < FetterIDList.Length) { fetterText[i].SetActive(true); var fetterID = FetterIDList[i]; HeroFetterConfig fetterConfig = HeroFetterConfig.Get(fetterID); List heroNames = new List(); bool isAllCollect = true; //是否全收集 foreach (var tmpHeroID in fetterConfig.HeroIDList) { heroNames.Add(HeroConfig.Get(tmpHeroID).Name); bool hasFetterHero = HasFetterHero(heroDatas, tmpHeroID); if (!hasFetterHero) { isAllCollect = false; } } fetterGo.SetActive(isAllCollect); var attrStr = string.Join(Language.Get("SplitString1"), heroNames) + Language.Get("herocard38"); for (int j = 0; j < fetterConfig.AttrIDList.Length; j++) { string format = !isAllCollect ? "{0}+{1}" : "{0}+" + UIHelper.AppendColor(TextColType.Green, "{1}"); attrStr += Language.Get("L1112") + PlayerPropertyConfig.GetFullDescription(fetterConfig.AttrIDList[j], fetterConfig.AttrValueList[j], format); } fetterText[i].text = attrStr; fetterText[i].color = isAllCollect ? descCol : grayCol; fetterNameText[i].text = fetterConfig.FetterName; fetterNameText[i].color = isAllCollect ? nameCol : grayCol; } else { fetterText[i].SetActive(false); } } } private void DisplayGiftBaseCell(int heroID, int awakeLevel, List talentIDList, List talentLvList) { int showCount = HeroUIManager.Instance.GetGiftGirdMaxCount(heroID); if (talentIDList == null || talentLvList == null) { for (int i = 0; i < giftBaseCells.Length; i++) { if (i >= showCount) { giftBaseCells[i].SetActive(false); continue; } giftBaseCells[i].SetActive(true); //非对比的显示 if (i < HeroUIManager.Instance.normalGiftMaxCnt) { giftBaseCells[i].Init(0, 0); } else { giftBaseCells[i].Init(-1, 0, 0, heroID, i); } } return; } for (int i = 0; i < giftBaseCells.Length; i++) { if (i >= showCount) { giftBaseCells[i].SetActive(false); continue; } giftBaseCells[i].SetActive(true); if (i < talentIDList.Count) { int giftID = talentIDList[i]; int giftLV = talentLvList[i]; int state = 0; //0:不显示 1:新增 2:提升 giftBaseCells[i].Init(giftID, giftLV, state, heroID, i, awakeLevel); } else { //非对比的显示 if (i < HeroUIManager.Instance.normalGiftMaxCnt) { giftBaseCells[i].Init(0, 0); } else { giftBaseCells[i].Init(-1, 0, 0, heroID, i); } } } } private void DisplayHeroShow(int heroID, int skinID, int breakLevel, int star, int awakeLevel, int lv) { heroShow.Init(heroID, skinID, breakLevel, star, awakeLevel, lv); } private void DisplaySkill(int heroID, int atkSkillID, int angerSkillID) { if (!HeroConfig.HasKey(heroID) || !SkillConfig.HasKey(atkSkillID) || !SkillConfig.HasKey(angerSkillID)) { normalSkillCell.SetActive(false); angerSkillCell.SetActive(false); return; } normalSkillCell.SetActive(true); angerSkillCell.SetActive(true); normalSkillCell.Init(atkSkillID, () => { UIManager.Instance.OpenWindow(heroID); }, true); angerSkillCell.Init(angerSkillID, () => { UIManager.Instance.OpenWindow(heroID); }, true); } /// /// 强制刷新Layout,解决嵌套Layout和ContentSizeFitter的重叠问题 /// async UniTask ForceRefreshLayout() { await UniTask.DelayFrame(2); // 刷新所有Layout组件 var layouts = allAttrScroll.GetComponentsInChildren(true); foreach (var layout in layouts) { LayoutRebuilder.ForceRebuildLayoutImmediate(layout.GetComponent()); } await UniTask.DelayFrame(2); // 刷新所有Layout组件 foreach (var layout in layouts) { LayoutRebuilder.ForceRebuildLayoutImmediate(layout.GetComponent()); } // Layout刷新完成后重新设置滚动位置 if (allAttrScroll != null) allAttrScroll.verticalNormalizedPosition = 1f; } }