From 01a6a9d95daa7d650f29b867baa437b8b1e38697 Mon Sep 17 00:00:00 2001
From: lcy <1459594991@qq.com>
Date: 星期二, 17 三月 2026 19:26:57 +0800
Subject: [PATCH] 262 幻境阁-客户端 支持配置关联皮肤解锁

---
 Main/System/PhantasmPavilion/PhantasmPavilionManager.Redpoint.cs |  117 +++++++++++++++++-----
 Main/System/PhantasmPavilion/PhantasmPavilionManager.cs          |   38 ++++++-
 Main/System/PhantasmPavilion/PhantasmPavilionUnlockButton.cs     |    9 +
 Main/System/HeroUI/HeroUIManager.Collect.cs                      |   85 +++++++++++++---
 4 files changed, 194 insertions(+), 55 deletions(-)

diff --git a/Main/System/HeroUI/HeroUIManager.Collect.cs b/Main/System/HeroUI/HeroUIManager.Collect.cs
index 862f42e..36417b6 100644
--- a/Main/System/HeroUI/HeroUIManager.Collect.cs
+++ b/Main/System/HeroUI/HeroUIManager.Collect.cs
@@ -30,25 +30,10 @@
             var newHeroData = netPack.HeroInfoList[i];
             int heroID = (int)newHeroData.HeroID;
 
-            // ---- 鏂板锛氬姣旀棫鏁版嵁锛屾娴嬬毊鑲ょ姸鎬佸彉鍖� ----
-            if (heroCollectInfoDic.TryGetValue(heroID, out var oldHeroData))
-            {
-                if (newHeroData.SkinList != null)
-                {
-                    foreach (var newSkin in newHeroData.SkinList)
-                    {
-                        // 鍦ㄦ棫鏁版嵁涓鎵惧搴旂殑鐨偆
-                        var oldSkin = oldHeroData.SkinList?.FirstOrDefault(s => s.SkinID == newSkin.SkinID);
+            // 1. 璋冪敤灏佽濂界殑鏂规硶锛氭娴嬪苟瑙﹀彂鏂扮毊鑲や簨浠�
+            CheckAndTriggerNewSkinEvents(heroID, newHeroData);
 
-                        // 濡傛灉鏃ф暟鎹腑娌℃湁杩欎釜鐨偆(棣栨鑾峰緱)锛屾垨鑰呯姸鎬佸彂鐢熶簡鍙樺寲
-                        if (oldSkin == null || oldSkin.State != newSkin.State)
-                        {
-                            OnHeroSkinStateChanged?.Invoke(heroID, (int)newSkin.SkinID, newSkin.State);
-                        }
-                    }
-                }
-            }
-
+            // 2. 鏇存柊瀛楀吀涓烘渶鏂扮殑缃戠粶鍖呮暟鎹�
             heroCollectInfoDic[heroID] = newHeroData;
         }
 
@@ -60,6 +45,70 @@
         OnHeroCollectEvent?.Invoke();
     }
 
+    public event Action<int, int> OnNewSkinAcquired;// 褰撶帺瀹惰幏寰楁柊鐨偆锛堟縺娲荤毊鑲わ級鏃惰Е鍙戠殑浜嬩欢 HeroID SkinID
+
+    /// <summary>
+    /// 妫�鏌ュ苟瑙﹀彂鑾峰緱鏂扮毊鑲ょ殑浜嬩欢
+    /// </summary>
+    private void CheckAndTriggerNewSkinEvents(int heroID, HB122_tagSCHeroInfo.tagSCHero newHeroData)
+    {
+        // 濡傛灉鏂版暟鎹腑娌℃湁鐨偆淇℃伅锛岀洿鎺ヨ繑鍥�
+        if (newHeroData?.SkinList == null || newHeroData?.SkinCnt <= 0) return;
+
+        // 灏濊瘯鑾峰彇鏃ф暟鎹�
+        bool isOldHeroExist = heroCollectInfoDic.TryGetValue(heroID, out var oldHeroData);
+
+        for (int j = 0; j < newHeroData.SkinCnt; j++)
+        {
+            var newSkin = newHeroData.SkinList[j];
+            
+            // 濡傛灉鏂扮毊鑲ゆ湭婵�娲伙紝鐩存帴璺宠繃褰撳墠寰幆锛屾鏌ヤ笅涓�涓毊鑲�
+            if (newSkin.State <= 0) continue;
+
+            bool isNewlyAcquired = false;
+
+            if (!isOldHeroExist)
+            {
+                // 鍦烘櫙A锛氳繖鏄竴涓叏鏂扮殑姝﹀皢锛屼笖鑷甫浜嗗凡婵�娲荤殑闈為粯璁ょ毊鑲�
+                isNewlyAcquired = true;
+            }
+            else
+            {
+                // 鍦烘櫙B锛氬凡鏈夌殑鑰佹灏嗭紝闇�瑕佸姣旀棫鏁版嵁鐪嬭繖涓毊鑲ゆ槸涓嶆槸鍒氬垰鎵嶈幏寰楃殑
+                bool foundOldSkin = false;
+
+                if (oldHeroData.SkinList != null)
+                {
+                    for (int k = 0; k < oldHeroData.SkinCnt; k++)
+                    {
+                        var oldSkin = oldHeroData.SkinList[k];
+                        if (oldSkin.SkinID == newSkin.SkinID)
+                        {
+                            foundOldSkin = true;
+                            // 濡傛灉鏃ф暟鎹腑璇ョ毊鑲ゆ湭婵�娲� (State == 0)锛岀幇鍦ㄦ縺娲讳簡锛岀畻浣滆幏寰楁柊鐨偆
+                            if (oldSkin.State == 0)
+                            {
+                                isNewlyAcquired = true;
+                            }
+                            break; 
+                        }
+                    }
+                }
+
+                // 濡傛灉鏃ф灏嗘暟鎹噷鍘嬫牴娌℃湁杩欎釜鐨偆鐨勬暟鎹紙鐜板湪鏄縺娲荤姸鎬侊級锛屼篃绠椾綔鑾峰緱鏂扮毊鑲�
+                if (!foundOldSkin)
+                {
+                    isNewlyAcquired = true;
+                }
+            }
+
+            // 濡傛灉鏈�缁堝垽瀹氫负鈥滃叏鏂拌幏寰椻�濈殑鐨偆锛屽垯瑙﹀彂浜嬩欢
+            if (isNewlyAcquired)
+            {
+                OnNewSkinAcquired?.Invoke(heroID, (int)newSkin.SkinID);
+            }
+        }
+    }
 
     // public int GetHeroCollectBookPer()
     // {
diff --git a/Main/System/PhantasmPavilion/PhantasmPavilionManager.Redpoint.cs b/Main/System/PhantasmPavilion/PhantasmPavilionManager.Redpoint.cs
index 923a788..ebd4974 100644
--- a/Main/System/PhantasmPavilion/PhantasmPavilionManager.Redpoint.cs
+++ b/Main/System/PhantasmPavilion/PhantasmPavilionManager.Redpoint.cs
@@ -73,13 +73,22 @@
                 continue;
             int unlockWay = GetUnlockWay(type, id);
             int unlockValue = GetUnlockValue(type, id);
-            if (unlockWay != 3)
+            if (unlockWay != 3 && unlockWay != 4)
                 continue;
-            bool hasNewHero = HasNewHero(type, unlockValue);
-            if (hasNewHero)
+            if (unlockWay == 3)
             {
-                tabRedPointDict[redType].state = RedPointState.Simple;
+                bool hasNewHero = HasNewHero(type, unlockValue);
+                if (hasNewHero)
+                {
+                    tabRedPointDict[redType].state = RedPointState.Simple;
+                }
             }
+            else if (unlockWay == 4)
+            {
+                if (HasNewSkin(type, unlockValue))
+                    tabRedPointDict[redType].state = RedPointState.Simple;
+            }
+
         }
     }
 
@@ -102,15 +111,21 @@
         }
 
         int unlockWay = GetUnlockWay(type, id);
-        if (unlockWay != 3)
+        if (unlockWay != 3 && unlockWay != 4)
             return;
 
         int unlockValue = GetUnlockValue(type, id);
-        bool hasNewHero = HasNewHero(type, unlockValue);
-        if (hasNewHero)
+        if (unlockWay == 3)
         {
-            imgRed.SetActive(true);
+            if (HasNewHero(type, unlockValue))
+                imgRed.SetActive(true);
         }
+        else if (unlockWay == 4)
+        {
+            if (HasNewSkin(type, unlockValue))
+                imgRed.SetActive(true);
+        }
+
     }
     readonly int funcId = 3;//鍐呮斂
     //鍐呮斂娌″紑涓嶅埛绾㈢偣
@@ -165,21 +180,42 @@
         }
     }
 
-    public List<int> newHeroIDModelList = new List<int>();
-    public List<int> newHeroIDFaceList = new List<int>();
-    public void AddNewHero(int heroID)
+    public List<int> newSkinIDModelList = new List<int>();
+    public List<int> newSkinIDFaceList = new List<int>();
+    string modelSkinKey { get { return StringUtility.Concat("PhantasmPavilion_Redponit_ModelSkin_", PlayerDatas.Instance.PlayerId.ToString()); } }
+    string faceSkinKey { get { return StringUtility.Concat("PhantasmPavilion_Redponit_FaceSkin_", PlayerDatas.Instance.PlayerId.ToString()); } }
+    public void AddNewSkin(int skinID)
     {
-        AddNewHero(newHeroIDModelList, heroID);
-        AddNewHero(newHeroIDFaceList, heroID);
+        AddNew(newSkinIDModelList, skinID);
+        AddNew(newSkinIDFaceList, skinID);
     }
-
-    void AddNewHero(List<int> list, int heroID)
+    // 鎶借薄娣诲姞閫昏緫
+    void AddNew(List<int> list, int id)
     {
-        if (list.Contains(heroID))
+        if (list.Contains(id))
             return;
-        list.Add(heroID);
+        list.Add(id);
         SaveLocal();
         UpdateRedPoint();
+    }
+
+    public bool HasNewSkin(PhantasmPavilionType type, int skinID)
+    {
+        switch (type)
+        {
+            case PhantasmPavilionType.Model: return newSkinIDModelList.Contains(skinID);
+            case PhantasmPavilionType.Face: return newSkinIDFaceList.Contains(skinID);
+            default: return false;
+        }
+    }
+
+    public List<int> newHeroIDModelList = new List<int>();
+    public List<int> newHeroIDFaceList = new List<int>();
+
+    public void AddNewHero(int heroID)
+    {
+        AddNew(newHeroIDModelList, heroID);
+        AddNew(newHeroIDFaceList, heroID);
     }
 
     public void RemoveAllNewHeroByTabType(PhantasmPavilionType type, int tabType = 0)
@@ -212,31 +248,29 @@
             return;
         int unlockWay = GetUnlockWay(type, id);
         int unlockValue = GetUnlockValue(type, id);
-        if (unlockWay != 3)
-            return;
+        if (unlockWay != 3 && unlockWay != 4) return;
 
         switch (type)
         {
             case PhantasmPavilionType.Model:
-                RemoveNewHero(newHeroIDModelList, unlockValue, isSave);
+                if (unlockWay == 3) RemoveNew(newHeroIDModelList, unlockValue, isSave);
+                else if (unlockWay == 4) RemoveNew(newSkinIDModelList, unlockValue, isSave); // 鐨偆
                 break;
             case PhantasmPavilionType.Face:
-                RemoveNewHero(newHeroIDFaceList, unlockValue, isSave);
+                if (unlockWay == 3) RemoveNew(newHeroIDFaceList, unlockValue, isSave);
+                else if (unlockWay == 4) RemoveNew(newSkinIDFaceList, unlockValue, isSave); // 鐨偆
                 break;
         }
     }
 
-    void RemoveNewHero(List<int> list, int heroID, bool isSave = true)
+    void RemoveNew(List<int> list, int id, bool isSave = true)
     {
-        if (!list.Contains(heroID))
-            return;
-        list.Remove(heroID);
-        if (isSave)
-        {
-            SaveLocal();
-        }
+        if (!list.Contains(id)) return;
+        list.Remove(id);
+        if (isSave) SaveLocal();
         UpdateRedPoint();
     }
+
 
     public bool HasNewHero(PhantasmPavilionType type, int heroID)
     {
@@ -258,11 +292,36 @@
     {
         LocalSave.SetIntArray(modelkey, newHeroIDModelList.ToArray());
         LocalSave.SetIntArray(facekey, newHeroIDFaceList.ToArray());
+        LocalSave.SetIntArray(modelSkinKey, newSkinIDModelList.ToArray());
+        LocalSave.SetIntArray(faceSkinKey, newSkinIDFaceList.ToArray());
     }
     public void LoadLocal()
     {
         LoadLocalModel();
         LoadLocalFace();
+        LoadLocalSkin();
+    }
+
+    void LoadLocalSkin()
+    {
+        if (LocalSave.HasKey(modelSkinKey))
+        {
+            int[] arr = LocalSave.GetIntArray(modelSkinKey);
+            newSkinIDModelList = arr.IsNullOrEmpty() ? new List<int>() : arr.ToList();
+        }
+        else
+        {
+            newSkinIDModelList = new List<int>();
+        }
+
+        if (LocalSave.HasKey(faceSkinKey))
+        {
+            int[] arr = LocalSave.GetIntArray(faceSkinKey);
+            newSkinIDFaceList = arr.IsNullOrEmpty() ? new List<int>() : arr.ToList();
+        }else
+        {
+            newSkinIDFaceList = new List<int>();
+        }
     }
 
     void LoadLocalModel()
diff --git a/Main/System/PhantasmPavilion/PhantasmPavilionManager.cs b/Main/System/PhantasmPavilion/PhantasmPavilionManager.cs
index c19d489..9a69423 100644
--- a/Main/System/PhantasmPavilion/PhantasmPavilionManager.cs
+++ b/Main/System/PhantasmPavilion/PhantasmPavilionManager.cs
@@ -53,6 +53,7 @@
         PackManager.Instance.RefreshItemEvent += OnRefreshItemEvent;
         GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
         FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
+        HeroUIManager.Instance.OnNewSkinAcquired += OnNewSkinAcquired;
         InitTable();
         InitTabRedPoint();
     }
@@ -65,6 +66,13 @@
         PackManager.Instance.RefreshItemEvent -= OnRefreshItemEvent;
         GlobalTimeEvent.Instance.secondEvent -= OnSecondEvent;
         FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
+        HeroUIManager.Instance.OnNewSkinAcquired -= OnNewSkinAcquired;
+    }
+
+    private void OnNewSkinAcquired(int arg1, int arg2)
+    {
+        AddNewSkin(arg2);
+        UpdateRedPoint();
     }
 
     private void OnFuncStateChangeEvent(int obj)
@@ -200,15 +208,21 @@
         int unlockValue = GetUnlockValue(type, id);
         int resourceType = GetResourceType(type, id);
         string resourceValue = GetResourceValue(type, id);
-        if (UnlockWay == 3 && resourceValue == "")
+        if ((UnlockWay == 3 || UnlockWay == 4) && resourceValue == "")
         {
-            int heroID = unlockValue;
-            if (!HeroConfig.HasKey(heroID))
-                return;
-            HeroConfig heroConfig = HeroConfig.Get(heroID);
-            int skinID = heroConfig.SkinIDList[0];
-            if (!HeroSkinConfig.HasKey(skinID))
-                return;
+            int skinID = 0;
+            if (UnlockWay == 3)
+            {
+                int heroID = unlockValue;
+                if (!HeroConfig.HasKey(heroID)) return;
+                skinID = HeroConfig.Get(heroID).SkinIDList[0];
+            }
+            else if (UnlockWay == 4)
+            {
+                skinID = unlockValue; // UnlockValue 鐩存帴灏辨槸 skinID
+            }
+
+            if (!HeroSkinConfig.HasKey(skinID)) return;
             HeroSkinConfig skinConfig = HeroSkinConfig.Get(skinID);
             var sprite = UILoader.LoadSprite("HeroHead", skinConfig.SquareIcon);
             if (sprite == null)
@@ -519,6 +533,9 @@
                 if (IsExpired(info, unlockWay))
                     return false;
                 return true;
+            case PhantasmPavilionUnlockWay.Skin:
+                bool hasSkin = HeroUIManager.Instance.IsHeroSkinActive(HeroConfig.GetHeroIDBySkinID(unlockValue), unlockValue);
+                return hasSkin;
             default:
                 return false;
         }
@@ -558,6 +575,10 @@
             case PhantasmPavilionUnlockWay.Hero:
                 int heroID = unlockValue;
                 return HeroManager.Instance.HasHero(heroID)
+                    ? PhantasmPavilionState.Activated
+                    : PhantasmPavilionState.Locked;
+            case PhantasmPavilionUnlockWay.Skin:
+                return HeroUIManager.Instance.IsHeroSkinActive(HeroConfig.GetHeroIDBySkinID(unlockValue), unlockValue)
                     ? PhantasmPavilionState.Activated
                     : PhantasmPavilionState.Locked;
             default:
@@ -870,6 +891,7 @@
     Activate = 1,               // 榛樿(鍒涜鑹插氨鍙互鐢ㄧ殑)
     Item,                       // 閬撳叿
     Hero,                       // 姝﹀皢
+    Skin,                   // 鐨偆
 }
 
 /// 骞诲闃佺墿鍝佺殑鐘舵��
diff --git a/Main/System/PhantasmPavilion/PhantasmPavilionUnlockButton.cs b/Main/System/PhantasmPavilion/PhantasmPavilionUnlockButton.cs
index 395aceb..78d9b25 100644
--- a/Main/System/PhantasmPavilion/PhantasmPavilionUnlockButton.cs
+++ b/Main/System/PhantasmPavilion/PhantasmPavilionUnlockButton.cs
@@ -40,6 +40,15 @@
                     return;
                 }
             }
+            else if (unlockWay == 4) // 鏂板锛氬鏋滄槸鐨偆瑙i攣
+            {
+                bool hasSkin = HeroUIManager.Instance.IsHeroSkinActive(HeroConfig.GetHeroIDBySkinID(unlockValue), unlockValue);
+                if (!hasSkin)
+                {
+                    SysNotifyMgr.Instance.ShowTip("UnLockFail1");
+                    return;
+                }
+            }
             manager.SendOPPack(type, PhantasmPavilionOperation.Activate, (uint)id);
             SysNotifyMgr.Instance.ShowTip("UnLockSuccess");
         });

--
Gitblit v1.8.0