using DG.Tweening; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace vnxbqy.UI { public class FairySiegeCityWin : Window { [SerializeField] ButtonEx btnBattleReport; //战报 [SerializeField] ButtonEx btnClose; [SerializeField] ButtonEx btnSummonDragon; //神龙召唤 [SerializeField] RedpointBehaviour rpSummonDragon; [SerializeField] ButtonEx btnSwitchGroup; //切换分组 [SerializeField] TextEx txtRemainTime; [SerializeField] ImageEx imgEndRound; //最后一轮横幅 [Header("城池")] [SerializeField] FairySiegeCityItem[] regularCityArr; [Header("修罗城")] [SerializeField] RectTransform rectBossCity; [SerializeField] ButtonEx btnBossCity; [SerializeField] FairySiegeSlider slidBossCity; [SerializeField] ImageEx imgBossCity; [SerializeField] ImageEx imgBossCityEffect; [Header("飞龙在天技能公告框")] [SerializeField] EmblemCell emblemSkill; [SerializeField] ImageEx imgSkillIcon; [SerializeField] ImageEx imgSkillName; [SerializeField] RectTransform rectSkill; [SerializeField] ScrollRect scrollRect; //滚动组件 [SerializeField] RectTransform tranMap; [SerializeField] TextEx txtFairyNameSkill; [SerializeField] TextEx txtPlayerNameSkill; [Header("个人仙盟面板")] [SerializeField] Transform transMyFairy; [SerializeField] TextEx txtFairyName; [SerializeField] EmblemCell emblem; [SerializeField] ButtonEx btnRank; [SerializeField] TextEx txtRank; [SerializeField] FairySiegeStarGroup starGroup; [SerializeField] Slider slidFairy; [SerializeField] Text txtFairyHP; [SerializeField] RectTransform rectStart; [SerializeField] RectTransform rectMiddle; [SerializeField] RectTransform rectEnd; FairySiegeActModel model { get { return ModelCenter.Instance.GetModel(); } } #region Build-in protected override void AddListeners() { btnBossCity.SetListener(() => { if (model.isWaitC030Pack) return; model.isWaitC030Pack = true; model.isClickCity = true; model.showCityId = model.BossCityId; model.SendQuery(4, model.showBatType, model.showBatGroup, model.showCityId); }); btnClose.SetListener(CloseClick); btnSummonDragon.SetListener(() => { WindowCenter.Instance.Open(); }); btnBattleReport.SetListener(() => { model.SendQuery(6, 0, 0, 0); }); btnSwitchGroup.SetListener(() => WindowCenter.Instance.Open()); btnRank.SetListener(() => WindowCenter.Instance.Open(false, 1)); } protected override void BindController() { } protected override void OnPreOpen() { rpSummonDragon.redpointId = model.GetRedpointId(FairySiegeRedPointType.SummonDragon); fairySiegeBatSceneInfoQueue.Clear(); playSiegeBatSceneInfoQueue.Clear(); model.atkAwardQueue.Clear(); isPlayingMySkillAnim = false; isPlaying = false; model.isClickCity = false; model.isWaitC030Pack = false; scrollRect.SetActive(false); rectBossCity.SetActive(false); model.UpdateSwitchGroupAction += OnUpdateSwitchGroupAction; model.UpdateFamilyGCZBatSceneInfoEvent += OnUpdateFamilyGCZBatSceneInfoEvent; model.UpdateFamilyGCZBatReportEvent += OnUpdateFamilyGCZBatReportEvent; model.JumpToCityAction += OnJumpToCityAction; model.UpdateFamilyGCZBatCityInfoEvent += OnUpdateFamilyGCZBatCityInfoEvent; GlobalTimeEvent.Instance.secondEvent += OnSecondEvent; model.UpdateBatSceneHurtListEvent += OnUpdateBatSceneHurtListEvent; } protected override void OnPreClose() { model.UpdateSwitchGroupAction -= OnUpdateSwitchGroupAction; model.UpdateFamilyGCZBatSceneInfoEvent -= OnUpdateFamilyGCZBatSceneInfoEvent; model.UpdateFamilyGCZBatReportEvent -= OnUpdateFamilyGCZBatReportEvent; model.JumpToCityAction -= OnJumpToCityAction; model.UpdateFamilyGCZBatCityInfoEvent -= OnUpdateFamilyGCZBatCityInfoEvent; GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent; model.UpdateBatSceneHurtListEvent -= OnUpdateBatSceneHurtListEvent; model.SendQuery(3, 0, 0, 0); } private void OnJumpToCityAction(uint tagFamilyID) { if (tagFamilyID == model.BossCityId) { JumpToCity(rectBossCity); } else { if (!TryFindCity(tagFamilyID, out RectTransform rect)) return; JumpToCity(rect); } } public Queue playSiegeBatSceneInfoQueue = new Queue(); public Queue fairySiegeBatSceneInfoQueue = new Queue(); private void OnUpdateBatSceneHurtListEvent(FairySiegeBatSceneInfo info) { if (info == null) return; if (info.AtkPlayerID == (int)PlayerDatas.Instance.baseData.PlayerID) { playSiegeBatSceneInfoQueue.Enqueue(model.DeepCopyFairySiegeBatSceneInfo(info)); } else { fairySiegeBatSceneInfoQueue.Enqueue(model.DeepCopyFairySiegeBatSceneInfo(info)); } } private void OnUpdateFamilyGCZBatReportEvent() { if (!WindowCenter.Instance.IsOpen()) { WindowCenter.Instance.Open(); } } private void OnUpdateSwitchGroupAction() { model.SendQuery(3, 0, 0, 0); model.SendQuery(2, model.showBatType, model.showBatGroup, 0); } private void OnUpdateFamilyGCZBatSceneInfoEvent() { imgEndRound.SetActive(model.matchRound == model.matchRoundMax); DisplayBatEndCountdown(); DisplayCity(); DisplayMyFamily(); } protected override void OnAfterOpen() { Reset(); Display(); scrollRect.SetActive(true); } protected override void OnAfterClose() { } #endregion //使用飞龙在天技能,移动到指定城池 private void MoveToCityPos(FairySiegeBatSceneInfo info) { //使用飞龙在天技能,移动到指定城池 if (info.AtkType == 2 && !info.BatSceneHurtList.IsNullOrEmpty() && info.AtkPlayerID == PlayerDatas.Instance.baseData.PlayerID) { bool isBossCityShow = model.TryGetBossCityData(model.showBatType, model.showBatGroup, out FairySiegeBatSceneCity bossCityData); if (isBossCityShow) { var normalizedPosition = CalculateNormalizedPosition(rectBossCity); scrollRect.horizontalNormalizedPosition = normalizedPosition; } else { for (int i = 0; i < info.BatSceneHurtList.Count; i++) { if (TryFindCity(info.BatSceneHurtList[i].CityID, out var rect)) { var normalizedPosition = CalculateNormalizedPosition(rect); scrollRect.horizontalNormalizedPosition = normalizedPosition; } } } } } private void UpdateSkillFrame(FairySiegeBatSceneInfo info) { imgSkillIcon.SetSprite(model.GetSkillIcon((int)info.AtkType)); imgSkillIcon.SetNativeSize(); imgSkillName.SetSprite(model.GetSkillNameIcon((int)info.AtkType)); imgSkillName.SetNativeSize(); if (info.BatScenePlayerInfoDict.TryGetValue(info.AtkPlayerID, out var batScenePlayerInfo) && model.TryGetFairySiegeFamilyInfo(batScenePlayerInfo.FamilyID, out FairySiegeFamilyInfo fairySiegeFamilyInfo)) { emblemSkill.SetActive(true); emblemSkill.InitUI(EmblemHelper.GetOtherEmblemModel((int)fairySiegeFamilyInfo.EmblemID)); txtFairyNameSkill.text = fairySiegeFamilyInfo.Name; txtPlayerNameSkill.text = batScenePlayerInfo.Name; } else { emblemSkill.SetActive(false); txtFairyNameSkill.text = string.Empty; txtPlayerNameSkill.text = string.Empty; } } protected override void LateUpdate() { PlayAnim(); DisplayAwardWin(); } Sequence seqFrame; bool isPlayingMySkillAnim = false; bool isPlaying = false; private void PlayAnim() { FairySiegeBatSceneInfo info = null; if (playSiegeBatSceneInfoQueue.Count <= 0 && fairySiegeBatSceneInfoQueue.Count <= 0) return; if (isPlaying) return; isPlaying = true; if (playSiegeBatSceneInfoQueue.Count > 0) { info = playSiegeBatSceneInfoQueue.Dequeue(); } else { if (fairySiegeBatSceneInfoQueue.Count > 0) { info = fairySiegeBatSceneInfoQueue.Dequeue(); } } if (info == null || info.BatSceneHurtList == null || info.AtkPlayerID <= 0) { isPlaying = false; return; } if (!model.isSummonDragonWatch && info.AtkPlayerID != PlayerDatas.Instance.baseData.PlayerID) { isPlaying = false; return; } isPlayingMySkillAnim = false; if (info.AtkPlayerID == PlayerDatas.Instance.baseData.PlayerID) { isPlayingMySkillAnim = true; } Reset(); MoveToCityPos(info); seqFrame = DOTween.Sequence(); seqFrame.Append(rectSkill.DOMove(rectMiddle.position, 0.3f) .OnStart(() => { UpdateSkillFrame(info); }) .OnComplete(() => { PlayThunder(info); PlayDamage(info); PlayShake(info); })); seqFrame.AppendInterval(0.3f); seqFrame.AppendCallback(StopThunder); seqFrame.Append(rectSkill.DOMove(rectEnd.position, 0.3f).SetDelay(0.8f). OnComplete(() => { isPlaying = false; isPlayingMySkillAnim = false; })); } //非战斗期玩家还在战斗界面时,退出相关界面 private void ExitWin() { if (!model.TryGetCurrentStateValue(out int stateValue)) return; int state = model.GetStateByStateValue(stateValue);// 0 公示期 1 备战期 2 开战期 3 休战期 4 领奖期 if (state != 2) { WindowCenter.Instance.Close(); } } private void OnSecondEvent() { imgEndRound.SetActive(model.matchRound == model.matchRoundMax); DisplayBatEndCountdown(); DisplayCity(); ExitWin(); } private void DisplayBatEndCountdown() { if (!model.TryGetCurrentStateValue(out int stateValue)) return; int state = model.GetStateByStateValue(stateValue);//0 公示期 1 备战期 2 开战期 3 休战期 4 领奖期 int roundNum = model.GetRoundNumByStateValue(stateValue); bool isRemainTimeShow = state == 2; txtRemainTime.SetActive(isRemainTimeShow); if (isRemainTimeShow && model.TryGetEndTimeByStateValue(stateValue, out DateTime endTime) && endTime > ILTimeUtility.ServerCrossNow ) { string time = TimeUtility.SecondsToDHMS((int)(endTime - ILTimeUtility.ServerCrossNow).TotalSeconds); txtRemainTime.text = Language.Get("FairySiege071", roundNum, time); } else { txtRemainTime.text = string.Empty; } } private void DisplayAwardWin() { if (model.cityAwardQueue.Count <= 0) return; if (isPlayingMySkillAnim) return; if (WindowCenter.Instance.IsOpen("FairySiegeSummonGetItemWin")) return; var netPack = model.cityAwardQueue.Dequeue(); model.nowAtkAwardInfo = netPack; if (model.nowAtkAwardInfo.atkAwardInfo == null) return; ItemLogicUtility.Instance.ShowGetItemEx("FairySiegeSummonGetItemWin", netPack.showItems, netPack.info, 0, eventName: netPack.eventName); } public void Reset() { rectSkill.localPosition = rectStart.localPosition; seqFrame?.Kill(); StopThunder(); StopShake(); } private void DisplayMyFamily() { transMyFairy.SetActive(false); if (!model.TryGetNowBatTypeAndGroup(model.myFamilyID, out int battleType, out int battleGroup)) return; if (model.showBatType != battleType || model.showBatGroup != battleGroup) return; if (!model.TryGetBatSceneCityInfo(battleType, battleGroup, model.myFamilyID, out FairySiegeBatSceneCity batSceneCity)) return; if (!model.TryGetFairySiegeFamilyInfo(model.myFamilyID, out FairySiegeFamilyInfo familyInfo)) return; transMyFairy.SetActive(true); if (FamilyGCZCampLVConfig.Has(model.myCityLV)) { FamilyGCZCampLVConfig config = FamilyGCZCampLVConfig.Get(model.myCityLV); starGroup.Display(config.StarCount); } float fillAmount = Mathf.Round((float)batSceneCity.HP / batSceneCity.HPMax * 1000f) / 1000f; string info = Language.Get("FairySiege125", UIHelper.ReplaceLargeNum(batSceneCity.HP), UIHelper.ReplaceLargeNum(batSceneCity.HPMax)); slidFairy.value = fillAmount; txtFairyHP.text = info; txtFairyName.text = familyInfo.Name; txtRank.text = Language.Get("FairySiege072", batSceneCity.Rank); emblem.InitUI(EmblemHelper.GetOtherEmblemModel((int)familyInfo.EmblemID)); } public void Display() { imgEndRound.SetActive(model.matchRound == model.matchRoundMax); DisplayBatEndCountdown(); DisplayCity(); JumpMyCity(); DisplayMyFamily(); } private void OnUpdateFamilyGCZBatCityInfoEvent(FairySiegeBatCityInfo nowInfo) { model.isWaitC030Pack = false; if (model.isClickCity) { model.isClickCity = false; if (WindowCenter.Instance.IsOpen()) return; model.DeepCopyFairySiegeBatCityInfo(nowInfo, model.lastFairySiegeBatCityInfo); WindowCenter.Instance.Open(); } } #region 城池 private void JumpToCity(RectTransform rect) { var normalizedPosition = CalculateNormalizedPosition(rect); scrollRect.horizontalNormalizedPosition = normalizedPosition; } // 尝试通过仙盟Id找到城池位置 public bool TryFindCity(uint cityId, out RectTransform rect) { rect = null; if (!model.TryGetCityIndex(model.showBatType, model.showBatGroup, cityId, out var index)) return false; if (index < 0 || index >= regularCityArr.Length) return false; rect = regularCityArr[index].transform as RectTransform; return true; } // 跳转到我的城池 private void JumpMyCity() { //存在修罗城跳转到修罗城 if (model.TryGetBossCityData(model.showBatType, model.showBatGroup, out FairySiegeBatSceneCity bossCityData)) { JumpToCity(rectBossCity); } else { var familyId = PlayerDatas.Instance.baseData.FamilyId; if (!TryFindCity(familyId, out var rect)) { return; } JumpToCity(rect); } } private float CalculateNormalizedPosition(RectTransform rect) { // 获取滚动视图的宽度 var scrollViewWidth = scrollRect.viewport.rect.width; // 获取地图的宽度 var mapWidth = tranMap.rect.width; // 获取城池在地图中的局部位置 Vector2 localPos = rect.localPosition; // 计算城池中心在地图中的X位置(考虑到城池的锚点是(0.5, 0.5)) var cityPosX = localPos.x; // 计算地图内容可滚动的总距离 var scrollableWidth = mapWidth - scrollViewWidth; if (scrollableWidth <= 0) return 0; // 计算目标位置,让城池尽量居中显示 var targetPos = cityPosX - scrollViewWidth / 2; // 确保目标位置在有效范围内 targetPos = Mathf.Clamp(targetPos, 0, scrollableWidth); // 计算归一化位置 (0 = 最左侧, 1 = 最右侧) var normalizedPosition = targetPos / scrollableWidth; return normalizedPosition; } public void DisplayCity() { rectBossCity.SetActive(false); if (!model.TryGetRegularCityDataList(model.showBatType, model.showBatGroup, out List regularCityDataList)) return; for (int i = 0; i < regularCityArr.Length; i++) { if (i < regularCityDataList.Count) { regularCityArr[i].SetActive(true); regularCityArr[i].Display(regularCityDataList[i]); } else { regularCityArr[i].SetActive(false); } } //存在修罗城 if (model.TryGetBossCityData(model.showBatType, model.showBatGroup, out FairySiegeBatSceneCity bossCityData)) { rectBossCity.SetActive(true); float rate = (float)bossCityData.HP / (float)bossCityData.HPMax; string rateStr = Language.Get("BlessedLand039", (rate * 100).ToString("F2")); slidBossCity.Display(rate, rateStr); } } #endregion #region 飘字 private void PlayDamage(FairySiegeBatSceneInfo info) { bool isBossCityShow = model.TryGetBossCityData(model.showBatType, model.showBatGroup, out FairySiegeBatSceneCity bossCityData); if (isBossCityShow) { if (TryGetBossCityDamage(info, out long damage)) { PlayBossCityDamageSeq(damage); } } else { for (int i = 0; i < info.BatSceneHurtList.Count; i++) { if (model.TryGetCityIndex(model.showBatType, model.showBatGroup, info.BatSceneHurtList[i].CityID, out var index)) { regularCityArr[index].PlayDamageSeq((long)info.BatSceneHurtList[i].HurtValue); } } } } public void PlayBossCityDamageSeq(long damage) { GameObject prefab = UIUtility.CreateWidget("FairySiegeCityPopUpNum", "FairySiegeCityPopUpNum"); prefab.transform.SetParentEx(this.transform, Vector3.zero, Quaternion.identity, Vector3.one); prefab.GetComponent().Play(damage); } public bool TryGetBossCityDamage(FairySiegeBatSceneInfo info, out long damage) { damage = 0; if (info == null || info.BatSceneHurtList == null) return false; foreach (var item in info.BatSceneHurtList) { if (item.CityID == model.BossCityId) { damage = (long)item.HurtValue; return true; } } return false; } #endregion #region 抖动 private Tweener shakeTween; public void PlayBossCityShakeTween() { shakeTween = imgBossCity.transform.DOShakeRotation(0.5f, 10, 10, 90).SetEase(Ease.InOutElastic).OnComplete(() => { imgBossCity.transform.localRotation = Quaternion.identity; }); } public void StopBossCityShakeTween() { shakeTween?.Kill(); imgBossCity.transform.localRotation = Quaternion.identity; } public void StopShakeTween() { foreach (var item in regularCityArr) { item.StopShakeTween(); } } public void StopShake() { StopShakeTween(); StopBossCityShakeTween(); } private void PlayShake(FairySiegeBatSceneInfo info) { bool isBossCityShow = model.TryGetBossCityData(model.showBatType, model.showBatGroup, out FairySiegeBatSceneCity bossCityData); if (isBossCityShow) { PlayBossCityShakeTween(); } else { for (int i = 0; i < info.BatSceneHurtList.Count; i++) { if (model.TryGetCityIndex(model.showBatType, model.showBatGroup, info.BatSceneHurtList[i].CityID, out var index)) { regularCityArr[index].PlayShakeTween(); } } } } #endregion #region 落雷 private void PlayThunder(FairySiegeBatSceneInfo info) { bool isBossCityShow = model.TryGetBossCityData(model.showBatType, model.showBatGroup, out FairySiegeBatSceneCity bossCityData); if (isBossCityShow) { PlayBossCityThunderEffect(); } else { for (int i = 0; i < info.BatSceneHurtList.Count; i++) { if (model.TryGetCityIndex(model.showBatType, model.showBatGroup, info.BatSceneHurtList[i].CityID, out var index)) { regularCityArr[index].PlayThunderEffect(); } } } } private void StopThunder() { StopThunderEffect(); StopBossCityThunderEffect(); } private void StopThunderEffect() { foreach (var city in regularCityArr) { city.StopThunderEffect(); } } public void PlayBossCityThunderEffect() { imgBossCityEffect.SetActive(true); } public void StopBossCityThunderEffect() { imgBossCityEffect.SetActive(false); } #endregion } }