From 772fb9532ff627222023e9550e5ec47f08dc4049 Mon Sep 17 00:00:00 2001
From: lcy <1459594991@qq.com>
Date: 星期二, 23 六月 2026 17:15:15 +0800
Subject: [PATCH] 662 武将试炼 修复等级达到或官职达到没视为新增的问题

---
 Main/System/HeroTrial/HeroTrialManager.cs |  303 +++++++++++++++++++++++---------------------------
 1 files changed, 141 insertions(+), 162 deletions(-)

diff --git a/Main/System/HeroTrial/HeroTrialManager.cs b/Main/System/HeroTrial/HeroTrialManager.cs
index d45a252..adf7e59 100644
--- a/Main/System/HeroTrial/HeroTrialManager.cs
+++ b/Main/System/HeroTrial/HeroTrialManager.cs
@@ -12,17 +12,23 @@
     int challengeRecordDay;
     // 褰撳ぉ鍙戣捣杩囨寫鎴樼殑姝﹀皢涓嶅啀鏄剧ず绾㈢偣锛岃儨璐熸棤鍏炽��
     HashSet<int> challengedHeroIDsToday = new HashSet<int>();
-    // 褰撳ぉ鏂板紑鏀剧殑鍙彁绀烘灏嗭紝浼樺厛浜庢櫘閫氬�欓�夋帓闃熼『寤躲��
-    List<int> pendingNewRedHeroIDsToday = new List<int>();
+    // 褰撳ぉ鏂板紑鏀捐繃鐨勬灏嗗壇鏈�傝繖閲屼繚瀛樷�滃彂鐢熻繃鏂板紑鏀锯�濈殑浜嬪疄锛屽緟鏄剧ず闃熷垪姣忔鍒锋柊鏃朵粠瀹冩淳鐢燂紝閬垮厤鎸佷箙鍖栧綋鍓嶇孩鐐�/闃熷垪杩涘害銆�
+    List<int> newOpenedHeroIDsToday = new List<int>();
+    // 鍘嗗彶涓婂鎴风宸茬粡瑙佽繃鐨勫彲鎸戞垬姝﹀皢鍓湰锛岀敤浜庤瘑鍒綋澶╁洜绛夌骇/瀹樿亴杈炬垚鑰屾柊瑙i攣鐨勫壇鏈��
+    HashSet<int> seenUnlockedHeroIDs = new HashSet<int>();
     int currentRedHeroID;
     bool isChallengeRecordLoaded;
+    bool needSeedSeenUnlockedHeroIDs;
+    bool isRefreshingByPlayerProgress;
+    int lastObservedPlayerLV = -1;
+    int lastObservedRealmLevel = -1;
 
     string challengeRecordDayKey { get { return StringUtility.Concat("HeroTrial_ChallengeRecordDay_", PlayerDatas.Instance.PlayerId.ToString()); } }
     string lastChallengeHeroIDTodayKey { get { return StringUtility.Concat("HeroTrial_LastChallengeHeroIDToday_", PlayerDatas.Instance.PlayerId.ToString()); } }
     string challengedHeroIDsTodayKey { get { return StringUtility.Concat("HeroTrial_ChallengedHeroIDsToday_", PlayerDatas.Instance.PlayerId.ToString()); } }
     string normalRedConsumedTodayKey { get { return StringUtility.Concat("HeroTrial_NormalRedConsumedToday_", PlayerDatas.Instance.PlayerId.ToString()); } }
-    string pendingNewRedHeroIDsTodayKey { get { return StringUtility.Concat("HeroTrial_PendingNewRedHeroIDsToday_", PlayerDatas.Instance.PlayerId.ToString()); } }
-    string currentRedHeroIDKey { get { return StringUtility.Concat("HeroTrial_CurrentRedHeroID_", PlayerDatas.Instance.PlayerId.ToString()); } }
+    string newOpenedHeroIDsTodayKey { get { return StringUtility.Concat("HeroTrial_NewOpenedHeroIDsToday_", PlayerDatas.Instance.PlayerId.ToString()); } }
+    string seenUnlockedHeroIDsKey { get { return StringUtility.Concat("HeroTrial_SeenUnlockedHeroIDs_", PlayerDatas.Instance.PlayerId.ToString()); } }
 
     /// <summary>鏁版嵁鏇存柊浜嬩欢锛孶I璁㈤槄鍒锋柊</summary>
     public event Action OnUpdateHeroTrialInfoEvent;
@@ -72,7 +78,15 @@
         if (type != PlayerDataType.LV && type != PlayerDataType.RealmLevel)
             return;
 
-        RefreshHeroTrialState();
+        isRefreshingByPlayerProgress = true;
+        try
+        {
+            RefreshHeroTrialState();
+        }
+        finally
+        {
+            isRefreshingByPlayerProgress = false;
+        }
     }
 
     void OnServerOpenDayRefresh()
@@ -110,6 +124,7 @@
         EnsureTodayChallengeRecord();
         RefreshCurrentRedHeroID();
         UpdateRedPoint();
+        RecordObservedPlayerProgress();
         OnUpdateHeroTrialInfoEvent?.Invoke();
     }
 
@@ -129,36 +144,43 @@
         }
 
         // 绾㈢偣瑙勫垯锛�
-        // 1. 褰撳ぉ鏂板紑鏀剧殑姝﹀皢浼樺厛鏄剧ず锛屽苟鎸夐厤缃『搴忛『寤躲��
-        // 2. 褰撳ぉ鏂板紑鏀鹃槦鍒楄鎸戞垬瀹屽悗锛屽綋澶╀笉鍐嶅洖娴佸埌鏃ф灏嗗壇鏈��
-        // 3. 浠婂ぉ娌℃湁鏂板紑鏀炬彁绀洪摼璺笖鏅�氱孩鐐规湭琚寫鎴樻秷璐规椂锛屾樉绀烘墍鏈夊凡瑙i攣涓旀湁鍙寫鎴樺叧鍗$殑姝﹀皢閲岋紝褰撳墠鍙寫鎴樺叧鍗℃垬鍔涙渶浣庣殑閭d釜銆�
+        // 1. 褰撳ぉ鏂板紑鏀炬灏嗕紭鍏堬紝鎸夐厤缃『搴忛�愪釜鎻愮ず锛涙柊寮�鏀炬潵婧愬寘鍚紑鏈嶅ぉ銆佺瓑绾с�佸畼鑱屻��
+        // 2. 鍙繚瀛樷�滀粖澶╁嚭鐜拌繃鍝簺鏂板紑鏀炬灏嗏�濓紝褰撳墠鏄剧ず鐩爣姣忔鍒锋柊瀹炴椂娲剧敓锛岄伩鍏嶆湰鍦板瓨鍌ㄩ槦鍒楄繘搴︺��
+        // 3. 浠婂ぉ鍑虹幇杩囨柊寮�鏀炬灏嗗悗锛岄槦鍒楄�楀敖涔熶笉鍥炴祦鏃ф灏嗭紱瀹屽叏娌℃湁鏂板紑鏀炬椂锛屾棫姝﹀皢涓�澶╁彧鎻愮ず涓�娆℃渶浣庢垬鍔涚洰鏍囥��
+        List<int> heroIDList = GetHeroTrialHeroIDList();
+        bool onlyProgressUnlocksCanBecomeNew = needSeedSeenUnlockedHeroIDs && isRefreshingByPlayerProgress;
+        if (needSeedSeenUnlockedHeroIDs && !onlyProgressUnlocksCanBecomeNew)
+        {
+            SeedSeenUnlockedHeroIDs(heroIDList);
+            needSeedSeenUnlockedHeroIDs = false;
+            isDirty = true;
+        }
+
+        if (DetectNewOpenedHeroIDsToday(heroIDList, onlyProgressUnlocksCanBecomeNew))
+            isDirty = true;
+
+        if (onlyProgressUnlocksCanBecomeNew)
+        {
+            needSeedSeenUnlockedHeroIDs = false;
+            isDirty = true;
+        }
+
         if (currentRedHeroID != 0 && !CanShowHeroItemRed(currentRedHeroID))
         {
             currentRedHeroID = 0;
             isDirty = true;
         }
 
-        List<int> heroIDList = GetHeroTrialHeroIDList();
-        List<int> candidateHeroIDs = BuildCandidateHeroIDs(heroIDList);
-        List<int> todayOpenHeroIDs = BuildTodayOpenHeroIDs(candidateHeroIDs);
-        RemoveHeroIDs(candidateHeroIDs, todayOpenHeroIDs);
-
-        if (NormalizePendingNewRedHeroIDs(heroIDList))
-            isDirty = true;
-
-        if (AppendTodayOpenPendingCandidates(todayOpenHeroIDs))
-            isDirty = true;
-
-        if (NormalizePendingNewRedHeroIDs(heroIDList))
-            isDirty = true;
-
-        if (PromoteTodayOpenPendingRed(todayOpenHeroIDs))
+        int nextNewOpenedHeroID = GetNextNewOpenedRedHeroID(heroIDList);
+        if (nextNewOpenedHeroID != 0)
         {
-            isDirty = true;
+            if (currentRedHeroID != nextNewOpenedHeroID)
+            {
+                currentRedHeroID = nextNewOpenedHeroID;
+                isDirty = true;
+            }
         }
-        else if (HasChallengedTodayOpenHeroTrialToday() &&
-            pendingNewRedHeroIDsToday.Count == 0 &&
-            (currentRedHeroID == 0 || !IsHeroTrialHeroOpenToday(currentRedHeroID)))
+        else if (newOpenedHeroIDsToday.Count > 0)
         {
             if (currentRedHeroID != 0)
             {
@@ -166,7 +188,7 @@
                 isDirty = true;
             }
         }
-        else if (!normalRedConsumedToday && (currentRedHeroID == 0 || !IsHeroTrialHeroOpenToday(currentRedHeroID)))
+        else if (!normalRedConsumedToday)
         {
             int bestHeroID = GetLowestCanChallengeHeroID(heroIDList);
             if (currentRedHeroID != bestHeroID)
@@ -180,43 +202,86 @@
             SaveTodayChallengeRecord();
     }
 
-    List<int> BuildCandidateHeroIDs(List<int> sortedHeroIDList)
+    bool DetectNewOpenedHeroIDsToday(List<int> sortedHeroIDList, bool onlyProgressUnlocksCanBecomeNew)
     {
-        List<int> candidateHeroIDs = new List<int>();
+        bool isDirty = false;
         for (int i = 0; i < sortedHeroIDList.Count; i++)
         {
             int heroID = sortedHeroIDList[i];
-            if (!CanShowHeroItemRed(heroID))
+            if (!IsVisibleUnlockedHeroTrial(heroID))
                 continue;
-            candidateHeroIDs.Add(heroID);
+
+            bool unlockedByPlayerProgressNow = isRefreshingByPlayerProgress && IsHeroTrialHeroUnlockedByPlayerProgressNow(heroID);
+            // 棣栨瑙佸埌涓�涓凡瑙i攣涓旀湁鍙寫鎴樺叧鍗$殑姝﹀皢锛岃鏄庡畠鍒氱敱绛夌骇/瀹樿亴鏉′欢杩涘叆鍙彁绀鸿寖鍥淬��
+            if (seenUnlockedHeroIDs.Add(heroID))
+            {
+                if (!onlyProgressUnlocksCanBecomeNew || unlockedByPlayerProgressNow)
+                    AppendNewOpenedHeroIDToday(heroID);
+                isDirty = true;
+            }
+            else if (unlockedByPlayerProgressNow && AppendNewOpenedHeroIDToday(heroID))
+            {
+                // 鍏煎鏃ф湰鍦拌褰曪細鑻ュ巻鍙插凡瑙侀泦鍚堟浘璇璇ユ灏嗭紝鏈鏄庣‘璺ㄨ繃绛夌骇/瀹樿亴闂ㄦ鏃朵粛鎸夋柊寮�鏀惧鐞嗐��
+                isDirty = true;
+            }
+
+            // 寮�鏈嶅ぉ鏂板紑鏀句笉渚濊禆鍘嗗彶宸茶闆嗗悎锛涘綋澶╅娆″埛鏂板氨搴旇繘鍏ユ柊寮�鏀句紭鍏堥槦鍒椼��
+            if (IsHeroTrialHeroOpenByServerDayToday(heroID) && AppendNewOpenedHeroIDToday(heroID))
+                isDirty = true;
         }
-        return candidateHeroIDs;
+
+        return isDirty;
     }
 
-    List<int> BuildTodayOpenHeroIDs(List<int> candidateHeroIDs)
+    bool IsHeroTrialHeroUnlockedByPlayerProgressNow(int heroID)
     {
-        List<int> todayOpenHeroIDs = new List<int>();
-        for (int i = 0; i < candidateHeroIDs.Count; i++)
-        {
-            int heroID = candidateHeroIDs[i];
-            if (IsHeroTrialHeroOpenToday(heroID))
-                todayOpenHeroIDs.Add(heroID);
-        }
-        return todayOpenHeroIDs;
+        if (!HeroTrialConfig.TryGetFirstLevelConfig(heroID, out var config))
+            return false;
+
+        int currentLV = PlayerDatas.Instance.baseData.LV;
+        int currentRealmLevel = PlayerDatas.Instance.baseData.realmLevel;
+        bool levelJustReached = config.LVLimit > 0 && currentLV >= config.LVLimit &&
+            ((lastObservedPlayerLV >= 0 && lastObservedPlayerLV < config.LVLimit) ||
+            (lastObservedPlayerLV < 0 && currentLV == config.LVLimit));
+        bool realmJustReached = config.RealmLimit > 0 && currentRealmLevel >= config.RealmLimit &&
+            ((lastObservedRealmLevel >= 0 && lastObservedRealmLevel < config.RealmLimit) ||
+            (lastObservedRealmLevel < 0 && currentRealmLevel == config.RealmLimit));
+
+        return levelJustReached || realmJustReached;
     }
 
-    bool HasChallengedTodayOpenHeroTrialToday()
+    void RecordObservedPlayerProgress()
     {
-        foreach (int heroID in challengedHeroIDsToday)
-        {
-            if (IsHeroTrialHeroOpenToday(heroID))
-                return true;
-        }
-
-        return false;
+        lastObservedPlayerLV = PlayerDatas.Instance.baseData.LV;
+        lastObservedRealmLevel = PlayerDatas.Instance.baseData.realmLevel;
     }
 
-    bool IsHeroTrialHeroOpenToday(int heroID)
+    void SeedSeenUnlockedHeroIDs(List<int> sortedHeroIDList)
+    {
+        // 娌℃湁鍘嗗彶宸茶璁板綍鏃讹紝鍏堟妸褰撳墠鍙鍓湰浣滀负鏃х姸鎬佽浣忥紝閬垮厤鐗堟湰鍗囩骇鍚庢妸鎵�鏈夋棫鍓湰璇垽鎴愬綋澶╂柊寮�鏀俱��
+        for (int i = 0; i < sortedHeroIDList.Count; i++)
+        {
+            int heroID = sortedHeroIDList[i];
+            if (IsVisibleUnlockedHeroTrial(heroID))
+                seenUnlockedHeroIDs.Add(heroID);
+        }
+    }
+
+    bool IsVisibleUnlockedHeroTrial(int heroID)
+    {
+        return IsHeroTrialHeroUnlocked(heroID) && HasChallengeableLevel(heroID);
+    }
+
+    bool AppendNewOpenedHeroIDToday(int heroID)
+    {
+        if (heroID == 0 || newOpenedHeroIDsToday.Contains(heroID))
+            return false;
+
+        newOpenedHeroIDsToday.Add(heroID);
+        return true;
+    }
+
+    bool IsHeroTrialHeroOpenByServerDayToday(int heroID)
     {
         HeroConfig heroConfig = HeroConfig.Get(heroID);
         return heroConfig != null &&
@@ -224,87 +289,16 @@
             heroConfig.OpenCollectionDay == TimeUtility.OpenDay + 1;
     }
 
-    void RemoveHeroIDs(List<int> heroIDs, List<int> removeHeroIDs)
+    int GetNextNewOpenedRedHeroID(List<int> sortedHeroIDList)
     {
-        if (removeHeroIDs.IsNullOrEmpty())
-            return;
-
-        for (int i = heroIDs.Count - 1; i >= 0; i--)
+        for (int i = 0; i < sortedHeroIDList.Count; i++)
         {
-            if (removeHeroIDs.Contains(heroIDs[i]))
-                heroIDs.RemoveAt(i);
-        }
-    }
-
-    bool AppendTodayOpenPendingCandidates(List<int> candidateHeroIDs)
-    {
-        bool isDirty = false;
-        for (int i = 0; i < candidateHeroIDs.Count; i++)
-        {
-            int heroID = candidateHeroIDs[i];
-            if (AppendPendingCandidate(heroID))
-                isDirty = true;
+            int heroID = sortedHeroIDList[i];
+            if (newOpenedHeroIDsToday.Contains(heroID) && CanShowHeroItemRed(heroID))
+                return heroID;
         }
 
-        return isDirty;
-    }
-
-    bool AppendPendingCandidate(int heroID)
-    {
-        if (heroID == currentRedHeroID || pendingNewRedHeroIDsToday.Contains(heroID))
-            return false;
-
-        pendingNewRedHeroIDsToday.Add(heroID);
-        return true;
-    }
-
-    bool NormalizePendingNewRedHeroIDs(List<int> sortedHeroIDList)
-    {
-        // 闃熷垪鍙繚鐣欎粛鍙彁绀虹殑褰撳ぉ鏂板紑鏀炬灏嗭紝骞舵寜閰嶇疆椤哄簭褰掍竴锛屼繚璇� E -> F -> G 椤哄欢銆�
-        List<int> normalizedHeroIDs = new List<int>();
-        for (int i = 0; i < pendingNewRedHeroIDsToday.Count; i++)
-        {
-            int heroID = pendingNewRedHeroIDsToday[i];
-            if (heroID == currentRedHeroID)
-                continue;
-
-            if (!IsHeroTrialHeroOpenToday(heroID))
-                continue;
-
-            if (!CanShowHeroItemRed(heroID))
-                continue;
-
-            if (!normalizedHeroIDs.Contains(heroID))
-                normalizedHeroIDs.Add(heroID);
-        }
-
-        normalizedHeroIDs.Sort((a, b) => GetHeroSortIndex(sortedHeroIDList, a).CompareTo(GetHeroSortIndex(sortedHeroIDList, b)));
-        if (IsSameHeroIDList(pendingNewRedHeroIDsToday, normalizedHeroIDs))
-            return false;
-
-        pendingNewRedHeroIDsToday.Clear();
-        pendingNewRedHeroIDsToday.AddRange(normalizedHeroIDs);
-        return true;
-    }
-
-    int GetHeroSortIndex(List<int> sortedHeroIDList, int heroID)
-    {
-        int index = sortedHeroIDList.IndexOf(heroID);
-        return index >= 0 ? index : int.MaxValue;
-    }
-
-    bool IsSameHeroIDList(List<int> listA, List<int> listB)
-    {
-        if (listA.Count != listB.Count)
-            return false;
-
-        for (int i = 0; i < listA.Count; i++)
-        {
-            if (listA[i] != listB[i])
-                return false;
-        }
-
-        return true;
+        return 0;
     }
 
     int GetLowestCanChallengeHeroID(List<int> heroIDList)
@@ -391,29 +385,6 @@
         }
 
         return config != null;
-    }
-
-    bool PromoteTodayOpenPendingRed(List<int> todayOpenHeroIDs)
-    {
-        if (todayOpenHeroIDs.IsNullOrEmpty())
-            return false;
-
-        if (currentRedHeroID != 0 && todayOpenHeroIDs.Contains(currentRedHeroID))
-            return false;
-
-        for (int i = 0; i < pendingNewRedHeroIDsToday.Count; i++)
-        {
-            int heroID = pendingNewRedHeroIDsToday[i];
-            if (!todayOpenHeroIDs.Contains(heroID))
-                continue;
-
-            // 浠婂ぉ鏂板紑鏀剧殑姝﹀皢浼樺厛灞曠ず锛涢槦鍒楄�楀敖鍚庡綋澶╀笉鍐嶅洖娴佸埌鏃ф灏嗗壇鏈��
-            currentRedHeroID = heroID;
-            pendingNewRedHeroIDsToday.RemoveAt(i);
-            return true;
-        }
-
-        return false;
     }
 
     /// <summary>
@@ -589,10 +560,10 @@
             lastChallengeHeroIDToday = config.HeroID;
             SaveTodayChallengeRecord();
         }
-        bool isDirty = pendingNewRedHeroIDsToday.Remove(config.HeroID);
+        bool isDirty = false;
         if (currentRedHeroID == config.HeroID)
         {
-            if (!IsHeroTrialHeroOpenToday(config.HeroID))
+            if (!newOpenedHeroIDsToday.Contains(config.HeroID))
                 normalRedConsumedToday = true;
 
             currentRedHeroID = 0;
@@ -651,9 +622,9 @@
 
         challengeRecordDay = today;
         challengedHeroIDsToday.Clear();
+        newOpenedHeroIDsToday.Clear();
         lastChallengeHeroIDToday = 0;
         normalRedConsumedToday = false;
-        pendingNewRedHeroIDsToday.Clear();
         currentRedHeroID = 0;
         SaveTodayChallengeRecord();
     }
@@ -662,24 +633,30 @@
     {
         challengeRecordDay = 0;
         challengedHeroIDsToday.Clear();
+        newOpenedHeroIDsToday.Clear();
+        seenUnlockedHeroIDs.Clear();
         lastChallengeHeroIDToday = 0;
         normalRedConsumedToday = false;
-        pendingNewRedHeroIDsToday.Clear();
         currentRedHeroID = 0;
         isChallengeRecordLoaded = false;
+        needSeedSeenUnlockedHeroIDs = false;
+        isRefreshingByPlayerProgress = false;
+        lastObservedPlayerLV = -1;
+        lastObservedRealmLevel = -1;
     }
 
     void LoadTodayChallengeRecord()
     {
         isChallengeRecordLoaded = true;
         challengeRecordDay = LocalSave.GetInt(challengeRecordDayKey);
+        needSeedSeenUnlockedHeroIDs = !LoadHeroIDSet(seenUnlockedHeroIDsKey, seenUnlockedHeroIDs);
         if (challengeRecordDay != GetTodayID())
         {
             challengeRecordDay = GetTodayID();
             challengedHeroIDsToday.Clear();
+            newOpenedHeroIDsToday.Clear();
             lastChallengeHeroIDToday = 0;
             normalRedConsumedToday = false;
-            pendingNewRedHeroIDsToday.Clear();
             currentRedHeroID = 0;
             SaveTodayChallengeRecord();
             return;
@@ -688,8 +665,8 @@
         LoadHeroIDSet(challengedHeroIDsTodayKey, challengedHeroIDsToday);
         lastChallengeHeroIDToday = LocalSave.GetInt(lastChallengeHeroIDTodayKey);
         normalRedConsumedToday = LocalSave.GetInt(normalRedConsumedTodayKey) != 0;
-        LoadHeroIDList(pendingNewRedHeroIDsTodayKey, pendingNewRedHeroIDsToday);
-        currentRedHeroID = LocalSave.GetInt(currentRedHeroIDKey);
+        LoadHeroIDList(newOpenedHeroIDsTodayKey, newOpenedHeroIDsToday);
+        currentRedHeroID = 0;
     }
 
     void SaveTodayChallengeRecord()
@@ -698,22 +675,24 @@
         LocalSave.SetIntArray(challengedHeroIDsTodayKey, ToArray(challengedHeroIDsToday));
         LocalSave.SetInt(lastChallengeHeroIDTodayKey, lastChallengeHeroIDToday);
         LocalSave.SetInt(normalRedConsumedTodayKey, normalRedConsumedToday ? 1 : 0);
-        LocalSave.SetIntArray(pendingNewRedHeroIDsTodayKey, pendingNewRedHeroIDsToday.ToArray());
-        LocalSave.SetInt(currentRedHeroIDKey, currentRedHeroID);
+        LocalSave.SetIntArray(newOpenedHeroIDsTodayKey, newOpenedHeroIDsToday.ToArray());
+        LocalSave.SetIntArray(seenUnlockedHeroIDsKey, ToArray(seenUnlockedHeroIDs));
     }
 
-    void LoadHeroIDSet(string key, HashSet<int> heroIDSet)
+    bool LoadHeroIDSet(string key, HashSet<int> heroIDSet)
     {
         heroIDSet.Clear();
         int[] heroIDs = LocalSave.GetIntArray(key);
         if (heroIDs == null)
-            return;
+            return false;
 
         for (int i = 0; i < heroIDs.Length; i++)
         {
             if (heroIDs[i] != 0)
                 heroIDSet.Add(heroIDs[i]);
         }
+
+        return true;
     }
 
     void LoadHeroIDList(string key, List<int> heroIDList)

--
Gitblit v1.8.0