From b8f554f03a6114db353736741eda63bdd6c63854 Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期三, 22 四月 2026 10:06:52 +0800
Subject: [PATCH] 125 战斗 战斗代码整理 修复卡死问题

---
 Main/System/Battle/Skill/SkillBase.Buff.cs          |   65 +
 Main/System/Battle/Motion/MotionBase.cs             |  118 +
 Main/System/Battle/Skill/SkillBase.Hit.cs.meta      |   11 
 Main/System/Battle/Skill/SkillBase.Death.cs         |  325 +++++
 Main/System/Battle/Skill/SkillBase.SubSkill.cs.meta |   11 
 Main/System/Battle/SkillEffect/SkillEffect.cs       |    8 
 Main/System/Battle/BattleObject/HeroBattleObject.cs |    4 
 Main/System/Battle/Skill/SkillBase.Finish.cs        |  464 ++++++++
 Main/System/Battle/BattleField/BattleField.cs       |   28 
 Main/System/Battle/Skill/SkillBase.Cast.cs.meta     |   11 
 Main/System/Battle/Skill/SkillBase.Buff.cs.meta     |   11 
 Main/System/Battle/RecordPlayer/RecordPlayer.cs     |   96 +
 Main/System/Battle/BattleDebug.cs                   |   42 
 Main/System/Battle/Skill/SkillBase.Death.cs.meta    |   11 
 Main/System/Battle/Skill/SkillBase.Finish.cs.meta   |   11 
 Main/System/Battle/Skill/SkillBase.Hit.cs           |  241 ++++
 Main/System/Battle/Skill/SkillBase.SubSkill.cs      |   86 +
 Main/System/Battle/Skill/SkillBase.cs               | 1534 ++------------------------
 Main/System/Battle/Skill/SkillBase.Cast.cs          |  366 ++++++
 19 files changed, 2,022 insertions(+), 1,421 deletions(-)

diff --git a/Main/System/Battle/BattleDebug.cs b/Main/System/Battle/BattleDebug.cs
index caa6a06..ac44a9a 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);
 		}
 #endif
 	}
diff --git a/Main/System/Battle/BattleField/BattleField.cs b/Main/System/Battle/BattleField/BattleField.cs
index f53eaba..39cdac7 100644
--- a/Main/System/Battle/BattleField/BattleField.cs
+++ b/Main/System/Battle/BattleField/BattleField.cs
@@ -107,6 +107,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
@@ -123,6 +138,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)
@@ -130,6 +152,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)
diff --git a/Main/System/Battle/BattleObject/HeroBattleObject.cs b/Main/System/Battle/BattleObject/HeroBattleObject.cs
index 8b6f0ad..df429c0 100644
--- a/Main/System/Battle/BattleObject/HeroBattleObject.cs
+++ b/Main/System/Battle/BattleObject/HeroBattleObject.cs
@@ -186,9 +186,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()
diff --git a/Main/System/Battle/Motion/MotionBase.cs b/Main/System/Battle/Motion/MotionBase.cs
index ce84ec0..56be39a 100644
--- a/Main/System/Battle/Motion/MotionBase.cs
+++ b/Main/System/Battle/Motion/MotionBase.cs
@@ -34,11 +34,35 @@
     // 瀛愭妧鑳借建閬撴睜绠$悊锛堝湪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;
+    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());
+            }
+#endif
+            _playingSkillWithAnim = value;
+        }
+    }
 
     private bool isUnderControl = false;
 
@@ -151,6 +175,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()
@@ -293,6 +349,9 @@
         // startTime 琛ㄧず鎶�鑳�"鏈湴閫昏緫鏃堕棿"鐨勮捣鐐癸紙浠� Time.time 涓哄熀鍑嗭級
         float startTime = hasAnim ? 0f : Time.time;
 
+        //  鐧昏鍒版椿璺冮泦鍚堬紝璁� HaveRest / ResetForReborn 鐭ラ亾鏈夊摢浜� skillBase 闇�瑕佸湪娓呭瓧鍏稿墠琚己鍒剁粨鏉熴��
+        activeSkillBases.Add(skillBase);
+
         skillBase.OnSkillStart();
 
         Action frameHandler = null;
@@ -326,7 +385,7 @@
 
                 
                 
-                RemoveAction(frameHandler);
+                RemoveSkillAnim(frameHandler, skillBase);
                 return;
             }
 
@@ -360,7 +419,7 @@
                     skillBase.ForceFinished();
 
                     // 娓呯悊骞剁‘淇濈姸鎬佸浣�
-                    RemoveAction(frameHandler);
+                    RemoveSkillAnim(frameHandler, skillBase);
                     
                     // 鍥炴敹瀛愭妧鑳借建閬�
                     if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
@@ -383,7 +442,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 +557,7 @@
 
                     // skillTrackDict.Remove(trackIndex);
 
-                    RemoveAction(frameHandler);
+                    RemoveSkillAnim(frameHandler, skillBase);
                     onComplete?.Invoke();
                     skillBase.OnFinalFrameEnd();
                     if (hasAnim)
@@ -647,6 +706,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 +737,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 +803,10 @@
         
         // 5. 閲嶇疆鎵�鏈夌姸鎬佹爣蹇�
         playingSkill = false;
+        //  reviveSelf 鍒嗘敮涓� runningActions 娌¤娓咃紝涓绘妧鑳� frameHandler 浼氳嚜宸辫蛋鍒� OnFinalFrameEnd 閭i噷澶嶄綅锛�
+        //  闈� reviveSelf 鍒嗘敮涓� runningActions 宸叉竻骞插噣锛岃繖閲屼竴骞跺浣嶃��
+        if (!reviveSelf)
+            playingSkillWithAnim = false;
         isUnderControl = false;
         
         // 6. 閲嶇疆鏃堕棿鐩稿叧瀛楁锛堝叧閿紒锛�
@@ -753,6 +854,11 @@
         return !playingSkillWithAnim || string.IsNullOrEmpty(skillSkinConfig.SkillMotionName);
     }
 
+#if UNITY_EDITOR
+    /// <summary>鍗℃璇婃柇鐢細鏆撮湶 playingSkillWithAnim 鏍囧織浣嶃��</summary>
+    public bool PlayingSkillWithAnimForDebug => playingSkillWithAnim;
+#endif
+
     public bool CanStartDeath()
     {
         return !playingSkillWithAnim;
diff --git a/Main/System/Battle/RecordPlayer/RecordPlayer.cs b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
index 83300c5..52440ff 100644
--- a/Main/System/Battle/RecordPlayer/RecordPlayer.cs
+++ b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
@@ -45,6 +45,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;
@@ -215,6 +302,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..14d5b8c
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Cast.cs
@@ -0,0 +1,366 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using Spine;
+
+// SkillBase锛圕ast 閮ㄥ垎锛夛細鏂芥硶闃舵鈥斺�旂Щ鍔ㄣ�佸姩鐢汇�佹畫褰便�侀珮浜�佹敾鍑荤粨鏉熴��
+public partial class SkillBase
+{
+    // 鎶�鑳介噴鏀句富閫昏緫锛氬箍鎾簨浠躲�侀珮浜洰鏍囥�佹墽琛岄噴鏀�
+    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);
+        }
+
+        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)
+    {
+        ShadowIllutionCreate(true);
+        MoveToTarget(target, new Vector2(skillSkinConfig.CastDistance, 0), () =>
+        {
+            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 (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;
+        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..f50d207
--- /dev/null
+++ b/Main/System/Battle/Skill/SkillBase.Finish.cs
@@ -0,0 +1,464 @@
+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}";
+        }
+        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 bad1562..3f64d78 100644
--- a/Main/System/Battle/Skill/SkillBase.cs
+++ b/Main/System/Battle/Skill/SkillBase.cs
@@ -1,12 +1,22 @@
-using System.Collections.Generic;
+锘縰sing System.Collections.Generic;
 using UnityEngine;
 using DG.Tweening;
 using Spine;
 using System.Linq;
 using System;
 
-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,
@@ -16,40 +26,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)
@@ -73,7 +158,7 @@
         {
             skillSkinConfig = skillConfig.GetOriginSkinConfig();
         }
-        
+
 
         // 娉ㄥ唽姝e湪閲婃斁鐨勬妧鑳�
         if (battleField != null && caster != null)
@@ -86,7 +171,7 @@
 
     public virtual void AfterAddToQueue()
     {
-        
+
     }
 
     //  璁剧疆鐖禦ecordAction
@@ -95,31 +180,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";
@@ -128,7 +210,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";
                 }
             }
@@ -141,11 +223,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";
@@ -161,7 +243,7 @@
             string origin = changeListDict[caster.battleField.guid];
             origin += skillDetail;
             changeListDict[caster.battleField.guid] = origin;
-            
+
         }
         else
             changeListDict.Add(caster.battleField.guid, skillDetail);
@@ -179,19 +261,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();
         }
-
-        
     }
 
     // 鎶�鑳借繍琛屼富閫昏緫锛氬鐞嗘妧鑳芥晥鏋滃拰鍏朵粬鎶�鑳藉姩浣�
@@ -210,290 +290,6 @@
             }
             return;
         }
-
-
-    }
-
-    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);
-        }
-
-        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)
-    {
-        ShadowIllutionCreate(true);
-        MoveToTarget(target, new Vector2(skillSkinConfig.CastDistance, 0), () =>
-        {
-            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 (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;
-        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);
     }
 
     // 鎶�鑳藉紑濮嬪洖璋冿細澶勭悊姝讳骸銆佸瓙鎶�鑳姐�佹妧鑳芥晥鏋滃垵濮嬪寲
@@ -513,86 +309,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() { }
@@ -621,1019 +343,7 @@
         //  鏍囪鍔ㄧ敾鎾斁瀹屾垚
         isMotionCompleted = true;
         BattleDebug.LogError($"SkillBase.OnFinalFrameEnd: 鎶�鑳� {skillConfig?.SkillID} 鍔ㄧ敾鎾斁瀹屾垚");
-        
+
         skillEffect?.OnFinalFrameEnd(); // 淇锛氭坊鍔犵┖鍊兼鏌�
     }
-
-    // 楂樹寒鎵�鏈夌浉鍏崇洰鏍囷細璁剧疆鏂芥硶鑰呭拰鐩爣鐨勬樉绀哄眰绾�
-    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);
-    }
-
-
-    // 鍛戒腑鐩爣鍥炶皟锛氬鐞嗘墍鏈夎鍛戒腑鐨勭洰鏍囷紙鍖呮嫭涓荤洰鏍囥�佸脊灏勭洰鏍囥�佹簠灏勭洰鏍囷級
-    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>(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;
-    }
-
-    // 妫�鏌ユ浜″悗鐨勫寘澶勭悊锛氬鐞嗘妧鑳藉寘銆佹帀钀藉寘銆佺粡楠屽寘
-    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;
-    }
-
-    // 妫�鏌ユ妧鑳芥槸鍚﹀畬鎴愶細缁煎悎妫�鏌ユ墍鏈夊畬鎴愭潯浠�
-    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;
-            }
-
-            //  濡傛灉鑷繁鍐呴儴鐨剅ecora action鐨� inner record player杩樻湁娌℃墽琛屽畬鐨勫寘 涔熸槸杩斿洖false
-            if (ownRecordAction != null && ownRecordAction.GetInnerRecordPlayer().IsPlaying())
-            {
-                return false;
-            }
-
-            // 鎶�鑳藉畬鍏ㄧ粨鏉燂紝绉婚櫎鎶�鑳芥敞鍐屽苟瑙﹀彂寤惰繜鐨勬浜″垽瀹�
-            if (battleField != null && caster != null)
-            {
-                battleField.RemoveCastingSkill(caster.ObjID, this);
-                
-                //  浼犻�抪arentRecordAction锛岃姝讳骸鎶�鑳界瓑寰呭綋鍓嶆妧鑳藉畬鎴�
-                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);
-        }
-
-        // 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);
-
-                //  闇�瑕佺粰鐪熸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;
-    }
-
-    #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 3fecf16..18179af 100644
--- a/Main/System/Battle/SkillEffect/SkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/SkillEffect.cs
@@ -78,6 +78,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;

--
Gitblit v1.8.0