From ad3ac1661daaf4b445914f87009d3d88c990f040 Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期二, 28 四月 2026 11:45:19 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into h5version

---
 Main/Core/GameEngine/Player/PlayerBaseData.cs                                                                 |    2 
 Main/Config/Configs/ActTotDayRechargeTempConfig.cs.meta                                                       |   11 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm.meta                                               |    8 
 Main/System/TotDayRecharge/TotDayRechargeManager.cs.meta                                                      |   11 
 Main/System/HeroDebut/HeroDebutZhanLingCell.cs.meta                                                           |   11 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs.meta                                                    |   11 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs                                                         |   35 
 Main/System/OtherPlayerDetail/OtherPlayerDetailWin.cs                                                         |    9 
 Main/System/BattlePass/BattlePassManager.cs                                                                   |   25 
 Main/System/OSActivity/OSGalaTabCell.cs                                                                       |   32 
 Main/Core/GameEngine/Launch/RequestPermissionStart.cs                                                         |    1 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs                      |   23 
 Main/System/Battle/UIComp/BattleHeroInfoBar.cs                                                                |   73 
 Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs.meta                           |   11 
 Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm.meta                                                       |    8 
 Main/System/Hero/HeroInfo.InheritPer.cs                                                                       |   40 
 Main/System/OSActivity/OSActivityManager.cs                                                                   |    2 
 Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs                                                        |   87 
 Main/System/TotalRecharge/TotalRechargeCell.cs.meta                                                           |   11 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs.meta       |   11 
 Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs                                                      |   59 
 Main/System/Battle/BattleObject/HeroBattleObject.cs                                                           |   13 
 Main/Config/Configs/ActTotalRechargeTempConfig.cs                                                             |   50 
 Main/System/HeroUI/HeroLVBreakCell.cs                                                                         |    7 
 Main/System/OpenServerActivity/OperationTimeHepler.cs                                                         |   72 
 Main/System/TotalRecharge.meta                                                                                |    8 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs                      |   12 
 Main/System/OfficialRank/OfficialRankManager.cs                                                               |    9 
 Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs                                                       |   35 
 Main/System/HeroDebut/HeroDebutZhanLingWin.cs                                                                 |  151 
 Main/Core/GameEngine/Launch/CheckAssetValidTask.cs                                                            |    1 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta |   11 
 Main/System/BillboardRank/PlayerTop3Cell.cs                                                                   |    2 
 Main/Config/Configs/ActTotalRechargeConfig.cs.meta                                                            |   11 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs.meta                                                     |   11 
 Main/System/Battle/Skill/SkillBase.SubSkill.cs                                                                |   86 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs.meta                 |   11 
 Main/SDK/SDKUtils.cs                                                                                          |    8 
 Main/System/HeroUI/HeroTrainWin.cs                                                                            |    9 
 Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs                                                           |    1 
 Main/System/Horse/HorseSuccessWin.cs                                                                          |   70 
 Main/System/HeroUI/HeroCollectionCardCell.cs                                                                  |    1 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs.meta                 |   11 
 Main/System/HeroDebut/HeroDebutManager.cs                                                                     |  409 ++
 Main/System/Battle/Skill/SkillBase.Death.cs                                                                   |  325 +
 Main/Config/Configs/ActTotalRechargeConfig.cs                                                                 |   47 
 Main/Config/Configs/ActTotalRechargeTempConfig.cs.meta                                                        |   11 
 Main/Core/GameEngine/Launch/LaunchInHot.cs                                                                    |    2 
 Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs.meta                                                  |   11 
 Main/System/OSActivity/OSGalaGiftCell.cs                                                                      |    2 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs                 |   21 
 Main/System/CrossServer/CrossServerBaseManager.cs.meta                                                        |   11 
 Main/System/Horse/GetHorseWin.cs                                                                              |   38 
 Main/System/HeroReturn/HeroReturnManager.cs                                                                   |  405 ++
 Main/System/WarlordPavilion/WarlordPavilionManager.cs                                                         |   25 
 Main/System/Horse/HorseItem.cs.meta                                                                           |   11 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs                                                        |   35 
 Main/Core/GameEngine/Player/PlayerDatas.cs                                                                    |    3 
 Main/Config/Configs/ActTotDayRechargeConfig.cs                                                                |   44 
 Main/System/BoneField/AdsManager.cs                                                                           |   37 
 Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs                                   |   20 
 Main/System/Battle/Skill/SkillBase.Finish.cs                                                                  |  480 ++
 Main/System/Horse/GetHorseWin.cs.meta                                                                         |   11 
 Main/System/Horse/HorseSkinWin.cs                                                                             |   26 
 Main/System/OtherPlayerDetail/OtherHeroDetailWin.cs                                                           |   16 
 Main/System/Battle/Skill/SkillBase.Buff.cs.meta                                                               |   11 
 Main/Config/Configs/ActHeroAppearConfig.cs                                                                    |   29 
 Main/System/Settlement/BattleSettlementManager.cs                                                             |    6 
 Main/System/Battle/BattleObject/BattleObject.cs                                                               |    4 
 Main/Config/PartialConfigs/PlayerPropertyConfig.cs                                                            |   24 
 Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs.meta                                                 |   11 
 Main/Config/Configs/HeroConfig.cs                                                                             |   11 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs                                                         |   91 
 Main/System/Main/FightPowerManager.cs                                                                         |   15 
 Main/System/HeroUI/HeroCollectionWin.cs                                                                       |   14 
 Main/System/OSActivity/OperationTotDayRechargeInfo.cs.meta                                                    |   11 
 Main/Config/Configs/HorseIDConfig.cs.meta                                                                     |   11 
 Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs                                    |   19 
 Main/System/Horse/HorseWin.cs                                                                                 |  168 
 Main/Core/GameEngine/Launch/SDKInitedTask.cs                                                                  |    1 
 Main/Core/GameEngine/Launch/AssetBundleInitTask.cs                                                            |    3 
 Main/System/Chat/ChatManager.cs                                                                               |   32 
 Main/System/Guild/GuildEmblemSelectCell.cs                                                                    |    6 
 Main/System/CrossServer/CrossServerBaseManager.cs                                                             |   62 
 Main/System/HeroDebut/HeroDebutZhanLingWin.cs.meta                                                            |   11 
 Main/System/HeroUI/HeroGiftEatWin.cs                                                                          |   15 
 Main/System/Guild/GuildHawkerWin.cs                                                                           |   14 
 Main/System/HeroUI/HeroCardCell.cs                                                                            |   20 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs                                                          |   87 
 Main/System/Horse/HorseItem.cs                                                                                |   50 
 Main/System/CrossServer.meta                                                                                  |    8 
 Main/System/TotalRecharge/TotalRechargeManager.cs.meta                                                        |   11 
 Main/Utility/OperationLogCollect.cs                                                                           |   60 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs.meta            |   11 
 Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs.meta                              |   11 
 Main/System/Battle/Skill/SkillBase.Cast.cs.meta                                                               |   11 
 Main/Config/Configs/ActTotDayRechargeTempConfig.cs                                                            |   47 
 Main/System/Battle/BattleDebug.cs                                                                             |   42 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs      |   14 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs.meta  |   11 
 Main/System/Main/AutoFightModel.cs                                                                            |   32 
 Main/System/Guild/GuildBossManager.cs                                                                         |    4 
 Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs.meta                                                  |   11 
 Main/System/HeroDebut/HeroDebutCallWin.cs                                                                     |   29 
 Main/System/HeroUI/HeroBestWin.cs                                                                             |    9 
 Main/System/Qunying/QYWin.cs                                                                                  |   36 
 Main/System/HeroReturn/HeroReturnZhanLingCell.cs                                                              |  121 
 Main/System/Horse/HorseRankUPWin.cs                                                                           |   69 
 Main/System/AssetVersion/InGameDownLoad.cs                                                                    |   11 
 Main/System/TotDayRecharge/TotDayRechargeCell.cs                                                              |   74 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs                          |   14 
 Main/System/HeroUI/HeroUIManager.Talent.cs                                                                    |   10 
 Main/System/Battle/Skill/SkillBase.Buff.cs                                                                    |   65 
 Main/System/Battle/Motion/MotionBase.cs                                                                       |  147 
 Main/Component/UI/Common/FuncOpen.cs                                                                          |   42 
 Main/System/Qunying/QunyingManager.cs                                                                         |   14 
 Main/System/Attribute/AttributeManager.cs                                                                     |   26 
 Main/System/HeroReturn/HeroReturnStarUpWin.cs                                                                 |   17 
 Main/System/HeroReturn/HeroReturnCallWin.cs                                                                   |   29 
 Main/Config/Configs/HorseClassConfig.cs                                                                       |   32 
 Main/System/TotDayRecharge/TotDayRechargeCell.cs.meta                                                         |   11 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta           |   11 
 Main/System/TotalRecharge/TotalRechargeManager.cs                                                             |  252 +
 Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs                                                      |   35 
 Main/System/HeroReturn/HeroReturnZhanLingWin.cs.meta                                                          |   11 
 Main/Utility/EnumHelper.cs                                                                                    |    4 
 Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs                                                       |   91 
 Main/System/TotDayRecharge/TotDayRechargeWin.cs.meta                                                          |   11 
 Main/System/Battle/Skill/SkillBase.SubSkill.cs.meta                                                           |   11 
 Main/System/HeroUI/HeroGiftEatSuccessWin.cs                                                                   |   19 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs.meta                     |   11 
 Main/System/TotDayRecharge.meta                                                                               |    8 
 Main/System/OSActivity/OperationTotalRechargeInfo.cs                                                          |   21 
 Main/System/HeroReturn/HeroReturnWin.cs                                                                       |    4 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs.meta        |   11 
 Main/System/Battle/Skill/SkillBase.cs                                                                         | 1588 --------
 Main/Config/Configs/HorseSkinConfig.cs                                                                        |   11 
 Main/System/OSActivity/OSGalaTabCell.cs.meta                                                                  |   11 
 Main/Core/GameEngine/Launch/InitSettingTask.cs                                                                |    1 
 Main/System/Login/LoginWin.cs                                                                                 |    2 
 Main/System/Battle/Skill/SkillBase.Hit.cs.meta                                                                |   11 
 Main/System/HeroDebut/HeroDebutZhanLingCell.cs                                                                |  121 
 Main/Core/GameEngine/Launch/DownLoadAssetTask.cs                                                              |    1 
 Main/Component/UI/Core/OutlineEx.cs                                                                           |   82 
 Main/System/TotalRecharge/TotalRechargeWin.cs.meta                                                            |   11 
 Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs.meta                                                   |   11 
 Main/System/UIBase/UIJumpManager.cs                                                                           |    4 
 Main/System/BillboardRank/PlayerRankWin.cs                                                                    |   14 
 Main/Config/Configs/HeroQualityBreakConfig.cs                                                                 |    5 
 Main/System/Message/GMNotify.cs                                                                               |    2 
 Main/System/Qunying/QYBattleVictoryWin.cs                                                                     |   12 
 Main/System/KnapSack/PackManager.cs                                                                           |   45 
 Main/System/TotalRecharge/TotalRechargeCell.cs                                                                |   74 
 Main/System/Horse/HorseCarouselView.cs                                                                        |  226 +
 Main/Utility/UIHelper.cs                                                                                      |   56 
 Main/System/Battle/Skill/SkillBase.Death.cs.meta                                                              |   11 
 Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs                                                          |    6 
 Main/System/Main/MainWin.cs                                                                                   |    3 
 Main/Config/Configs/HorseIDConfig.cs                                                                          |   50 
 Main/Config/PartialConfigs/HorseSkinConfig.cs                                                                 |   12 
 Main/System/HeroUI/HeroUIManager.cs                                                                           |    9 
 Main/System/Login/ServerData.cs                                                                               |    7 
 Main/System/OSActivity/OperationTotalRechargeInfo.cs.meta                                                     |   11 
 Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs.meta                                                 |   11 
 Main/Core/NetworkPackage/ClientPack/CA1_Sys/CA130_tagCMViewBillboard.cs                                       |   14 
 Main/System/Battle/UIComp/TotalDamageDisplayer.cs                                                             |   88 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs.meta                  |   11 
 Main/System/FirstCharge/FirstChargeHeroInfoWin.cs                                                             |    9 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs       |   12 
 Main/System/Horse/HorseSkinCell.cs                                                                            |    2 
 Main/System/Message/SysNotifyMgr.cs                                                                           |    8 
 Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs                                |   25 
 Main/Core/GameEngine/Launch/LaunchFadeOutTask.cs                                                              |    2 
 Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs.meta                               |   11 
 Main/System/TotDayRecharge/TotDayRechargeWin.cs                                                               |   51 
 Main/System/HeroReturn/HeroReturnZhanLingWin.cs                                                               |  151 
 Main/Config/Configs/ActTotDayRechargeConfig.cs.meta                                                           |   11 
 Main/System/BillboardRank/RankModel.cs                                                                        |   10 
 Main/System/Tip/ConfirmCancel.cs                                                                              |    1 
 Main/Core/GameEngine/Launch/ConfigInitTask.cs                                                                 |    2 
 Main/System/HeroDebut/HeroDebutWin.cs                                                                         |    4 
 Main/System/Debug/DebugLogin.cs                                                                               |    2 
 Main/System/Login/ServerListCenter.cs                                                                         |   26 
 Main/System/OSActivity/OSGalaBaseWin.cs                                                                       |  279 +
 Main/System/Battle/Skill/SkillBase.Hit.cs                                                                     |  241 +
 Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs.meta                                                |   11 
 Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs                                                     |   58 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs                |   21 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs             |   14 
 Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB431_tagSCTurnFightRet.cs                                |    2 
 Main/System/Horse/HorseCarouselView.cs.meta                                                                   |   11 
 Main/Config/ConfigManager.cs                                                                                  |   15 
 Main/System/Horse/HorseManager.cs                                                                             |  312 +
 Main/Core/GameEngine/Launch/GetVersionInfoTask.cs                                                             |    1 
 Main/System/OSActivity/OperationTotDayRechargeInfo.cs                                                         |   21 
 Main/System/Battle/BattleField/BattleField.cs                                                                 |   31 
 Main/Core/NetworkPackage/DTCFile/ServerPack/H01_System/DTC0104_tagServerDisconnect.cs                         |    6 
 Main/System/Main/HomeWin.cs                                                                                   |   25 
 Main/Main.cs                                                                                                  |    5 
 Main/System/HeroReturn/HeroReturnZhanLingCell.cs.meta                                                         |   11 
 Main/Component/UI/Effect/EffectPlayer.cs                                                                      |  107 
 Main/System/TotDayRecharge/TotDayRechargeManager.cs                                                           |  251 +
 Main/System/TotalRecharge/TotalRechargeWin.cs                                                                 |   51 
 Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs            |   12 
 Main/System/TimeRush/TimeRushManager.cs                                                                       |    3 
 Main/System/Battle/SkillEffect/SkillEffect.cs                                                                 |    8 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs.meta                                                   |   11 
 Main/System/Battle/RecordPlayer/RecordPlayer.cs                                                               |   96 
 Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs                       |   23 
 Main/System/Battle/Skill/SkillBase.Finish.cs.meta                                                             |   11 
 Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs.meta                                                    |   11 
 Main/System/Battle/Skill/SkillBase.Cast.cs                                                                    |  427 ++
 212 files changed, 8,289 insertions(+), 1,950 deletions(-)

diff --git a/Main/Component/UI/Common/FuncOpen.cs b/Main/Component/UI/Common/FuncOpen.cs
index e92c9b8..93ac833 100644
--- a/Main/Component/UI/Common/FuncOpen.cs
+++ b/Main/Component/UI/Common/FuncOpen.cs
@@ -346,42 +346,20 @@
 
     public string GetErrorStr(int funcId)
     {
-        if (!FuncOpenLVConfig.HasKey(funcId))
-            return string.Empty;
         FuncOpenLVConfig config = FuncOpenLVConfig.Get(funcId);
-        List<string> conditionStrs = new List<string>();
-        if (config.LimitLV > 0)
-        {
-            conditionStrs.Add(Language.Get("FunctionPreviewErr01", config.LimitLV));
-        }
-
-        if (config.LimiRealmLV > 0)
-        {
-            conditionStrs.Add(Language.Get("FunctionPreviewErr02", RealmConfig.Get(config.LimiRealmLV).Name));
-        }
-
-        if (config.LimitMissionID > 0)
-        {
-            conditionStrs.Add(Language.Get("FunctionPreviewErr03", Mathf.Max(TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID), 0)));
-        }
-
-        if (config.OpenDay > 0)
-        {
-            conditionStrs.Add(Language.Get("FunctionPreviewErr04", config.OpenDay));
-        }
+        if (config == null)
+            return string.Empty;
 
         if (config.ManLevel > 0)
-        {
-            conditionStrs.Add(Language.Get("FunctionPreviewErr05", config.ManLevel / 10000, config.ManLevel / 100 % 100, config.ManLevel % 100));
-        }
+            return Language.Get("FunctionPreviewLimit_ManLevel", config.ManLevel / 10000, config.ManLevel / 100 % 100, config.ManLevel % 100);
 
-        if (conditionStrs.Count == 0)
-        {
-            return string.Empty;
-        }
-        string connector = Language.Get("FunctionPreview01"); // "涓�"
-        string result = string.Join(connector, conditionStrs);
-        return result;
+        if (config.LimitMissionID > 0)
+            return Language.Get("FunctionPreviewErr03", Mathf.Max(TaskManager.Instance.GetNeedFinishTaskCount(config.LimitMissionID), 0));
+
+        if (config.LimitLV > 0 && config.OpenDay > 0)
+            return Language.Get("FunctionPreviewLimit_LimitLV_OpenDay", config.LimitLV, config.OpenDay);
+
+        return string.Empty;
     }
 
     public void SendGetAward(int funcId)
diff --git a/Main/Component/UI/Core/OutlineEx.cs b/Main/Component/UI/Core/OutlineEx.cs
index f7a3993..c65cb9b 100644
--- a/Main/Component/UI/Core/OutlineEx.cs
+++ b/Main/Component/UI/Core/OutlineEx.cs
@@ -40,7 +40,7 @@
     //榛樿10锛屼笉鍚岀殑棰滆壊锛堝寘鎷皟鏁碼lpha锛夎瑙変笂鎻忚竟绮楃粏鏈夊樊寮傦紝鏁卻hader閲屼箻浠�0.2閫傚簲涓嶅悓鎯呭喌
     public int OutlineWidth = 10;    
 
-    private static List<UIVertex> m_VetexList = new List<UIVertex>();
+    private List<UIVertex> m_VetexList = new List<UIVertex>();
 
     protected override void Start()
     {
@@ -48,28 +48,6 @@
 
         if (base.graphic)
         {
-            if (base.graphic.material == null || base.graphic.material.shader.name != "TSF Shaders/UI/OutlineEx")
-            {
-// #if UNITY_EDITOR
-
-                ResManager.Instance.LoadAssetAsync<Material>("Materials", "OutlineMat").ContinueWith(texMaterial =>
-                {
-                    if (texMaterial != null)
-                    {
-                        base.graphic.material = texMaterial;
-                    }
-                    else
-                    {
-                        Debug.LogError("娌℃湁鎵惧埌鏉愯川OutlineMat.mat");
-                    }
-                }).Forget();
-
-// #else
-//                 var shader = Shader.Find("TSF Shaders/UI/OutlineEx");
-//                 base.graphic.material = new Material(shader);
-// #endif
-            }
-
             if (base.graphic.canvas)
             {
                 var v1 = base.graphic.canvas.additionalShaderChannels;
@@ -99,9 +77,55 @@
                     base.graphic.canvas.additionalShaderChannels |= v2;
                 }
             }
-            this._Refresh();
+
+            // 寮傛鍔犺浇鏉愯川锛屽畬鎴愬悗鍐嶈皟鐢� _Refresh锛涘吋瀹� WebGL锛堝悓姝� LoadAsset 鍦� WebGL 涓嬩笉鍙敤锛�
+            LoadOutlineMaterialAsync().Forget();
         }
     }
+
+    private async UniTaskVoid LoadOutlineMaterialAsync()
+    {
+        var texMaterial = await ResManager.Instance.LoadAssetAsync<Material>("Materials", "OutlineMat");
+        if (this == null || base.graphic == null) return;
+        if (texMaterial == null)
+        {
+            Debug.LogError("娌℃湁鎵惧埌鏉愯川OutlineMat.mat");
+            return;
+        }
+
+        // 鍒涘缓瀹炰緥鏉愯川锛岄伩鍏嶅叡浜潗璐ㄧ殑闂
+        var instanceMat = new Material(texMaterial);
+
+        // 鑾峰彇姝g‘鐨勭汗鐞嗗苟缁戝畾
+        Texture mainTexture = null;
+        if (base.graphic is Text text)
+        {
+            mainTexture = text.font.material.mainTexture;
+        }
+        else if (base.graphic is Image image && image.sprite != null)
+        {
+            mainTexture = image.sprite.texture;
+        }
+        else if (base.graphic is RawImage rawImage && rawImage.texture != null)
+        {
+            mainTexture = rawImage.texture;
+        }
+        else
+        {
+            mainTexture = instanceMat.GetTexture("_MainTex");
+        }
+
+        if (mainTexture != null)
+        {
+            instanceMat.SetTexture("_MainTex", mainTexture);
+        }
+
+        base.graphic.material = instanceMat;
+
+        // 鏉愯川灏辩华鍚庡啀鍒锋柊涓�娆★紝纭繚鎻忚竟姝g‘鏄剧ず
+        this._Refresh();
+    }
+    
     
 #if UNITY_EDITOR
     protected override void OnValidate()
@@ -134,11 +158,6 @@
 
     private void _Refresh()
     {
-        /*if (base.graphic.material.GetInt("_OutlineWidth") != this.OutlineWidth || base.graphic.material.GetColor("_OutlineColor") != this.OutlineColor)
-        {
-            base.graphic.material.SetColor("_OutlineColor", this.OutlineColor);
-            base.graphic.material.SetInt("_OutlineWidth", this.OutlineWidth);
-        }*/
         base.graphic.SetVerticesDirty();
     }
 
@@ -237,9 +256,8 @@
         // UV
         var uv = pVertex.uv0;
 
-
-    uv += new Vector4((pUVX / pTriangleX.magnitude * posXOffset * (Vector2.Dot(pTriangleX, Vector2.right) > 0 ? 1 : -1)).x, (pUVX / pTriangleX.magnitude * posXOffset * (Vector2.Dot(pTriangleX, Vector2.right) > 0 ? 1 : -1)).y, 0, 0);
-    uv += new Vector4((pUVY / pTriangleY.magnitude * posYOffset * (Vector2.Dot(pTriangleY, Vector2.up) > 0 ? 1 : -1)).x, (pUVY / pTriangleY.magnitude * posYOffset * (Vector2.Dot(pTriangleY, Vector2.up) > 0 ? 1 : -1)).y, 0, 0);
+        uv += new Vector4((pUVX / pTriangleX.magnitude * posXOffset * (Vector2.Dot(pTriangleX, Vector2.right) > 0 ? 1 : -1)).x, (pUVX / pTriangleX.magnitude * posXOffset * (Vector2.Dot(pTriangleX, Vector2.right) > 0 ? 1 : -1)).y, 0, 0);
+        uv += new Vector4((pUVY / pTriangleY.magnitude * posYOffset * (Vector2.Dot(pTriangleY, Vector2.up) > 0 ? 1 : -1)).x, (pUVY / pTriangleY.magnitude * posYOffset * (Vector2.Dot(pTriangleY, Vector2.up) > 0 ? 1 : -1)).y, 0, 0);
     
         pVertex.uv0 = uv;
 
diff --git a/Main/Component/UI/Effect/EffectPlayer.cs b/Main/Component/UI/Effect/EffectPlayer.cs
index c506f18..19eb8a7 100644
--- a/Main/Component/UI/Effect/EffectPlayer.cs
+++ b/Main/Component/UI/Effect/EffectPlayer.cs
@@ -263,67 +263,64 @@
 
     protected async UniTask PlaySpineEffect(bool closePMA = false)
     {
-
-        // 浠庣壒鏁堥鍒朵綋姹犺幏鍙栫壒鏁�
-        if (spineComp == null)
-        { 
-            spineComp = gameObject.AddMissingComponent<SkeletonGraphic>();
-        }
-
-        if (spineComp.skeletonDataAsset == null || spineAnimationState == null)
+        try
         {
-            //LoadAsset 宸茬粡鏈夌紦瀛楽keletonDataAsset
-            spineComp.skeletonDataAsset = await ResManager.Instance.LoadAssetAsync<SkeletonDataAsset>("UIEffect/" + effectConfig.packageName, effectConfig.fxName);
-            //涓簍rue鏃朵細鏈夐儴鍒嗙壒鏁堜笉鏄剧ず 濡傛弧绾х粡楠屾潯锛涙敼鎴愪冀椹悗閮ㄥ垎鐗规晥姝e父锛岃繕鏈夐儴鍒嗕緷鐒惰鏀规璁剧疆
-            spineComp.MeshGenerator.settings.pmaVertexColors = !closePMA;   
-            spineComp.raycastTarget = false;
-            spineComp.Initialize(true);
-            // 妫�鏌ュ姩鐢绘槸鍚︽湁鐩稿姞妯″紡
-            // bool hasAdditiveBlend = CheckForAdditiveBlend(spineComp.Skeleton);
-            // if (hasAdditiveBlend)
-            // {
-            //    spineComp.material = ResManager.Instance.LoadAsset<Material>("UIEffect/" + effectConfig.packageName, effectConfig.fxName.Split('_')[0] + "_Material-Additive");
-            // }
-            // else
-            // {
-            //     spineComp.material = null;
-            // }
-            var material = await ResManager.Instance.LoadAssetAsync<Material>("Materials", "SkeletonGraphicDefault-Straight");
-            if (material != null)
-            {
-                spineComp.material = material;
-                #if UNITY_WEBGL && !UNITY_EDITOR
-                Debug.Log($"[SpineEffect][WebGL] effectId={effectConfig.id} fxName={effectConfig.fxName}" +
-                    $" mat={material.name} shader={material.shader.name}" +
-                    $" straightAlpha={material.IsKeywordEnabled("_STRAIGHT_ALPHA_INPUT")}" +
-                    $" canvasGroup={material.IsKeywordEnabled("_CANVAS_GROUP_COMPATIBLE")}" +
-                    $" pmaVert={spineComp.MeshGenerator.settings.pmaVertexColors}");
-                #endif
-            }
-            else
-            {
-                Debug.LogError("Failed to load material for Spine effect: " + effectConfig.fxName);
+            // 浠庣壒鏁堥鍒朵綋姹犺幏鍙栫壒鏁�
+            if (spineComp == null)
+            { 
+                spineComp = gameObject.AddMissingComponent<SkeletonGraphic>();
             }
 
-            spineAnimationState = spineComp.AnimationState;
-            spineAnimationState.TimeScale = speedRate;
-            spineAnimationState.Data.DefaultMix = 0f;
-            spineAnimationState.Complete -= OnSpineAnimationComplete;
-            spineAnimationState.Complete += OnSpineAnimationComplete;
+            if (spineComp.skeletonDataAsset == null || spineAnimationState == null)
+            {
+                //LoadAsset 宸茬粡鏈夌紦瀛楽keletonDataAsset锛涗娇鐢ㄥ紓姝PI鍏煎WebGL
+                spineComp.skeletonDataAsset = await ResManager.Instance.LoadAssetAsync<SkeletonDataAsset>("UIEffect/" + effectConfig.packageName, effectConfig.fxName);
+                if (this == null || spineComp == null) return;
+                //涓簍rue鏃朵細鏈夐儴鍒嗙壒鏁堜笉鏄剧ず 濡傛弧绾х粡楠屾潯锛涙敼鎴愪冀椹悗閮ㄥ垎鐗规晥姝e父锛岃繕鏈夐儴鍒嗕緷鐒惰鏀规璁剧疆
+                spineComp.MeshGenerator.settings.pmaVertexColors = !closePMA;   
+                spineComp.raycastTarget = false;
+                spineComp.Initialize(true);
+                // 妫�鏌ュ姩鐢绘槸鍚︽湁鐩稿姞妯″紡
+                // bool hasAdditiveBlend = CheckForAdditiveBlend(spineComp.Skeleton);
+                // if (hasAdditiveBlend)
+                // {
+                //    spineComp.material = ResManager.Instance.LoadAsset<Material>("UIEffect/" + effectConfig.packageName, effectConfig.fxName.Split('_')[0] + "_Material-Additive");
+                // }
+                // else
+                // {
+                //     spineComp.material = null;
+                // }
+                var material = await ResManager.Instance.LoadAssetAsync<Material>("Materials", "SkeletonGraphicDefault-Straight");
+                if (this == null || spineComp == null) return;
+                if (material != null)
+                {
+                    spineComp.material = material;
+#if UNITY_WEBGL && !UNITY_EDITOR
+                    Debug.Log($"[SpineEffect][WebGL] effectId={effectConfig.id} fxName={effectConfig.fxName}" +
+                        $" mat={material.name} shader={material.shader.name}" +
+                        $" straightAlpha={material.IsKeywordEnabled("_STRAIGHT_ALPHA_INPUT")}" +
+                        $" canvasGroup={material.IsKeywordEnabled("_CANVAS_GROUP_COMPATIBLE")}" +
+                        $" pmaVert={spineComp.MeshGenerator.settings.pmaVertexColors}");
+#endif
+                }
+
+                spineAnimationState = spineComp.AnimationState;
+                spineAnimationState.TimeScale = speedRate;
+                spineAnimationState.Data.DefaultMix = 0f;
+                spineAnimationState.Complete -= OnSpineAnimationComplete;
+                spineAnimationState.Complete += OnSpineAnimationComplete;
+            }
+
+            spineComp.enabled = true;
+            PlayerTheSpineAnim();
+            SoundPlayer.Instance.PlayUIAudioDelay(effectConfig.audio).Forget();
         }
-
-        spineComp.enabled = true;
-        PlayerTheSpineAnim();
-        SoundPlayer.Instance.PlayUIAudioDelay(effectConfig.audio).Forget();
-
-        #if UNITY_EDITOR
-        // 缂栬緫鍣ㄦā寮忎笅寮哄埗鍒锋柊鏉愯川鐞冿紝瑙e喅閮ㄥ垎鐗规晥涓嶆樉绀洪棶棰�
-        await UniTask.Delay(100);
-        if (spineComp != null && this != null && spineComp.material != null)
+        catch (Exception e)
         {
-            spineComp.material.shader = Shader.Find(spineComp.material.shader.name);
+            Debug.LogError(e);
         }
-        #endif
+
+        await UniTask.CompletedTask;
     }
 
         // 鎾斁鎸囧畾鍔ㄧ敾
diff --git a/Main/Config/ConfigManager.cs b/Main/Config/ConfigManager.cs
index 8759a51..e178ae3 100644
--- a/Main/Config/ConfigManager.cs
+++ b/Main/Config/ConfigManager.cs
@@ -62,6 +62,10 @@
             typeof(ActHeroReturnArtConfig),
             typeof(ActLunhuidianTypeConfig),
             typeof(ActSignAwardConfig),
+            typeof(ActTotalRechargeConfig),
+            typeof(ActTotalRechargeTempConfig),
+            typeof(ActTotDayRechargeConfig),
+            typeof(ActTotDayRechargeTempConfig),
             typeof(ADAwardConfig),
             typeof(AppointItemConfig),
             typeof(AudioConfig),
@@ -124,6 +128,7 @@
             typeof(HeroSkinConfig),
             typeof(HeroTalentConfig),
             typeof(HorseClassConfig),
+            typeof(HorseIDConfig),
             typeof(HorseSkinConfig),
             typeof(IconConfig),
             typeof(ItemCompoundConfig),
@@ -401,6 +406,14 @@
         ClearConfigDictionary<ActLunhuidianTypeConfig>();
         // 娓呯┖ ActSignAwardConfig 瀛楀吀
         ClearConfigDictionary<ActSignAwardConfig>();
+        // 娓呯┖ ActTotalRechargeConfig 瀛楀吀
+        ClearConfigDictionary<ActTotalRechargeConfig>();
+        // 娓呯┖ ActTotalRechargeTempConfig 瀛楀吀
+        ClearConfigDictionary<ActTotalRechargeTempConfig>();
+        // 娓呯┖ ActTotDayRechargeConfig 瀛楀吀
+        ClearConfigDictionary<ActTotDayRechargeConfig>();
+        // 娓呯┖ ActTotDayRechargeTempConfig 瀛楀吀
+        ClearConfigDictionary<ActTotDayRechargeTempConfig>();
         // 娓呯┖ ADAwardConfig 瀛楀吀
         ClearConfigDictionary<ADAwardConfig>();
         // 娓呯┖ BattleMapConfig 瀛楀吀
@@ -469,6 +482,8 @@
         ClearConfigDictionary<HeroSkinAttrConfig>();
         // 娓呯┖ HorseClassConfig 瀛楀吀
         ClearConfigDictionary<HorseClassConfig>();
+        // 娓呯┖ HorseIDConfig 瀛楀吀
+        ClearConfigDictionary<HorseIDConfig>();
         // 娓呯┖ HorseSkinConfig 瀛楀吀
         ClearConfigDictionary<HorseSkinConfig>();
         // 娓呯┖ ItemCompoundConfig 瀛楀吀
diff --git a/Main/Config/Configs/ActHeroAppearConfig.cs b/Main/Config/Configs/ActHeroAppearConfig.cs
index fb2450f..6fe770f 100644
--- a/Main/Config/Configs/ActHeroAppearConfig.cs
+++ b/Main/Config/Configs/ActHeroAppearConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           Thursday, March 26, 2026
+//    [  Date ]:           Thursday, April 16, 2026
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -20,6 +20,7 @@
 	public int ActNum;
 	public int[] ActHeroIDList;
 	public int ActTreasureType;
+	public int ActZhanlingType;
 	public int StarGiftTempID;
 	public int[] SkinCTGIDList;
 	public int[] GiftCTGIDList;
@@ -59,15 +60,17 @@
 
 			int.TryParse(tables[3],out ActTreasureType); 
 
-			int.TryParse(tables[4],out StarGiftTempID); 
+			int.TryParse(tables[4],out ActZhanlingType); 
 
-			if (tables[5].Contains("["))
+			int.TryParse(tables[5],out StarGiftTempID); 
+
+			if (tables[6].Contains("["))
 			{
-				SkinCTGIDList = JsonMapper.ToObject<int[]>(tables[5]);
+				SkinCTGIDList = JsonMapper.ToObject<int[]>(tables[6]);
 			}
 			else
 			{
-				string[] SkinCTGIDListStringArray = tables[5].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] SkinCTGIDListStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				SkinCTGIDList = new int[SkinCTGIDListStringArray.Length];
 				for (int i=0;i<SkinCTGIDListStringArray.Length;i++)
 				{
@@ -75,13 +78,13 @@
 				}
 			}
 
-			if (tables[6].Contains("["))
+			if (tables[7].Contains("["))
 			{
-				GiftCTGIDList = JsonMapper.ToObject<int[]>(tables[6]);
+				GiftCTGIDList = JsonMapper.ToObject<int[]>(tables[7]);
 			}
 			else
 			{
-				string[] GiftCTGIDListStringArray = tables[6].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				string[] GiftCTGIDListStringArray = tables[7].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
 				GiftCTGIDList = new int[GiftCTGIDListStringArray.Length];
 				for (int i=0;i<GiftCTGIDListStringArray.Length;i++)
 				{
@@ -89,15 +92,15 @@
 				}
 			}
 
-			int.TryParse(tables[7],out GiftShopType); 
+			int.TryParse(tables[8],out GiftShopType); 
 
-			int.TryParse(tables[8],out ExShopType); 
+			int.TryParse(tables[9],out ExShopType); 
 
-			int.TryParse(tables[9],out ExShopCostItemID); 
+			int.TryParse(tables[10],out ExShopCostItemID); 
 
-			int.TryParse(tables[10],out SignTempID); 
+			int.TryParse(tables[11],out SignTempID); 
 
-			int.TryParse(tables[11],out BillTempID); 
+			int.TryParse(tables[12],out BillTempID); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/Configs/ActTotDayRechargeConfig.cs b/Main/Config/Configs/ActTotDayRechargeConfig.cs
new file mode 100644
index 0000000..2ab126e
--- /dev/null
+++ b/Main/Config/Configs/ActTotDayRechargeConfig.cs
@@ -0,0 +1,44 @@
+锘�//--------------------------------------------------------
+//    [Author]:           YYL
+//    [  Date ]:           2026骞�4鏈�20鏃�
+//--------------------------------------------------------
+
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using LitJson;
+
+public partial class ActTotDayRechargeConfig : ConfigBase<int, ActTotDayRechargeConfig>
+{
+    static ActTotDayRechargeConfig()
+    {
+        // 璁块棶杩囬潤鎬佹瀯閫犲嚱鏁�
+        visit = true; 
+    }
+
+    public int CfgID;
+	public int TemplateID;
+	public int ActShopType;
+
+    public override int LoadKey(string _key)
+    {
+        int key = GetKey(_key);
+        return key;
+    }
+
+    public override void LoadConfig(string input)
+    {
+        try {
+        string[] tables = input.Split('\t');
+        int.TryParse(tables[0],out CfgID); 
+
+			int.TryParse(tables[1],out TemplateID); 
+
+			int.TryParse(tables[2],out ActShopType); 
+        }
+        catch (Exception exception)
+        {
+            Debug.LogError(exception);
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActTotDayRechargeConfig.cs.meta b/Main/Config/Configs/ActTotDayRechargeConfig.cs.meta
new file mode 100644
index 0000000..1618988
--- /dev/null
+++ b/Main/Config/Configs/ActTotDayRechargeConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 76b774172f2c1ec41852272287e4b25c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/Configs/ActTotDayRechargeTempConfig.cs b/Main/Config/Configs/ActTotDayRechargeTempConfig.cs
new file mode 100644
index 0000000..29d5cc7
--- /dev/null
+++ b/Main/Config/Configs/ActTotDayRechargeTempConfig.cs
@@ -0,0 +1,47 @@
+锘�//--------------------------------------------------------
+//    [Author]:           YYL
+//    [  Date ]:           2026骞�4鏈�20鏃�
+//--------------------------------------------------------
+
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using LitJson;
+
+public partial class ActTotDayRechargeTempConfig : ConfigBase<int, ActTotDayRechargeTempConfig>
+{
+    static ActTotDayRechargeTempConfig()
+    {
+        // 璁块棶杩囬潤鎬佹瀯閫犲嚱鏁�
+        visit = true; 
+    }
+
+    public int AwardID;
+	public int TemplateID;
+	public int NeedDay;
+	public int[][] AwardItemList;
+
+    public override int LoadKey(string _key)
+    {
+        int key = GetKey(_key);
+        return key;
+    }
+
+    public override void LoadConfig(string input)
+    {
+        try {
+        string[] tables = input.Split('\t');
+        int.TryParse(tables[0],out AwardID); 
+
+			int.TryParse(tables[1],out TemplateID); 
+
+			int.TryParse(tables[2],out NeedDay); 
+
+			AwardItemList = JsonMapper.ToObject<int[][]>(tables[3].Replace("(", "[").Replace(")", "]")); 
+        }
+        catch (Exception exception)
+        {
+            Debug.LogError(exception);
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActTotDayRechargeTempConfig.cs.meta b/Main/Config/Configs/ActTotDayRechargeTempConfig.cs.meta
new file mode 100644
index 0000000..c92212a
--- /dev/null
+++ b/Main/Config/Configs/ActTotDayRechargeTempConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b6d7d5571b6413f489eb78b5fe653a5f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/Configs/ActTotalRechargeConfig.cs b/Main/Config/Configs/ActTotalRechargeConfig.cs
new file mode 100644
index 0000000..03e5cff
--- /dev/null
+++ b/Main/Config/Configs/ActTotalRechargeConfig.cs
@@ -0,0 +1,47 @@
+锘�//--------------------------------------------------------
+//    [Author]:           YYL
+//    [  Date ]:           2026骞�4鏈�20鏃�
+//--------------------------------------------------------
+
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using LitJson;
+
+public partial class ActTotalRechargeConfig : ConfigBase<int, ActTotalRechargeConfig>
+{
+    static ActTotalRechargeConfig()
+    {
+        // 璁块棶杩囬潤鎬佹瀯閫犲嚱鏁�
+        visit = true; 
+    }
+
+    public int CfgID;
+	public int IsDayReset;
+	public int CTGTempID;
+	public int CTGShopType;
+
+    public override int LoadKey(string _key)
+    {
+        int key = GetKey(_key);
+        return key;
+    }
+
+    public override void LoadConfig(string input)
+    {
+        try {
+        string[] tables = input.Split('\t');
+        int.TryParse(tables[0],out CfgID); 
+
+			int.TryParse(tables[1],out IsDayReset); 
+
+			int.TryParse(tables[2],out CTGTempID); 
+
+			int.TryParse(tables[3],out CTGShopType); 
+        }
+        catch (Exception exception)
+        {
+            Debug.LogError(exception);
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActTotalRechargeConfig.cs.meta b/Main/Config/Configs/ActTotalRechargeConfig.cs.meta
new file mode 100644
index 0000000..af9d069
--- /dev/null
+++ b/Main/Config/Configs/ActTotalRechargeConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a27d596fa4a6e284c90afe1cb0e50d5b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/Configs/ActTotalRechargeTempConfig.cs b/Main/Config/Configs/ActTotalRechargeTempConfig.cs
new file mode 100644
index 0000000..520f4c4
--- /dev/null
+++ b/Main/Config/Configs/ActTotalRechargeTempConfig.cs
@@ -0,0 +1,50 @@
+锘�//--------------------------------------------------------
+//    [Author]:           YYL
+//    [  Date ]:           2026骞�4鏈�20鏃�
+//--------------------------------------------------------
+
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using LitJson;
+
+public partial class ActTotalRechargeTempConfig : ConfigBase<int, ActTotalRechargeTempConfig>
+{
+    static ActTotalRechargeTempConfig()
+    {
+        // 璁块棶杩囬潤鎬佹瀯閫犲嚱鏁�
+        visit = true; 
+    }
+
+    public int AwardID;
+	public int TemplateID;
+	public float NeedAmount;
+	public int AwardIndex;
+	public int[][] AwardItemList;
+
+    public override int LoadKey(string _key)
+    {
+        int key = GetKey(_key);
+        return key;
+    }
+
+    public override void LoadConfig(string input)
+    {
+        try {
+        string[] tables = input.Split('\t');
+        int.TryParse(tables[0],out AwardID); 
+
+			int.TryParse(tables[1],out TemplateID); 
+
+			float.TryParse(tables[2],out NeedAmount); 
+
+			int.TryParse(tables[3],out AwardIndex); 
+
+			AwardItemList = JsonMapper.ToObject<int[][]>(tables[4].Replace("(", "[").Replace(")", "]")); 
+        }
+        catch (Exception exception)
+        {
+            Debug.LogError(exception);
+        }
+    }
+}
diff --git a/Main/Config/Configs/ActTotalRechargeTempConfig.cs.meta b/Main/Config/Configs/ActTotalRechargeTempConfig.cs.meta
new file mode 100644
index 0000000..6c66a76
--- /dev/null
+++ b/Main/Config/Configs/ActTotalRechargeTempConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f90ea937d9f96a549a3f2f9c9ce1c59b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/Configs/HeroConfig.cs b/Main/Config/Configs/HeroConfig.cs
index 4c4ed0c..b34990d 100644
--- a/Main/Config/Configs/HeroConfig.cs
+++ b/Main/Config/Configs/HeroConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2026骞�3鏈�16鏃�
+//    [  Date ]:           2026骞�4鏈�10鏃�
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -42,6 +42,9 @@
 	public int[] TalentList;
 	public int OpenCollectionDay;
 	public int IsActLimit;
+	public int AtkInheritPerStar;
+	public int DefInheritPerStar;
+	public int HPInheritPerStar;
 
     public override int LoadKey(string _key)
     {
@@ -152,6 +155,12 @@
 			int.TryParse(tables[24],out OpenCollectionDay); 
 
 			int.TryParse(tables[25],out IsActLimit); 
+
+			int.TryParse(tables[26],out AtkInheritPerStar); 
+
+			int.TryParse(tables[27],out DefInheritPerStar); 
+
+			int.TryParse(tables[28],out HPInheritPerStar); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/Configs/HeroQualityBreakConfig.cs b/Main/Config/Configs/HeroQualityBreakConfig.cs
index a2c5261..d3ceb59 100644
--- a/Main/Config/Configs/HeroQualityBreakConfig.cs
+++ b/Main/Config/Configs/HeroQualityBreakConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           Tuesday, December 9, 2025
+//    [  Date ]:           2026骞�4鏈�10鏃�
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -21,6 +21,7 @@
 	public int BreakLV;
 	public int UPLVNeed;
 	public int[][] UPCostItemList;
+	public int UPLVNeedStar;
 
     public override int LoadKey(string _key)
     {
@@ -41,6 +42,8 @@
 			int.TryParse(tables[3],out UPLVNeed); 
 
 			UPCostItemList = JsonMapper.ToObject<int[][]>(tables[4].Replace("(", "[").Replace(")", "]")); 
+
+			int.TryParse(tables[5],out UPLVNeedStar); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/Configs/HorseClassConfig.cs b/Main/Config/Configs/HorseClassConfig.cs
index 9c9c0b0..96fdade 100644
--- a/Main/Config/Configs/HorseClassConfig.cs
+++ b/Main/Config/Configs/HorseClassConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2025骞�11鏈�16鏃�
+//    [  Date ]:           2026骞�4鏈�15鏃�
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -25,6 +25,8 @@
 	public int[] AttrIDList;
 	public int[] ClassAttrValueList;
 	public int[] PerLVAttrValueList;
+	public int[] HorseEffAttrIDList;
+	public int[] HorseEffAttrValueList;
 
     public override int LoadKey(string _key)
     {
@@ -113,6 +115,34 @@
 					 int.TryParse(PerLVAttrValueListStringArray[i],out PerLVAttrValueList[i]);
 				}
 			}
+
+			if (tables[9].Contains("["))
+			{
+				HorseEffAttrIDList = JsonMapper.ToObject<int[]>(tables[9]);
+			}
+			else
+			{
+				string[] HorseEffAttrIDListStringArray = tables[9].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				HorseEffAttrIDList = new int[HorseEffAttrIDListStringArray.Length];
+				for (int i=0;i<HorseEffAttrIDListStringArray.Length;i++)
+				{
+					 int.TryParse(HorseEffAttrIDListStringArray[i],out HorseEffAttrIDList[i]);
+				}
+			}
+
+			if (tables[10].Contains("["))
+			{
+				HorseEffAttrValueList = JsonMapper.ToObject<int[]>(tables[10]);
+			}
+			else
+			{
+				string[] HorseEffAttrValueListStringArray = tables[10].Trim().Split(StringUtility.splitSeparator,StringSplitOptions.RemoveEmptyEntries);
+				HorseEffAttrValueList = new int[HorseEffAttrValueListStringArray.Length];
+				for (int i=0;i<HorseEffAttrValueListStringArray.Length;i++)
+				{
+					 int.TryParse(HorseEffAttrValueListStringArray[i],out HorseEffAttrValueList[i]);
+				}
+			}
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/Configs/HorseIDConfig.cs b/Main/Config/Configs/HorseIDConfig.cs
new file mode 100644
index 0000000..0aafe4e
--- /dev/null
+++ b/Main/Config/Configs/HorseIDConfig.cs
@@ -0,0 +1,50 @@
+锘�//--------------------------------------------------------
+//    [Author]:           YYL
+//    [  Date ]:           Wednesday, April 15, 2026
+//--------------------------------------------------------
+
+using System.Collections.Generic;
+using System;
+using UnityEngine;
+using LitJson;
+
+public partial class HorseIDConfig : ConfigBase<int, HorseIDConfig>
+{
+    static HorseIDConfig()
+    {
+        // 璁块棶杩囬潤鎬佹瀯閫犲嚱鏁�
+        visit = true; 
+    }
+
+    public int HorseID;
+	public int UnlockWay;
+	public int UnlockValue;
+	public int UnlockNeedCnt;
+	public int AttrID;
+
+    public override int LoadKey(string _key)
+    {
+        int key = GetKey(_key);
+        return key;
+    }
+
+    public override void LoadConfig(string input)
+    {
+        try {
+        string[] tables = input.Split('\t');
+        int.TryParse(tables[0],out HorseID); 
+
+			int.TryParse(tables[1],out UnlockWay); 
+
+			int.TryParse(tables[2],out UnlockValue); 
+
+			int.TryParse(tables[3],out UnlockNeedCnt); 
+
+			int.TryParse(tables[4],out AttrID); 
+        }
+        catch (Exception exception)
+        {
+            Debug.LogError(exception);
+        }
+    }
+}
diff --git a/Main/Config/Configs/HorseIDConfig.cs.meta b/Main/Config/Configs/HorseIDConfig.cs.meta
new file mode 100644
index 0000000..e033c49
--- /dev/null
+++ b/Main/Config/Configs/HorseIDConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d3c2fe448c55f7c4a82cd8dc635934d6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/Configs/HorseSkinConfig.cs b/Main/Config/Configs/HorseSkinConfig.cs
index b2bfe44..07f4660 100644
--- a/Main/Config/Configs/HorseSkinConfig.cs
+++ b/Main/Config/Configs/HorseSkinConfig.cs
@@ -1,6 +1,6 @@
 锘�//--------------------------------------------------------
 //    [Author]:           YYL
-//    [  Date ]:           2025骞�11鏈�23鏃�
+//    [  Date ]:           Monday, April 13, 2026
 //--------------------------------------------------------
 
 using System.Collections.Generic;
@@ -31,6 +31,9 @@
 	public int[] Poses;
 	public int heroFirst;
 	public string getWay;
+	public string Icon;
+	public int showType;
+	public int sortOrder;
 
     public override int LoadKey(string _key)
     {
@@ -119,6 +122,12 @@
 			int.TryParse(tables[13],out heroFirst); 
 
 			getWay = tables[14];
+
+			Icon = tables[15];
+
+			int.TryParse(tables[16],out showType); 
+
+			int.TryParse(tables[17],out sortOrder); 
         }
         catch (Exception exception)
         {
diff --git a/Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs b/Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs
new file mode 100644
index 0000000..825dceb
--- /dev/null
+++ b/Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs
@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+
+public partial class ActTotDayRechargeTempConfig : ConfigBase<int, ActTotDayRechargeTempConfig>
+{
+    // 妯℃澘缂栧彿: 鎵�闇�绱厖澶� :濂栧姳ID
+    private static Dictionary<int, Dictionary<int, int>> infoDict = new Dictionary<int, Dictionary<int, int>>();
+    // 妯℃澘缂栧彿 鎵�闇�绱厖澶�
+    private static Dictionary<int, List<int>> sortDict = new Dictionary<int, List<int>>();
+    protected override void OnConfigParseCompleted()
+    {
+        if (!infoDict.TryGetValue(TemplateID, out var dict))
+        {
+            dict = new Dictionary<int, int>();
+            infoDict[TemplateID] = dict;
+        }
+        dict[NeedDay] = AwardID;
+    }
+
+    private static void LoadSortList()
+    {
+        if (!sortDict.IsNullOrEmpty()) return;
+        foreach (var kvp in infoDict)
+        {
+            int templateID = kvp.Key;
+            List<int> list = new List<int>(kvp.Value.Keys);
+            list.Sort();
+            sortDict[templateID] = list;
+        }
+    }
+
+    public static List<int> GetNeedDaySortList(int templateID)
+    {
+        LoadSortList();
+        sortDict.TryGetValue(templateID, out var list);
+        return list;
+    }
+
+    public static Dictionary<int, int> GetTemplateIDDict(int templateID)
+    {
+        infoDict.TryGetValue(templateID, out var dict);
+        return dict;
+    }
+
+    public static int GetID(int templateID, int needDay)
+    {
+        var dict = GetTemplateIDDict(templateID);
+        if (dict == null) return 0;
+
+        dict.TryGetValue(needDay, out var id);
+        return id;
+    }
+
+    public static ActTotDayRechargeTempConfig GetConfig(int templateID, int needDay)
+    {
+        int id = GetID(templateID, needDay);
+        return Get(id);
+    }
+}
\ No newline at end of file
diff --git a/Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs.meta b/Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs.meta
new file mode 100644
index 0000000..c6fa559
--- /dev/null
+++ b/Main/Config/PartialConfigs/ActTotDayRechargeTempConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 200643bb4766ae74fbb865f9583a43e0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs b/Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs
new file mode 100644
index 0000000..1c36c9e
--- /dev/null
+++ b/Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs
@@ -0,0 +1,59 @@
+using System.Collections.Generic;
+
+public partial class ActTotalRechargeTempConfig : ConfigBase<int, ActTotalRechargeTempConfig>
+{
+    // 妯℃澘缂栧彿: 濂栧姳绱㈠紩 :濂栧姳ID
+    private static Dictionary<int, Dictionary<int, int>> infoDict = new Dictionary<int, Dictionary<int, int>>();
+    // 妯℃澘缂栧彿 濂栧姳绱㈠紩
+    private static Dictionary<int, List<int>> sortDict = new Dictionary<int, List<int>>();
+    protected override void OnConfigParseCompleted()
+    {
+        if (!infoDict.TryGetValue(TemplateID, out var dict))
+        {
+            dict = new Dictionary<int, int>();
+            infoDict[TemplateID] = dict;
+        }
+        dict[AwardIndex] = AwardID;
+    }
+
+    private static void LoadSortList()
+    {
+        if (!sortDict.IsNullOrEmpty()) return;
+        foreach (var kvp in infoDict)
+        {
+            int templateID = kvp.Key;
+            List<int> list = new List<int>(kvp.Value.Keys);
+            list.Sort();
+            sortDict[templateID] = list;
+        }
+    }
+
+    public static List<int> GetAwardIndexSortList(int templateID)
+    {
+        LoadSortList();
+        sortDict.TryGetValue(templateID, out var list);
+        return list;
+    }
+    
+    public static Dictionary<int, int> GetTemplateIDDict(int templateID)
+    {
+        infoDict.TryGetValue(templateID, out var dict);
+        return dict;
+    }
+
+    public static int GetID(int templateID, int awardIndex)
+    {
+        var dict = GetTemplateIDDict(templateID);
+        if (dict == null) return 0;
+
+        dict.TryGetValue(awardIndex, out var id);
+        return id;
+    }
+
+    public static ActTotalRechargeTempConfig GetConfig(int templateID, int awardIndex)
+    {
+        int id = GetID(templateID, awardIndex);
+        return Get(id);
+    }
+
+}
\ No newline at end of file
diff --git a/Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs.meta b/Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs.meta
new file mode 100644
index 0000000..fd9d204
--- /dev/null
+++ b/Main/Config/PartialConfigs/ActTotalRechargeTempConfig.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c6b8fcbcc60e80f459e9b25121ff4f34
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Config/PartialConfigs/HorseSkinConfig.cs b/Main/Config/PartialConfigs/HorseSkinConfig.cs
index 216784e..d60ccd4 100644
--- a/Main/Config/PartialConfigs/HorseSkinConfig.cs
+++ b/Main/Config/PartialConfigs/HorseSkinConfig.cs
@@ -2,6 +2,11 @@
 public partial class HorseSkinConfig : ConfigBase<int, HorseSkinConfig>
 {
     public static List<int> itemsList = new List<int>(); //鐨偆閬撳叿瑙i攣/鍗囨槦
+    //鍧愰獞ID,鐨偆ID
+    public static Dictionary<int, int> horseIDTohorseSkinIDDict = new();
+    //鐨偆ID,鍧愰獞ID (鍙嶅悜鏄犲皠)
+    public static Dictionary<int, int> skinIDToHorseIDDict = new();
+    
     protected override void OnConfigParseCompleted()
     {
 
@@ -13,7 +18,12 @@
             }
         }
 
+        if (UnlockWay == 3)
+        {
+            horseIDTohorseSkinIDDict[UnlockValue] = SkinID;
+            skinIDToHorseIDDict[SkinID] = UnlockValue;
+        }
     }
 
-   
+
 }
diff --git a/Main/Config/PartialConfigs/PlayerPropertyConfig.cs b/Main/Config/PartialConfigs/PlayerPropertyConfig.cs
index aea6967..c5fefcc 100644
--- a/Main/Config/PartialConfigs/PlayerPropertyConfig.cs
+++ b/Main/Config/PartialConfigs/PlayerPropertyConfig.cs
@@ -107,6 +107,30 @@
         }
     }
 
+    public static string GetFullDescriptionOrgName(int id, long value, string format="{0}+{1}")
+    {
+        var config = Get(id);
+        if (config == null)
+        {
+            return string.Empty;
+        }
+
+        if (config.Name.Contains("%s"))
+        {
+            // if (id == 52)
+            // {
+            //     return Regex.Replace(config.ShowName, "%s", (value * 0.0001f).ToString("f2"));
+            // }
+            // else
+            {
+                return Regex.Replace(config.Name, "%s", value.ToString());
+            }
+        }
+        else
+        {
+            return string.Format(format, config.Name, GetValueDescription(id, value));
+        }
+    }
     //鍩虹灞炴�ф弿杩�
     public static string GetBaseFullDescription(int id, long value, string format = "{0}+{1}")
     {
diff --git a/Main/Core/GameEngine/Launch/AssetBundleInitTask.cs b/Main/Core/GameEngine/Launch/AssetBundleInitTask.cs
index 2d000cc..0c44328 100644
--- a/Main/Core/GameEngine/Launch/AssetBundleInitTask.cs
+++ b/Main/Core/GameEngine/Launch/AssetBundleInitTask.cs
@@ -36,9 +36,10 @@
 
     public override void End()
     {
-        expectTime = timer; 
+        expectTime = timer;
         // UILoader.LoadWindowAsync("LaunchBackGroundWin", null);
         Debug.LogFormat("{0}鎵ц鏃堕暱锛歿1}锛�", this.GetType().Name, timer);
+        OperationLogCollect.Instance.RecordLauchEvent(15);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs b/Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs
index c45a2ef..569115b 100644
--- a/Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs
+++ b/Main/Core/GameEngine/Launch/BuiltInAssetCopyTask.cs
@@ -77,6 +77,7 @@
         UIManager.Instance.CloseWindow<DownLoadWin>();
         UIManager.Instance.CloseWindow<VersionUpdateWin>();
         Language.InitDefaultLanguage();
+        OperationLogCollect.Instance.RecordLauchEvent(8);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/CheckAssetValidTask.cs b/Main/Core/GameEngine/Launch/CheckAssetValidTask.cs
index edc0453..319922b 100644
--- a/Main/Core/GameEngine/Launch/CheckAssetValidTask.cs
+++ b/Main/Core/GameEngine/Launch/CheckAssetValidTask.cs
@@ -66,6 +66,7 @@
         Debug.LogFormat("{0}鎵ц鏃堕暱锛歿1}锛�", this.GetType().Name, timer);
 
         GameNotice.OpenGameNotice();
+        OperationLogCollect.Instance.RecordLauchEvent(13);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/ConfigInitTask.cs b/Main/Core/GameEngine/Launch/ConfigInitTask.cs
index 662dbbe..0d0ca63 100644
--- a/Main/Core/GameEngine/Launch/ConfigInitTask.cs
+++ b/Main/Core/GameEngine/Launch/ConfigInitTask.cs
@@ -33,7 +33,7 @@
     {
         expectTime = timer;
         Debug.LogFormat("{0}鎵ц鏃堕暱锛歿1}锛�", this.GetType().Name, timer);
-        
+        OperationLogCollect.Instance.RecordLauchEvent(16);
         // TODO YYL
         // OperationLogCollect.Instance.RecordLauchEvent(3);
         // OperationLogCollect.Instance.RecordEvent(3);
diff --git a/Main/Core/GameEngine/Launch/DownLoadAssetTask.cs b/Main/Core/GameEngine/Launch/DownLoadAssetTask.cs
index c08b850..f90b1c1 100644
--- a/Main/Core/GameEngine/Launch/DownLoadAssetTask.cs
+++ b/Main/Core/GameEngine/Launch/DownLoadAssetTask.cs
@@ -45,6 +45,7 @@
         {
             AssetVersionUtility.BeginDownLoadTask(false);
         }
+        OperationLogCollect.Instance.RecordLauchEvent(14);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/GetVersionInfoTask.cs b/Main/Core/GameEngine/Launch/GetVersionInfoTask.cs
index f282146..da8ea3f 100644
--- a/Main/Core/GameEngine/Launch/GetVersionInfoTask.cs
+++ b/Main/Core/GameEngine/Launch/GetVersionInfoTask.cs
@@ -57,6 +57,7 @@
     {
         expectTime = timer;
         Debug.LogFormat("{0}鎵ц鏃堕暱锛歿1}锛�", this.GetType().Name, timer);
+        OperationLogCollect.Instance.RecordLauchEvent(12);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/InitSettingTask.cs b/Main/Core/GameEngine/Launch/InitSettingTask.cs
index dd0e105..ee29e0f 100644
--- a/Main/Core/GameEngine/Launch/InitSettingTask.cs
+++ b/Main/Core/GameEngine/Launch/InitSettingTask.cs
@@ -48,6 +48,7 @@
     public override void End()
     {
         expectTime = timer;
+        OperationLogCollect.Instance.RecordLauchEvent(10);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/LaunchFadeOutTask.cs b/Main/Core/GameEngine/Launch/LaunchFadeOutTask.cs
index 99d4d08..c015dff 100644
--- a/Main/Core/GameEngine/Launch/LaunchFadeOutTask.cs
+++ b/Main/Core/GameEngine/Launch/LaunchFadeOutTask.cs
@@ -52,7 +52,7 @@
         expectTime = timer;
         Debug.LogFormat("{0}鎵ц鏃堕暱锛歿1}锛�", this.GetType().Name, timer);
 
-
+        OperationLogCollect.Instance.RecordLauchEvent(17);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/LaunchInHot.cs b/Main/Core/GameEngine/Launch/LaunchInHot.cs
index 17d3c03..f77a2cb 100644
--- a/Main/Core/GameEngine/Launch/LaunchInHot.cs
+++ b/Main/Core/GameEngine/Launch/LaunchInHot.cs
@@ -63,6 +63,8 @@
             
         }
 
+        OperationLogCollect.Instance.RecordLauchEvent(7);
+
         // US1: Add YooAsset initialization task 鈥� replaces AssetBundleInitTask
         var yooAssetInitTask = new YooAssetInitTask();
         tasks.Enqueue(yooAssetInitTask);
diff --git a/Main/Core/GameEngine/Launch/RequestPermissionStart.cs b/Main/Core/GameEngine/Launch/RequestPermissionStart.cs
index ea92668..31818bd 100644
--- a/Main/Core/GameEngine/Launch/RequestPermissionStart.cs
+++ b/Main/Core/GameEngine/Launch/RequestPermissionStart.cs
@@ -37,6 +37,7 @@
 
     public override void End()
     {
+        OperationLogCollect.Instance.RecordLauchEvent(9);
     }
 
     public override void Update()
diff --git a/Main/Core/GameEngine/Launch/SDKInitedTask.cs b/Main/Core/GameEngine/Launch/SDKInitedTask.cs
index a76b3ff..f54598d 100644
--- a/Main/Core/GameEngine/Launch/SDKInitedTask.cs
+++ b/Main/Core/GameEngine/Launch/SDKInitedTask.cs
@@ -32,6 +32,7 @@
         var memory = 2048;
         DeviceUtility.GetCpuAndMemory(out cpu, out memory);
         Debug.LogFormat("鑾峰緱鏈哄櫒淇℃伅锛歝pu {0}----鍐呭瓨 {1}", cpu, memory);
+        OperationLogCollect.Instance.RecordLauchEvent(11);
 
     }
 
diff --git a/Main/Core/GameEngine/Player/PlayerBaseData.cs b/Main/Core/GameEngine/Player/PlayerBaseData.cs
index abc24d9..c9b1843 100644
--- a/Main/Core/GameEngine/Player/PlayerBaseData.cs
+++ b/Main/Core/GameEngine/Player/PlayerBaseData.cs
@@ -68,6 +68,7 @@
     public uint chatBox;    //鎵╁睍灞炴��10锛屽悇椤圭洰涓撶敤
     public uint ExAttr11;    //棰勭暀鐨勬墿灞曞睘鎬у瓧娈碉紝鐢ㄦ潵瀛樻斁椤圭洰鐗瑰畾鐨勫睘鎬�121 鐜伴噾浠e竵锛堜唬閲戝埜锛�
     public uint ExAttr16;    //棰勭暀鐨勬墿灞曞睘鎬у瓧娈碉紝鐢ㄦ潵瀛樻斁椤圭洰鐗瑰畾鐨勫睘鎬�    鍏ㄨ韩鐗规晥
+    public uint ExAttr17;   //璐﹀彿鐘舵�� 鎸変綅 4 灏佸彿 5绂佽█ 6绂佽澶�
     public uint ServerGroupId;    //鏈嶅姟鍣ㄧ粍ID
     public uint hangTime;//鐜颁负鑴辨満鎸傚墿浣欐椂闂� 23
     public uint faction; //闃佃惀 107
@@ -204,6 +205,7 @@
         ExAttr11 = _serverInfo.ExAttr11;
         leaveGuildInfo = (int)_serverInfo.ExAttr12;
         ExAttr16 = _serverInfo.ExAttr16;
+        ExAttr17 = _serverInfo.ExAttr17;
         ServerGroupId = _serverInfo.ExAttr13;
         faction = _serverInfo.Faction;
         coinPointTotal = _serverInfo.ChangeCoinPointTotal;
diff --git a/Main/Core/GameEngine/Player/PlayerDatas.cs b/Main/Core/GameEngine/Player/PlayerDatas.cs
index 7508276..8408313 100644
--- a/Main/Core/GameEngine/Player/PlayerDatas.cs
+++ b/Main/Core/GameEngine/Player/PlayerDatas.cs
@@ -437,6 +437,9 @@
             case PlayerDataType.CDBPlayerRefresh_ZhuxianRate:
                 baseData.ExAttr16 = value;
                 break;
+            case PlayerDataType.default1:
+                baseData.ExAttr17 = value;
+                break;
             case PlayerDataType.CDBPlayerRefresh_Mater:
                 baseData.mater = (int)value;
                 break;
diff --git a/Main/Core/NetworkPackage/ClientPack/CA1_Sys/CA130_tagCMViewBillboard.cs b/Main/Core/NetworkPackage/ClientPack/CA1_Sys/CA130_tagCMViewBillboard.cs
index 862cfff..558594a 100644
--- a/Main/Core/NetworkPackage/ClientPack/CA1_Sys/CA130_tagCMViewBillboard.cs
+++ b/Main/Core/NetworkPackage/ClientPack/CA1_Sys/CA130_tagCMViewBillboard.cs
@@ -1,15 +1,16 @@
-using UnityEngine;
-using System.Collections;
-
+using UnityEngine;
+using System.Collections;
+
 // A1 30 鏌ョ湅姒滃崟 #tagCMViewBillboard
 
 public class CA130_tagCMViewBillboard : GameNetPackBasic {
     public byte Type;    //姒滃崟绫诲瀷
     public uint GroupValue1;    //鍒嗙粍鍊�1
     public uint GroupValue2;    //鍒嗙粍鍊�2锛屼笌鍒嗙粍鍊�1缁勫悎褰掍负鍚岀粍姒滃崟鏁版嵁
-    public ushort StartIndex;    //鏌ョ湅鐨勮捣濮嬬储寮曪紝 榛樿0  闈炲悕娆�
-    public byte ViewCnt;    //鏌ョ湅鏉℃暟锛岄粯璁�20锛屽崟娆℃渶澶т笉瓒呰繃100锛屽拰StartIndex鍏宠仈
-    public uint ViewID;    //闄勫甫鏌ョ湅鎸囧畾ID鎵�鍦ㄥ悕娆″墠鍚庢暟鎹紝濡傜帺瀹禝D銆佸鏃廔D绛夛紝涓嶸iewCnt鏃犲叧锛屾湇鍔$鍥哄畾杩斿洖鏉℃暟
+    public ushort StartIndex;    //鏌ョ湅鐨勮捣濮嬪悕娆$储寮曪紝 榛樿0
+    public byte ViewCnt;    //鏌ョ湅鏉℃暟锛岄粯璁�20锛屽崟娆℃渶澶т笉瓒呰繃100
+    public uint ViewID;    //闄勫甫鏌ョ湅鎸囧畾ID鎵�鍦ㄥ悕娆″墠鍚庢暟鎹紝濡傜帺瀹禝D銆佸鏃廔D绛�
+    public uint CrossServerID;    //璺ㄦ湇姒滄椂闇�鍙戦�佹墍灞炶法鏈嶆湇鍔″櫒ID锛�0榛樿鏈湇
 
     public CA130_tagCMViewBillboard () {
         combineCmd = (ushort)0x03FE;
@@ -23,6 +24,7 @@
         WriteBytes (StartIndex, NetDataType.WORD);
         WriteBytes (ViewCnt, NetDataType.BYTE);
         WriteBytes (ViewID, NetDataType.DWORD);
+        WriteBytes (CrossServerID, NetDataType.DWORD);
     }
 
 }
diff --git a/Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs b/Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs
new file mode 100644
index 0000000..8aa87d6
--- /dev/null
+++ b/Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs
@@ -0,0 +1,20 @@
+using UnityEngine;
+using System.Collections;
+
+// B2 04 鍧愰獞ID鎿嶄綔 #tagCSHorseIDOP
+
+public class CB204_tagCSHorseIDOP : GameNetPackBasic {
+    public byte OPType;    // 鎿嶄綔 1-婵�娲伙紱2-浣╂埓锛�
+    public byte HorseID;
+
+    public CB204_tagCSHorseIDOP () {
+        combineCmd = (ushort)0x03FE;
+        _cmd = (ushort)0xB204;
+    }
+
+    public override void WriteToBytes () {
+        WriteBytes (OPType, NetDataType.BYTE);
+        WriteBytes (HorseID, NetDataType.BYTE);
+    }
+
+}
diff --git a/Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs.meta b/Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs.meta
new file mode 100644
index 0000000..fe8b561
--- /dev/null
+++ b/Main/Core/NetworkPackage/ClientPack/CB2_NewFunction/CB204_tagCSHorseIDOP.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 89a08c975b158c54eac484cba180a62b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/H01_System/DTC0104_tagServerDisconnect.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/H01_System/DTC0104_tagServerDisconnect.cs
index 6b6d58d..ddb0667 100644
--- a/Main/Core/NetworkPackage/DTCFile/ServerPack/H01_System/DTC0104_tagServerDisconnect.cs
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/H01_System/DTC0104_tagServerDisconnect.cs
@@ -13,8 +13,12 @@
         try
         {
             Debug.Log("DTC0104_tagServerDisconnect" + vNetData.Reason);
-
             ServerForceExitHintWin.reason = vNetData.Reason;
+            // 鍜岀鍥涗綅涓庨潪0 鍒欐槸灏佸彿
+            if ((PlayerDatas.Instance.baseData.ExAttr17 & (1 << 4)) != 0)
+            {
+                ServerForceExitHintWin.reason = 51;
+            }
             LoginManager.Instance.busy = false;
             VersionConfig.GetAsync().ContinueWith(config =>
             {
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs
new file mode 100644
index 0000000..717442d
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs
@@ -0,0 +1,14 @@
+using UnityEngine;
+using System.Collections;
+
+// A3 05 鍧愰獞ID淇℃伅 #tagSCHorseIDInfo
+
+public class DTCA305_tagSCHorseIDInfo : DtcBasic
+{
+    public override void Done(GameNetPackBasic vNetPack)
+    {
+        base.Done(vNetPack);
+        HA305_tagSCHorseIDInfo vNetData = vNetPack as HA305_tagSCHorseIDInfo;
+        HorseManager.Instance.UpdateHorseIDInfo(vNetData);
+    }
+}
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs.meta b/Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs.meta
new file mode 100644
index 0000000..2eaa2a8
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA305_tagSCHorseIDInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 24c3deaa0b65c2f45a4f0d7a0cfda6ee
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs
new file mode 100644
index 0000000..58c7e01
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs
@@ -0,0 +1,14 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1A 绱厖澶╂椿鍔ㄧ帺瀹朵俊鎭� #tagSCActTotDayRechargePlayerInfo
+
+public class DTCAA1A_tagSCActTotDayRechargePlayerInfo : DtcBasic
+{
+    public override void Done(GameNetPackBasic vNetPack)
+    {
+        base.Done(vNetPack);
+        HAA1A_tagSCActTotDayRechargePlayerInfo vNetData = vNetPack as HAA1A_tagSCActTotDayRechargePlayerInfo;
+        TotDayRechargeManager.Instance.UpdateTotDayRechargePlayerInfo(vNetData);
+    }
+}
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta
new file mode 100644
index 0000000..8001d55
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ff910fd4544f88147a8ac9ebe5d54a6c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs
new file mode 100644
index 0000000..0d452f5
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs
@@ -0,0 +1,12 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1B 绱厖澶╂椿鍔ㄤ俊鎭� #tagSCActTotDayRechargeInfo
+
+public class DTCAA1B_tagSCActTotDayRechargeInfo : DtcBasic {
+    public override void Done(GameNetPackBasic vNetPack) {
+        base.Done(vNetPack);
+        HAA1B_tagSCActTotDayRechargeInfo vNetData = vNetPack as HAA1B_tagSCActTotDayRechargeInfo;
+        OperationTimeHepler.Instance.UpdateActTotDayRechargeInfo(vNetData);
+    }
+}
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs.meta b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs.meta
new file mode 100644
index 0000000..60e3430
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1B_tagSCActTotDayRechargeInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2ab40d2df9df70846b324d89389c5fb7
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs
new file mode 100644
index 0000000..15cb47b
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs
@@ -0,0 +1,12 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1C 绱厖娲诲姩鐜╁淇℃伅 #tagSCActTotalRechargePlayerInfo
+
+public class DTCAA1C_tagSCActTotalRechargePlayerInfo : DtcBasic {
+    public override void Done(GameNetPackBasic vNetPack) {
+        base.Done(vNetPack);
+        HAA1C_tagSCActTotalRechargePlayerInfo vNetData = vNetPack as HAA1C_tagSCActTotalRechargePlayerInfo;
+        TotalRechargeManager.Instance.UpdateTotalRechargePlayerInfo(vNetData);
+    }
+}
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs.meta b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs.meta
new file mode 100644
index 0000000..b3e6cd0
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1C_tagSCActTotalRechargePlayerInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8bf165379885e0a4685dd17c772c34c2
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs
new file mode 100644
index 0000000..779c964
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs
@@ -0,0 +1,14 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1D 绱厖娲诲姩淇℃伅 #tagSCActTotalRechargeInfo
+
+public class DTCAA1D_tagSCActTotalRechargeInfo : DtcBasic
+{
+    public override void Done(GameNetPackBasic vNetPack)
+    {
+        base.Done(vNetPack);
+        HAA1D_tagSCActTotalRechargeInfo vNetData = vNetPack as HAA1D_tagSCActTotalRechargeInfo;
+        OperationTimeHepler.Instance.UpdateActTotalRechargeInfo(vNetData);
+    }
+}
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs.meta b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs.meta
new file mode 100644
index 0000000..aab4fce
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HAA_SaleActivity/DTCAA1D_tagSCActTotalRechargeInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a9b1c15e1cc65e940a9e3c967001c7cd
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm.meta b/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm.meta
new file mode 100644
index 0000000..a05bcee
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e7faa43c224a58d489d17e76866fa935
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs
new file mode 100644
index 0000000..1951c2d
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs
@@ -0,0 +1,12 @@
+using UnityEngine;
+using System.Collections;
+
+// C0 10 璺ㄦ湇鍔熻兘鎵�灞炲垎鍖� #tagSCCrossZoneInfo
+
+public class DTCC010_tagSCCrossZoneInfo : DtcBasic {
+    public override void Done(GameNetPackBasic vNetPack) {
+        base.Done(vNetPack);
+        HC010_tagSCCrossZoneInfo vNetData = vNetPack as HC010_tagSCCrossZoneInfo;
+        CrossServerBaseManager.Instance.UpdateSCCrossZoneInfo(vNetData);
+    }
+}
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs.meta b/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs.meta
new file mode 100644
index 0000000..eeabfad
--- /dev/null
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/HC0_CrossRealm/DTCC010_tagSCCrossZoneInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9b77e3d6c1900db4995c9d2fab85f831
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs b/Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
index e0253d2..270cccc 100644
--- a/Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
+++ b/Main/Core/NetworkPackage/DataToCtl/PackageRegedit.cs
@@ -161,6 +161,12 @@
         Register(typeof(HAA22_tagSCActHeroAppearPlayerInfo), typeof(DTCAA22_tagSCActHeroAppearPlayerInfo));
         Register(typeof(HA924_tagSCQunyingMatchList), typeof(DTCA924_tagSCQunyingMatchList));
         Register(typeof(HA925_tagSCQunyingPlayerInfo), typeof(DTCA925_tagSCQunyingPlayerInfo));
+        Register(typeof(HC010_tagSCCrossZoneInfo), typeof(DTCC010_tagSCCrossZoneInfo));
+        Register(typeof(HA305_tagSCHorseIDInfo), typeof(DTCA305_tagSCHorseIDInfo));
+        Register(typeof(HAA1A_tagSCActTotDayRechargePlayerInfo), typeof(DTCAA1A_tagSCActTotDayRechargePlayerInfo));
+        Register(typeof(HAA1B_tagSCActTotDayRechargeInfo), typeof(DTCAA1B_tagSCActTotDayRechargeInfo));
+        Register(typeof(HAA1C_tagSCActTotalRechargePlayerInfo), typeof(DTCAA1C_tagSCActTotalRechargePlayerInfo));
+        Register(typeof(HAA1D_tagSCActTotalRechargeInfo), typeof(DTCAA1D_tagSCActTotalRechargeInfo));
     }
 
     //涓诲伐绋嬫敞鍐屽皝鍖�
diff --git a/Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs b/Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs
new file mode 100644
index 0000000..7446554
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs
@@ -0,0 +1,19 @@
+using UnityEngine;
+using System.Collections;
+
+// A3 05 鍧愰獞ID淇℃伅 #tagSCHorseIDInfo
+
+public class HA305_tagSCHorseIDInfo : GameNetPackBasic {
+    public uint HorseIDState;    // 鍧愰獞ID瑙i攣鐘舵�侊紝鎸変簩杩涘埗浣嶈繍绠楀垽鏂潗楠慖D鏄惁宸茶В閿�
+    public byte HorseID;    // 褰撳墠浣╂埓鐨勫潗楠慖D
+
+    public HA305_tagSCHorseIDInfo () {
+        _cmd = (ushort)0xA305;
+    }
+
+    public override void ReadFromBytes (byte[] vBytes) {
+        TransBytes (out HorseIDState, vBytes, NetDataType.DWORD);
+        TransBytes (out HorseID, vBytes, NetDataType.BYTE);
+    }
+
+}
diff --git a/Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs.meta b/Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs.meta
new file mode 100644
index 0000000..d21f5a6
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HA3_Function/HA305_tagSCHorseIDInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 38ac993795b713545bc24a1fce151d67
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs
new file mode 100644
index 0000000..bae4046
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs
@@ -0,0 +1,21 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1A 绱厖澶╂椿鍔ㄧ帺瀹朵俊鎭� #tagSCActTotDayRechargePlayerInfo
+
+public class HAA1A_tagSCActTotDayRechargePlayerInfo : GameNetPackBasic {
+    public byte ActNum;    //娲诲姩缂栧彿
+    public byte TotalDays;    //娲诲姩绱厖澶╂暟
+    public uint AwardRecord;    //绱厖澶╁鍔遍濂栬褰曪紝鎸夊ぉ浜岃繘鍒朵綅瀛樺偍鏄惁宸查鍙�
+
+    public HAA1A_tagSCActTotDayRechargePlayerInfo () {
+        _cmd = (ushort)0xAA1A;
+    }
+
+    public override void ReadFromBytes (byte[] vBytes) {
+        TransBytes (out ActNum, vBytes, NetDataType.BYTE);
+        TransBytes (out TotalDays, vBytes, NetDataType.BYTE);
+        TransBytes (out AwardRecord, vBytes, NetDataType.DWORD);
+    }
+
+}
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta
new file mode 100644
index 0000000..e95cb46
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1A_tagSCActTotDayRechargePlayerInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d69e237c7851de84ab85e666d561e809
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs
new file mode 100644
index 0000000..2eb3f93
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1B 绱厖澶╂椿鍔ㄤ俊鎭� #tagSCActTotDayRechargeInfo
+
+public class HAA1B_tagSCActTotDayRechargeInfo : GameNetPackBasic {
+    public byte ActNum;    // 娲诲姩缂栧彿
+    public string StartDate;    // 寮�濮嬫棩鏈� y-m-d
+    public string EndtDate;    // 缁撴潫鏃ユ湡 y-m-d
+    public ushort CfgID;    // 娲诲姩鏃堕棿琛ㄩ厤缃甀D
+
+    public HAA1B_tagSCActTotDayRechargeInfo () {
+        _cmd = (ushort)0xAA1B;
+    }
+
+    public override void ReadFromBytes (byte[] vBytes) {
+        TransBytes (out ActNum, vBytes, NetDataType.BYTE);
+        TransBytes (out StartDate, vBytes, NetDataType.Chars, 10);
+        TransBytes (out EndtDate, vBytes, NetDataType.Chars, 10);
+        TransBytes (out CfgID, vBytes, NetDataType.WORD);
+    }
+
+}
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs.meta b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs.meta
new file mode 100644
index 0000000..37561d1
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1B_tagSCActTotDayRechargeInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 98ba7407ed7fd9e4eac77a6e39e53bce
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs
new file mode 100644
index 0000000..e9e5af8
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs
@@ -0,0 +1,21 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1C 绱厖娲诲姩鐜╁淇℃伅 #tagSCActTotalRechargePlayerInfo
+
+public class HAA1C_tagSCActTotalRechargePlayerInfo : GameNetPackBasic {
+    public byte ActNum;    //娲诲姩缂栧彿
+    public uint CoinTotal;    //娲诲姩绱鍏呭�奸coin鍊�
+    public uint AwardRecord;    //绱厖濂栧姳棰嗗璁板綍锛屾寜濂栧姳绱㈠紩浜岃繘鍒朵綅瀛樺偍鏄惁宸查鍙�
+
+    public HAA1C_tagSCActTotalRechargePlayerInfo () {
+        _cmd = (ushort)0xAA1C;
+    }
+
+    public override void ReadFromBytes (byte[] vBytes) {
+        TransBytes (out ActNum, vBytes, NetDataType.BYTE);
+        TransBytes (out CoinTotal, vBytes, NetDataType.DWORD);
+        TransBytes (out AwardRecord, vBytes, NetDataType.DWORD);
+    }
+
+}
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs.meta b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs.meta
new file mode 100644
index 0000000..f24772e
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1C_tagSCActTotalRechargePlayerInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 041f64014b18e6340be4b4c2f63f2a8d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs
new file mode 100644
index 0000000..87d4722
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs
@@ -0,0 +1,23 @@
+using UnityEngine;
+using System.Collections;
+
+// AA 1D 绱厖娲诲姩淇℃伅 #tagSCActTotalRechargeInfo
+
+public class HAA1D_tagSCActTotalRechargeInfo : GameNetPackBasic {
+    public byte ActNum;    // 娲诲姩缂栧彿
+    public string StartDate;    // 寮�濮嬫棩鏈� y-m-d
+    public string EndtDate;    // 缁撴潫鏃ユ湡 y-m-d
+    public ushort CfgID;    // 娲诲姩鏃堕棿琛ㄩ厤缃甀D
+
+    public HAA1D_tagSCActTotalRechargeInfo () {
+        _cmd = (ushort)0xAA1D;
+    }
+
+    public override void ReadFromBytes (byte[] vBytes) {
+        TransBytes (out ActNum, vBytes, NetDataType.BYTE);
+        TransBytes (out StartDate, vBytes, NetDataType.Chars, 10);
+        TransBytes (out EndtDate, vBytes, NetDataType.Chars, 10);
+        TransBytes (out CfgID, vBytes, NetDataType.WORD);
+    }
+
+}
diff --git a/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs.meta b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs.meta
new file mode 100644
index 0000000..75b10b3
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA1D_tagSCActTotalRechargeInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8e1a6e96357ef3e4e91707b9a141f552
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB431_tagSCTurnFightRet.cs b/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB431_tagSCTurnFightRet.cs
index 0296a8b..af94ee2 100644
--- a/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB431_tagSCTurnFightRet.cs
+++ b/Main/Core/NetworkPackage/ServerPack/HB4_FightDefine/HB431_tagSCTurnFightRet.cs
@@ -17,6 +17,7 @@
     public string BatStatMsg;    //鎴樻枟鐩稿叧缁熻淇℃伅
     public string PathDate;    //鎴樻姤璺緞鏃ユ湡, yyyyMMdd, 涓虹┖鏃朵唬琛ㄥ叕鍏辩被鐨勬垬鎶ワ紝涓嶄负绌烘椂涓虹帺瀹朵釜浜虹被鎴樻姤
     public string GUID;    //鎴樻姤guid锛屽墠绔牴鎹姛鑳組apID鍒ゆ柇鏄惁璺ㄦ湇鍔熻兘锛屾槸鐨勮瘽浠庤法鏈嶆湇鍔″櫒涓嬭浇鎴樻姤锛屽惁鐨勮瘽浠庢湰鏈嶄笅杞�
+    public uint CrossServerID;    //鎴樻姤鎵�鍦ㄨ法鏈岻D锛屾湰鏈嶆椂涓�0
 
     public HB431_tagSCTurnFightRet () {
         _cmd = (ushort)0xB431;
@@ -36,6 +37,7 @@
         TransBytes (out BatStatMsg, vBytes, NetDataType.Chars, BatLen);
         TransBytes (out PathDate, vBytes, NetDataType.Chars, 8);
         TransBytes (out GUID, vBytes, NetDataType.Chars, 40);
+        TransBytes (out CrossServerID, vBytes, NetDataType.DWORD);
     }
 
 }
diff --git a/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm.meta b/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm.meta
new file mode 100644
index 0000000..5d91960
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 15e37157e4f2d9045aaf5e0f0166f99b
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs b/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs
new file mode 100644
index 0000000..c50586b
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs
@@ -0,0 +1,25 @@
+using UnityEngine;
+using System.Collections;
+
+// C0 10 璺ㄦ湇鍔熻兘鎵�灞炲垎鍖� #tagSCCrossZoneInfo
+
+public class HC010_tagSCCrossZoneInfo : GameNetPackBasic {
+    public uint MapID;    // 鍔熻兘鍦板浘ID锛屾湁鏀跺埌璇ュ皝鍖呮椂浠h〃璇ュ姛鑳藉紑濮嬭法鏈嶄簡锛屼絾骞朵笉涓�瀹氭湁鍒嗗尯浜掗�氫俊鎭紝鍙兘澶勪簬鍒嗛厤闃舵
+    public uint CrossServerID;    // 鎵�灞炶法鏈嶆湇鍔″櫒ID
+    public uint ZoneID;    // 鎵�灞炲垎鍖猴紝鍙兘涓�0
+    public ushort ServerCnt;
+    public  uint[] ServerIDList;    // 浜掗�氭湇鍔″櫒ID鍒楄〃锛屽彲鑳戒负绌�
+
+    public HC010_tagSCCrossZoneInfo () {
+        _cmd = (ushort)0xC010;
+    }
+
+    public override void ReadFromBytes (byte[] vBytes) {
+        TransBytes (out MapID, vBytes, NetDataType.DWORD);
+        TransBytes (out CrossServerID, vBytes, NetDataType.DWORD);
+        TransBytes (out ZoneID, vBytes, NetDataType.DWORD);
+        TransBytes (out ServerCnt, vBytes, NetDataType.WORD);
+        TransBytes (out ServerIDList, vBytes, NetDataType.DWORD, ServerCnt);
+    }
+
+}
diff --git a/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs.meta b/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs.meta
new file mode 100644
index 0000000..c90388f
--- /dev/null
+++ b/Main/Core/NetworkPackage/ServerPack/HC0_CrossRealm/HC010_tagSCCrossZoneInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dd35c1a0622229f468c39e902fdfc3af
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/Main.cs b/Main/Main.cs
index 481b314..4cbc618 100644
--- a/Main/Main.cs
+++ b/Main/Main.cs
@@ -65,6 +65,7 @@
         SysNotifyMgr.Instance.BeforePlayerDataInitializeEvent();
 #endif
         StageManager.Instance.ToLoginScene().Forget();
+        OperationLogCollect.Instance.RecordLauchEvent(18);
     }
 
     public static async UniTask InitManagers()
@@ -139,6 +140,10 @@
         managers.Add(QunyingManager.Instance);
         managers.Add(ViewBuffManager.Instance);
         managers.Add(HeroReturnManager.Instance);
+        managers.Add(CrossServerBaseManager.Instance);
+        managers.Add(TotalRechargeManager.Instance);
+        managers.Add(TotDayRechargeManager.Instance);
+
 
         foreach (var manager in managers)
         {
diff --git a/Main/SDK/SDKUtils.cs b/Main/SDK/SDKUtils.cs
index a839df2..2c5891b 100644
--- a/Main/SDK/SDKUtils.cs
+++ b/Main/SDK/SDKUtils.cs
@@ -529,7 +529,6 @@
                 {
                     Yj_BanHao = _json["banhao"].ToString();
                 }
-
                 break;
             case CodeA2U.PushClientID:
                 RegistrationID = _json["clientID"].ToString();
@@ -553,7 +552,6 @@
                     break;
                 }
             case CodeA2U.FreePlatformInitOk:
-
                 if (_json.Keys.Contains("channelSign"))
                 {
                     channelSign = _json["channelSign"].ToString();
@@ -562,13 +560,14 @@
                 {
                     onFreePlatformInitOk();
                 }
-
+                OperationLogCollect.Instance.RecordLauchEvent(101);
                 break;
             case CodeA2U.FreePlatformInitFail:
                 if (onFreePlatformInitFail != null)
                 {
                     onFreePlatformInitFail();
                 }
+                OperationLogCollect.Instance.RecordLauchEvent(102);
                 break;
             case CodeA2U.FreePlatformRegisterOk:
                 // HandleFreePlatformRegisteOk(_json);
@@ -579,6 +578,7 @@
                 break;
             case CodeA2U.FreePlatformLoginOk:
                 HandleFreePlatformLoginOk(_json["info"]);
+                OperationLogCollect.Instance.RecordLauchEvent(103);
                 // OperationLogCollect.Instance.RecordEvent(6);
                 break;
             case CodeA2U.FreePlatformLoginFail:
@@ -586,6 +586,7 @@
                 {
                     onFreePlatformLoginFail();
                 }
+                OperationLogCollect.Instance.RecordLauchEvent(104);
                 break;
             case CodeA2U.FreePlatformLogoutOk:
                 if (onFreePlatformLogoutOk != null)
@@ -654,7 +655,6 @@
                 if (AdsManager.Instance.waitAdID > 0)
                 {
                     AdsManager.Instance.GetAdsAward(AdsManager.Instance.waitAdID);
-                    AdsManager.Instance.waitAdID = 0;
                 }
                 break;
             case CodeA2U.AdLoadFail:
diff --git a/Main/System/AssetVersion/InGameDownLoad.cs b/Main/System/AssetVersion/InGameDownLoad.cs
index f4a1f92..8601a66 100644
--- a/Main/System/AssetVersion/InGameDownLoad.cs
+++ b/Main/System/AssetVersion/InGameDownLoad.cs
@@ -95,6 +95,13 @@
         DownloadHotMgr.MaxDownLoadTask = GetMaxTask();
     }
 
+    
+    public async UniTask  OnPlayerLoginOk()
+    {
+        await UniTask.Delay(1000);
+        OnPlayerLevelChange(PlayerDataType.LV);
+    }
+
     private void LateUpdate()
     {
         if (state == State.None || state == State.Award || state == State.Completed)
@@ -564,8 +571,8 @@
         {
             case PlayerDataType.LV:
                 var level = PlayerDatas.Instance.baseData.LV;
-                var count = GeneralDefine.inGameDownLoadLevelCheckPoints.Count;
-                var lastLevelCheckPoint = GeneralDefine.inGameDownLoadLevelCheckPoints[count - 1];
+                // var count = GeneralDefine.inGameDownLoadLevelCheckPoints.Count;
+                // var lastLevelCheckPoint = GeneralDefine.inGameDownLoadLevelCheckPoints[count - 1];
                 if (GeneralDefine.inGameDownLoadLevelCheckPoints.Contains(level) || IsHighLevelPlayer())
                 {
                     if (CheckDominantDownLoad())
diff --git a/Main/System/Attribute/AttributeManager.cs b/Main/System/Attribute/AttributeManager.cs
index 3b3d2e1..dae6e8b 100644
--- a/Main/System/Attribute/AttributeManager.cs
+++ b/Main/System/Attribute/AttributeManager.cs
@@ -79,7 +79,7 @@
             if (!PlayerPropertyConfig.HasKey(kvp.Key))
                 continue;
             PlayerPropertyConfig config = PlayerPropertyConfig.Get(kvp.Key);
-            if (kvp.Value > 0 && config.showType > 0 && config.showType < 5)
+            if (kvp.Value > 0 && config.showType > 0)
             {
                 result.Add(kvp.Key, kvp.Value);
             }
@@ -110,7 +110,11 @@
             int showTypeB = configB?.showType ?? 0;
 
             if (showTypeA != showTypeB)
-                return showTypeA.CompareTo(showTypeB);
+            {
+                int priorityA = GetShowTypePriority(showTypeA);
+                int priorityB = GetShowTypePriority(showTypeB);
+                return priorityA.CompareTo(priorityB);
+            }
 
             int showSequenceA = configA?.showSequence ?? 0;
             int showSequenceB = configB?.showSequence ?? 0;
@@ -121,4 +125,22 @@
         });
         return list;
     }
+
+    /// <summary>
+    /// 鑾峰彇showType鐨勪紭鍏堟潈锛屽�艰秺灏忚秺闈犲墠
+    /// 浼樺厛鏉冮『搴忥細[1,6,2,3,4,5]锛屽叾浠栧�兼帓鍦ㄦ渶鍚�
+    /// </summary>
+    private int GetShowTypePriority(int showType)
+    {
+        return showType switch
+        {
+            1 => 0,   // 鏈�楂樹紭鍏堟潈
+            6 => 1,
+            2 => 2,
+            3 => 3,
+            4 => 4,
+            5 => 5,
+            _ => 999  // 鏈畾涔夌殑showType鎺掑湪鏈�鍚�
+        };
+    }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/BattleDebug.cs b/Main/System/Battle/BattleDebug.cs
index c51b6c2..38e32e1 100644
--- a/Main/System/Battle/BattleDebug.cs
+++ b/Main/System/Battle/BattleDebug.cs
@@ -3,12 +3,52 @@
 
 public static class BattleDebug
 {
+#if UNITY_EDITOR
+	// 姣忔 Editor 杩涘叆 PlayMode 浼氶噸缃繖涓� static锛屽垵娆¤皟鐢ㄦ椂娓呯┖鏃ф枃浠�
+	private static bool _logFileInitialized = false;
+	private static string _logFilePath;
+
+	private static void EnsureLogFile()
+	{
+		if (_logFileInitialized) return;
+		_logFileInitialized = true;
+		try
+		{
+			string dir = Application.dataPath + "/../BattleReport";
+			if (!System.IO.Directory.Exists(dir))
+				System.IO.Directory.CreateDirectory(dir);
+			_logFilePath = dir + "/BattleDebug.log";
+			// 姣忔鍚姩 PlayMode 娓呯┖鏂囦欢锛岄伩鍏嶈法娆℃薄鏌�
+			System.IO.File.WriteAllText(_logFilePath, $"=== BattleDebug log opened at {System.DateTime.Now:HH:mm:ss.fff} ===\n");
+		}
+		catch (System.Exception e)
+		{
+			Debug.LogWarning("BattleDebug 鎵撳紑鏃ュ織鏂囦欢澶辫触锛�" + e.Message);
+			_logFilePath = null;
+		}
+	}
+
+	private static void WriteToFile(string line)
+	{
+		EnsureLogFile();
+		if (string.IsNullOrEmpty(_logFilePath)) return;
+		try
+		{
+			System.IO.File.AppendAllText(_logFilePath,
+				$"[{Time.frameCount} {Time.realtimeSinceStartup:F3}] " + line + "\n");
+		}
+		catch { /* 蹇界暐鏂囦欢鍐欏叆寮傚父锛屽埆褰卞搷閫昏緫 */ }
+	}
+#endif
+
 	public static void LogError(string _logMessage)
 	{
 #if UNITY_EDITOR
-		if (Launch.Instance.isOpenBattleDebug)
+		if (Launch.Instance != null && Launch.Instance.isOpenBattleDebug)
 		{
 			Debug.LogWarning("BattleLog: " + _logMessage);
+			if (Launch.Instance.isOpenBattleDebugLogFile)
+				WriteToFile(_logMessage);
 		}
 #elif UNITY_WEBGL && !UNITY_EDITOR
 		WebGLDebug.LogError("BattleLog: " + _logMessage);
diff --git a/Main/System/Battle/BattleField/BattleField.cs b/Main/System/Battle/BattleField/BattleField.cs
index 3c8fae0..8bbfecc 100644
--- a/Main/System/Battle/BattleField/BattleField.cs
+++ b/Main/System/Battle/BattleField/BattleField.cs
@@ -121,6 +121,21 @@
 
         if (castingSkillDict.TryGetValue(objID, out skillBases))
         {
+#if UNITY_EDITOR
+            //  璇婃柇锛氬悓涓�涓� caster 宸茬粡鍦� casting锛岃鏄庡墠涓�涓妧鑳芥病姝g‘ Remove銆�
+            //  鎵撳嵃鐜板瓨鎶�鑳界殑 skillId / StateFlags锛屾柟渚垮畾浣嶆硠婕忕偣銆�
+            var sb = new System.Text.StringBuilder();
+            sb.Append("BattleField.AddCastingSkill 鍙戠幇鍚� caster 宸叉湁 ").Append(skillBases.Count).Append(" 涓� casting 鎶�鑳芥湭娓呯悊锛歰bjID=").Append(objID);
+            sb.Append("  鏂板叆=skillId=").Append(skill?.skillConfig?.SkillID ?? 0);
+            for (int i = 0; i < skillBases.Count; i++)
+            {
+                var s = skillBases[i];
+                sb.Append("\n    [").Append(i).Append("] skillId=")
+                  .Append(s?.skillConfig?.SkillID ?? 0)
+                  .Append(" StateFlags=").Append(s == null ? "null" : s.StateFlagsForDebug.ToString());
+            }
+            BattleDebug.LogError(sb.ToString());
+#endif
             skillBases.Add(skill);
         }
         else
@@ -137,6 +152,13 @@
 
         if (castingSkillDict.TryGetValue(objID, out skillBases))
         {
+#if UNITY_EDITOR
+            bool existed = skillBases.Contains(skillBase);
+            if (!existed)
+            {
+                BattleDebug.LogError($"BattleField.RemoveCastingSkill 鐩爣涓嶅湪 casting 鍒楄〃锛歰bjID={objID} skillId={skillBase?.skillConfig?.SkillID ?? 0}");
+            }
+#endif
             skillBases.Remove(skillBase);
 
             if (skillBases.Count == 0)
@@ -144,6 +166,12 @@
                 castingSkillDict.Remove(objID);
             }
         }
+#if UNITY_EDITOR
+        else
+        {
+            BattleDebug.LogError($"BattleField.RemoveCastingSkill objID 涓嶅湪瀛楀吀閲岋細objID={objID} skillId={skillBase?.skillConfig?.SkillID ?? 0}");
+        }
+#endif
     }
 
     public bool IsCastingSkill(long objID)
@@ -861,6 +889,9 @@
 
         // 娓呯悊姝讳骸澶勭悊璁板綍
         processingDeathObjIds.Clear();
+
+        // 娓呯┖褰撳墠鎴樺満鐨勮閲忚褰�
+        BattleHeroInfoBar.ClearStaticBattleData(guid);
     }
 
     public bool IsBattleEnd()
diff --git a/Main/System/Battle/BattleObject/BattleObject.cs b/Main/System/Battle/BattleObject/BattleObject.cs
index b30a55c..12f5dd3 100644
--- a/Main/System/Battle/BattleObject/BattleObject.cs
+++ b/Main/System/Battle/BattleObject/BattleObject.cs
@@ -41,6 +41,10 @@
         battleField = _battleField;
     }
 
+    //  SkillBase.MoveToTarget 鍙戣捣鐨勫墠鍐� / 鍥炰綅 tween 鍙ユ焺锛堢敱 SkillBase 缁存姢锛夈��
+    //  CanCastSkillAnimation 鍙垽鏂繖涓�涓彞鏌勶紝閬垮厤璇激 caster 韬笂鍏跺畠涓氬姟 tween銆�
+    public Tween activeMoveTween;
+
     // ============ 鎶借薄璁块棶鏂规硶锛堝瓙绫昏繑鍥炲悇鑷殑Team绫诲瀷淇℃伅锛� ============
     
     public abstract int GetPositionNum();
diff --git a/Main/System/Battle/BattleObject/HeroBattleObject.cs b/Main/System/Battle/BattleObject/HeroBattleObject.cs
index 150d8ff..0e8f011 100644
--- a/Main/System/Battle/BattleObject/HeroBattleObject.cs
+++ b/Main/System/Battle/BattleObject/HeroBattleObject.cs
@@ -187,9 +187,9 @@
         }
     }
     
-    public override Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillSkinConfig skillSkinConfig, SkillBase skillBase, bool isCounter, Action onComplete)
+    public override Spine.TrackEntry PlaySkillAnimation(SkillConfig skillConfig, SkillSkinConfig skillSkinConfig, SkillBase skillBase, bool isSubSkill, Action onComplete)
     {
-        return motionBase.PlaySkillAnimation(skillConfig, skillSkinConfig, skillBase, isCounter, onComplete);
+        return motionBase.PlaySkillAnimation(skillConfig, skillSkinConfig, skillBase, isSubSkill, onComplete);
     }
     
     public override bool CanStartDeath()
@@ -199,6 +199,15 @@
     
     public override bool CanCastSkillAnimation(SkillSkinConfig skillSkinConfig)
     {
+        //  闄や簡绛� Spine 鎶�鑳藉姩鐢婚攣锛坧layingSkillWithAnim锛夛紝杩樺繀椤荤瓑 caster 鑷韩鐢� SkillBase.MoveToTarget
+        //  鍙戣捣鐨勫墠鍐� / 鍥炰綅 tween 璺戝畬銆傚惁鍒欎笂涓�涓妧鑳界殑鍥炰綅 tween 杩樺湪鍗婅矾锛屼笅涓�涓妧鑳斤紙灏ゅ叾鏄鍔�
+        //  BattleType=5锛変細鍦ㄥ綋鍓嶄綅缃啀鍙戣捣鍓嶅啿锛屾棫鍥炰綅 tween 鍜屾柊鍓嶅啿 tween 鍚屾椂鍐� anchoredPosition锛�
+        //  瑙嗚琛ㄧ幇鏄�"娌″洖浣嶅張绐佺劧鍐插嚭鍘绘敾鍑�"銆傝繖閲屽彧鍒ゅ畾 SkillBase 鑷繁璁板綍鐨勭Щ鍔� tween 鍙ユ焺锛屼笉璇激
+        //  鎸傚湪 heroRectTrans 涓婄殑鍏跺畠涓氬姟 tween銆�
+        if (activeMoveTween != null && activeMoveTween.IsActive() && !activeMoveTween.IsComplete())
+        {
+            return false;
+        }
         return motionBase.CanCastSkill(skillSkinConfig);
     }
 
diff --git a/Main/System/Battle/Motion/MotionBase.cs b/Main/System/Battle/Motion/MotionBase.cs
index 6621627..211e7fc 100644
--- a/Main/System/Battle/Motion/MotionBase.cs
+++ b/Main/System/Battle/Motion/MotionBase.cs
@@ -34,11 +34,55 @@
     // 瀛愭妧鑳借建閬撴睜绠$悊锛堝湪Init涓垵濮嬪寲锛屼笉瑕佸湪杩欓噷鍒濆鍖栵級
     private Queue<int> availableSubTracks;
     private Dictionary<SkillBase, int> subSkillTrackMap = new Dictionary<SkillBase, int>();
+
+    //  璁板綍"褰撳墠鎵�鏈変粛鍦ㄦ湰 MotionBase 涓婅繍琛岀殑 skillBase"锛屼笉鍖哄垎涓�/瀛愭妧鑳姐��
+    //  浣滅敤锛欻aveRest / ResetForReborn 杩欑被绮楁毚娓呭瓧鍏哥殑璋冪敤鍦ㄦ竻涔嬪墠蹇呴』寮哄埗缁撴潫杩欎簺 skillBase锛�
+    //  鍚﹀垯瀹冧滑鐨� frameHandler 琚垹銆佹椿璺� track 琚竻锛屼絾 skillBase.IsFinished() 姘歌繙 false锛�
+    //  涓婂眰 RecordPlayer 灏辨案杩滅瓑涓嶅埌瀹冪粨鏉熴��
+    private HashSet<SkillBase> activeSkillBases = new HashSet<SkillBase>();
     
     private SkeletonIllusionShadow illusionShadow;
     private bool playingSkill = false;
 
-    private bool playingSkillWithAnim = false;
+    private bool _playingSkillWithAnim = false;
+#if UNITY_EDITOR
+    //  [鍗℃璇婃柇] 璁板綍鏄皝鎶� playingSkillWithAnim 閿佷负 true銆佸湪鍝竴甯э紝渚� SkillBase.ReportStuckIfNeeded 浣跨敤銆�
+    //  涓嶅仛 Run() 鍐� watchdog锛堥伩鍏嶅埛灞忥級锛涘彧鍦� SkillBase 鑷韩鍙戠幇鍗℃鏃朵竴娆℃�ф妸杩欎簺淇℃伅鎵撳嚭鏉ャ��
+    private int _pswaSetTrueFrame = -1;
+    private int _pswaSetTrueSkillId = 0;
+    private string _pswaSetTrueStack = null;
+#endif
+    private bool playingSkillWithAnim
+    {
+        get => _playingSkillWithAnim;
+        set
+        {
+#if UNITY_EDITOR
+            if (_playingSkillWithAnim != value
+                && Launch.Instance != null && Launch.Instance.isOpenBattleDebug)
+            {
+                string owner = skeletonAnim != null && skeletonAnim.gameObject != null ? skeletonAnim.gameObject.name : "(no-skel)";
+                // 姣忔鍙樻洿鎵撳嵃鏍堬紝瀹氫綅鍒板簳鏄皝鎶� playingSkillWithAnim 璁� true 浜嗐�佽皝娓�/涓嶆竻
+                BattleDebug.LogError($"[MotionBase owner={owner} hash={GetHashCode()}] playingSkillWithAnim {_playingSkillWithAnim} -> {value}\n"
+                    + UnityEngine.StackTraceUtility.ExtractStackTrace());
+            }
+            //  [鍗℃璇婃柇] 缁存姢閿佺殑鎸佹湁鑰呬俊鎭紙涓婁竴杞殑瀛楁琚洖婊氫簡锛岃繖閲屾槸鏈�灏忓繀瑕侀泦鍚堬級
+            if (value && !_playingSkillWithAnim)
+            {
+                _pswaSetTrueFrame = UnityEngine.Time.frameCount;
+                _pswaSetTrueStack = UnityEngine.StackTraceUtility.ExtractStackTrace();
+                // skillId 鐢� ExecuteSkillAnim 绱ф帴鐫�璧嬪�硷紙setter 杩欓噷鎷夸笉鍒帮級
+            }
+            else if (!value && _playingSkillWithAnim)
+            {
+                _pswaSetTrueFrame = -1;
+                _pswaSetTrueSkillId = 0;
+                _pswaSetTrueStack = null;
+            }
+#endif
+            _playingSkillWithAnim = value;
+        }
+    }
 
     private bool isUnderControl = false;
 
@@ -151,6 +195,38 @@
 
     private void AddAction(Action action) => runningActions.Add(action);
     private void RemoveAction(Action action) => runningActions.Remove(action);
+
+    //  鍦� ExecuteSkillAnim 鐨勫悇鏉¢��鍑鸿矾寰勭粺涓�璋冪敤锛屼繚璇� activeSkillBases 涓� runningActions 鍚屾銆�
+    private void RemoveSkillAnim(Action frameHandler, SkillBase skillBase)
+    {
+        RemoveAction(frameHandler);
+        if (skillBase != null) activeSkillBases.Remove(skillBase);
+    }
+
+#if UNITY_EDITOR
+    // 璇婃柇鐢細瀵煎嚭娲昏穬鎶�鑳借建閬� + Spine 鍔ㄧ敾鐘舵�� + 鎸傝捣鐨� frameHandler 鏁伴噺
+    public string DumpActiveTracksForDebug()
+    {
+        var sb = new System.Text.StringBuilder();
+        string owner = skeletonAnim != null && skeletonAnim.gameObject != null ? skeletonAnim.gameObject.name : "(no-skel)";
+        sb.Append($"[hash={GetHashCode()} owner={owner}] playingSkill={playingSkill} playingSkillWithAnim={playingSkillWithAnim} runningActions.Count={runningActions.Count} activeSkillTracks.Count={activeSkillTracks.Count}");
+        if (isUnderControl) sb.Append(" [UnderControl]");
+        if (skeletonAnim != null) sb.Append($" timeScale={skeletonAnim.timeScale}");
+        foreach (var kv in activeSkillTracks)
+        {
+            var track = kv.Value;
+            if (track == null)
+            {
+                sb.Append($"\n    track[{kv.Key}]=null");
+                continue;
+            }
+            string animName = track.Animation != null ? track.Animation.Name : "(null)";
+            float duration = track.Animation != null ? track.Animation.Duration : -1f;
+            sb.Append($"\n    track[{kv.Key}] anim={animName} TrackTime={track.TrackTime:F3} duration={duration:F3} isComplete={track.IsComplete} timeScale={track.TimeScale}");
+        }
+        return sb.ToString();
+    }
+#endif
     
     // 妫�鏌ユ槸鍚︽湁娲昏穬鐨勬妧鑳借建閬擄紙鎺掗櫎姝讳骸杞ㄩ亾锛�
     private bool HasActiveSkillTracks()
@@ -279,6 +355,10 @@
             activeSkillTracks[trackIndex] = skillTrack;
 
             playingSkillWithAnim = true;
+#if UNITY_EDITOR
+            //  [鍗℃璇婃柇] setter 閲屾嬁涓嶅埌 skillId锛岃繖閲岃ˉ涓婏紝渚� SkillBase.ReportStuckIfNeeded dump
+            _pswaSetTrueSkillId = skillConfig != null ? skillConfig.SkillID : 0;
+#endif
         }
         
         playingSkill = true;
@@ -292,6 +372,9 @@
 
         // startTime 琛ㄧず鎶�鑳�"鏈湴閫昏緫鏃堕棿"鐨勮捣鐐癸紙浠� Time.time 涓哄熀鍑嗭級
         float startTime = hasAnim ? 0f : Time.time;
+
+        //  鐧昏鍒版椿璺冮泦鍚堬紝璁� HaveRest / ResetForReborn 鐭ラ亾鏈夊摢浜� skillBase 闇�瑕佸湪娓呭瓧鍏稿墠琚己鍒剁粨鏉熴��
+        activeSkillBases.Add(skillBase);
 
         skillBase.OnSkillStart();
 
@@ -326,7 +409,7 @@
 
                 
                 
-                RemoveAction(frameHandler);
+                RemoveSkillAnim(frameHandler, skillBase);
                 return;
             }
 
@@ -360,7 +443,7 @@
                     skillBase.ForceFinished();
 
                     // 娓呯悊骞剁‘淇濈姸鎬佸浣�
-                    RemoveAction(frameHandler);
+                    RemoveSkillAnim(frameHandler, skillBase);
                     
                     // 鍥炴敹瀛愭妧鑳借建閬�
                     if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
@@ -383,7 +466,7 @@
                 {
                     Debug.LogError("鎶�鑳藉姩鐢绘挱鏀惧け璐ワ紝寮哄埗缁撴潫 " + skillConfig.SkillID + " is caster dead " + skillBase.caster.IsDead());
                     skillBase.ForceFinished();
-                    RemoveAction(frameHandler);
+                    RemoveSkillAnim(frameHandler, skillBase);
                     if (activeSkillTracks.ContainsKey(trackIndex))
                         activeSkillTracks.Remove(trackIndex);
                     
@@ -498,7 +581,7 @@
 
                     // skillTrackDict.Remove(trackIndex);
 
-                    RemoveAction(frameHandler);
+                    RemoveSkillAnim(frameHandler, skillBase);
                     onComplete?.Invoke();
                     skillBase.OnFinalFrameEnd();
                     if (hasAnim)
@@ -647,6 +730,16 @@
     // 鍘熸湁鐨� HaveRest 淇濇寔涓嶅彉锛岀敤浜庝竴鑸殑閲嶇疆
     public void HaveRest()
     {
+#if UNITY_EDITOR
+        if (Launch.Instance != null && Launch.Instance.isOpenBattleDebug)
+        {
+            string owner = skeletonAnim != null && skeletonAnim.gameObject != null ? skeletonAnim.gameObject.name : "(no-skel)";
+            BattleDebug.LogError($"[MotionBase.HaveRest owner={owner} hash={GetHashCode()}] 璋冪敤鏍堬細\n{UnityEngine.StackTraceUtility.ExtractStackTrace()}");
+        }
+#endif
+        // 鍏堝己鍒剁粨鏉熸墍鏈夋鍦ㄨ繍琛岀殑 skillBase锛岄伩鍏嶆竻瀛楀吀鍚庤繖浜� skillBase 鐨� frameHandler 琚垹浣嗚嚜韬� StateFlags 姘歌繙鍋滃湪 Started
+        ForceFinishRunningSkillBases();
+
         animState?.ClearTracks();
 
         trackEntryCallbacks.Clear();
@@ -668,14 +761,42 @@
 
         currentTrack = null;
 
-        
         playingSkill = false;
+        playingSkillWithAnim = false;
         PlayAnimation(MotionName.idle, true);
+    }
+
+    // HaveRest / ResetForReborn 杩欑被鈥滅矖鏆存竻鐞嗏�濊皟鐢ㄤ細鐩存帴 Clear runningActions/activeSkillTracks锛�
+    // 瀵艰嚧璺熻繖浜涜建閬撶粦瀹氱殑 skillBase 姘歌繙鏀朵笉鍒� OnFinalFrameEnd锛屽▉鑳佷笂灞� RecordPlayer銆�
+    // 杩欓噷閬嶅巻 activeSkillBases锛堜富/瀛愭妧鑳介兘瑕嗙洊锛夛紝閫愪釜 ForceFinished锛岀劧鍚庢竻绌洪泦鍚堛��
+    private void ForceFinishRunningSkillBases()
+    {
+        if (activeSkillBases.Count == 0)
+            return;
+        var snapshot = new List<SkillBase>(activeSkillBases);
+        activeSkillBases.Clear();
+        foreach (var sb in snapshot)
+        {
+            if (sb != null && !sb.IsFinished())
+                sb.ForceFinished();
+        }
     }
 
     // 鏂板锛氫笓闂ㄧ敤浜庡娲荤殑瀹屾暣閲嶇疆鏂规硶
     public void ResetForReborn(bool reviveSelf = false)
     {
+#if UNITY_EDITOR
+        if (Launch.Instance != null && Launch.Instance.isOpenBattleDebug)
+        {
+            string owner = skeletonAnim != null && skeletonAnim.gameObject != null ? skeletonAnim.gameObject.name : "(no-skel)";
+            BattleDebug.LogError($"[MotionBase.ResetForReborn owner={owner} hash={GetHashCode()}] reviveSelf={reviveSelf} 璋冪敤鏍堬細\n{UnityEngine.StackTraceUtility.ExtractStackTrace()}");
+        }
+#endif
+        // 璺� HaveRest 鍚岀悊锛氬厛寮哄埗缁撴潫鎵�鏈夋鍦ㄨ繍琛岀殑 skillBase锛�
+        // 閬垮厤涓嬮潰娓� runningActions / activeSkillTracks 鍚庡畠浠案杩滄帴鏀朵笉鍒板抚鍥炶皟銆�
+        if (!reviveSelf)
+            ForceFinishRunningSkillBases();
+
         // 1. 娓呯悊鎵�鏈夊姩鐢昏建閬擄紙鍖呮嫭姝讳骸鍔ㄧ敾鐨勮建閬�9锛�
         animState?.ClearTracks();
 
@@ -706,6 +827,10 @@
         
         // 5. 閲嶇疆鎵�鏈夌姸鎬佹爣蹇�
         playingSkill = false;
+        //  reviveSelf 鍒嗘敮涓� runningActions 娌¤娓咃紝涓绘妧鑳� frameHandler 浼氳嚜宸辫蛋鍒� OnFinalFrameEnd 閭i噷澶嶄綅锛�
+        //  闈� reviveSelf 鍒嗘敮涓� runningActions 宸叉竻骞插噣锛岃繖閲屼竴骞跺浣嶃��
+        if (!reviveSelf)
+            playingSkillWithAnim = false;
         isUnderControl = false;
         
         // 6. 閲嶇疆鏃堕棿鐩稿叧瀛楁锛堝叧閿紒锛�
@@ -753,6 +878,16 @@
         return !playingSkillWithAnim || string.IsNullOrEmpty(skillSkinConfig.SkillMotionName);
     }
 
+#if UNITY_EDITOR
+    /// <summary>鍗℃璇婃柇鐢細鏆撮湶 playingSkillWithAnim 鏍囧織浣嶃��</summary>
+    public bool PlayingSkillWithAnimForDebug => playingSkillWithAnim;
+
+    //  [鍗℃璇婃柇] 缁� SkillBase 鍗℃鎶ュ憡鐢細璋佹妸 playingSkillWithAnim 閿佷负 true銆佸湪鍝竴甯с��
+    public int PlayingSkillAnimOwnerSkillIdForDebug => _pswaSetTrueSkillId;
+    public int PlayingSkillAnimOwnerFrameForDebug => _pswaSetTrueFrame;
+    public string PlayingSkillAnimOwnerStackForDebug => _pswaSetTrueStack;
+#endif
+
     public bool CanStartDeath()
     {
         return !playingSkillWithAnim;
diff --git a/Main/System/Battle/RecordPlayer/RecordPlayer.cs b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
index 09f140e..cf7acb9 100644
--- a/Main/System/Battle/RecordPlayer/RecordPlayer.cs
+++ b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
@@ -56,6 +56,93 @@
         return isPlaying;
     }
 
+#if UNITY_EDITOR
+    /// <summary>
+    /// 鍗℃鎺掓煡鐢細dump 鍑哄綋鍓� RecordPlayer 鍐呴儴鎵�鏈夊湪鎾� / 鎺掗槦 / 鍗虫椂鎾斁 鐨� RecordAction 姒傝銆�
+    /// </summary>
+    public string DumpPlayingState()
+    {
+        return DumpPlayingState(0);
+    }
+
+    //  depth 鐢ㄤ簬鎺у埗閫掑綊娣卞害锛屾渶澶氬睍寮�涓ゅ眰宓屽锛堢埗 inner player -> 瀛� SkillRecordAction -> 瀛� inner player锛�
+    public string DumpPlayingState(int depth)
+    {
+        string indent = new string(' ', depth * 4);
+        var sb = new System.Text.StringBuilder();
+        sb.Append("current=");
+        if (currentRecordAction == null)
+        {
+            sb.Append("null");
+        }
+        else
+        {
+            AppendActionBrief(sb, currentRecordAction);
+        }
+
+        sb.Append("  queue.Count=").Append(recordActionQueue.Count);
+        if (recordActionQueue.Count > 0)
+        {
+            sb.Append(" [");
+            int i = 0;
+            foreach (var act in recordActionQueue)
+            {
+                if (i > 0) sb.Append(", ");
+                sb.Append(act.GetType().Name);
+                if (++i >= 5) { sb.Append(", ..."); break; }
+            }
+            sb.Append("]");
+        }
+
+        sb.Append("  immediatelyList.Count=").Append(immediatelyActionList.Count);
+        if (immediatelyActionList.Count > 0)
+        {
+            sb.Append(" [");
+            for (int i = 0; i < immediatelyActionList.Count && i < 5; i++)
+            {
+                if (i > 0) sb.Append(", ");
+                var act = immediatelyActionList[i];
+                if (act == null) { sb.Append("null"); continue; }
+                sb.Append(act.GetType().Name)
+                  .Append("(IsFin=").Append(act.IsFinished())
+                  .Append(",CanStart=").Append(act.CanStartExecution())
+                  .Append(",Waiting=").Append(act.isWaitingPlay)
+                  .Append(")");
+            }
+            if (immediatelyActionList.Count > 5) sb.Append(", ...");
+            sb.Append("]");
+        }
+
+        //  閫掑綊灞曞紑宓屽 SkillRecordAction 鐨勫唴閮ㄧ姸鎬侊紙鏈�澶� 2 灞傦紝閬垮厤鏃犻檺閫掑綊锛�
+        if (depth < 2)
+        {
+            if (currentRecordAction is SkillRecordAction sra && sra.skillBase != null)
+            {
+                sb.Append('\n').Append(indent).Append("  鈹� [current] skillId=")
+                  .Append(sra.skillBase.skillConfig?.SkillID ?? 0)
+                  .Append(" caster=").Append(sra.skillBase.tagUseSkillAttack?.ObjID ?? 0UL)
+                  .Append(" StateFlags=").Append(sra.skillBase.StateFlagsForDebug);
+                //  杩涗竴姝ュ睍寮�瀹冭嚜宸辩殑 inner player
+                var innerPlayer = sra.GetInnerRecordPlayer();
+                if (innerPlayer != null && innerPlayer.IsPlaying())
+                {
+                    sb.Append('\n').Append(indent).Append("    innerRecordPlayer: ")
+                      .Append(innerPlayer.DumpPlayingState(depth + 1));
+                }
+            }
+        }
+
+        return sb.ToString();
+    }
+
+    private static void AppendActionBrief(System.Text.StringBuilder sb, RecordAction act)
+    {
+        sb.Append(act.GetType().Name)
+          .Append(" IsFinished=").Append(act.IsFinished())
+          .Append(" IsActionCompleted=").Append(act.IsActionCompleted());
+    }
+#endif
+
     public void PlayRecord(RecordAction recordAction)
     {
         if (recordAction == null) return;
@@ -229,6 +316,15 @@
                 //  妫�鏌ユ槸鍚﹀彲浠ュ紑濮嬫墽琛岋紙WaitingPlay鏉′欢妫�鏌ワ級
                 if (!action.CanStartExecution())
                 {
+                    //  淇锛氬嵆渚� CanStartExecution 杩斿洖 false锛屽彧瑕� action 宸茬粡 IsFinished锛�
+                    //  涔熷繀椤讳粠鍒楄〃閲岀Щ闄わ紝鍚﹀垯瀹冧細姘镐箙鍗犱綅瀵艰嚧 IsPlaying() 涓�鐩翠负 true锛�
+                    //  璁╃埗鎶�鑳藉崱鍦� ownRecordAction.innerRecordPlayer.IsPlaying() 鐨勫垎鏀笂銆�
+                    //  锛堝吀鍨嬪満鏅細涓�涓� caster 杩炵画閲婃斁涓や釜鎶�鑳斤紝绗竴涓凡缁撴潫浣� caster 浠嶈
+                    //  璁颁负 IsCastingSkill锛孲killBase.CanStartExecution 杩斿洖 false銆傦級
+                    if (action.IsFinished())
+                    {
+                        removeIndexList.Add(i);
+                    }
                     continue;
                 }
                 
diff --git a/Main/System/Battle/Skill/SkillBase.Buff.cs b/Main/System/Battle/Skill/SkillBase.Buff.cs
new file mode 100644
index 0000000..7befa17
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Buff.cs
@@ -0,0 +1,65 @@
+using System.Collections.Generic;
+
+// SkillBase锛圔uff 閮ㄥ垎锛夛細Buff 鍖咃紙HB428 鍒锋柊 / HB429 鍒犻櫎锛夌殑璇嗗埆涓庡垎鍙戙��
+public partial class SkillBase
+{
+    /// <summary>
+    /// 鍒ゆ柇鏄惁涓� Buff 鐩稿叧鐨勫寘锛圚B428 鎴� HB429锛�
+    /// </summary>
+    protected bool IsBuffPack(GameNetPackBasic pack)
+    {
+        return pack is HB428_tagSCBuffRefresh || pack is HB429_tagSCBuffDel;
+    }
+
+    /// <summary>
+    /// 澶勭悊鏀堕泦鍒扮殑 Buff 鍖呭垪琛紙HB428 鍒锋柊 鍜� HB429 鍒犻櫎锛�
+    /// </summary>
+    protected void ProcessBuffPacks(List<GameNetPackBasic> buffPacks)
+    {
+        if (buffPacks == null || buffPacks.Count == 0) return;
+
+        foreach (var pack in buffPacks)
+        {
+            if (pack is HB428_tagSCBuffRefresh buffRefresh)
+            {
+                BattleObject battleObj = battleField.battleObjMgr.GetBattleObject((int)buffRefresh.ObjID);
+                if (battleObj != null)
+                {
+                    var buffMgr = battleObj.GetBuffMgr();
+                    if (buffMgr != null) // 鍛芥牸涓嶆湁 buff 绠$悊鍣�
+                    {
+                        buffMgr.RefreshBuff(buffRefresh, true);
+                    }
+                }
+            }
+            else if (pack is HB429_tagSCBuffDel buffDel)
+            {
+                BattleObject battleObj = battleField.battleObjMgr.GetBattleObject((int)buffDel.ObjID);
+                if (battleObj != null)
+                {
+                    var buffMgr = battleObj.GetBuffMgr();
+                    if (buffMgr != null) // 鍛芥牸涓嶆湁 buff 绠$悊鍣�
+                    {
+                        buffMgr.RemoveBuff(buffDel, false);
+                    }
+                }
+            }
+        }
+    }
+
+    /// <summary>
+    /// 寮哄埗鍒嗗彂 Buff 鍖咃紙鐢ㄤ簬 ForceFinished 鍦烘櫙锛�
+    /// </summary>
+    protected void DistributeBuffPacks(List<GameNetPackBasic> buffPacks)
+    {
+        if (buffPacks == null || buffPacks.Count == 0) return;
+
+        foreach (var pack in buffPacks)
+        {
+            // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
+            // 鍘熷洜锛欱uff鍖呮槸鎶�鑳芥晥鏋滅殑鏍稿績缁勬垚閮ㄥ垎锛屽簲璇ョ敱SkillRecordAction绠$悊
+            // 鍗充娇鏄己鍒跺垎鍙戠殑鎯呭喌锛屼篃瑕佷繚鎸佸湪姝g‘鐨凴ecordAction涓婁笅鏂囦腑
+            PackageRegeditEx.DistributeToRecordAction(pack, ownRecordAction);
+        }
+    }
+}
diff --git a/Main/System/Battle/Skill/SkillBase.Buff.cs.meta b/Main/System/Battle/Skill/SkillBase.Buff.cs.meta
new file mode 100644
index 0000000..24b3c3c
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Buff.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6a276ba860f155b4ebb6131e4a9d03be
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/Skill/SkillBase.Cast.cs b/Main/System/Battle/Skill/SkillBase.Cast.cs
new file mode 100644
index 0000000..8d3ef90
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Cast.cs
@@ -0,0 +1,427 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using Spine;
+
+// SkillBase锛圕ast 閮ㄥ垎锛夛細鏂芥硶闃舵鈥斺�旂Щ鍔ㄣ�佸姩鐢汇�佹畫褰便�侀珮浜�佹敾鍑荤粨鏉熴��
+public partial class SkillBase
+{
+    // 鎶�鑳介噴鏀句富閫昏緫锛氬箍鎾簨浠躲�侀珮浜洰鏍囥�佹墽琛岄噴鏀�
+    public virtual void Cast()
+    {
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] Cast() 鍏ュ彛锛氳褰� skillId/caster/BattleType/褰撳墠浣嶇疆/褰撳墠鏄惁杩樺湪 tween銆�
+        //  鐢ㄦ潵鍒ゆ柇鏂版妧鑳芥槸鍚﹀湪涓婁竴涓妧鑳界殑鍥炰綅 tween 杩樻病瀹屾垚鏃跺氨杩涘叆 Cast()銆�
+        {
+            Vector2 castEntryPos = (caster != null && caster.GetRectTransform() != null)
+                ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+            bool casterTweening = caster != null && caster.GetRectTransform() != null
+                && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform());
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] Cast 鍏ュ彛 skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} castMode={skillSkinConfig?.castMode} anchoredPos={castEntryPos} casterTweening={casterTweening}");
+        }
+#endif
+        // 骞挎挱鎶�鑳介噴鏀句簨浠�
+        string guid = battleField.guid;
+        // 鑾峰彇閲婃斁鑰呮暟鎹細Hero 浼犻�� teamHero锛孧ingge 浼犻�� null锛堝洜涓轰簨浠剁洃鍚櫒鍙鐞� Hero 鏁版嵁锛�
+        TeamHero teamHero = null;
+        if (caster is HeroBattleObject heroBattleObject)
+        {
+            teamHero = heroBattleObject.teamHero;
+        }
+        // 鍛芥牸閲婃斁鎶�鑳芥椂 teamHero 涓� null锛岀洃鍚櫒浼氭纭鐞嗭紙宸叉湁 null 妫�鏌ワ級
+        EventBroadcast.Instance.Broadcast<string, SkillConfig, TeamHero>(EventName.BATTLE_CAST_SKILL, guid, skillConfig, teamHero);
+
+        if (skillSkinConfig.SkinllSFX1 != 0)
+        {
+            battleField.soundManager.PlayEffectSound(skillSkinConfig.SkinllSFX1, false);
+        }
+
+        if (caster != null)
+        {
+            // 鎴樻枟绫诲瀷 0-甯歌锛�1-杩炲嚮锛�2-鍙嶅嚮锛�3-杩藉嚮锛�4-瀛愭妧鑳斤紱5-琚姩瑙﹀彂鐨�
+            DamageNumConfig hintConfig = null;
+            if (tagUseSkillAttack.BattleType == 1)
+            {
+                hintConfig = DamageNumConfig.Get(BattleConst.BattleComboAttack);
+            }
+            else if (tagUseSkillAttack.BattleType == 2)
+            {
+                hintConfig = DamageNumConfig.Get(BattleConst.BattleCounterAttack);
+            }
+            else if (tagUseSkillAttack.BattleType == 3)
+            {
+                hintConfig = DamageNumConfig.Get(BattleConst.BattleChaseAttack);
+            }
+
+            Hint(caster, hintConfig);
+        }
+
+        // 楂樹寒鎵�鏈夋湰娆℃妧鑳界浉鍏崇殑鐩爣
+        HighLightAllTargets();
+
+        // 鏍规嵁閲婃斁妯″紡鎵ц鐩稿簲閫昏緫
+        switch (skillSkinConfig.castMode)
+        {
+            case SkillCastMode.None:
+            case SkillCastMode.Self:
+                CastImpl(OnAttackFinish);
+                break;
+            case SkillCastMode.Enemy:
+                CastToEnemy();
+                break;
+            case SkillCastMode.Target:
+                CastToTarget();
+                break;
+            case SkillCastMode.Allies:
+                CastToAllies();
+                break;
+            case SkillCastMode.DashCast:
+                DashCast(OnAttackFinish);
+                break;
+            default:
+                Debug.LogError("寮哄埗缁撴潫鎶�鑳� 鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹俻lease鑱旂郴绛栧垝 鎶�鑳絠d:" + skillConfig.SkillID + " cast position " + skillSkinConfig.CastPosition);
+                ForceFinished();
+                break;
+        }
+    }
+
+    protected void Hint(BattleObject battleObject, DamageNumConfig hintConfig)
+    {
+        if (hintConfig != null)
+        {
+            battleObject.ShowTips(((char)hintConfig.prefix).ToString(), true, false, 1.25f);
+        }
+    }
+
+    // 鍐叉挒鏀诲嚮妯″紡锛堝緟瀹炵幇锛�
+    protected void DashCast(Action _onComplete)
+    {
+        Debug.LogError("DashCast 杩樻病瀹炵幇");
+        ForceFinished();
+    }
+
+    // 瀵规晫鏂归噴鏀炬妧鑳斤細绉诲姩鍒版晫鏂瑰尯鍩熻繘琛屾敾鍑�
+    protected void CastToEnemy()
+    {
+        RectTransform target = battleField.GetTeamNode(caster.GetEnemyCamp(), skillSkinConfig);
+        ExecuteMoveAndCastSequence(target, () =>
+        {
+            if (skillConfig.ClientTriggerTiming == 1)
+            {
+                OnAttackFinish();
+            }
+            else
+            {
+                // ShadowIllutionCreate(true);
+                MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.GetPositionNum()), Vector2.zero, () =>
+                {
+                    // ShadowIllutionCreate(false);
+                    OnAttackFinish();
+                }, MoveSpeed);
+            }
+        });
+    }
+
+    // 瀵规寚瀹氱洰鏍囬噴鏀炬妧鑳斤細绉诲姩鍒颁富瑕佺洰鏍囦綅缃繘琛屾敾鍑�
+    protected void CastToTarget()
+    {
+        if (tagUseSkillAttack.HurtCount <= 0)
+        {
+            Debug.LogError("鎶�鑳芥敾鍑诲寘娌℃湁鐩爣 HurtCount <= 0");
+            OnSkillFinished();
+            return;
+        }
+
+        int mainTargetPosNum = BattleUtility.GetMainTargetPositionNum(this, caster, tagUseSkillAttack.HurtList.ToList(), skillConfig);
+        BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
+        RectTransform targetTrans = battleField.GetTeamNode(battleCamp, mainTargetPosNum);
+
+        ExecuteMoveAndCastSequence(targetTrans, () =>
+        {
+            RectTransform rectTransform = battleField.GetTeamNode(caster.Camp, caster.GetPositionNum());
+            // ShadowIllutionCreate(true);
+            MoveToTarget(rectTransform, Vector2.zero, () =>
+            {
+                // ShadowIllutionCreate(false);
+                OnAttackFinish();
+            }, MoveSpeed);
+        });
+    }
+
+    // 瀵瑰弸鏂归噴鏀炬妧鑳斤細绉诲姩鍒板弸鏂瑰尯鍩熻繘琛屾不鐤楁垨澧炵泭
+    protected void CastToAllies()
+    {
+        RectTransform target = battleField.GetTeamNode(caster.Camp, skillSkinConfig);
+        ExecuteMoveAndCastSequence(target, () =>
+        {
+            if (skillConfig.ClientTriggerTiming == 1)
+            {
+                OnAttackFinish();
+            }
+            else
+            {
+                // ShadowIllutionCreate(true);
+                MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.GetPositionNum()), Vector2.zero, () =>
+                {
+                    // ShadowIllutionCreate(false);
+                    OnAttackFinish();
+                }, MoveSpeed);
+            }
+        });
+    }
+
+    // 鎵ц绉诲姩-鏂芥硶-杩斿洖搴忓垪锛氶�氱敤鐨勭Щ鍔ㄦ敾鍑绘祦绋�
+    private void ExecuteMoveAndCastSequence(RectTransform target, Action onReturnComplete)
+    {
+#if UNITY_EDITOR
+        BattleDebug.LogError($"[鍓嶅啿璇婃柇] ExecuteMoveAndCastSequence 寮�濮� skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} CastDistance={skillSkinConfig?.CastDistance} castMode={skillSkinConfig?.castMode}");
+#endif
+        ShadowIllutionCreate(true);
+        MoveToTarget(target, new Vector2(skillSkinConfig.CastDistance, 0), () =>
+        {
+#if UNITY_EDITOR
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] 鍓嶅啿瀹屾垚 skillId={skillConfig?.SkillID} caster={caster?.ObjID} 鍑嗗 CastImpl");
+#endif
+            if (skillSkinConfig.CastDistance < 9999 && skillSkinConfig.SkinllSFX2 != 0)
+            {
+                battleField.soundManager.PlayEffectSound(skillSkinConfig.SkinllSFX2, false);
+            }
+
+            TurnBack(() =>
+            {
+                ShadowIllutionCreate(false);
+
+                CastImpl(() =>
+                {
+                    TurnBack(() =>
+                    {
+                        try
+                        {
+                            onReturnComplete?.Invoke(); // 娣诲姞寮傚父澶勭悊闃叉鍥炶皟寮傚父瀵艰嚧鐘舵�佷笉瀹屾暣
+                        }
+                        catch (Exception ex)
+                        {
+                            Debug.LogError($"ExecuteMoveAndCastSequence鍥炶皟寮傚父: {ex.Message}");
+                            throw;
+                        }
+                    }, -1f);
+                });
+            }, -1f);
+        });
+    }
+
+    // 绉诲姩鍒扮洰鏍囦綅缃細澶勭悊瑙掕壊鐨勭Щ鍔ㄥ姩鐢诲拰閫昏緫
+    protected void MoveToTarget(RectTransform target, Vector2 offset, Action _onComplete = null, float speed = 750f)
+    {
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] 璁板綍鍏ュ彛鍙傛暟锛欳astDistance銆乷ffset銆乻peed锛涗互鍙婂綋鍓� caster 鐨勯敋鐐逛綅缃��
+        Vector2 fromPos = caster != null && caster.GetRectTransform() != null
+            ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+        bool mttTweening = caster != null && caster.GetRectTransform() != null
+            && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform());
+        BattleDebug.LogError($"[鍓嶅啿璇婃柇] MoveToTarget 鍏ュ彛 skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} CastDistance={skillSkinConfig?.CastDistance} offset={offset} speed={speed} fromPos={fromPos} casterTweening={mttTweening}");
+#endif
+        if (skillSkinConfig.CastDistance >= 9999)
+        {
+#if UNITY_EDITOR
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] CastDistance>=9999 鐩存帴璺宠繃绉诲姩 skillId={skillConfig?.SkillID} caster={caster?.ObjID}");
+#endif
+            _onComplete?.Invoke();
+            return;
+        }
+
+        caster.PlayAnimation(MotionName.run, true);
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] 璁板綍 target 鐨勫悕瀛�/涓栫晫鍧愭爣/鐖惰妭鐐� scale锛屼究浜庡畾浣嶉暅鍍忓潗鏍囩郴瀵艰嚧 offset 鏂瑰悜鍙嶈浆
+        string targetName = target != null ? target.name : "(null)";
+        Vector3 targetWorld = target != null ? target.position : Vector3.zero;
+        Vector3 targetLossyScale = target != null ? (Vector3)target.lossyScale : Vector3.one;
+        Vector2 targetAnchored = target != null ? target.anchoredPosition : Vector2.zero;
+        BattleDebug.LogError($"[鍓嶅啿璇婃柇] target淇℃伅 skillId={skillConfig?.SkillID} caster={caster?.ObjID} casterCamp={caster?.Camp} target.name={targetName} target.anchoredPos={targetAnchored} target.worldPos={targetWorld} target.lossyScale={targetLossyScale}");
+#endif
+        var tweener = BattleUtility.MoveToTarget(caster.GetRectTransform(), target, offset, () =>
+        {
+#if UNITY_EDITOR
+            Vector2 toPos = caster != null && caster.GetRectTransform() != null
+                ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] MoveToTarget 瀹屾垚 skillId={skillConfig?.SkillID} caster={caster?.ObjID} toPos={toPos}");
+#endif
+            //  tween 瀹屾垚鏃舵竻闄� caster 涓婄殑 activeMoveTween 鍙ユ焺锛屾斁寮� CanCastSkillAnimation 鐨勯椄闂ㄣ��
+            if (caster != null)
+            {
+                caster.activeMoveTween = null;
+            }
+            caster.PlayAnimation(MotionName.idle, true);
+            _onComplete?.Invoke();
+        }, speed);
+        //  璁板綍鍒� caster锛岃 CanCastSkillAnimation 鑳界簿纭瓑寰呰繖涓�涓� tween锛堣�屼笉鏄� caster 韬笂浠绘剰 tween锛夈��
+        if (caster != null)
+        {
+            caster.activeMoveTween = tweener;
+        }
+        battleField.battleTweenMgr.OnPlayTween(tweener);
+    }
+
+    // 杞韩閫昏緫锛氭牴鎹妧鑳介厤缃鐞嗚鑹茶浆鍚�
+    protected void TurnBack(Action _onComplete, float forward)
+    {
+        if (skillSkinConfig.CastDistance < 0)
+        {
+            caster.SetFacing(forward);
+        }
+        _onComplete?.Invoke();
+    }
+
+    // 鏀诲嚮瀹屾垚鍚庣殑澶勭悊锛氳浆韬�佹仮澶嶇姸鎬併�佹挱鏀惧緟鏈哄姩鐢�
+    protected void OnAttackFinish()
+    {
+#if UNITY_EDITOR
+        //  [鍓嶅啿璇婃柇] OnAttackFinish 鍏ュ彛锛氳褰曞抚鍙峰拰褰撳墠浣嶇疆锛屽拰 Cast()/MoveToTarget 鏃ュ織瀵归綈銆�
+        {
+            Vector2 finPos = (caster != null && caster.GetRectTransform() != null)
+                ? caster.GetRectTransform().anchoredPosition : Vector2.zero;
+            bool finTweening = caster != null && caster.GetRectTransform() != null
+                && DG.Tweening.DOTween.IsTweening(caster.GetRectTransform());
+            BattleDebug.LogError($"[鍓嶅啿璇婃柇] OnAttackFinish skillId={skillConfig?.SkillID} caster={caster?.ObjID} battleType={tagUseSkillAttack?.BattleType} anchoredPos={finPos} casterTweening={finTweening}");
+        }
+#endif
+        TurnBack(null, 1f);
+        OnAllAttackMoveFinished();
+        caster.PlayAnimation(MotionName.idle, true);
+    }
+
+    // 鎵�鏈夋敾鍑荤Щ鍔ㄥ畬鎴愬悗鐨勫鐞嗭細鎭㈠UI鏄剧ず鐘舵��
+    protected virtual void OnAllAttackMoveFinished()
+    {
+        moveFinished = true;
+        List<BattleObject> allList = battleField.battleObjMgr.allBattleObjDict.Values.ToList<BattleObject>();
+        foreach (BattleObject bo in allList)
+        {
+            bo.layerMgr.SetFront();
+            bo.GetHeroInfoBar()?.SetActive(true);
+        }
+        battleField.battleRootNode.skillMaskNode.SetActive(false);
+    }
+
+    // 鎵ц鎶�鑳介噴鏀惧姩鐢诲拰閫昏緫锛氭挱鏀炬柦娉曞姩浣滃苟鎻愪緵鍥炶皟
+    protected TrackEntry CastImpl(Action onComplete = null)
+    {
+        return caster.PlaySkillAnimation(skillConfig, skillSkinConfig, this, tagUseSkillAttack.BattleType == 4, onComplete);
+    }
+
+    // 娈嬪奖鏁堟灉寮�鍏筹細杩炲嚮/鍙嶅嚮/杩藉嚮鏃跺紑鍚僵鑹叉畫褰卞苟鍔犻��
+    protected void ShadowIllutionCreate(bool create)
+    {
+        if (create)
+        {
+            Color color = Color.white;
+            //1-杩炲嚮锛�2-鍙嶅嚮锛�3-杩藉嚮
+            //  鍙嶅嚮钃濊壊
+            //  杩藉嚮杩炲嚮缁胯壊
+            bool change = false;
+            if (tagUseSkillAttack.BattleType == 1)
+            {
+                color = colorGreen;
+                change = true;
+            }
+            else if (tagUseSkillAttack.BattleType == 2)
+            {
+                color = colorBlue;
+                change = true;
+            }
+            else if (tagUseSkillAttack.BattleType == 3)
+            {
+                color = colorGreen;
+                change = true;
+            }
+
+            if (change)
+            {
+                MoveSpeed = 1125f;
+                caster.ShowIllusionShadow(true, color);
+            }
+        }
+        else
+        {
+            MoveSpeed = 750f;
+            caster.ShowIllusionShadow(false);
+        }
+    }
+
+    // 楂樹寒鎵�鏈夌浉鍏崇洰鏍囷細璁剧疆鏂芥硶鑰呭拰鐩爣鐨勬樉绀哄眰绾�
+    protected void HighLightAllTargets()
+    {
+        caster.layerMgr.SetSortingOrder(BattleConst.SkillMaskOrder + 1);// offset鏄�3 鑻遍泟灞傜骇 +1灏辨槸 active绾у埆 
+
+        if (skillConfig.FuncType != 2)
+            return;
+
+        // 鏀堕泦鎵�鏈夌洰鏍囷紙鍖呭惈 HurtList銆佹瘡涓� Hurt 鐨� HurtListEx銆佷互鍙婇《灞� HurtListEx锛�
+        var targetSet = new HashSet<BattleObject>();
+        if (tagUseSkillAttack != null)
+        {
+            // 涓荤洰鏍囧垪琛�
+            if (tagUseSkillAttack.HurtList != null)
+            {
+                foreach (var hurt in tagUseSkillAttack.HurtList)
+                {
+                    var bo = battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
+                    if (bo != null) targetSet.Add(bo);
+
+                    // 涓荤洰鏍囩殑棰濆鐩爣锛堝脊灏�/骞虫憡锛�
+                    if (hurt.HurtListEx != null)
+                    {
+                        foreach (var hurtEx in hurt.HurtListEx)
+                        {
+                            var exBo = battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
+                            if (exBo != null) targetSet.Add(exBo);
+                        }
+                    }
+                }
+            }
+
+            // 鎶�鑳藉寘椤跺眰鐨� HurtListEx锛堝婧呭皠銆侀《灞傚钩鎽婏級
+            if (tagUseSkillAttack.HurtListEx != null)
+            {
+                foreach (var hurtEx in tagUseSkillAttack.HurtListEx)
+                {
+                    var exBo = battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
+                    if (exBo != null) targetSet.Add(exBo);
+                }
+            }
+        }
+
+        // 纭繚鏂芥硶鑰呬篃琚珮浜紙鍘熼�昏緫锛�
+        var highlightList = new List<BattleObject>(targetSet) { caster };
+
+        var allList = battleField.battleObjMgr.allBattleObjDict.Values.ToList();
+
+        // 鏋勯�犻泦鍚堜究浜庡垽鏂�
+        var targetSetLookup = new HashSet<BattleObject>(targetSet);
+        var highlightSet = new HashSet<BattleObject>(highlightList);
+
+        // 鍏堟妸鏂芥硶鑰呯殑 InfoBar 闅愯棌锛堝師閫昏緫淇濈暀锛�
+        caster.GetHeroInfoBar()?.SetActive(false);
+
+        foreach (BattleObject bo in allList)
+        {
+            bool isHighlight = highlightSet.Contains(bo);
+            bool isTarget = targetSetLookup.Contains(bo);
+
+            if (isHighlight)
+            {
+                bo.layerMgr.SetFront();
+            }
+            else
+            {
+                bo.layerMgr.SetBack();
+            }
+
+            // 鐩爣锛堝惈 HurtListEx锛夐兘搴旀樉绀� InfoBar
+            bo.GetHeroInfoBar()?.SetActive(isTarget);
+        }
+
+        battleField.battleRootNode.skillMaskNode.SetActive(true);
+    }
+}
diff --git a/Main/System/Battle/Skill/SkillBase.Cast.cs.meta b/Main/System/Battle/Skill/SkillBase.Cast.cs.meta
new file mode 100644
index 0000000..4e73e58
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Cast.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a3bffc7bae40d6e4dbd4f0ee6fd7d6f9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/Skill/SkillBase.Death.cs b/Main/System/Battle/Skill/SkillBase.Death.cs
new file mode 100644
index 0000000..bcb6ebe
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Death.cs
@@ -0,0 +1,325 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+// SkillBase锛圖eath 閮ㄥ垎锛夛細姝讳骸鍖呫�丠P 鍒锋柊銆佹帀钀姐�佺粡楠岀殑鏀堕泦涓庡垎閰嶃��
+public partial class SkillBase
+{
+    // 澶勭悊HP鍒锋柊鍖咃紙绠�鍖栭�昏緫锛�
+    private void HandleRefreshHP()
+    {
+        // 鏌ユ壘HP鍒锋柊鍖�
+        HB419_tagSCObjHPRefresh refreshPack = BattleUtility.FindObjHPRefreshPack(packList);
+
+        if (refreshPack != null)
+        {
+            // 鍒嗗彂HP鍒锋柊鍖�
+            // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
+            // 鍘熷洜锛欻P鍒锋柊鍖呮槸鎶�鑳藉唴閮ㄤ骇鐢熺殑锛屽簲璇ョ敱褰撳墠SkillRecordAction鐨刬nnerRecordPlayer绠$悊
+            // 杩欐牱鍙互纭繚HP鍒锋柊涓庢妧鑳界殑鐢熷懡鍛ㄦ湡缁戝畾锛孎orceFinish鏃朵竴骞跺鐞�
+            PackageRegeditEx.DistributeToRecordAction(refreshPack, ownRecordAction);
+            packList.Remove(refreshPack);
+        }
+    }
+
+    // 澶勭悊姝讳骸鐩稿叧閫昏緫锛氬垎閰嶆帀钀藉拰缁忛獙
+    protected void HandleDead()
+    {
+        List<BattleDeadPack> deadPackList = BattleUtility.FindDeadPack(packList);
+        if (deadPackList.Count <= 0) return;
+
+        foreach (var deadPack in deadPackList)
+        {
+            packList.Remove(deadPack.deadPack);
+            packList.Remove(deadPack.deadTriggerSkill);
+        }
+
+        // 鎵惧埌鏈�澶х殑姝讳骸鍖� packUID
+        BattleDeadPack lastBattleDeadPack = null;
+        ulong maxDeathPackUID = 0;
+        foreach (var deadPack in deadPackList)
+        {
+            if (deadPack.deadPack != null && deadPack.deadPack.packUID > maxDeathPackUID)
+            {
+                maxDeathPackUID = deadPack.deadPack.packUID;
+                lastBattleDeadPack = deadPack;
+            }
+        }
+
+        // 濡傛灉鎵惧埌浜嗘浜″寘锛屾敹闆嗘墍鏈� packUID > maxDeathPackUID 鐨勫寘
+        if (maxDeathPackUID > 0 && lastBattleDeadPack != null)
+        {
+            BattleDebug.LogError($"SkillBase.HandleDead: 鎵惧埌姝讳骸鍖咃紝maxDeathPackUID = {maxDeathPackUID}锛屽紑濮嬫敹闆嗘浜″悗鐨勫寘");
+
+            // 1. 鏀堕泦 packList 涓� packUID 澶т簬姝讳骸鍖呯殑鍖咃紙鎺掗櫎缁忛獙鍖呭拰鎺夎惤鍖咃紝瀹冧滑闇�瑕佸湪褰撳墠鎶�鑳戒腑澶勭悊锛�
+            List<GameNetPackBasic> packsToRemove = new List<GameNetPackBasic>();
+            foreach (var pack in packList)
+            {
+                ulong packUID = GetPackUID(pack);
+                if (packUID > maxDeathPackUID)
+                {
+                    // 鎺掗櫎缁忛獙鍖呭拰鎺夎惤鍖咃紝瀹冧滑灞炰簬褰撳墠姝讳骸浜嬩欢鐨勪竴閮ㄥ垎锛屼笉鏄�"姝讳骸鍚�"鐨勫寘
+                    if (pack is HB405_tagMCAddExp expPack && expPack.Source == 2 ||
+                        (pack is H0704_tagRolePackRefresh h0704 && h0704.PackType == (byte)PackType.DropItem && h0704.IsBind == 1))
+                    {
+                        continue; // 璺宠繃缁忛獙鍖呭拰鎺夎惤鍖咃紝璁� CheckAfterDeadhPack() 澶勭悊瀹冧滑
+                    }
+
+                    BattleDebug.LogError($"SkillBase.HandleDead: 浠巔ackList鏀堕泦姝讳骸鍚庣殑鍖� - Type: {pack.GetType().Name}, UID: {packUID}");
+                    lastBattleDeadPack.packListAfterDeath.Add(pack);
+                    packsToRemove.Add(pack);
+                }
+            }
+
+            packList.RemoveAll(p => packsToRemove.Contains(p));
+        }
+
+        CheckAfterDeadhPack();
+
+        // 淇锛氬厛鏀堕泦瑕佸垹闄ょ殑鍖咃紝閬垮厤鍦╢oreach涓慨鏀归泦鍚�
+        var dropPacksToRemove = new List<H0704_tagRolePackRefresh>(dropPackList);
+        foreach (var _dropPack in dropPacksToRemove)
+        {
+            // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
+            // 鍘熷洜锛氭帀钀藉寘鏄妧鑳芥晥鏋滅殑涓�閮ㄥ垎锛屽簲璇ョ敱褰撳墠SkillRecordAction绠$悊
+            // 鎺夎惤鍖呯殑鍒嗗彂涓庢妧鑳藉畬鎴愮粦瀹氾紝纭繚鍦ㄦ妧鑳紽orceFinish鏃舵纭鐞�
+            PackageRegeditEx.DistributeToRecordAction(_dropPack, ownRecordAction);
+            packList.Remove(_dropPack);
+        }
+
+        // 鑾峰彇骞跺垎閰嶆帀钀界墿鍝佸拰缁忛獙
+        var dropPack = PackManager.Instance.GetSinglePack(PackType.DropItem);
+        var itemDict = dropPack.GetAllItems();
+        List<ItemModel> itemList = new List<ItemModel>(itemDict.Values.Where(item => item != null && item.isAuction));
+
+        var dropAssign = AssignDrops(itemList, deadPackList.Count);
+        var expAssign = AssignExp(expPackList, deadPackList.Count);
+
+        // 鏋勯�燘attleDrops骞剁紦瀛�
+        for (int i = 0; i < deadPackList.Count; i++)
+        {
+            BattleDeadPack bdp = deadPackList[i];
+            int objID = (int)bdp.deadPack.ObjID;
+            BattleObject deadTarget = battleField.battleObjMgr.GetBattleObject(objID);
+
+            // 淇锛氭坊鍔犵┖鍊兼鏌�
+            if (deadTarget == null)
+            {
+                Debug.LogError($"鎵句笉鍒版浜$洰鏍囷紝ObjID: {objID}");
+                continue;
+            }
+
+            List<int> itemIndexList = dropAssign[i].Select(item => item.gridIndex).ToList();
+
+            BattleDrops battleDrops = new BattleDrops()
+            {
+                rectTransform = deadTarget.GetRectTransform(),
+                dropItemPackIndex = itemIndexList,
+                expDrops = expAssign[i]
+            };
+
+            // 淇锛氶伩鍏嶅瓧鍏搁敭鍐茬獊锛屼娇鐢ㄥ畨鍏ㄧ殑娣诲姞鏂瑰紡
+            if (!tempDropList.ContainsKey(objID))
+            {
+                tempDropList.Add(objID, battleDrops);
+            }
+            else
+            {
+                Debug.LogWarning($"tempDropList涓凡瀛樺湪ObjID={objID}鐨勮褰曪紝灏嗚鐩栧師鍊�");
+                tempDropList[objID] = battleDrops; // 瑕嗙洊鐜版湁鍊�
+            }
+
+            if (!tempDeadPackList.ContainsKey(objID))
+            {
+                tempDeadPackList.Add(objID, deadPackList[i]);
+            }
+            else
+            {
+                Debug.LogWarning($"tempDeadPackList涓凡瀛樺湪ObjID={objID}鐨勮褰曪紝灏嗚鐩栧師鍊�");
+                tempDeadPackList[objID] = deadPackList[i]; // 瑕嗙洊鐜版湁鍊�
+            }
+        }
+
+        // 淇锛氶伩鍏嶅湪閬嶅巻鏃朵慨鏀归泦鍚堬紝鍏堟敹闆嗗悗鍒犻櫎
+        var deadPacksToRemove = new List<GameNetPackBasic>(deadPackList.Select(d => d.deadPack));
+        deadPacksToRemove.AddRange(deadPackList.Where(d => d.deadTriggerSkill != null).Select(d => d.deadTriggerSkill));
+        foreach (var deadPack in deadPacksToRemove)
+        {
+            packList.Remove(deadPack);
+        }
+    }
+
+    // 鍒嗛厤鎺夎惤鐗╁搧锛氬皢鎺夎惤鐗╁搧骞冲潎鍒嗛厤缁欐浜″璞�
+    protected List<List<ItemModel>> AssignDrops(List<ItemModel> itemList, int deadCount)
+    {
+        var dropAssign = new List<List<ItemModel>>();
+        for (int i = 0; i < deadCount; i++)
+            dropAssign.Add(new List<ItemModel>());
+        for (int i = 0; i < itemList.Count; i++)
+            dropAssign[i % deadCount].Add(itemList[i]);
+        return dropAssign;
+    }
+
+    // 鑾峰彇鍖呯殑 packUID
+    protected ulong GetPackUID(GameNetPackBasic pack)
+    {
+        if (pack == null) return 0;
+
+        if (pack is HB422_tagMCTurnFightObjDead deadPack)
+            return deadPack.packUID;
+
+        if (pack is CustomHB426CombinePack combinePack)
+        {
+            var mainSkillPack = combinePack.GetMainHB427SkillPack();
+            return mainSkillPack?.packUID ?? 0;
+        }
+
+        if (pack is HB427_tagSCUseSkill skillPack)
+            return skillPack.packUID;
+
+        if (pack is HB428_tagSCBuffRefresh buffRefresh)
+            return buffRefresh.packUID;
+
+        if (pack is HB429_tagSCBuffDel buffDel)
+            return buffDel.packUID;
+
+        if (pack is HB419_tagSCObjHPRefresh hpRefresh)
+            return hpRefresh.packUID;
+
+        if (pack is HB405_tagMCAddExp expPack)
+            return expPack.packUID;
+
+        if (pack is H0704_tagRolePackRefresh dropPack)
+            return dropPack.packUID;
+
+        // 灏濊瘯閫氳繃鍙嶅皠鑾峰彇 packUID
+        var packUIDField = pack.GetType().GetField("packUID");
+        if (packUIDField != null)
+        {
+            return (ulong)packUIDField.GetValue(pack);
+        }
+
+        return 0;
+    }
+
+    // 鍒嗛厤缁忛獙鍊硷細灏嗙粡楠屽寘骞冲潎鍒嗛厤缁欐瘡涓浜″璞�
+    protected List<List<HB405_tagMCAddExp>> AssignExp(List<HB405_tagMCAddExp> expList, int deadCount)
+    {
+        var expAssign = new List<List<HB405_tagMCAddExp>>();
+        for (int i = 0; i < deadCount; i++)
+            expAssign.Add(new List<HB405_tagMCAddExp>());
+
+        // 淇锛氭鏌ラ櫎闆堕闄�
+        if (deadCount == 0)
+        {
+            Debug.LogWarning("AssignExp: deadCount涓�0锛屾棤娉曞垎閰嶇粡楠�");
+            return expAssign;
+        }
+
+        // 淇锛氬厛鏀堕泦瑕佸垹闄ょ殑鍖咃紝閬垮厤鍦╢oreach涓慨鏀筽ackList
+        var expPacksToRemove = new List<HB405_tagMCAddExp>();
+
+        foreach (var expPack in expList)
+        {
+            long totalExp = GeneralDefine.GetFactValue(expPack.Exp, expPack.ExpPoint);
+            long avgExp = totalExp / deadCount;
+            long remain = totalExp % deadCount;
+
+            for (int i = 0; i < deadCount; i++)
+            {
+                long assignExp = avgExp + (i < remain ? 1 : 0);
+                var newPack = new HB405_tagMCAddExp
+                {
+                    Exp = (uint)(assignExp % Constants.ExpPointValue),
+                    ExpPoint = (uint)(assignExp / Constants.ExpPointValue),
+                    Source = expPack.Source
+                };
+                expAssign[i].Add(newPack);
+            }
+            expPacksToRemove.Add(expPack);
+        }
+
+        // 缁熶竴鍒犻櫎鏀堕泦鐨勫寘
+        foreach (var pack in expPacksToRemove)
+        {
+            packList.Remove(pack);
+        }
+
+        return expAssign;
+    }
+
+    /// <summary>
+    /// 灏� tempDeadPackList 閲� pending 鐨勬浜″寘鎶曢�掔粰 BattleField 鐢熸垚 DeathRecordAction銆�
+    /// 鍚堝苟 IsFinished锛堟甯哥粨鏉燂級涓� ForceFinished锛堝己鍒剁粨鏉燂級涓ゆ潯璺緞鐨勫叡鍚岄儴鍒嗐��
+    /// </summary>
+    /// <param name="useInnerPlayer">
+    /// true锛氭妸 DeathRecordAction 缁戝畾鍒� ownRecordAction锛堟甯哥粨鏉燂紝姝讳骸鍔ㄤ綔浼氱瓑寰呭綋鍓嶆妧鑳藉畬鎴愶級锛�
+    /// false锛氫笉缁戝畾锛堝己鍒剁粨鏉燂紝姝讳骸鍔ㄤ綔绔嬪嵆鍦ㄩ粯璁� RecordPlayer 閲屾挱鏀撅級銆�
+    /// </param>
+    /// <param name="clearEvenIfNotDispatched">
+    /// true锛氭棤璁烘槸鍚︽姇閫掓垚鍔熼兘娓呯┖ tempDeadPackList锛團orceFinished 璇箟锛夛紱
+    /// false锛氫粎鍦ㄦ垚鍔熸姇閫� DeathRecordAction 鏃舵竻绌猴紙IsFinished 璇箟锛夈��
+    /// </param>
+    /// <returns>鏄惁鎴愬姛鎶曢�掍簡 DeathRecordAction銆�</returns>
+    protected bool FlushPendingDeathActions(bool useInnerPlayer, bool clearEvenIfNotDispatched)
+    {
+        //  闃插尽锛歜attleField / caster 浠讳竴涓� null 鏃剁洿鎺ヨ繑鍥烇紝閬垮厤 NullReferenceException銆�
+        if (battleField == null || caster == null)
+        {
+            if (clearEvenIfNotDispatched) tempDeadPackList.Clear();
+            return false;
+        }
+
+        //  缁熶竴鍋氱殑浜嬶細浠庢垬鍦� casting 娉ㄥ唽閲岀Щ闄よ嚜韬��
+        battleField.RemoveCastingSkill(caster.ObjID, this);
+
+        var deadPacks = new List<BattleDeadPack>(tempDeadPackList.Values);
+        //  涓ゆ潯璺緞鐨勫敮涓�宸埆锛氭槸鍚︽妸 DeathRecordAction 缁戝畾鍒� ownRecordAction锛堣姝讳骸鍔ㄤ綔绛夋妧鑳藉畬鎴愶級銆�
+        DeathRecordAction recordAction = useInnerPlayer
+            ? battleField.OnObjsDead(deadPacks, null, ownRecordAction)
+            : battleField.OnObjsDead(deadPacks);
+
+        if (null != recordAction && ownRecordAction != null)
+        {
+            ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAction);
+            tempDeadPackList.Clear();
+            return true;
+        }
+
+        if (clearEvenIfNotDispatched)
+        {
+            tempDeadPackList.Clear();
+        }
+        return false;
+    }
+
+    // 妫�鏌ユ浜″悗鐨勫寘澶勭悊锛氬鐞嗘妧鑳藉寘銆佹帀钀藉寘銆佺粡楠屽寘
+    protected void CheckAfterDeadhPack()
+    {
+        List<int> removeIndexList = new List<int>();
+
+        for (int i = 0; i < packList.Count; i++)
+        {
+            var pack = packList[i];
+
+            // 澶嶆椿鍩烘湰閮介潬鎶�鑳藉寘
+            if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
+                break;
+
+            if (pack is H0704_tagRolePackRefresh h0704Pack && h0704Pack.PackType == (byte)PackType.DropItem && h0704Pack.IsBind == 1)
+            {
+                dropPackList.Add(h0704Pack);
+                removeIndexList.Add(i);
+            }
+
+            if (pack is HB405_tagMCAddExp h405Pack && h405Pack.Source == 2)
+            {
+                expPackList.Add(h405Pack);
+                removeIndexList.Add(i);
+            }
+        }
+
+        for (int i = removeIndexList.Count - 1; i >= 0; i--)
+            packList.RemoveAt(removeIndexList[i]);
+    }
+}
diff --git a/Main/System/Battle/Skill/SkillBase.Death.cs.meta b/Main/System/Battle/Skill/SkillBase.Death.cs.meta
new file mode 100644
index 0000000..cbf92e4
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Death.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b94f32045be1dcd4793d5d0c275b969a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/Skill/SkillBase.Finish.cs b/Main/System/Battle/Skill/SkillBase.Finish.cs
new file mode 100644
index 0000000..b8758c4
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Finish.cs
@@ -0,0 +1,480 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+// SkillBase锛團inish 閮ㄥ垎锛夛細瀹屾垚鍒ゅ畾涓庡己鍒剁粨鏉熴��
+public partial class SkillBase
+{
+    public virtual bool IsActionCompleted()
+    {
+        if (!isPlay) return false;
+
+        if (skillEffect != null)
+        {
+            if (!skillEffect.IsFinished()) return false;
+        }
+
+        if (moveFinished)
+        {
+            //  濡傛灉鎶�鑳芥湁鍔ㄧ敾锛圫killMotionName涓嶄负绌猴級锛岄渶瑕佺瓑寰呭姩鐢绘挱鏀惧畬鎴�
+            if (skillSkinConfig != null && !string.IsNullOrEmpty(skillSkinConfig.SkillMotionName))
+            {
+                if (!isMotionCompleted)
+                {
+                    BattleDebug.LogError($"SkillBase.IsActionCompleted: 鎶�鑳� {skillConfig.SkillID} 绛夊緟鍔ㄧ敾鎾斁瀹屾垚");
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    // 妫�鏌ユ妧鑳芥槸鍚﹀畬鎴愶細缁煎悎妫�鏌ユ墍鏈夊畬鎴愭潯浠�
+    public virtual bool IsFinished()
+    {
+        if (!isPlay)
+        {
+            ReportStuckIfNeeded("isPlay=false锛圤nSkillStart 鏈璋冪敤鎴栨彁鍓嶉��鍑猴級");
+            return false;
+        }
+
+        bool tempRetValue = true;
+
+        // 妫�鏌ユ妧鑳芥晥鏋滄槸鍚﹀畬鎴�
+        if (skillEffect != null)
+        {
+            if (!skillEffect.IsFinished())
+            {
+                ReportStuckIfNeeded("skillEffect 鏈畬鎴�");
+                return false;
+            }
+            skillEffect = null;
+            OnSkillFinished();
+            tempRetValue = false;
+        }
+
+        // 妫�鏌ュ叾浠栨妧鑳藉姩浣滄槸鍚﹀畬鎴�
+        if (currentWaitingSkill.Count > 0)
+        {
+            if (currentWaitingSkill.Any(s => s.IsFinished()))
+            {
+                currentWaitingSkill.RemoveAll(s => s.IsFinished());
+                OnSkillFinished();
+            }
+            else
+            {
+                tempRetValue = false;
+            }
+        }
+
+        if (!tempRetValue)
+        {
+            if (currentWaitingSkill.Count > 0)
+            {
+                ReportStuckIfNeeded($"currentWaitingSkill 浠嶆湁 {currentWaitingSkill.Count} 涓瓙鍔ㄤ綔");
+            }
+            return false;
+        }
+
+
+        // 妫�鏌ユ渶缁堝畬鎴愮姸鎬�
+        if (isFinished && moveFinished)
+        {
+            if (packList.Count > 0)
+            {
+                OnSkillFinished();
+                ReportStuckIfNeeded($"packList 浠嶅墿 {packList.Count} 涓寘锛孯esolvePackList 鏈秷璐瑰畬");
+                return false;
+            }
+
+            //  濡傛灉鑷繁鍐呴儴鐨剅ecora action鐨� inner record player杩樻湁娌℃墽琛屽畬鐨勫寘 涔熸槸杩斿洖false
+            if (ownRecordAction != null && ownRecordAction.GetInnerRecordPlayer().IsPlaying())
+            {
+                ReportStuckIfNeeded("ownRecordAction.innerRecordPlayer.IsPlaying() == true锛堝瓙 RecordAction 鏈挱瀹岋級");
+                return false;
+            }
+
+            // 鎶�鑳藉畬鍏ㄧ粨鏉燂紝绉婚櫎鎶�鑳芥敞鍐屽苟瑙﹀彂寤惰繜鐨勬浜″垽瀹�
+            //  useInnerPlayer=true锛欴eathRecordAction 鎶曞埌 ownRecordAction.innerRecordPlayer锛岀瓑寰呭綋鍓嶆妧鑳藉畬鎴�
+            //  clearEvenIfNotDispatched=false锛氫繚鎸佸師鏈夎涓猴紝OnObjsDead 杩斿洖 null 鏃朵笉娓呯┖缂撳瓨
+            if (FlushPendingDeathActions(useInnerPlayer: true, clearEvenIfNotDispatched: false))
+            {
+                ReportStuckIfNeeded("FlushPendingDeathActions 鎶曢�掍簡 DeathRecordAction锛岀瓑寰呭叾鎾斁瀹屾垚");
+                return false;
+            }
+
+            bool done = !ownRecordAction.GetInnerRecordPlayer().IsPlaying();
+            if (!done) ReportStuckIfNeeded("鏈熬 innerRecordPlayer.IsPlaying() == true");
+            else       ResetStuckCounter();
+            return done;
+        }
+
+        ReportStuckIfNeeded($"isFinished={isFinished} moveFinished={moveFinished}锛堣繕娌″埌鏈锛�");
+        return false;
+    }
+
+#if UNITY_EDITOR
+    //  鍗℃渚︽祴璁℃暟鍣細IsFinished 杩炵画澶氬皯娆¤繑鍥� false銆�
+    //  绗� StuckThreshold 娆¢娆� dump锛屼箣鍚庢瘡 StuckRepeatInterval 娆″啀 dump锛岄伩鍏嶅埛灞忋��
+    private int _stuckCheckCount = 0;
+    private string _lastStuckReason = null;
+    private const int StuckThreshold = 120;        // ~2 绉掞紙60fps锛�
+    private const int StuckRepeatInterval = 180;   // ~3 绉�
+#endif
+
+    /// <summary>
+    /// 褰� IsFinished 鎸佺画杩斿洖 false 鏃舵墦涓�娆¤缁嗚瘖鏂�俽eason 鎻忚堪闃诲鍘熷洜銆�
+    /// 鍙湪 UNITY_EDITOR + BattleDebug 寮�鍏充笅杈撳嚭銆�
+    /// </summary>
+    private void ReportStuckIfNeeded(string reason)
+    {
+#if UNITY_EDITOR
+        _stuckCheckCount++;
+
+        //  闃诲鍘熷洜鍒囨崲浜� 鈫� 绔嬪埢鎵撲竴娆★紝骞堕噸缃鏁�
+        bool reasonChanged = _lastStuckReason != reason;
+        if (reasonChanged)
+        {
+            _lastStuckReason = reason;
+            _stuckCheckCount = 1;
+        }
+
+        bool firstHit = _stuckCheckCount == StuckThreshold;
+        bool repeat   = _stuckCheckCount > StuckThreshold
+                     && (_stuckCheckCount - StuckThreshold) % StuckRepeatInterval == 0;
+
+        if (!firstHit && !repeat) return;
+
+        int skillId = skillConfig != null ? skillConfig.SkillID : 0;
+        ulong casterId = tagUseSkillAttack != null ? tagUseSkillAttack.ObjID : 0UL;
+
+        string subSkillDump = "  (鏃�)";
+        if (currentWaitingSkill.Count > 0)
+        {
+            var lines = new List<string>();
+            for (int i = 0; i < currentWaitingSkill.Count; i++)
+            {
+                var s = currentWaitingSkill[i];
+                lines.Add($"    [{i}] type={s.GetType().Name} IsFinished={s.IsFinished()}");
+            }
+            subSkillDump = string.Join("\n", lines);
+        }
+
+        string packListDump = "  (鏃�)";
+        if (packList != null && packList.Count > 0)
+        {
+            var lines = new List<string>();
+            for (int i = 0; i < packList.Count && i < 8; i++)
+            {
+                var p = packList[i];
+                string tag = p is CustomHB426CombinePack cb ? $" tag={cb.startTag?.Tag}" : "";
+                lines.Add($"    [{i}] {p.GetType().Name}{tag}");
+            }
+            if (packList.Count > 8) lines.Add($"    ... 杩樻湁 {packList.Count - 8} 涓�");
+            packListDump = string.Join("\n", lines);
+        }
+
+        bool innerPlaying = ownRecordAction != null && ownRecordAction.GetInnerRecordPlayer().IsPlaying();
+
+        string innerPlayerDump = "  (innerRecordPlayer: 鏃�)";
+        if (ownRecordAction != null)
+        {
+            innerPlayerDump = "  innerRecordPlayer: " + ownRecordAction.GetInnerRecordPlayer().DumpPlayingState();
+        }
+
+        //  棰濆璇婃柇锛歝aster 鍔ㄧ敾鐘舵�� + SkillEffect 鍐呴儴鏍囧織浣� + 鎶�鑳藉姩浣滃悕
+        string casterAnim = "  (caster 淇℃伅涓嶅彲鐢�)";
+        if (caster is HeroBattleObject hbo && hbo.motionBase != null)
+        {
+            casterAnim = $"  caster.motionBase: playingSkillWithAnim={hbo.motionBase.PlayingSkillWithAnimForDebug}";
+            //  [鍗℃璇婃柇] 褰� playingSkillWithAnim=true 浣嗘湰 skillBase 杩樻病 OnSkillStart锛�
+            //  涓�娆℃�ф妸 MotionBase 鐨勭幇鍦轰篃 dump 鍑烘潵锛氶攣鏄皝鍔犵殑 + 娲昏穬杞ㄩ亾鍒楄〃 + 鍔犻攣鏃剁殑璋冪敤鏍堛��
+            //  杩欐牱 SkillBase 鐨� 120 甯у崱姝绘姤鍛婂氨鑳界洿鎺ュ畾浣嶅埌 MotionBase 渚х殑 owner skill銆�
+            if (hbo.motionBase.PlayingSkillWithAnimForDebug)
+            {
+                int ownerSid = hbo.motionBase.PlayingSkillAnimOwnerSkillIdForDebug;
+                int ownerFrame = hbo.motionBase.PlayingSkillAnimOwnerFrameForDebug;
+                int elapsed = ownerFrame > 0 ? (UnityEngine.Time.frameCount - ownerFrame) : -1;
+                casterAnim += $"\n  MotionBase閿佹寔鏈夎��: skillId={ownerSid} setFrame={ownerFrame} 宸叉寔鏈墈elapsed}甯�";
+                casterAnim += $"\n  MotionBase鐜板満: {hbo.motionBase.DumpActiveTracksForDebug()}";
+                string ownerStack = hbo.motionBase.PlayingSkillAnimOwnerStackForDebug;
+                if (!string.IsNullOrEmpty(ownerStack))
+                {
+                    casterAnim += $"\n  MotionBase閿佸姞閿佽皟鐢ㄦ爤:\n{ownerStack}";
+                }
+            }
+        }
+        string skinInfo = $"  skillSkinConfig.SkillMotionName={(skillSkinConfig == null ? "null" : (string.IsNullOrEmpty(skillSkinConfig.SkillMotionName) ? "(绌�)" : skillSkinConfig.SkillMotionName))}";
+        string skillEffectDump = skillEffect == null ? "  skillEffect=null" : $"  skillEffect: {skillEffect.DumpState()}";
+
+        BattleDebug.LogError(
+            "SkillBase.IsFinished 鐤戜技鍗℃ (鎸佺画 " + _stuckCheckCount + " 娆℃湭瀹屾垚)\n" +
+            $"  skillId={skillId} caster={casterId} 鍘熷洜: {reason}\n" +
+            $"  StateFlags={_stateFlags}\n" +
+            $"{skillEffectDump}\n" +
+            $"{skinInfo}\n" +
+            $"{casterAnim}\n" +
+            $"  currentWaitingSkill.Count={currentWaitingSkill.Count}\n{subSkillDump}\n" +
+            $"  packList.Count={(packList?.Count ?? 0)}\n{packListDump}\n" +
+            $"  innerRecordPlayer.IsPlaying={innerPlaying}\n" +
+            $"{innerPlayerDump}\n" +
+            $"  tempDeadPackList.Count={tempDeadPackList.Count}\n" +
+            $"  buffPackCollections.Count={buffPackCollections.Count}");
+#endif
+    }
+
+    private void ResetStuckCounter()
+    {
+#if UNITY_EDITOR
+        _stuckCheckCount = 0;
+        _lastStuckReason = null;
+#endif
+    }
+
+
+    // 寮哄埗缁撴潫鎶�鑳斤細绔嬪嵆缁撴潫鎵�鏈夋妧鑳界浉鍏崇殑澶勭悊
+    public virtual void ForceFinished()
+    {
+        if (isFinished)
+            return;
+
+        //  寮哄埗缁撴潫璺緞锛氱Щ闄ゆ敞鍐� + 鎶曢�掓浜″姩浣滐紙涓嶇瓑鎶�鑳藉畬鎴愶紝鐩存帴鎾斁锛�+ 濮嬬粓娓呯┖缂撳瓨銆�
+        //  useInnerPlayer=false 淇濇寔鍘� ForceFinished 鐨勮涓猴紙涓嶆寚瀹� _playSkillRecordAction锛夈��
+        //  clearEvenIfNotDispatched=true 淇濇寔 ForceFinished 鍘熸湁鐨�"鏃犺鏄惁鎶曢�掗兘 Clear"璇箟銆�
+        FlushPendingDeathActions(useInnerPlayer: false, clearEvenIfNotDispatched: true);
+
+        // 1. 寮哄埗缁撴潫鎶�鑳芥晥鏋�
+        skillEffect?.ForceFinished();
+        skillEffect = null;
+
+        // 2. 寮哄埗缁撴潫鎵�鏈夊瓙鎶�鑳藉姩浣�
+        if (currentWaitingSkill.Count > 0)
+        {
+            foreach (var skill in currentWaitingSkill)
+            {
+                skill.ForceFinish();
+            }
+            currentWaitingSkill.Clear();
+        }
+
+        // 3. 娓呯悊 DOTween 鍔ㄧ敾锛堥槻姝㈢Щ鍔ㄥ洖璋冨湪鎴樻枟缁撴潫鍚庢墽琛岋級
+        if (caster != null)
+        {
+            caster.StopMoveAnimation();
+        }
+
+        // 4. 閲嶇疆鏂芥硶鑰呯姸鎬�
+        if (caster != null)
+        {
+            // 閲嶇疆浣嶇疆鍒板師鐐�
+            caster.ResetPosition();
+
+            // 閲嶇疆鏈濆悜
+            caster.ResetFacing();
+
+            // 鍙栨秷骞诲奖鏁堟灉
+            caster.ShowIllusionShadow(false);
+        }
+
+        // 5. 鎭㈠ UI 鐘舵��
+        if (battleField != null)
+        {
+            // 鎭㈠鎵�鏈夎鑹茬殑鏄剧ず灞傜骇鍜岃鏉�
+            var allList = battleField.battleObjMgr?.allBattleObjDict?.Values;
+            if (allList != null)
+            {
+                foreach (BattleObject bo in allList)
+                {
+                    bo.layerMgr?.SetFront();
+                    bo.GetHeroInfoBar()?.SetActive(true);
+                }
+            }
+
+            // 鍏抽棴鎶�鑳介伄缃�
+            if (battleField.battleRootNode != null && battleField.battleRootNode.skillMaskNode != null)
+            {
+                battleField.battleRootNode.skillMaskNode.SetActive(false);
+            }
+        }
+
+        isFinished = true;
+        moveFinished = true;
+        isPlay = true;
+
+        //  寮哄埗缁撴潫鏃讹紝鏃犺鏄惁鏈夊姩鐢伙紝閮芥爣璁板姩鐢诲畬鎴�
+        isMotionCompleted = true;
+
+        // 6. 澶勭悊鎵�鏈夊墿浣欏寘锛堝寘鎷� buff 鍖咃級
+        // 鍏堝鐞� buffPackCollections
+        DistributeBuffPacks(buffPackCollections);
+        buffPackCollections.Clear();
+
+        // 澶勭悊鍓╀綑鐨� packList
+        while (packList.Count > 0)
+        {
+            var pack = packList[0];
+            packList.RemoveAt(0);
+
+            if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
+            {
+                var otherSkillAction = combinePack.CreateSkillAction();
+                otherSkillAction.fromSkill = this;
+                otherSkillAction.ForceFinish();
+            }
+            else
+            {
+                // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
+                // 鍘熷洜锛欶orceFinished鏃跺墿浣欑殑鍖呬篃鏄妧鑳藉唴閮ㄤ骇鐢熺殑锛屽簲璇ョ敱innerRecordPlayer绠$悊
+                // 杩欐牱鍙互纭繚鍗充娇寮哄埗缁撴潫锛屽寘鐨勫鐞嗕篃鍦ㄦ纭殑涓婁笅鏂囦腑
+                PackageRegedit.Distribute(pack);
+            }
+        }
+    }
+
+    // 鎶�鑳藉畬鎴愬鐞嗭細姝e父瀹屾垚鏃剁殑娓呯悊宸ヤ綔
+    public void OnSkillFinished()
+    {
+        // 淇锛氫娇鐢ㄥ惊鐜唬鏇块�掑綊锛岄伩鍏嶆爤婧㈠嚭椋庨櫓
+        while (true)
+        {
+            // 楠岃瘉鎶�鑳芥晥鏋滄槸鍚﹀畬鎴�
+            if (skillEffect != null && !skillEffect.IsFinished())
+                return;
+
+            if (skillEffect != null)
+            {
+                skillEffect = null;
+                continue; // 浣跨敤continue浠f浛閫掑綊璋冪敤
+            }
+
+            // 楠岃瘉鍏朵粬鎶�鑳藉姩浣滄槸鍚﹀畬鎴�
+            if (currentWaitingSkill.Count > 0)
+            {
+                bool hasFinishedAction = currentWaitingSkill.All(s => s.IsFinished());
+
+                if (hasFinishedAction)
+                {
+                    // 淇姝诲惊鐜細瀹屾垚鍚庨渶瑕佹竻绌� currentWaitingSkill
+                    currentWaitingSkill.Clear();
+                    continue; // 浣跨敤continue浠f浛閫掑綊璋冪敤
+                }
+                return;
+            }
+
+            break; // 娌℃湁鏇村闇�瑕佸鐞嗙殑锛岄��鍑哄惊鐜�
+        }
+
+        // 澶勭悊鍓╀綑鍖�
+        if (!ResolvePackList())
+        {
+            return;
+        }
+
+        isFinished = true;
+    }
+
+    protected virtual bool ResolvePackList()
+    {
+        if (currentWaitingSkill.Count > 0)
+        {
+            return false;
+        }
+
+        while (packList.Count > 0)
+        {
+            var pack = packList[0];
+            packList.RemoveAt(0);
+
+
+            if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
+            {
+                var skillRecordAction = combinePack.CreateSkillAction();
+                skillRecordAction.fromSkill = this;
+                currentWaitingSkill.Add(skillRecordAction);
+
+                //  闇�瑕佺粰鐪熸parent鎾殑
+                if (skillRecordAction.useParentRecordPlayer && skillRecordAction.parentSkillAction != null)
+                {
+                    skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
+                }
+                else
+                {
+                    ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
+                }
+
+                return false;
+            }
+            else if (IsBuffPack(pack))
+            {
+                // 浠庢壘鍒扮涓�涓� Buff 鍖呭紑濮嬶紝鏀堕泦杩炵画鐨� HB428/HB429 鍖�
+                buffPackCollections.Add(pack);
+                while (packList.Count > 0)
+                {
+                    var nextPack = packList[0];
+                    if (IsBuffPack(nextPack))
+                    {
+                        buffPackCollections.Add(nextPack);
+                        packList.RemoveAt(0);
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+
+                // 澶勭悊鎵�鏈夋敹闆嗗埌鐨� buff 鍖�
+                ProcessBuffPacks(buffPackCollections);
+
+                // 娓呯┖宸插鐞嗙殑 buff 闆嗗悎
+                buffPackCollections.Clear();
+                continue;
+            }
+            else
+            {
+                // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
+                // 鍘熷洜锛氭妧鑳芥墽琛岃繃绋嬩腑鐨勫寘锛圔uff銆佸睘鎬у埛鏂扮瓑锛夋槸鎶�鑳芥晥鏋滅殑涓�閮ㄥ垎
+                // 搴旇鐢盨killRecordAction鐨刬nnerRecordPlayer绠$悊锛岀‘淇濅笌鎶�鑳界敓鍛藉懆鏈熶竴鑷�
+                PackageRegeditEx.DistributeToRecordAction(pack, ownRecordAction);
+            }
+        }
+
+        return true;
+    }
+
+    // 娣诲姞娓呯悊鏂规硶锛氶槻姝㈠唴瀛樻硠婕�
+    public virtual void Cleanup()
+    {
+        tempDropList?.Clear();
+        tempDeadPackList?.Clear();
+        currentWaitingSkill?.Clear();
+        dropPackList?.Clear();
+        expPackList?.Clear();
+        buffPackCollections?.Clear();
+
+        skillEffect = null;
+        packList = null;
+    }
+
+    public virtual bool CanStartExecution()
+    {
+        if (null == caster)
+        {
+            return false;
+        }
+
+        if (null == skillConfig)
+        {
+            return false;
+        }
+
+        if (string.IsNullOrEmpty(skillSkinConfig.SkillMotionName))
+        {
+            return true;
+        }
+
+        return !battleField.IsCastingSkill(caster.ObjID);
+    }
+}
diff --git a/Main/System/Battle/Skill/SkillBase.Finish.cs.meta b/Main/System/Battle/Skill/SkillBase.Finish.cs.meta
new file mode 100644
index 0000000..d8d5bf4
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Finish.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a8ac29e3b0befe44c8eda664b3586454
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/Skill/SkillBase.Hit.cs b/Main/System/Battle/Skill/SkillBase.Hit.cs
new file mode 100644
index 0000000..a46e286
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Hit.cs
@@ -0,0 +1,241 @@
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+// SkillBase锛圚it 閮ㄥ垎锛夛細鍛戒腑闃舵鈥斺�擮nHit 鍒嗗彂鍒颁富鐩爣 / 婧呭皠鐩爣 / 鍛戒腑鎻愮ず銆�
+public partial class SkillBase
+{
+    // 鍛戒腑鐩爣鍥炶皟锛氬鐞嗘墍鏈夎鍛戒腑鐨勭洰鏍囷紙鍖呮嫭涓荤洰鏍囥�佸脊灏勭洰鏍囥�佹簠灏勭洰鏍囷級
+    protected virtual void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
+    {
+        // Debug.LogError($"Skill {skillConfig.SkillID} hit targets _hitIndex: {_hitIndex} hit {string.Join(", ", hitList.Select(h => h.ObjID + ":" + battleField.battleObjMgr.GetBattleObject((int)h.ObjID)?.GetName()))}");
+
+        //  閫犳垚浼ゅ鍓嶅厛澶勭悊琛�閲忓埛鏂板寘
+        HandleRefreshHP();
+
+        bool suckHp = true;
+
+        // 澶勭悊涓荤洰鏍囧垪琛�
+        foreach (var hurt in hitList)
+        {
+            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
+            if (target == null)
+            {
+                Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                continue;
+            }
+
+            OnHitEachTarget(_hitIndex, target, hurt, suckHp);
+
+            suckHp = false;
+
+            // 澶勭悊璇ョ洰鏍囩殑棰濆鐩爣鍒楄〃锛堝寮瑰皠浼ゅ鐨勫钩鎽婄洰鏍囷級
+            if (hurt.HurtListEx != null && hurt.HurtListEx.Length > 0)
+            {
+                foreach (var hurtEx in hurt.HurtListEx)
+                {
+                    BattleObject exTarget = caster.battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
+                    if (exTarget == null)
+                    {
+                        Debug.LogError($"棰濆鐩爣涓虹┖ HurtListEx target == null ObjId : {hurtEx.ObjID}");
+                        continue;
+                    }
+
+                    OnHitEachTargetEx(_hitIndex, exTarget, hurtEx);
+                }
+            }
+        }
+
+        // 澶勭悊鎶�鑳藉寘椤跺眰鐨勯澶栫洰鏍囧垪琛紙濡傛簠灏勪激瀹炽�佸钩鎽婁激瀹筹級
+        if (tagUseSkillAttack.HurtListEx != null && tagUseSkillAttack.HurtListEx.Length > 0)
+        {
+            foreach (var hurtEx in tagUseSkillAttack.HurtListEx)
+            {
+                BattleObject exTarget = caster.battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
+                if (exTarget == null)
+                {
+                    Debug.LogError($"椤跺眰棰濆鐩爣涓虹┖ tagUseSkillAttack.HurtListEx target == null ObjId : {hurtEx.ObjID}");
+                    continue;
+                }
+
+                OnHitEachTargetEx(_hitIndex, exTarget, hurtEx);
+            }
+        }
+
+        HandleHint(_hitIndex, hitList);
+    }
+
+    protected void HandleHint(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
+    {
+        if (0 == _hitIndex)
+        {
+            bool needhint = false;
+
+            for (int i = 0; i < hitList.Count; i++)
+            {
+                var hurt = hitList[i];
+
+                //8-鍑绘檿
+                if ((hurt.AttackTypes & (int)DamageType.Stunned) == (int)DamageType.Stunned)
+                {
+                    needhint = true;
+                    break;
+                }
+
+                for (int j = 0; j < hurt.HurtListEx?.Length; j++)
+                {
+                    var hurtex = hurt.HurtListEx[j];
+                    //8-鍑绘檿
+                    if ((hurtex.AttackTypes & (int)ServerDamageType.Stunned) == (int)ServerDamageType.Stunned)
+                    {
+                        needhint = true;
+                        break;
+                    }
+                }
+
+                if (needhint)
+                    break;
+            }
+
+            if (needhint)
+            {
+                DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.BattleStun);
+                Hint(caster, hintConfig);
+            }
+
+            for (int i = 0; i < hitList.Count; i++)
+            {
+                var hurt = hitList[i];
+
+                if ((hurt.AttackTypes & (int)DamageType.BreakArmor) == (int)DamageType.BreakArmor)
+                {
+                    BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
+                    if (battleObject != null)
+                    {
+                        DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.BreakArmor);
+                        Hint(battleObject, hintConfig);
+                        battleField.battleEffectMgr.PlayEffect(battleObject,
+                            BattleConst.BreakArmorEffectID, battleObject.GetRectTransform(), battleObject.Camp,
+                            battleObject.GetModelScale());
+                    }
+                }
+                else if ((hurt.AttackTypes & (int)DamageType.Parry) == (int)DamageType.Parry)
+                {
+                    BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
+                    if (battleObject != null)
+                    {
+                        DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.Parry);
+                        Hint(battleObject, hintConfig);
+                        battleField.battleEffectMgr.PlayEffect(battleObject,
+                            BattleConst.ParryEffectID, battleObject.GetRectTransform(), battleObject.Camp,
+                            battleObject.GetModelScale());
+                    }
+                }
+            }
+        }
+    }
+
+    // 澶勭悊鍗曚釜鐩爣琚懡涓�:搴旂敤浼ゅ鍜屾柦娉曡�呮晥鏋�
+    protected virtual void OnHitEachTarget(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, bool suckHp)
+    {
+        // ============ 鑾峰彇涓存椂鏁版嵁(鎺夎惤銆佹浜$瓑) ============
+        int objID = (int)target.ObjID;
+        tempDropList.TryGetValue(objID, out BattleDrops battleDrops);
+        tempDeadPackList.TryGetValue(objID, out BattleDeadPack deadPack);
+
+        // 濡傛灉鐩爣姝e湪閲婃斁鎶�鑳斤紝璺宠繃姝讳骸澶勭悊锛堝欢杩熷埌鎶�鑳界粨鏉燂級
+        if (battleField != null && battleField.IsCastingSkill(target.ObjID))
+        {
+            deadPack = null;
+        }
+
+        // ============ 鍙傛暟鎵撳寘 ============
+        BattleHurtParam hurtParam = BattleUtility.CalcBattleHurtParam(this, _hitIndex, target, hurt, battleDrops, deadPack, suckHp);
+#if UNITY_EDITOR
+        PrintHurtParamDebugInfo(hurtParam);
+#endif
+
+        // 鍏堣皟鐢ㄧ洰鏍囧彈浼�
+        DeathRecordAction recordAc = target.Hurt(hurtParam, ownRecordAction);
+
+        if (null != recordAc)
+        {
+            tempDeadPackList.Remove(hurtParam.hurter.hurtObj.ObjID);
+            ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAc, ownRecordAction, true);
+            currentWaitingSkill.Add(recordAc);
+        }
+
+        // 鍐嶈皟鐢ㄦ柦娉曡�呭惛琛�/鍙嶄激
+        caster.OnHurtTarget(hurtParam);
+    }
+
+    // 澶勭悊棰濆鐩爣琚懡涓紙HurtListEx锛夛細婧呭皠銆佸脊灏勩�佸钩鎽婁激瀹崇瓑
+    protected virtual void OnHitEachTargetEx(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurtEx hurtEx)
+    {
+        // ============ 鑾峰彇涓存椂鏁版嵁(鎺夎惤銆佹浜$瓑) ============
+        int objID = (int)target.ObjID;
+        tempDropList.TryGetValue(objID, out BattleDrops battleDrops);
+
+        tempDeadPackList.TryGetValue(objID, out BattleDeadPack deadPack);
+
+        // 濡傛灉鐩爣姝e湪閲婃斁鎶�鑳斤紝璺宠繃姝讳骸澶勭悊锛堝欢杩熷埌鎶�鑳界粨鏉燂級
+        if (battleField != null && battleField.IsCastingSkill(target.ObjID))
+        {
+            deadPack = null;
+        }
+        // ============ 鍙傛暟鎵撳寘锛堝皢 tagSCUseSkillHurtEx 杞崲涓� tagSCUseSkillHurt锛�============
+        HB427_tagSCUseSkill.tagSCUseSkillHurt hurt = new HB427_tagSCUseSkill.tagSCUseSkillHurt
+        {
+            ObjID = hurtEx.ObjID,
+            AttackTypes = hurtEx.AttackTypes,
+            HurtHP = hurtEx.HurtHP,
+            HurtHPEx = hurtEx.HurtHPEx,
+            CurHP = hurtEx.CurHP,
+            CurHPEx = hurtEx.CurHPEx,
+            SuckHP = 0,//hurtEx.SuckHP, 鑾峰彇鍏ㄩ儴鍚歌鏃跺凡缁忚绠楄繃 杩欓噷灏变笉鍐嶈绠�
+            BounceHP = 0, // HurtEx 娌℃湁鍙嶄激瀛楁
+            HurtCountEx = 0,
+            HurtListEx = null
+        };
+
+        OnHitEachTarget(_hitIndex, target, hurt, false);//鑾峰彇鍏ㄩ儴鍚歌鏃跺凡缁忚绠楄繃 杩欓噷灏变笉鍐嶈绠�
+    }
+
+#if UNITY_EDITOR
+    private void PrintHurtParamDebugInfo(BattleHurtParam hurtParam)
+    {
+        bool isLastHit = hurtParam.hitIndex >= hurtParam.skillSkinConfig.DamageDivide.Length - 1;
+
+        long currentHitDamage = hurtParam.hurter.damageList != null ? hurtParam.hurter.damageList.Sum() : 0;
+        long currentHitSuckHp = hurtParam.caster.suckHpList != null ? hurtParam.caster.suckHpList.Sum() : 0;
+        long currentHitReflectHp = hurtParam.caster.reflectHpList != null ? hurtParam.caster.reflectHpList.Sum() : 0;
+
+        long totalDamage = GeneralDefine.GetFactValue(hurtParam.hurt.HurtHP, hurtParam.hurt.HurtHPEx);
+        long totalSuckHp = BattleUtility.GetSuckHp(tagUseSkillAttack);
+        long totalReflectHp = hurtParam.hurt.BounceHP;
+
+        BattleDebug.LogError(
+            (hurtParam.caster.casterObj.Camp == BattleCamp.Red ? "銆愮孩鏂硅鍔ㄣ��" : "銆愯摑鏂硅鍔ㄣ�� ") +
+            $"鏀诲嚮鑰�: {hurtParam.caster.casterObj.GetName()} (ObjID:{hurtParam.caster.casterObj.ObjID})\n" +
+            $"鐩爣: {hurtParam.hurter.hurtObj.GetName()} (ObjID:{hurtParam.hurter.hurtObj.ObjID})\n" +
+            $"鎶�鑳�: {hurtParam.skillConfig.SkillName} (ID:{hurtParam.skillConfig.SkillID})\n" +
+            $"鍑绘暟: 绗瑊hurtParam.hitIndex + 1}鍑� / 鍏眥hurtParam.skillSkinConfig.DamageDivide.Length}鍑�" + (isLastHit ? " [鏈�鍚庝竴鍑籡" : " [涓棿鍑籡") + "\n" +
+            $"\n" +
+            $"========== 鐩爣鍙椾激鏁版嵁 ==========\n" +
+            $"浼ゅ: {currentHitDamage} / 鎬讳激瀹�: {totalDamage}\n" +
+            $"浼ゅ鍒嗘: [{string.Join(", ", hurtParam.hurter.damageList ?? new System.Collections.Generic.List<long>())}]\n" +
+            $"鐩爣琛�閲�: {hurtParam.hurter.fromHp} -> {hurtParam.hurter.toHp} (鏈�澶�:{hurtParam.hurter.maxHp})\n" +
+            $"鐩爣鎶ょ浘: {hurtParam.hurter.fromShieldValue} -> {hurtParam.hurter.toShieldValue}\n" +
+            $"鏀诲嚮绫诲瀷: {hurtParam.hurt.AttackTypes}\n" +
+            $"\n" +
+            $"========== 鏂芥硶鑰呮暟鎹� ==========\n" +
+            $"鍚歌: {currentHitSuckHp} / 鎬诲惛琛�: {totalSuckHp}\n" +
+            $"鍚歌鍒嗘: [{string.Join(", ", hurtParam.caster.suckHpList ?? new System.Collections.Generic.List<long>())}]\n" +
+            $"鍙嶄激: {currentHitReflectHp} / 鎬诲弽浼�: {totalReflectHp}\n" +
+            $"鍙嶄激鍒嗘: [{string.Join(", ", hurtParam.caster.reflectHpList ?? new System.Collections.Generic.List<long>())}]\n" +
+            $"鏂芥硶鑰呰閲�: {hurtParam.caster.fromHp} -> {hurtParam.caster.toHp} (鏈�澶�:{hurtParam.caster.maxHp})\n" +
+            $"鏂芥硶鑰呮姢鐩�: {hurtParam.caster.fromShieldValue} -> {hurtParam.caster.toShieldValue}\n"
+        );
+    }
+#endif
+}
diff --git a/Main/System/Battle/Skill/SkillBase.Hit.cs.meta b/Main/System/Battle/Skill/SkillBase.Hit.cs.meta
new file mode 100644
index 0000000..47ae2e2
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Hit.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 51400dced66a2be438fb359d60a01280
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/Skill/SkillBase.SubSkill.cs b/Main/System/Battle/Skill/SkillBase.SubSkill.cs
new file mode 100644
index 0000000..a3bb3d4
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.SubSkill.cs
@@ -0,0 +1,86 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+// SkillBase锛圫ubSkill 閮ㄥ垎锛夛細鍓嶇疆鍐呭祵瀛愭妧鑳界殑鏀堕泦涓庢姇閫掋��
+//
+// 瑙勫垯锛�
+//   浠� packList 澶撮儴杩炵画鏀堕泦"绾潤榛樺墠缃瓙鎶�鑳�"锛堟病鏈夊姩浣溿�侀潪姝讳骸澶嶆椿銆佷笉瑙﹀彂姝讳骸锛�
+//   鐩村埌閬囧埌浠讳綍涓�涓�"闇�瑕佺瓑寰�"鐨勫寘锛堝甫鍔ㄤ綔/SkillType==8/HB422锛夊氨鍋滄銆�
+//   宸叉敹闆嗙殑鍓嶇疆瀛愭妧鑳芥寜 packUID 鎺掑簭鍚庢姇閫掑埌 ownRecordAction.innerRecordPlayer銆�
+//
+// 瀛愭妧鑳介�掑綊鍒ゆ柇锛�
+//   褰撻亣鍒� CustomHB426CombinePack 鏃讹紝浣跨敤 combinePack.NeedWaiting() 鍒ゆ柇锛�
+//   NeedWaiting 鍐呴儴浼氶�掑綊妫�鏌ュ祵濂楃殑 CustomHB426CombinePack锛�
+//   鍥犳"瀛愭妧鑳介噷闈㈢殑瀛愭妧鑳�"涔熶細琚纭垽鏂��
+public partial class SkillBase
+{
+    protected void ProcessSubSkill()
+    {
+        // 鎸塸ackUID鎺掑簭鎵�鏈夊瓙鎶�鑳�
+        var allSubSkills = new List<(ulong packUID, SkillRecordAction action)>();
+
+        List<GameNetPackBasic> removePackList = new List<GameNetPackBasic>();
+
+        foreach (var pack in packList)
+        {
+            if (pack is HB427_tagSCUseSkill skillPack)
+            {
+                SkillConfig ssc = SkillConfig.Get((int)skillPack.SkillID);
+                SkillSkinConfig sscSkin = ssc.GetOriginSkinConfig();
+                if (!string.IsNullOrEmpty(sscSkin.SkillMotionName))
+                {
+                    break;
+                }
+                if (ssc.SkillType == 8)
+                {
+                    break;
+                }
+                SkillRecordAction skillRecordAction = CustomHB426CombinePack.CreateSkillAction(battleField.guid, new List<GameNetPackBasic> { skillPack });
+                allSubSkills.Add((skillPack.packUID, skillRecordAction));
+                removePackList.Add(pack);
+            }
+            else if (pack is HB422_tagMCTurnFightObjDead dead)
+            {
+                break;
+            }
+            else if (pack is CustomHB426CombinePack combinePack)
+            {
+                // 閫掑綊鍒ゆ柇锛歝ombinePack 鑷韩鎴栧叾宓屽鍖呴噷鍙鍚湁鍔ㄤ綔 / SkillType==8 / HB422锛�
+                // 灏辫涓�"闇�瑕佺瓑寰�"锛屼笉浣滀负闈欓粯鍓嶇疆瀛愭妧鑳藉鐞嗭紝
+                // 鐣欑粰鍚庣画 ResolvePackList 璧版甯搁槦鍒楁祦绋嬨��
+                // NeedWaiting() 鍐呴儴宸查�掑綊閬嶅巻宓屽鐨� CustomHB426CombinePack銆�
+                if (combinePack.NeedWaiting())
+                {
+                    break;
+                }
+
+                HB427_tagSCUseSkill sp = combinePack.GetMainHB427SkillPack();
+                SkillRecordAction skillRecordAction = combinePack.CreateSkillAction();
+                allSubSkills.Add((sp.packUID, skillRecordAction));
+                removePackList.Add(pack);
+            }
+        }
+
+        for (int i = 0; i < removePackList.Count; i++)
+        {
+            packList.Remove(removePackList[i]);
+        }
+
+        // 鎸塸ackUID鎺掑簭
+        allSubSkills.Sort((a, b) => a.packUID.CompareTo(b.packUID));
+
+        foreach (var (packUID, recordAction) in allSubSkills)
+        {
+            // 缁忚繃 NeedWaiting 杩囨护鍚庯紝姝ゅ recordAction.useParentRecordPlayer 鐞嗚涓婂缁堜负 false锛�
+            // 淇濈暀鍒嗘敮鏄槻寰″紡缂栫爜锛岃涓轰笌鍘熷疄鐜颁竴鑷淬��
+            if (recordAction.useParentRecordPlayer)
+            {
+                ownRecordAction.GetInnerRecordPlayer().PlayRecord(recordAction, ownRecordAction);
+            }
+            else
+            {
+                ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAction);
+            }
+        }
+    }
+}
diff --git a/Main/System/Battle/Skill/SkillBase.SubSkill.cs.meta b/Main/System/Battle/Skill/SkillBase.SubSkill.cs.meta
new file mode 100644
index 0000000..12c2feb
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.SubSkill.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 30efa070918de9a47a0a4937b69340b8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/Skill/SkillBase.cs b/Main/System/Battle/Skill/SkillBase.cs
index 83da046..ac4ac2f 100644
--- a/Main/System/Battle/Skill/SkillBase.cs
+++ b/Main/System/Battle/Skill/SkillBase.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+锘縰sing System.Collections.Generic;
 using UnityEngine;
 using DG.Tweening;
 using Spine;
@@ -6,8 +6,18 @@
 using System;
 using Cysharp.Threading.Tasks;
 
-public class SkillBase
+// SkillBase锛氭妧鑳借繍琛屾椂鍩虹被銆�
+// 鏈被浣跨敤 partial 鎷嗗垎涓哄涓枃浠讹紝鎸夎亴璐e垎缁勶細
+//   SkillBase.cs             瀛楁銆佹瀯閫犮�佸叕鍏卞叆鍙o紙Cast/Run/OnSkillStart/鍚� Frame 鍥炶皟 绛夛級
+//   SkillBase.Cast.cs        鏂芥硶闃舵锛氱Щ鍔ㄣ�佸姩鐢汇�佹畫褰便�侀珮浜�佹敾鍑诲洖鍚堢粨鏉�
+//   SkillBase.Hit.cs         鍛戒腑闃舵锛歄nHit 鍒嗗彂鍒颁富鐩爣 / 婧呭皠鐩爣 / 鍛戒腑鎻愮ず
+//   SkillBase.SubSkill.cs    鍓嶇疆鍐呭祵瀛愭妧鑳界殑鏀堕泦涓庢姇閫�
+//   SkillBase.Death.cs       姝讳骸鍖呬笌鎺夎惤/缁忛獙鍒嗛厤
+//   SkillBase.Buff.cs        Buff 鍖咃紙HB428/HB429锛夌殑鏀堕泦涓庡垎鍙�
+//   SkillBase.Finish.cs      瀹屾垚鍒ゅ畾涓庡己鍒剁粨鏉�
+public partial class SkillBase
 {
+    // ===== 甯搁噺 =====
     const float moveTime = 0.5f;
 
     private static readonly Color colorGreen = new Color(33f / 255f,
@@ -17,40 +27,115 @@
                                                         87f / 255f,
                                                         189f / 255f);
 
-    protected SkillEffect skillEffect;
+    // ===== 鏍稿績寮曠敤 =====
     public HB427_tagSCUseSkill tagUseSkillAttack;
     public SkillConfig skillConfig;
-
     public SkillSkinConfig skillSkinConfig;
-    protected bool isFinished = false;
+    public BattleObject caster = null; // 鏂芥硶鑰�
     protected BattleField battleField = null; // 鎴樺満
     protected RectTransform targetNode = null; // 鐩爣鑺傜偣
-    public BattleObject caster = null; // 鏂芥硶鑰�
     protected List<GameNetPackBasic> packList;
 
+    // ===== 鍛戒腑鏁堟灉 =====
+    protected SkillEffect skillEffect;
+
+    // ===== 瀛愭妧鑳�/瀛愬姩浣滅瓑寰呭垪琛� =====
     protected List<RecordAction> currentWaitingSkill = new List<RecordAction>();
 
+    // ===== 姝讳骸鐩稿叧涓存椂鏁版嵁 =====
     protected List<H0704_tagRolePackRefresh> dropPackList = new List<H0704_tagRolePackRefresh>();
     protected List<HB405_tagMCAddExp> expPackList = new List<HB405_tagMCAddExp>();
-
-    protected bool moveFinished = false;
-    public SkillBase fromSkill;
-    public bool isPlay = false;
-
-    //  鐖禦ecordAction锛圫killRecordAction锛夛紝鐢ㄤ簬瀛愭妧鑳藉缓绔嬬埗瀛愬叧绯�
-    protected SkillRecordAction ownRecordAction;
-    
-    //  鎶�鑳藉姩鐢绘槸鍚︽挱鏀惧畬鎴愶紙閽堝鏈夊姩鐢荤殑鎶�鑳斤級
-    protected bool isMotionCompleted = false;
-
-    private float MoveSpeed = 750f;
-
     private Dictionary<int, BattleDrops> tempDropList = new Dictionary<int, BattleDrops>();
     private Dictionary<int, BattleDeadPack> tempDeadPackList = new Dictionary<int, BattleDeadPack>();
 
-    // Buff鐩稿叧鍖呴泦鍚堬紝鏀寔 HB428(鍒锋柊) 鍜� HB429(鍒犻櫎)
+    // ===== Buff 鐩稿叧鍖呴泦鍚堬紝鏀寔 HB428(鍒锋柊) 鍜� HB429(鍒犻櫎) =====
     protected List<GameNetPackBasic> buffPackCollections = new List<GameNetPackBasic>();
 
+    // ===== 鐢熷懡鍛ㄦ湡鐘舵�侊紙4 涓苟琛岄噷绋嬬浣嶏紝鍚堝苟鍒板悓涓� Flags 瀛楁锛� =====
+    //   Started        : 宸茶繘鍏ユ柦娉曢樁娈碉紙OnSkillStart 璋冪敤鍚庯級
+    //   MoveCompleted  : 浣嶇Щ宸叉敹灏撅紙OnAllAttackMoveFinished锛�
+    //   MotionCompleted: 鎶�鑳藉姩鐢诲凡鎾斁瀹岋紙OnFinalFrameEnd锛�
+    //   Finished       : 鍖呭垪琛ㄥ凡澶勭悊瀹岋紙OnSkillFinished / ForceFinished 缁撳熬锛�
+    //   4 涓噷绋嬬鐩镐簰鐙珛锛岄潪绾挎�ч樁娈碉紝涓嶈兘鐢ㄥ崟涓� state 琛ㄨ揪銆�
+    [System.Flags]
+    protected enum SkillStateFlags
+    {
+        None            = 0,
+        Started         = 1 << 0,
+        MoveCompleted   = 1 << 1,
+        MotionCompleted = 1 << 2,
+        Finished        = 1 << 3,
+    }
+
+    private SkillStateFlags _stateFlags = SkillStateFlags.None;
+
+    /// <summary>褰撳墠鎶�鑳界姸鎬佷綅锛堝彧璇伙紝璋冭瘯鐢級銆�</summary>
+    protected SkillStateFlags StateFlags => _stateFlags;
+
+#if UNITY_EDITOR
+    /// <summary>渚涘閮ㄨ皟璇�/璇婃柇鎵撳嵃鐢紝闈炵紪杈戝櫒涓嬩笉缂栬瘧銆�</summary>
+    public string StateFlagsForDebug => _stateFlags.ToString();
+#endif
+
+    /// <summary>鏄惁宸茶繘鍏ユ柦娉曢樁娈碉紙OnSkillStart 璋冪敤鍚庝负 true锛夈��</summary>
+    public bool isPlay
+    {
+        get => (_stateFlags & SkillStateFlags.Started) != 0;
+        set => SetFlag(SkillStateFlags.Started, value);
+    }
+
+    /// <summary>鍖呭垪琛ㄦ槸鍚﹀凡鍏ㄩ儴澶勭悊瀹屻��</summary>
+    protected bool isFinished
+    {
+        get => (_stateFlags & SkillStateFlags.Finished) != 0;
+        set => SetFlag(SkillStateFlags.Finished, value);
+    }
+
+    /// <summary>浣嶇Щ鏄惁宸叉敹灏俱��</summary>
+    protected bool moveFinished
+    {
+        get => (_stateFlags & SkillStateFlags.MoveCompleted) != 0;
+        set => SetFlag(SkillStateFlags.MoveCompleted, value);
+    }
+
+    /// <summary>鎶�鑳藉姩鐢绘槸鍚﹀凡鎾斁瀹屻��</summary>
+    protected bool isMotionCompleted
+    {
+        get => (_stateFlags & SkillStateFlags.MotionCompleted) != 0;
+        set => SetFlag(SkillStateFlags.MotionCompleted, value);
+    }
+
+    private void SetFlag(SkillStateFlags flag, bool value)
+    {
+#if UNITY_EDITOR
+        //  璁板綍鐘舵�佸彉鏇达細鍗℃/鍗℃椿鐨勬帓鏌ュ埄鍣ㄣ��
+        //  缂栬緫鍣ㄤ笅鍙湪鍊肩湡姝e彂鐢熸敼鍙樻椂鎵撳嵃锛岄伩鍏嶅埛灞忋��
+        bool oldValue = (_stateFlags & flag) != 0;
+        if (oldValue != value)
+        {
+            int skillId = skillConfig != null ? skillConfig.SkillID : 0;
+            ulong casterId = tagUseSkillAttack != null ? tagUseSkillAttack.ObjID : 0UL;
+            BattleDebug.LogError(
+                $"SkillBase.StateFlags 鍙樻洿:skillId={skillId} caster={casterId} " +
+                $"{flag}: {oldValue} -> {value}  (before={_stateFlags})");
+        }
+#endif
+
+        if (value) _stateFlags |= flag;
+        else       _stateFlags &= ~flag;
+    }
+
+    // ===== 鐖跺瓙鍏崇郴 =====
+    public SkillBase fromSkill;
+    //  鐖禦ecordAction锛圫killRecordAction锛夛紝鐢ㄤ簬瀛愭妧鑳藉缓绔嬬埗瀛愬叧绯�
+    protected SkillRecordAction ownRecordAction;
+
+    // ===== 绉诲姩閫熷害锛堟畫褰卞姞閫熸椂浼氭敼鍙橈級 =====
+    private float MoveSpeed = 750f;
+
+#if UNITY_EDITOR
+    public static Dictionary<string, string> changeListDict = new Dictionary<string, string>();
+#endif
 
     // 鏋勯�犲嚱鏁帮細鍒濆鍖栨妧鑳藉熀纭�鏁版嵁
     public SkillBase(BattleObject _caster, SkillConfig _skillCfg, HB427_tagSCUseSkill vNetData, List<GameNetPackBasic> _packList, BattleField _battleField = null)
@@ -74,7 +159,7 @@
         {
             skillSkinConfig = skillConfig.GetOriginSkinConfig();
         }
-        
+
 
         // 娉ㄥ唽姝e湪閲婃斁鐨勬妧鑳�
         if (battleField != null && caster != null)
@@ -87,7 +172,7 @@
 
     public virtual void AfterAddToQueue()
     {
-        
+
     }
 
     //  璁剧疆鐖禦ecordAction
@@ -96,31 +181,28 @@
         ownRecordAction = recordAction;
     }
 
-#if UNITY_EDITOR
-    public static Dictionary<string, string> changeListDict = new Dictionary<string, string>();
-#endif
     private void PinrtHB427Hp()
     {
 #if UNITY_EDITOR
         string skillDetail = "SkillCaster : " + tagUseSkillAttack.ObjID + " -> cast SkillID: " + skillConfig.SkillID + "\n";
-        
+
         skillDetail += "------------------ HurtList ------------------\n";
         for (int i = 0; i < tagUseSkillAttack.HurtCount; i++)
         {
             var Hurt = tagUseSkillAttack.HurtList[i];
             BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)Hurt.ObjID);
-            
+
             string targetName = battleObject != null ? battleObject.GetName() : "Unknown";
             long hurtHp = GeneralDefine.GetFactValue(Hurt.HurtHP, Hurt.HurtHPEx);
             long curHp = GeneralDefine.GetFactValue(Hurt.CurHP, Hurt.CurHPEx);
-            
+
             skillDetail += $"  [{i}] Target: {targetName} (ObjID:{Hurt.ObjID})\n";
             skillDetail += $"      HurtHP: {hurtHp}\n";
             skillDetail += $"      CurHP: {curHp}\n";
             skillDetail += $"      SuckHP: {Hurt.SuckHP}\n";
             skillDetail += $"      BounceHP: {Hurt.BounceHP}\n";
             skillDetail += $"      AttackTypes: {Hurt.AttackTypes}\n";
-            
+
             if (Hurt.HurtListEx != null && Hurt.HurtListEx.Length > 0)
             {
                 skillDetail += $"      HurtListEx ({Hurt.HurtListEx.Length}):\n";
@@ -129,7 +211,7 @@
                     var hurtEx = Hurt.HurtListEx[j];
                     long hurtExHp = GeneralDefine.GetFactValue(hurtEx.HurtHP, hurtEx.HurtHPEx);
                     long curExHp = GeneralDefine.GetFactValue(hurtEx.CurHP, hurtEx.CurHPEx);
-                    
+
                     skillDetail += $"        [{j}] ObjID:{hurtEx.ObjID} HurtHP:{hurtExHp} CurHP:{curExHp} SuckHP:{hurtEx.SuckHP} AttackTypes:{hurtEx.AttackTypes}\n";
                 }
             }
@@ -142,11 +224,11 @@
             {
                 var HurtEx = tagUseSkillAttack.HurtListEx[i];
                 BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)HurtEx.ObjID);
-                
+
                 string targetName = battleObject != null ? battleObject.GetName() : "Unknown";
                 long hurtHp = GeneralDefine.GetFactValue(HurtEx.HurtHP, HurtEx.HurtHPEx);
                 long curHp = GeneralDefine.GetFactValue(HurtEx.CurHP, HurtEx.CurHPEx);
-                
+
                 skillDetail += $"  [{i}] Target: {targetName} (ObjID:{HurtEx.ObjID})\n";
                 skillDetail += $"      HurtHP: {hurtHp}\n";
                 skillDetail += $"      CurHP: {curHp}\n";
@@ -162,7 +244,7 @@
             string origin = changeListDict[caster.battleField.guid];
             origin += skillDetail;
             changeListDict[caster.battleField.guid] = origin;
-            
+
         }
         else
             changeListDict.Add(caster.battleField.guid, skillDetail);
@@ -180,19 +262,17 @@
         }
 #endif
 
-        bool safety = caster != null 
-                        && skillConfig != null 
-                        && tagUseSkillAttack != null 
+        bool safety = caster != null
+                        && skillConfig != null
+                        && tagUseSkillAttack != null
                         && battleField != null;
 
-        
+
         if (!safety)
         {
             Debug.LogError("SkillBase SafetyCheck failed! Caster or SkillConfig or TagUseSkillAttack or BattleField is null, or Caster is dead.");
             ForceFinished();
         }
-
-        
     }
 
     // 鎶�鑳借繍琛屼富閫昏緫锛氫粎椹卞姩鎶�鑳芥晥鏋滐紙skillEffect锛夛紝瀛愭妧鑳藉拰姝讳骸鐢盜sFinished()鎺ㄨ繘
@@ -213,288 +293,6 @@
         }
     }
 
-    protected void ShadowIllutionCreate(bool create)
-    {
-        if (create)
-        {
-            Color color = Color.white;
-            //1-杩炲嚮锛�2-鍙嶅嚮锛�3-杩藉嚮
-            //  鍙嶅嚮钃濊壊
-            //  杩藉嚮杩炲嚮缁胯壊
-            bool change = false;
-            if (tagUseSkillAttack.BattleType == 1)
-            {
-                color = colorGreen;
-                change = true;
-            }
-            else if (tagUseSkillAttack.BattleType == 2)
-            {
-                color = colorBlue;
-                change = true;
-            }
-            else if (tagUseSkillAttack.BattleType == 3)
-            {
-                color = colorGreen;
-                change = true;
-            }
-            
-            if (change)
-            {
-                MoveSpeed = 1125f;
-                caster.ShowIllusionShadow(true, color);
-            }
-        }
-        else
-        {
-            MoveSpeed = 750f;
-            caster.ShowIllusionShadow(false);
-        }
-    }
-
-    // 鎶�鑳介噴鏀句富閫昏緫锛氬箍鎾簨浠躲�侀珮浜洰鏍囥�佹墽琛岄噴鏀�
-    public virtual void Cast()
-    {
-        // 骞挎挱鎶�鑳介噴鏀句簨浠�
-        string guid = battleField.guid;
-        // 鑾峰彇閲婃斁鑰呮暟鎹細Hero 浼犻�� teamHero锛孧ingge 浼犻�� null锛堝洜涓轰簨浠剁洃鍚櫒鍙鐞� Hero 鏁版嵁锛�
-        TeamHero teamHero = null;
-        if (caster is HeroBattleObject heroBattleObject)
-        {
-            teamHero = heroBattleObject.teamHero;
-        }
-        // 鍛芥牸閲婃斁鎶�鑳芥椂 teamHero 涓� null锛岀洃鍚櫒浼氭纭鐞嗭紙宸叉湁 null 妫�鏌ワ級
-        EventBroadcast.Instance.Broadcast<string, SkillConfig, TeamHero>(EventName.BATTLE_CAST_SKILL, guid, skillConfig, teamHero);
-
-        if (skillSkinConfig.SkinllSFX1 != 0)
-        {
-            battleField.soundManager.PlayEffectSound(skillSkinConfig.SkinllSFX1, false).Forget();
-        }
-
-        if (caster != null)
-        {
-            // 鎴樻枟绫诲瀷 0-甯歌锛�1-杩炲嚮锛�2-鍙嶅嚮锛�3-杩藉嚮锛�4-瀛愭妧鑳斤紱5-琚姩瑙﹀彂鐨�
-            DamageNumConfig hintConfig = null;
-            if (tagUseSkillAttack.BattleType == 1)
-            {
-                hintConfig = DamageNumConfig.Get(BattleConst.BattleComboAttack);
-            }
-            else if (tagUseSkillAttack.BattleType == 2)
-            {
-                hintConfig = DamageNumConfig.Get(BattleConst.BattleCounterAttack);
-            }
-            else if (tagUseSkillAttack.BattleType == 3)
-            {
-                hintConfig = DamageNumConfig.Get(BattleConst.BattleChaseAttack);
-            }
-            
-            Hint(caster, hintConfig);
-
-
-        }
-
-        // 楂樹寒鎵�鏈夋湰娆℃妧鑳界浉鍏崇殑鐩爣
-        HighLightAllTargets();
-
-        // 鏍规嵁閲婃斁妯″紡鎵ц鐩稿簲閫昏緫
-        switch (skillSkinConfig.castMode)
-        {
-            case SkillCastMode.None:
-            case SkillCastMode.Self:
-                CastImpl(OnAttackFinish);
-                break;
-            case SkillCastMode.Enemy:
-                CastToEnemy();
-                break;
-            case SkillCastMode.Target:
-                CastToTarget();
-                break;
-            case SkillCastMode.Allies:
-                CastToAllies();
-                break;
-            case SkillCastMode.DashCast:
-                DashCast(OnAttackFinish);
-                break;
-            default:
-                Debug.LogError("寮哄埗缁撴潫鎶�鑳� 鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹俻lease鑱旂郴绛栧垝 鎶�鑳絠d:" + skillConfig.SkillID + " cast position " + skillSkinConfig.CastPosition);
-                ForceFinished();
-                break;
-        }
-    }
-
-    protected void Hint(BattleObject battleObject, DamageNumConfig hintConfig)
-    {
-        if (hintConfig != null)
-        {
-            battleObject.ShowTips(((char)hintConfig.prefix).ToString(), true, false, 1.25f);
-        }
-    }
-
-    // 鍐叉挒鏀诲嚮妯″紡锛堝緟瀹炵幇锛�
-    protected void DashCast(Action _onComplete)
-    {
-        Debug.LogError("DashCast 杩樻病瀹炵幇");
-        ForceFinished();
-    }
-
-    // 瀵规晫鏂归噴鏀炬妧鑳斤細绉诲姩鍒版晫鏂瑰尯鍩熻繘琛屾敾鍑�
-    protected void CastToEnemy()
-    {
-        RectTransform target = battleField.GetTeamNode(caster.GetEnemyCamp(), skillSkinConfig);
-        ExecuteMoveAndCastSequence(target, () =>
-        {
-            if (skillConfig.ClientTriggerTiming == 1)
-            {
-                OnAttackFinish();
-            }
-            else
-            {
-                // ShadowIllutionCreate(true);
-                MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.GetPositionNum()), Vector2.zero, () =>
-                {
-                    // ShadowIllutionCreate(false);
-                    OnAttackFinish();
-                }, MoveSpeed);   
-            }
-        });
-    }
-
-    // 瀵规寚瀹氱洰鏍囬噴鏀炬妧鑳斤細绉诲姩鍒颁富瑕佺洰鏍囦綅缃繘琛屾敾鍑�
-    protected void CastToTarget()
-    {
-        if (tagUseSkillAttack.HurtCount <= 0)
-        {
-            Debug.LogError("鎶�鑳芥敾鍑诲寘娌℃湁鐩爣 HurtCount <= 0");
-            OnSkillFinished();
-            return;
-        }
-
-        int mainTargetPosNum = BattleUtility.GetMainTargetPositionNum(this, caster, tagUseSkillAttack.HurtList, skillConfig);
-        BattleCamp battleCamp = skillConfig.TagFriendly != 0 ? caster.Camp : caster.GetEnemyCamp();
-        RectTransform targetTrans = battleField.GetTeamNode(battleCamp, mainTargetPosNum);
-
-        ExecuteMoveAndCastSequence(targetTrans, () =>
-        {
-            RectTransform rectTransform = battleField.GetTeamNode(caster.Camp, caster.GetPositionNum());
-            // ShadowIllutionCreate(true);
-            MoveToTarget(rectTransform, Vector2.zero, () =>
-            {
-                // ShadowIllutionCreate(false);
-                OnAttackFinish();
-            }, MoveSpeed);
-        });
-    }
-
-    // 瀵瑰弸鏂归噴鏀炬妧鑳斤細绉诲姩鍒板弸鏂瑰尯鍩熻繘琛屾不鐤楁垨澧炵泭
-    protected void CastToAllies()
-    {
-        RectTransform target = battleField.GetTeamNode(caster.Camp, skillSkinConfig);
-        ExecuteMoveAndCastSequence(target, () =>
-        {
-            if (skillConfig.ClientTriggerTiming == 1)
-            {
-                OnAttackFinish();
-            }
-            else
-            {
-                // ShadowIllutionCreate(true);
-                MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.GetPositionNum()), Vector2.zero, () =>
-                {
-                    // ShadowIllutionCreate(false);
-                    OnAttackFinish();
-                }, MoveSpeed);   
-            }
-        });
-    }
-
-    // 鎵ц绉诲姩-鏂芥硶-杩斿洖搴忓垪锛氶�氱敤鐨勭Щ鍔ㄦ敾鍑绘祦绋�
-    private void ExecuteMoveAndCastSequence(RectTransform target, Action onReturnComplete)
-    {
-        ShadowIllutionCreate(true);
-        MoveToTarget(target, new Vector2(skillSkinConfig.CastDistance, 0), () =>
-        {
-            if (skillSkinConfig.CastDistance < 9999 && skillSkinConfig.SkinllSFX2 != 0)
-            {
-                battleField.soundManager.PlayEffectSound(skillSkinConfig.SkinllSFX2, false).Forget();
-            }
-
-            TurnBack(() =>
-            {
-                ShadowIllutionCreate(false);
-                
-                CastImpl(() =>
-                {
-                    TurnBack(() => 
-                    {
-                        try
-                        {
-                            onReturnComplete?.Invoke(); // 娣诲姞寮傚父澶勭悊闃叉鍥炶皟寮傚父瀵艰嚧鐘舵�佷笉瀹屾暣
-                        }
-                        catch (Exception ex)
-                        {
-                            Debug.LogError($"ExecuteMoveAndCastSequence鍥炶皟寮傚父: {ex.Message}");
-                            throw;
-                        }
-                    }, -1f);
-                });
-            }, -1f);
-        });
-    }
-
-    // 绉诲姩鍒扮洰鏍囦綅缃細澶勭悊瑙掕壊鐨勭Щ鍔ㄥ姩鐢诲拰閫昏緫
-    protected void MoveToTarget(RectTransform target, Vector2 offset, Action _onComplete = null, float speed = 750f)
-    {
-        if (skillSkinConfig.CastDistance >= 9999)
-        {
-            _onComplete?.Invoke();
-            return;
-        }
-
-        caster.PlayAnimation(MotionName.run, true);
-        var tweener = BattleUtility.MoveToTarget(caster.GetRectTransform(), target, offset, () =>
-        {
-            caster.PlayAnimation(MotionName.idle, true);
-            _onComplete?.Invoke();
-        }, speed);
-        battleField.battleTweenMgr.OnPlayTween(tweener);
-    }
-
-    // 杞韩閫昏緫锛氭牴鎹妧鑳介厤缃鐞嗚鑹茶浆鍚�
-    protected void TurnBack(Action _onComplete, float forward)
-    {
-        if (skillSkinConfig.CastDistance < 0)
-        {
-            caster.SetFacing(forward);
-        }
-        _onComplete?.Invoke();
-    }
-
-    // 鏀诲嚮瀹屾垚鍚庣殑澶勭悊锛氳浆韬�佹仮澶嶇姸鎬併�佹挱鏀惧緟鏈哄姩鐢�
-    protected void OnAttackFinish()
-    {
-        TurnBack(null, 1f);
-        OnAllAttackMoveFinished();
-        caster.PlayAnimation(MotionName.idle, true);
-    }
-
-    // 鎵�鏈夋敾鍑荤Щ鍔ㄥ畬鎴愬悗鐨勫鐞嗭細鎭㈠UI鏄剧ず鐘舵��
-    protected virtual void OnAllAttackMoveFinished()
-    {
-        moveFinished = true;
-        foreach (var kv in battleField.battleObjMgr.allBattleObjDict)
-        {
-            BattleObject bo = kv.Value;
-            bo.layerMgr.SetFront();
-            bo.GetHeroInfoBar()?.SetActive(true);
-        }
-        battleField.battleRootNode.skillMaskNode.SetActive(false);
-    }
-
-    // 鎵ц鎶�鑳介噴鏀惧姩鐢诲拰閫昏緫锛氭挱鏀炬柦娉曞姩浣滃苟鎻愪緵鍥炶皟
-    protected TrackEntry CastImpl(Action onComplete = null)
-    {
-        return caster.PlaySkillAnimation(skillConfig, skillSkinConfig, this, tagUseSkillAttack.BattleType == 4, onComplete);
-    }
-
     // 鎶�鑳藉紑濮嬪洖璋冿細澶勭悊姝讳骸銆佸瓙鎶�鑳姐�佹妧鑳芥晥鏋滃垵濮嬪寲
     public void OnSkillStart()
     {
@@ -512,86 +310,12 @@
 
         skillEffect = SkillEffectFactory.CreateSkillEffect(this, caster, skillConfig, skillSkinConfig, tagUseSkillAttack);
         skillEffect.Play(OnHitTargets);
-        
+
 
         isPlay = true;
     }
 
-    protected void ProcessSubSkill()
-    {
-        // 鎸塸ackUID鎺掑簭鎵�鏈夊瓙鎶�鑳�
-        var allSubSkills = new List<(ulong packUID, SkillRecordAction action)>();
-        
-        List<GameNetPackBasic> removePackList = new List<GameNetPackBasic>();
-
-        foreach (var pack in packList)
-        {
-            if (pack is HB427_tagSCUseSkill skillPack)
-            {
-                SkillConfig ssc = SkillConfig.Get((int)skillPack.SkillID);
-                SkillSkinConfig sscSkin = ssc.GetOriginSkinConfig();
-                if (!string.IsNullOrEmpty(sscSkin.SkillMotionName))
-                {
-                    break;
-                }
-                if (ssc.SkillType == 8)
-                {
-                    break;
-                }
-                SkillRecordAction skillRecordAction = CustomHB426CombinePack.CreateSkillAction(battleField.guid, new List<GameNetPackBasic> { skillPack });
-                allSubSkills.Add((skillPack.packUID, skillRecordAction));
-                removePackList.Add(pack);
-            }
-            else if (pack is HB422_tagMCTurnFightObjDead dead)
-            {
-                break;
-            }
-            else if (pack is CustomHB426CombinePack combinePack)
-            {
-                HB427_tagSCUseSkill sp = combinePack.GetMainHB427SkillPack();
-                SkillConfig ssc = SkillConfig.Get((int)sp.SkillID);
-                SkillSkinConfig sscSkin = ssc.GetOriginSkinConfig();
-                if (!string.IsNullOrEmpty(sscSkin.SkillMotionName))
-                {
-                    break;
-                }
-
-                if (ssc.SkillType == 8)
-                {
-                    break;
-                }
-                
-                SkillRecordAction skillRecordAction = combinePack.CreateSkillAction();
-                allSubSkills.Add((sp.packUID, skillRecordAction));
-                removePackList.Add(pack);
-
-                if (skillRecordAction.useParentRecordPlayer)
-                {
-                    break;
-                }
-            }
-        }
-
-        for (int i = 0; i < removePackList.Count; i++)
-        {
-            packList.Remove(removePackList[i]);
-        }
-
-        // 鎸塸ackUID鎺掑簭
-        allSubSkills.Sort((a, b) => a.packUID.CompareTo(b.packUID));
-
-        foreach (var (packUID, recordAction) in allSubSkills)
-        {
-            if (recordAction.useParentRecordPlayer)
-            {
-                ownRecordAction.GetInnerRecordPlayer().PlayRecord(recordAction, ownRecordAction);
-            }
-            else
-            {
-                ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAction);
-            }
-        }
-    }
+    // ===== 鎶�鑳借妭鎷嶅洖璋� =====
 
     // 鎶�鑳藉墠鎽囩粨鏉熷洖璋�
     public virtual void OnStartSkillFrameEnd() { }
@@ -620,1073 +344,7 @@
         //  鏍囪鍔ㄧ敾鎾斁瀹屾垚
         isMotionCompleted = true;
         BattleDebug.LogError($"SkillBase.OnFinalFrameEnd: 鎶�鑳� {skillConfig?.SkillID} 鍔ㄧ敾鎾斁瀹屾垚");
-        
+
         skillEffect?.OnFinalFrameEnd(); // 淇锛氭坊鍔犵┖鍊兼鏌�
     }
-
-    // 楂樹寒鎵�鏈夌浉鍏崇洰鏍囷細璁剧疆鏂芥硶鑰呭拰鐩爣鐨勬樉绀哄眰绾�
-    protected void HighLightAllTargets()
-    {
-        caster.layerMgr.SetSortingOrder(BattleConst.SkillMaskOrder + BattleConst.BattleActiveHeroOffset);
-
-        if (skillConfig.FuncType != 2)
-            return;
-
-        // 鏀堕泦鎵�鏈夌洰鏍囷紙鍖呭惈 HurtList銆佹瘡涓� Hurt 鐨� HurtListEx銆佷互鍙婇《灞� HurtListEx锛�
-        var targetSet = new HashSet<BattleObject>();
-        if (tagUseSkillAttack != null)
-        {
-            // 涓荤洰鏍囧垪琛�
-            if (tagUseSkillAttack.HurtList != null)
-            {
-                foreach (var hurt in tagUseSkillAttack.HurtList)
-                {
-                    var bo = battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
-                    if (bo != null) targetSet.Add(bo);
-
-                    // 涓荤洰鏍囩殑棰濆鐩爣锛堝脊灏�/骞虫憡锛�
-                    if (hurt.HurtListEx != null)
-                    {
-                        foreach (var hurtEx in hurt.HurtListEx)
-                        {
-                            var exBo = battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
-                            if (exBo != null) targetSet.Add(exBo);
-                        }
-                    }
-                }
-            }
-
-            // 鎶�鑳藉寘椤跺眰鐨� HurtListEx锛堝婧呭皠銆侀《灞傚钩鎽婏級
-            if (tagUseSkillAttack.HurtListEx != null)
-            {
-                foreach (var hurtEx in tagUseSkillAttack.HurtListEx)
-                {
-                    var exBo = battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
-                    if (exBo != null) targetSet.Add(exBo);
-                }
-            }
-        }
-
-        // 纭繚鏂芥硶鑰呬篃琚珮浜紙鍘熼�昏緫锛�
-        var highlightList = new List<BattleObject>(targetSet) { caster };
-
-        var allList = battleField.battleObjMgr.allBattleObjDict.Values;
-
-        // 鏋勯�犻泦鍚堜究浜庡垽鏂�
-        var targetSetLookup = new HashSet<BattleObject>(targetSet);
-        var highlightSet = new HashSet<BattleObject>(highlightList);
-
-        // 鍏堟妸鏂芥硶鑰呯殑 InfoBar 闅愯棌锛堝師閫昏緫淇濈暀锛�
-        caster.GetHeroInfoBar()?.SetActive(false);
-
-        foreach (BattleObject bo in allList)
-        {
-            bool isHighlight = highlightSet.Contains(bo);
-            bool isTarget = targetSetLookup.Contains(bo);
-
-            if (isHighlight)
-            {
-                bo.layerMgr.SetFront();
-            }
-            else
-            {
-                bo.layerMgr.SetBack();
-            }
-
-            // 鐩爣锛堝惈 HurtListEx锛夐兘搴旀樉绀� InfoBar
-            bo.GetHeroInfoBar()?.SetActive(isTarget);
-        }
-
-        battleField.battleRootNode.skillMaskNode.SetActive(true);
-    }
-
-
-    // 鍛戒腑鐩爣鍥炶皟锛氬鐞嗘墍鏈夎鍛戒腑鐨勭洰鏍囷紙鍖呮嫭涓荤洰鏍囥�佸脊灏勭洰鏍囥�佹簠灏勭洰鏍囷級
-    protected virtual void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
-    {
-        // Debug.LogError($"Skill {skillConfig.SkillID} hit targets _hitIndex: {_hitIndex} hit {string.Join(", ", hitList.Select(h => h.ObjID + ":" + battleField.battleObjMgr.GetBattleObject((int)h.ObjID)?.GetName()))}");
-
-        //  閫犳垚浼ゅ鍓嶅厛澶勭悊琛�閲忓埛鏂板寘
-        HandleRefreshHP();
-
-        bool suckHp = true;
-
-        // 澶勭悊涓荤洰鏍囧垪琛�
-        foreach (var hurt in hitList)
-        { 
-            BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
-            if (target == null)
-            {
-                Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
-                continue;
-            }
-
-            OnHitEachTarget(_hitIndex, target, hurt, suckHp);
-
-            suckHp = false;
-
-            // 澶勭悊璇ョ洰鏍囩殑棰濆鐩爣鍒楄〃锛堝寮瑰皠浼ゅ鐨勫钩鎽婄洰鏍囷級
-            if (hurt.HurtListEx != null && hurt.HurtListEx.Length > 0)
-            {
-                foreach (var hurtEx in hurt.HurtListEx)
-                {
-                    BattleObject exTarget = caster.battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
-                    if (exTarget == null)
-                    {
-                        Debug.LogError($"棰濆鐩爣涓虹┖ HurtListEx target == null ObjId : {hurtEx.ObjID}");
-                        continue;
-                    }
-
-                    OnHitEachTargetEx(_hitIndex, exTarget, hurtEx);
-                }
-            }
-        }
-
-        // 澶勭悊鎶�鑳藉寘椤跺眰鐨勯澶栫洰鏍囧垪琛紙濡傛簠灏勪激瀹炽�佸钩鎽婁激瀹筹級
-        if (tagUseSkillAttack.HurtListEx != null && tagUseSkillAttack.HurtListEx.Length > 0)
-        {
-            foreach (var hurtEx in tagUseSkillAttack.HurtListEx)
-            {
-                BattleObject exTarget = caster.battleField.battleObjMgr.GetBattleObject((int)hurtEx.ObjID);
-                if (exTarget == null)
-                {
-                    Debug.LogError($"椤跺眰棰濆鐩爣涓虹┖ tagUseSkillAttack.HurtListEx target == null ObjId : {hurtEx.ObjID}");
-                    continue;
-                }
-
-                OnHitEachTargetEx(_hitIndex, exTarget, hurtEx);
-            }
-        }
-
-        HandleHint(_hitIndex, hitList);
-    }
-
-    protected void HandleHint(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
-    {
-        if (0 == _hitIndex)
-        {
-            bool needhint = false;
-
-            for (int i = 0; i < hitList.Count; i++)
-            {
-                var hurt = hitList[i];
-
-                //8-鍑绘檿
-                if ((hurt.AttackTypes & (int)DamageType.Stunned) == (int)DamageType.Stunned)
-                {
-                    needhint = true;
-                    break;
-                }
-
-                for (int j = 0; j < hurt.HurtListEx?.Length; j++)
-                {
-                    var hurtex = hurt.HurtListEx[j];
-                    //8-鍑绘檿
-                    if ((hurtex.AttackTypes & (int)ServerDamageType.Stunned) == (int)ServerDamageType.Stunned)
-                    {
-                        needhint = true;
-                        break;
-                    }
-                }
-
-                if (needhint)
-                    break;
-            }
-
-            if (needhint)
-            {
-                DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.BattleStun);
-                Hint(caster, hintConfig);
-            }
-
-            for (int i = 0; i < hitList.Count; i++)
-            {
-                var hurt = hitList[i];
-
-                if ((hurt.AttackTypes & (int)DamageType.BreakArmor) == (int)DamageType.BreakArmor)
-                {
-                    BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
-                    if (battleObject != null)
-                    {
-                        DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.BreakArmor);
-                        Hint(battleObject, hintConfig);
-                        battleField.battleEffectMgr.PlayEffect(battleObject, 
-                            BattleConst.BreakArmorEffectID, battleObject.GetRectTransform(), battleObject.Camp, 
-                            battleObject.GetModelScale());
-                    }
-                }
-                else if ((hurt.AttackTypes & (int)DamageType.Parry) == (int)DamageType.Parry)
-                {
-                    BattleObject battleObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
-                    if (battleObject != null)
-                    {
-                        DamageNumConfig hintConfig = DamageNumConfig.Get(BattleConst.Parry);
-                        Hint(battleObject, hintConfig);
-                        battleField.battleEffectMgr.PlayEffect(battleObject, 
-                            BattleConst.ParryEffectID, battleObject.GetRectTransform(), battleObject.Camp, 
-                            battleObject.GetModelScale());
-                    }
-                }
-            }
-        }
-    }
-
-    // 澶勭悊鍗曚釜鐩爣琚懡涓�:搴旂敤浼ゅ鍜屾柦娉曡�呮晥鏋�
-    protected virtual void OnHitEachTarget(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurt hurt, bool suckHp)
-    {
-        // ============ 鑾峰彇涓存椂鏁版嵁(鎺夎惤銆佹浜$瓑) ============
-        int objID = (int)target.ObjID;
-        tempDropList.TryGetValue(objID, out BattleDrops battleDrops);
-        tempDeadPackList.TryGetValue(objID, out BattleDeadPack deadPack);
-
-        // 濡傛灉鐩爣姝e湪閲婃斁鎶�鑳斤紝璺宠繃姝讳骸澶勭悊锛堝欢杩熷埌鎶�鑳界粨鏉燂級
-        if (battleField != null && battleField.IsCastingSkill(target.ObjID))
-        {
-            deadPack = null;
-        }
-
-        // ============ 鍙傛暟鎵撳寘 ============
-        BattleHurtParam hurtParam = BattleUtility.CalcBattleHurtParam(this, _hitIndex, target, hurt, battleDrops, deadPack, suckHp);
-#if UNITY_EDITOR
-        PrintHurtParamDebugInfo(hurtParam);
-#endif
-
-        // 鍏堣皟鐢ㄧ洰鏍囧彈浼�
-        DeathRecordAction recordAc = target.Hurt(hurtParam, ownRecordAction);
-
-        if (null != recordAc)
-        {
-            tempDeadPackList.Remove(hurtParam.hurter.hurtObj.ObjID);
-            ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAc, ownRecordAction, true);
-            currentWaitingSkill.Add(recordAc);
-        }
-        
-        // 鍐嶈皟鐢ㄦ柦娉曡�呭惛琛�/鍙嶄激
-        caster.OnHurtTarget(hurtParam);
-    }
-
-    // 澶勭悊棰濆鐩爣琚懡涓紙HurtListEx锛夛細婧呭皠銆佸脊灏勩�佸钩鎽婁激瀹崇瓑
-    protected virtual void OnHitEachTargetEx(int _hitIndex, BattleObject target, HB427_tagSCUseSkill.tagSCUseSkillHurtEx hurtEx)
-    {
-        // ============ 鑾峰彇涓存椂鏁版嵁(鎺夎惤銆佹浜$瓑) ============
-        int objID = (int)target.ObjID;
-        tempDropList.TryGetValue(objID, out BattleDrops battleDrops);
-
-        tempDeadPackList.TryGetValue(objID, out BattleDeadPack deadPack);
-
-        // 濡傛灉鐩爣姝e湪閲婃斁鎶�鑳斤紝璺宠繃姝讳骸澶勭悊锛堝欢杩熷埌鎶�鑳界粨鏉燂級
-        if (battleField != null && battleField.IsCastingSkill(target.ObjID))
-        {
-            deadPack = null;
-        }
-        // ============ 鍙傛暟鎵撳寘锛堝皢 tagSCUseSkillHurtEx 杞崲涓� tagSCUseSkillHurt锛�============
-        HB427_tagSCUseSkill.tagSCUseSkillHurt hurt = new HB427_tagSCUseSkill.tagSCUseSkillHurt
-        {
-            ObjID = hurtEx.ObjID,
-            AttackTypes = hurtEx.AttackTypes,
-            HurtHP = hurtEx.HurtHP,
-            HurtHPEx = hurtEx.HurtHPEx,
-            CurHP = hurtEx.CurHP,
-            CurHPEx = hurtEx.CurHPEx,
-            SuckHP = 0,//hurtEx.SuckHP, 鑾峰彇鍏ㄩ儴鍚歌鏃跺凡缁忚绠楄繃 杩欓噷灏变笉鍐嶈绠�
-            BounceHP = 0, // HurtEx 娌℃湁鍙嶄激瀛楁
-            HurtCountEx = 0,
-            HurtListEx = null
-        };
-
-        OnHitEachTarget(_hitIndex, target, hurt, false);//鑾峰彇鍏ㄩ儴鍚歌鏃跺凡缁忚绠楄繃 杩欓噷灏变笉鍐嶈绠�
-    }
-
-#if UNITY_EDITOR
-    private void PrintHurtParamDebugInfo(BattleHurtParam hurtParam)
-    {
-        bool isLastHit = hurtParam.hitIndex >= hurtParam.skillSkinConfig.DamageDivide.Length - 1;
-        
-        long currentHitDamage = hurtParam.hurter.damageList != null ? hurtParam.hurter.damageList.Sum() : 0;
-        long currentHitSuckHp = hurtParam.caster.suckHpList != null ? hurtParam.caster.suckHpList.Sum() : 0;
-        long currentHitReflectHp = hurtParam.caster.reflectHpList != null ? hurtParam.caster.reflectHpList.Sum() : 0;
-        
-        long totalDamage = GeneralDefine.GetFactValue(hurtParam.hurt.HurtHP, hurtParam.hurt.HurtHPEx);
-        long totalSuckHp = BattleUtility.GetSuckHp(tagUseSkillAttack);
-        long totalReflectHp = hurtParam.hurt.BounceHP;
-        
-        BattleDebug.LogError(
-            (hurtParam.caster.casterObj.Camp == BattleCamp.Red ? "銆愮孩鏂硅鍔ㄣ��" : "銆愯摑鏂硅鍔ㄣ�� ") +
-            $"鏀诲嚮鑰�: {hurtParam.caster.casterObj.GetName()} (ObjID:{hurtParam.caster.casterObj.ObjID})\n" +
-            $"鐩爣: {hurtParam.hurter.hurtObj.GetName()} (ObjID:{hurtParam.hurter.hurtObj.ObjID})\n" +
-            $"鎶�鑳�: {hurtParam.skillConfig.SkillName} (ID:{hurtParam.skillConfig.SkillID})\n" +
-            $"鍑绘暟: 绗瑊hurtParam.hitIndex + 1}鍑� / 鍏眥hurtParam.skillSkinConfig.DamageDivide.Length}鍑�" + (isLastHit ? " [鏈�鍚庝竴鍑籡" : " [涓棿鍑籡") + "\n" +
-            $"\n" +
-            $"========== 鐩爣鍙椾激鏁版嵁 ==========\n" +
-            $"浼ゅ: {currentHitDamage} / 鎬讳激瀹�: {totalDamage}\n" +
-            $"浼ゅ鍒嗘: [{string.Join(", ", hurtParam.hurter.damageList ?? new List<long>())}]\n" +
-            $"鐩爣琛�閲�: {hurtParam.hurter.fromHp} -> {hurtParam.hurter.toHp} (鏈�澶�:{hurtParam.hurter.maxHp})\n" +
-            $"鐩爣鎶ょ浘: {hurtParam.hurter.fromShieldValue} -> {hurtParam.hurter.toShieldValue}\n" +
-            $"鏀诲嚮绫诲瀷: {hurtParam.hurt.AttackTypes}\n" +
-            $"\n" +
-            $"========== 鏂芥硶鑰呮暟鎹� ==========\n" +
-            $"鍚歌: {currentHitSuckHp} / 鎬诲惛琛�: {totalSuckHp}\n" +
-            $"鍚歌鍒嗘: [{string.Join(", ", hurtParam.caster.suckHpList ?? new List<long>())}]\n" +
-            $"鍙嶄激: {currentHitReflectHp} / 鎬诲弽浼�: {totalReflectHp}\n" +
-            $"鍙嶄激鍒嗘: [{string.Join(", ", hurtParam.caster.reflectHpList ?? new List<long>())}]\n" +
-            $"鏂芥硶鑰呰閲�: {hurtParam.caster.fromHp} -> {hurtParam.caster.toHp} (鏈�澶�:{hurtParam.caster.maxHp})\n" +
-            $"鏂芥硶鑰呮姢鐩�: {hurtParam.caster.fromShieldValue} -> {hurtParam.caster.toShieldValue}\n"
-        );
-    }
-#endif
-
-    // 澶勭悊HP鍒锋柊鍖咃紙绠�鍖栭�昏緫锛�
-    private void HandleRefreshHP()
-    {
-        // 鏌ユ壘HP鍒锋柊鍖�
-        HB419_tagSCObjHPRefresh refreshPack = BattleUtility.FindObjHPRefreshPack(packList);
-
-        if (refreshPack != null)
-        {
-            // 鍒嗗彂HP鍒锋柊鍖�
-            // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
-            // 鍘熷洜锛欻P鍒锋柊鍖呮槸鎶�鑳藉唴閮ㄤ骇鐢熺殑锛屽簲璇ョ敱褰撳墠SkillRecordAction鐨刬nnerRecordPlayer绠$悊
-            // 杩欐牱鍙互纭繚HP鍒锋柊涓庢妧鑳界殑鐢熷懡鍛ㄦ湡缁戝畾锛孎orceFinish鏃朵竴骞跺鐞�
-            PackageRegeditEx.DistributeToRecordAction(refreshPack, ownRecordAction);
-            packList.Remove(refreshPack);
-        }
-    }
-
-    // 澶勭悊姝讳骸鐩稿叧閫昏緫锛氬垎閰嶆帀钀藉拰缁忛獙
-    protected void HandleDead()
-    {
-        List<BattleDeadPack> deadPackList = BattleUtility.FindDeadPack(packList);
-        if (deadPackList.Count <= 0) return;
-
-        foreach (var deadPack in deadPackList)
-        {
-            packList.Remove(deadPack.deadPack);
-            packList.Remove(deadPack.deadTriggerSkill);
-        }
-
-        // 鎵惧埌鏈�澶х殑姝讳骸鍖� packUID
-        BattleDeadPack lastBattleDeadPack = null;
-        ulong maxDeathPackUID = 0;
-        foreach (var deadPack in deadPackList)
-        {
-            if (deadPack.deadPack != null && deadPack.deadPack.packUID > maxDeathPackUID)
-            {
-                maxDeathPackUID = deadPack.deadPack.packUID;
-                lastBattleDeadPack = deadPack;
-            }
-        }
-        
-        // 濡傛灉鎵惧埌浜嗘浜″寘锛屾敹闆嗘墍鏈� packUID > maxDeathPackUID 鐨勫寘
-        if (maxDeathPackUID > 0 && lastBattleDeadPack != null)
-        {
-            BattleDebug.LogError($"SkillBase.HandleDead: 鎵惧埌姝讳骸鍖咃紝maxDeathPackUID = {maxDeathPackUID}锛屽紑濮嬫敹闆嗘浜″悗鐨勫寘");
-            
-            // 1. 鏀堕泦 packList 涓� packUID 澶т簬姝讳骸鍖呯殑鍖咃紙鎺掗櫎缁忛獙鍖呭拰鎺夎惤鍖咃紝瀹冧滑闇�瑕佸湪褰撳墠鎶�鑳戒腑澶勭悊锛�
-            List<GameNetPackBasic> packsToRemove = new List<GameNetPackBasic>();
-            foreach (var pack in packList)
-            {
-                ulong packUID = GetPackUID(pack);
-                if (packUID > maxDeathPackUID)
-                {
-                    // 鎺掗櫎缁忛獙鍖呭拰鎺夎惤鍖咃紝瀹冧滑灞炰簬褰撳墠姝讳骸浜嬩欢鐨勪竴閮ㄥ垎锛屼笉鏄�"姝讳骸鍚�"鐨勫寘
-                    if (pack is HB405_tagMCAddExp expPack && expPack.Source == 2 || 
-                        (pack is H0704_tagRolePackRefresh h0704 && h0704.PackType == (byte)PackType.DropItem && h0704.IsBind == 1))
-                    {
-                        continue; // 璺宠繃缁忛獙鍖呭拰鎺夎惤鍖咃紝璁� CheckAfterDeadhPack() 澶勭悊瀹冧滑
-                    }
-                    
-                    BattleDebug.LogError($"SkillBase.HandleDead: 浠巔ackList鏀堕泦姝讳骸鍚庣殑鍖� - Type: {pack.GetType().Name}, UID: {packUID}");
-                    lastBattleDeadPack.packListAfterDeath.Add(pack);
-                    packsToRemove.Add(pack);
-                }
-            }
-
-            packList.RemoveAll(p => packsToRemove.Contains(p));
-        }
-
-        CheckAfterDeadhPack();
-
-        // 淇锛氬厛鏀堕泦瑕佸垹闄ょ殑鍖咃紝閬垮厤鍦╢oreach涓慨鏀归泦鍚�
-        var dropPacksToRemove = new List<H0704_tagRolePackRefresh>(dropPackList);
-        foreach (var _dropPack in dropPacksToRemove)
-        {
-            // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
-            // 鍘熷洜锛氭帀钀藉寘鏄妧鑳芥晥鏋滅殑涓�閮ㄥ垎锛屽簲璇ョ敱褰撳墠SkillRecordAction绠$悊
-            // 鎺夎惤鍖呯殑鍒嗗彂涓庢妧鑳藉畬鎴愮粦瀹氾紝纭繚鍦ㄦ妧鑳紽orceFinish鏃舵纭鐞�
-            PackageRegeditEx.DistributeToRecordAction(_dropPack, ownRecordAction);
-            packList.Remove(_dropPack);
-        }
-
-        // 鑾峰彇骞跺垎閰嶆帀钀界墿鍝佸拰缁忛獙
-        var dropPack = PackManager.Instance.GetSinglePack(PackType.DropItem);
-        var itemDict = dropPack.GetAllItems();
-        List<ItemModel> itemList = new List<ItemModel>();
-        foreach (var item in itemDict.Values)
-        {
-            if (item != null && item.isAuction)
-                itemList.Add(item);
-        }
-
-        var dropAssign = AssignDrops(itemList, deadPackList.Count);
-        var expAssign = AssignExp(expPackList, deadPackList.Count);
-
-        // 鏋勯�燘attleDrops骞剁紦瀛�
-        for (int i = 0; i < deadPackList.Count; i++)
-        {
-            BattleDeadPack bdp = deadPackList[i];
-            int objID = (int)bdp.deadPack.ObjID;
-            BattleObject deadTarget = battleField.battleObjMgr.GetBattleObject(objID);
-            
-            // 淇锛氭坊鍔犵┖鍊兼鏌�
-            if (deadTarget == null)
-            {
-                Debug.LogError($"鎵句笉鍒版浜$洰鏍囷紝ObjID: {objID}");
-                continue;
-            }
-            
-            List<int> itemIndexList = new List<int>(dropAssign[i].Count);
-            for (int j = 0; j < dropAssign[i].Count; j++)
-                itemIndexList.Add(dropAssign[i][j].gridIndex);
-            
-            BattleDrops battleDrops = new BattleDrops()
-            {
-                rectTransform = deadTarget.GetRectTransform(),
-                dropItemPackIndex = itemIndexList,
-                expDrops = expAssign[i]
-            };
-
-            // 淇锛氶伩鍏嶅瓧鍏搁敭鍐茬獊锛屼娇鐢ㄥ畨鍏ㄧ殑娣诲姞鏂瑰紡
-            if (!tempDropList.ContainsKey(objID))
-            {
-                tempDropList.Add(objID, battleDrops);
-            }
-            else
-            {
-                Debug.LogWarning($"tempDropList涓凡瀛樺湪ObjID={objID}鐨勮褰曪紝灏嗚鐩栧師鍊�");
-                tempDropList[objID] = battleDrops; // 瑕嗙洊鐜版湁鍊�
-            }
-
-            if (!tempDeadPackList.ContainsKey(objID))
-            {
-                tempDeadPackList.Add(objID, deadPackList[i]);
-            }
-            else
-            {
-                Debug.LogWarning($"tempDeadPackList涓凡瀛樺湪ObjID={objID}鐨勮褰曪紝灏嗚鐩栧師鍊�");
-                tempDeadPackList[objID] = deadPackList[i]; // 瑕嗙洊鐜版湁鍊�
-            }
-        }
-
-        // 淇锛氶伩鍏嶅湪閬嶅巻鏃朵慨鏀归泦鍚堬紝鍏堟敹闆嗗悗鍒犻櫎
-        var deadPacksToRemove = new List<GameNetPackBasic>(deadPackList.Select(d => d.deadPack));
-        deadPacksToRemove.AddRange(deadPackList.Where(d => d.deadTriggerSkill != null).Select(d => d.deadTriggerSkill));
-        foreach (var deadPack in deadPacksToRemove)
-        {
-            packList.Remove(deadPack);
-        }
-    }
-
-    // 鍒嗛厤鎺夎惤鐗╁搧锛氬皢鎺夎惤鐗╁搧骞冲潎鍒嗛厤缁欐浜″璞�
-    protected List<List<ItemModel>> AssignDrops(List<ItemModel> itemList, int deadCount)
-    {
-        var dropAssign = new List<List<ItemModel>>();
-        for (int i = 0; i < deadCount; i++)
-            dropAssign.Add(new List<ItemModel>());
-        for (int i = 0; i < itemList.Count; i++)
-            dropAssign[i % deadCount].Add(itemList[i]);
-        return dropAssign;
-    }
-
-    // 鑾峰彇鍖呯殑 packUID
-    protected ulong GetPackUID(GameNetPackBasic pack)
-    {
-        if (pack == null) return 0;
-        
-        if (pack is HB422_tagMCTurnFightObjDead deadPack)
-            return deadPack.packUID;
-        
-        if (pack is CustomHB426CombinePack combinePack)
-        {
-            var mainSkillPack = combinePack.GetMainHB427SkillPack();
-            return mainSkillPack?.packUID ?? 0;
-        }
-        
-        if (pack is HB427_tagSCUseSkill skillPack)
-            return skillPack.packUID;
-        
-        if (pack is HB428_tagSCBuffRefresh buffRefresh)
-            return buffRefresh.packUID;
-        
-        if (pack is HB429_tagSCBuffDel buffDel)
-            return buffDel.packUID;
-        
-        if (pack is HB419_tagSCObjHPRefresh hpRefresh)
-            return hpRefresh.packUID;
-        
-        if (pack is HB405_tagMCAddExp expPack)
-            return expPack.packUID;
-        
-        if (pack is H0704_tagRolePackRefresh dropPack)
-            return dropPack.packUID;
-        
-        // 灏濊瘯閫氳繃鍙嶅皠鑾峰彇 packUID
-        var packUIDField = pack.GetType().GetField("packUID");
-        if (packUIDField != null)
-        {
-            return (ulong)packUIDField.GetValue(pack);
-        }
-        
-        return 0;
-    }
-
-    // 鍒嗛厤缁忛獙鍊硷細灏嗙粡楠屽寘骞冲潎鍒嗛厤缁欐瘡涓浜″璞�
-    protected List<List<HB405_tagMCAddExp>> AssignExp(List<HB405_tagMCAddExp> expList, int deadCount)
-    {
-        var expAssign = new List<List<HB405_tagMCAddExp>>();
-        for (int i = 0; i < deadCount; i++)
-            expAssign.Add(new List<HB405_tagMCAddExp>());
-
-        // 淇锛氭鏌ラ櫎闆堕闄�
-        if (deadCount == 0)
-        {
-            Debug.LogWarning("AssignExp: deadCount涓�0锛屾棤娉曞垎閰嶇粡楠�");
-            return expAssign;
-        }
-
-        // 淇锛氬厛鏀堕泦瑕佸垹闄ょ殑鍖咃紝閬垮厤鍦╢oreach涓慨鏀筽ackList
-        var expPacksToRemove = new List<HB405_tagMCAddExp>();
-
-        foreach (var expPack in expList)
-        {
-            long totalExp = GeneralDefine.GetFactValue(expPack.Exp, expPack.ExpPoint);
-            long avgExp = totalExp / deadCount;
-            long remain = totalExp % deadCount;
-
-            for (int i = 0; i < deadCount; i++)
-            {
-                long assignExp = avgExp + (i < remain ? 1 : 0);
-                var newPack = new HB405_tagMCAddExp
-                {
-                    Exp = (uint)(assignExp % Constants.ExpPointValue),
-                    ExpPoint = (uint)(assignExp / Constants.ExpPointValue),
-                    Source = expPack.Source
-                };
-                expAssign[i].Add(newPack);
-            }
-            expPacksToRemove.Add(expPack);
-        }
-        
-        // 缁熶竴鍒犻櫎鏀堕泦鐨勫寘
-        foreach (var pack in expPacksToRemove)
-        {
-            packList.Remove(pack);
-        }
-
-        return expAssign;
-    }
-
-    // 妫�鏌ユ浜″悗鐨勫寘澶勭悊锛氬鐞嗘妧鑳藉寘銆佹帀钀藉寘銆佺粡楠屽寘
-    protected void CheckAfterDeadhPack()
-    {
-        List<int> removeIndexList = new List<int>();
-        
-        for (int i = 0; i < packList.Count; i++)
-        {
-            var pack = packList[i];
-
-            // 澶嶆椿鍩烘湰閮介潬鎶�鑳藉寘
-            if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
-                break;
-                
-            if (pack is H0704_tagRolePackRefresh h0704Pack && h0704Pack.PackType == (byte)PackType.DropItem && h0704Pack.IsBind == 1)
-            {
-                dropPackList.Add(h0704Pack);
-                removeIndexList.Add(i);
-            }
-            
-            if (pack is HB405_tagMCAddExp h405Pack && h405Pack.Source == 2)
-            {
-                expPackList.Add(h405Pack);
-                removeIndexList.Add(i);
-            }
-        }
-
-        for (int i = removeIndexList.Count - 1; i >= 0; i--)
-            packList.RemoveAt(removeIndexList[i]);
-    }
-
-
-    public virtual bool IsActionCompleted()
-    {
-        if (!isPlay) return false;
-
-        if (skillEffect != null)
-        {
-            if (!skillEffect.IsFinished()) return false;
-        }
-
-        if (moveFinished)
-        {
-            //  濡傛灉鎶�鑳芥湁鍔ㄧ敾锛圫killMotionName涓嶄负绌猴級锛岄渶瑕佺瓑寰呭姩鐢绘挱鏀惧畬鎴�
-            if (skillSkinConfig != null && !string.IsNullOrEmpty(skillSkinConfig.SkillMotionName))
-            {
-                if (!isMotionCompleted)
-                {
-                    BattleDebug.LogError($"SkillBase.IsActionCompleted: 鎶�鑳� {skillConfig.SkillID} 绛夊緟鍔ㄧ敾鎾斁瀹屾垚");
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-    // 妫�鏌ユ妧鑳芥槸鍚﹀畬鎴愶細鍚屾椂鎺ㄨ繘鐘舵�侊紙娓呯悊瀹屾垚鐨勫瓙鎶�鑳姐�佸鐞嗗墿浣欏寘銆佽Е鍙戞浜″垽瀹氾級
-    // 娉ㄦ剰锛氭鏂规硶鏈夊壇浣滅敤锛岃繖鏄璁′娇鐒垛�斺�旂敱SkillRecordAction.Run()姣忓抚璋冪敤鏉ラ┍鍔ㄧ姸鎬佹帹杩�
-    public virtual bool IsFinished()
-    {
-        if (!isPlay) return false;
-        
-        bool tempRetValue = true;
-
-        // 妫�鏌ユ妧鑳芥晥鏋滄槸鍚﹀畬鎴�
-        if (skillEffect != null)
-        {
-            if (!skillEffect.IsFinished()) return false;
-            skillEffect = null;
-            OnSkillFinished();
-            tempRetValue = false;
-        }
-
-        // 妫�鏌ヨ窡杩涚殑鎶�鑳藉姩浣滄槸鍚﹀畬鎴愶紙杩藉嚮/杩炲嚮/鍙嶅嚮绛夛級
-        if (currentWaitingSkill.Count > 0)
-        {
-            if (currentWaitingSkill.Any(s => s.IsFinished()))
-            {
-                currentWaitingSkill.RemoveAll(s => s.IsFinished());
-                OnSkillFinished();
-            }
-            else
-            {
-                tempRetValue = false;
-            }
-        }
-
-        if (!tempRetValue)
-        {
-            return false;
-        }
-
-        // 妫�鏌ユ渶缁堝畬鎴愮姸鎬�
-        if (isFinished && moveFinished)
-        {
-            if (packList.Count > 0)
-            {
-                OnSkillFinished();
-                return false;
-            }
-
-            //  濡傛灉鑷繁鍐呴儴鐨� innerRecordPlayer 杩樻湁娌℃墽琛屽畬鐨勫寘 涔熸槸杩斿洖false
-            if (ownRecordAction != null && ownRecordAction.GetInnerRecordPlayer().IsPlaying())
-            {
-                return false;
-            }
-
-            // 鎶�鑳藉畬鍏ㄧ粨鏉燂紝绉婚櫎鎶�鑳芥敞鍐屽苟瑙﹀彂寤惰繜鐨勬浜″垽瀹�
-            if (battleField != null && caster != null)
-            {
-                battleField.RemoveCastingSkill(caster.ObjID, this);
-                
-                DeathRecordAction recordAction = battleField.OnObjsDead(new List<BattleDeadPack>(tempDeadPackList.Values), null, ownRecordAction);
-                if (null != recordAction)
-                {
-                    ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAction);
-                    tempDeadPackList.Clear();
-                    return false;
-                }
-            }
-
-            return !ownRecordAction.GetInnerRecordPlayer().IsPlaying();
-        }
-
-        return false;
-    }
-
-
-    // 寮哄埗缁撴潫鎶�鑳斤細绔嬪嵆缁撴潫鎵�鏈夋妧鑳界浉鍏崇殑澶勭悊
-    public virtual void ForceFinished()
-    {
-        if (isFinished)
-            return;
-
-        // 绉婚櫎鎶�鑳芥敞鍐�
-        if (battleField != null && caster != null)
-        {
-            battleField.RemoveCastingSkill(caster.ObjID, this);
-        }
-
-        //  浼犻�抪arentRecordAction锛岃姝讳骸鎶�鑳界瓑寰呭綋鍓嶆妧鑳藉畬鎴�
-        RecordAction rc = battleField.OnObjsDead(new List<BattleDeadPack>(tempDeadPackList.Values));
-        if (null != rc)
-        {
-            ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(rc);
-        }
-        tempDeadPackList.Clear();
-
-        // 1. 寮哄埗缁撴潫鎶�鑳芥晥鏋�
-        skillEffect?.ForceFinished();
-        skillEffect = null;
-        
-        // 2. 寮哄埗缁撴潫鎵�鏈夊瓙鎶�鑳藉姩浣�
-        if (currentWaitingSkill.Count > 0)
-        {
-            foreach (var skill in currentWaitingSkill)
-            {
-                skill.ForceFinish();
-            }
-            currentWaitingSkill.Clear();
-        }
-
-        // 3. 娓呯悊 DOTween 鍔ㄧ敾锛堥槻姝㈢Щ鍔ㄥ洖璋冨湪鎴樻枟缁撴潫鍚庢墽琛岋級
-        if (caster != null)
-        {
-            caster.StopMoveAnimation();
-        }
-
-        // 4. 閲嶇疆鏂芥硶鑰呯姸鎬�
-        if (caster != null)
-        {
-            // 閲嶇疆浣嶇疆鍒板師鐐�
-            caster.ResetPosition();
-            
-            // 閲嶇疆鏈濆悜
-            caster.ResetFacing();
-
-            // 鍙栨秷骞诲奖鏁堟灉
-            caster.ShowIllusionShadow(false);
-
-            // 閲嶇疆MotionBase鐨勬妧鑳藉姩鐢荤姸鎬侊紝闃叉playingSkillWithAnim鍗′綇鍚庣画鎶�鑳�
-            if (caster is HeroBattleObject heroCaster)
-            {
-                heroCaster.ForceResetMotionSkillState();
-            }
-        }
-
-        // 5. 鎭㈠ UI 鐘舵��
-        if (battleField != null)
-        {
-            // 鎭㈠鎵�鏈夎鑹茬殑鏄剧ず灞傜骇鍜岃鏉�
-            var allList = battleField.battleObjMgr?.allBattleObjDict?.Values;
-            if (allList != null)
-            {
-                foreach (BattleObject bo in allList)
-                {
-                    bo.layerMgr?.SetFront();
-                    bo.GetHeroInfoBar()?.SetActive(true);
-                }
-            }
-            
-            // 鍏抽棴鎶�鑳介伄缃�
-            if (battleField.battleRootNode != null && battleField.battleRootNode.skillMaskNode != null)
-            {
-                battleField.battleRootNode.skillMaskNode.SetActive(false);
-            }
-        }
-
-        isFinished = true;
-        moveFinished = true;
-        isPlay = true;
-        
-        //  寮哄埗缁撴潫鏃讹紝鏃犺鏄惁鏈夊姩鐢伙紝閮芥爣璁板姩鐢诲畬鎴�
-        isMotionCompleted = true;
-
-        // 6. 澶勭悊鎵�鏈夊墿浣欏寘锛堝寘鎷� buff 鍖咃級
-        // 鍏堝鐞� buffPackCollections
-        DistributeBuffPacks(buffPackCollections);
-        buffPackCollections.Clear();
-
-        // 澶勭悊鍓╀綑鐨� packList
-        while (packList.Count > 0)
-        {
-            var pack = packList[0];
-            packList.RemoveAt(0);
-
-            if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
-            {
-                var otherSkillAction = combinePack.CreateSkillAction();
-                otherSkillAction.fromSkill = this;
-                otherSkillAction.ForceFinish();
-            }
-            else
-            {
-                // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
-                // 鍘熷洜锛欶orceFinished鏃跺墿浣欑殑鍖呬篃鏄妧鑳藉唴閮ㄤ骇鐢熺殑锛屽簲璇ョ敱innerRecordPlayer绠$悊
-                // 杩欐牱鍙互纭繚鍗充娇寮哄埗缁撴潫锛屽寘鐨勫鐞嗕篃鍦ㄦ纭殑涓婁笅鏂囦腑
-                PackageRegedit.Distribute(pack);
-            }
-        }
-    }
-
-    // 鎶�鑳藉畬鎴愬鐞嗭細姝e父瀹屾垚鏃剁殑娓呯悊宸ヤ綔
-    public void OnSkillFinished()
-    {
-        // 淇锛氫娇鐢ㄥ惊鐜唬鏇块�掑綊锛岄伩鍏嶆爤婧㈠嚭椋庨櫓
-        // try
-        // {
-        while (true)
-        {
-            // 楠岃瘉鎶�鑳芥晥鏋滄槸鍚﹀畬鎴�
-            if (skillEffect != null && !skillEffect.IsFinished())
-                return;
-
-            if (skillEffect != null)
-            {
-                skillEffect = null;
-                continue; // 浣跨敤continue浠f浛閫掑綊璋冪敤
-            }
-
-            // 楠岃瘉鍏朵粬鎶�鑳藉姩浣滄槸鍚﹀畬鎴�
-            if (currentWaitingSkill.Count > 0)
-            {
-                bool hasFinishedAction = currentWaitingSkill.All(s => s.IsFinished());
-
-                if (hasFinishedAction)
-                {
-                    // 淇姝诲惊鐜細瀹屾垚鍚庨渶瑕佹竻绌� currentWaitingSkill
-                    currentWaitingSkill.Clear();
-                    continue; // 浣跨敤continue浠f浛閫掑綊璋冪敤
-                }
-                return;
-            }
-
-            break; // 娌℃湁鏇村闇�瑕佸鐞嗙殑锛岄��鍑哄惊鐜�
-        }
-
-        // 澶勭悊鍓╀綑鍖�
-        if (!ResolvePackList())
-        {
-            return;
-        }
-            // }
-            // catch (Exception ex)
-            // {
-            //     Debug.LogError($"OnSkillFinished寮傚父: {ex.Message}锛屾妧鑳絀D={skillConfig.SkillID}");
-            //     // 纭繚鐘舵�佷竴鑷存�э紝鍗充娇鍑虹幇寮傚父涔熻鏍囪瀹屾垚
-            //     isFinished = true;
-            //     throw; // 閲嶆柊鎶涘嚭寮傚父渚涗笂灞傚鐞�
-            // }
-
-        isFinished = true;
-    }
-    
-    protected virtual bool ResolvePackList()
-    {
-        if (currentWaitingSkill.Count > 0)
-        {
-            return false;
-        }
-
-        while (packList.Count > 0)
-        {
-            var pack = packList[0];
-            packList.RemoveAt(0);
-
-
-            if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
-            {
-                var skillRecordAction = combinePack.CreateSkillAction();
-                skillRecordAction.fromSkill = this;
-                currentWaitingSkill.Add(skillRecordAction);
-
-                //  鏍规嵁鍚庣画鎶�鑳界殑灞炴�у喅瀹氭槸鍚﹂渶瑕佺瓑寰呭綋鍓嶆妧鑳藉綊浣�
-                RecordAction waitAction = GetFollowUpWaitAction(skillRecordAction);
-
-                if (skillRecordAction.useParentRecordPlayer && skillRecordAction.parentSkillAction != null)
-                {
-                    if (waitAction != null)
-                        skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction, waitAction);
-                    else
-                        skillRecordAction.parentSkillAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
-                }
-                else
-                {
-                    if (waitAction != null)
-                        ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction, waitAction);
-                    else
-                        ownRecordAction.GetInnerRecordPlayer().PlayRecord(skillRecordAction);
-                }
-
-                return false;
-            }
-            else if (IsBuffPack(pack))
-            {
-                // 浠庢壘鍒扮涓�涓� Buff 鍖呭紑濮嬶紝鏀堕泦杩炵画鐨� HB428/HB429 鍖�
-                buffPackCollections.Add(pack);
-                while (packList.Count > 0)
-                {
-                    var nextPack = packList[0];
-                    if (IsBuffPack(nextPack))
-                    {
-                        buffPackCollections.Add(nextPack);
-                        packList.RemoveAt(0);
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-
-                // 澶勭悊鎵�鏈夋敹闆嗗埌鐨� buff 鍖�
-                ProcessBuffPacks(buffPackCollections);
-
-                // 娓呯┖宸插鐞嗙殑 buff 闆嗗悎
-                buffPackCollections.Clear();
-                continue;
-            }
-            else
-            {
-                // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
-                // 鍘熷洜锛氭妧鑳芥墽琛岃繃绋嬩腑鐨勫寘锛圔uff銆佸睘鎬у埛鏂扮瓑锛夋槸鎶�鑳芥晥鏋滅殑涓�閮ㄥ垎
-                // 搴旇鐢盨killRecordAction鐨刬nnerRecordPlayer绠$悊锛岀‘淇濅笌鎶�鑳界敓鍛藉懆鏈熶竴鑷�
-                PackageRegeditEx.DistributeToRecordAction(pack, ownRecordAction);
-            }
-        }
-
-        return true;
-    }
-
-    /// <summary>
-    /// 鍒ゅ畾鍚庣画鎶�鑳斤紙杩藉嚮/杩炲嚮/鍙嶅嚮绛夛級鏄惁闇�瑕佺瓑寰呭綋鍓嶆妧鑳藉畬鎴愬姩浣滃悗鍐嶉噴鏀�
-    /// 缁煎悎鍒ゅ埆锛氭妧鑳芥槸鍚︽湁鍔ㄧ敾銆侀噴鏀炬ā寮忔槸鍚﹂渶瑕佷綅绉汇�佹槸鍚﹀悓涓�鏂芥硶鑰�
-    /// 浠呭湪纭瀹夊叏鏃惰繑鍥瀢aitAction锛岄伩鍏嶄笉蹇呰鐨勭瓑寰呭拰娼滃湪鐨勮法瑙掕壊鐩镐簰绛夊緟
-    /// </summary>
-    private RecordAction GetFollowUpWaitAction(SkillRecordAction followUp)
-    {
-        // 褰撳墠鎶�鑳藉凡缁忓綊浣嶏紝鏃犻渶绛夊緟
-        if (moveFinished) return null;
-
-        if (followUp.skillBase == null) return null;
-
-        // 鍚庣画鎶�鑳芥病鏈夊姩鐢诲姩浣滐紙鏃燬killMotionName锛夛紝涓嶆秹鍙婁綅绉伙紝鏃犻渶绛夊緟褰掍綅
-        // 杩欑被鎶�鑳藉湪CanCastSkill涓篃涓嶅彈playingSkillWithAnim闄愬埗
-        var followUpSkin = followUp.skillBase.skillSkinConfig;
-        if (followUpSkin == null || string.IsNullOrEmpty(followUpSkin.SkillMotionName))
-            return null;
-
-        // 鍚庣画鎶�鑳藉師鍦伴噴鏀撅紙None/Self锛夛紝铏芥湁鍔ㄧ敾浣嗕笉闇�瑕佷綅绉诲埌鐩爣锛屾棤闇�绛夊緟
-        if (followUpSkin.castMode == SkillCastMode.None || followUpSkin.castMode == SkillCastMode.Self)
-            return null;
-
-        // 鍚屼竴鏂芥硶鑰呯殑鍚庣画鎶�鑳斤紙杩炲嚮绛夛級锛氬繀椤荤瓑寰呭綊浣�
-        // 鍘熷洜锛氬悓涓�瑙掕壊鐨凜astToEnemy/CastToTarget浼歁oveToTarget锛�
-        // 濡傛灉涓婁竴涓妧鑳界殑DOTween褰掍綅杩樻病瀹屾垚灏卞彂璧锋柊浣嶇Щ锛屼袱涓狣OTween浼氬啿绐�
-        if (followUp.skillBase.caster == caster)
-            return ownRecordAction;
-
-        // 涓嶅悓鏂芥硶鑰呯殑鍚庣画鎶�鑳斤紙杩藉嚮/鍙嶅嚮绛夛級锛氫笉娣诲姞绛夊緟
-        // 鍘熷洜锛氫笉鍚岃鑹蹭粠鍚勮嚜浣嶇疆鍑哄彂锛屼笉瀛樺湪DOTween鍐茬獊
-        // 娉ㄦ剰锛氭澶勪笉娣诲姞璺ㄨ鑹茬瓑寰呭叧绯伙紝閬垮厤鎶�鑳介摼A绛塀銆丅绛堿鐨勭浉浜掔瓑寰呴闄�
-        return null;
-    }
-
-    // 娣诲姞娓呯悊鏂规硶锛氶槻姝㈠唴瀛樻硠婕�
-    public virtual void Cleanup()
-    {
-        tempDropList?.Clear();
-        tempDeadPackList?.Clear();
-        currentWaitingSkill?.Clear();
-        dropPackList?.Clear();
-        expPackList?.Clear();
-        buffPackCollections?.Clear();
-        
-        skillEffect = null;
-        packList = null;
-    }
-
-    #region Buff鍖呭鐞�
-
-    /// <summary>
-    /// 鍒ゆ柇鏄惁涓� Buff 鐩稿叧鐨勫寘锛圚B428 鎴� HB429锛�
-    /// </summary>
-    protected bool IsBuffPack(GameNetPackBasic pack)
-    {
-        return pack is HB428_tagSCBuffRefresh || pack is HB429_tagSCBuffDel;
-    }
-
-    /// <summary>
-    /// 澶勭悊鏀堕泦鍒扮殑 Buff 鍖呭垪琛紙HB428 鍒锋柊 鍜� HB429 鍒犻櫎锛�
-    /// </summary>
-    protected void ProcessBuffPacks(List<GameNetPackBasic> buffPacks)
-    {
-        if (buffPacks == null || buffPacks.Count == 0) return;
-
-        foreach (var pack in buffPacks)
-        {
-            if (pack is HB428_tagSCBuffRefresh buffRefresh)
-            {
-                BattleObject battleObj = battleField.battleObjMgr.GetBattleObject((int)buffRefresh.ObjID);
-                if (battleObj != null)
-                {
-                    var buffMgr = battleObj.GetBuffMgr();
-                    if (buffMgr != null) // 鍛芥牸涓嶆湁 buff 绠$悊鍣�
-                    {
-                        buffMgr.RefreshBuff(buffRefresh, true);
-                    }
-                }
-            }
-            else if (pack is HB429_tagSCBuffDel buffDel)
-            {
-                BattleObject battleObj = battleField.battleObjMgr.GetBattleObject((int)buffDel.ObjID);
-                if (battleObj != null)
-                {
-                    var buffMgr = battleObj.GetBuffMgr();
-                    if (buffMgr != null) // 鍛芥牸涓嶆湁 buff 绠$悊鍣�
-                    {
-                        buffMgr.RemoveBuff(buffDel, false);
-                    }
-                }
-            }
-        }
-    }
-
-    /// <summary>
-    /// 寮哄埗鍒嗗彂 Buff 鍖咃紙鐢ㄤ簬 ForceFinished 鍦烘櫙锛�
-    /// </summary>
-    protected void DistributeBuffPacks(List<GameNetPackBasic> buffPacks)
-    {
-        if (buffPacks == null || buffPacks.Count == 0) return;
-
-        foreach (var pack in buffPacks)
-        {
-            // 銆愪娇鐢� parentRecordAction.innerRecordPlayer銆�
-            // 鍘熷洜锛欱uff鍖呮槸鎶�鑳芥晥鏋滅殑鏍稿績缁勬垚閮ㄥ垎锛屽簲璇ョ敱SkillRecordAction绠$悊
-            // 鍗充娇鏄己鍒跺垎鍙戠殑鎯呭喌锛屼篃瑕佷繚鎸佸湪姝g‘鐨凴ecordAction涓婁笅鏂囦腑
-            PackageRegeditEx.DistributeToRecordAction(pack, ownRecordAction);
-        }
-    }
-
-    public virtual bool CanStartExecution()
-    {
-        if (null == caster)
-        {
-            return false;
-        }
-
-        if (null == skillConfig)
-        {
-            return false;
-        }
-
-        if (string.IsNullOrEmpty(skillSkinConfig.SkillMotionName))
-        {
-            return true;
-        }
-
-        return !battleField.IsCastingSkill(caster.ObjID);
-    }
-
-    #endregion
-
-}
\ No newline at end of file
+}
diff --git a/Main/System/Battle/SkillEffect/SkillEffect.cs b/Main/System/Battle/SkillEffect/SkillEffect.cs
index 01a4d36..5231a17 100644
--- a/Main/System/Battle/SkillEffect/SkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/SkillEffect.cs
@@ -90,6 +90,14 @@
         return isFinish && isFinishFrameEnd;
     }
 
+#if UNITY_EDITOR
+    /// <summary>鍗℃璇婃柇鐢細鎵撳嵃 SkillEffect 鍐呴儴 isFinish / isFinishFrameEnd 绛夋爣蹇椾綅銆�</summary>
+    public virtual string DumpState()
+    {
+        return $"{GetType().Name} isFinish={isFinish} isFinishFrameEnd={isFinishFrameEnd}";
+    }
+#endif
+
     public virtual void ForceFinished()
     {
         isFinish = true;
diff --git a/Main/System/Battle/UIComp/BattleHeroInfoBar.cs b/Main/System/Battle/UIComp/BattleHeroInfoBar.cs
index c8f823a..ac5cb40 100644
--- a/Main/System/Battle/UIComp/BattleHeroInfoBar.cs
+++ b/Main/System/Battle/UIComp/BattleHeroInfoBar.cs
@@ -72,6 +72,7 @@
     public static Dictionary<string, ulong> largestPackUID = new Dictionary<string, ulong>();
     public static Dictionary<string, Dictionary<long, long>> largestPackUIDAllObjectsToHp = new Dictionary<string, Dictionary<long, long>>();
     public static Dictionary<string, Dictionary<long, long>> largestPackUIDAllObjectsMaxHp = new Dictionary<string, Dictionary<long, long>>();
+    public static Dictionary<string, Dictionary<long, ulong>> objectLargestPackUID = new Dictionary<string, Dictionary<long, ulong>>();
     
     protected void OnDisable()
     {
@@ -414,11 +415,11 @@
         long objID = battleObject.ObjID;
         ulong currentPackUID = dmgInfo.battleHurtParam.packUID;
         
-        // 妫�鏌ユ槸鍚︽槸鏈�鏂扮殑 PackUID锛屽鏋滀笉鏄垯蹇界暐
-        if (!largestPackUID.ContainsKey(guid) || currentPackUID < largestPackUID[guid])
+        // 鑾峰彇璇ユ垬鍦虹殑瀵硅薄PackUID瀛楀吀锛堢敤浜庢寜瑙掕壊+瑙掕壊韬唤绮掑害鍒ゆ柇锛�
+        Dictionary<long, ulong> objPackUIDDict = null;
+        if (objectLargestPackUID.ContainsKey(guid))
         {
-            // Debug.LogWarning($"[ExecuteDamageUpdate] 蹇界暐鏃у寘 - ObjID:{objID}, 褰撳墠PackUID:{currentPackUID} < 鏈�澶ackUID:{largestPackUID[guid]}");
-            return;
+            objPackUIDDict = objectLargestPackUID[guid];
         }
         
         long maxHp, fromHp, toHp, fromShield, toShield;
@@ -427,6 +428,16 @@
         BattleHurtObj hurter = dmgInfo.battleHurtParam.hurter;
         if (hurter?.hurtObj != null && hurter.hurtObj.ObjID == objID)
         {
+            // 鎸夊璞�+鍙楀嚮鑰呰韩浠芥鏌ackUID锛岄伩鍏嶄笉鍚岃韩浠斤紙hurter/caster锛夌殑鍖呬簰鐩搁樆鎷�
+            long hurterKey = objID * 2; // hurter鐢ㄥ伓鏁発ey
+            if (objPackUIDDict != null 
+                && objPackUIDDict.ContainsKey(hurterKey) 
+                && currentPackUID < objPackUIDDict[hurterKey])
+            {
+                // Debug.LogWarning($"[ExecuteDamageUpdate] 蹇界暐鏃у寘(鍙楀嚮鑰�) - ObjID:{objID}, 褰撳墠PackUID:{currentPackUID} < 瀵硅薄鍙楀嚮鏈�澶ackUID:{objPackUIDDict[hurterKey]}");
+                return;
+            }
+            
             // 褰撳墠InfoBar鏄彈鍑昏�咃紙鍖呮嫭缁欒嚜宸辨不鐤椼�佺粰鑷繁閫犳垚浼ゅ鐨勬儏鍐碉級
             if (hurter.hurtObj.IsTianziBoss())
             {
@@ -440,6 +451,12 @@
             fromShield = hurter.fromShieldValue;
             toShield = hurter.toShieldValue;
             
+            // 鏇存柊璇ュ璞′綔涓哄彈鍑昏�呯殑鏈�澶ackUID
+            if (objPackUIDDict != null)
+            {
+                objPackUIDDict[hurterKey] = currentPackUID;
+            }
+            
             // Debug.LogError($"[ExecuteDamageUpdate] 鍙楀嚮鑰� - ObjID:{objID}, fromHp:{fromHp}, toHp:{toHp}, maxHp:{maxHp} (PackUID:{currentPackUID})");
         }
         // 鍏舵鍒ゆ柇鏄惁涓烘柦娉曡�咃紙鏂芥硶娑堣�楃敓鍛界瓑鎯呭喌锛�
@@ -449,6 +466,16 @@
             if (caster?.casterObj == null || caster.casterObj.ObjID != objID)
             {
                 // Debug.LogWarning($"[ExecuteDamageUpdate] 褰撳墠瀵硅薄 {objID} 鏃笉鏄柦娉曡�呬篃涓嶆槸鍙楀嚮鑰�");
+                return;
+            }
+            
+            // 鎸夊璞�+鏂芥硶鑰呰韩浠芥鏌ackUID
+            long casterKey = objID * 2 + 1; // caster鐢ㄥ鏁発ey
+            if (objPackUIDDict != null 
+                && objPackUIDDict.ContainsKey(casterKey) 
+                && currentPackUID < objPackUIDDict[casterKey])
+            {
+                // Debug.LogWarning($"[ExecuteDamageUpdate] 蹇界暐鏃у寘(鏂芥硶鑰�) - ObjID:{objID}, 褰撳墠PackUID:{currentPackUID} < 瀵硅薄鏂芥硶鏈�澶ackUID:{objPackUIDDict[casterKey]}");
                 return;
             }
             
@@ -463,6 +490,12 @@
             toHp = caster.toHp;
             fromShield = caster.fromShieldValue;
             toShield = caster.toShieldValue;
+            
+            // 鏇存柊璇ュ璞′綔涓烘柦娉曡�呯殑鏈�澶ackUID
+            if (objPackUIDDict != null)
+            {
+                objPackUIDDict[casterKey] = currentPackUID;
+            }
             
             // Debug.LogError($"[ExecuteDamageUpdate] 鏂芥硶鑰� - ObjID:{objID}, fromHp:{fromHp}, toHp:{toHp}, maxHp:{maxHp} (PackUID:{currentPackUID})");
         }
@@ -584,10 +617,15 @@
         {
             largestPackUIDAllObjectsMaxHp[guid] = new Dictionary<long, long>();
         }
+        if (!objectLargestPackUID.ContainsKey(guid))
+        {
+            objectLargestPackUID[guid] = new Dictionary<long, ulong>();
+        }
         
         ulong currentLargestPackUID = largestPackUID[guid];
         Dictionary<long, long> hpDict = largestPackUIDAllObjectsToHp[guid];
         Dictionary<long, long> maxHpDict = largestPackUIDAllObjectsMaxHp[guid];
+        Dictionary<long, ulong> objPackUIDDict = objectLargestPackUID[guid];
         
         // 濡傛灉閬囧埌鏇村ぇ鐨刾ackUID锛屾洿鏂版爣璁帮紙涓嶆竻绌烘暟鎹紝淇濈暀鎵�鏈夎瘉鎹級
         if (currentPackUID > currentLargestPackUID)
@@ -610,11 +648,13 @@
             long maxHp = battleCastObj.maxHp;
             long hpChange = newHp - oldHp;
             
-            // 鍙湁褰撳墠packUID绛変簬鏈�澶ackUID鏃舵墠鏇存柊璁板綍
-            if (currentPackUID == currentLargestPackUID)
+            // 鍙湁褰撳墠packUID涓嶅皬浜庤瀵硅薄鐨勬渶澶ackUID鏃舵墠鏇存柊璁板綍
+            ulong casterLastPackUID = objPackUIDDict.ContainsKey(casterID) ? objPackUIDDict[casterID] : 0ul;
+            if (currentPackUID >= casterLastPackUID)
             {
                 hpDict[casterID] = newHp;
                 maxHpDict[casterID] = maxHp;
+                objPackUIDDict[casterID] = currentPackUID;
                 
                 // 鎵撳嵃琛�閲忓彉鍖栨棩蹇楋紙鏂芥硶鑰呴�氬父鏄仮澶嶇敓鍛斤級
                 // string casterName = caster.casterObj.teamHero?.heroConfig.Name ?? "鏈煡姝﹀皢";
@@ -626,7 +666,7 @@
             }
             else
             {
-                // Debug.LogWarning($"[琛�閲忚褰昡 蹇界暐鏃у寘鏁版嵁 - 鏂芥硶鑰厈casterID}, 褰撳墠PackUID:{currentPackUID} < 鏈�澶ackUID:{currentLargestPackUID}");
+                // Debug.LogWarning($"[琛�閲忚褰昡 蹇界暐鏃у寘鏁版嵁 - 鏂芥硶鑰厈casterID}, 褰撳墠PackUID:{currentPackUID} < 瀵硅薄鏈�澶ackUID:{casterLastPackUID}");
             }
         }
         
@@ -643,11 +683,13 @@
             long maxHp = battleHurtObj.maxHp;
             long damage = oldHp - newHp;
             
-            // 鍙湁褰撳墠packUID绛変簬鏈�澶ackUID鏃舵墠鏇存柊璁板綍
-            if (currentPackUID == currentLargestPackUID)
+            // 鍙湁褰撳墠packUID涓嶅皬浜庤瀵硅薄鐨勬渶澶ackUID鏃舵墠鏇存柊璁板綍
+            ulong hurterLastPackUID = objPackUIDDict.ContainsKey(hurterID) ? objPackUIDDict[hurterID] : 0ul;
+            if (currentPackUID >= hurterLastPackUID)
             {
                 hpDict[hurterID] = newHp;
                 maxHpDict[hurterID] = maxHp;
+                objPackUIDDict[hurterID] = currentPackUID;
                 
                 // 鎵撳嵃琛�閲忓彉鍖栨棩蹇�
                 // string hurterName = hurter.hurtObj.teamHero?.heroConfig.Name ?? "鏈煡姝﹀皢";
@@ -658,7 +700,7 @@
             }
             else
             {
-                // Debug.LogWarning($"[琛�閲忚褰昡 蹇界暐鏃у寘鏁版嵁 - 鍙楀嚮鑰厈hurterID}, 褰撳墠PackUID:{currentPackUID} < 鏈�澶ackUID:{currentLargestPackUID}");
+                // Debug.LogWarning($"[琛�閲忚褰昡 蹇界暐鏃у寘鏁版嵁 - 鍙楀嚮鑰厈hurterID}, 褰撳墠PackUID:{currentPackUID} < 瀵硅薄鏈�澶ackUID:{hurterLastPackUID}");
             }
         }
     }
@@ -894,6 +936,17 @@
         // TODO: 鏄剧ずbuff鎻忚堪/褰撳墠韬笂鎵�鏈塨uff
     }
 
+    /// <summary>
+    /// 娓呯悊鎸囧畾鎴樺満鐨勯潤鎬丳ackUID鍜岃閲忚褰�
+    /// </summary>
+    public static void ClearStaticBattleData(string guid)
+    {
+        largestPackUID.Remove(guid);
+        largestPackUIDAllObjectsToHp.Remove(guid);
+        largestPackUIDAllObjectsMaxHp.Remove(guid);
+        objectLargestPackUID.Remove(guid);
+    }
+
     public void HaveRest()
     {
         CleanupTips();
diff --git a/Main/System/Battle/UIComp/TotalDamageDisplayer.cs b/Main/System/Battle/UIComp/TotalDamageDisplayer.cs
index 5e48926..a6c5323 100644
--- a/Main/System/Battle/UIComp/TotalDamageDisplayer.cs
+++ b/Main/System/Battle/UIComp/TotalDamageDisplayer.cs
@@ -8,8 +8,12 @@
 {
     public Image damageBackground;
     public Text textDamage;
-    public Image imgTotalDesc; //鎬讳激瀹虫垨鑰呮�绘不鐤�
-
+    public Color recoveryColor;
+    public Color recoveryOutlineColor;
+    public Color damageColor;
+    public Color damageOutlineColor;
+    public Text textTotalDesc;
+    public OutlineEx outlineTotalDesc;
     private long damage = 0;
 
     private long heal = 0;
@@ -47,7 +51,9 @@
             }
             textDamage.text = BattleUtility.DisplayDamageNum(heal, BattleConst.BattleTotalRecoverType);
             UILoader.LoadSprite("Fight", "Fight1_img_83", damageBackground).Forget();
-            UILoader.LoadSprite("Fight", "Fight1_img_80", imgTotalDesc).Forget();
+            textTotalDesc.text = Language.Get("DamageTypeRecovery");
+            textTotalDesc.color = recoveryColor;
+            outlineTotalDesc.OutlineColor = recoveryOutlineColor;
         }
         else if (dmgInfo.IsType(DamageType.Damage) || dmgInfo.IsType(DamageType.Realdamage))
         {
@@ -57,8 +63,10 @@
                 damage += d;
             }
             textDamage.text = BattleUtility.DisplayDamageNum(damage, BattleConst.BattleTotalDamageType);
-            UILoader.LoadSprite("Fight", "Fight1_img_85", imgTotalDesc).Forget();
             UILoader.LoadSprite("Fight", "Fight1_img_88", damageBackground).Forget();
+            textTotalDesc.text = Language.Get("DamageTypeDamage");
+            textTotalDesc.color = damageColor;
+            outlineTotalDesc.OutlineColor = damageOutlineColor;
         }
         else
         {
@@ -100,75 +108,7 @@
 
     public async UniTask SetDamageAsync(BattleDmgInfo dmgInfo)
     {
-        var battleField = BattleManager.Instance.GetBattleField(dmgInfo.battleFieldGuid);
-
-        if (!gameObject.activeInHierarchy)
-            gameObject.SetActive(true);
-
-        if (dmgInfo == null)
-            return;
-
-        if (dmgInfo.isFirstHit)
-        {
-            damage = 0;
-            heal = 0;
-        }
-
-        if (dmgInfo.IsType(DamageType.Recovery))
-        {
-            // 淇濇寔鍘熸湁澶勭悊閫昏緫浣嶇疆
-            foreach (var h in dmgInfo.damageList)
-            {
-                heal += h;
-            }
-            textDamage.text = BattleUtility.DisplayDamageNum(heal, BattleConst.BattleTotalRecoverType);
-            damageBackground.sprite = await UILoader.LoadSpriteAsync("Fight", "Fight1_img_83");
-            if (this == null) return;
-            imgTotalDesc.sprite = await UILoader.LoadSpriteAsync("Fight", "Fight1_img_80");
-            if (this == null) return;
-        }
-        else if (dmgInfo.IsType(DamageType.Damage) || dmgInfo.IsType(DamageType.Realdamage))
-        {
-            // 淇濇寔鍘熸湁澶勭悊閫昏緫浣嶇疆
-            foreach (var d in dmgInfo.damageList)
-            {
-                damage += d;
-            }
-            textDamage.text = BattleUtility.DisplayDamageNum(damage, BattleConst.BattleTotalDamageType);
-            imgTotalDesc.sprite = await UILoader.LoadSpriteAsync("Fight", "Fight1_img_85");
-            if (this == null) return;
-            damageBackground.sprite = await UILoader.LoadSpriteAsync("Fight", "Fight1_img_88");
-            if (this == null) return;
-        }
-        else
-        {
-            gameObject.SetActive(false);
-            return;
-        }
-
-        if (punchTween != null && punchTween.IsActive())
-        {
-            battleField.battleTweenMgr.OnKillTween(punchTween);
-            textDamage.transform.localScale = Vector3.one;
-            punchTween = null;
-        }
-
-        punchTween = DOTween.Sequence();
-        var tween1 = textDamage.transform.DOPunchScale(scalePunch, scaleDuration / battleField.speedRatio, 1);
-        punchTween.Append(tween1);
-        //  鎾斁缁撴潫鍚� 寤惰繜1.5绉掑啀娑堝け
-        var tween2 = DOVirtual.DelayedCall(delayCloseDuration / battleField.speedRatio, () => { });
-        punchTween.Append(tween2);
-        punchTween.OnComplete(() =>
-        {
-            textDamage.transform.localScale = Vector3.one;
-            if (dmgInfo.isLastHit)
-            {
-                gameObject.SetActive(false);
-            }
-        });
-
-        battleField.battleTweenMgr.OnPlayTween(punchTween);
-
+        SetDamage(dmgInfo);
+        await UniTask.CompletedTask;
     }
 }
diff --git a/Main/System/BattlePass/BattlePassManager.cs b/Main/System/BattlePass/BattlePassManager.cs
index ead813c..d4f3745 100644
--- a/Main/System/BattlePass/BattlePassManager.cs
+++ b/Main/System/BattlePass/BattlePassManager.cs
@@ -133,11 +133,19 @@
                     UpdateWeekRedPoint();
                     break;
                 }
+
+        }
+
+        if (HeroDebutManager.IsZhanLingType(type))
+        {
+            HeroDebutManager.Instance.UpdateRedpoint();
+            HeroReturnManager.Instance.UpdateRedpoint();
+            return;
         }
     }
 
-    
-    
+
+
     #endregion
     //鏄惁鏈変换浣曞鍔卞彲浠ラ鍙�
     public bool HasAnyAward(int type, int totalValue)
@@ -370,7 +378,18 @@
 
 
         }
-        return 0;       
+
+        if (HeroDebutManager.IsZhanLingType(_type))
+        {
+            return HeroDebutManager.GetZhanLingValueByType(_type);
+        }
+
+        if (HeroReturnManager.IsZhanLingType(_type))
+        {
+            return HeroReturnManager.GetZhanLingValueByType(_type);
+        }
+
+        return 0;
     }
 }
 
diff --git a/Main/System/BillboardRank/PlayerRankWin.cs b/Main/System/BillboardRank/PlayerRankWin.cs
index 606a023..4a42e78 100644
--- a/Main/System/BillboardRank/PlayerRankWin.cs
+++ b/Main/System/BillboardRank/PlayerRankWin.cs
@@ -21,8 +21,9 @@
 
 
     //鏁版嵁鍚庣画浠巑anager涓褰曡幏鍙�
-    [HideInInspector] public int groupValue1 = 0;   //涓�鑸敤浜庤法鏈�
-    [HideInInspector] public int groupValue2 = 0;   //涓�鑸敤浜庤法鏈�
+    [HideInInspector] public static int groupValue1 = 0;   //涓�鑸敤浜庤法鏈�
+    [HideInInspector] public static int groupValue2 = 0;   //涓�鑸敤浜庤法鏈�
+    [HideInInspector] public static int crossServerID = 0;   //涓�鑸敤浜庤法鏈�
     protected int rankType; //浠巉unctionOrder鑾峰彇
 
     protected override void InitComponent()
@@ -35,7 +36,8 @@
     {
         rankType = functionOrder;
         RankModel.Instance.ResetQueryParam();
-        RankModel.Instance.QueryRankByPage(rankType, watchID: (int)PlayerDatas.Instance.baseData.PlayerID);
+        RankModel.Instance.QueryRankByPage(rankType, watchID: (int)PlayerDatas.Instance.baseData.PlayerID,
+            groupValue1: groupValue1, groupValue2: groupValue2, crossServerID: crossServerID);
 
         RankModel.Instance.onRankRefresh += OnRankRefresh;
         scrollerController.OnRefreshCell += OnRefreshCell;
@@ -46,6 +48,10 @@
     {
         RankModel.Instance.onRankRefresh -= OnRankRefresh;
         scrollerController.OnRefreshCell -= OnRefreshCell;
+
+        groupValue1 = 0;
+        groupValue2 = 0;
+        crossServerID = 0;
     }
 
     protected override void OnClose()
@@ -84,7 +90,7 @@
     {
         var _cell = cell.GetComponent<PlayerRankCell>();
         _cell.Display(rankType, cell.index + 1);
-        RankModel.Instance.ListenRankPage(rankType, cell.index, groupValue1, groupValue2);
+        RankModel.Instance.ListenRankPage(rankType, cell.index, groupValue1, groupValue2, crossServerID);
     }
 
 
diff --git a/Main/System/BillboardRank/PlayerTop3Cell.cs b/Main/System/BillboardRank/PlayerTop3Cell.cs
index 43df966..51027f7 100644
--- a/Main/System/BillboardRank/PlayerTop3Cell.cs
+++ b/Main/System/BillboardRank/PlayerTop3Cell.cs
@@ -27,7 +27,7 @@
         }
         officialTitleCell.SetActive(true);
         //rankValueText.text = string.Format(valueFormat, UIHelper.ReplaceLargeNum(rankData.cmpValue2 + rankData.cmpValue * Constants.ExpPointValue));
-        if (rankType == QunyingManager.rankType)
+        if (rankType == QunyingManager.rankType || rankType == QunyingManager.crossRankType)
         {
             //鍖烘湇
             if (GeneralDefine.IsRobot((int)rankData.id))
diff --git a/Main/System/BillboardRank/RankModel.cs b/Main/System/BillboardRank/RankModel.cs
index 1c54c61..c2a920e 100644
--- a/Main/System/BillboardRank/RankModel.cs
+++ b/Main/System/BillboardRank/RankModel.cs
@@ -104,7 +104,8 @@
     //
     //  startIndex 鍜� count 閰嶅锛屼笌watchID鏃犲叧鑱�
     //  watchID;    //鏌ョ湅鎸囧畾ID鍚嶆鍓嶅悗锛屾煡璇㈣寖鍥存湇鍔$宸插浐瀹氾紝濡傛灉鍙鏌ユ寚瀹氱洰鏍囷紝count鍙互璁剧疆1鍑忓皯闄勫姞淇℃伅
-    public void QueryRankByPage(int type, int startIndex = 0, int count = 20, int watchID = 0, bool forceQuery = false, int groupValue1 = 0, int groupValue2 = 0)
+    public void QueryRankByPage(int type, int startIndex = 0, int count = 20, int watchID = 0, bool forceQuery = false,
+        int groupValue1 = 0, int groupValue2 = 0, int crossServerID=0)
     {
         if (queryRankCD.ContainsKey(type) && !forceQuery)
         {
@@ -121,13 +122,14 @@
         pak.StartIndex = (ushort)startIndex;  //鎺掑悕浠�0寮�濮�
         pak.ViewCnt = (byte)count;
         pak.ViewID = (uint)watchID;
+        pak.CrossServerID = (uint)crossServerID;
 
         GameNetSystem.Instance.SendInfo(pak);
         queryRankCD[type] = (int)Time.time;
     }
 
 
-    public void ListenRankPage(int type, int index, int groupValue1 = 0, int groupValue2 = 0)
+    public void ListenRankPage(int type, int index, int groupValue1 = 0, int groupValue2 = 0, int crossServerID = 0)
     {
         int page = index / pageCnt;
         if (index > page * pageCnt + queryPointNum)
@@ -143,7 +145,7 @@
                 }
             }
             Debug.LogFormat("鍒嗛〉鏌ヨ锛歿0} - {1}", index, page);
-            QueryRankByPage(type, pageCnt * (page + 1), pageCnt, 0, true, groupValue1, groupValue2);
+            QueryRankByPage(type, pageCnt * (page + 1), pageCnt, 0, true, groupValue1, groupValue2, crossServerID);
             queryPageTimes[page] = Time.realtimeSinceStartup;
         }
     }
@@ -237,7 +239,7 @@
         for (int i = 0; i < package.PageDataCnt; i++)
         {
             int orderIndex = (int)package.PageDataList[i].Rank;
-            if (rankType == QunyingManager.rankType && GeneralDefine.IsRobot((int)package.PageDataList[i].ID))
+            if ((rankType == QunyingManager.rankType || rankType == QunyingManager.crossRankType) && GeneralDefine.IsRobot((int)package.PageDataList[i].ID))
             {
                 //缇よ嫳姒滄満鍣ㄤ汉ID浼氶噸澶� 鐢ㄦ帓鍚嶆浛鎹D
                 package.PageDataList[i].ID = (uint)orderIndex;
diff --git a/Main/System/BoneField/AdsManager.cs b/Main/System/BoneField/AdsManager.cs
index c24235c..45afd4b 100644
--- a/Main/System/BoneField/AdsManager.cs
+++ b/Main/System/BoneField/AdsManager.cs
@@ -9,13 +9,14 @@
     public Dictionary<int, Redpoint> redPointDict = new Dictionary<int, Redpoint>();
 
     public int waitAdID = 0;  //鍥炶皟鍚庡彂鏀惧鍔辩敤
+    public int waitRemainAdsCount = 0;  //鏂嚎骞朵笉鐭ユ槸鍚﹂鍙栨垚鍔� 鐢ㄦ鏁板仛浜屾楠岃瘉
     int loadErrorCD = 10;   //绛夊緟10绉掑悗鎵嶈兘鍐嶈姹�
     public float lastLoadErrorTime = 0;
 
     public override void Init()
     {
         DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEvent;
-        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += UpdateRedpoint;
+        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += PlayerLoginOkEvent;
         DungeonManager.Instance.UpdateFBInfoListEvent += OnUpdateFBInfoChangeEvent;
         FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
 
@@ -34,7 +35,7 @@
     public override void Release()
     {
         DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEvent;
-        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= UpdateRedpoint;
+        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= PlayerLoginOkEvent;
         DungeonManager.Instance.UpdateFBInfoListEvent -= OnUpdateFBInfoChangeEvent;
         FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
     }
@@ -52,7 +53,13 @@
     public void OnBeforePlayerDataInitializeEvent()
     {
         waitAdID = 0;
+        waitRemainAdsCount = 0;
         adsInfoDict.Clear();
+    }
+
+    public void PlayerLoginOkEvent()
+    {
+        UpdateRedpoint();
     }
 
     private void OnUpdateFBInfoChangeEvent(int mapID)
@@ -73,6 +80,23 @@
         GameNetSystem.Instance.SendInfo(pack);
     }
 
+    //鏌ョ湅骞垮憡绛夊緟澶箙鍙兘瀵艰嚧濂栧姳琚竻绌猴紝闇�瑕佹仮澶�
+    public void RestoreAdsAward()
+    {
+        if (waitAdID == 0) return;
+        int adsCnt = GetADCntByADID(waitAdID);
+        var aDAwardConfig = ADAwardConfig.Get(waitAdID);
+        if (waitRemainAdsCount != 0 && waitRemainAdsCount == aDAwardConfig.ADCntMax - adsCnt)
+        {
+            //鎭㈠濂栧姳棰嗗彇
+            GetAdsAward(waitAdID);
+        }
+
+        waitAdID = 0;
+        waitRemainAdsCount = 0;
+    }
+
+
     //鍖哄垎涓嶅悓娓犻亾鏄惁鏈夊箍鍛奡DK
     public void PlayAds(int ADID)
     {
@@ -89,7 +113,14 @@
                     SysNotifyMgr.Instance.ShowTip("AdLoadFail");
                     return;
                 }
+
+                //绛夊緟骞垮憡鐨処D鍜屽墿浣欐鏁�
                 waitAdID = ADID;
+                int adsCnt = GetADCntByADID(waitAdID);
+                var aDAwardConfig = ADAwardConfig.Get(waitAdID);
+                waitRemainAdsCount = aDAwardConfig.ADCntMax - adsCnt;
+
+
                 SDKUtils.Instance.PlayAds("b69a2b68bb3d22");
                 return;
             }
@@ -190,6 +221,8 @@
             UpdateRedpoint();
 
         }
+
+        RestoreAdsAward();
     }
 
     void UpdateRedpoint()
diff --git a/Main/System/Chat/ChatManager.cs b/Main/System/Chat/ChatManager.cs
index fd02c86..a4e0e76 100644
--- a/Main/System/Chat/ChatManager.cs
+++ b/Main/System/Chat/ChatManager.cs
@@ -1,8 +1,8 @@
-锘縰sing System.Collections;
+锘縰sing System;
+using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using System.Text;
-using System;
 using LitJson;
 
 public partial class ChatManager : GameSystemManager<ChatManager>
@@ -161,6 +161,7 @@
             return true;
         return false;
     }
+
     // 0-绯荤粺 1-鏃ユ湡 2-鑷繁 3-鍏朵粬鐜╁
     public int GetTalkDataType(TalkData talkData)
     {
@@ -428,6 +429,7 @@
     }
 
 
+    
     public void AddTalkData(ChatChannel type, TalkData data, bool isSendBullet)
     {
         //濡傛灉瓒呰繃闄愬埗鍏堝垹闄ゆ棫鏁版嵁
@@ -447,10 +449,7 @@
             }
         }
 
-        if (isSendBullet)
-        {
-            OnUpdateTalkEvent?.Invoke(type, data, isSendBullet);
-        }
+        OnUpdateTalkEvent?.Invoke(type, data, isSendBullet);
     }
 
     public Dictionary<ChatChannel, int> currentDayDict = new Dictionary<ChatChannel, int>();
@@ -478,16 +477,17 @@
         return false;
     }
 
-    public void AddSysData(string msg, ArrayList infoList, ChatChannel type, bool isSendBullet)
+    public void AddSysData(string msg, ArrayList infoList, ChatChannel type)
     {
         int allSeconds = type == ChatChannel.CrossServer ? TimeUtility.GetCommServerTick(GuildManager.Instance.zoneID) : TimeUtility.AllSeconds;
-        // 濡傛灉闅斿ぉ,澧炲姞鏃ユ湡琛�
-        TryAddDate(allSeconds, type, isSendBullet);
+        
+        TryAddDate(allSeconds, type, false);
 
         if (!talkDict.ContainsKey(type))
         {
             talkDict[type] = new List<TalkData>();
         }
+        
         AddTalkData(type, new TalkData()
         {
             ChannelType = (byte)type,
@@ -496,9 +496,21 @@
             BubbleBox = 1,
             TalkTime = (uint)allSeconds,
             InfoList = new ArrayList(infoList),
-        }, isSendBullet);
+        }, false);
     }
 
+    public void SendPureBullet(string msg, ArrayList infoList, ChatChannel type = ChatChannel.World)
+    {
+        TalkData talkData = new TalkData()
+        {
+            ChannelType = (byte)type,
+            isSystem = true,
+            Content = msg,
+            InfoList = infoList != null ? new ArrayList(infoList) : null
+        };
+
+        OnUpdateTalkEvent?.Invoke(type, talkData, true);
+    }
     public void UpdateTalk(HB310_tagMCTalk vNetData)
     {
         if (!IsValidChatChannel(vNetData.ChannelType))
diff --git a/Main/System/CrossServer.meta b/Main/System/CrossServer.meta
new file mode 100644
index 0000000..eb0ce04
--- /dev/null
+++ b/Main/System/CrossServer.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8fae93ee0ca9b9040896b208bbadd15f
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/CrossServer/CrossServerBaseManager.cs b/Main/System/CrossServer/CrossServerBaseManager.cs
new file mode 100644
index 0000000..d08c743
--- /dev/null
+++ b/Main/System/CrossServer/CrossServerBaseManager.cs
@@ -0,0 +1,62 @@
+锘縰sing System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using System;
+
+
+
+public class CrossServerBaseManager : GameSystemManager<CrossServerBaseManager>
+{
+    public Dictionary<int, CrossZoneInfo> crossZoneInfoDict = new Dictionary<int, CrossZoneInfo>();
+    public override void Init()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitialize;
+    }
+
+    public override void Release()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitialize;
+    }
+
+    void OnBeforePlayerDataInitialize()
+    {
+        crossZoneInfoDict.Clear();
+    }
+
+    public void UpdateSCCrossZoneInfo(HC010_tagSCCrossZoneInfo netPack)
+    {
+        crossZoneInfoDict[(int)netPack.MapID] = new CrossZoneInfo()
+        {
+            MapID = netPack.MapID,
+            ZoneID = netPack.ZoneID,
+            ServerIDList = netPack.ServerIDList,
+            CrossServerID = netPack.CrossServerID
+        };
+
+    }
+
+    // 娌℃湁鏁版嵁浠h〃涓嶅湪璺ㄦ湇涓紝缇よ嫳鏈変釜鐗规畩绾﹀畾zoneid绛変簬0浠h〃缁撶畻涓�
+    public bool IsOpenCrossServer(int mapID)
+    {
+        return crossZoneInfoDict.ContainsKey(mapID);
+    }
+
+    public CrossZoneInfo GetCrossZoneInfo(int mapID)
+    {
+        if (crossZoneInfoDict.ContainsKey(mapID))
+        {
+            return crossZoneInfoDict[mapID];
+        }
+        return null;
+    }
+
+}
+
+public class CrossZoneInfo
+{
+    public uint MapID;
+    public uint ZoneID;    // 鎵�灞炲垎鍖猴紝鍙兘涓�0
+    public uint CrossServerID;    // 鎵�灞炶法鏈嶆湇鍔″櫒ID
+    public uint[] ServerIDList;    // 浜掗�氭湇鍔″櫒ID鍒楄〃锛屽彲鑳戒负绌�
+}
+
diff --git a/Main/System/CrossServer/CrossServerBaseManager.cs.meta b/Main/System/CrossServer/CrossServerBaseManager.cs.meta
new file mode 100644
index 0000000..65de1d0
--- /dev/null
+++ b/Main/System/CrossServer/CrossServerBaseManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 041122dd73b1a6645a00bfa5ead9b7e9
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Debug/DebugLogin.cs b/Main/System/Debug/DebugLogin.cs
index 3dc2939..62c4d56 100644
--- a/Main/System/Debug/DebugLogin.cs
+++ b/Main/System/Debug/DebugLogin.cs
@@ -101,7 +101,7 @@
 
             LoginManager.Instance.sdkLogined = true;
             var ip = ServerListCenter.Instance.currentServer.region_domain;
-            var port = ServerListCenter.Instance.currentServer.login_port;
+            var port = ServerListCenter.Instance.currentServer.http_port;
             var gamePort = ServerListCenter.Instance.currentServer.game_port;
             if (!string.IsNullOrEmpty(serverId.text))
             {
diff --git a/Main/System/FirstCharge/FirstChargeHeroInfoWin.cs b/Main/System/FirstCharge/FirstChargeHeroInfoWin.cs
index c8ca37f..50c4532 100644
--- a/Main/System/FirstCharge/FirstChargeHeroInfoWin.cs
+++ b/Main/System/FirstCharge/FirstChargeHeroInfoWin.cs
@@ -38,9 +38,12 @@
         ItemInfo itemInfo = new ItemInfo();
         itemInfo.itemId = FirstChargeManager.Instance.heroItemID;
         HeroInfo heroInfo = new HeroInfo(new ItemModel(PackType.Item, itemInfo));
-        txtInheritAttr[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0], heroInfo.heroConfig.AtkInheritPer));
-        txtInheritAttr[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1], heroInfo.heroConfig.DefInheritPer));
-        txtInheritAttr[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2], heroInfo.heroConfig.HPInheritPer));
+        txtInheritAttr[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0],
+            HeroUIManager.Instance.GetMaxInheritAttr(PlayerPropertyConfig.inheritAttrs[0], heroInfo.heroId, heroInfo.Quality, heroInfo.heroConfig)));
+        txtInheritAttr[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1],
+            HeroUIManager.Instance.GetMaxInheritAttr(PlayerPropertyConfig.inheritAttrs[1], heroInfo.heroId, heroInfo.Quality, heroInfo.heroConfig)));
+        txtInheritAttr[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2],
+            HeroUIManager.Instance.GetMaxInheritAttr(PlayerPropertyConfig.inheritAttrs[2], heroInfo.heroId, heroInfo.Quality, heroInfo.heroConfig)));
 
         int valuePer = heroInfo.GetFakeOnBattleAddPer();
         for (int i = 0; i < txtHeroAddAttrPer.Length; i++)
diff --git a/Main/System/Guild/GuildBossManager.cs b/Main/System/Guild/GuildBossManager.cs
index b96ceef..02c70f1 100644
--- a/Main/System/Guild/GuildBossManager.cs
+++ b/Main/System/Guild/GuildBossManager.cs
@@ -320,7 +320,7 @@
             Job = playerInfo.Job,
             Name = playerInfo.Name,
             FacePic = playerInfo.FacePic,
-            FightPower = (ulong)playerInfo.FightPower,
+            FightPower = playerInfo.FightPower,
             RealmLV = playerInfo.RealmLV,
             ServerID = playerInfo.ServerID,
             TitleID = playerInfo.TitleID,
@@ -380,7 +380,7 @@
     public int Job;
     public string Name;
     public int FacePic;
-    public ulong FightPower;
+    public long FightPower;
     public int RealmLV;
     public int ServerID;
     public int TitleID;
diff --git a/Main/System/Guild/GuildEmblemSelectCell.cs b/Main/System/Guild/GuildEmblemSelectCell.cs
index b325ac1..6212360 100644
--- a/Main/System/Guild/GuildEmblemSelectCell.cs
+++ b/Main/System/Guild/GuildEmblemSelectCell.cs
@@ -7,7 +7,7 @@
 public class GuildEmblemSelectCell : MonoBehaviour
 {
     [SerializeField] GuildEmblemCell emblemIcon;
-    [SerializeField] Image useImg;
+    [SerializeField] TextEx usetext;
     [SerializeField] Image lockImg;
     [SerializeField] Image selectImg;
     [SerializeField] Button selectBtn;
@@ -19,11 +19,11 @@
         emblemIcon.Display(id, "", 0.5f);
         if (PlayerDatas.Instance.fairyData.fairy == null)
         {
-            useImg.SetActive(false);
+            usetext.SetActive(false);
         }
         else
         {
-            useImg.SetActive(id == PlayerDatas.Instance.fairyData.fairy.EmblemID);
+            usetext.SetActive(id == PlayerDatas.Instance.fairyData.fairy.EmblemID);
         }
         lockImg.SetActive(!GuildEmblemModel.Instance.IsUnLock(id));
         selectImg.SetActive(id == GuildEmblemModel.Instance.nowChooseEmblemId);
diff --git a/Main/System/Guild/GuildHawkerWin.cs b/Main/System/Guild/GuildHawkerWin.cs
index 468dd8a..b6cc1ff 100644
--- a/Main/System/Guild/GuildHawkerWin.cs
+++ b/Main/System/Guild/GuildHawkerWin.cs
@@ -1,4 +1,5 @@
-锘縰sing System.Collections.Generic;
+锘縰sing System;
+using System.Collections.Generic;
 using System.Linq;
 using UnityEngine;
 using UnityEngine.UI;
@@ -40,8 +41,15 @@
         GuildManager.Instance.UpdateZhenbaogeEvent += OnPlayerZBGEvent;
         GlobalTimeEvent.Instance.secondEvent += OnSecondEvent;
         GlobalTimeEvent.Instance.fiveSecondEvent += OnFiveSecondEvent;
-        
-        Display();
+
+        try
+        {
+            Display();
+        }
+        catch (Exception e)
+        {
+            Debug.LogError(e);
+        }
         CreateScroller();
     }
 
diff --git a/Main/System/Hero/HeroInfo.InheritPer.cs b/Main/System/Hero/HeroInfo.InheritPer.cs
index 7eb9123..615a233 100644
--- a/Main/System/Hero/HeroInfo.InheritPer.cs
+++ b/Main/System/Hero/HeroInfo.InheritPer.cs
@@ -12,17 +12,49 @@
 			if (_inheritPer == null)
 			{
 				_inheritPer = new Dictionary<int, int>() {
-					{ 6, heroConfig.AtkInheritPer },
-					{ 7, heroConfig.DefInheritPer },
-					{ 8, heroConfig.HPInheritPer },
+					{ 6, heroConfig.AtkInheritPer + heroConfig.AtkInheritPerStar * heroStar },
+					{ 7, heroConfig.DefInheritPer + heroConfig.DefInheritPerStar * heroStar},
+					{ 8, heroConfig.HPInheritPer + heroConfig.HPInheritPerStar * heroStar},
 				};
 			}
 			return _inheritPer;
 		}
 	}
-	
+
+	public void RefreshInheritPer()
+	{
+		_inheritPer = null;
+	}
+
+	//鍘熸潵缁ф壙鏄寜鍝侀�氱敤锛岀幇鍦ㄥ崌鏄熶篃浼氬姞缁ф壙锛岄�氳繃涓夌淮ID鑾峰彇6锛�7锛�8
 	public int GetInheritAttrPer(int attrType)
 	{
 		return inheritPer.TryGetValue(attrType, out int value) ? value : 0;
 	}
+
+	//閫氳繃缁ф壙ID鑾峰彇瀵瑰簲鐨勪竾鍒嗙巼
+	public int GetInheritAttrPerByInheritID(int id)
+	{
+		var baseID = id == 13 ? 6 : id == 14 ? 7 : id == 15 ? 8 : 0;
+		return GetInheritAttrPer(baseID);
+	}
+	// 鑾峰彇缁ф壙ID
+	public int GetInheritAttrIDByBaseID(int id)
+	{
+		if (id == 6) return 13;
+		if (id == 7) return 14;
+		if (id == 8) return 15;
+		return 0;
+	}
+
+	//鑾峰彇姣忔槦鎻愬崌灞炴�у�� 涓囧垎鐜�
+	public int GetInheritSingleAttrValue(int id)
+	{
+		if (id == 13) return heroConfig.AtkInheritPerStar;
+		if (id == 14) return heroConfig.DefInheritPerStar;
+		if (id == 15) return heroConfig.HPInheritPerStar;
+		return 0;
+	}
+
+
 }
diff --git a/Main/System/HeroDebut/HeroDebutCallWin.cs b/Main/System/HeroDebut/HeroDebutCallWin.cs
index 2606539..2e76b25 100644
--- a/Main/System/HeroDebut/HeroDebutCallWin.cs
+++ b/Main/System/HeroDebut/HeroDebutCallWin.cs
@@ -45,6 +45,7 @@
     [SerializeField] UIHeroController lhController;
     [SerializeField] UIHeroController uiHeroController;
     [SerializeField] HeroDebutCallBubbleCell[] bubbleCell;
+    [SerializeField] RichText richText;
 
     [SerializeField] float modleSize = 1f;
     HeroDebutManager manager => HeroDebutManager.Instance;
@@ -264,8 +265,10 @@
         xbButton10.Display(config.ActTreasureType, 1);
         resMoneyCallCntText.text = Language.Get("HeroDebut24", Mathf.Max(treasureSetConfig.DailyMaxCountMoney - xbTypeInfo.treasureCountTodayGold, 0));
 
-        var needCount = GetNextXBCountForBigAward(treasureType);
-        nextBigAwardCntText.text = Language.Get("HeroDebut08", needCount.ToString());
+        int buyState = manager.GetZhanLingBuyState();
+        bool isBuyPaidH = buyState == 2 || buyState == 3;
+        var needCount = manager.GetNextXBCountForBigAward(treasureType) - (isBuyPaidH ? manager.subVulue : 0);
+        nextBigAwardCntText.text = Language.Get("HeroDebut08", needCount <= 0 ? 1 : needCount);
 
         heroQualityText.text = Language.Get($"heroCallQaulity{heroConfig.Quality}");
         manager.SetheroQaulityColor(heroQualityText, heroConfig.Quality);
@@ -292,28 +295,14 @@
             }
         }
 
+        // 璐拱浜嗛珮绾ф垬浠わ紙鐜勭骇锛夋椂闅愯棌richText
+        richText.SetActive(!isBuyPaidH);
+
         ShowTop3();
         OnSecondEvent();
     }
 
-    public int GetNextXBCountForBigAward(int type)
-    {
-        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
-        if (typeInfo == null) return 0;
 
-        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
-        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
-        luckList.Sort();
-        for (int i = 0; i < luckList.Count; i++)
-        {
-            var luckyValue = typeInfo.luckValue;
-            if (luckyValue < luckList[i])
-            {
-                return luckList[i] - luckyValue;
-            }
-        }
-        return 0;
-    }
     void ShowTop3()
     {
         for (int i = 0; i < top3NameText.Length; i++)
@@ -341,6 +330,8 @@
         scroller.Refresh();
 
         int listCount = list?.Count ?? 0;
+        historyButton.SetActive(listCount > 0);
+
         if (list != null)
         {
             for (int i = 0; i < listCount; i++)
diff --git a/Main/System/HeroDebut/HeroDebutManager.cs b/Main/System/HeroDebut/HeroDebutManager.cs
index 74cb1c8..baa2f25 100644
--- a/Main/System/HeroDebut/HeroDebutManager.cs
+++ b/Main/System/HeroDebut/HeroDebutManager.cs
@@ -7,9 +7,13 @@
 
 public class HeroDebutManager : GameSystemManager<HeroDebutManager>, IOpenServerActivity
 {
+    // 缂撳瓨鐨刏hanLingType鍒楄〃锛堜粠ActHeroAppearConfig鑾峰彇锛屽悗缁笉鍙橈級
+    private static List<int> zhanLingTypeList = null;
+
     public int[] xbGridArr;
     public Dictionary<int, int[][]> heroQaulityColor;
     public int[][] seeArr;
+    public int subVulue;
     public override void Init()
     {
         DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
@@ -29,8 +33,11 @@
         xbGridArr = JsonMapper.ToObject<int[]>(config.Numerical1);
         heroQaulityColor = ConfigParse.ParseIntArray2Dict(config.Numerical2);
         seeArr = JsonMapper.ToObject<int[][]>(config.Numerical3);
+        subVulue = int.Parse(config.Numerical4);
 
         InitRedPointId();
+
+        BattlePassManager.Instance.BattlePassDataUpdateEvent += OnBattlePassDataUpdate;
     }
 
     public void SetheroQaulityColor(GradientText text, int qaulity)
@@ -53,6 +60,8 @@
         GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent -= OnUpdateActSignInfosEvent;
         HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
         TimeMgr.Instance.OnDayEvent -= OnDayEvent;
+
+        BattlePassManager.Instance.BattlePassDataUpdateEvent -= OnBattlePassDataUpdate;
     }
 
     private void OnDayEvent()
@@ -117,7 +126,6 @@
                 UIManager.Instance.CloseWindow<HeroDebutPopWin>();
             if (UIManager.Instance.IsOpened<HeroDebutWin>())
                 UIManager.Instance.CloseWindow<HeroDebutWin>();
-            gameRecDict.Clear();
             UpdateRedpoint();
         }
     }
@@ -126,6 +134,8 @@
     {
         if (type == operaType && state == 0)
         {
+            gameRecDict.Clear();
+            isSendFirst = true;
             onStateUpdate?.Invoke(activityID);
             TryPopWin();
             UpdateRedpoint();
@@ -290,12 +300,14 @@
     public Redpoint starUpRedpoint;
     public Redpoint shopRedpoint;
     public Redpoint giftRedpoint;
+    public Redpoint zhanLingRedpoint;
     public void InitRedPointId()
     {
         checkInRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.CheckIn));
         starUpRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.StarUp));
         shopRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.Shop));
         giftRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.Gift));
+        zhanLingRedpoint ??= new Redpoint(MainRedDot.HeroDebutRepoint, GetRedPointId(HeroDebutRedPointType.ZhanLing));
     }
 
     public void UpdateRedpoint()
@@ -305,6 +317,7 @@
         starUpRedpoint.state = RedPointState.None;
         shopRedpoint.state = RedPointState.None;
         giftRedpoint.state = RedPointState.None;
+        zhanLingRedpoint.state = RedPointState.None;
 
         if (!IsHeroDebutOpen()) return;
 
@@ -327,6 +340,11 @@
         if (HasGiftCanHave())//鐨囨潈绀煎寘
         {
             giftRedpoint.state = RedPointState.Simple;
+        }
+
+        if (HasZhanLingCanHave())//鎴樹护
+        {
+            zhanLingRedpoint.state = RedPointState.Simple;
         }
     }
     #endregion
@@ -495,8 +513,8 @@
         if (heroConfig == null) return 0;
 
         // 娌¤幏寰楁灏嗘湰浣撲笉鍙鍙�
-        if (!HeroManager.Instance.HasHero(heroId))return 0;
-        
+        if (!HeroManager.Instance.HasHero(heroId)) return 0;
+
         if (IsStarUpFreeHave(starHeroIndex, config.AwardIndex)) return 2;
         if (IsHeroStarCntOk(heroConfig.HeroID, config.NeedStar)) return 1;
         return 0;
@@ -747,7 +765,43 @@
         return config.ActHeroIDList[callHeroIndex];
     }
 
+    public int GetLuckValueAward(int type)
+    {
+        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
+        if (typeInfo == null) return 0;
 
+        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
+        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
+        luckList.Sort();
+        for (int i = 0; i < luckList.Count; i++)
+        {
+            var luckyValue = typeInfo.luckValue;
+            if (luckyValue < luckList[i])
+            {
+                return luckList[i];
+            }
+        }
+        return 0;
+    }
+
+    public int GetNextXBCountForBigAward(int type)
+    {
+        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
+        if (typeInfo == null) return 0;
+
+        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
+        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
+        luckList.Sort();
+        for (int i = 0; i < luckList.Count; i++)
+        {
+            var luckyValue = typeInfo.luckValue;
+            if (luckyValue < luckList[i])
+            {
+                return luckList[i] - luckyValue;
+            }
+        }
+        return 0;
+    }
     #endregion
 
     #region 鏃惰鐗瑰崠
@@ -924,6 +978,354 @@
 
     #endregion
 
+    #region 鎴樹护
+    /// <summary>
+    /// 姝﹀皢鐧诲満鎴樹护绫诲瀷锛堜粠閰嶇疆瀹炴椂鑾峰彇锛�
+    /// </summary>
+    public int ZhanLingType => GetCurrentZhanLingType();
+
+    /// <summary>
+    /// 鑾峰彇褰撳墠鎴樹护绫诲瀷
+    /// </summary>
+    private int GetCurrentZhanLingType()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null)
+            return 0;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        return config?.ActZhanlingType ?? 0;
+    }
+
+    /// <summary>
+    /// 姝﹀皢鐧诲満鎴樹护鍔熻兘ID
+    /// </summary>
+    public const int ZhanLingFuncId = 63;
+
+    /// <summary>
+    /// 鎴樹护鏁版嵁鏇存柊浜嬩欢
+    /// </summary>
+    public event Action OnZhanLingUpdateEvent;
+
+    private void OnBattlePassDataUpdate(int type)
+    {
+        if (type == ZhanLingType)
+        {
+            OnZhanLingUpdateEvent?.Invoke();
+        }
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鐨勫綋鍓嶈繘搴﹀��
+    /// </summary>
+    public int GetZhanLingValue()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        return data != null ? (int)data.value1 : 0;
+    }
+
+    /// <summary>
+    /// 鍒ゆ柇鎸囧畾绫诲瀷鏄惁涓篫hanLing绫诲瀷锛堢紦瀛樻煡璇級
+    /// </summary>
+    public static bool IsZhanLingType(int type)
+    {
+        if (zhanLingTypeList == null)
+        {
+            zhanLingTypeList = ActHeroAppearConfig.GetValues()
+                .Select(x => x.ActZhanlingType)
+                .Where(x => x > 0)
+                .Distinct()
+                .ToList();
+        }
+        return zhanLingTypeList.Contains(type);
+    }
+
+    /// <summary>
+    /// 鑾峰彇鎸囧畾ZhanLing绫诲瀷鐨勮繘搴﹀��
+    /// </summary>
+    public static int GetZhanLingValueByType(int zhanLingType)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(zhanLingType);
+        return data != null ? (int)data.value1 : 0;
+    }
+
+    /// <summary>
+    /// 鍒ゆ柇姝﹀皢鐧诲満鎴樹护鐨勬寚瀹氱瓑绾ф槸鍚﹁揪鎴�
+    /// </summary>
+    public bool IsZhanLingNeedValueOk(int needValue)
+    {
+        return GetZhanLingValue() >= needValue;
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鐨勮喘涔扮姸鎬�
+    /// 0 娌¤喘涔拌繘闃跺拰鐜勭骇 1 璐拱浜嗚繘闃舵病涔扮巹绾� 2 璐拱浜嗙巹绾ф病涔拌繘闃� 3 璐拱浜嗚繘闃跺拰鐜勭骇
+    /// </summary>
+    public int GetZhanLingBuyState()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+
+        bool isBuyPaid = data.isActivite > 0;
+        bool isBuyPaidH = data.isActiviteH > 0;
+        if (isBuyPaid && isBuyPaidH)
+            return 3;
+        if (isBuyPaid)
+            return 1;
+        if (isBuyPaidH)
+            return 2;
+        return 0;
+    }
+
+    /// <summary>
+    /// 鏄惁鏈夊彲棰嗗彇鐨勬垬浠ゅ鍔�
+    /// </summary>
+    public bool HasZhanLingCanHave()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return false;
+
+        var dict = ZhanlingConfig.GetTypeToIDDict(ZhanLingType);
+        if (dict.IsNullOrEmpty())
+            return false;
+
+        int buyState = GetZhanLingBuyState();
+        bool isBuyPaid = buyState == 1 || buyState == 3;
+        bool isBuyPaidH = buyState == 2 || buyState == 3;
+
+        foreach (var kvp in dict)
+        {
+            int needValue = kvp.Key;
+            // 妫�鏌ュ厤璐瑰鍔�
+            int freeState = GetZhanLingFreeGiftState(needValue);
+            if (freeState == 1)
+                return true;
+
+            // 妫�鏌ユ櫘閫氬鍔憋紙闇�瑕佸凡璐拱杩涢樁锛�
+            if (isBuyPaid)
+            {
+                int paidState = GetZhanLingPaidGiftState(needValue);
+                if (paidState == 1)
+                    return true;
+            }
+
+            // 妫�鏌ラ珮绾у鍔憋紙闇�瑕佸凡璐拱鐜勭骇锛�
+            if (isBuyPaidH)
+            {
+                int paidHState = GetZhanLingPaidGiftHState(needValue);
+                if (paidHState == 1)
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鍏嶈垂濂栧姳鐘舵��
+    /// 0 涓嶈兘棰� 1 鏈鍙� 2 宸查鍙�
+    /// </summary>
+    public int GetZhanLingFreeGiftState(int needValue)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 0);
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鏅�氬鍔辩姸鎬�
+    /// 0 涓嶈兘棰� 1 鏈鍙� 2 宸查鍙�
+    /// </summary>
+    public int GetZhanLingPaidGiftState(int needValue)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 1);
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护楂樼骇濂栧姳鐘舵��
+    /// 0 涓嶈兘棰� 1 鏈鍙� 2 宸查鍙�
+    /// </summary>
+    public int GetZhanLingPaidGiftHState(int needValue)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 2);
+    }
+
+    /// <summary>
+    /// 涓�閿鍙栨灏嗙櫥鍦烘垬浠ゆ墍鏈夊彲棰嗗彇濂栧姳
+    /// </summary>
+    public void HaveAllZhanLingGift()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return;
+
+        if (PackManager.Instance.GetEmptyGridCount(PackType.Item) < 1)
+        {
+            SysNotifyMgr.Instance.ShowTip("GeRen_lhs_202580");
+            return;
+        }
+
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        BattlePassManager.Instance.GetAllAward(data, ZhanLingType, totalValue);
+    }
+    #endregion
+
+    #region 鎴樹护棰勮璐拱
+    /// <summary>
+    /// 褰撳墠棰勮鐨勬垬浠ょ被鍨�
+    /// </summary>
+    public int previewZhanLingType { get; private set; }
+
+    /// <summary>
+    /// 褰撳墠棰勮鐨勭ぜ鍖呯被鍨� 1 鏅�氭垬浠ょぜ鍖� 2 楂樼骇鎴樹护绀煎寘
+    /// </summary>
+    public int previewGiftType { get; private set; }
+
+    /// <summary>
+    /// 鏄剧ず鎴樹护璐拱棰勮鐣岄潰
+    /// </summary>
+    public void ShowZhanLingHBuy(int zhanLingType, int showGiftType)
+    {
+        previewZhanLingType = zhanLingType;
+        previewGiftType = showGiftType;
+
+        if (showGiftType == 1)
+        {
+            UIManager.Instance.OpenWindow<HeroDebutZhanLingPreviewWin>();
+        }
+        else if (showGiftType == 2)
+        {
+            UIManager.Instance.OpenWindow<HeroDebutZhanLingPreviewHWin>();
+        }
+    }
+
+    /// <summary>
+    /// 鑾峰彇褰撳墠棰勮绫诲瀷鐨勫厖鍊糏D
+    /// </summary>
+    public int GetPreviewCtgID()
+    {
+        int ctgid = 0;
+        if (previewGiftType == 1)
+        {
+            ctgid = BattlePassManager.Instance.GetCTGIDByType(previewZhanLingType);
+        }
+        else if (previewGiftType == 2)
+        {
+            // 楂樼骇鎴樹护浣跨敤 Numerical3
+            var config = FuncConfigConfig.Get("Zhanling");
+            if (config != null)
+            {
+                var dict = ConfigParse.ParseIntArrayDict(config.Numerical3);
+                if (dict.TryGetValue(previewZhanLingType, out var arr) && arr.Length > 0)
+                {
+                    ctgid = arr[0];
+                }
+            }
+        }
+        return ctgid;
+    }
+
+    /// <summary>
+    /// 鑾峰彇璐拱鍚庢墍鏈夌瓑绾х殑濂栧姳
+    /// </summary>
+    /// <param name="maxCountPerSlot">姣忎釜鐩稿悓鐨刬temid姣忎釜鏍煎瓙鏈�澶у悓鏃舵樉绀虹殑鏁伴噺</param>
+    public List<Item> GetPreviewGiftAllItem(int maxCountPerSlot = 20)
+    {
+        List<int> collectList = new List<int>();
+        var dict = ZhanlingConfig.GetTypeToIDDict(previewZhanLingType);
+        if (dict.IsNullOrEmpty())
+            return new List<Item>();
+
+        var arr = dict.Keys.ToArray();
+        for (int i = 0; i < arr.Length; i++)
+        {
+            int needValue = arr[i];
+            int zhanLingId = dict[needValue];
+            collectList.Add(zhanLingId);
+        }
+        return CollectPreviewItems(collectList, maxCountPerSlot);
+    }
+
+    private List<Item> CollectPreviewItems(List<int> collectList, int maxCountPerSlot)
+    {
+        Dictionary<int, int> resultDict = new Dictionary<int, int>();
+        for (int i = 0; i < collectList.Count; i++)
+        {
+            int zhanLingId = collectList[i];
+            int[][] itemArr = GetPreviewItemArr(zhanLingId, previewGiftType);
+            if (itemArr.IsNullOrEmpty())
+                continue;
+
+            for (int j = 0; j < itemArr.Length; j++)
+            {
+                int itemID = itemArr[j][0];
+                int count = itemArr[j][1];
+                if (resultDict.ContainsKey(itemID))
+                    resultDict[itemID] += count;
+                else
+                    resultDict[itemID] = count;
+            }
+        }
+        List<Item> result = GetItemListByDict(resultDict, maxCountPerSlot);
+        result.Sort(CmpPreviewItem);
+        return result;
+    }
+
+    private int[][] GetPreviewItemArr(int zhanLingId, int showGiftType)
+    {
+        var config = ZhanlingConfig.Get(zhanLingId);
+        if (config == null)
+            return new int[][] { };
+
+        if (showGiftType == 1)
+            return config.ZLRewardItemList;
+        if (showGiftType == 2)
+            return config.ZLRewardItemListH;
+        return new int[][] { };
+    }
+
+    private List<Item> GetItemListByDict(Dictionary<int, int> dict, int maxCountPerSlot)
+    {
+        List<Item> result = new List<Item>();
+        var arr = dict.Keys.ToArray();
+        for (int i = 0; i < arr.Length; i++)
+        {
+            int itemID = arr[i];
+            int count = dict[itemID];
+
+            // 鏍规嵁maxCountPerSlot鎷嗗垎鏁伴噺锛屾瘡涓狪tem鏈�澶氭樉绀簃axCountPerSlot涓�
+            int slotCount = Mathf.CeilToInt((float)count / maxCountPerSlot);
+            for (int s = 0; s < slotCount; s++)
+            {
+                int itemCount = Mathf.Min(maxCountPerSlot, count - s * maxCountPerSlot);
+                result.Add(new Item(itemID, itemCount));
+            }
+        }
+        return result;
+    }
+
+    private int CmpPreviewItem(Item a, Item b)
+    {
+        int quality1 = ItemConfig.Get(a.id).ItemColor;
+        int quality2 = ItemConfig.Get(b.id).ItemColor;
+        if (quality1 != quality2)
+            return quality2.CompareTo(quality1);
+        return a.countEx.CompareTo(b.countEx);
+    }
+    #endregion
+
     #region 鑾峰璁板綍
     public static readonly int RecordType = 311;
 
@@ -1012,6 +1414,7 @@
     StarUp = 2,
     Shop = 3,
     Gift = 4,
+    ZhanLing = 5,
 }
 
 public class HeroDebutGameRec
diff --git a/Main/System/HeroDebut/HeroDebutWin.cs b/Main/System/HeroDebut/HeroDebutWin.cs
index 13fa454..2394f88 100644
--- a/Main/System/HeroDebut/HeroDebutWin.cs
+++ b/Main/System/HeroDebut/HeroDebutWin.cs
@@ -29,6 +29,8 @@
     [SerializeField] UIHeroController lhController;
     [SerializeField] Image callRedImage;
     [SerializeField] ButtonEx closeButton;
+    [SerializeField] ButtonEx zhanlingBtn;
+    [SerializeField] RedpointBehaviour zhanlingRedpoint;
     [SerializeField] float modleSize = 0.8f;
     HeroDebutManager manager => HeroDebutManager.Instance;
     protected override void InitComponent()
@@ -40,6 +42,7 @@
         skinButton.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroDebutSkinWin>().Forget());
         giftButton.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroDebutGiftWin>().Forget());
         callButton.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroDebutCallWin>().Forget());
+        zhanlingBtn.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroDebutZhanLingWin>().Forget());
     }
 
     protected override void OnPreOpen()
@@ -77,6 +80,7 @@
         starUpRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.StarUp);
         shopRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Shop);
         giftRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.Gift);
+        zhanlingRedpoint.redpointId = manager.GetRedPointId(HeroDebutRedPointType.ZhanLing);
     }
 
     private void Display()
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingCell.cs b/Main/System/HeroDebut/HeroDebutZhanLingCell.cs
new file mode 100644
index 0000000..233c51a
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingCell.cs
@@ -0,0 +1,121 @@
+锘縰sing System.Linq;
+using UnityEngine;
+
+public class HeroDebutZhanLingCell : CellView
+{
+    [SerializeField] ItemCell freeItemCell;
+    [SerializeField] Transform freeGotRect;
+    [SerializeField] Transform baseCanGetAwardRect;
+
+    [SerializeField] ItemCell[] paidAwards;
+    [SerializeField] Transform[] paidGotRects;
+    [SerializeField] Transform[] paidCanGetRects;
+    [SerializeField] Transform[] paidLockRects;
+    [SerializeField] ItemCell[] paidHAwards;
+    [SerializeField] Transform[] paidHGotRects;
+    [SerializeField] Transform[] paidHCanGetRects;
+    [SerializeField] Transform[] paidHLockRects;
+    [SerializeField] Transform upProcssBGRect;
+    [SerializeField] Transform upProcessRect;
+    [SerializeField] Transform downProcssBGRect;
+    [SerializeField] Transform downProcessRect;
+    [SerializeField] TextEx txtUnlockLV;
+    [SerializeField] Transform mask;
+
+    HeroDebutManager zhanLingModel => HeroDebutManager.Instance;
+
+    public void Display(int needValue)
+    {
+        var totalValue = BattlePassManager.Instance.GetTotalValue(zhanLingModel.ZhanLingType);
+        int zhanlingId = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType)[needValue];
+        int freeState = zhanLingModel.GetZhanLingFreeGiftState(needValue);
+        int paidState = zhanLingModel.GetZhanLingPaidGiftState(needValue);
+        int paidHState = zhanLingModel.GetZhanLingPaidGiftHState(needValue);
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+
+        freeGotRect.SetActive(freeState == 2);
+        baseCanGetAwardRect.SetActive(freeState == 1);
+        mask.SetActive(freeState == 0);
+
+        for (int i = 0; i < paidAwards.Length; i++)
+        {
+            bool isBuy = buyState == 1 || buyState == 3;
+            paidGotRects[i].SetActive(paidState == 2);
+            paidCanGetRects[i].SetActive(paidState == 1 && isBuy);
+            paidLockRects[i].SetActive(!isBuy || paidState == 0);
+        }
+        for (int i = 0; i < paidHAwards.Length; i++)
+        {
+            bool isBuy = buyState == 2 || buyState == 3;
+            paidHGotRects[i].SetActive(paidHState == 2);
+            paidHCanGetRects[i].SetActive(paidHState == 1 && isBuy);
+            paidHLockRects[i].SetActive(!isBuy || paidHState == 0);
+        }
+        txtUnlockLV.text = needValue.ToString();
+
+        // 杩涘害鏉℃樉绀洪�昏緫
+        var ids = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType).Values.ToList();
+        ids.Sort();
+        upProcssBGRect.SetActive(ids[0] != zhanlingId);
+        upProcessRect.SetActive(freeState != 0);
+
+        downProcssBGRect.SetActive(ids[ids.Count - 1] != zhanlingId);
+        var nextConfig = ZhanlingConfig.Get(zhanlingId + 1);
+        downProcessRect.SetActive(nextConfig != null && totalValue >= nextConfig.NeedValue);
+
+        // 灞曠ずItemCell
+        var config = ZhanlingConfig.Get(zhanlingId);
+        if (config == null)
+            return;
+
+        // 鍏嶈垂濂栧姳
+        int freeItemId = config.FreeRewardItemList[0][0];
+        freeItemCell.Init(new ItemCellModel(freeItemId, false, config.FreeRewardItemList[0][1]));
+        freeItemCell.button.onClick.RemoveAllListeners();
+        freeItemCell.button.onClick.AddListener(() =>
+        {
+            if (freeState == 1)
+                zhanLingModel.HaveAllZhanLingGift();
+            else
+                ItemTipUtility.Show(freeItemId);
+        });
+
+        // 鏅�氬鍔�
+        for (int i = 0; i < paidAwards.Length; i++)
+        {
+            if (i >= config.ZLRewardItemList.Length)
+                continue;
+            int itemId2 = config.ZLRewardItemList[i][0];
+            paidAwards[i].Init(new ItemCellModel(itemId2, false, config.ZLRewardItemList[i][1]));
+            paidAwards[i].button.onClick.RemoveAllListeners();
+            paidAwards[i].button.onClick.AddListener(() =>
+            {
+                if (buyState == 0 || buyState == 2)
+                    zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 1);
+                else if (paidState == 1)
+                    zhanLingModel.HaveAllZhanLingGift();
+                else
+                    ItemTipUtility.Show(itemId2);
+            });
+        }
+
+        // 楂樼骇濂栧姳
+        for (int i = 0; i < paidHAwards.Length; i++)
+        {
+            if (i >= config.ZLRewardItemListH.Length)
+                continue;
+            int itemId3 = config.ZLRewardItemListH[i][0];
+            paidHAwards[i].Init(new ItemCellModel(itemId3, false, config.ZLRewardItemListH[i][1]));
+            paidHAwards[i].button.onClick.RemoveAllListeners();
+            paidHAwards[i].button.onClick.AddListener(() =>
+            {
+                if (buyState == 0 || buyState == 1)
+                    zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 2);
+                else if (paidHState == 1)
+                    zhanLingModel.HaveAllZhanLingGift();
+                else
+                    ItemTipUtility.Show(itemId3);
+            });
+        }
+    }
+}
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingCell.cs.meta b/Main/System/HeroDebut/HeroDebutZhanLingCell.cs.meta
new file mode 100644
index 0000000..f854cde
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 53ed1e831bb755c4085557d561217459
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs b/Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs
new file mode 100644
index 0000000..0ab54c7
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+using System.Collections.Generic;
+
+public class HeroDebutZhanLingPreviewCell : CellView
+{
+    [SerializeField] ItemCell[] itemCells;
+    public const int itemCountPerRow = 5;
+
+    public void Display(int rowIndex, List<Item> items)
+    {
+        if (items == null)
+            return;
+
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            int index = rowIndex * itemCountPerRow + i;
+            if (index < items.Count)
+            {
+                itemCells[i].SetActive(true);
+                int itemID = items[index].id;
+                long count = items[index].countEx;
+                itemCells[i].Init(new ItemCellModel(itemID, false, count));
+                int clickItemId = itemID;
+                itemCells[i].button.AddListener(() =>
+                {
+                    ItemTipUtility.Show(clickItemId);
+                });
+            }
+            else
+            {
+                itemCells[i].SetActive(false);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs.meta b/Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs.meta
new file mode 100644
index 0000000..5e0f025
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a3cd52709b8e8fc419ae3993e855cbab
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs
new file mode 100644
index 0000000..7a669b4
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+using System.Collections.Generic;
+
+public class HeroDebutZhanLingPreviewHCell : CellView
+{
+    [SerializeField] ItemCell[] itemCells;
+    public const int itemCountPerRow = 5;
+
+    public void Display(int rowIndex, List<Item> items)
+    {
+        if (items == null)
+            return;
+
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            int index = rowIndex * itemCountPerRow + i;
+            if (index < items.Count)
+            {
+                itemCells[i].SetActive(true);
+                int itemID = items[index].id;
+                long count = items[index].countEx;
+                itemCells[i].Init(new ItemCellModel(itemID, false, count));
+                int clickItemId = itemID;
+                itemCells[i].button.AddListener(() =>
+                {
+                    ItemTipUtility.Show(clickItemId);
+                });
+            }
+            else
+            {
+                itemCells[i].SetActive(false);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs.meta b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs.meta
new file mode 100644
index 0000000..30408cf
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a426bf3edcc306240b4994629c254691
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs
new file mode 100644
index 0000000..157467d
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs
@@ -0,0 +1,91 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroDebutZhanLingPreviewHWin : UIBase
+{
+    [SerializeField] ScrollerController allScroller; //鎵�鏈夌瓑绾у鍔�
+    [SerializeField] Button btnClose;
+    [SerializeField] Button btnBuy;
+
+    [SerializeField] Text txtBuy;
+    [SerializeField] Text txtPercentage;
+    [SerializeField] Image imgMoney;
+    [SerializeField] Text txtMoney;
+
+    HeroDebutManager model => HeroDebutManager.Instance;
+    int ctgID;
+    int showCnt = 50;
+    protected override void InitComponent()
+    {
+        btnClose.AddListener(CloseWindow);
+        btnBuy.AddListener(OnBuyClick);
+    }
+
+    protected override void OnPreOpen()
+    {
+        allScroller.OnRefreshCell += OnScrollerRefreshAllCell;
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        allScroller.OnRefreshCell -= OnScrollerRefreshAllCell;
+
+    }
+
+    void OnBuyClick()
+    {
+        if (ctgID == 0)
+        {
+            CloseWindow();
+            return;
+        }
+        RechargeManager.Instance.CTG(ctgID);
+        CloseWindow();
+    }
+
+    protected override void NextFrameAfterOpen()
+    {
+        CreateAllScroller();
+    }
+
+    private void OnScrollerRefreshAllCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroDebutZhanLingPreviewHCell;
+        _cell.Display(_cell.index, model.GetPreviewGiftAllItem(showCnt));
+    }
+
+    void Display()
+    {
+        ctgID = model.GetPreviewCtgID();
+        var config = CTGConfig.Get(ctgID);
+        if (config == null)
+        {
+            CloseWindow();
+            return;
+        }
+        OrderInfoConfig orderCfg;
+        RechargeManager.Instance.TryGetOrderInfo(ctgID, out orderCfg);
+
+        txtPercentage.text = Language.Get("TimingGift02", config.Percentage);
+        txtBuy.text = Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderCfg.PayRMBNumOnSale));
+        imgMoney.SetIconWithMoneyType(config.MoneyType);
+        txtMoney.text = config.GainGold.ToString();
+    }
+
+    private void CreateAllScroller()
+    {
+        var items = model.GetPreviewGiftAllItem(showCnt);
+        if (items == null || items.Count == 0)
+            return;
+        int rowCount = (int)Math.Ceiling((double)items.Count / HeroDebutZhanLingPreviewCell.itemCountPerRow);
+        allScroller.Refresh();
+        for (int i = 0; i < rowCount; i++)
+        {
+            allScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        allScroller.Restart();
+    }
+
+}
\ No newline at end of file
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs.meta b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs.meta
new file mode 100644
index 0000000..1b101ef
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewHWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 954d7f3edfe26ed4c91e79c003c82484
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs b/Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs
new file mode 100644
index 0000000..8863f57
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs
@@ -0,0 +1,87 @@
+锘縰sing System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroDebutZhanLingPreviewWin : UIBase
+{
+    [SerializeField] ScrollerController allScroller; //鎵�鏈夌瓑绾у鍔�
+    [SerializeField] Button btnClose;
+    [SerializeField] Button btnBuy;
+    [SerializeField] Text txtBuy;
+    [SerializeField] Text txtPercentage;
+    [SerializeField] Image imgMoney;
+    [SerializeField] Text txtMoney;
+    HeroDebutManager model => HeroDebutManager.Instance;
+    int ctgID;
+    int showCnt = 10;
+
+    protected override void OnPreOpen()
+    {
+        allScroller.OnRefreshCell += OnScrollerRefreshAllCell;
+        btnClose.AddListener(CloseWindow);
+        btnBuy.AddListener(OnBuyClick);
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        allScroller.OnRefreshCell -= OnScrollerRefreshAllCell;
+
+    }
+
+    void OnBuyClick()
+    {
+        if (ctgID == 0)
+        {
+            CloseWindow();
+            return;
+        }
+        RechargeManager.Instance.CTG(ctgID);
+        CloseWindow();
+    }
+
+    protected override void NextFrameAfterOpen()
+    {
+        CreateAllScroller();
+    }
+
+    private void OnScrollerRefreshAllCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroDebutZhanLingPreviewCell;
+        _cell.Display(_cell.index, model.GetPreviewGiftAllItem(showCnt));
+    }
+
+    void Display()
+    {
+        ctgID = model.GetPreviewCtgID();
+        var config = CTGConfig.Get(ctgID);
+        if (config == null)
+        {
+            CloseWindow();
+            return;
+        }
+        OrderInfoConfig orderCfg;
+        RechargeManager.Instance.TryGetOrderInfo(ctgID, out orderCfg);
+
+        txtPercentage.text = Language.Get("TimingGift02", config.Percentage);
+        txtBuy.text = Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderCfg.PayRMBNumOnSale));
+        imgMoney.SetIconWithMoneyType(config.MoneyType);
+        txtMoney.text = config.GainGold.ToString();
+    }
+
+    private void CreateAllScroller()
+    {
+        var items = model.GetPreviewGiftAllItem(showCnt);
+        if (items == null || items.Count == 0)
+            return;
+        int rowCount = (int)Math.Ceiling((double)items.Count / HeroDebutZhanLingPreviewCell.itemCountPerRow);
+        allScroller.Refresh();
+        for (int i = 0; i < rowCount; i++)
+        {
+            allScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        allScroller.Restart();
+    }
+
+
+}
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs.meta b/Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs.meta
new file mode 100644
index 0000000..057192a
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingPreviewWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bef022f6fa7c2584bb050ca842bbe368
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingWin.cs b/Main/System/HeroDebut/HeroDebutZhanLingWin.cs
new file mode 100644
index 0000000..b140cfb
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingWin.cs
@@ -0,0 +1,151 @@
+锘縰sing System.Linq;
+using UnityEngine;
+using UnityEngine.UI;
+
+// 姝﹀皢鐧诲満鎴樹护
+public class HeroDebutZhanLingWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx btnGo;
+    [SerializeField] ButtonEx btnPaid;
+    [SerializeField] ButtonEx btnPaidH;
+
+    [SerializeField] ImageEx imgPaidLock;
+    [SerializeField] ImageEx imgPaidLockH;
+
+    [SerializeField] Text txtNowNeedValue;
+
+    [SerializeField] Text welfarePerText;
+    [SerializeField] Text itemNameText;
+    [SerializeField] Image adImg;
+    [SerializeField] Image adWordImg;
+    [SerializeField] Image adHeroImg;
+
+    [SerializeField] Text txtPaidLock;
+    [SerializeField] Text txtPaidLockH;
+    [SerializeField] Text txtPaidLockBuyed;
+    [SerializeField] Text txtPaidLockBuyedH;
+
+    HeroDebutManager zhanLingModel => HeroDebutManager.Instance;
+    protected override void InitComponent()
+    {
+        btnGo.AddListener(OnGoClick);
+        btnPaid.AddListener(OnPaidClick);
+        btnPaidH.AddListener(OnPaidHClick);
+    }
+
+
+    protected override void OnPreOpen()
+    {
+        zhanLingModel.OnZhanLingUpdateEvent += OnZhanLingUpdateEvent;
+        scroller.OnRefreshCell += OnScrollerRefreshCell;
+        ShowStaticUI();
+        Initialize();
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        zhanLingModel.OnZhanLingUpdateEvent -= OnZhanLingUpdateEvent;
+        scroller.OnRefreshCell -= OnScrollerRefreshCell;
+    }
+
+    private void Display()
+    {
+        //0 娌¤喘涔拌繘闃跺拰鐜勭骇 1 璐拱浜嗚繘闃舵病涔扮巹绾� 2 璐拱浜嗙巹绾ф病涔拌繘闃� 3 璐拱浜嗚繘闃跺拰鐜勭骇
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+        scroller.m_Scorller.RefreshActiveCellViews();
+        txtNowNeedValue.text = Language.Get("HeroDebutZhanLing06", zhanLingModel.GetZhanLingValue());
+
+        // imgPaidLock: 鏈喘涔拌繘闃�(type 1)涓旀湭璐拱鐜勭骇(type 2)鏃舵樉绀洪攣锛屾垨宸茶喘涔扮巹绾т絾鏈喘涔拌繘闃舵椂鏄剧ず閿�
+        imgPaidLock.SetActive(buyState == 0 || buyState == 2);
+        // imgPaidLockH: 鏈喘涔扮巹绾т笖鏈喘涔拌繘闃舵椂鏄剧ず閿侊紝鎴栧凡璐拱杩涢樁浣嗘湭璐拱鐜勭骇鏃舵樉绀洪攣
+        imgPaidLockH.SetActive(buyState == 0 || buyState == 1);
+
+        txtPaidLock.SetActive(buyState == 0 || buyState == 2);
+        txtPaidLockBuyed.SetActive(buyState == 1 || buyState == 3);
+
+        txtPaidLockH.SetActive(buyState == 0 || buyState == 1);
+        txtPaidLockBuyedH.SetActive(buyState == 2 || buyState == 3);
+    }
+
+    private void OnZhanLingUpdateEvent()
+    {
+        Display();
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    private void OnScrollerRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroDebutZhanLingCell;
+        _cell.Display(_cell.index);
+    }
+
+    private void Initialize()
+    {
+        var cellList = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType).Keys.ToList();
+        scroller.Refresh();
+        for (int i = 0; i < cellList.Count; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, cellList[i]);
+        }
+        scroller.Restart();
+
+        var data = BattlePassManager.Instance.GetBattlePassData(zhanLingModel.ZhanLingType);
+        var totalValue = BattlePassManager.Instance.GetTotalValue(zhanLingModel.ZhanLingType);
+        scroller.JumpIndex(BattlePassManager.Instance.JumpIndex(data, zhanLingModel.ZhanLingType, totalValue));
+    }
+
+
+
+    void ShowStaticUI()
+    {
+        // 鑾峰彇楂樼骇浠樿垂锛圥aidH/鐜勭骇锛夌殑CTGID鍜岀櫨鍒嗘瘮
+        var funcConfig = FuncConfigConfig.Get("Zhanling");
+        var dict = ConfigParse.ParseIntArrayDict(funcConfig.Numerical3);
+        if (dict.TryGetValue(zhanLingModel.ZhanLingType, out var arr) && arr.Length > 0)
+        {
+            var paidHConfig = CTGConfig.Get(arr[0]);
+            welfarePerText.text = paidHConfig.Percentage + "%";
+        }
+
+        adWordImg.SetSprite("BattlePassInWord" + zhanLingModel.ZhanLingType);
+        adImg.SetSprite("BattlePassInWord" + zhanLingModel.ZhanLingType);
+
+        var act = zhanLingModel.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+        var needCount = zhanLingModel.GetLuckValueAward(config.ActTreasureType) - zhanLingModel.subVulue;
+        itemNameText.text = Language.Get("HeroDebutZhanLing01", needCount);
+
+        int heroID = zhanLingModel.GetCurrentDisplayCallHeroId();
+        adImg.SetSprite($"HeroDebutZhanLingBG_{heroID}");
+        adWordImg.SetSprite($"HeroDebutZhanLingWord_{heroID}");
+        adHeroImg.SetSprite($"HeroDebutZhanLingHero_{heroID}");
+    }
+
+    void OnGoClick()
+    {
+        UIJumpManager.Instance.OpenWindow(14);
+    }
+
+    void OnPaidClick()
+    {
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+        // 宸茶喘涔拌繘闃�(type 1)鎴栧凡璐拱鐜勭骇鍜岃繘闃�(buyState == 3)鏃朵笉鍐嶈烦杞�
+        if (buyState == 1 || buyState == 3)
+            return;
+        zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 1);
+    }
+
+    void OnPaidHClick()
+    {
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+        // 宸茶喘涔扮巹绾�(type 2)鎴栧凡璐拱鐜勭骇鍜岃繘闃�(buyState == 3)鏃朵笉鍐嶈烦杞�
+        if (buyState == 2 || buyState == 3)
+            return;
+        zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 2);
+    }
+}
diff --git a/Main/System/HeroDebut/HeroDebutZhanLingWin.cs.meta b/Main/System/HeroDebut/HeroDebutZhanLingWin.cs.meta
new file mode 100644
index 0000000..ff4bf78
--- /dev/null
+++ b/Main/System/HeroDebut/HeroDebutZhanLingWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8dd1ef3c24623734dbad0ca6cff2bd48
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroReturn/HeroReturnCallWin.cs b/Main/System/HeroReturn/HeroReturnCallWin.cs
index 84a866e..de1a3e8 100644
--- a/Main/System/HeroReturn/HeroReturnCallWin.cs
+++ b/Main/System/HeroReturn/HeroReturnCallWin.cs
@@ -55,6 +55,7 @@
     [SerializeField] UIHeroController lhController;
     [SerializeField] UIHeroController uiHeroController;
     [SerializeField] HeroReturnCallBubbleCell[] bubbleCell;
+    [SerializeField] RichText richText;
 
     [SerializeField] float modleSize = 1f;
     HeroReturnManager manager => HeroReturnManager.Instance;
@@ -276,8 +277,10 @@
         xbButton10.Display(config.ActTreasureType, 1);
         resMoneyCallCntText.text = Language.Get("HeroDebut24", Mathf.Max(treasureSetConfig.DailyMaxCountMoney - xbTypeInfo.treasureCountTodayGold, 0));
 
-        var needCount = GetNextXBCountForBigAward(treasureType);
-        nextBigAwardCntText.text = Language.Get("HeroDebut08", needCount.ToString());
+        int buyState = manager.GetZhanLingBuyState();
+        bool isBuyPaidH = buyState == 2 || buyState == 3;
+        var needCount = manager.GetNextXBCountForBigAward(treasureType) - (isBuyPaidH ? manager.subVulue : 0);
+        nextBigAwardCntText.text = Language.Get("HeroDebut08", needCount <= 0 ? 1 : needCount);
 
         heroQualityText.text = Language.Get($"heroCallQaulity{heroConfig.Quality}");
         manager.SetheroQaulityColor(heroQualityText, heroConfig.Quality);
@@ -304,28 +307,13 @@
             }
         }
 
+        // 璐拱浜嗛珮绾ф垬浠わ紙鐜勭骇锛夋椂闅愯棌richText
+        richText.SetActive(!isBuyPaidH);
+
         ShowTop3();
         OnSecondEvent();
     }
 
-    public int GetNextXBCountForBigAward(int type)
-    {
-        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
-        if (typeInfo == null) return 0;
-
-        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
-        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
-        luckList.Sort();
-        for (int i = 0; i < luckList.Count; i++)
-        {
-            var luckyValue = typeInfo.luckValue;
-            if (luckyValue < luckList[i])
-            {
-                return luckList[i] - luckyValue;
-            }
-        }
-        return 0;
-    }
     void ShowTop3()
     {
         for (int i = 0; i < top3NameText.Length; i++)
@@ -353,6 +341,7 @@
         scroller.Refresh();
 
         int listCount = list?.Count ?? 0;
+        historyButton.SetActive(listCount > 0);
         if (list != null)
         {
             for (int i = 0; i < listCount; i++)
diff --git a/Main/System/HeroReturn/HeroReturnManager.cs b/Main/System/HeroReturn/HeroReturnManager.cs
index 7c53bb7..ee7b916 100644
--- a/Main/System/HeroReturn/HeroReturnManager.cs
+++ b/Main/System/HeroReturn/HeroReturnManager.cs
@@ -7,9 +7,12 @@
 
 public class HeroReturnManager : GameSystemManager<HeroReturnManager>, IOpenServerActivity
 {
+    // 缂撳瓨鐨刏hanLingType鍒楄〃锛堜粠ActHeroAppearConfig鑾峰彇锛屽悗缁笉鍙橈級
+    private static List<int> zhanLingTypeList = null;
     public int[] xbGridArr;
     public Dictionary<int, int[][]> heroQaulityColor;
     public int[][] seeArr;
+    public int subVulue;
     public override void Init()
     {
         DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
@@ -23,15 +26,19 @@
         GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent += OnUpdateActSignInfosEvent;
         HeroManager.Instance.onHeroChangeEvent += OnHeroChangeEvent;
         TimeMgr.Instance.OnDayEvent += OnDayEvent;
+        BattlePassManager.Instance.BattlePassDataUpdateEvent += OnBattlePassDataUpdate;
 
         var config = FuncConfigConfig.Get("HeroAppear");
         xbGridArr = JsonMapper.ToObject<int[]>(config.Numerical1);
+        subVulue = int.Parse(config.Numerical4);
 
         config = FuncConfigConfig.Get("HeroReturn");
         heroQaulityColor = ConfigParse.ParseIntArray2Dict(config.Numerical1);
         seeArr = JsonMapper.ToObject<int[][]>(config.Numerical2);
-
+        
         InitRedPointId();
+
+
     }
 
     public void SetheroQaulityColor(GradientText text, int qaulity)
@@ -54,6 +61,7 @@
         GeneralActInfoManager.Instance.OnUpdateActSignInfosEvent -= OnUpdateActSignInfosEvent;
         HeroManager.Instance.onHeroChangeEvent -= OnHeroChangeEvent;
         TimeMgr.Instance.OnDayEvent -= OnDayEvent;
+        BattlePassManager.Instance.BattlePassDataUpdateEvent -= OnBattlePassDataUpdate;
     }
 
     private void OnDayEvent()
@@ -118,7 +126,6 @@
                 UIManager.Instance.CloseWindow<HeroReturnPopWin>();
             if (UIManager.Instance.IsOpened<HeroReturnWin>())
                 UIManager.Instance.CloseWindow<HeroReturnWin>();
-            gameRecDict.Clear();
             UpdateRedpoint();
         }
     }
@@ -127,6 +134,8 @@
     {
         if (type == operaType && state == 0)
         {
+            gameRecDict.Clear();
+            isSendFirst = true;
             onStateUpdate?.Invoke(activityID);
             TryPopWin();
             UpdateRedpoint();
@@ -305,12 +314,14 @@
     public Redpoint starUpRedpoint;
     public Redpoint shopRedpoint;
     public Redpoint giftRedpoint;
+    public Redpoint zhanLingRedpoint;
     public void InitRedPointId()
     {
         checkInRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.CheckIn));
         starUpRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.StarUp));
         shopRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.Shop));
         giftRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.Gift));
+        zhanLingRedpoint ??= new Redpoint(MainRedDot.HeroReturnRepoint, GetRedPointId(HeroReturnRedPointType.ZhanLing));
     }
 
     public void UpdateRedpoint()
@@ -320,6 +331,7 @@
         starUpRedpoint.state = RedPointState.None;
         shopRedpoint.state = RedPointState.None;
         giftRedpoint.state = RedPointState.None;
+        zhanLingRedpoint.state = RedPointState.None;
 
         if (!IsHeroReturnOpen()) return;
 
@@ -342,6 +354,10 @@
         if (HasGiftCanHave())//鐨囨潈绀煎寘
         {
             giftRedpoint.state = RedPointState.Simple;
+        }
+        if (HasZhanLingCanHave())//鎴樹护
+        {
+            zhanLingRedpoint.state = RedPointState.Simple;
         }
     }
     #endregion
@@ -827,7 +843,6 @@
         LocalSave.SetBool(GetCallSkipKey(cfgID, startDate, endDate), value);
     }
 
-
     /// <summary>
     /// 褰撳墠鎷涘嫙閫変腑鐨勬灏咺D
     /// </summary>
@@ -840,6 +855,43 @@
         if (config == null || config.ActHeroIDList?.Length <= callHeroIndex) return 0;
 
         return config.ActHeroIDList[callHeroIndex];
+    }
+    public int GetLuckValueAward(int type)
+    {
+        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
+        if (typeInfo == null) return 0;
+
+        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
+        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
+        luckList.Sort();
+        for (int i = 0; i < luckList.Count; i++)
+        {
+            var luckyValue = typeInfo.luckValue;
+            if (luckyValue < luckList[i])
+            {
+                return luckList[i];
+            }
+        }
+        return 0;
+    }
+
+    public int GetNextXBCountForBigAward(int type)
+    {
+        XBTypeInfo typeInfo = HappyXBModel.Instance.GetXBInfoByType(type);
+        if (typeInfo == null) return 0;
+
+        var xbConfig = HappyXBModel.Instance.GetXBItemConfigByType(type);
+        var luckList = xbConfig.LuckyItemRateInfo.Keys.ToList();
+        luckList.Sort();
+        for (int i = 0; i < luckList.Count; i++)
+        {
+            var luckyValue = typeInfo.luckValue;
+            if (luckyValue < luckList[i])
+            {
+                return luckList[i] - luckyValue;
+            }
+        }
+        return 0;
     }
 
     public int GetFirstHeroId()
@@ -1044,7 +1096,353 @@
     }
 
     #endregion
+    #region 鎴樹护
+    /// <summary>
+    /// 姝﹀皢鐧诲満鎴樹护绫诲瀷锛堜粠閰嶇疆瀹炴椂鑾峰彇锛�
+    /// </summary>
+    public int ZhanLingType => GetCurrentZhanLingType();
 
+    /// <summary>
+    /// 鑾峰彇褰撳墠鎴樹护绫诲瀷
+    /// </summary>
+    private int GetCurrentZhanLingType()
+    {
+        var act = GetOperationHeroAppearInfo();
+        if (act == null)
+            return 0;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        return config?.ActZhanlingType ?? 0;
+    }
+
+    /// <summary>
+    /// 姝﹀皢鐧诲満鎴樹护鍔熻兘ID
+    /// </summary>
+    public const int ZhanLingFuncId = 63;
+
+    /// <summary>
+    /// 鎴樹护鏁版嵁鏇存柊浜嬩欢
+    /// </summary>
+    public event Action OnZhanLingUpdateEvent;
+
+    private void OnBattlePassDataUpdate(int type)
+    {
+        if (type == ZhanLingType)
+        {
+            OnZhanLingUpdateEvent?.Invoke();
+        }
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鐨勫綋鍓嶈繘搴﹀��
+    /// </summary>
+    public int GetZhanLingValue()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        return data != null ? (int)data.value1 : 0;
+    }
+
+    /// <summary>
+    /// 鍒ゆ柇鎸囧畾绫诲瀷鏄惁涓篫hanLing绫诲瀷锛堢紦瀛樻煡璇級
+    /// </summary>
+    public static bool IsZhanLingType(int type)
+    {
+        if (zhanLingTypeList == null)
+        {
+            zhanLingTypeList = ActHeroAppearConfig.GetValues()
+                .Select(x => x.ActZhanlingType)
+                .Where(x => x > 0)
+                .Distinct()
+                .ToList();
+        }
+        return zhanLingTypeList.Contains(type);
+    }
+
+    /// <summary>
+    /// 鑾峰彇鎸囧畾ZhanLing绫诲瀷鐨勮繘搴﹀��
+    /// </summary>
+    public static int GetZhanLingValueByType(int zhanLingType)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(zhanLingType);
+        return data != null ? (int)data.value1 : 0;
+    }
+
+    /// <summary>
+    /// 鍒ゆ柇姝﹀皢鐧诲満鎴樹护鐨勬寚瀹氱瓑绾ф槸鍚﹁揪鎴�
+    /// </summary>
+    public bool IsZhanLingNeedValueOk(int needValue)
+    {
+        return GetZhanLingValue() >= needValue;
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鐨勮喘涔扮姸鎬�
+    /// 0 娌¤喘涔拌繘闃跺拰鐜勭骇 1 璐拱浜嗚繘闃舵病涔扮巹绾� 2 璐拱浜嗙巹绾ф病涔拌繘闃� 3 璐拱浜嗚繘闃跺拰鐜勭骇
+    /// </summary>
+    public int GetZhanLingBuyState()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+
+        bool isBuyPaid = data.isActivite > 0;
+        bool isBuyPaidH = data.isActiviteH > 0;
+        if (isBuyPaid && isBuyPaidH)
+            return 3;
+        if (isBuyPaid)
+            return 1;
+        if (isBuyPaidH)
+            return 2;
+        return 0;
+    }
+
+    /// <summary>
+    /// 鏄惁鏈夊彲棰嗗彇鐨勬垬浠ゅ鍔�
+    /// </summary>
+    public bool HasZhanLingCanHave()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return false;
+
+        var dict = ZhanlingConfig.GetTypeToIDDict(ZhanLingType);
+        if (dict.IsNullOrEmpty())
+            return false;
+
+        int buyState = GetZhanLingBuyState();
+        bool isBuyPaid = buyState == 1 || buyState == 3;
+        bool isBuyPaidH = buyState == 2 || buyState == 3;
+
+        foreach (var kvp in dict)
+        {
+            int needValue = kvp.Key;
+            // 妫�鏌ュ厤璐瑰鍔�
+            int freeState = GetZhanLingFreeGiftState(needValue);
+            if (freeState == 1)
+                return true;
+
+            // 妫�鏌ユ櫘閫氬鍔憋紙闇�瑕佸凡璐拱杩涢樁锛�
+            if (isBuyPaid)
+            {
+                int paidState = GetZhanLingPaidGiftState(needValue);
+                if (paidState == 1)
+                    return true;
+            }
+
+            // 妫�鏌ラ珮绾у鍔憋紙闇�瑕佸凡璐拱鐜勭骇锛�
+            if (isBuyPaidH)
+            {
+                int paidHState = GetZhanLingPaidGiftHState(needValue);
+                if (paidHState == 1)
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鍏嶈垂濂栧姳鐘舵��
+    /// 0 涓嶈兘棰� 1 鏈鍙� 2 宸查鍙�
+    /// </summary>
+    public int GetZhanLingFreeGiftState(int needValue)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 0);
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护鏅�氬鍔辩姸鎬�
+    /// 0 涓嶈兘棰� 1 鏈鍙� 2 宸查鍙�
+    /// </summary>
+    public int GetZhanLingPaidGiftState(int needValue)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 1);
+    }
+
+    /// <summary>
+    /// 鑾峰彇姝﹀皢鐧诲満鎴樹护楂樼骇濂栧姳鐘舵��
+    /// 0 涓嶈兘棰� 1 鏈鍙� 2 宸查鍙�
+    /// </summary>
+    public int GetZhanLingPaidGiftHState(int needValue)
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return 0;
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        return BattlePassManager.Instance.GetBPCellAwardState(data, totalValue, needValue, 2);
+    }
+
+    /// <summary>
+    /// 涓�閿鍙栨灏嗙櫥鍦烘垬浠ゆ墍鏈夊彲棰嗗彇濂栧姳
+    /// </summary>
+    public void HaveAllZhanLingGift()
+    {
+        var data = BattlePassManager.Instance.GetBattlePassData(ZhanLingType);
+        if (data == null)
+            return;
+
+        if (PackManager.Instance.GetEmptyGridCount(PackType.Item) < 1)
+        {
+            SysNotifyMgr.Instance.ShowTip("GeRen_lhs_202580");
+            return;
+        }
+
+        var totalValue = BattlePassManager.Instance.GetTotalValue(ZhanLingType);
+        BattlePassManager.Instance.GetAllAward(data, ZhanLingType, totalValue);
+    }
+    #endregion
+
+    #region 鎴樹护棰勮璐拱
+    /// <summary>
+    /// 褰撳墠棰勮鐨勬垬浠ょ被鍨�
+    /// </summary>
+    public int previewZhanLingType { get; private set; }
+
+    /// <summary>
+    /// 褰撳墠棰勮鐨勭ぜ鍖呯被鍨� 1 鏅�氭垬浠ょぜ鍖� 2 楂樼骇鎴樹护绀煎寘
+    /// </summary>
+    public int previewGiftType { get; private set; }
+
+    /// <summary>
+    /// 鏄剧ず鎴樹护璐拱棰勮鐣岄潰
+    /// </summary>
+    public void ShowZhanLingHBuy(int zhanLingType, int showGiftType)
+    {
+        previewZhanLingType = zhanLingType;
+        previewGiftType = showGiftType;
+
+        if (showGiftType == 1)
+        {
+            UIManager.Instance.OpenWindow<HeroReturnZhanLingPreviewWin>();
+        }
+        else if (showGiftType == 2)
+        {
+            UIManager.Instance.OpenWindow<HeroReturnZhanLingPreviewHWin>();
+        }
+    }
+
+    /// <summary>
+    /// 鑾峰彇褰撳墠棰勮绫诲瀷鐨勫厖鍊糏D
+    /// </summary>
+    public int GetPreviewCtgID()
+    {
+        int ctgid = 0;
+        if (previewGiftType == 1)
+        {
+            ctgid = BattlePassManager.Instance.GetCTGIDByType(previewZhanLingType);
+        }
+        else if (previewGiftType == 2)
+        {
+            // 楂樼骇鎴樹护浣跨敤 Numerical3
+            var config = FuncConfigConfig.Get("Zhanling");
+            if (config != null)
+            {
+                var dict = ConfigParse.ParseIntArrayDict(config.Numerical3);
+                if (dict.TryGetValue(previewZhanLingType, out var arr) && arr.Length > 0)
+                {
+                    ctgid = arr[0];
+                }
+            }
+        }
+        return ctgid;
+    }
+
+    /// <summary>
+    /// 鑾峰彇璐拱鍚庢墍鏈夌瓑绾х殑濂栧姳
+    /// </summary>
+    /// <param name="maxCountPerSlot">姣忎釜鐩稿悓鐨刬temid姣忎釜鏍煎瓙鏈�澶у悓鏃舵樉绀虹殑鏁伴噺</param>
+    public List<Item> GetPreviewGiftAllItem(int maxCountPerSlot = 20)
+    {
+        List<int> collectList = new List<int>();
+        var dict = ZhanlingConfig.GetTypeToIDDict(previewZhanLingType);
+        if (dict.IsNullOrEmpty())
+            return new List<Item>();
+
+        var arr = dict.Keys.ToArray();
+        for (int i = 0; i < arr.Length; i++)
+        {
+            int needValue = arr[i];
+            int zhanLingId = dict[needValue];
+            collectList.Add(zhanLingId);
+        }
+        return CollectPreviewItems(collectList, maxCountPerSlot);
+    }
+
+    private List<Item> CollectPreviewItems(List<int> collectList, int maxCountPerSlot)
+    {
+        Dictionary<int, int> resultDict = new Dictionary<int, int>();
+        for (int i = 0; i < collectList.Count; i++)
+        {
+            int zhanLingId = collectList[i];
+            int[][] itemArr = GetPreviewItemArr(zhanLingId, previewGiftType);
+            if (itemArr.IsNullOrEmpty())
+                continue;
+
+            for (int j = 0; j < itemArr.Length; j++)
+            {
+                int itemID = itemArr[j][0];
+                int count = itemArr[j][1];
+                if (resultDict.ContainsKey(itemID))
+                    resultDict[itemID] += count;
+                else
+                    resultDict[itemID] = count;
+            }
+        }
+        List<Item> result = GetItemListByDict(resultDict, maxCountPerSlot);
+        result.Sort(CmpPreviewItem);
+        return result;
+    }
+
+    private int[][] GetPreviewItemArr(int zhanLingId, int showGiftType)
+    {
+        var config = ZhanlingConfig.Get(zhanLingId);
+        if (config == null)
+            return new int[][] { };
+
+        if (showGiftType == 1)
+            return config.ZLRewardItemList;
+        if (showGiftType == 2)
+            return config.ZLRewardItemListH;
+        return new int[][] { };
+    }
+
+    private List<Item> GetItemListByDict(Dictionary<int, int> dict, int maxCountPerSlot)
+    {
+        List<Item> result = new List<Item>();
+        var arr = dict.Keys.ToArray();
+        for (int i = 0; i < arr.Length; i++)
+        {
+            int itemID = arr[i];
+            int count = dict[itemID];
+
+            // 鏍规嵁maxCountPerSlot鎷嗗垎鏁伴噺锛屾瘡涓狪tem鏈�澶氭樉绀簃axCountPerSlot涓�
+            int slotCount = Mathf.CeilToInt((float)count / maxCountPerSlot);
+            for (int s = 0; s < slotCount; s++)
+            {
+                int itemCount = Mathf.Min(maxCountPerSlot, count - s * maxCountPerSlot);
+                result.Add(new Item(itemID, itemCount));
+            }
+        }
+        return result;
+    }
+
+    private int CmpPreviewItem(Item a, Item b)
+    {
+        int quality1 = ItemConfig.Get(a.id).ItemColor;
+        int quality2 = ItemConfig.Get(b.id).ItemColor;
+        if (quality1 != quality2)
+            return quality2.CompareTo(quality1);
+        return a.countEx.CompareTo(b.countEx);
+    }
+    #endregion
     #region 鑾峰璁板綍
     public static readonly int RecordType = 311;
 
@@ -1134,6 +1532,7 @@
     StarUp = 2,
     Shop = 3,
     Gift = 4,
+    ZhanLing = 5,
 }
 
 public class HeroReturnGameRec
diff --git a/Main/System/HeroReturn/HeroReturnStarUpWin.cs b/Main/System/HeroReturn/HeroReturnStarUpWin.cs
index 30c92ec..c2bcee1 100644
--- a/Main/System/HeroReturn/HeroReturnStarUpWin.cs
+++ b/Main/System/HeroReturn/HeroReturnStarUpWin.cs
@@ -37,9 +37,18 @@
         });
         lockButton.SetListener(() =>
         {
-            manager.SaveStarUpLockState(manager.GetOperationHeroAppearInfo());
-            Display();
-            manager.UpdateRedpoint();
+            ConfirmCancel.ShowPopConfirm(
+                Language.Get("Mail101"),
+                Language.Get("HeroReturnLockHero"),
+                (bool isOK) =>
+                {
+                    if (isOK)
+                    {
+                        manager.SaveStarUpLockState(manager.GetOperationHeroAppearInfo());
+                        Display();
+                        manager.UpdateRedpoint();
+                    }
+                });
         });
     }
 
@@ -111,7 +120,7 @@
 
         bool isLockStarHero = manager.IsLockStarHero(act);
         changeButton.SetActive(!isLockStarHero);
-        lockButton.interactable = !isLockStarHero;
+        lockButton.SetActive(!isLockStarHero);
 
         heroHeadBaseCell.Init(heroConfig.HeroID, skinID, 0, 0, 0, () =>
         {
diff --git a/Main/System/HeroReturn/HeroReturnWin.cs b/Main/System/HeroReturn/HeroReturnWin.cs
index 9f46d84..0cad1cc 100644
--- a/Main/System/HeroReturn/HeroReturnWin.cs
+++ b/Main/System/HeroReturn/HeroReturnWin.cs
@@ -30,6 +30,8 @@
     [SerializeField] UIHeroController lhController;
     [SerializeField] Image callRedImage;
     [SerializeField] ButtonEx closeButton;
+    [SerializeField] ButtonEx zhanlingBtn;
+    [SerializeField] RedpointBehaviour zhanlingRedpoint;
     [SerializeField] float modleSize = 0.8f;
 
     // 杞挱鐩稿叧
@@ -67,6 +69,7 @@
         skinButton.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroReturnSkinWin>().Forget());
         giftButton.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroReturnGiftWin>().Forget());
         callButton.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroReturnCallWin>().Forget());
+        zhanlingBtn.SetListener(() => UIManager.Instance.OpenWindowAsync<HeroReturnZhanLingWin>().Forget());
     }
 
     protected override void OnPreOpen()
@@ -105,6 +108,7 @@
         starUpRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.StarUp);
         shopRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.Shop);
         giftRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.Gift);
+        zhanlingRedpoint.redpointId = manager.GetRedPointId(HeroReturnRedPointType.ZhanLing);
     }
 
     private void Display()
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingCell.cs b/Main/System/HeroReturn/HeroReturnZhanLingCell.cs
new file mode 100644
index 0000000..cd97fbb
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingCell.cs
@@ -0,0 +1,121 @@
+锘縰sing System.Linq;
+using UnityEngine;
+
+public class HeroReturnZhanLingCell : CellView
+{
+    [SerializeField] ItemCell freeItemCell;
+    [SerializeField] Transform freeGotRect;
+    [SerializeField] Transform baseCanGetAwardRect;
+
+    [SerializeField] ItemCell[] paidAwards;
+    [SerializeField] Transform[] paidGotRects;
+    [SerializeField] Transform[] paidCanGetRects;
+    [SerializeField] Transform[] paidLockRects;
+    [SerializeField] ItemCell[] paidHAwards;
+    [SerializeField] Transform[] paidHGotRects;
+    [SerializeField] Transform[] paidHCanGetRects;
+    [SerializeField] Transform[] paidHLockRects;
+    [SerializeField] Transform upProcssBGRect;
+    [SerializeField] Transform upProcessRect;
+    [SerializeField] Transform downProcssBGRect;
+    [SerializeField] Transform downProcessRect;
+    [SerializeField] TextEx txtUnlockLV;
+    [SerializeField] Transform mask;
+
+    HeroReturnManager zhanLingModel => HeroReturnManager.Instance;
+
+    public void Display(int needValue)
+    {
+        var totalValue = BattlePassManager.Instance.GetTotalValue(zhanLingModel.ZhanLingType);
+        int zhanlingId = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType)[needValue];
+        int freeState = zhanLingModel.GetZhanLingFreeGiftState(needValue);
+        int paidState = zhanLingModel.GetZhanLingPaidGiftState(needValue);
+        int paidHState = zhanLingModel.GetZhanLingPaidGiftHState(needValue);
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+
+        freeGotRect.SetActive(freeState == 2);
+        baseCanGetAwardRect.SetActive(freeState == 1);
+        mask.SetActive(freeState == 0);
+
+        for (int i = 0; i < paidAwards.Length; i++)
+        {
+            bool isBuy = buyState == 1 || buyState == 3;
+            paidGotRects[i].SetActive(paidState == 2);
+            paidCanGetRects[i].SetActive(paidState == 1 && isBuy);
+            paidLockRects[i].SetActive(!isBuy || paidState == 0);
+        }
+        for (int i = 0; i < paidHAwards.Length; i++)
+        {
+            bool isBuy = buyState == 2 || buyState == 3;
+            paidHGotRects[i].SetActive(paidHState == 2);
+            paidHCanGetRects[i].SetActive(paidHState == 1 && isBuy);
+            paidHLockRects[i].SetActive(!isBuy || paidHState == 0);
+        }
+        txtUnlockLV.text = needValue.ToString();
+
+        // 杩涘害鏉℃樉绀洪�昏緫
+        var ids = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType).Values.ToList();
+        ids.Sort();
+        upProcssBGRect.SetActive(ids[0] != zhanlingId);
+        upProcessRect.SetActive(freeState != 0);
+
+        downProcssBGRect.SetActive(ids[ids.Count - 1] != zhanlingId);
+        var nextConfig = ZhanlingConfig.Get(zhanlingId + 1);
+        downProcessRect.SetActive(nextConfig != null && totalValue >= nextConfig.NeedValue);
+
+        // 灞曠ずItemCell
+        var config = ZhanlingConfig.Get(zhanlingId);
+        if (config == null)
+            return;
+
+        // 鍏嶈垂濂栧姳
+        int freeItemId = config.FreeRewardItemList[0][0];
+        freeItemCell.Init(new ItemCellModel(freeItemId, false, config.FreeRewardItemList[0][1]));
+        freeItemCell.button.onClick.RemoveAllListeners();
+        freeItemCell.button.onClick.AddListener(() =>
+        {
+            if (freeState == 1)
+                zhanLingModel.HaveAllZhanLingGift();
+            else
+                ItemTipUtility.Show(freeItemId);
+        });
+
+        // 鏅�氬鍔�
+        for (int i = 0; i < paidAwards.Length; i++)
+        {
+            if (i >= config.ZLRewardItemList.Length)
+                continue;
+            int itemId2 = config.ZLRewardItemList[i][0];
+            paidAwards[i].Init(new ItemCellModel(itemId2, false, config.ZLRewardItemList[i][1]));
+            paidAwards[i].button.onClick.RemoveAllListeners();
+            paidAwards[i].button.onClick.AddListener(() =>
+            {
+                if (buyState == 0 || buyState == 2)
+                    zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 1);
+                else if (paidState == 1)
+                    zhanLingModel.HaveAllZhanLingGift();
+                else
+                    ItemTipUtility.Show(itemId2);
+            });
+        }
+
+        // 楂樼骇濂栧姳
+        for (int i = 0; i < paidHAwards.Length; i++)
+        {
+            if (i >= config.ZLRewardItemListH.Length)
+                continue;
+            int itemId3 = config.ZLRewardItemListH[i][0];
+            paidHAwards[i].Init(new ItemCellModel(itemId3, false, config.ZLRewardItemListH[i][1]));
+            paidHAwards[i].button.onClick.RemoveAllListeners();
+            paidHAwards[i].button.onClick.AddListener(() =>
+            {
+                if (buyState == 0 || buyState == 1)
+                    zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 2);
+                else if (paidHState == 1)
+                    zhanLingModel.HaveAllZhanLingGift();
+                else
+                    ItemTipUtility.Show(itemId3);
+            });
+        }
+    }
+}
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingCell.cs.meta b/Main/System/HeroReturn/HeroReturnZhanLingCell.cs.meta
new file mode 100644
index 0000000..a54a57a
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 39bf58fd6d8037e48900b76fe480d1e6
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs b/Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs
new file mode 100644
index 0000000..aaa06c7
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+using System.Collections.Generic;
+
+public class HeroReturnZhanLingPreviewCell : CellView
+{
+    [SerializeField] ItemCell[] itemCells;
+    public const int itemCountPerRow = 5;
+
+    public void Display(int rowIndex, List<Item> items)
+    {
+        if (items == null)
+            return;
+
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            int index = rowIndex * itemCountPerRow + i;
+            if (index < items.Count)
+            {
+                itemCells[i].SetActive(true);
+                int itemID = items[index].id;
+                long count = items[index].countEx;
+                itemCells[i].Init(new ItemCellModel(itemID, false, count));
+                int clickItemId = itemID;
+                itemCells[i].button.AddListener(() =>
+                {
+                    ItemTipUtility.Show(clickItemId);
+                });
+            }
+            else
+            {
+                itemCells[i].SetActive(false);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs.meta b/Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs.meta
new file mode 100644
index 0000000..81a41a4
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f2ea9ee2a4a29b742987ad12099575d4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs
new file mode 100644
index 0000000..cbcecbe
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+using System.Collections.Generic;
+
+public class HeroReturnZhanLingPreviewHCell : CellView
+{
+    [SerializeField] ItemCell[] itemCells;
+    public const int itemCountPerRow = 5;
+
+    public void Display(int rowIndex, List<Item> items)
+    {
+        if (items == null)
+            return;
+
+        for (int i = 0; i < itemCells.Length; i++)
+        {
+            int index = rowIndex * itemCountPerRow + i;
+            if (index < items.Count)
+            {
+                itemCells[i].SetActive(true);
+                int itemID = items[index].id;
+                long count = items[index].countEx;
+                itemCells[i].Init(new ItemCellModel(itemID, false, count));
+                int clickItemId = itemID;
+                itemCells[i].button.AddListener(() =>
+                {
+                    ItemTipUtility.Show(clickItemId);
+                });
+            }
+            else
+            {
+                itemCells[i].SetActive(false);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs.meta b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs.meta
new file mode 100644
index 0000000..6fb4bc5
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ba3207764a58b62479b99da756d17f30
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs
new file mode 100644
index 0000000..15359e8
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs
@@ -0,0 +1,91 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnZhanLingPreviewHWin : UIBase
+{
+    [SerializeField] ScrollerController allScroller; //鎵�鏈夌瓑绾у鍔�
+    [SerializeField] Button btnClose;
+    [SerializeField] Button btnBuy;
+
+    [SerializeField] Text txtBuy;
+    [SerializeField] Text txtPercentage;
+    [SerializeField] Image imgMoney;
+    [SerializeField] Text txtMoney;
+
+    HeroReturnManager model => HeroReturnManager.Instance;
+    int ctgID;
+    int showCnt = 50;
+    protected override void InitComponent()
+    {
+        btnClose.AddListener(CloseWindow);
+        btnBuy.AddListener(OnBuyClick);
+    }
+
+    protected override void OnPreOpen()
+    {
+        allScroller.OnRefreshCell += OnScrollerRefreshAllCell;
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        allScroller.OnRefreshCell -= OnScrollerRefreshAllCell;
+
+    }
+
+    void OnBuyClick()
+    {
+        if (ctgID == 0)
+        {
+            CloseWindow();
+            return;
+        }
+        RechargeManager.Instance.CTG(ctgID);
+        CloseWindow();
+    }
+
+    protected override void NextFrameAfterOpen()
+    {
+        CreateAllScroller();
+    }
+
+    private void OnScrollerRefreshAllCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnZhanLingPreviewHCell;
+        _cell.Display(_cell.index, model.GetPreviewGiftAllItem(showCnt));
+    }
+
+    void Display()
+    {
+        ctgID = model.GetPreviewCtgID();
+        var config = CTGConfig.Get(ctgID);
+        if (config == null)
+        {
+            CloseWindow();
+            return;
+        }
+        OrderInfoConfig orderCfg;
+        RechargeManager.Instance.TryGetOrderInfo(ctgID, out orderCfg);
+
+        txtPercentage.text = Language.Get("TimingGift02", config.Percentage);
+        txtBuy.text = Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderCfg.PayRMBNumOnSale));
+        imgMoney.SetIconWithMoneyType(config.MoneyType);
+        txtMoney.text = config.GainGold.ToString();
+    }
+
+    private void CreateAllScroller()
+    {
+        var items = model.GetPreviewGiftAllItem(showCnt);
+        if (items == null || items.Count == 0)
+            return;
+        int rowCount = (int)Math.Ceiling((double)items.Count / HeroReturnZhanLingPreviewCell.itemCountPerRow);
+        allScroller.Refresh();
+        for (int i = 0; i < rowCount; i++)
+        {
+            allScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        allScroller.Restart();
+    }
+
+}
\ No newline at end of file
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs.meta b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs.meta
new file mode 100644
index 0000000..90833e6
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewHWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 94b75faeefad0d640b0016287e56158f
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs b/Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs
new file mode 100644
index 0000000..8b1d5a8
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs
@@ -0,0 +1,87 @@
+锘縰sing System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HeroReturnZhanLingPreviewWin : UIBase
+{
+    [SerializeField] ScrollerController allScroller; //鎵�鏈夌瓑绾у鍔�
+    [SerializeField] Button btnClose;
+    [SerializeField] Button btnBuy;
+    [SerializeField] Text txtBuy;
+    [SerializeField] Text txtPercentage;
+    [SerializeField] Image imgMoney;
+    [SerializeField] Text txtMoney;
+    HeroReturnManager model => HeroReturnManager.Instance;
+    int ctgID;
+    int showCnt = 10;
+
+    protected override void OnPreOpen()
+    {
+        allScroller.OnRefreshCell += OnScrollerRefreshAllCell;
+        btnClose.AddListener(CloseWindow);
+        btnBuy.AddListener(OnBuyClick);
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        allScroller.OnRefreshCell -= OnScrollerRefreshAllCell;
+
+    }
+
+    void OnBuyClick()
+    {
+        if (ctgID == 0)
+        {
+            CloseWindow();
+            return;
+        }
+        RechargeManager.Instance.CTG(ctgID);
+        CloseWindow();
+    }
+
+    protected override void NextFrameAfterOpen()
+    {
+        CreateAllScroller();
+    }
+
+    private void OnScrollerRefreshAllCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnZhanLingPreviewCell;
+        _cell.Display(_cell.index, model.GetPreviewGiftAllItem(showCnt));
+    }
+
+    void Display()
+    {
+        ctgID = model.GetPreviewCtgID();
+        var config = CTGConfig.Get(ctgID);
+        if (config == null)
+        {
+            CloseWindow();
+            return;
+        }
+        OrderInfoConfig orderCfg;
+        RechargeManager.Instance.TryGetOrderInfo(ctgID, out orderCfg);
+
+        txtPercentage.text = Language.Get("TimingGift02", config.Percentage);
+        txtBuy.text = Language.Get("PayMoneyNum", UIHelper.GetMoneyFormat(orderCfg.PayRMBNumOnSale));
+        imgMoney.SetIconWithMoneyType(config.MoneyType);
+        txtMoney.text = config.GainGold.ToString();
+    }
+
+    private void CreateAllScroller()
+    {
+        var items = model.GetPreviewGiftAllItem(showCnt);
+        if (items == null || items.Count == 0)
+            return;
+        int rowCount = (int)Math.Ceiling((double)items.Count / HeroReturnZhanLingPreviewCell.itemCountPerRow);
+        allScroller.Refresh();
+        for (int i = 0; i < rowCount; i++)
+        {
+            allScroller.AddCell(ScrollerDataType.Header, i);
+        }
+        allScroller.Restart();
+    }
+
+
+}
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs.meta b/Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs.meta
new file mode 100644
index 0000000..da44361
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingPreviewWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b229745ad3e66044f931ac7deefcf6aa
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingWin.cs b/Main/System/HeroReturn/HeroReturnZhanLingWin.cs
new file mode 100644
index 0000000..aff6ea6
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingWin.cs
@@ -0,0 +1,151 @@
+锘縰sing System.Linq;
+using UnityEngine;
+using UnityEngine.UI;
+
+// 姝﹀皢鐧诲満鎴樹护
+public class HeroReturnZhanLingWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+    [SerializeField] ButtonEx btnGo;
+    [SerializeField] ButtonEx btnPaid;
+    [SerializeField] ButtonEx btnPaidH;
+
+    [SerializeField] ImageEx imgPaidLock;
+    [SerializeField] ImageEx imgPaidLockH;
+
+    [SerializeField] Text txtNowNeedValue;
+
+    [SerializeField] Text welfarePerText;
+    [SerializeField] Text itemNameText;
+    [SerializeField] Image adImg;
+    [SerializeField] Image adWordImg;
+    [SerializeField] Image adHeroImg;
+
+    [SerializeField] Text txtPaidLock;
+    [SerializeField] Text txtPaidLockH;
+    [SerializeField] Text txtPaidLockBuyed;
+    [SerializeField] Text txtPaidLockBuyedH;
+
+    HeroReturnManager zhanLingModel => HeroReturnManager.Instance;
+    protected override void InitComponent()
+    {
+        btnGo.AddListener(OnGoClick);
+        btnPaid.AddListener(OnPaidClick);
+        btnPaidH.AddListener(OnPaidHClick);
+    }
+
+
+    protected override void OnPreOpen()
+    {
+        zhanLingModel.OnZhanLingUpdateEvent += OnZhanLingUpdateEvent;
+        scroller.OnRefreshCell += OnScrollerRefreshCell;
+        ShowStaticUI();
+        Initialize();
+        Display();
+    }
+
+    protected override void OnPreClose()
+    {
+        zhanLingModel.OnZhanLingUpdateEvent -= OnZhanLingUpdateEvent;
+        scroller.OnRefreshCell -= OnScrollerRefreshCell;
+    }
+
+    private void Display()
+    {
+        //0 娌¤喘涔拌繘闃跺拰鐜勭骇 1 璐拱浜嗚繘闃舵病涔扮巹绾� 2 璐拱浜嗙巹绾ф病涔拌繘闃� 3 璐拱浜嗚繘闃跺拰鐜勭骇
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+        scroller.m_Scorller.RefreshActiveCellViews();
+        txtNowNeedValue.text = Language.Get("HeroReturnZhanLing06", zhanLingModel.GetZhanLingValue());
+
+        // imgPaidLock: 鏈喘涔拌繘闃�(type 1)涓旀湭璐拱鐜勭骇(type 2)鏃舵樉绀洪攣锛屾垨宸茶喘涔扮巹绾т絾鏈喘涔拌繘闃舵椂鏄剧ず閿�
+        imgPaidLock.SetActive(buyState == 0 || buyState == 2);
+        // imgPaidLockH: 鏈喘涔扮巹绾т笖鏈喘涔拌繘闃舵椂鏄剧ず閿侊紝鎴栧凡璐拱杩涢樁浣嗘湭璐拱鐜勭骇鏃舵樉绀洪攣
+        imgPaidLockH.SetActive(buyState == 0 || buyState == 1);
+
+        txtPaidLock.SetActive(buyState == 0 || buyState == 2);
+        txtPaidLockBuyed.SetActive(buyState == 1 || buyState == 3);
+
+        txtPaidLockH.SetActive(buyState == 0 || buyState == 1);
+        txtPaidLockBuyedH.SetActive(buyState == 2 || buyState == 3);
+    }
+
+    private void OnZhanLingUpdateEvent()
+    {
+        Display();
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    private void OnScrollerRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as HeroReturnZhanLingCell;
+        _cell.Display(_cell.index);
+    }
+
+    private void Initialize()
+    {
+        var cellList = ZhanlingConfig.GetTypeToIDDict(zhanLingModel.ZhanLingType).Keys.ToList();
+        scroller.Refresh();
+        for (int i = 0; i < cellList.Count; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, cellList[i]);
+        }
+        scroller.Restart();
+
+        var data = BattlePassManager.Instance.GetBattlePassData(zhanLingModel.ZhanLingType);
+        var totalValue = BattlePassManager.Instance.GetTotalValue(zhanLingModel.ZhanLingType);
+        scroller.JumpIndex(BattlePassManager.Instance.JumpIndex(data, zhanLingModel.ZhanLingType, totalValue));
+    }
+
+
+
+    void ShowStaticUI()
+    {
+        // 鑾峰彇楂樼骇浠樿垂锛圥aidH/鐜勭骇锛夌殑CTGID鍜岀櫨鍒嗘瘮
+        var funcConfig = FuncConfigConfig.Get("Zhanling");
+        var dict = ConfigParse.ParseIntArrayDict(funcConfig.Numerical3);
+        if (dict.TryGetValue(zhanLingModel.ZhanLingType, out var arr) && arr.Length > 0)
+        {
+            var paidHConfig = CTGConfig.Get(arr[0]);
+            welfarePerText.text = paidHConfig.Percentage + "%";
+        }
+
+        adWordImg.SetSprite("BattlePassInWord" + zhanLingModel.ZhanLingType);
+        adImg.SetSprite("BattlePassInWord" + zhanLingModel.ZhanLingType);
+
+        var act = zhanLingModel.GetOperationHeroAppearInfo();
+        if (act == null) return;
+
+        var config = ActHeroAppearConfig.Get(act.CfgID);
+        if (config == null) return;
+        var needCount = zhanLingModel.GetLuckValueAward(config.ActTreasureType) - zhanLingModel.subVulue;
+        itemNameText.text = Language.Get("HeroReturnZhanLing01", needCount);
+
+        int heroID = zhanLingModel.GetCurrentDisplayCallHeroId();
+        adImg.SetSprite($"HeroReturnZhanLingBG_{heroID}");
+        adWordImg.SetSprite($"HeroReturnZhanLingWord_{heroID}");
+        adHeroImg.SetSprite($"HeroReturnZhanLingHero_{heroID}");
+    }
+
+    void OnGoClick()
+    {
+        UIJumpManager.Instance.OpenWindow(20);
+    }
+
+    void OnPaidClick()
+    {
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+        // 宸茶喘涔拌繘闃�(type 1)鎴栧凡璐拱鐜勭骇鍜岃繘闃�(buyState == 3)鏃朵笉鍐嶈烦杞�
+        if (buyState == 1 || buyState == 3)
+            return;
+        zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 1);
+    }
+
+    void OnPaidHClick()
+    {
+        int buyState = zhanLingModel.GetZhanLingBuyState();
+        // 宸茶喘涔扮巹绾�(type 2)鎴栧凡璐拱鐜勭骇鍜岃繘闃�(buyState == 3)鏃朵笉鍐嶈烦杞�
+        if (buyState == 2 || buyState == 3)
+            return;
+        zhanLingModel.ShowZhanLingHBuy(zhanLingModel.ZhanLingType, 2);
+    }
+}
diff --git a/Main/System/HeroReturn/HeroReturnZhanLingWin.cs.meta b/Main/System/HeroReturn/HeroReturnZhanLingWin.cs.meta
new file mode 100644
index 0000000..a7eb564
--- /dev/null
+++ b/Main/System/HeroReturn/HeroReturnZhanLingWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bda89cf1dbeb16b4a8db1746e5a85a90
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/HeroUI/HeroBestWin.cs b/Main/System/HeroUI/HeroBestWin.cs
index 43d5ace..4d180ee 100644
--- a/Main/System/HeroUI/HeroBestWin.cs
+++ b/Main/System/HeroUI/HeroBestWin.cs
@@ -315,9 +315,12 @@
 
     void RefreshAttr()
     {
-        inheritAttrText[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0], heroConfig.AtkInheritPer));
-        inheritAttrText[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1], heroConfig.DefInheritPer));
-        inheritAttrText[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2], heroConfig.HPInheritPer));
+        inheritAttrText[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0],
+            HeroUIManager.Instance.GetMaxInheritAttr(PlayerPropertyConfig.inheritAttrs[0], heroConfig.HeroID, heroConfig.Quality, heroConfig)));
+        inheritAttrText[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1],
+            HeroUIManager.Instance.GetMaxInheritAttr(PlayerPropertyConfig.inheritAttrs[1], heroConfig.HeroID, heroConfig.Quality, heroConfig)));
+        inheritAttrText[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2],
+            HeroUIManager.Instance.GetMaxInheritAttr(PlayerPropertyConfig.inheritAttrs[2], heroConfig.HeroID, heroConfig.Quality, heroConfig)));
 
         //涓婇樀灞炴��
         int valuePer = GetOnBattleAddPer();
diff --git a/Main/System/HeroUI/HeroCardCell.cs b/Main/System/HeroUI/HeroCardCell.cs
index aece00f..6b9ff13 100644
--- a/Main/System/HeroUI/HeroCardCell.cs
+++ b/Main/System/HeroUI/HeroCardCell.cs
@@ -15,6 +15,8 @@
     [SerializeField] RedpointBehaviour redpoint;
     [SerializeField] Image newImage;    //鏂版爣璇嗗拰绾㈢偣浜掓枼
     [SerializeField] Image trainStateImg;
+    [SerializeField] TextEx trainStatetxt;
+    [SerializeField] OutlineEx trainStateOutline;
     [SerializeField] Image starRedImg;
     [SerializeField] Text nameText;
     [SerializeField] Image awakeImg;
@@ -49,7 +51,7 @@
             newImage.SetActive(false);
         }
         else
-        { 
+        {
             redpoint.redpointId = 0;
             newImage.SetActive(HeroUIManager.Instance.newHeroIDList.Contains(hero.heroId));
         }
@@ -59,6 +61,22 @@
         {
             trainStateImg.SetActive(true);
             trainStateImg.SetSprite("herofuncstate" + funcState);
+            trainStatetxt.text = funcState switch
+            {
+                1 => Language.Get("herocard41"),
+                2 => Language.Get("HeroGift3"),
+                3 => Language.Get("L1111"),
+                4 => Language.Get("L1109"),
+                _ => string.Empty,
+            };
+            trainStateOutline.OutlineColor = funcState switch
+            {
+                1 => new Color32(0x5c, 0x2b, 0x2b, 255),
+                2 => new Color32(0x5c, 0x46, 0x2b, 255),
+                3 => new Color32(0x2b, 0x3d, 0x5c, 255),
+                4 => new Color32(0x2e, 0x5c, 0x2b, 255),
+                _ => Color.white,
+            };
         }
         else
         {
diff --git a/Main/System/HeroUI/HeroCollectionCardCell.cs b/Main/System/HeroUI/HeroCollectionCardCell.cs
index b93702d..084f1aa 100644
--- a/Main/System/HeroUI/HeroCollectionCardCell.cs
+++ b/Main/System/HeroUI/HeroCollectionCardCell.cs
@@ -100,3 +100,4 @@
     }
 }
 
+ 
\ No newline at end of file
diff --git a/Main/System/HeroUI/HeroCollectionWin.cs b/Main/System/HeroUI/HeroCollectionWin.cs
index 4781a29..b3467c4 100644
--- a/Main/System/HeroUI/HeroCollectionWin.cs
+++ b/Main/System/HeroUI/HeroCollectionWin.cs
@@ -171,6 +171,20 @@
         {
             var _cell = cell.GetComponent<Image>();
             _cell.SetSprite("herocoltitle" + cell.index);
+
+            var title = cell.GetComponentInChildren<Text>();
+            title.text = RichTextMsgReplaceConfig.GetRichReplace("HeroQuality", cell.index);
+
+            var outlineEx = title.GetComponent<OutlineEx>();
+            outlineEx.OutlineColor = cell.index switch
+            {
+                1 => new Color32(0x17, 0x25, 0x43, 255),
+                2 => new Color32(0x2a, 0x0f, 0x30, 255),
+                3 => new Color32(0x4a, 0x2f, 0x00, 255),
+                4 => new Color32(0x45, 0x18, 0x00, 255),
+                5 => new Color32(0x51, 0x00, 0x00, 255),
+                _ => Color.white,
+            };
         }
         else if (type == ScrollerDataType.Normal)
         {
diff --git a/Main/System/HeroUI/HeroGiftEatSuccessWin.cs b/Main/System/HeroUI/HeroGiftEatSuccessWin.cs
index c4cdd86..a873467 100644
--- a/Main/System/HeroUI/HeroGiftEatSuccessWin.cs
+++ b/Main/System/HeroUI/HeroGiftEatSuccessWin.cs
@@ -13,6 +13,9 @@
 
     [SerializeField] Image[] beforeStars;
     [SerializeField] Image[] afterStars;
+    [SerializeField] Text[] attrInheritPerNameArr;  //鏂板缁ф壙灞炴�ф垚闀�
+    [SerializeField] Text[] attrInheritPerTextArr;
+    [SerializeField] Text[] nextAttrInheritPerTextArr;
     [SerializeField] Text[] attrPerNameArr;
     [SerializeField] Text[] attrPerTextArr;
     [SerializeField] Text[] nextAttrPerTextArr;
@@ -50,7 +53,8 @@
         HeroInfo hero = HeroManager.Instance.GetHero(HeroUIManager.Instance.selectHeroGuidForGiftFuncForSuccessWin);
         if (hero == null)
             return;
-
+        hero.RefreshInheritPer();   //寮哄埗閲嶅埛
+        
         int beforeStarCount = HeroUIManager.Instance.eatBeforeStar;
         int afterStarCount = hero.heroStar;
 
@@ -65,7 +69,18 @@
             int id = PlayerPropertyConfig.basePerAttrs[i];
             attrPerNameArr[i].text = PlayerPropertyConfig.Get(id).Name;
             nextAttrPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(id, valuePer);
-            attrPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(id, valuePer - hero.qualityConfig.StarAddPer*(afterStarCount - beforeStarCount));
+            attrPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(id, valuePer - hero.qualityConfig.StarAddPer * (afterStarCount - beforeStarCount));
+        }
+        
+        for (int i = 0; i < attrInheritPerNameArr.Length; i++)
+        {
+            int id = PlayerPropertyConfig.baseAttrs[i];
+            var curValue = hero.GetInheritAttrPer(id);
+            var showID = hero.GetInheritAttrIDByBaseID(id);
+            attrInheritPerNameArr[i].text = PlayerPropertyConfig.Get(showID).Name;
+            nextAttrInheritPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(showID, curValue);
+            var addPer = hero.GetInheritSingleAttrValue(showID);
+            attrInheritPerTextArr[i].text = PlayerPropertyConfig.GetValueDescription(showID, curValue -  addPer * (afterStarCount - beforeStarCount));
         }
 
         //澶╄祴
diff --git a/Main/System/HeroUI/HeroGiftEatWin.cs b/Main/System/HeroUI/HeroGiftEatWin.cs
index 9a51f8c..080c19a 100644
--- a/Main/System/HeroUI/HeroGiftEatWin.cs
+++ b/Main/System/HeroUI/HeroGiftEatWin.cs
@@ -17,6 +17,7 @@
     [SerializeField] GiftBaseCell[] addGiftCells;
     [SerializeField] GameObject addTip;
     [SerializeField] GameObject addAttrGo;
+    [SerializeField] Text[] addInheritAttrTexts;
     [SerializeField] Text[] addAttrTexts;
     [SerializeField] Text addGiftTip;
     [SerializeField] GameObject addNumGo;
@@ -83,10 +84,18 @@
             for (int i = 0; i < addAttrTexts.Length; i++)
             {
                 int id = PlayerPropertyConfig.basePerAttrs[i];
-                addAttrTexts[i].text = PlayerPropertyConfig.GetBaseFullDescription(id, hero.qualityConfig.StarAddPer,
+                addAttrTexts[i].text = PlayerPropertyConfig.GetBaseFullDescription(id, hero.qualityConfig.StarAddPer * HeroUIManager.Instance.selectEatHeroIndexList.Count,
                 "{0}+" + UIHelper.AppendColor(TextColType.Green, "{1}", true));
             }
-            addGiftTip.SetActive(!hero.IsFullGift());
+            addGiftTip.text = Language.Get("HeroGift10") + HeroUIManager.Instance.selectEatHeroIndexList.Count;
+
+            for (int i = 0; i < addInheritAttrTexts.Length; i++)
+            {
+                int id = PlayerPropertyConfig.baseAttrs[i];
+                int showID = hero.GetInheritAttrIDByBaseID(id);
+                addInheritAttrTexts[i].text = PlayerPropertyConfig.GetFullDescriptionOrgName(showID, hero.GetInheritSingleAttrValue(showID) * HeroUIManager.Instance.selectEatHeroIndexList.Count,
+                "{0}+" + UIHelper.AppendColor(TextColType.Green, "{1}", true));
+            }
         }
 
         if (HeroUIManager.Instance.selectEatHeroIndexList.IsNullOrEmpty())
@@ -158,7 +167,7 @@
         HeroUIManager.Instance.heroBeforeGiftLevelList = new List<int>(hero.talentLvList);
         HeroUIManager.Instance.lastFightPower = new KeyValuePair<string, long>(hero.itemHero.guid, hero.CalculateFightPower(false));
         HeroUIManager.Instance.eatBeforeStar = hero.heroStar;
-
+        
         //璁剧疆涓瓑寰呭洖澶嶇殑鏍囪瘑 鏄剧ず鎴愬姛鐣岄潰
         HeroUIManager.Instance.waitResponse = new WaitHeroFuncResponse()
         {
diff --git a/Main/System/HeroUI/HeroLVBreakCell.cs b/Main/System/HeroUI/HeroLVBreakCell.cs
index 78b5b2a..3bdfd47 100644
--- a/Main/System/HeroUI/HeroLVBreakCell.cs
+++ b/Main/System/HeroUI/HeroLVBreakCell.cs
@@ -101,7 +101,7 @@
 
         for (int i = 0; i < moneyIcons.Length; i++)
         {
-            if (i < hero.qualityBreakConfig.UPCostItemList.Length)
+            if (hero.qualityBreakConfig.UPCostItemList != null && i < hero.qualityBreakConfig.UPCostItemList.Length)
             {
                 moneyRects[i].SetActive(true);
                 moneyIcons[i].SetOrgSprite(ItemConfig.Get(hero.qualityBreakConfig.UPCostItemList[i][0]).IconKey);
@@ -144,7 +144,10 @@
         potentialText.text = Language.Get("L1100", Language.Get("herocard56"), string.Join("\n", attrStrArr));
 
         string needLV = UIHelper.AppendColor(hero.heroLevel < hero.qualityBreakConfig.UPLVNeed ? TextColType.Red : TextColType.Green, $"{hero.heroLevel}/{hero.qualityBreakConfig.UPLVNeed}");
-        needLVText.text = Language.Get("herobreak3", needLV);
+        
+        string needStar = UIHelper.AppendColor(hero.heroStar < hero.qualityBreakConfig.UPLVNeedStar ? TextColType.Red : TextColType.Green, $"{hero.heroStar}/{hero.qualityBreakConfig.UPLVNeedStar}");
+        
+        needLVText.text = Language.Get("herobreak3", needLV) + (hero.qualityBreakConfig.UPLVNeedStar > 0 ? "    " + Language.Get("HeroBreakStar") + needStar : string.Empty);
     }
 
     void BreakLV()
diff --git a/Main/System/HeroUI/HeroTrainWin.cs b/Main/System/HeroUI/HeroTrainWin.cs
index 38321dd..e34b969 100644
--- a/Main/System/HeroUI/HeroTrainWin.cs
+++ b/Main/System/HeroUI/HeroTrainWin.cs
@@ -515,9 +515,12 @@
 
     void RefreshAttr()
     {
-        inheritAttrText[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0], hero.heroConfig.AtkInheritPer));
-        inheritAttrText[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1], hero.heroConfig.DefInheritPer));
-        inheritAttrText[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2], hero.heroConfig.HPInheritPer));
+        inheritAttrText[0].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[0],
+            hero.GetInheritAttrPerByInheritID(PlayerPropertyConfig.inheritAttrs[0])));
+        inheritAttrText[1].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[1],
+            hero.GetInheritAttrPerByInheritID(PlayerPropertyConfig.inheritAttrs[1])));
+        inheritAttrText[2].text = PlayerPropertyConfig.GetFullDescription(new Int2(PlayerPropertyConfig.inheritAttrs[2],
+            hero.GetInheritAttrPerByInheritID(PlayerPropertyConfig.inheritAttrs[2])));
 
         //涓婇樀灞炴��
         int valuePer = hero.GetAddPer();
diff --git a/Main/System/HeroUI/HeroUIManager.Talent.cs b/Main/System/HeroUI/HeroUIManager.Talent.cs
index b8b5b9f..636b483 100644
--- a/Main/System/HeroUI/HeroUIManager.Talent.cs
+++ b/Main/System/HeroUI/HeroUIManager.Talent.cs
@@ -98,7 +98,15 @@
         return HeroQualityConfig.Get(quality).InitStarUpper + addStarCount;
     }
 
-
+	//鐢ㄧ户鎵縄D鑾峰緱鏈�澶х户鎵垮睘鎬�
+	public int GetMaxInheritAttr(int id, int heroID, int quality, HeroConfig heroConfig)
+	{
+		var maxStar = GetMaxStarCount(heroID, quality);
+		if (id == 13) return heroConfig.AtkInheritPer + heroConfig.AtkInheritPerStar * maxStar;
+		if (id == 14) return heroConfig.DefInheritPer + heroConfig.DefInheritPerStar * maxStar;
+		if (id == 15) return heroConfig.HPInheritPer + heroConfig.HPInheritPerStar * maxStar;
+		return 0;
+	}
 
     //beforeGiftIDList鐢ㄤ簬瀵规瘮鍙樺寲鐨勫ぉ璧嬫牸瀛�
     public void RefreshGiftCell(GiftBaseCell[] giftBaseCells, HeroInfo hero, List<int> beforeGiftIDList = null, List<int> beforeGiftLevelList = null)
diff --git a/Main/System/HeroUI/HeroUIManager.cs b/Main/System/HeroUI/HeroUIManager.cs
index da04202..b17ed9c 100644
--- a/Main/System/HeroUI/HeroUIManager.cs
+++ b/Main/System/HeroUI/HeroUIManager.cs
@@ -239,6 +239,15 @@
             }
             return false;
         }
+        if (hero.heroStar < HeroQualityBreakConfig.GetQualityBreakConfig(hero.Quality, hero.breakLevel).UPLVNeedStar)
+        {
+            //鏄熺骇鏈揪鏍�
+            if (showTip != 0)
+            {
+                SysNotifyMgr.Instance.ShowTip("HeroStarNotEnough");
+            }
+            return false;
+        }
         if (hero.breakLevel >= HeroBreakConfig.GetMaxBreakLv(hero.heroId))
         {
             //绐佺牬绛夌骇宸茶揪鏈�楂樼骇
diff --git a/Main/System/Horse/GetHorseWin.cs b/Main/System/Horse/GetHorseWin.cs
new file mode 100644
index 0000000..9a9ca62
--- /dev/null
+++ b/Main/System/Horse/GetHorseWin.cs
@@ -0,0 +1,38 @@
+using System;
+using UnityEngine;
+
+public class GetHorseWin : UIBase
+{
+    [SerializeField] ImageEx iconImg;
+    [SerializeField] TextEx nameTxt;
+    [SerializeField] TextEx attrTxt;
+    [SerializeField] ButtonEx okBtn;
+
+    protected override void InitComponent()
+    {
+        okBtn.AddListener(CloseWindow);
+    }
+
+    protected override void OnPreOpen()
+    {
+        int horseID = HorseManager.Instance.unLockHorseID;
+        int skinID = HorseManager.Instance.unLockSkinID;
+
+        var horseIDConfig = HorseIDConfig.Get(horseID);
+        if (horseIDConfig == null)
+            return;
+
+        var horseSkinConfig = HorseSkinConfig.Get(skinID);
+        if (horseSkinConfig == null)
+            return;
+
+        nameTxt.text = horseSkinConfig.Name;
+        iconImg.overrideSprite = UILoader.LoadSprite("HorseIcon", horseSkinConfig.Icon);
+        iconImg.SetNativeSize();
+        HorseManager.Instance.GetRiderTotalAttrInfoByHorseID(horseID, out int attrID, out long value, out PlayerPropertyConfig playerPropertyConfig);
+        attrTxt.text = StringUtility.Concat(PlayerPropertyConfig.Get(attrID).ShowName, " ", "+", PlayerPropertyConfig.GetValueDescription(attrID, value));
+
+    }
+
+
+}
\ No newline at end of file
diff --git a/Main/System/Horse/GetHorseWin.cs.meta b/Main/System/Horse/GetHorseWin.cs.meta
new file mode 100644
index 0000000..cba1bb8
--- /dev/null
+++ b/Main/System/Horse/GetHorseWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3a845cc8515c95b4bafd63b59c6d7a0e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Horse/HorseCarouselView.cs b/Main/System/Horse/HorseCarouselView.cs
new file mode 100644
index 0000000..9ffa92e
--- /dev/null
+++ b/Main/System/Horse/HorseCarouselView.cs
@@ -0,0 +1,226 @@
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using System;
+
+public class HorseCarouselView : MonoBehaviour, IDragHandler, IEndDragHandler, IBeginDragHandler
+{
+    /// 褰撳墠閫変腑绱㈠紩鍙樺寲鏃惰Е鍙�
+    public event Action OnSelectedIndexChanged;
+
+    [Header("UI References")]
+    public RectTransform content;          // 瀛樻斁Item鐨勭埗鑺傜偣
+    public GameObject horseItemPrefab;     // 鍧愰獞Item棰勫埗浣�
+
+    [Header("Carousel Settings")]
+    List<HorseIDConfig> horseConfigs;  // 鍧愰獞閰嶇疆鍒楄〃
+    public float itemSpacing = 150f;       // 姣忎釜鍧愰獞鐨勯棿璺�
+    public float scaleMax = 1.3f;          // 灞呬腑鏃剁殑鏈�澶х缉鏀�
+    public float scaleMin = 0.8f;          // 杈圭紭鏃剁殑鏈�灏忕缉鏀�
+
+    private List<HorseItem> items = new List<HorseItem>();
+
+    // 褰撳墠閫昏緫涓績鐨勫亸绉婚噺 (娴偣鏁帮紝鐢ㄤ簬骞虫粦婊戝姩)
+    private float currentCenterOffset = 0f;
+    private float targetCenterOffset = 0f;
+
+    private bool isDragging = false;
+    private int currentSelectedIndex = 0;
+
+    /// <summary>
+    /// 褰撳墠閫変腑鐨勫潗楠慖D
+    /// </summary>
+    public int CurrentHorseId
+    {
+        get
+        {
+            if (horseConfigs != null && horseConfigs.Count > 0 && currentSelectedIndex >= 0)
+            {
+                int realIndex = (currentSelectedIndex % horseConfigs.Count + horseConfigs.Count) % horseConfigs.Count;
+                return horseConfigs[realIndex].HorseID;
+            }
+            return 0;
+        }
+    }
+
+    /// <summary>
+    /// 鍒濆鍖栨睜瀛愶紙鐢卞閮ㄨ皟鐢級
+    /// </summary>
+    public void InitPool()
+    {
+        if (items.Count > 0)
+            return;
+        // 鍒濆鍖栨睜瀛愶細涓轰簡淇濊瘉宸﹀彸婊戝姩涓嶇┛甯紝瑙嗛噹鍐呮樉绀�5涓紝姹犲瓙鍙互寤�7涓� (5 + 宸﹀彸鍚勫1涓紦鍐�)
+        int poolSize = 7;
+        for (int i = 0; i < poolSize; i++)
+        {
+            GameObject go = Instantiate(horseItemPrefab, content);
+            HorseItem item = go.GetComponent<HorseItem>();
+            items.Add(item);
+        }
+    }
+
+    /// <summary>
+    /// 鍒濆鍖栧潗楠戦厤缃紙鐢卞閮ㄨ皟鐢級
+    /// </summary>
+    public void InitHorseConfigs(List<HorseIDConfig> configs)
+    {
+        horseConfigs = configs;
+    }
+
+    // 鐣岄潰鎵撳紑鏃惰皟鐢紝浼犲叆褰撳墠楠戜箻鐨勫潗楠戝簭鍙�
+    public void InitWithHorse(int horseIndex)
+    {
+        currentSelectedIndex = horseIndex;
+        currentCenterOffset = horseIndex;
+        targetCenterOffset = horseIndex;
+        UpdateItems();
+    }
+
+    // 鐐瑰嚮閫変腑鎸囧畾绱㈠紩鐨勫潗楠�
+    public void SelectIndex(int index)
+    {
+        int oldIndex = currentSelectedIndex;
+        currentSelectedIndex = index;
+        targetCenterOffset = index;
+        currentCenterOffset = index;
+        UpdateItems();
+
+        if (oldIndex != currentSelectedIndex)
+        {
+            OnSelectedIndexChanged?.Invoke();
+        }
+    }
+
+    /// <summary>
+    /// 鍒囨崲鍒颁笂涓�涓潗楠�
+    /// </summary>
+    public void SelectPrevious()
+    {
+        int newIndex = (currentSelectedIndex - 1 + horseConfigs.Count) % horseConfigs.Count;
+        SelectIndex(newIndex);
+    }
+
+    /// <summary>
+    /// 鍒囨崲鍒颁笅涓�涓潗楠�
+    /// </summary>
+    public void SelectNext()
+    {
+        int newIndex = (currentSelectedIndex + 1) % horseConfigs.Count;
+        SelectIndex(newIndex);
+    }
+
+    /// <summary>
+    /// 鍒锋柊鎵�鏈塇orseItem鐨勬樉绀猴紙澶栭儴璋冪敤鎺ュ彛锛�
+    /// </summary>
+    public void RefreshAllItems()
+    {
+        if (horseConfigs != null && horseConfigs.Count > 0)
+        {
+            UpdateItems();
+        }
+    }
+
+    void Update()
+    {
+        // 娌″湪鎷栨嫿鏃讹紝骞虫粦鍚搁檮鍒扮洰鏍囦綅缃�
+        if (!isDragging && Mathf.Abs(currentCenterOffset - targetCenterOffset) > 0.001f)
+        {
+            currentCenterOffset = Mathf.Lerp(currentCenterOffset, targetCenterOffset, Time.deltaTime * 10f);
+            UpdateItems();
+        }
+    }
+
+    // 鏍稿績鍒锋柊閫昏緫
+    private void UpdateItems()
+    {
+        int poolSize = items.Count;
+        // 璁$畻褰撳墠涓績浣嶇疆宸︿晶搴旇浠庡摢涓亸绉婚噺寮�濮嬫覆鏌�
+        int startOffset = Mathf.FloorToInt(currentCenterOffset) - (poolSize / 2);
+
+        for (int i = 0; i < poolSize; i++)
+        {
+            // 1. 璁$畻閫昏緫绱㈠紩 (鍖呭惈璐熸暟鎯呭喌)
+            int logicIndex = startOffset + i;
+
+            // 2. 灏嗛�昏緫绱㈠紩鏄犲皠鍒板疄闄呯殑鍧愰獞搴忓彿 (鏍稿績锛氬疄鐜伴灏剧浉杩炵殑鏃犻檺寰幆)
+            // 姣斿 horseConfigs.Count=10锛屽綋 logicIndex=-1鏃讹紝realIndex=9 (鏈綅)
+            int realIndex = (logicIndex % horseConfigs.Count + horseConfigs.Count) % horseConfigs.Count;
+
+            // 3. 璁$畻璇� Item 搴旇鍦ㄧ殑 X 鍧愭爣浣嶇疆
+            // logicIndex - currentCenterOffset 琛ㄧず璇� item 璺濈涓績鐨勯�昏緫璺濈
+            float distanceToCenter = logicIndex - currentCenterOffset;
+            float posX = distanceToCenter * itemSpacing;
+
+            // 4. 鏇存柊 UI 鏄剧ず
+            HorseItem itemUI = items[i];
+            itemUI.rectTransform.anchoredPosition = new Vector2(posX, 0);
+
+            // 5. 璁$畻缂╂斁涓庨�変腑鐘舵�� (鏍规嵁璺濈涓績鐨勭粷瀵硅窛绂�)
+            float absDist = Mathf.Abs(distanceToCenter);
+            // 璺濈灏忎簬1鏃跺紑濮嬫斁澶э紝澶т簬绛変簬1鏃朵负鏈�灏忕缉鏀�
+            float scaleProgress = Mathf.Clamp01(1f - absDist);
+            float currentScale = Mathf.Lerp(scaleMin, scaleMax, scaleProgress);
+            itemUI.rectTransform.localScale = Vector3.one * currentScale;
+
+            // 6. 鏁版嵁涓庤〃鐜版洿鏂� (鍒锋柊澶村儚銆佸悕瀛楃瓑)
+            itemUI.UpdateData(horseConfigs[realIndex], realIndex);
+            itemUI.onItemClick = SelectIndex;
+
+            // 7. 鏍规嵁鏄惁灞呬腑鏉ヨ缃�変腑鐘舵��
+            bool isSelected = Mathf.Approximately(distanceToCenter, 0f);
+            itemUI.SetSelected(isSelected);
+        }
+    }
+
+    #region 鎷栨嫿涓庡惛闄勯�昏緫
+
+    public void OnBeginDrag(PointerEventData eventData)
+    {
+        isDragging = true;
+    }
+
+    public void OnDrag(PointerEventData eventData)
+    {
+        // 灏嗛紶鏍�/鎵嬫寚鐨勬粦鍔ㄥ儚绱犺浆鍖栦负閫昏緫鍋忕Щ閲�
+        float dragDeltaX = eventData.delta.x;
+        // 闃诲凹绯绘暟锛屾帶鍒舵粦鍔ㄩ�熷害
+        currentCenterOffset -= dragDeltaX / itemSpacing;
+        UpdateItems();
+    }
+
+    public void OnEndDrag(PointerEventData eventData)
+    {
+        isDragging = false;
+
+        // 鏉炬墜鏃讹紝璁$畻搴旇鍚搁檮鍒板摢涓�涓暣鏁扮储寮�
+        // 鍔犲叆鎯�у垽鏂細濡傛灉婊戝姩閫熷害澶熷揩锛岀洿鎺ヨ繘涓�浣嶆垨閫�涓�浣�
+        float speedX = eventData.delta.x;
+        if (speedX > 5f)
+        {
+            targetCenterOffset = Mathf.Floor(currentCenterOffset);
+        }
+        else if (speedX < -5f)
+        {
+            targetCenterOffset = Mathf.Ceil(currentCenterOffset);
+        }
+        else
+        {
+            // 鍚﹀垯灏辫繎鍥涜垗浜斿叆鍚搁檮
+            targetCenterOffset = Mathf.Round(currentCenterOffset);
+        }
+
+        // 鏇存柊鏈�缁堥�変腑鐨勭湡瀹炵储寮�
+        int oldIndex = currentSelectedIndex;
+        currentSelectedIndex = (Mathf.RoundToInt(targetCenterOffset) % horseConfigs.Count + horseConfigs.Count) % horseConfigs.Count;
+
+        if (oldIndex != currentSelectedIndex)
+        {
+            OnSelectedIndexChanged?.Invoke();
+        }
+
+        Debug.Log("褰撳墠閫変腑鍧愰獞搴忓彿: " + currentSelectedIndex);
+    }
+
+    #endregion
+}
\ No newline at end of file
diff --git a/Main/System/Horse/HorseCarouselView.cs.meta b/Main/System/Horse/HorseCarouselView.cs.meta
new file mode 100644
index 0000000..5fbc2e6
--- /dev/null
+++ b/Main/System/Horse/HorseCarouselView.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b1022553a62dd7d47afae33bd87625e3
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Horse/HorseItem.cs b/Main/System/Horse/HorseItem.cs
new file mode 100644
index 0000000..652e07a
--- /dev/null
+++ b/Main/System/Horse/HorseItem.cs
@@ -0,0 +1,50 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class HorseItem : MonoBehaviour
+{
+    public RectTransform rectTransform;
+    public Image iconImg;
+    public Image attrNameBg;
+    public TextEx attrName;
+    public Image lockImg;
+    public TextEx useTxt;
+    public ButtonEx clickBtn;
+    public Image chooseImg;
+
+    // 鐐瑰嚮鍥炶皟锛屼紶閫掕Item瀵瑰簲鐨剅ealIndex
+    public System.Action<int> onItemClick;
+    public int realIndex;
+
+    // 鍒锋柊鏁版嵁
+    public void UpdateData(HorseIDConfig config, int index)
+    {
+        if (config == null)
+            return;
+        if (!HorseSkinConfig.horseIDTohorseSkinIDDict.TryGetValue(config.HorseID, out int skinID))
+            return;
+        var horseSkinConfig = HorseSkinConfig.Get(skinID);
+        if (horseSkinConfig == null)
+            return;
+
+        iconImg.overrideSprite = UILoader.LoadSprite("HorseIcon", horseSkinConfig.Icon);
+        iconImg.SetNativeSize();
+
+        bool hasArrtId = PlayerPropertyConfig.HasKey(config.AttrID);
+        attrNameBg.SetActive(hasArrtId);
+        attrName.text = hasArrtId ? PlayerPropertyConfig.Get(config.AttrID).Name : string.Empty;
+
+        lockImg.SetActive(!HorseManager.Instance.IsHorseUnlocked(config.HorseID));
+        useTxt.SetActive(config.HorseID == HorseManager.Instance.horseID);
+
+        realIndex = index;
+        clickBtn.onClick.RemoveAllListeners();
+        clickBtn.onClick.AddListener(() => onItemClick?.Invoke(realIndex));
+    }
+
+    // 鎺у埗閫変腑鍥剧墖鐨勬樉绀�
+    public void SetSelected(bool selected)
+    {
+        chooseImg.SetActive(selected);
+    }
+}
\ No newline at end of file
diff --git a/Main/System/Horse/HorseItem.cs.meta b/Main/System/Horse/HorseItem.cs.meta
new file mode 100644
index 0000000..4219927
--- /dev/null
+++ b/Main/System/Horse/HorseItem.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e7860cf1649b57e479b5a50f0058a8c8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Horse/HorseManager.cs b/Main/System/Horse/HorseManager.cs
index 76c3fea..7ca7a52 100644
--- a/Main/System/Horse/HorseManager.cs
+++ b/Main/System/Horse/HorseManager.cs
@@ -1,12 +1,15 @@
-锘縰sing System;
+using System;
 using LitJson;
 using Cysharp.Threading.Tasks;
-
 using System.Collections.Generic;
 using System.Linq;
 
 public class HorseManager : GameSystemManager<HorseManager>
 {
+
+    public int unLockSkinID;
+    public int unLockHorseID;
+
     public int classLV;    //褰撳墠闃剁骇锛屼粠0寮�濮�
     public int horseLV;    //褰撳墠闃剁瓑绾э紝浠�1寮�濮�
     public int exp;    //褰撳墠闃剁瓑绾х粡楠岋紝姣忕骇浠�0寮�濮�
@@ -36,6 +39,31 @@
     public int lvUPItemID;
     public int rankUPItemID;
     public int quickRankLV;
+    public int defaultSkinID;
+
+    // 鎺掑簭鍚庣殑鍧愰獞閰嶇疆缂撳瓨
+    private static List<HorseIDConfig> sortedHorseConfigs;
+
+    /// <summary>
+    /// 鑾峰彇鎺掑簭鍚庣殑鍧愰獞閰嶇疆鍒楄〃锛堝甫缂撳瓨锛�
+    /// </summary>
+    public static List<HorseIDConfig> GetSortedHorseConfigs()
+    {
+        if (sortedHorseConfigs == null)
+        {
+            sortedHorseConfigs = HorseIDConfig.GetValues().OrderBy(c =>
+            {
+                int skinID = HorseSkinConfig.horseIDTohorseSkinIDDict.TryGetValue(c.HorseID, out var id) ? id : int.MaxValue;
+                var skinConfig = HorseSkinConfig.Get(skinID);
+                return skinConfig?.sortOrder ?? int.MaxValue;
+            }).ThenBy(c =>
+            {
+                return HorseSkinConfig.horseIDTohorseSkinIDDict.TryGetValue(c.HorseID, out var skinID) ? skinID : int.MaxValue;
+            }).ToList();
+        }
+        return sortedHorseConfigs;
+    }
+
 
     public override void Init()
     {
@@ -53,12 +81,15 @@
         DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk;
     }
 
+
+
     void ParseConfig()
     {
         var config = FuncConfigConfig.Get("HorseUpItem");
         lvUPItemID = int.Parse(config.Numerical1);
         rankUPItemID = int.Parse(config.Numerical2);
         quickRankLV = int.Parse(config.Numerical3);
+        defaultSkinID = int.Parse(config.Numerical4);
     }
 
     void OnBeforePlayerDataInitialize()
@@ -67,6 +98,8 @@
         horseLV = 0;
         exp = 0;
         skinDic.Clear();
+        horseIDState = 0;
+        horseID = 0;
     }
 
     void OnPlayerLoginOk()
@@ -91,14 +124,15 @@
     }
 
     //鑾峰彇褰撳墠浣跨敤鍧愰獞鐨偆ID
-    public int GetUsingHorseSkinID(bool useDefault = false)
+    public int GetUsingHorseSkinID(bool useDefault = true)
     {
         var id = (int)PlayerDatas.Instance.baseData.equipShowSwitch % 1000;
-        if (id == 0)
+        // 0 鏈够鍖�
+        if (id == 0 || !HorseSkinConfig.HasKey(id))
         {
             if (useDefault)
             {
-                return 1;
+                return defaultSkinID;
             }
         }
         return id;
@@ -107,9 +141,29 @@
     //鑾峰彇鍏朵粬鐜╁浣跨敤鍧愰獞鐨偆ID
     public int GetOtherPlayerHorseSkinID(int value)
     {
-        return value % 1000;
+        int id = value % 1000;
+        if (id == 0 || !HorseSkinConfig.HasKey(id))
+            return defaultSkinID;
+        return id;
     }
 
+    //鏄惁澶勪簬骞诲寲鐘舵��
+    public bool IsChangeState(int skinID)
+    {
+        if (skinID == 0) return false;
+        if (!HorseSkinConfig.HasKey(skinID)) return false;
+
+        var config = HorseSkinConfig.Get(skinID);
+        if (config == null) return false;
+        return config.showType == 1;
+    }
+
+    public bool IsHorseIDSkin(int skinID)
+    {
+        var config = HorseSkinConfig.Get(skinID);
+        if (config == null) return false;
+        return config.showType == 2;
+    }
 
     public void UpdateHorseInfo(HA303_tagSCHorseClassInfo netPack)
     {
@@ -154,6 +208,86 @@
             UIManager.Instance.OpenWindowAsync<HorseSkinGetWin>(netPack.HorseSkinList[0].HorseSkinID).Forget();
         }
 
+    }
+    public void SendHorseIDOP(int horseID, int opType)
+    {
+        CB204_tagCSHorseIDOP pack = new CB204_tagCSHorseIDOP()
+        {
+            HorseID = (byte)horseID,
+            OPType = (byte)opType
+        };
+        GameNetSystem.Instance.SendInfo(pack);
+    }
+
+    //鍧愰獞ID淇℃伅
+    public uint horseIDState;
+    public int horseID;
+    public event Action OnUpdateHorseIDInfoEvent;
+    /// <summary>鏂拌В閿佸潗楠戜簨浠讹紝鍙傛暟锛氭柊瑙i攣鐨勫潗楠慖D (0-31)</summary>
+    public event Action<int> OnHorseUnlockedEvent;
+    /// <summary>浣╂埓鍧愰獞鍙樺寲浜嬩欢锛屽弬鏁帮細(鏃D, 鏂癐D)</summary>
+    public event Action<int, int> OnHorseChangedEvent;
+    public void UpdateHorseIDInfo(HA305_tagSCHorseIDInfo netPack)
+    {
+        // 1. 妫�娴嬫柊瑙i攣鐨勫潗楠� (horseID 浠� 0 寮�濮�)
+        uint diff = horseIDState ^ netPack.HorseIDState; // 宸紓浣�
+        uint newUnlock = netPack.HorseIDState & diff;       // 鏂板瑙i攣鐨勪綅
+
+        if (newUnlock != 0)
+        {
+            for (int i = 0; i < 32; i++)
+            {
+                if ((newUnlock & (1u << i)) != 0)
+                {
+                    OnHorseUnlockedEvent?.Invoke(i); // i 灏辨槸鍧愰獞ID (0-31)
+                }
+            }
+        }
+
+        // 2. 妫�娴嬩僵鎴碔D鍙樺寲
+        if (horseID != netPack.HorseID)
+        {
+            byte oldID = (byte)horseID;
+            horseID = netPack.HorseID;
+            OnHorseChangedEvent?.Invoke(oldID, horseID);
+        }
+
+        // 鏇存柊鐘舵��
+        horseIDState = netPack.HorseIDState;
+        OnUpdateHorseIDInfoEvent?.Invoke();
+    }
+
+    /// <summary>
+    /// 鍒ゆ柇鍧愰獞ID鏄惁宸茶В閿� (horseID 浠� 0 寮�濮�)
+    /// </summary>
+    /// <param name="horseID">鍧愰獞ID (0-31)</param>
+    public bool IsHorseUnlocked(int horseID)
+    {
+        var config = HorseIDConfig.Get(horseID);
+        if (config == null) return false;
+
+        if (config.UnlockWay == 1) return true;
+
+        if (horseID < 0 || horseID > 31) return false;
+        return (horseIDState & (1u << horseID)) != 0;
+    }
+    public int GetNowAttrValue(int attrID)
+    {
+        int totalValue = 0;
+        // 浠�0闃剁疮鍔犲埌褰撳墠闃�
+        for (int lv = 0; lv <= classLV; lv++)
+        {
+            var config = HorseClassConfig.Get(lv);
+            if (config.ClassSpecAttrIDList != null)
+            {
+                int index = Array.IndexOf(config.ClassSpecAttrIDList, attrID);
+                if (index >= 0 && config.ClassSpecAttrValueList != null && index < config.ClassSpecAttrValueList.Length)
+                {
+                    totalValue += config.ClassSpecAttrValueList[index];
+                }
+            }
+        }
+        return totalValue;
     }
 
     #region 绾㈢偣
@@ -204,9 +338,13 @@
         }
 
 
+
         //鍗囨槦/瑙i攣绾㈢偣
         foreach (var skin in HorseSkinConfig.GetValues())
         {
+            if (skin.showType != 1)
+                continue;
+
             if (IsSkinActive(skin.SkinID))
             {
                 if (skin.StarMax > 0)
@@ -226,7 +364,7 @@
 
                 if (skin.UnlockWay == 1)
                 {
-                    if (classLV >= skin.UnlockValue &&  skin.UnlockValue > 0)
+                    if (classLV >= skin.UnlockValue && skin.UnlockValue > 0)
                     {
                         skinRedpoint.state = RedPointState.Simple;
                         return;
@@ -273,7 +411,8 @@
     public bool IsShowTheHorseRedImg(int skinID)
     {
         var skin = HorseSkinConfig.Get(skinID);
-
+        if (skin.showType != 1)
+            return false;
         if (IsSkinActive(skin.SkinID))
         {
             if (skin.StarMax > 0)
@@ -306,7 +445,7 @@
                 {
                     return true;
                 }
-            }            
+            }
         }
         return false;
     }
@@ -343,6 +482,7 @@
     {
         specialAttrDic.Clear();
         attrDic.Clear();
+
         for (int lv = 0; lv <= classLV; lv++)
         {
             //鎸夐樁鍔犳垚
@@ -386,6 +526,7 @@
                 }
             }
         }
+
     }
 
     //鍒锋柊鐨偆灞炴��
@@ -432,12 +573,130 @@
         }
     }
 
+    private long AccumulateAttrValues(int attrID, int[] attrIDList, int[] attrValueList)
+    {
+        long result = 0;
+        if (attrIDList == null || attrIDList.Length == 0)
+            return result;
+        for (int i = 0; i < attrIDList.Length; i++)
+        {
+            if (attrIDList[i] == attrID)
+            {
+                result += attrValueList[i];
+            }
+        }
+        return result;
+    }
+
+    public bool GetNowRiderAttrInfo(out int attrID, out long value, out PlayerPropertyConfig playerPropertyConfig)
+    {
+        value = 0;
+        HorseIDConfig horseIDConfig = HorseIDConfig.Get(horseID);
+        attrID = horseIDConfig.AttrID;
+        for (int lv = 0; lv <= classLV; lv++)
+        {
+            var config = HorseClassConfig.Get(lv);
+            value += AccumulateAttrValues(attrID, config.HorseEffAttrIDList, config.HorseEffAttrValueList);
+        }
+        playerPropertyConfig = PlayerPropertyConfig.Get(attrID);
+        return playerPropertyConfig != null;
+    }
+
+    public bool GetNowRiderTotalAttrInfo(out int attrID, out long value, out PlayerPropertyConfig playerPropertyConfig)
+    {
+        GetNowRiderAttrInfo(out attrID, out value, out playerPropertyConfig);
+        for (int lv = 0; lv <= classLV; lv++)
+        {
+            var config = HorseClassConfig.Get(lv);
+            value += AccumulateAttrValues(attrID, config.ClassSpecAttrIDList, config.ClassSpecAttrValueList);
+        }
+        return playerPropertyConfig != null;
+    }
+
+    public bool GetRiderTotalAttrInfoByHorseID(int horseID, out int attrID, out long value, out PlayerPropertyConfig playerPropertyConfig)
+    {
+        value = 0;
+        HorseIDConfig horseIDConfig = HorseIDConfig.Get(horseID);
+        if (horseIDConfig == null)
+        {
+            attrID = 0;
+            playerPropertyConfig = null;
+            return false;
+        }
+        attrID = horseIDConfig.AttrID;
+        for (int lv = 0; lv <= classLV; lv++)
+        {
+            var config = HorseClassConfig.Get(lv);
+            value += AccumulateAttrValues(attrID, config.HorseEffAttrIDList, config.HorseEffAttrValueList);
+            value += AccumulateAttrValues(attrID, config.ClassSpecAttrIDList, config.ClassSpecAttrValueList);
+        }
+        playerPropertyConfig = PlayerPropertyConfig.Get(attrID);
+        return playerPropertyConfig != null;
+    }
+
+
+    Dictionary<int, long> mergedResultDic = new Dictionary<int, long>();
+    public Dictionary<int, long> GetMergedAttrDic()
+    {
+
+        mergedResultDic.Clear();
+        // 鍚堝苟 specialAttrDic
+        foreach (var kvp in specialAttrDic)
+        {
+            mergedResultDic[kvp.Key] = kvp.Value;
+        }
+
+        if (GetNowRiderAttrInfo(out int attrID, out long value, out PlayerPropertyConfig playerPropertyConfig))
+        {
+            if (mergedResultDic.TryGetValue(attrID, out long existingValue))
+            {
+                mergedResultDic[attrID] = existingValue + value;
+            }
+            else
+            {
+                mergedResultDic[attrID] = value;
+            }
+        }
+
+
+        // 鍚堝苟 attrDic
+        foreach (var kvp in attrDic)
+        {
+            if (mergedResultDic.ContainsKey(kvp.Key))
+                mergedResultDic[kvp.Key] += kvp.Value;
+            else
+                mergedResultDic[kvp.Key] = kvp.Value;
+        }
+
+        // 鍚堝苟 skinAttrDic
+        foreach (var kvp in skinAttrDic)
+        {
+            if (mergedResultDic.ContainsKey(kvp.Key))
+                mergedResultDic[kvp.Key] += kvp.Value;
+            else
+                mergedResultDic[kvp.Key] = kvp.Value;
+        }
+
+        return mergedResultDic;
+    }
+
+
     public long GetAttrValue(int attrID)
     {
         attrDic.TryGetValue(attrID, out long value);
         specialAttrDic.TryGetValue(attrID, out long specialValue);
         skinAttrDic.TryGetValue(attrID, out long skinValue);
-        return value + specialValue + skinValue;
+
+        GetNowRiderAttrInfo(out int nowRiderAttrID, out long nowRiderValue, out PlayerPropertyConfig playerPropertyConfig);
+        if (nowRiderAttrID == attrID)
+        {
+            return value + specialValue + skinValue + nowRiderValue;
+        }
+        else
+        {
+            return value + specialValue + skinValue;
+        }
+
     }
 
     public int GetAttrPer(int attrID)
@@ -449,7 +708,15 @@
             specialAttrDic.TryGetValue(pertype, out long specialValue);
             skinAttrDic.TryGetValue(pertype, out long skinValue);
 
-            return (int)(value + specialValue + skinValue);
+            GetNowRiderAttrInfo(out int nowRiderAttrID, out long nowRiderValue, out PlayerPropertyConfig playerPropertyConfig);
+            if (nowRiderAttrID == attrID)
+            {
+                return (int)(value + specialValue + skinValue + nowRiderValue);
+            }
+            else
+            {
+                return (int)(value + specialValue + skinValue);
+            }
         }
 
         return 0;
@@ -459,7 +726,15 @@
     public List<int> sortSkinList = new List<int>();
     public void SortHorseSkinList()
     {
-        sortSkinList = HorseSkinConfig.GetKeys();
+        sortSkinList.Clear();
+        var temp = HorseSkinConfig.GetValues();
+        foreach (var config in temp)
+        {
+            if (config.showType == 1)
+            {
+                sortSkinList.Add(config.SkinID);
+            }
+        }
         sortSkinList.Sort((a, b) =>
         {
             var isActiveA = IsSkinActive(a);
@@ -470,9 +745,19 @@
             }
             var skinA = HorseSkinConfig.Get(a);
             var skinB = HorseSkinConfig.Get(b);
+
+            // isActive 鐩稿悓鏃讹紝鍏堟寜 sortOrder 鎺掑簭
+            if (skinA.sortOrder != skinB.sortOrder)
+            {
+                return skinA.sortOrder - skinB.sortOrder;
+            }
+
+            // sortOrder 鐩稿悓鏃讹紝鍐嶆寜 SkinID 鎺掑簭
             return skinA.SkinID - skinB.SkinID;
         });
     }
+
+
 
     public Dictionary<int, long> GetAttrBySkinID(HorseSkinConfig config)
     {
@@ -525,7 +810,8 @@
     }
 }
 
-public class HorseSkin {
+public class HorseSkin
+{
     public int State;        //鏄惁宸叉縺娲�
     public int EndTime;        //鍒版湡鏃堕棿鎴筹紝0涓烘案涔�
     public int Star;        //鏄熺骇
diff --git a/Main/System/Horse/HorseRankUPWin.cs b/Main/System/Horse/HorseRankUPWin.cs
index e21a8db..fc7ebb9 100644
--- a/Main/System/Horse/HorseRankUPWin.cs
+++ b/Main/System/Horse/HorseRankUPWin.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -11,14 +12,17 @@
 {
     [SerializeField] Text curLVText;
     [SerializeField] Text nextLVText;
-    [SerializeField] Text[] attrNameTexts;
-    [SerializeField] Text[] attrValueTexts;
-    [SerializeField] Text[] nextAttrValueTexts;
 
     [SerializeField] Transform[] specialAttrRect;
     [SerializeField] Text[] specialAttrNameTexts;
     [SerializeField] Text[] specialAttrValueTexts;
     [SerializeField] Text[] specialNextAttrValueTexts;
+
+    [SerializeField] Transform riderAttrRect;
+    [SerializeField] Text riderAttrNameText;
+    [SerializeField] Text riderAttrValueText;
+    [SerializeField] Text riderNextAttrValueText;
+    [SerializeField] Text noRiderText;
 
     [SerializeField] Text costText;
     [SerializeField] Image costItemImg;
@@ -50,18 +54,6 @@
 
         var keys = HorseManager.Instance.attrDic.Keys.ToList();
         keys.Sort();
-        for (int i = 0; i < attrNameTexts.Length; i++)
-        {
-            if (i < keys.Count)
-            {
-                var curValue = HorseManager.Instance.attrDic[keys[i]];
-                attrNameTexts[i].text = PlayerPropertyConfig.Get(keys[i]).Name;
-                attrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(keys[i], curValue, 2);
-
-                nextAttrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(keys[i],
-                    curValue + nextConfig.ClassAttrValueList[i] + nextConfig.PerLVAttrValueList[i], 2);
-            }
-        }
 
         var nextKeys = HorseManager.Instance.specialAttrDic.Keys.ToList();
         nextKeys.Sort();
@@ -92,6 +84,51 @@
         costText.text = UIHelper.ShowUseItem(PackType.Item, HorseManager.Instance.rankUPItemID, HorseClassConfig.Get(HorseManager.Instance.classLV).ClassUPItemCnt);
         costItemImg.SetItemSprite(HorseManager.Instance.rankUPItemID);
 
+        // 浣跨敤鏂版柟娉曡幏鍙栧綋鍓嶇殑鎬诲�煎拰灞炴�ч厤缃�
+        bool hasAttr = HorseManager.Instance.GetNowRiderTotalAttrInfo(out int attrID, out long curAttrValue, out PlayerPropertyConfig propConfig);
+
+        // 妫�鏌ュ睘鎬ф槸鍚﹀瓨鍦�
+        if (!hasAttr)
+        {
+            // 娌℃湁灞炴��
+            noRiderText.SetActive(true);
+            riderAttrRect.SetActive(false);
+        }
+        else
+        {
+            // 鏈夊睘鎬�
+            noRiderText.SetActive(false);
+            riderAttrRect.SetActive(true);
+            riderAttrNameText.text = propConfig.Name;
+            
+            // 褰撳墠闃剁殑灞炴�у��
+            riderAttrValueText.text = PlayerPropertyConfig.GetValueDescription(attrID, curAttrValue, 2);
+
+            // 棰勬祴涓嬩竴闃剁殑灞炴�у��
+            long nextAttrValue = curAttrValue;
+            
+            if (nextConfig.ClassSpecAttrIDList != null)
+            {
+                // 鍔犱笂涓嬩竴闃跺鍔犵殑 ClassSpecAttrValue
+                int index = Array.IndexOf(nextConfig.ClassSpecAttrIDList, attrID);
+                if (index >= 0 && nextConfig.ClassSpecAttrValueList != null && index < nextConfig.ClassSpecAttrValueList.Length)
+                {
+                    nextAttrValue += nextConfig.ClassSpecAttrValueList[index];
+                }
+            }
+
+            if (nextConfig.HorseEffAttrIDList != null)
+            {
+                // 鍔犱笂涓嬩竴闃跺鍔犵殑 HorseEffAttrValue
+                int effIndex = Array.IndexOf(nextConfig.HorseEffAttrIDList, attrID);
+                if (effIndex >= 0 && nextConfig.HorseEffAttrValueList != null && effIndex < nextConfig.HorseEffAttrValueList.Length)
+                {
+                    nextAttrValue += nextConfig.HorseEffAttrValueList[effIndex];
+                }
+            }
+
+            riderNextAttrValueText.text = PlayerPropertyConfig.GetValueDescription(attrID, nextAttrValue, 2);
+        }
     }
 
     //鍗囬樁
@@ -107,7 +144,7 @@
         var pack = new CB202_tagCSHorseClassUP();
         GameNetSystem.Instance.SendInfo(pack);
         CloseWindow();
-        
+
         if (!TimingGiftManager.Instance.TryAddWhenExactConsumption(12, PackType.Item, HorseManager.Instance.rankUPItemID, config.ClassUPItemCnt))
         {
             TimingGiftManager.Instance.TryAddWithFixedProbabilityWhenSufficient(12, PackType.Item, HorseManager.Instance.rankUPItemID, config.ClassUPItemCnt);
diff --git a/Main/System/Horse/HorseSkinCell.cs b/Main/System/Horse/HorseSkinCell.cs
index 2d67347..3f7cdab 100644
--- a/Main/System/Horse/HorseSkinCell.cs
+++ b/Main/System/Horse/HorseSkinCell.cs
@@ -32,7 +32,7 @@
     {
         skinID = _skinID;
         horseModel.Create(skinID, 0, 0.6f).Forget();
-        emptyImg.SetActive(skinID == 0);
+        emptyImg.SetActive(skinID == 0 || skinID == 999);
         usingObj.SetActive(HorseManager.Instance.GetUsingHorseSkinID() == skinID);
         bool isShowRed = HorseManager.Instance.IsShowTheHorseRedImg(skinID);
         redObj.SetActive(isShowRed);
diff --git a/Main/System/Horse/HorseSkinWin.cs b/Main/System/Horse/HorseSkinWin.cs
index e465bbe..5f865d9 100644
--- a/Main/System/Horse/HorseSkinWin.cs
+++ b/Main/System/Horse/HorseSkinWin.cs
@@ -1,5 +1,6 @@
 using System.Collections;
 using System.Collections.Generic;
+using System.Linq;
 using Cysharp.Threading.Tasks;
 using UnityEngine;
 using UnityEngine.UI;
@@ -23,8 +24,7 @@
     [SerializeField] Image lvUpItemImg;
     [SerializeField] Button changeSkinBtn;
     [SerializeField] Text timeText;
-    [SerializeField] Transform inSkinMarkObj;   //骞诲寲涓�
-
+    [SerializeField] Button removeBtn;  //瑙i櫎骞诲寲
     [SerializeField] Button unlockBtn;
     [SerializeField] Text unlockCostText;
     [SerializeField] Image unlockItemImg;
@@ -35,11 +35,15 @@
         lvUpBtn.AddListener(OnLvUpBtnClick);
         changeSkinBtn.AddListener(OnChangeSkinBtnClick);
         unlockBtn.AddListener(OnUnlockBtnClick);
+        removeBtn.AddListener(OnRemoveBtnClick);
     }
 
     protected override void OnPreOpen()
     {
-        HorseManager.Instance.selectSkinID = HorseManager.Instance.GetUsingHorseSkinID();
+        HorseManager.Instance.SortHorseSkinList();
+
+        int usingHorseSkinID = HorseManager.Instance.GetUsingHorseSkinID();
+        HorseManager.Instance.selectSkinID = usingHorseSkinID == 0 || !HorseManager.Instance.sortSkinList.Contains(usingHorseSkinID) ? HorseManager.Instance.sortSkinList[0] : usingHorseSkinID;
         HorseManager.Instance.SortHorseSkinList();
         HorseManager.Instance.OnSkinUpdateEvent += OnSkinUpdateEvent;
         HorseManager.Instance.OnSelectEvent += OnSelectEvent;
@@ -141,12 +145,12 @@
             if (HorseManager.Instance.selectSkinID == HorseManager.Instance.GetUsingHorseSkinID())
             {
                 changeSkinBtn.SetActive(false);
-                inSkinMarkObj.SetActive(true);
+                removeBtn.SetActive(true);
             }
             else
             {
                 changeSkinBtn.SetActive(true);
-                inSkinMarkObj.SetActive(false);
+                removeBtn.SetActive(false);
             }
 
             ShowTime();
@@ -211,12 +215,14 @@
         var _cell = cell as HorseSkinLineCell;
         _cell.Display(cell.index);
     }
-    
+
 
     void OnSeeAttrBtnClick()
     {
-        AttributeManager.Instance.OpenSimpleAttributeWin(HorseManager.Instance.skinAttrDic, "AttributeTitle04");
+        Dictionary<int, long> totalAttrDic = HorseManager.Instance.GetMergedAttrDic();
+        AttributeManager.Instance.OpenSimpleAttributeWin(totalAttrDic, "AttributeTitle04");
     }
+
 
 
     string GetSkinAttrSring(HorseSkinConfig config)
@@ -280,5 +286,9 @@
             HorseManager.Instance.SendSkinOP(1, HorseManager.Instance.selectSkinID);
         }
     }
-    
+
+    void OnRemoveBtnClick()
+    {
+        HorseManager.Instance.SendSkinOP(2, 0);
+    }
 }
\ No newline at end of file
diff --git a/Main/System/Horse/HorseSuccessWin.cs b/Main/System/Horse/HorseSuccessWin.cs
index f21c45d..b80df53 100644
--- a/Main/System/Horse/HorseSuccessWin.cs
+++ b/Main/System/Horse/HorseSuccessWin.cs
@@ -1,3 +1,4 @@
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
@@ -11,9 +12,6 @@
 {
     [SerializeField] Text curLVText;
     [SerializeField] Text nextLVText;
-    [SerializeField] Text[] attrNameTexts;
-    [SerializeField] Text[] attrValueTexts;
-    [SerializeField] Text[] nextAttrValueTexts;
 
     [SerializeField] Transform[] specialAttrRect;
     [SerializeField] Text[] specialAttrNameTexts;
@@ -21,6 +19,11 @@
     [SerializeField] Text[] specialNextAttrValueTexts;
     [SerializeField] Button okBtn;
 
+    [SerializeField] Transform riderAttrRect;
+    [SerializeField] Text riderAttrNameText;
+    [SerializeField] Text riderAttrValueText;
+    [SerializeField] Text riderNextAttrValueText;
+    [SerializeField] Text noRiderText;
 
 
     protected override void InitComponent()
@@ -49,17 +52,6 @@
 
         var keys = HorseManager.Instance.attrDic.Keys.ToList();
         keys.Sort();
-        for (int i = 0; i < attrNameTexts.Length; i++)
-        {
-            if (i < keys.Count)
-            {
-                var curValue = HorseManager.Instance.attrDic[keys[i]];
-                attrNameTexts[i].text = PlayerPropertyConfig.Get(keys[i]).Name;
-                attrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(keys[i], 
-                    curValue - nextConfig.ClassAttrValueList[i] - nextConfig.PerLVAttrValueList[i], 2);
-                nextAttrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(keys[i], curValue, 2);
-            }
-        }
 
         var nextKeys = HorseManager.Instance.specialAttrDic.Keys.ToList();
         nextKeys.Sort();
@@ -72,9 +64,9 @@
                 specialAttrNameTexts[i].text = PlayerPropertyConfig.Get(id).Name;
                 if (i < nextKeys.Count)
                 {
-                    specialAttrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(id, 
+                    specialAttrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(id,
                         HorseManager.Instance.specialAttrDic[nextKeys[i]] - nextConfig.ClassSpecAttrValueList[i], 2);
-                    specialNextAttrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(id, 
+                    specialNextAttrValueTexts[i].text = PlayerPropertyConfig.GetValueDescription(id,
                         HorseManager.Instance.specialAttrDic[nextKeys[i]], 2);
                 }
                 else
@@ -88,8 +80,52 @@
                 specialAttrRect[i].SetActive(false);
             }
         }
+        // 浣跨敤鏂版柟娉曡幏鍙栬繘闃躲�愬悗銆戠殑鏈�鏂版�诲�煎拰灞炴�ч厤缃�
+        bool hasAttr = HorseManager.Instance.GetNowRiderTotalAttrInfo(out int attrID, out long newAttrValue, out PlayerPropertyConfig propConfig);
 
+        // 妫�鏌ュ睘鎬ф槸鍚﹀瓨鍦�
+        if (!hasAttr)
+        {
+            // 娌℃湁灞炴��
+            noRiderText.SetActive(true);
+            riderAttrRect.SetActive(false);
+        }
+        else
+        {
+            // 鏈夊睘鎬�
+            noRiderText.SetActive(false);
+            riderAttrRect.SetActive(true);
+            riderAttrNameText.text = propConfig.Name;
 
+            // 璁$畻杩涢樁鍓嶇殑鏃у��
+            long oldAttrValue = newAttrValue; // 榛樿濡傛灉娌℃湁澧為噺锛屾棫鍊肩瓑浜庢柊鍊�
+
+            // nextConfig 鍙橀噺鍦ㄨ繖閲屽叾瀹炰唬琛ㄧ殑鏄�滃垰杈惧埌鐨勬柊闃剁骇閰嶇疆鈥�
+            if (nextConfig.ClassSpecAttrIDList != null)
+            {
+                // 鎵i櫎鍒氬鍔犵殑 ClassSpecAttrValue
+                int index = Array.IndexOf(nextConfig.ClassSpecAttrIDList, attrID);
+                if (index >= 0 && nextConfig.ClassSpecAttrValueList != null && index < nextConfig.ClassSpecAttrValueList.Length)
+                {
+                    oldAttrValue -= nextConfig.ClassSpecAttrValueList[index];
+                }
+            }
+
+            if (nextConfig.HorseEffAttrIDList != null)
+            {
+                // 鎵i櫎鍒氬鍔犵殑 HorseEffAttrValue
+                int effIndex = Array.IndexOf(nextConfig.HorseEffAttrIDList, attrID);
+                if (effIndex >= 0 && nextConfig.HorseEffAttrValueList != null && effIndex < nextConfig.HorseEffAttrValueList.Length)
+                {
+                    oldAttrValue -= nextConfig.HorseEffAttrValueList[effIndex];
+                }
+            }
+
+            // 宸﹁竟鏄剧ず鍗囬樁鍓嶇殑鏃у��
+            riderAttrValueText.text = PlayerPropertyConfig.GetValueDescription(attrID, oldAttrValue, 2);
+
+            // 鍙宠竟鏄剧ず鍗囬樁鍚庣殑鏂板��
+            riderNextAttrValueText.text = PlayerPropertyConfig.GetValueDescription(attrID, newAttrValue, 2);
+        }
     }
-
 }
\ No newline at end of file
diff --git a/Main/System/Horse/HorseWin.cs b/Main/System/Horse/HorseWin.cs
index 849a1d3..975f53d 100644
--- a/Main/System/Horse/HorseWin.cs
+++ b/Main/System/Horse/HorseWin.cs
@@ -14,7 +14,6 @@
     [SerializeField] HorseController modelImg;
     [SerializeField] UIEffectPlayer lvUPEffect;
     [SerializeField] Text nameText;
-    [SerializeField] Text specialAttrText;
     [SerializeField] Button skinBtn;
     [SerializeField] Text[] attrNameTexts;
     [SerializeField] Text[] attrValueTexts;
@@ -30,8 +29,20 @@
     [SerializeField] Text needUPText;
     [SerializeField] Button rankUpBtn;
 
+    [SerializeField] TextEx[] specialAttrNameTexts;
+    [SerializeField] TextEx[] specialAttrValueTexts;
 
-
+    [SerializeField] Button lastHorseBtn;
+    [SerializeField] Button nextHorseBtn;
+    [SerializeField] HorseCarouselView carouselView;
+    [SerializeField] ImageEx attrImg;
+    [SerializeField] TextEx attrTxt;
+    [SerializeField] TextEx noAttrTxt;
+    [SerializeField] ButtonEx unlockBtn;
+    [SerializeField] TextEx moneyTxt;
+    [SerializeField] ImageEx moneyImg;
+    [SerializeField] ButtonEx useBtn;
+    [SerializeField] TextEx usingTxt;
     int beforeLV;
 
     protected override void InitComponent()
@@ -44,6 +55,56 @@
         lvupBtn.onPress.AddListener(HorseUpgrade);
         quickUpToggle.onValueChanged.AddListener((bool value) => { OnToggle(value); });
         rankUpBtn.AddListener(HorseRankUpgrade);
+        lastHorseBtn.AddListener(OnLastHorse);
+        nextHorseBtn.AddListener(OnNextHorse);
+        useBtn.AddListener(() =>
+        {
+            HorseManager.Instance.SendHorseIDOP(carouselView.CurrentHorseId, 2);
+
+            if (!HorseSkinConfig.horseIDTohorseSkinIDDict.TryGetValue(carouselView.CurrentHorseId, out var skinID))
+                return;
+            bool isChangeState = HorseManager.Instance.IsChangeState(HorseManager.Instance.GetUsingHorseSkinID(false));
+            if (!isChangeState)
+            {
+                HorseManager.Instance.SendSkinOP(2, skinID);
+            }
+        });
+        unlockBtn.AddListener(() =>
+        {
+            if (!HorseSkinConfig.horseIDTohorseSkinIDDict.TryGetValue(carouselView.CurrentHorseId, out var skinID))
+                return;
+            var skinConfig = HorseSkinConfig.Get(skinID);
+            if (skinConfig == null)
+                return;
+
+            var horseConfig = HorseIDConfig.Get(carouselView.CurrentHorseId);
+            if (horseConfig == null)
+                return;
+
+            ConfirmCancel.MoneyIconToggleConfirmByType(
+                ToggleCheckType.Horse,
+                horseConfig.UnlockNeedCnt,
+                horseConfig.UnlockValue,
+                Language.Get("Horse20", UIHelper.GetIconNameWithMoneyType(horseConfig.UnlockValue), horseConfig.UnlockNeedCnt),
+                () =>
+                {
+                    if (!UIHelper.CheckMoneyCount(horseConfig.UnlockValue, horseConfig.UnlockNeedCnt, 2))
+                        return;
+                    HorseManager.Instance.unLockHorseID = carouselView.CurrentHorseId;
+                    HorseManager.Instance.SendHorseIDOP(carouselView.CurrentHorseId, 1);
+                    HorseManager.Instance.unLockSkinID = skinID;
+                });
+        });
+    }
+
+    void OnLastHorse()
+    {
+        carouselView?.SelectPrevious();
+    }
+
+    void OnNextHorse()
+    {
+        carouselView?.SelectNext();
     }
 
     protected override void OnPreOpen()
@@ -54,6 +115,20 @@
         HorseManager.Instance.OnHorseUpdateEvent += OnHorseUpdateEvent;
         PlayerDatas.Instance.playerDataRefreshEvent += PlayerDataRefresh;
         PackManager.Instance.RefreshItemEvent += OnRefreshItemEvent;
+        HorseManager.Instance.OnUpdateHorseIDInfoEvent += OnUpdateHorseIDInfoEvent;
+        carouselView.OnSelectedIndexChanged += OnSelectedIndexChanged;
+        HorseManager.Instance.OnHorseUnlockedEvent += OnHorseUnlockedEvent;
+
+        // 澶栭儴鍒濆鍖�
+        if (carouselView != null)
+        {
+            carouselView.InitPool();
+            int currentHorseID = HorseManager.Instance.horseID;
+            var horseConfigs = HorseManager.GetSortedHorseConfigs();
+            carouselView.InitHorseConfigs(horseConfigs);
+            int index = horseConfigs.FindIndex(c => c.HorseID == currentHorseID);
+            carouselView.InitWithHorse(index >= 0 ? index : 0);
+        }
 
         Display();
     }
@@ -63,6 +138,28 @@
         HorseManager.Instance.OnHorseUpdateEvent -= OnHorseUpdateEvent;
         PlayerDatas.Instance.playerDataRefreshEvent -= PlayerDataRefresh;
         PackManager.Instance.RefreshItemEvent -= OnRefreshItemEvent;
+        HorseManager.Instance.OnUpdateHorseIDInfoEvent -= OnUpdateHorseIDInfoEvent;
+        carouselView.OnSelectedIndexChanged -= OnSelectedIndexChanged;
+        HorseManager.Instance.OnHorseUnlockedEvent -= OnHorseUnlockedEvent;
+    }
+
+    private void OnHorseUnlockedEvent(int horseID)
+    {
+        if (!UIManager.Instance.IsOpened<GetHorseWin>())
+        {
+            UIManager.Instance.OpenWindowAsync<GetHorseWin>().Forget();
+        }
+    }
+
+    private void OnUpdateHorseIDInfoEvent()
+    {
+        Display();
+        carouselView.RefreshAllItems();
+    }
+
+    private void OnSelectedIndexChanged()
+    {
+        DisplayModel();
     }
 
     void OnHorseUpdateEvent()
@@ -113,12 +210,45 @@
         UIManager.Instance.OpenWindowAsync<HorseRankUPWin>().Forget();
     }
 
+    void DisplayModel()
+    {
+        int nowSkinID = HorseManager.Instance.GetUsingHorseSkinID(false);
+
+        int nowhorseID = HorseManager.Instance.horseID;
+        int showHorseID = carouselView.CurrentHorseId;
+        HorseSkinConfig.horseIDTohorseSkinIDDict.TryGetValue(showHorseID, out int horseSkinID);
+        var horseIdSkinConfig = HorseSkinConfig.Get(horseSkinID);
+
+        bool isChangeState = HorseManager.Instance.IsChangeState(nowSkinID);
+        modelImg.Create(isChangeState ? nowSkinID : horseSkinID, PhantasmPavilionManager.Instance.GetMyModelSkinID()).Forget();
+        nameText.text = isChangeState ? HorseSkinConfig.Get(nowSkinID).Name : horseIdSkinConfig.Name;
+        HorseIDConfig horseIDConfig = HorseIDConfig.Get(showHorseID);
+
+        bool hasAttr = HorseManager.Instance.GetRiderTotalAttrInfoByHorseID(showHorseID, out int attrID, out long value, out PlayerPropertyConfig playerPropertyConfig);
+        attrImg.SetActive(hasAttr);
+        noAttrTxt.SetActive(!hasAttr);
+        if (hasAttr)
+        {
+            attrTxt.text = StringUtility.Concat(playerPropertyConfig.ShowName, " ", "+", PlayerPropertyConfig.GetValueDescription(attrID, value));
+        }
+
+        useBtn.SetActive(carouselView.CurrentHorseId != nowhorseID && HorseManager.Instance.IsHorseUnlocked(carouselView.CurrentHorseId));
+        usingTxt.SetActive(carouselView.CurrentHorseId == nowhorseID);
+
+        bool isUnlock = HorseManager.Instance.IsHorseUnlocked(carouselView.CurrentHorseId);
+        unlockBtn.SetActive(!isUnlock);
+        if (!isUnlock)
+        {
+            moneyImg.SetIconWithMoneyType(horseIDConfig.UnlockValue);
+            moneyTxt.text = horseIDConfig.UnlockNeedCnt.ToString();
+        }
+
+    }
+
     void Display()
     {
-        var skinConfig = HorseSkinConfig.Get(HorseManager.Instance.GetUsingHorseSkinID());
-        modelImg.Create(skinConfig.SkinID, PhantasmPavilionManager.Instance.GetMyModelSkinID()).Forget();
-        nameText.text = skinConfig.Name;
-        specialAttrText.text = GetSpecialAttr();
+        DisplayModel();
+        DisplaySpecialAttr();
 
         var config = HorseClassConfig.Get(HorseManager.Instance.classLV);
         lvText.text = Language.Get("Horse8", HorseManager.Instance.classLV, HorseManager.Instance.horseLV);
@@ -195,17 +325,27 @@
         }
     }
 
-    string GetSpecialAttr()
+    public void DisplaySpecialAttr()
     {
-        if (HorseManager.Instance.specialAttrDic.Count == 0)
-            return "";
+        var specialAttrDic = HorseManager.Instance.specialAttrDic;
+        var attrs = specialAttrDic.Keys.ToList();
+        int arrtCnt = attrs.Count;
 
-        List<string> attrList = new List<string>();
-        foreach (var attrID in HorseManager.Instance.specialAttrDic.Keys)
+        for (int i = 0; i < specialAttrNameTexts.Length; i++)
         {
-            attrList.Add(UIHelper.AppendColor(TextColType.itemchuanqi, PlayerPropertyConfig.GetFullDescription(attrID, HorseManager.Instance.specialAttrDic[attrID])));
+            if (i < arrtCnt)
+            {
+                specialAttrNameTexts[i].SetActive(true);
+                specialAttrValueTexts[i].SetActive(true);
+                specialAttrNameTexts[i].text = PlayerPropertyConfig.Get(attrs[i]).Name;
+                specialAttrValueTexts[i].text = StringUtility.Concat("+", PlayerPropertyConfig.GetValueDescription(attrs[i], specialAttrDic.ContainsKey(attrs[i]) ? specialAttrDic[attrs[i]] : 0, 2));
+            }
+            else
+            {
+                specialAttrNameTexts[i].SetActive(false);
+                specialAttrValueTexts[i].SetActive(false);
+            }
         }
-        return Language.Get("L1100", Language.Get("herocard55"), string.Join(Language.Get("L1112"), attrList));
     }
 
     void OnToggle(bool value)
@@ -236,7 +376,7 @@
         switch (type)
         {
             case PlayerDataType.EquipShowSwitch:
-                var skinConfig = HorseSkinConfig.Get(HorseManager.Instance.GetUsingHorseSkinID());
+                var skinConfig = HorseSkinConfig.Get(HorseManager.Instance.GetUsingHorseSkinID(true));
                 modelImg.Create(skinConfig.SkinID, PhantasmPavilionManager.Instance.GetMyModelSkinID()).Forget();
                 nameText.text = skinConfig.Name;
                 break;
diff --git a/Main/System/KnapSack/PackManager.cs b/Main/System/KnapSack/PackManager.cs
index e35cb16..6c21ee8 100644
--- a/Main/System/KnapSack/PackManager.cs
+++ b/Main/System/KnapSack/PackManager.cs
@@ -6,6 +6,7 @@
 using System.Collections;
 using System.IO;
 using Cysharp.Threading.Tasks;
+using UnityEngine.Networking;
 
 public class PackManager : GameSystemManager<PackManager>
 {
@@ -523,7 +524,7 @@
 
     async UniTask ParsePackConfigIni()
     {
-        string[] lines = await LoadConfigIni("MapServerConfig.ini");
+        string[] lines = await LoadConfigIni("MapServerConfig");
         foreach (string line in lines)
         {
             if (line.StartsWith("PackCnt") && line.Contains("="))
@@ -541,26 +542,34 @@
         }
     }
 
-    public async UniTask<string[]> LoadConfigIni(string name)
+    public UniTask<string[]> LoadConfigIni(string name)
     {
-//         string path = string.Empty;
-// #if UNITY_EDITOR
-//         if (!AssetSource.isUseAssetBundle)
-//         {
-//             path = ResourcesPath.CONFIG_FODLER + "/" + name + ".ini";
-//         }
-//         else
-// #endif
-//         {
-//             //浠庢湇鍔$鎷疯礉鏄痠ni锛屾墦鍖呯敤txt缁熶竴澶勭悊
-//             path = AssetVersionUtility.GetAssetFilePath($"Config/{name}.txt");
-//         }
-
-        return await ResManager.Instance.LoadConfigAsync(name, false);
-
-        // return File.ReadAllLines(path);
+        return LoadConfigIniInternal(name);
     }
 
+    private async UniTask<string[]> LoadConfigIniInternal(string name)
+    {
+        string path;
+
+    #if UNITY_EDITOR
+        if (!AssetSource.isUseAssetBundle)
+        {
+            path = $"{ResourcesPath.CONFIG_FODLER}/{name}.ini";
+            return File.ReadAllLines(path);
+        }
+    #endif
+
+        path = AssetVersionUtility.GetAssetFilePath($"Config/{name}.txt");
+
+        using var req = UnityEngine.Networking.UnityWebRequest.Get(path);
+        await req.SendWebRequest();
+
+        if (req.result != UnityEngine.Networking.UnityWebRequest.Result.Success)
+            throw new Exception($"LoadConfigIni failed: {req.error}");
+
+        return req.downloadHandler.text
+            .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
+    }
     public int GetCanBuyPackGirdCount(PackType type)
     {
         if (!PackMaxCountDict.ContainsKey((int)type))
diff --git a/Main/System/Login/LoginWin.cs b/Main/System/Login/LoginWin.cs
index c774456..35f7b46 100644
--- a/Main/System/Login/LoginWin.cs
+++ b/Main/System/Login/LoginWin.cs
@@ -236,7 +236,7 @@
     {
         m_ServerName.text = _serverData.name.Replace("@gm", "");
         m_ServerIP = _serverData.region_domain;
-        m_Port = _serverData.login_port;
+        m_Port = _serverData.http_port;
         m_GamePort = _serverData.game_port;
 
         switch ((ServerState)_serverData.running_status)
diff --git a/Main/System/Login/ServerData.cs b/Main/System/Login/ServerData.cs
index fab893a..c38ecdd 100644
--- a/Main/System/Login/ServerData.cs
+++ b/Main/System/Login/ServerData.cs
@@ -14,6 +14,7 @@
 {
     public ServerGroup recommend;
     public ServerGroup[] common;
+    public ServerGroup[] crossserver;
 
     public bool FindServerData(int _id, out ServerData _serverData)
     {
@@ -81,8 +82,10 @@
     public int statue;
     public int is_recommend;
     public string region_domain;
-    public int login_port;
-    public int game_port;
+    public int login_port;   //鏃х殑 搴熷純 鐢ㄦ柊 http_port 浣嗘槸涓轰簡鍏煎鍒囨崲杩囩▼鍏堢暀鐫�锛屽悗缁悓姝ュ垹闄�
+    public int http_port;   //缃戦〉鐩稿叧鐨勮姹�
+    public int game_port;   //娓告垙socket鐨勭櫥褰曠鍙�
+    public int web_game_port;   //娓告垙web鐧诲綍绔彛
     public DateTime start_date;
     public int job;
     public string roleid;
diff --git a/Main/System/Login/ServerListCenter.cs b/Main/System/Login/ServerListCenter.cs
index faf1a59..69f826d 100644
--- a/Main/System/Login/ServerListCenter.cs
+++ b/Main/System/Login/ServerListCenter.cs
@@ -166,6 +166,24 @@
                 }
             }
         }
+
+        //璺ㄦ湇鏈嶅姟鍣� 涓嶅睍绀轰絾鏄彲浠ユ悳绱㈢敤
+        if (serverInfoCommon != null && serverInfoCommon.crossserver != null)
+        {
+            for (int i = 0; i < serverInfoCommon.crossserver.Length; i++)
+            {
+                var group = serverInfoCommon.crossserver[i];
+                for (int j = 0; j < group.group_list.Length; j++)
+                {
+                    var serverData = group.group_list[j];
+                    if (serverData.region_flag == _id)
+                    {
+                        return serverData;
+                    }
+                }
+            }
+        }
+
         
         //浠庣櫧鍚嶅崟鐨勬湇鍔″櫒琛ㄤ腑鏌ユ壘锛堟祴璇曠敤锛�
         if (serverInfoPlayer != null && serverInfoPlayer.gametest != null && serverInfoPlayer.gametest.group_list != null)
@@ -204,7 +222,11 @@
         {
             return $"{defaultHead}{data.region_domain}:{replacePort}";
         }
-        return $"{defaultHead}{data.region_domain}:{data.login_port}";
+
+        //鏃х殑鍏煎
+        if (data.login_port > 0)
+            return $"{defaultHead}{data.region_domain}:{data.login_port}";
+        return $"{defaultHead}{data.region_domain}:{data.http_port}";
 
     }
 
@@ -493,7 +515,7 @@
                         statue = serverData.statue,
                         is_recommend = serverData.is_recommend,
                         region_domain = serverData.region_domain,
-                        login_port = serverData.login_port,
+                        http_port = serverData.http_port,
                         game_port = serverData.game_port,
                         start_date = serverData.start_date,
                         job = originalData.job,
diff --git a/Main/System/Main/AutoFightModel.cs b/Main/System/Main/AutoFightModel.cs
index 5a97ca6..acaf4e3 100644
--- a/Main/System/Main/AutoFightModel.cs
+++ b/Main/System/Main/AutoFightModel.cs
@@ -267,6 +267,7 @@
     {
         nowChallengeCount = 0;
         isAutoExchangeDecomposeOld = true;
+        CheckAndResetExpiredCardSettings();
     }
 
     Dictionary<string, int> winWaitCloseDict = new Dictionary<string, int>();
@@ -574,10 +575,41 @@
         UpdateRedpint();
     }
 
+    /// <summary>
+    /// 妫�鏌ュ苟閲嶇疆鏈堝崱杩囨湡鍚庣殑鐗规潈璁剧疆
+    /// </summary>
+    void CheckAndResetExpiredCardSettings()
+    {
+        // 鏈堝崱杩囨湡鏃堕噸缃�熷害鍜岄噸璇曟鏁�
+        if (!InvestModel.Instance.IsInvested(InvestModel.monthCardType))
+        {
+            // 濡傛灉褰撳墠閫熷害鏄湀鍗′笓灞炵殑3鍊嶉�燂紝閲嶇疆涓�1鍊嶉��
+            // 鐩存帴鎿嶄綔QuickSetting锛岀粫杩噑toryBattleField鍙兘涓簄ull鐨勯棶棰�
+            int savedSpeed = QuickSetting.Instance.GetQuickSettingValue<int>(QuickSettingType.AutoFight_Speed, 0);
+            if (savedSpeed > 2)
+            {
+                QuickSetting.Instance.SetQuickSetting(QuickSettingType.AutoFight_Speed, 1);
+                if (BattleManager.Instance.storyBattleField != null)
+                {
+                    BattleManager.Instance.storyBattleField.SetSpeedRatio(BattleManager.Instance.speedGear[0]);
+                }
+            }
+            
+            // 濡傛灉褰撳墠閲嶈瘯娆℃暟瓒呰繃闈炴湀鍗¢檺鍒讹紝閲嶇疆涓�1
+            int savedTry = QuickSetting.Instance.GetQuickSettingValue<int>(QuickSettingType.AutoFight_TryChallengeCount, 0);
+            if (savedTry > 1)
+            {
+                QuickSetting.Instance.SetQuickSetting(QuickSettingType.AutoFight_TryChallengeCount, 1);
+            }
+        }
+    }
+
     void OnInvestUpdate(int type)
     {
         if (type > 2)
             return;
+        
+        CheckAndResetExpiredCardSettings();
         UpdateRedpint();
     }
 }
diff --git a/Main/System/Main/FightPowerManager.cs b/Main/System/Main/FightPowerManager.cs
index 8713b32..9454ffc 100644
--- a/Main/System/Main/FightPowerManager.cs
+++ b/Main/System/Main/FightPowerManager.cs
@@ -82,7 +82,7 @@
     // public Dictionary<string, int> lineUpPerDict = new Dictionary<string, int>();  //闃靛灞炴�у姞鎴�
     public Dictionary<int, int> countryAttrs = new Dictionary<int, int>();   //闃靛鍥藉锛堝厜鐜級灞炴��
     public Dictionary<int, long> minggeAttrs = new Dictionary<int, long>();   //鍛芥牸灞炴��
-
+    public Dictionary<int, long> djgAttrs = new Dictionary<int, long>();   //瀹氬啗闃佸睘鎬�
     double allHeroAddPer = 0;  //鎵�鏈夋灏嗗姞鎴�
 
     //绛夌骇灞炴��
@@ -340,8 +340,10 @@
         var beautyPer = BeautyMMManager.Instance.GetAttrPer(attrType) / 10000.0;
         var fatesValue = HeroFatesManager.Instance.GetAttrValue(attrType);
         var fatesPer = HeroFatesManager.Instance.GetAttrPer(attrType) / 10000.0;
-        var dingjungeValue = 0; //榛樿涓嶉渶瑕佸姞锛岀埇濉旂壒娈婄敤锛岄厤鍚堝叕寮�
-        var dingjungePer = 0;   //榛樿涓嶉渶瑕佸姞锛岀埇濉旂壒娈婄敤锛岄厤鍚堝叕寮�
+
+        djgAttrs.TryGetValue(attrType, out var dingjungeValue);
+        var dingjungePer = GetAttrPer(attrType, djgAttrs) / 10000.0;   //榛樿涓嶉渶瑕佸姞锛岀埇濉旂壒娈婄敤锛岄厤鍚堝叕寮�
+
         minggeAttrs.TryGetValue(attrType, out var minggeValue);
         var minggePer = GetAttrPer(attrType, minggeAttrs) / 10000.0;
         
@@ -397,7 +399,7 @@
         var horseValue = HorseManager.Instance.GetAttrValue(attrType);
         var beautyValue = BeautyMMManager.Instance.GetAttrValue(attrType);
         var fatesValue = HeroFatesManager.Instance.GetAttrValue(attrType);
-        var dingjungeValue = 0; //榛樿涓嶉渶瑕佸姞锛岀埇濉旂壒娈婄敤锛岄厤鍚堝叕寮�
+        djgAttrs.TryGetValue(attrType, out var dingjungeValue);
         minggeAttrs.TryGetValue(attrType, out var minggeValue);
 
         //闃靛鍏夌幆 涓夊洿鐧惧垎姣斿姞鎴�
@@ -487,7 +489,8 @@
         RefreshOfficialAttrs();
         RefrehEquipAttrs();
         RefrehMinggeAttrs();
-
+        djgAttrs.Clear();
+        
         bool diffFP = lastFightPower != PlayerDatas.Instance.baseData.FightPower;   //鎴樺姏鏄惁鏈夊彉鍖�
         if (diffFP || calcType == 0)
         {
@@ -541,6 +544,7 @@
     public long CalculateTeamHeroPower(HeroInfo hero)
     {
         hero.RefreshFetterAttrsWhenCalcPower(teamTypeCalc); //缇佺粖灞炴�ц瀹炴椂绠�
+        hero.RefreshInheritPer();
 
         var Atk = GetPropertyVaule(6, hero);
         var Def = GetPropertyVaule(7, hero);
@@ -811,6 +815,7 @@
         RefrehMinggeAttrs();
         RefrehEquipAttrs();
         RefreshTeamAttrs();
+        djgAttrs.Clear();
 
         var fightPower = CalculateTeamHeroPower(heroInfo);
         fightPower += GetMinggeSkillPower();
diff --git a/Main/System/Main/HomeWin.cs b/Main/System/Main/HomeWin.cs
index 50b0424..4e1ad8d 100644
--- a/Main/System/Main/HomeWin.cs
+++ b/Main/System/Main/HomeWin.cs
@@ -342,7 +342,10 @@
         {
             DisplayHeroReturn();
         }
-
+        else if (type == OperationType.TotalRecharge || type == OperationType.TotDayRecharge)
+        {
+            DisplayGalaBtn();
+        }
     }
 
     private void OpenServerActivityStateChange()
@@ -350,6 +353,7 @@
         DisplayTimeRush();
         DisplayHeroDebut();
         DisplayHeroReturn();
+        DisplayGalaBtn();
     }
 
     private void OnShowGiftIdListAddEvent()
@@ -898,7 +902,17 @@
             horseBGImg.SetActive(true);
             //equipShowSwitch;//褰撳墠閰嶇疆鐨勫潗楠戝瑙侷D瀛樺偍鍦紙鏈�澶ф敮鎸� 1~999锛�
             var skinConfig = HorseSkinConfig.Get(HorseManager.Instance.GetUsingHorseSkinID(true));
-            horseImg.Create(skinConfig.SkinID, 0, 0.6f).Forget();
+            if (skinConfig.SkinID == 999)
+            {
+                int nowhorseID = HorseManager.Instance.horseID;
+                HorseSkinConfig.horseIDTohorseSkinIDDict.TryGetValue(nowhorseID, out int horseSkinID);
+                var horseIdSkinConfig = HorseSkinConfig.Get(horseSkinID);
+                horseImg.Create(horseIdSkinConfig.SkinID, 0, 0.6f).Forget();
+            }
+            else
+            {
+                horseImg.Create(skinConfig.SkinID, 0, 0.6f).Forget();
+            }
             horseLVText.text = Language.Get("Horse8", HorseManager.Instance.classLV, HorseManager.Instance.horseLV);
         }
         else
@@ -922,7 +936,7 @@
         osHeroTrainBtn.SetActive(OSActivityManager.Instance.IsOpened(7));
         osBeautyMMBtn.SetActive(OSActivityManager.Instance.IsOpened(8));
         osMinggeBtn.SetActive(OSActivityManager.Instance.IsOpened(9));
-        osGalaBtn.SetActive(OSActivityManager.Instance.IsOpenedOSGala());
+        DisplayGalaBtn();
     }
 
     void OnDayEvent()
@@ -930,6 +944,11 @@
         DisplayOSActivity();
     }
 
+    void DisplayGalaBtn()
+    {
+        bool isGalaOpen = TotDayRechargeManager.Instance.IsOpen || TotalRechargeManager.Instance.IsOpen;
+        osGalaBtn.SetActive(OSActivityManager.Instance.IsOpenedOSGala() || isGalaOpen);
+    }
 
     void DisplayTimeRush()
     {
diff --git a/Main/System/Main/MainWin.cs b/Main/System/Main/MainWin.cs
index 6bec7ea..fdbee9e 100644
--- a/Main/System/Main/MainWin.cs
+++ b/Main/System/Main/MainWin.cs
@@ -1,9 +1,9 @@
 锘縰sing System;
 using System.Collections;
 using System.Collections.Generic;
+using Cysharp.Threading.Tasks;
 using UnityEngine;
 using UnityEngine.UI;
-using Cysharp.Threading.Tasks;
 
 /// <summary>
 /// 娓告垙涓荤晫闈㈠簳閮ㄥ姛鑳芥寜閽�
@@ -41,6 +41,7 @@
     protected override void InitComponent()
     {
         base.InitComponent();
+        InGameDownLoad.Instance.OnPlayerLoginOk().Forget();
         avatarCell.SetOnLoaded(() =>
         {
             avatarCell.redpoint.redpointId = MainRedDot.PhantasmPavilionRepoint;
diff --git a/Main/System/Message/GMNotify.cs b/Main/System/Message/GMNotify.cs
index 05d82d6..86cbd4c 100644
--- a/Main/System/Message/GMNotify.cs
+++ b/Main/System/Message/GMNotify.cs
@@ -84,7 +84,7 @@
     private void Notify(GMNotifyMessgae _notify)
     {
         ServerTipDetails.ShowMarquee(_notify.message, null, 10);
-        ChatManager.Instance.AddSysData(_notify.message, infoArray, ChatChannel.World, false);
+        ChatManager.Instance.AddSysData(_notify.message, infoArray, ChatChannel.World);
     }
 
     private bool CheckNotify(GMNotifyMessgae _notify)
diff --git a/Main/System/Message/SysNotifyMgr.cs b/Main/System/Message/SysNotifyMgr.cs
index f9aa613..04ee321 100644
--- a/Main/System/Message/SysNotifyMgr.cs
+++ b/Main/System/Message/SysNotifyMgr.cs
@@ -241,11 +241,14 @@
                 case SysNotifyType.SysMarqueeTip:
                     ServerTipDetails.ShowMarquee(msg, tipInfoList, order);
                     break;
+                case SysNotifyType.SysBulletScreen:
+                    ChatManager.Instance.SendPureBullet(msg, tipInfoList);
+                    break;
                 case SysNotifyType.ChatChannelWorld:
-                    ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.World, true);
+                    ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.World);
                     break;
                 case SysNotifyType.ChatChannelGuild:
-                    ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.Guild, true);
+                    ChatManager.Instance.AddSysData(msg, tipInfoList, ChatChannel.Guild);
                     break;
                 case SysNotifyType.SysRealmTip:
                     if (OnSysTipEvent != null)
@@ -278,6 +281,7 @@
         SysChatWin = 6, //鑱婂ぉ浣嶇疆鐨勬彁绀�
         SysEvenKill = 7,//涓婂彜鎴樺満杩炴潃鎻愮ず
         SysFixedTip1 = 11,//鍥哄畾鎻愮ず2
+        SysBulletScreen = 19,//寮瑰箷
         ChatChannelWorld = 20,//鑱婂ぉ-涓栫晫棰戦亾
         ChatChannelGuild = 21,//鑱婂ぉ-鍏細棰戦亾
         SysFairyQuestionTip = 31,//浠欑洘棰戦亾闂瓟鎻愮ず
diff --git a/Main/System/OSActivity/OSActivityManager.cs b/Main/System/OSActivity/OSActivityManager.cs
index c2ca0a3..56002d0 100644
--- a/Main/System/OSActivity/OSActivityManager.cs
+++ b/Main/System/OSActivity/OSActivityManager.cs
@@ -232,7 +232,7 @@
     public void UpdateRedpoint()
     {
         osMainLevelRedpoint.state = !DayRemind.Instance.GetDayRemind(DayRemind.OSMainLevel) ? RedPointState.Simple : RedPointState.None;
-        osGalaRedpoint2.state = !DayRemind.Instance.GetDayRemind(DayRemind.OSGalaChange) ? RedPointState.Simple : RedPointState.None;
+        osGalaRedpoint2.state = IsOpenedOSGala() && !DayRemind.Instance.GetDayRemind(DayRemind.OSGalaChange) ? RedPointState.Simple : RedPointState.None;
         osHeroTrainRedpoint.state = !DayRemind.Instance.GetDayRemind(DayRemind.OSMainLevel) ? RedPointState.Simple : RedPointState.None;
         osBeautyMMRedpoint.state = !DayRemind.Instance.GetDayRemind(DayRemind.OSMainLevel) ? RedPointState.Simple : RedPointState.None;
         osMinggeRedpoint.state = !DayRemind.Instance.GetDayRemind(DayRemind.OSMainLevel) ? RedPointState.Simple : RedPointState.None;
diff --git a/Main/System/OSActivity/OSGalaBaseWin.cs b/Main/System/OSActivity/OSGalaBaseWin.cs
index e6f5da9..47dec38 100644
--- a/Main/System/OSActivity/OSGalaBaseWin.cs
+++ b/Main/System/OSActivity/OSGalaBaseWin.cs
@@ -4,6 +4,7 @@
 //--------------------------------------------------------
 
 
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using UnityEngine;
@@ -12,36 +13,170 @@
 
 
 ////寮�鏈嶇洓鍏�
-public class OSGalaBaseWin : FunctionsBaseWin
+public class OSGalaBaseWin : UIBase
 {
+    [SerializeField] Transform moneyTrans2;
+    [SerializeField] Transform galaTrans;
+    [SerializeField] ScrollerController tabScroller;
     [SerializeField] Image processImg;
-    [SerializeField] Text timeText;
+    [SerializeField] Text galaTimeText;
     [SerializeField] Text totalScoreText;
     [SerializeField] ItemCell[] itemCells;
     [SerializeField] Image[] gotImgs;
     [SerializeField] Text[] scoreTexts;
     [SerializeField] UIEffectPlayer[] effectPlayers;
 
+    [SerializeField] Transform totalRechargeTrans;
+    [SerializeField] Text totalRechargeTimeText;
+    [SerializeField] ItemCell totalRechargeItemCell;
+    [SerializeField] Text totalRechargeScoreText;
+    [SerializeField] RotationTween totalRechargeRotationTween;
+    [SerializeField] Image totalRechargeFreeRedImage;
+    [SerializeField] Image totalRechargeHaveImage;
+
+    [SerializeField] Transform totDayRechargeTrans;
+    [SerializeField] Text totDayRechargeTimeText;
+    [SerializeField] ItemCell totDayRechargeItemCell;
+    [SerializeField] Text totDayRechargeScoreText;
+    [SerializeField] RotationTween totDayRechargeRotationTween;
+    [SerializeField] Image totDayRechargeFreeRedImage;
+    [SerializeField] Image totDayRechargeHaveImage;
+
+    private int nowTabId = 0;
+    private UIBase currentSubUI;
+    private List<int> tabIdList = new List<int> { 0, 1, 2, 3, 4 };
+    private Dictionary<int, string> tabTitleKeys = new Dictionary<int, string>
+    {
+        { 0, "DayMission1" },
+        { 1, "OSActivity9" },
+        { 2, "OSActivity3" },
+        { 3, "TotalRecharge04" },
+        { 4, "TotalRecharge05" },
+    };
+    private Dictionary<int, int> tabRedpointKeys = new Dictionary<int, int>
+    {
+        { 0, 1131 },
+        { 1, 1132 },
+        { 2, 1133 },
+        { 3, 1135 },
+        { 4, 1136 },
+    };
 
     protected override void OnPreOpen()
     {
-        base.OnPreOpen();
+        tabScroller.OnRefreshCell += OnRefreshTabCell;
         OSActivityManager.Instance.OnOSGalaDataChangeEvent += OnOSGalaDataChangeEvent;
         GlobalTimeEvent.Instance.secondEvent += ShowTime;
+        StoreModel.Instance.RefreshBuyShopLimitEvent += OnRefreshBuyShopLimitEvent;
+        TotalRechargeManager.Instance.OnTotalRechargePlayerInfoEvent += OnTotalRechargePlayerInfoEvent;
+        TotDayRechargeManager.Instance.OnTotDayRechargePlayerInfoEvent += OnTotDayRechargePlayerInfoEvent;
+        CreateTabScroller();
         Display();
     }
 
     protected override void OnPreClose()
     {
-        base.OnPreClose();
+        tabScroller.OnRefreshCell -= OnRefreshTabCell;
         OSActivityManager.Instance.OnOSGalaDataChangeEvent -= OnOSGalaDataChangeEvent;
         GlobalTimeEvent.Instance.secondEvent -= ShowTime;
+        StoreModel.Instance.RefreshBuyShopLimitEvent -= OnRefreshBuyShopLimitEvent;
+        TotalRechargeManager.Instance.OnTotalRechargePlayerInfoEvent -= OnTotalRechargePlayerInfoEvent;
+        TotDayRechargeManager.Instance.OnTotDayRechargePlayerInfoEvent -= OnTotDayRechargePlayerInfoEvent;
+        CloseCurrentSubUI();
     }
 
-
-    protected override async void OpenSubUIByTabIndex()
+    private void OnTotDayRechargePlayerInfoEvent()
     {
-        switch (functionOrder)
+        tabScroller.m_Scorller.RefreshActiveCellViews();
+        RefreshRechargeTransData();
+        Display();
+    }
+
+    private void OnTotalRechargePlayerInfoEvent()
+    {
+        tabScroller.m_Scorller.RefreshActiveCellViews();
+        RefreshRechargeTransData();
+        Display();
+    }
+
+    private void OnRefreshBuyShopLimitEvent()
+    {
+        tabScroller.m_Scorller.RefreshActiveCellViews();
+        RefreshRechargeTransData();
+        Display();
+    }
+
+    private void CreateTabScroller()
+    {
+        tabScroller.Refresh();
+        bool isOSGalaOpen = OSActivityManager.Instance.IsOpenedOSGala();
+        bool isTotDayRechargeOpen = TotDayRechargeManager.Instance.IsOpen;
+        bool isTotalRechargeOpen = TotalRechargeManager.Instance.IsOpen;
+        List<int> visibleTabs = new List<int>();
+        for (int i = 0; i < tabIdList.Count; i++)
+        {
+            int tabId = tabIdList[i];
+            bool canShow = false;
+            if (tabId == 0 || tabId == 1 || tabId == 2)
+            {
+                canShow = isOSGalaOpen;
+            }
+            else if (tabId == 3)
+            {
+                canShow = isTotalRechargeOpen;
+            }
+            else if (tabId == 4)
+            {
+                canShow = isTotDayRechargeOpen;
+            }
+            if (canShow)
+            {
+                visibleTabs.Add(tabId);
+                tabScroller.AddCell(ScrollerDataType.Header, tabId);
+            }
+        }
+        if (visibleTabs.Count > 0)
+        {
+            nowTabId = visibleTabs[0];
+        }
+        tabScroller.Restart();
+        SelectBottomTab(nowTabId);
+    }
+
+    private void OnRefreshTabCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell.GetComponent<OSGalaTabCell>();
+        string titleKey = tabTitleKeys.ContainsKey(cell.index) ? tabTitleKeys[cell.index] : "";
+        int redpointId = tabRedpointKeys.ContainsKey(cell.index) ? tabRedpointKeys[cell.index] : 0;
+        _cell?.Display(cell.index, nowTabId, titleKey, redpointId, OnTabClicked);
+    }
+
+    private void OnTabClicked(int index)
+    {
+        if (nowTabId == index)
+        {
+            return;
+        }
+        nowTabId = index;
+        tabScroller.m_Scorller.RefreshActiveCellViews();
+        SelectBottomTab(index).Forget();
+    }
+
+    private async UniTaskVoid SelectBottomTab(int index)
+    {
+        if (currentSubUI != null)
+        {
+            currentSubUI.CloseWindow();
+            currentSubUI = null;
+        }
+
+        galaTrans.SetActive(index == 0 || index == 1 || index == 2);
+        moneyTrans2.SetActive(index == 0 || index == 1 || index == 2);
+
+        totalRechargeTrans.SetActive(index == 3);
+        totDayRechargeTrans.SetActive(index == 4);
+
+        switch (index)
         {
             case 0:
                 currentSubUI = await UIManager.Instance.OpenWindowAsync<OSGalaMissionWin>();
@@ -52,6 +187,128 @@
             case 2:
                 currentSubUI = await UIManager.Instance.OpenWindowAsync<OSGalaGiftWin>();
                 break;
+            case 3:
+                currentSubUI = await UIManager.Instance.OpenWindowAsync<TotalRechargeWin>();
+
+                var data = TotalRechargeManager.Instance.GetStoreData();
+                bool isReceived = TotalRechargeManager.Instance.IsReceived(data.shopId);
+                totalRechargeItemCell.Init(new ItemCellModel(data.storeConfig.ItemID, false, data.storeConfig.ItemCnt));
+                totalRechargeItemCell.button.SetListener(() =>
+                {
+                    if (!isReceived)
+                    {
+                        StoreModel.Instance.SendBuyShopItem(data.storeConfig, 1);
+                    }
+                    else
+                    {
+                        ItemTipUtility.Show(data.storeConfig.ItemID);
+                    }
+
+                });
+
+                totalRechargeHaveImage.SetActive(isReceived);
+                totalRechargeFreeRedImage.SetActive(!isReceived);
+                totalRechargeTimeText.text = TotalRechargeManager.Instance.GetActTimeStr();
+                totalRechargeScoreText.text = Language.Get("TotalRecharge06", TotalRechargeManager.Instance.coinTotal);
+                if (!isReceived)
+                {
+                    totalRechargeRotationTween.Play();
+                }
+                else
+                {
+                    totalRechargeRotationTween.Stop();
+                    totalRechargeRotationTween.SetStartState();
+                }
+                break;
+            case 4:
+                currentSubUI = await UIManager.Instance.OpenWindowAsync<TotDayRechargeWin>();
+
+                var data1 = TotDayRechargeManager.Instance.GetStoreData();
+                bool isReceived1 = TotDayRechargeManager.Instance.IsReceived(data1.shopId);
+                totDayRechargeItemCell.Init(new ItemCellModel(data1.storeConfig.ItemID, false, data1.storeConfig.ItemCnt));
+                totDayRechargeItemCell.button.SetListener(() =>
+                {
+                    if (!isReceived1)
+                    {
+                        StoreModel.Instance.SendBuyShopItem(data1.storeConfig, 1);
+                    }
+                    else
+                    {
+                        ItemTipUtility.Show(data1.storeConfig.ItemID);
+                    }
+
+                });
+
+                totDayRechargeHaveImage.SetActive(isReceived1);
+                totDayRechargeFreeRedImage.SetActive(!isReceived1);
+                totDayRechargeTimeText.text = TotDayRechargeManager.Instance.GetActTimeStr();
+                totDayRechargeScoreText.text = Language.Get("TotalRecharge07", TotDayRechargeManager.Instance.totalDays);
+                if (!isReceived1)
+                {
+                    totDayRechargeRotationTween.Play();
+                }
+                else
+                {
+                    totDayRechargeRotationTween.Stop();
+                    totDayRechargeRotationTween.SetStartState();
+                }
+                break;
+        }
+    }
+
+    private void CloseCurrentSubUI()
+    {
+        if (currentSubUI != null)
+        {
+            currentSubUI.CloseWindow();
+            currentSubUI = null;
+        }
+    }
+
+    /// <summary>
+    /// 鍒锋柊绱鍏呭�煎拰姣忔棩鍏呭�肩晫闈㈢殑鏁版嵁锛堜笉閲嶆柊鍒涘缓鐣岄潰锛�
+    /// </summary>
+    private void RefreshRechargeTransData()
+    {
+        // 鍒锋柊绱鍏呭�兼暟鎹紙tab 3锛�
+        if (nowTabId == 3)
+        {
+            var data = TotalRechargeManager.Instance.GetStoreData();
+            bool isReceived = TotalRechargeManager.Instance.IsReceived(data.shopId);
+            totalRechargeItemCell.Init(new ItemCellModel(data.storeConfig.ItemID, false, data.storeConfig.ItemCnt));
+            totalRechargeHaveImage.SetActive(isReceived);
+            totalRechargeFreeRedImage.SetActive(!isReceived);
+            totalRechargeTimeText.text = TotalRechargeManager.Instance.GetActTimeStr();
+            totalRechargeScoreText.text = Language.Get("TotalRecharge06", TotalRechargeManager.Instance.coinTotal);
+            if (!isReceived)
+            {
+                totalRechargeRotationTween.Play();
+            }
+            else
+            {
+                totalRechargeRotationTween.Stop();
+                totalRechargeRotationTween.SetStartState();
+            }
+        }
+        // 鍒锋柊姣忔棩鍏呭�兼暟鎹紙tab 4锛�
+        else if (nowTabId == 4)
+        {
+            var data1 = TotDayRechargeManager.Instance.GetStoreData();
+            bool isReceived1 = TotDayRechargeManager.Instance.IsReceived(data1.shopId);
+            totDayRechargeItemCell.Init(new ItemCellModel(data1.storeConfig.ItemID, false, data1.storeConfig.ItemCnt));
+            totDayRechargeHaveImage.SetActive(isReceived1);
+            totDayRechargeFreeRedImage.SetActive(!isReceived1);
+            totDayRechargeTimeText.text = TotDayRechargeManager.Instance.GetActTimeStr();
+            totDayRechargeScoreText.text = Language.Get("TotalRecharge07", TotDayRechargeManager.Instance.totalDays);
+            if (!isReceived1)
+            {
+                totDayRechargeRotationTween.Play();
+            }
+            else
+            {
+                totDayRechargeRotationTween.Stop();
+                totDayRechargeRotationTween.SetStartState();
+            }
         }
     }
 
@@ -124,17 +381,19 @@
             }
         }
     }
-    
+
     void ShowTime()
     {
         if (TimeUtility.OpenDay >= OSActivityManager.Instance.osGalaOpenDays)
         {
-            timeText.text = Language.Get("OSActivity6");
+            galaTimeText.text = Language.Get("OSActivity6");
         }
         else
         {
-            timeText.text = Language.Get("OSActivity10") + TimeUtility.SecondsToShortDHMS(TimeUtility.GetRemindTimeByOpenDay(OSActivityManager.Instance.osGalaOpenDays));
+            galaTimeText.text = Language.Get("OSActivity10") + TimeUtility.SecondsToShortDHMS(TimeUtility.GetRemindTimeByOpenDay(OSActivityManager.Instance.osGalaOpenDays));
         }
+        totalRechargeTimeText.text = TotalRechargeManager.Instance.GetActTimeStr();
+        totDayRechargeTimeText.text = TotDayRechargeManager.Instance.GetActTimeStr();
     }
 }
 
diff --git a/Main/System/OSActivity/OSGalaGiftCell.cs b/Main/System/OSActivity/OSGalaGiftCell.cs
index 08369e9..0197f6f 100644
--- a/Main/System/OSActivity/OSGalaGiftCell.cs
+++ b/Main/System/OSActivity/OSGalaGiftCell.cs
@@ -164,7 +164,7 @@
                 {
                     moneyIcon.SetIconWithMoneyType(storeConfig.MoneyType);
                 }
-                redImg.SetActive(storeConfig.MoneyNum == 0);
+                redImg.SetActive(storeConfig.MoneyNum == 0 && OSActivityManager.Instance.IsOpenedOSGala(false));
             }
             var buyCnt = StoreModel.Instance.GetShopLimitBuyCount(id);
             buyLimitText.text = Language.Get("storename6", storeConfig.LimitCnt - buyCnt, storeConfig.LimitCnt);
diff --git a/Main/System/OSActivity/OSGalaTabCell.cs b/Main/System/OSActivity/OSGalaTabCell.cs
new file mode 100644
index 0000000..fbc9916
--- /dev/null
+++ b/Main/System/OSActivity/OSGalaTabCell.cs
@@ -0,0 +1,32 @@
+using System;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class OSGalaTabCell : MonoBehaviour
+{
+    [SerializeField] Color unSelectColor;
+    [SerializeField] Color selectColor;
+    [SerializeField] ImageEx bgImage;
+    [SerializeField] TextEx titleText;
+    [SerializeField] RedpointBehaviour redpoint;
+    [SerializeField] ButtonEx tabButton;
+
+    private Action<int> onClick;
+
+    public void Display(int index, int selectedIndex, string title, int redpointId, Action<int> onClick)
+    {
+        this.onClick = onClick;
+        bool isSelected = index == selectedIndex;
+
+        bgImage.SetSprite(isSelected ? "TimeRushTabSelect" : "TimeRushTabUnSelect");
+        titleText.text = Language.Get(title);
+        titleText.color = isSelected ? selectColor : unSelectColor;
+
+        redpoint.redpointId = redpointId;
+
+        tabButton.SetListener(() =>
+        {
+            onClick?.Invoke(index);
+        });
+    }
+}
\ No newline at end of file
diff --git a/Main/System/OSActivity/OSGalaTabCell.cs.meta b/Main/System/OSActivity/OSGalaTabCell.cs.meta
new file mode 100644
index 0000000..2c193e5
--- /dev/null
+++ b/Main/System/OSActivity/OSGalaTabCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 3e7742ee2b0612c43bac55038ea42ed0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/OSActivity/OperationTotDayRechargeInfo.cs b/Main/System/OSActivity/OperationTotDayRechargeInfo.cs
new file mode 100644
index 0000000..d81f74c
--- /dev/null
+++ b/Main/System/OSActivity/OperationTotDayRechargeInfo.cs
@@ -0,0 +1,21 @@
+锘縰sing System.Collections.Generic;
+
+
+//绱厖娲诲姩
+public class OperationTotDayRechargeInfo : OperationBase
+{
+    public int CfgID;   // 娲诲姩鏃堕棿琛ㄩ厤缃甀D
+
+    public override string ToDisplayTime()
+    {
+        var textBuilder = OperationTimeHepler.textBuilder;
+        textBuilder.Length = 0;
+        textBuilder.Append(startDate.ToDisplay());
+        if (startDate != endDate)
+        {
+            textBuilder.Append("鈥�");
+            textBuilder.Append(endDate.ToDisplay());
+        }
+        return textBuilder.ToString();
+    }
+}
diff --git a/Main/System/OSActivity/OperationTotDayRechargeInfo.cs.meta b/Main/System/OSActivity/OperationTotDayRechargeInfo.cs.meta
new file mode 100644
index 0000000..e41ce3b
--- /dev/null
+++ b/Main/System/OSActivity/OperationTotDayRechargeInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ed77821f2b2191d49b55143750ec812c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/OSActivity/OperationTotalRechargeInfo.cs b/Main/System/OSActivity/OperationTotalRechargeInfo.cs
new file mode 100644
index 0000000..196de07
--- /dev/null
+++ b/Main/System/OSActivity/OperationTotalRechargeInfo.cs
@@ -0,0 +1,21 @@
+锘縰sing System.Collections.Generic;
+
+
+//绱厖娲诲姩
+public class OperationTotalRechargeInfo : OperationBase
+{
+    public int CfgID;   // 娲诲姩鏃堕棿琛ㄩ厤缃甀D
+
+    public override string ToDisplayTime()
+    {
+        var textBuilder = OperationTimeHepler.textBuilder;
+        textBuilder.Length = 0;
+        textBuilder.Append(startDate.ToDisplay());
+        if (startDate != endDate)
+        {
+            textBuilder.Append("鈥�");
+            textBuilder.Append(endDate.ToDisplay());
+        }
+        return textBuilder.ToString();
+    }
+}
diff --git a/Main/System/OSActivity/OperationTotalRechargeInfo.cs.meta b/Main/System/OSActivity/OperationTotalRechargeInfo.cs.meta
new file mode 100644
index 0000000..570b29f
--- /dev/null
+++ b/Main/System/OSActivity/OperationTotalRechargeInfo.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2ca29732cd569824088e31f2f83bdbfb
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/OfficialRank/OfficialRankManager.cs b/Main/System/OfficialRank/OfficialRankManager.cs
index 5458b73..1969998 100644
--- a/Main/System/OfficialRank/OfficialRankManager.cs
+++ b/Main/System/OfficialRank/OfficialRankManager.cs
@@ -271,6 +271,15 @@
             case 13:
                 // ffd0f7
                 return new Color32(255, 208, 247, 255);
+            case 14:
+                // ffefcl
+                return new Color32(255, 239, 203, 255);
+            case 15:
+                // ffc096
+                return new Color32(255, 192, 150, 255);
+            case 16:
+                // fe9896
+                return new Color32(254, 152, 150, 255);
         }
         return Color.white;
     }
diff --git a/Main/System/OpenServerActivity/OperationTimeHepler.cs b/Main/System/OpenServerActivity/OperationTimeHepler.cs
index 18a98ec..0738659 100644
--- a/Main/System/OpenServerActivity/OperationTimeHepler.cs
+++ b/Main/System/OpenServerActivity/OperationTimeHepler.cs
@@ -495,6 +495,76 @@
         operationTimeUpdateEvent?.Invoke(opreationType);
     }
 
+    public void UpdateActTotalRechargeInfo(HAA1D_tagSCActTotalRechargeInfo package)
+    {
+        OperationBase operationBase = null;
+        operationDict.TryGetValue(OperationType.TotalRecharge, out operationBase);
+        if (string.IsNullOrEmpty(package.StartDate) || string.IsNullOrEmpty(package.EndtDate))
+        {
+            ForceStopOperation(OperationType.TotalRecharge);
+        }
+        else
+        {
+            if (operationBase == null)
+            {
+                operationBase = new OperationTotalRechargeInfo();
+                operationDict.Add(OperationType.TotalRecharge, operationBase);
+            }
+            OperationTotalRechargeInfo operation = operationBase as OperationTotalRechargeInfo;
+            operation.Reset();
+            operation.startDate = ParseOperationDate(package.StartDate);
+            operation.endDate = ParseOperationDate(package.EndtDate);
+            operation.ActNum = package.ActNum;
+            operation.CfgID = package.CfgID;
+            
+            var config = ActTotalRechargeConfig.Get(package.CfgID);
+            if (config == null)
+            {
+                SysNotifyMgr.Instance.ShowTip("LoadConfigErr");
+                return;
+            }
+
+            if (operationTimeUpdateEvent != null)
+            {
+                operationTimeUpdateEvent(OperationType.TotalRecharge);
+            }
+        }
+    }
+
+    public void UpdateActTotDayRechargeInfo(HAA1B_tagSCActTotDayRechargeInfo package)
+    {
+        OperationBase operationBase = null;
+        operationDict.TryGetValue(OperationType.TotDayRecharge, out operationBase);
+        if (string.IsNullOrEmpty(package.StartDate) || string.IsNullOrEmpty(package.EndtDate))
+        {
+            ForceStopOperation(OperationType.TotDayRecharge);
+        }
+        else
+        {
+            if (operationBase == null)
+            {
+                operationBase = new OperationTotDayRechargeInfo();
+                operationDict.Add(OperationType.TotDayRecharge, operationBase);
+            }
+            OperationTotDayRechargeInfo operation = operationBase as OperationTotDayRechargeInfo;
+            operation.Reset();
+            operation.startDate = ParseOperationDate(package.StartDate);
+            operation.endDate = ParseOperationDate(package.EndtDate);
+            operation.ActNum = package.ActNum;
+            operation.CfgID = package.CfgID;
+
+            var config = ActTotalRechargeConfig.Get(package.CfgID);
+            if (config == null)
+            {
+                SysNotifyMgr.Instance.ShowTip("LoadConfigErr");
+                return;
+            }
+            
+            operation.dayReset = config.IsDayReset == 1;
+            operationTimeUpdateEvent?.Invoke(OperationType.TotDayRecharge);
+        }
+    }
+
     // public void UpdateActYunShiInfo(HAA87_tagMCActYunshiInfo package)
     // {
     //     Operation operationType = Operation.default48;
@@ -1085,5 +1155,7 @@
     TimeRush = 1,  //鏃ユ湡鍨嬫椿鍔� - 杞洖娈�
     HeroDebut = 2,  //鏃ユ湡鍨嬫椿鍔� - 姝﹀皢鐧诲満
     HeroReturn = 3, //鏃ユ湡鍨嬫椿鍔� - 姝﹀皢杩斿満
+    TotalRecharge = 4,//绱厖娲诲姩
+    TotDayRecharge = 5, //绱厖澶╂椿鍔�
     max,
 }
\ No newline at end of file
diff --git a/Main/System/OtherPlayerDetail/OtherHeroDetailWin.cs b/Main/System/OtherPlayerDetail/OtherHeroDetailWin.cs
index 94717ff..e45e4ef 100644
--- a/Main/System/OtherPlayerDetail/OtherHeroDetailWin.cs
+++ b/Main/System/OtherPlayerDetail/OtherHeroDetailWin.cs
@@ -82,8 +82,20 @@
                         return;
                     }
                     heroInfo.CalculateFightPower();
-                    attrDict = FightPowerManager.Instance.GetHeroTotalAttr(heroInfo);
-                    DisplayByMyPack(heroInfo, data);
+
+                    if (data.battleName == BattleConst.WarlordPavilionBattleField)
+                    {
+                        FightPowerManager.Instance.djgAttrs = WarlordPavilionManager.Instance.GetAllAttrBonus();
+                        attrDict = FightPowerManager.Instance.GetHeroTotalAttr(heroInfo);
+                        FightPowerManager.Instance.djgAttrs.Clear();
+                        DisplayByMyPack(heroInfo, data);
+                    }
+                    else
+                    {
+                        attrDict = FightPowerManager.Instance.GetHeroTotalAttr(heroInfo);
+                        DisplayByMyPack(heroInfo, data);
+                    }
+
                 }
                 else
                 {
diff --git a/Main/System/OtherPlayerDetail/OtherPlayerDetailWin.cs b/Main/System/OtherPlayerDetail/OtherPlayerDetailWin.cs
index 2b919d2..6a12381 100644
--- a/Main/System/OtherPlayerDetail/OtherPlayerDetailWin.cs
+++ b/Main/System/OtherPlayerDetail/OtherPlayerDetailWin.cs
@@ -192,7 +192,14 @@
         if (horseData != null)
         {
             txtHorseLV.text = Language.Get("Horse8", horseData.ClassLV, horseData.LV);
-            horseController.Create(horseSkinID <= 0 ? 1 : horseSkinID, scale: 0.6f).Forget();
+            if (horseSkinID <= 0 || horseSkinID == 999)
+            {
+                horseController.Create(HorseManager.Instance.defaultSkinID, scale: 0.6f).Forget();
+            }
+            else
+            {
+                horseController.Create(horseSkinID, scale: 0.6f).Forget();
+            }
         }
 
     }
diff --git a/Main/System/Qunying/QYBattleVictoryWin.cs b/Main/System/Qunying/QYBattleVictoryWin.cs
index 1d5dfe1..0a2a1f6 100644
--- a/Main/System/Qunying/QYBattleVictoryWin.cs
+++ b/Main/System/Qunying/QYBattleVictoryWin.cs
@@ -53,9 +53,17 @@
     // itemInfo:濂栧姳鐗╁搧鍒楄〃锛屽彲鑳戒负绌�
     void Display()
     {
-
         int quickCnt = QunyingManager.Instance.quickCnt;
-        uint tagPlayerID = quickCnt == 0 ? (uint)jsonData["tagPlayerID"] : (uint)QunyingManager.Instance.tagPlayerID;
+        uint tmpTagPlayerID = 0;
+        if (jsonData != null && jsonData.ContainsKey("tagPlayerID"))
+        {
+            tmpTagPlayerID = (uint)jsonData["tagPlayerID"];
+        }
+        else
+        {
+            tmpTagPlayerID = (uint)QunyingManager.Instance.tagPlayerID;
+        }
+        uint tagPlayerID = quickCnt == 0 ? tmpTagPlayerID : (uint)QunyingManager.Instance.tagPlayerID;
         if (!QunyingManager.Instance.TryGetPlayerInfo(tagPlayerID, out QunyingMatchInfo info))
             return;
         uint enemyFace = info.Face;
diff --git a/Main/System/Qunying/QYWin.cs b/Main/System/Qunying/QYWin.cs
index 0fef520..029ef06 100644
--- a/Main/System/Qunying/QYWin.cs
+++ b/Main/System/Qunying/QYWin.cs
@@ -14,6 +14,7 @@
     [SerializeField] Button closeBtn;
 
     [SerializeField] Text gameTimeText;
+    [SerializeField] Text gameStepNameText;
     [SerializeField] Button buyTicketBtn;
     [SerializeField] Text ticketCountText;
     [SerializeField] Text ticketTimeText;
@@ -33,6 +34,7 @@
     [SerializeField] Button awardBtn;
     [SerializeField] Button noteBtn;
 
+    int rankType = 0;
     protected override void InitComponent()
     {
         closeBtn.AddListener(CloseWindow);
@@ -63,6 +65,9 @@
         });
         rankBtn.AddListener(() =>
         {
+            var zoneInfo = CrossServerBaseManager.Instance.GetCrossZoneInfo(QunyingManager.DataMapID);
+            PlayerRankWin.groupValue1 = zoneInfo != null ? (int)zoneInfo.ZoneID : 0;
+            PlayerRankWin.crossServerID = zoneInfo != null ? (int)zoneInfo.CrossServerID : 0;
             UIManager.Instance.OpenWindowAsync<PlayerRankWin>(QunyingManager.rankType).Forget();
         });
         awardBtn.AddListener(() =>
@@ -77,6 +82,7 @@
 
     protected override void OnPreOpen()
     {
+        rankType = QunyingManager.Instance.GetRankType();
         if (!QunyingManager.Instance.openQYWinNeedRoll)
         {
             var myMatch = QunyingManager.Instance.GetMyMatchInfo(out int index);
@@ -87,7 +93,10 @@
             battleScrollRect.verticalNormalizedPosition = 1f;
         }
         RankModel.Instance.ResetQueryParam();
-        RankModel.Instance.QueryRankByPage(QunyingManager.rankType, 0, 3);
+        var zoneInfo = CrossServerBaseManager.Instance.GetCrossZoneInfo(QunyingManager.DataMapID);
+        int zoneID = zoneInfo != null ? (int)zoneInfo.ZoneID : 0;
+        int csID = zoneInfo != null ? (int)zoneInfo.CrossServerID : 0;
+        RankModel.Instance.QueryRankByPage(rankType, 0, 3, groupValue1: zoneID, crossServerID: csID);
         QunyingManager.Instance.RequestRefreshFighters(0);
 
         RankModel.Instance.onRankRefresh += OnRankRefresh;
@@ -136,7 +145,10 @@
     void OnDayEvent()
     {
         RankModel.Instance.ResetQueryParam();
-        RankModel.Instance.QueryRankByPage(QunyingManager.rankType, 0, 3);
+        var zoneInfo = CrossServerBaseManager.Instance.GetCrossZoneInfo(QunyingManager.DataMapID);
+        int zoneID = zoneInfo != null ? (int)zoneInfo.ZoneID : 0;
+        int csID = zoneInfo != null ? (int)zoneInfo.CrossServerID : 0;
+        RankModel.Instance.QueryRankByPage(rankType, 0, 3, groupValue1: zoneID, crossServerID: csID);
         QunyingManager.Instance.RequestRefreshFighters(0);
 
     }
@@ -159,7 +171,21 @@
     //娲诲姩鏃堕棿
     void ShowGameTime()
     {
-        gameTimeText.text = QunyingManager.Instance.GetEndSecondStr();
+        var zoneInfo = CrossServerBaseManager.Instance.GetCrossZoneInfo(QunyingManager.DataMapID);
+        if (zoneInfo != null && zoneInfo.ZoneID == 0)
+        {
+            //鍊掕鏃舵寜0:05缁撴潫
+            var seconds = (TimeUtility.GetTodayStartTime().AddMinutes(5) - TimeUtility.GetCommServerNow(0)).TotalSeconds;
+            gameTimeText.text = TimeUtility.SecondsToDHMS((int)seconds);
+            gameStepNameText.text = Language.Get("Qunying3_1");
+        }
+        else
+        {
+            //闈炶法鏈� 鎴栬�� 璺ㄦ湇鍦ㄨ繘琛屼腑鐨勬椂鍊欐甯告樉绀哄�掕鏃�
+            gameTimeText.text = QunyingManager.Instance.GetEndSecondStr();
+            gameStepNameText.text = Language.Get("Qunying3");
+        }
+
         if (QunyingManager.Instance.m_LastRecoverTime == 0)
         {
             ticketTimeText.text = "";
@@ -180,7 +206,7 @@
     {
         for (int i = 0; i < playerTop3Cells.Length; i++)
         {
-            playerTop3Cells[i].Display(QunyingManager.rankType, i + 1);
+            playerTop3Cells[i].Display(rankType, i + 1);
         }
     }
 
@@ -195,7 +221,7 @@
 
     void OnRankRefresh(int type)
     {
-        if (type != QunyingManager.rankType)
+        if (type != rankType)
             return;
         DisplayPlayerTop3();
     }
diff --git a/Main/System/Qunying/QunyingManager.cs b/Main/System/Qunying/QunyingManager.cs
index c7f6049..eeeff8c 100644
--- a/Main/System/Qunying/QunyingManager.cs
+++ b/Main/System/Qunying/QunyingManager.cs
@@ -10,6 +10,7 @@
     public const int challengeMoneyType = 56;   //鎸戞垬 闂紟浠�
     public const int challengeShopID = 16;
     public const int rankType = 10;
+    public const int crossRankType = 150;
     public const int recType = 312;  // 鎸戞垬璁板綍绫诲瀷 
     public const int DataMapID = 32000;
 
@@ -408,9 +409,20 @@
         {
             matchRedpoint.state = RedPointState.Simple;
         }
-        
+
     }
     #endregion
+
+    public int GetRankType()
+    {
+        if (CrossServerBaseManager.Instance.IsOpenCrossServer(DataMapID))
+        {
+            return crossRankType;
+        }
+        return rankType;
+    }
+
+
 }
 
 public class QunyingMatchInfo
diff --git a/Main/System/Settlement/BattleSettlementManager.cs b/Main/System/Settlement/BattleSettlementManager.cs
index c8169af..1144ab6 100644
--- a/Main/System/Settlement/BattleSettlementManager.cs
+++ b/Main/System/Settlement/BattleSettlementManager.cs
@@ -237,7 +237,7 @@
         {
             Debug.Log("鎴樻枟鏃跺簭 鏀跺埌B431 骞惰姹備笅杞芥垬鎶�" + Time.time);
             var date = UIHelper.ServerStringTrim(netData.PathDate);
-            RequestTurnFightData(guid, date, mapID);
+            RequestTurnFightData(guid, date, mapID, (int)netData.CrossServerID);
         }
         else
         {
@@ -257,10 +257,10 @@
         }
 
     }
-    public void RequestTurnFightData(string guid, string date, int mapID)
+    public void RequestTurnFightData(string guid, string date, int mapID, int crossServerID = 0)
     {
         //mobile.secondworld.net.cn:53080\S9006\20251202\3042602\5b11338f-cf2c-11f0-a0a0-000c29b22418.tfr
-        var serverID = UIHelper.GetServerIDByAccount(PlayerDatas.Instance.baseData.AccID);
+        var serverID = crossServerID !=0 ? crossServerID : UIHelper.GetServerIDByAccount(PlayerDatas.Instance.baseData.AccID);
 
         var url = ServerListCenter.Instance.GetServerUrl(serverID);
         string assetVersionUrl = string.Empty;
diff --git a/Main/System/TimeRush/TimeRushManager.cs b/Main/System/TimeRush/TimeRushManager.cs
index b6ed1e5..364d752 100644
--- a/Main/System/TimeRush/TimeRushManager.cs
+++ b/Main/System/TimeRush/TimeRushManager.cs
@@ -251,6 +251,9 @@
     public event Action OnNewAwardHaveEvent;
     public void CheckNewAwardHave(int roundType, int curRound, int curValue)
     {
+        if (!IsFuncOpen())
+            return;
+
         if (lastCurRoundDict.ContainsKey(roundType) && lastCurValueDict.ContainsKey(roundType))
         {
             int lastCurRound = lastCurRoundDict[roundType];
diff --git a/Main/System/Tip/ConfirmCancel.cs b/Main/System/Tip/ConfirmCancel.cs
index c23713d..bbc9f01 100644
--- a/Main/System/Tip/ConfirmCancel.cs
+++ b/Main/System/Tip/ConfirmCancel.cs
@@ -359,6 +359,7 @@
     GoldRush = 2,   //娣橀噾 
     BoneField = 3,   //鐧介鐩堥噹
     FuncPreset = 4, //鍔熻兘(娴佹淳)棰勮
+    Horse = 5,//鍧愰獞璐拱
 }
 
 
diff --git a/Main/System/TotDayRecharge.meta b/Main/System/TotDayRecharge.meta
new file mode 100644
index 0000000..9cbc8b9
--- /dev/null
+++ b/Main/System/TotDayRecharge.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 640279443a4eebc458a4b9a817e0fe2f
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/TotDayRecharge/TotDayRechargeCell.cs b/Main/System/TotDayRecharge/TotDayRechargeCell.cs
new file mode 100644
index 0000000..10996a8
--- /dev/null
+++ b/Main/System/TotDayRecharge/TotDayRechargeCell.cs
@@ -0,0 +1,74 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TotDayRechargeCell : CellView
+{
+    [SerializeField] Text nameText;
+    [SerializeField] Image processImage;
+    [SerializeField] Text processText;
+    [SerializeField] ItemCell[] itemCells;
+
+    [SerializeField] Button getBtn;
+    [SerializeField] Button gotoBtn;
+    [SerializeField] Transform gotRect;
+
+    TotDayRechargeManager manager { get { return TotDayRechargeManager.Instance; } }
+
+    public void Display(int index, List<int> list)
+    {
+        if (list.IsNullOrEmpty() || index < 0 || index >= list.Count)
+            return;
+        int awardID = list[index];
+        var config = ActTotDayRechargeTempConfig.Get(awardID);
+        if (config == null)
+            return;
+        nameText.text = Language.Get($"TotalRecharge03", config.NeedDay);
+
+        if (config.AwardItemList != null)
+        {
+            for (int i = 0; i < itemCells.Length; i++)
+            {
+                var cell = itemCells[i];
+
+                if (i < config.AwardItemList.Length)
+                {
+                    var item = config.AwardItemList[i];
+                    cell.SetActive(true);
+                    cell.Init(new ItemCellModel(item[0], false, item[1]));
+                    cell.button.AddListener(() => ItemTipUtility.Show(item[0]));
+                }
+                else
+                {
+                    cell.SetActive(false);
+                }
+            }
+        }
+
+        processText.text = Language.Get("BoneField09", manager.totalDays, config.NeedDay);
+        processImage.fillAmount = manager.totalDays / (float)config.NeedDay;
+
+        int state = manager.GetState(awardID);// 鑾峰彇濂栧姳鐘舵�� 0 涓嶅彲棰嗗彇 1 鏈鍙� 2 宸查鍙�
+
+        gotoBtn.SetActive(state == 0);
+        getBtn.SetActive(state == 1);
+        gotRect.SetActive(state == 2);
+
+        getBtn.SetListener(() => manager.SendGetReward(config.NeedDay));
+        gotoBtn.SetListener(() =>
+        {
+            if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Recharge, true))
+            {
+                RechargeManager.Instance.selectTabIndex = 1;
+                if (UIManager.Instance.IsOpened<StoreBaseWin>())
+                {
+                    UIManager.Instance.GetUI<StoreBaseWin>().ClickFuncBtn(2);
+                }
+                else
+                {
+                    UIManager.Instance.OpenWindow<StoreBaseWin>(2);
+                }
+            }
+        });
+    }
+}
diff --git a/Main/System/TotDayRecharge/TotDayRechargeCell.cs.meta b/Main/System/TotDayRecharge/TotDayRechargeCell.cs.meta
new file mode 100644
index 0000000..85749d4
--- /dev/null
+++ b/Main/System/TotDayRecharge/TotDayRechargeCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 731ccb7a2bf5d7e49bcd9379cad5ca55
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/TotDayRecharge/TotDayRechargeManager.cs b/Main/System/TotDayRecharge/TotDayRechargeManager.cs
new file mode 100644
index 0000000..b2a7871
--- /dev/null
+++ b/Main/System/TotDayRecharge/TotDayRechargeManager.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public class TotDayRechargeManager : GameSystemManager<TotDayRechargeManager>, IOpenServerActivity
+{
+    public readonly int ActNum = 10;
+    public override void Init()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
+        OperationTimeHepler.Instance.operationTimeUpdateEvent += OperationTimeUpdateEvent;
+        OperationTimeHepler.Instance.operationStartEvent += OperationStartEvent;
+        OperationTimeHepler.Instance.operationEndEvent += OperationEndEvent;
+        OperationTimeHepler.Instance.operationAdvanceEvent += OperationAdvanceEvent;
+        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent += OnRefreshBuyShopLimitEvent;
+    }
+
+    public override void Release()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin;
+        OperationTimeHepler.Instance.operationTimeUpdateEvent -= OperationTimeUpdateEvent;
+        OperationTimeHepler.Instance.operationStartEvent -= OperationStartEvent;
+        OperationTimeHepler.Instance.operationEndEvent -= OperationEndEvent;
+        OperationTimeHepler.Instance.operationAdvanceEvent -= OperationAdvanceEvent;
+        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent -= OnRefreshBuyShopLimitEvent;
+
+    }
+
+    private void OnRefreshBuyShopLimitEvent()
+    {
+        UpdateRedPoint();
+    }
+
+
+    private void OnFuncStateChangeEvent(int obj)
+    {
+        if (obj != (int)FuncOpenEnum.OSGala)
+            return;
+        UpdateRedPoint();
+    }
+
+    private void OnBeforePlayerDataInitializeEventOnRelogin()
+    {
+        totalDays = 0;
+        awardRecord = 0;
+    }
+
+    public const int activityType = (int)OpenServerActivityCenter.ActivityType.AT_DateActivity;
+    public const int activityID = (int)NewDayActivityID.TotDayRechargeAct;
+    public static OperationType operaType = OperationType.TotDayRecharge;
+    // 鎬诲鍔�
+    public Redpoint redPoint = new Redpoint(MainRedDot.RedPoint_OSGala, MainRedDot.RedPoint_OSGala * 10 + 6);
+    public bool IsOpen => OperationTimeHepler.Instance.SatisfyOpenCondition(operaType);
+    public bool IsAdvance => OperationTimeHepler.Instance.SatisfyAdvanceCondition(operaType);
+    public bool priorityOpen => redPoint.state == RedPointState.Simple;
+    public readonly int actNum = 10;
+    public event Action<int> onStateUpdate;
+
+    private void OperationTimeUpdateEvent(OperationType type)
+    {
+        if (type == operaType)
+        {
+
+        }
+        if (UIManager.Instance.IsOpened<OSGalaBaseWin>())
+            UIManager.Instance.CloseWindow<OSGalaBaseWin>();
+        UpdateRedPoint();
+    }
+
+    private void OperationStartEvent(OperationType type, int state)
+    {
+        if (type == operaType && state == 0)
+        {
+            UpdateRedPoint();
+            onStateUpdate?.Invoke(activityID);
+        }
+    }
+
+    private void OperationEndEvent(OperationType type, int state)
+    {
+        if (type == operaType)
+        {
+            if (UIManager.Instance.IsOpened<OSGalaBaseWin>())
+                UIManager.Instance.CloseWindow<OSGalaBaseWin>();
+            UpdateRedPoint();
+            onStateUpdate?.Invoke(activityID);
+        }
+    }
+
+    private void OperationAdvanceEvent(OperationType type)
+    {
+        if (type == operaType)
+        {
+            UpdateRedPoint();
+            onStateUpdate?.Invoke(activityID);
+        }
+    }
+
+    public void UpdateRedPoint()
+    {
+        redPoint.state = RedPointState.None;
+        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.OSGala))
+            return;
+        if (!IsOpen)
+            return;
+
+        var awardList = GetShowList();
+        if (awardList == null)
+            return;
+        for (int i = 0; i < awardList.Count; i++)
+        {
+            if (GetState(awardList[i]) == 1)
+            {
+                redPoint.state = RedPointState.Simple;
+                return;
+            }
+        }
+
+        var storeData = GetStoreData();
+        if (storeData != null && !IsReceived(storeData.shopId))
+        {
+            redPoint.state = RedPointState.Simple;
+        }
+    }
+
+    public bool GetActInfo(out OperationTotDayRechargeInfo act, out ActTotDayRechargeConfig config)
+    {
+        config = null;
+        if (!OperationTimeHepler.Instance.TryGetOperation(operaType, out act) || act == null)
+            return false;
+        config = ActTotDayRechargeConfig.Get(act.CfgID);
+        return config != null;
+    }
+
+    public List<int> GetShowList(bool isSort = false)
+    {
+        if (!GetActInfo(out var act, out var config))
+            return null;
+
+        int templateID = config.TemplateID;
+        var res = new List<int>();
+
+        var awardIndexSortList = ActTotDayRechargeTempConfig.GetNeedDaySortList(templateID);
+        for (int i = 0; i < awardIndexSortList.Count; i++)
+        {
+            var tempConfig = ActTotDayRechargeTempConfig.GetConfig(templateID, awardIndexSortList[i]);
+            if (tempConfig == null)
+                continue;
+            res.Add(tempConfig.AwardID);
+        }
+
+        if (isSort)
+        {
+            res = res.OrderBy(awardId =>
+            {
+                var tempConfig = ActTotDayRechargeTempConfig.Get(awardId);
+                return IsAwardHave(tempConfig.NeedDay);
+            })
+            .ThenBy(awardId => awardId)
+            .ToList();
+
+        }
+        return res;
+    }
+
+    public bool IsCanBuyShop(int shopID)
+    {
+        StoreConfig config = StoreConfig.Get(shopID);
+        if (config == null)
+            return false;
+        StoreModel.Instance.TryGetIsSellOut(config, out int remainNum);
+        return remainNum > 0;
+    }
+
+    public StoreModel.StoreData GetStoreData()
+    {
+        if (!GetActInfo(out var act, out var config))
+            return null;
+        int actShopType = config.ActShopType;
+        if (StoreModel.Instance.storeTypeDict == null)
+            return null;
+        if (!StoreModel.Instance.storeTypeDict.TryGetValue(actShopType, out var list))
+            return null;
+        if (list.IsNullOrEmpty())
+            return null;
+        return list[0];
+    }
+
+    bool IsAwardHave(int awardIndex)
+    {
+        if (awardIndex < 0 || awardIndex >= 32)
+            return false;
+        return (awardRecord & (1u << awardIndex)) != 0;
+    }
+
+    // 鑾峰彇濂栧姳鐘舵�� 0 涓嶅彲棰嗗彇 1 鏈鍙� 2 宸查鍙�
+    public int GetState(int awardID)
+    {
+        var config = ActTotDayRechargeTempConfig.Get(awardID);
+        if (config == null)
+            return 0;
+        if (totalDays < config.NeedDay)
+            return 0;
+        bool isAwardHave = IsAwardHave(config.NeedDay);
+        return isAwardHave ? 2 : 1;
+    }
+
+    public bool IsReceived(int shopId)
+    {
+        var config = StoreConfig.Get(shopId);
+        if (config == null)
+            return false;
+        int boughtCount = StoreModel.Instance.GetShopLimitBuyCount(shopId);
+        return boughtCount >= config.LimitCnt;
+    }
+
+    public string GetActTimeStr()
+    {
+        if (!GetActInfo(out var act, out var config))
+        {
+            return Language.Get("OSActivity6");
+        }
+        return Language.Get("TotalRecharge08", TimeUtility.SecondsToShortDHMS(act.GetResetSurplusTime()));
+    }
+
+    public byte totalDays;    //娲诲姩绱厖澶╂暟
+    public uint awardRecord;    //绱厖濂栧姳棰嗗璁板綍锛屾寜濂栧姳绱㈠紩浜岃繘鍒朵綅瀛樺偍鏄惁宸查鍙�
+    public event Action OnTotDayRechargePlayerInfoEvent;
+    public void UpdateTotDayRechargePlayerInfo(HAA1A_tagSCActTotDayRechargePlayerInfo vNetData)
+    {
+        if (ActNum != vNetData.ActNum)
+            return;
+        totalDays = vNetData.TotalDays;
+        awardRecord = vNetData.AwardRecord;
+        UpdateRedPoint();
+        OnTotDayRechargePlayerInfoEvent?.Invoke();
+    }
+
+    public void SendGetReward(int needDay)
+    {
+        string actStr = ActNum.ToString();
+        var pack = new CA504_tagCMPlayerGetReward();
+        pack.RewardType = 19;
+        pack.DataEx = (uint)needDay;
+        pack.DataExStr = actStr;
+        pack.DataExStrLen = (byte)actStr.Length;
+        GameNetSystem.Instance.SendInfo(pack);
+    }
+}
\ No newline at end of file
diff --git a/Main/System/TotDayRecharge/TotDayRechargeManager.cs.meta b/Main/System/TotDayRecharge/TotDayRechargeManager.cs.meta
new file mode 100644
index 0000000..6fc9d93
--- /dev/null
+++ b/Main/System/TotDayRecharge/TotDayRechargeManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4231ac3f6f8d84f4189f5e0f55b93ca0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/TotDayRecharge/TotDayRechargeWin.cs b/Main/System/TotDayRecharge/TotDayRechargeWin.cs
new file mode 100644
index 0000000..c011d14
--- /dev/null
+++ b/Main/System/TotDayRecharge/TotDayRechargeWin.cs
@@ -0,0 +1,51 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+
+//寮�鏈嶆椿鍔�-绱厖
+public class TotDayRechargeWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+
+    TotDayRechargeManager manager { get { return TotDayRechargeManager.Instance; } }
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        TotDayRechargeManager.Instance.OnTotDayRechargePlayerInfoEvent += OnTotDayRechargePlayerInfoEvent;
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        TotDayRechargeManager.Instance.OnTotDayRechargePlayerInfoEvent -= OnTotDayRechargePlayerInfoEvent;
+    }
+
+    private void OnTotDayRechargePlayerInfoEvent()
+    {
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    List<int> showList;
+    void CreateScroller()
+    {
+
+        showList = manager.GetShowList(true);
+        scroller.Refresh();
+        for (int i = 0; i < showList.Count; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as TotDayRechargeCell;
+        _cell.Display(cell.index, showList);
+    }
+}
+
+
+
+
diff --git a/Main/System/TotDayRecharge/TotDayRechargeWin.cs.meta b/Main/System/TotDayRecharge/TotDayRechargeWin.cs.meta
new file mode 100644
index 0000000..82ee6bd
--- /dev/null
+++ b/Main/System/TotDayRecharge/TotDayRechargeWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7b483a9d19723db4da256313000559c0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/TotalRecharge.meta b/Main/System/TotalRecharge.meta
new file mode 100644
index 0000000..87f0866
--- /dev/null
+++ b/Main/System/TotalRecharge.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 027d9e03375d65d4197c9f4d1fefa8a5
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/TotalRecharge/TotalRechargeCell.cs b/Main/System/TotalRecharge/TotalRechargeCell.cs
new file mode 100644
index 0000000..789adfc
--- /dev/null
+++ b/Main/System/TotalRecharge/TotalRechargeCell.cs
@@ -0,0 +1,74 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TotalRechargeCell : CellView
+{
+    [SerializeField] Text nameText;
+    [SerializeField] Image processImage;
+    [SerializeField] Text processText;
+    [SerializeField] ItemCell[] itemCells;
+
+    [SerializeField] Button getBtn;
+    [SerializeField] Button gotoBtn;
+    [SerializeField] Transform gotRect;
+
+    TotalRechargeManager manager { get { return TotalRechargeManager.Instance; } }
+
+    public void Display(int index, List<int> list)
+    {
+        if (list.IsNullOrEmpty() || index < 0 || index >= list.Count)
+            return;
+        int awardID = list[index];
+        var config = ActTotalRechargeTempConfig.Get(awardID);
+        if (config == null)
+            return;
+        nameText.text = Language.Get($"TotalRecharge02", config.NeedAmount);
+
+        if (config.AwardItemList != null)
+        {
+            for (int i = 0; i < itemCells.Length; i++)
+            {
+                var cell = itemCells[i];
+
+                if (i < config.AwardItemList.Length)
+                {
+                    var item = config.AwardItemList[i];
+                    cell.SetActive(true);
+                    cell.Init(new ItemCellModel(item[0], false, item[1]));
+                    cell.button.AddListener(() => ItemTipUtility.Show(item[0]));
+                }
+                else
+                {
+                    cell.SetActive(false);
+                }
+            }
+        }
+
+        processText.text = Language.Get("BoneField09", manager.coinTotal, config.NeedAmount);
+        processImage.fillAmount = manager.coinTotal / (float)config.NeedAmount;
+
+        int state = manager.GetState(awardID);// 鑾峰彇濂栧姳鐘舵�� 0 涓嶅彲棰嗗彇 1 鏈鍙� 2 宸查鍙�
+
+        gotoBtn.SetActive(state == 0);
+        getBtn.SetActive(state == 1);
+        gotRect.SetActive(state == 2);
+
+        getBtn.SetListener(() => manager.SendGetReward(config.AwardIndex));
+        gotoBtn.SetListener(() =>
+        {
+            if (FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.Recharge, true))
+            {
+                RechargeManager.Instance.selectTabIndex = 1;
+                if (UIManager.Instance.IsOpened<StoreBaseWin>())
+                {
+                    UIManager.Instance.GetUI<StoreBaseWin>().ClickFuncBtn(2);
+                }
+                else
+                {
+                    UIManager.Instance.OpenWindow<StoreBaseWin>(2);
+                }
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/Main/System/TotalRecharge/TotalRechargeCell.cs.meta b/Main/System/TotalRecharge/TotalRechargeCell.cs.meta
new file mode 100644
index 0000000..e6153fb
--- /dev/null
+++ b/Main/System/TotalRecharge/TotalRechargeCell.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 133e398df7d3dcb408b3a7dcfb33f083
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/TotalRecharge/TotalRechargeManager.cs b/Main/System/TotalRecharge/TotalRechargeManager.cs
new file mode 100644
index 0000000..2a23413
--- /dev/null
+++ b/Main/System/TotalRecharge/TotalRechargeManager.cs
@@ -0,0 +1,252 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public class TotalRechargeManager : GameSystemManager<TotalRechargeManager>, IOpenServerActivity
+{
+    public readonly int ActNum = 10;
+    public override void Init()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
+        OperationTimeHepler.Instance.operationTimeUpdateEvent += OperationTimeUpdateEvent;
+        OperationTimeHepler.Instance.operationStartEvent += OperationStartEvent;
+        OperationTimeHepler.Instance.operationEndEvent += OperationEndEvent;
+        OperationTimeHepler.Instance.operationAdvanceEvent += OperationAdvanceEvent;
+        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent += OnRefreshBuyShopLimitEvent;
+    }
+
+    public override void Release()
+    {
+        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin;
+        OperationTimeHepler.Instance.operationTimeUpdateEvent -= OperationTimeUpdateEvent;
+        OperationTimeHepler.Instance.operationStartEvent -= OperationStartEvent;
+        OperationTimeHepler.Instance.operationEndEvent -= OperationEndEvent;
+        OperationTimeHepler.Instance.operationAdvanceEvent -= OperationAdvanceEvent;
+        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent;
+        StoreModel.Instance.RefreshBuyShopLimitEvent -= OnRefreshBuyShopLimitEvent;
+
+    }
+
+    private void OnRefreshBuyShopLimitEvent()
+    {
+        UpdateRedPoint();
+    }
+
+
+    private void OnFuncStateChangeEvent(int obj)
+    {
+        if (obj != (int)FuncOpenEnum.OSGala)
+            return;
+        UpdateRedPoint();
+    }
+
+
+    private void OnBeforePlayerDataInitializeEventOnRelogin()
+    {
+        coinTotal = 0;
+        awardRecord = 0;
+    }
+
+    public const int activityType = (int)OpenServerActivityCenter.ActivityType.AT_DateActivity;
+    public const int activityID = (int)NewDayActivityID.TotalRechargeAct;
+    public static OperationType operaType = OperationType.TotalRecharge;
+    // 鎬诲鍔�
+    public Redpoint redPoint = new Redpoint(MainRedDot.RedPoint_OSGala, MainRedDot.RedPoint_OSGala * 10 + 5);
+    public bool IsOpen => OperationTimeHepler.Instance.SatisfyOpenCondition(operaType);
+    public bool IsAdvance => OperationTimeHepler.Instance.SatisfyAdvanceCondition(operaType);
+    public bool priorityOpen => redPoint.state == RedPointState.Simple;
+    public readonly int actNum = 10;
+    public event Action<int> onStateUpdate;
+
+    private void OperationTimeUpdateEvent(OperationType type)
+    {
+        if (type == operaType)
+        {
+
+        }
+        if (UIManager.Instance.IsOpened<OSGalaBaseWin>())
+            UIManager.Instance.CloseWindow<OSGalaBaseWin>();
+        UpdateRedPoint();
+    }
+
+    private void OperationStartEvent(OperationType type, int state)
+    {
+        if (type == operaType && state == 0)
+        {
+            UpdateRedPoint();
+            onStateUpdate?.Invoke(activityID);
+        }
+    }
+
+    private void OperationEndEvent(OperationType type, int state)
+    {
+        if (type == operaType)
+        {
+            if (UIManager.Instance.IsOpened<OSGalaBaseWin>())
+                UIManager.Instance.CloseWindow<OSGalaBaseWin>();
+            UpdateRedPoint();
+            onStateUpdate?.Invoke(activityID);
+        }
+    }
+
+    private void OperationAdvanceEvent(OperationType type)
+    {
+        if (type == operaType)
+        {
+            UpdateRedPoint();
+            onStateUpdate?.Invoke(activityID);
+        }
+    }
+
+    public void UpdateRedPoint()
+    {
+        redPoint.state = RedPointState.None;
+        if (!FuncOpen.Instance.IsFuncOpen((int)FuncOpenEnum.OSGala))
+            return;
+        if (!IsOpen)
+            return;
+
+        var awardList = GetShowList();
+        if (awardList == null)
+            return;
+        for (int i = 0; i < awardList.Count; i++)
+        {
+            if (GetState(awardList[i]) == 1)
+            {
+                redPoint.state = RedPointState.Simple;
+                return;
+            }
+        }
+
+        var storeData = GetStoreData();
+        if (storeData != null && !IsReceived(storeData.shopId))
+        {
+            redPoint.state = RedPointState.Simple;
+        }
+    }
+    public bool GetActInfo(out OperationTotalRechargeInfo act, out ActTotalRechargeConfig config)
+    {
+        config = null;
+        if (!OperationTimeHepler.Instance.TryGetOperation(operaType, out act) || act == null)
+            return false;
+        config = ActTotalRechargeConfig.Get(act.CfgID);
+        return config != null;
+    }
+
+    public List<int> GetShowList(bool isSort = false)
+    {
+        if (!GetActInfo(out var act, out var config))
+            return null;
+
+        int ctgTempID = config.CTGTempID;
+        int ctgShopType = config.CTGShopType;
+        var res = new List<int>();
+
+        var awardIndexSortList = ActTotalRechargeTempConfig.GetAwardIndexSortList(ctgTempID);
+        for (int i = 0; i < awardIndexSortList.Count; i++)
+        {
+            var tempConfig = ActTotalRechargeTempConfig.GetConfig(ctgTempID, awardIndexSortList[i]);
+            if (tempConfig == null)
+                continue;
+            res.Add(tempConfig.AwardID);
+        }
+
+        if (isSort)
+        {
+            res = res.OrderBy(awardId =>
+            {
+                var tempConfig = ActTotalRechargeTempConfig.Get(awardId);
+                return IsAwardHave(tempConfig.AwardIndex);
+            })
+            .ThenBy(awardId => awardId)
+            .ToList();
+
+        }
+        return res;
+    }
+
+    public bool IsCanBuyShop(int shopID)
+    {
+        StoreConfig config = StoreConfig.Get(shopID);
+        if (config == null)
+            return false;
+        StoreModel.Instance.TryGetIsSellOut(config, out int remainNum);
+        return remainNum > 0;
+    }
+
+    public StoreModel.StoreData GetStoreData()
+    {
+        if (!GetActInfo(out var act, out var config))
+            return null;
+        int ctgShopType = config.CTGShopType;
+        if (StoreModel.Instance.storeTypeDict == null)
+            return null;
+        if (!StoreModel.Instance.storeTypeDict.TryGetValue(ctgShopType, out var list))
+            return null;
+        if (list.IsNullOrEmpty())
+            return null;
+        return list[0];
+    }
+
+    public float coinTotal;    //娲诲姩绱鍏呭�奸coin鍊�
+    public uint awardRecord;    //绱厖濂栧姳棰嗗璁板綍锛屾寜濂栧姳绱㈠紩浜岃繘鍒朵綅瀛樺偍鏄惁宸查鍙�
+    public event Action OnTotalRechargePlayerInfoEvent;
+    public void UpdateTotalRechargePlayerInfo(HAA1C_tagSCActTotalRechargePlayerInfo vNetData)
+    {
+        if (ActNum != vNetData.ActNum)
+            return;
+        coinTotal = (float)vNetData.CoinTotal / (float)100;
+        awardRecord = vNetData.AwardRecord;
+        UpdateRedPoint();
+        OnTotalRechargePlayerInfoEvent?.Invoke();
+    }
+
+    bool IsAwardHave(int awardIndex)
+    {
+        if (awardIndex < 0 || awardIndex >= 32)
+            return false;
+        return (awardRecord & (1u << awardIndex)) != 0;
+    }
+
+    // 鑾峰彇濂栧姳鐘舵�� 0 涓嶅彲棰嗗彇 1 鏈鍙� 2 宸查鍙�
+    public int GetState(int awardID)
+    {
+        var config = ActTotalRechargeTempConfig.Get(awardID);
+        if (config == null)
+            return 0;
+        if (coinTotal < config.NeedAmount)
+            return 0;
+        bool isAwardHave = IsAwardHave(config.AwardIndex);
+        return isAwardHave ? 2 : 1;
+    }
+
+    public bool IsReceived(int shopId)
+    {
+        var config = StoreConfig.Get(shopId);
+        if (config == null)
+            return false;
+        int boughtCount = StoreModel.Instance.GetShopLimitBuyCount(shopId);
+        return boughtCount >= config.LimitCnt;
+    }
+
+    public string GetActTimeStr()
+    {
+        if (!GetActInfo(out var act, out var config))
+        {
+            return Language.Get("OSActivity6");
+        }
+        return Language.Get("TotalRecharge08", TimeUtility.SecondsToShortDHMS(act.GetResetSurplusTime()));
+    }
+
+    public void SendGetReward(int awardIndex)
+    {
+        string actStr = ActNum.ToString();
+        var pack = new CA504_tagCMPlayerGetReward();
+        pack.RewardType = 18;
+        pack.DataEx = (uint)awardIndex;
+        pack.DataExStr = actStr;
+        pack.DataExStrLen = (byte)actStr.Length;
+        GameNetSystem.Instance.SendInfo(pack);
+    }
+}
diff --git a/Main/System/TotalRecharge/TotalRechargeManager.cs.meta b/Main/System/TotalRecharge/TotalRechargeManager.cs.meta
new file mode 100644
index 0000000..f907fae
--- /dev/null
+++ b/Main/System/TotalRecharge/TotalRechargeManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2aa04ba840c15be45a5d2236db47addb
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/TotalRecharge/TotalRechargeWin.cs b/Main/System/TotalRecharge/TotalRechargeWin.cs
new file mode 100644
index 0000000..1d5fd9c
--- /dev/null
+++ b/Main/System/TotalRecharge/TotalRechargeWin.cs
@@ -0,0 +1,51 @@
+锘縰sing System.Collections.Generic;
+using UnityEngine;
+
+//寮�鏈嶆椿鍔�-绱厖
+public class TotalRechargeWin : UIBase
+{
+    [SerializeField] ScrollerController scroller;
+
+    TotalRechargeManager manager { get { return TotalRechargeManager.Instance; } }
+    protected override void OnPreOpen()
+    {
+        scroller.OnRefreshCell += OnRefreshCell;
+        TotalRechargeManager.Instance.OnTotalRechargePlayerInfoEvent += OnTotalRechargePlayerInfoEvent;
+        CreateScroller();
+    }
+
+    protected override void OnPreClose()
+    {
+        scroller.OnRefreshCell -= OnRefreshCell;
+        TotalRechargeManager.Instance.OnTotalRechargePlayerInfoEvent -= OnTotalRechargePlayerInfoEvent;
+    }
+
+    private void OnTotalRechargePlayerInfoEvent()
+    {
+        scroller.m_Scorller.RefreshActiveCellViews();
+    }
+
+    List<int> showList;
+    void CreateScroller()
+    {
+
+        showList = manager.GetShowList(true);
+        scroller.Refresh();
+        for (int i = 0; i < showList.Count; i++)
+        {
+            scroller.AddCell(ScrollerDataType.Header, i);
+        }
+        scroller.Restart();
+
+    }
+
+    void OnRefreshCell(ScrollerDataType type, CellView cell)
+    {
+        var _cell = cell as TotalRechargeCell;
+        _cell.Display(cell.index, showList);
+    }
+}
+
+
+
+
diff --git a/Main/System/TotalRecharge/TotalRechargeWin.cs.meta b/Main/System/TotalRecharge/TotalRechargeWin.cs.meta
new file mode 100644
index 0000000..0aa7a01
--- /dev/null
+++ b/Main/System/TotalRecharge/TotalRechargeWin.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c6c1822a2a0e67a428b6826bc212fd68
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/UIBase/UIJumpManager.cs b/Main/System/UIBase/UIJumpManager.cs
index 64c9048..8182c05 100644
--- a/Main/System/UIBase/UIJumpManager.cs
+++ b/Main/System/UIBase/UIJumpManager.cs
@@ -65,7 +65,7 @@
 		//姝﹀皢鐧诲満鐩稿叧
 		else if (config.WinName == "HeroDebutCallWin" || config.WinName == "HeroDebutSkinWin" ||
 				config.WinName == "HeroDebutCheckInWin" || config.WinName == "HeroDebutGiftWin" ||
-				config.WinName == "HeroDebutShopWin")
+				config.WinName == "HeroDebutShopWin" || config.WinName == "HeroDebutZhanLingWin")
 		{
 			var heroDebutAct = HeroDebutManager.Instance.GetOperationHeroAppearInfo();
 			if (heroDebutAct == null)
@@ -99,7 +99,7 @@
 		//姝﹀皢杩斿満鐩稿叧
 		else if (config.WinName == "HeroReturnCallWin" || config.WinName == "HeroReturnSkinWin" ||
 				config.WinName == "HeroReturnCheckInWin" || config.WinName == "HeroReturnGiftWin" ||
-				config.WinName == "HeroReturnShopWin")
+				config.WinName == "HeroReturnShopWin"|| config.WinName == "HeroReturnZhanLingWin")
 		{
 			var heroDebutAct = HeroReturnManager.Instance.GetOperationHeroAppearInfo();
 			if (heroDebutAct == null)
diff --git a/Main/System/WarlordPavilion/WarlordPavilionManager.cs b/Main/System/WarlordPavilion/WarlordPavilionManager.cs
index e7ba944..5f8103c 100644
--- a/Main/System/WarlordPavilion/WarlordPavilionManager.cs
+++ b/Main/System/WarlordPavilion/WarlordPavilionManager.cs
@@ -499,6 +499,31 @@
         return SelectAuto == 1;
     }
 
+    /// <summary>
+    /// 鑾峰彇褰撳墠鍔犳垚鐨勫叏浣撳睘鎬�
+    /// </summary>
+    /// <returns>灞炴�у姞鎴愬瓧鍏革紝key涓篈ttrID锛寁alue涓虹疮璁$殑灞炴�у��</returns>
+    public Dictionary<int, long> GetAllAttrBonus()
+    {
+        Dictionary<int, long> attrBonusDict = new Dictionary<int, long>();
+        if (EffList.IsNullOrEmpty())
+            return attrBonusDict;
+
+        for (int i = 0; i < EffList.Length; i++)
+        {
+            var eff = EffList[i];
+            var config = FBDJGEffectConfig.Get(eff.EffID);
+            if (config == null)
+                continue;
+            long bonusValue = (long)eff.EffLV * config.AttrValue;
+            if (attrBonusDict.ContainsKey(config.AttrID))
+                attrBonusDict[config.AttrID] += bonusValue;
+            else
+                attrBonusDict[config.AttrID] = bonusValue;
+        }
+        return attrBonusDict;
+    }
+
     // 鏄惁鍙互蹇�熸寫鎴�
     public bool CanFastChallenge()
     {
diff --git a/Main/Utility/EnumHelper.cs b/Main/Utility/EnumHelper.cs
index 4096fc4..65646a6 100644
--- a/Main/Utility/EnumHelper.cs
+++ b/Main/Utility/EnumHelper.cs
@@ -665,7 +665,7 @@
     CDBPlayerRefresh_SkillReducePerG = 228, //灏勬棩绁炲紦鎶�鑳藉噺浼ょ櫨鍒嗘瘮
 
     //鍚庣画IL寮�鍙戞坊鍔犻璁�
-    default1,   // 229 
+    default1,   // 229 璐﹀彿鐘舵��
     default2,   //230
     default3,   // 鍔熻兘鐗规潈浠� 231
     default4,   //  鐜繚鍊� 232
@@ -1815,6 +1815,8 @@
     TimeRushAct = 200,  //杞洖娈�(姝﹀皢鍐插埡)
     HeroDebutAct = 201,  //鑻遍泟鐧诲満娲诲姩
     HeroReturnAct = 202,  //鑻遍泟杩斿満娲诲姩
+    TotalRechargeAct = 4,   //绱厖娲诲姩
+    TotDayRechargeAct = 5,  //绱厖澶╂椿鍔�
 }
 
 //浠欑帀璐拱鐨勪簩娆$‘璁ゆ绫诲瀷
diff --git a/Main/Utility/OperationLogCollect.cs b/Main/Utility/OperationLogCollect.cs
index 132fdd0..135fbd1 100644
--- a/Main/Utility/OperationLogCollect.cs
+++ b/Main/Utility/OperationLogCollect.cs
@@ -9,6 +9,64 @@
 {
 
 #if TEST_BUILD
+    const string url = "http://gamecenter.secondworld.net.cn:11000/center/eventreport.php?";
+#else
+    const string url = "http://xssgcenter.secondworld.net.cn:11000/center/eventreport.php?";
+#endif
+
+    //6001 鍚姩娓告垙
+    //6002 璇锋眰鐗堟湰淇℃伅
+    //6003 鍑嗗涓嬭浇
+    //6004 寮�濮嬩笅杞�
+    //6005 鍔犺浇浠g爜
+    //6006 鍚姩浠g爜
+    //6007 杩涘叆娓告垙
+    //6008 鎷疯礉琛ㄦ牸
+    //6009 璇锋眰鏉冮檺
+    //6010 鍒濆鍖栬缃�
+    //6011 sdk鍒濆鍖�
+    //6012 娓告垙鐗堟湰淇℃伅
+    //6013 妫�娴嬭祫婧�
+    //6014 涓嬭浇璧勬簮
+    //6015 鍔犺浇璧勬簮
+    //6016 鍔犺浇琛ㄦ牸
+    //6017 鍔犺浇 shader
+    //6018 鏄剧ず鐧诲綍鐣岄潰
+
+    //6101 SDK鍒濆鍖栨垚鍔�
+    //6102 SDK鍒濆鍖栧け璐�
+    //6103 SDK璐﹀彿鐧诲綍鎴愬姛
+    //6104 SDK璐﹀彿鐧诲綍澶辫触
+    public void RecordLauchEvent(int _step)
+    {
+#if !UNITY_EDITOR
+        //榛樿鍙戦�佸嵆浣胯〃娌℃湁鍒濆鍖�
+        if (SDKUtils.Instance.AssetCopyFinished)
+        {
+            var config = InitialFunctionConfig.Get("Event");
+            if (config != null && config.Numerical1 != "1")
+            {
+                return;
+            }
+        }
+        var tables = new Dictionary<string, string>();
+        tables["OperatorID"] = VersionConfig.Get().appId;
+        tables["RegionName"] = "data";
+        tables["EventID"] = (6000 + _step).ToString();
+        tables["ProductID"] = VersionConfig.Get().gameId;
+        tables["Device"] = DeviceUtility.GetDeviceModel();
+        tables["os_version"] = DeviceUtility.GetDeviceOSLevel();
+        tables["game_version"] = StringUtility.Concat(VersionConfig.Get().version, "_", VersionConfig.Get().buildIndex.ToString());
+        tables["IMEI"] = DeviceUtility.GetDeviceUniquenessIdentify();
+        tables["Time"] = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+
+        HttpRequest.Instance.RequestHttpGet(StringUtility.Concat(url, HttpRequest.HashtablaToString(tables)), HttpRequest.defaultHttpContentType);
+#endif
+    }
+
+
+
+#if TEST_BUILD
     const string bugReportUrl = "http://gamecenter.secondworld.net.cn:11000/center/eventreport.php?";
 #else
     const string bugReportUrl = "http://xssgcenter.secondworld.net.cn:11000/center/eventreport.php?";
@@ -104,6 +162,7 @@
         tables["ProductID"] = VersionConfig.Get().gameId;
         tables["OperatorID"] = VersionConfig.Get().appId;
         tables["OperatorName"] = string.Empty;
+        tables["ChannelType"] = chatType.ToString();
         tables["RegionName"] = StringUtility.Concat("s", ServerListCenter.Instance.currentServer.region_flag.ToString());
         tables["RegionID"] = ServerListCenter.Instance.currentServer.region_flag.ToString();
         tables["EventID"] = 9003.ToString();
@@ -115,6 +174,7 @@
         tables["RoleID"] = StringUtility.Concat(isFairy ? UIHelper.ServerStringTrim(PlayerDatas.Instance.baseData.FamilyName) : string.Empty,
            isFairy ? "-" : string.Empty, UIHelper.ServerStringTrim(PlayerDatas.Instance.baseData.PlayerName));
         tables["ToRoleID"] = UIHelper.ServerStringTrim(toPlayer);
+        tables["PlayerID"] = PlayerDatas.Instance.baseData.PlayerID.ToString();
         tables["Level"] = PlayerDatas.Instance.baseData.LV.ToString();
         tables["VIPLevel"] = PlayerDatas.Instance.baseData.VIPLv.ToString();
         tables["Content"] = UrlEncode(UIHelper.TrimContentToServer(content));
diff --git a/Main/Utility/UIHelper.cs b/Main/Utility/UIHelper.cs
index 0c20d9b..4a8b288 100644
--- a/Main/Utility/UIHelper.cs
+++ b/Main/Utility/UIHelper.cs
@@ -549,6 +549,25 @@
             case 28:
             case 29:
                 return GetUIColor(TextColType.itemyonghen, bright);
+            case 30:
+            case 31:
+            case 32:
+            case 33:
+            case 34:
+                return GetUIColor(TextColType.itemanjin, bright);
+            case 35:
+            case 36:
+            case 37:
+            case 38:
+            case 39:
+                return GetUIColor(TextColType.itemchuanqi, bright);
+            case 40:
+            case 41:
+            case 42:
+            case 43:
+            case 44:
+                return GetUIColor(TextColType.itemshenhua, bright);
+                
 
 
         }
@@ -667,6 +686,25 @@
             case 28:
             case 29:
                 return GetUIOutlineColor(QualityTextColType.itemyonghen);
+            case 30:
+            case 31:
+            case 32:
+            case 33:
+            case 34:
+                return GetUIOutlineColor(QualityTextColType.itemanjin);
+            case 35:
+            case 36:
+            case 37:
+            case 38:
+            case 39:
+                return GetUIOutlineColor(QualityTextColType.itemchuanqi);
+            case 40:
+            case 41:
+            case 42:
+            case 43:
+            case 44:
+                return GetUIOutlineColor(QualityTextColType.itemshenhua);
+
         }
         return GetUIOutlineColor(QualityTextColType.itemputong);
     }
@@ -980,6 +1018,24 @@
             case 28:
             case 29:
                 return AppendColor(TextColType.itemyonghen, msg, bright);
+            case 30:
+            case 31:
+            case 32:
+            case 33:
+            case 34:
+                return AppendColor(TextColType.itemanjin, msg, bright);
+            case 35:
+            case 36:
+            case 37:
+            case 38:
+            case 39:
+                return AppendColor(TextColType.itemchuanqi, msg, bright);
+            case 40:
+            case 41:
+            case 42:
+            case 43:
+            case 44:
+                return AppendColor(TextColType.itemshenhua, msg, bright);
 
         }
         return msg;

--
Gitblit v1.8.0