From cec8b67d82c2c2c1662d55c818c4a46bcc0487db Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期一, 25 八月 2025 17:36:02 +0800
Subject: [PATCH] 125 【战斗】战斗系统 战斗技能

---
 Main/System/Battle/SkillEffect/NormalSkillEffect.cs                                |   17 
 Main/System/Battle/BattleObject/BattleObjectFactory.cs                             |   17 
 Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs                    |    2 
 Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs                  |   18 
 Main/System/Battle/Motion/MotionBase.cs                                            |   10 
 Main/System/Battle/BattleField/StoryBattleField.cs                                 |   12 
 Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs                   |   20 
 Main/System/Battle/SkillEffect/SkillEffectFactory.cs                               |    2 
 Main/System/Battle/BattleField/BattleField.cs                                      |   96 ++++
 Main/Core/NetworkPackage/CustomServerPack/CustomB421ActionPack.cs                  |    9 
 Main/System/Battle/BattleDebug.cs                                                  |   13 
 Main/System/Battle/BattleObject/BattleObject.cs                                    |    6 
 Main/System/Battle/Skill/DirectlyHealSkill.cs                                      |    2 
 Main/System/Battle/BattleEffectMgr.cs                                              |   24 +
 Main/System/Battle/BattleField/RecordActions/EditorSkillRecordAction.cs            |    4 
 Main/Component/UI/Effect/BattleEffectPlayer.cs                                     |   32 
 Main/System/Battle/TestMoveToTarget.cs                                             |   25 +
 Main/System/Battle/BattleDebug.cs.meta                                             |   11 
 Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs                          |   13 
 Main/System/Battle/Skill/SkillFactory.cs                                           |    2 
 Main/System/Battle/BattleManager.cs                                                |   30 +
 Main/System/Battle/BattleUtility.cs                                                |  100 ++++
 Main/System/Battle/BattleWin.cs                                                    |    4 
 Main/System/Battle/Skill/DirectlyDamageSkill.cs                                    |   59 --
 Main/System/Battle/BattleField/RecordActions/TestAction.cs.meta                    |   11 
 Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs.meta               |   11 
 Main/System/Battle/BattleField/OperationAgent/StopModeOperationAgent.cs            |    1 
 Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs.meta               |   11 
 Main/System/Battle/SkillEffect/SkillEffect.cs                                      |   11 
 Main/Core/NetworkPackage/CustomServerPack/CustomHB426CombinePack.cs                |   19 +
 Main/System/Battle/SkillEffect/BulletSkillEffect.cs                                |   73 ++
 Main/System/Battle/BattleField/RecordActions/TestAction.cs                         |   69 +++
 Main/System/Battle/RecordPlayer/RecordAction.cs                                    |    3 
 Main/System/Battle/RecordPlayer/RecordPlayer.cs                                    |    8 
 Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs                    |   35 +
 Main/System/Battle/Skill/SkillBase.cs                                              |  194 ++++++----
 Main/System/Battle/BattleObject/BattleObjMgr.cs                                    |   14 
 Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs                    |   73 +++
 Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs                  |   22 
 Main/System/Team/TeamHero.cs                                                       |    4 
 Main/Core/NetworkPackage/DTCFile/ServerPack/H04_Scene/DTC0418_tagObjInfoRefresh.cs |   10 
 Main/System/Battle/TestMoveToTarget.cs.meta                                        |   11 
 Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs            |   14 
 43 files changed, 861 insertions(+), 261 deletions(-)

diff --git a/Main/Component/UI/Effect/BattleEffectPlayer.cs b/Main/Component/UI/Effect/BattleEffectPlayer.cs
index 5dc1a4b..853ecf8 100644
--- a/Main/Component/UI/Effect/BattleEffectPlayer.cs
+++ b/Main/Component/UI/Effect/BattleEffectPlayer.cs
@@ -184,6 +184,12 @@
             this.gameObject.SetActive(true);
         }
 
+        if (effectConfig.autoDestroy != 0)
+        {
+            GameObject.Destroy(gameObject, effectConfig.destroyDelay);
+        }
+
+
         PlayEffect();
         
 
@@ -396,25 +402,19 @@
 
 
     //  鍒涘缓鍚庣殑鐗规晥浼氳嚜鍔ㄩ殣钘� 闇�瑕佹墜鍔ㄨ皟鐢≒lay鎵嶈兘鎾斁
-    public static BattleEffectPlayer Create(int effectId, Transform parent, bool createNewChild = false)
+    public static BattleEffectPlayer Create(int effectId, Transform parent)
     {
         // 鐩存帴鍒涘缓鐗规晥鎾斁鍣紝涓嶄娇鐢ㄥ璞℃睜
-        BattleEffectPlayer BattleEffectPlayer = null;
+        BattleEffectPlayer battleEffectPlayer = null;
 
-        if (createNewChild)
-        {
-            GameObject newGo = new GameObject("BattleEffectPlayer_" + effectId);
-            newGo.transform.SetParent(parent, false);
-            BattleEffectPlayer = newGo.AddComponent<BattleEffectPlayer>();
-        }
-        else
-        {
-            BattleEffectPlayer = parent.AddMissingComponent<BattleEffectPlayer>();
-        }
-
-        BattleEffectPlayer.effectId = effectId;
-        BattleEffectPlayer.SetActive(true);
-        return BattleEffectPlayer;
+        GameObject newGo = new GameObject("BattleEffectPlayer_" + effectId);
+        newGo.transform.SetParent(parent, false);
+        newGo.AddMissingComponent<RectTransform>();
+        battleEffectPlayer = newGo.AddComponent<BattleEffectPlayer>();
+        
+        battleEffectPlayer.effectId = effectId;
+        battleEffectPlayer.SetActive(true);
+        return battleEffectPlayer;
     }
 
     /// <summary>
diff --git a/Main/Core/NetworkPackage/CustomServerPack/CustomB421ActionPack.cs b/Main/Core/NetworkPackage/CustomServerPack/CustomB421ActionPack.cs
index 78bb4d2..718f080 100644
--- a/Main/Core/NetworkPackage/CustomServerPack/CustomB421ActionPack.cs
+++ b/Main/Core/NetworkPackage/CustomServerPack/CustomB421ActionPack.cs
@@ -18,13 +18,13 @@
         return actionPack;
     }
 
-    public void Distribute()
+    public bool Distribute()
     {
-        while (actionPacks.Count > 0)
+        if (actionPacks.Count > 0)
         {
             GameNetPackBasic pack = actionPacks.Dequeue();
 
-            Debug.LogError("CustomB421ActionPack distribute pack " + pack.GetType().Name);
+            BattleDebug.LogError("CustomB421ActionPack distribute pack " + pack.GetType().Name);
 
             if (pack is CustomHB426CombinePack)
             {
@@ -33,8 +33,11 @@
             }
             else
             {
+                BattleDebug.LogError("distribute pack " + pack.GetType().Name);
                 PackageRegedit.Distribute(pack);
             }
         }
+
+        return actionPacks.Count > 0;
     }
 }
\ No newline at end of file
diff --git a/Main/Core/NetworkPackage/CustomServerPack/CustomHB426CombinePack.cs b/Main/Core/NetworkPackage/CustomServerPack/CustomHB426CombinePack.cs
index beb0ffd..2593088 100644
--- a/Main/Core/NetworkPackage/CustomServerPack/CustomHB426CombinePack.cs
+++ b/Main/Core/NetworkPackage/CustomServerPack/CustomHB426CombinePack.cs
@@ -166,6 +166,7 @@
         if (startTag.Tag.StartsWith("Skill_"))
         {
             HB427_tagSCUseSkill skill = packList[0] as HB427_tagSCUseSkill;
+            packList.Remove(skill);
             BattleObject _caster = battleField.battleObjMgr.GetBattleObject((int)skill.ObjID);
             SkillRecordAction skillAction = new SkillRecordAction(battleField, _caster, skill, packList);
             return skillAction;
@@ -173,4 +174,22 @@
 
         return null;
     }
+
+#if UNITY_EDITOR
+    public static CustomHB426CombinePack CreateCustomPack(string _guid, HB427_tagSCUseSkill skill)
+    {
+        CustomHB426CombinePack pack = new CustomHB426CombinePack();
+        pack.guid = string.Empty;
+
+        pack.startTag = new HB426_tagSCTurnFightTag
+        {
+            Tag = "Skill_Start",
+            Sign = 0
+        };
+
+        pack.packList.Add(skill);
+
+        return pack;
+    }
+#endif
 }
\ No newline at end of file
diff --git a/Main/Core/NetworkPackage/DTCFile/ServerPack/H04_Scene/DTC0418_tagObjInfoRefresh.cs b/Main/Core/NetworkPackage/DTCFile/ServerPack/H04_Scene/DTC0418_tagObjInfoRefresh.cs
index a78cb09..e160113 100644
--- a/Main/Core/NetworkPackage/DTCFile/ServerPack/H04_Scene/DTC0418_tagObjInfoRefresh.cs
+++ b/Main/Core/NetworkPackage/DTCFile/ServerPack/H04_Scene/DTC0418_tagObjInfoRefresh.cs
@@ -5,7 +5,8 @@
 //04 18 鍛ㄥ洿瀵硅薄鍒锋柊#tagObjInfoRefresh
 
 public class DTC0418_tagObjInfoRefresh : DtcBasic {
-    public override void Done(GameNetPackBasic vNetPack) {
+    public override void Done(GameNetPackBasic vNetPack)
+    {
         base.Done(vNetPack);
         H0418_tagObjInfoRefresh vNetData = vNetPack as H0418_tagObjInfoRefresh;
 
@@ -22,6 +23,12 @@
                 break;
             default:
                 break;
+        }
+
+        BattleField battleField = BattleManager.Instance.GetBattleField(vNetData.packUID);
+        if (null != battleField)
+        {
+            battleField.DistributeNextPackage();
         }
     }
 
@@ -44,6 +51,5 @@
     {
         BattleField battleField = BattleManager.Instance.GetBattleField(vNetData.packUID);
         battleField.ObjInfoRefresh(vNetData);
-        battleField.DistributeNextPackage();
     }
 }
diff --git a/Main/System/Battle/BattleDebug.cs b/Main/System/Battle/BattleDebug.cs
new file mode 100644
index 0000000..243e018
--- /dev/null
+++ b/Main/System/Battle/BattleDebug.cs
@@ -0,0 +1,13 @@
+using UnityEngine;
+
+
+public static class BattleDebug
+{
+	public static void LogError(string _logMessage)
+	{
+		if (Launch.Instance.isOpenBattleDebug)
+		{
+			Debug.LogError(_logMessage);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Main/System/Battle/BattleDebug.cs.meta b/Main/System/Battle/BattleDebug.cs.meta
new file mode 100644
index 0000000..745462d
--- /dev/null
+++ b/Main/System/Battle/BattleDebug.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 404517adec3b9ab41ad061c30e7bea6c
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/BattleEffectMgr.cs b/Main/System/Battle/BattleEffectMgr.cs
index 2c5e120..755757d 100644
--- a/Main/System/Battle/BattleEffectMgr.cs
+++ b/Main/System/Battle/BattleEffectMgr.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using UnityEngine;
 
 public class BattleEffectMgr : MonoBehaviour
@@ -45,12 +46,14 @@
     {
         if (effectId <= 0)
         {
+            BattleDebug.LogError("effect id <= 0");
             return null;
         }
 
         var effectCfg = EffectConfig.Get(effectId);
         if (null == effectCfg)
         {
+            BattleDebug.LogError("effect config is null, effectId : " + effectId);
             return null;
         }
 
@@ -59,12 +62,16 @@
             effectDict[effectId] = new List<BattleEffectPlayer>();
         }
 
-        BattleEffectPlayer effectPlayer = BattleEffectPlayer.Create(effectId, parent);
+        BattleEffectPlayer effectPlayer = BattleEffectPlayer.Create(effectId, battleField.battleRootNode.transform);
+        effectPlayer.transform.position = parent.position;
+        float effectScale = parent.transform.localScale.x;
+        effectPlayer.transform.localScale *= effectScale;
         effectPlayer.onDestroy += OnEffectDestroy;
         if (effectPlayer != null)
         {
             effectDict[effectId].Add(effectPlayer);
         }
+        effectPlayer.Play(true);
         return effectPlayer;
     }
 
@@ -80,7 +87,7 @@
         }
         else
         {
-            Debug.LogError("could not find effect in list, effectid : " + effectId);
+            BattleDebug.LogError("could not find effect in list, effectid : " + effectId);
         }
     }
 
@@ -98,16 +105,25 @@
 
     public void HaveRest()
     {
-        foreach (KeyValuePair<int, List<BattleEffectPlayer>> kvPair in effectDict)
+        List<int> fKeys = effectDict.Keys.ToList();
+
+        for (int i = 0; i < fKeys.Count; i++)
         {
-            foreach (BattleEffectPlayer effectPlayer in kvPair.Value)
+            List<BattleEffectPlayer> effectPlayers = effectDict[fKeys[i]];
+            while (effectPlayers.Count > 0)
             {
+                var effectPlayer = effectPlayers[0];
                 if (effectPlayer != null)
                 {
                     GameObject.DestroyImmediate(effectPlayer.gameObject);
                 }
+                else
+                {
+                    effectPlayers.RemoveAt(0);
+                }
             }
         }
+
         effectDict.Clear();
     }
 
diff --git a/Main/System/Battle/BattleField/BattleField.cs b/Main/System/Battle/BattleField/BattleField.cs
index 073df12..1de9db3 100644
--- a/Main/System/Battle/BattleField/BattleField.cs
+++ b/Main/System/Battle/BattleField/BattleField.cs
@@ -146,7 +146,7 @@
 
         if (operationAgent == null)
         {
-            Debug.LogError("you should SetBattleMode before Run");
+            BattleDebug.LogError("you should SetBattleMode before Run");
             return;
         }
 
@@ -178,7 +178,7 @@
                 break;
         }
 
-        Debug.LogError("battleMode is " + battleMode.ToString());
+        BattleDebug.LogError("battleMode is " + battleMode.ToString());
     }
 
     public virtual void AutoSetBattleMode()
@@ -283,8 +283,11 @@
 
     public virtual void OnObjsDead(List<HB422_tagMCTurnFightObjDead> deadPackList)
     {
-        DeathRecordAction recordAction = new DeathRecordAction(this, deadPackList);
-        recordPlayer.PlayRecord(recordAction);
+        if (deadPackList.Count > 0)
+        {
+            DeathRecordAction recordAction = new DeathRecordAction(this, deadPackList);
+            recordPlayer.PlayRecord(recordAction);
+        }
     }
 
     public virtual void Destroy()
@@ -328,7 +331,7 @@
     {
         if (index < 0 || index >= battleRootNode.redTeamNodeList.Count)
         {
-            Debug.LogError($"GetTeamNode: Index {index} is out of range for {battleCamp} camp.");
+            BattleDebug.LogError($"GetTeamNode: Index {index} is out of range for {battleCamp} camp.");
             return null;
         }
 
@@ -402,18 +405,95 @@
         }
         else
         {
-            Debug.LogError($"BattleObject with ID {vNetData.ObjID} not found for reborn.");
+            BattleDebug.LogError($"BattleObject with ID {vNetData.ObjID} not found for reborn.");
         }
+    }
+
+    protected virtual void OnSettlement(JsonData turnFightStateData)
+    {
+
     }
 
 
     public virtual void OnBattleEnd(JsonData turnFightStateData)
     {
+        BattleEndAction battleEndAction = new BattleEndAction(this, turnFightStateData, () =>
+        {
+            BattleDebug.LogError(turnFightStateData.ToJson());
+            // 杩欓噷鍙互娣诲姞鎴樻枟缁撴潫鐨勫叿浣撻�昏緫
+            OnSettlement(turnFightStateData);
+
+            int winFaction = (int)turnFightStateData["winFaction"];
+            //鑾疯儨闃佃惀:   涓�鑸负1鎴栬��2锛屽綋鐜╁鍙戣捣鐨勬垬鏂楁椂锛屽鏋滆幏鑳滈樀钀ヤ笉绛変簬1浠h〃鐜╁澶辫触浜�
+
+            if (winFaction == 1)
+            {
+                Debug.LogError("鎴樻枟鑳滃埄");
+                //  鎴樻枟鑳滃埄
+
+                //  濡傛灉鏄嚜鍔ㄦ垬鏂楄浆鑷姩鎴樻枟锛�
+            }
+            else
+            {
+                //  鎴樻枟澶辫触
+                Debug.LogError("鎴樻枟澶辫触");
+                HaveRest();
+            }
+
+            IsBattleFinish = true;
+            
+        });
+        recordPlayer.PlayRecord(battleEndAction);
         // 澶勭悊鎴樻枟缁撴潫閫昏緫
-        IsBattleFinish = true;
+        // IsBattleFinish = true;
         // 缁撶畻閫昏緫
 
-        // {"winFaction":鑾疯儨闃佃惀, "statInfo":缁熻淇℃伅, 鈥渋temInfo鈥�:[濂栧姳鐗╁搧淇℃伅鍒楄〃]}
+            // {
+            // "itemInfo": [],
+            // "winFaction": 1,//鑾疯儨闃佃惀:   涓�鑸负1鎴栬��2锛屽綋鐜╁鍙戣捣鐨勬垬鏂楁椂锛屽鏋滆幏鑳滈樀钀ヤ笉绛変簬1浠h〃鐜╁澶辫触浜�
+            // "statInfo": {
+            //     "1": {
+            //     "1": {
+            //         "5": {
+            //         "NPCID": 0,
+            //         "DefHurt": 633,
+            //         "CureHP": 0,
+            //         "AtkHurt": 169247,
+            //         "ObjID": 1,
+            //         "HeroID": 510006
+            //         }
+            //     }
+            //     },
+            //     "2": {
+            //     "1": {
+            //         "2": {
+            //         "NPCID": 10101001,
+            //         "DefHurt": 169246,
+            //         "CureHP": 143096,
+            //         "AtkHurt": 999952,
+            //         "ObjID": 2,
+            //         "HeroID": 0
+            //         },
+            //         "4": {
+            //         "NPCID": 10101001,
+            //         "DefHurt": 0,
+            //         "CureHP": 0,
+            //         "AtkHurt": 0,
+            //         "ObjID": 3,
+            //         "HeroID": 0
+            //         },
+            //         "6": {
+            //         "NPCID": 10101001,
+            //         "DefHurt": 1,
+            //         "CureHP": 0,
+            //         "AtkHurt": 0,
+            //         "ObjID": 4,
+            //         "HeroID": 0
+            //         }
+            //     }
+            //     }
+            // }
+            // }
     }
 
     public virtual void HaveRest()
diff --git a/Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs b/Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs
index 8e75dcf..da8d3f5 100644
--- a/Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs
+++ b/Main/System/Battle/BattleField/OperationAgent/HandModeOperationAgent.cs
@@ -19,14 +19,14 @@
 	//	閫氳繃涓荤晫闈㈢殑鎸夐挳鎺ㄥ姩(璋冪敤)DoNext
 	public override void DoNext()
 	{
-		Debug.LogError("HandModeOperationAgent DoNext");
+		BattleDebug.LogError("HandModeOperationAgent DoNext");
 
 		base.DoNext();
 
 		//	褰撳墠娌℃湁鍦ㄦ挱鏀炬垬鏂楀綍鍍�
 		if (!battleField.recordPlayer.IsPlaying())
 		{
-			Debug.LogError("HandModeOperationAgent DoNext  1");
+			BattleDebug.LogError("HandModeOperationAgent DoNext  1");
 			// 娌℃湁涓嬩竴涓寘鍙互鍙戜簡
 			if (!BattleManager.Instance.DistributeNextPackage())
 			{
@@ -39,14 +39,14 @@
 
 				//	妫�鏌ヤ竴涓嬮敜瀛愮殑娑堣��
 				//FightPoint             鐢ㄤ簬璁板綍娑堣�楁垬閿ゅ�嶆暟锛屽皬浜庣瓑浜�1鏃堕粯璁�1鍊嶏紝澶т簬1鏃朵负瀵瑰簲娑堣�楀�嶅�硷紝0418鍒锋柊绫诲瀷22
-				Debug.LogError("HandModeOperationAgent DoNext  2");
+				BattleDebug.LogError("HandModeOperationAgent DoNext  2");
 				ulong costRate = PlayerDatas.Instance.GetPlayerDataByType(PlayerDataType.FightPoint);
 
 				ulong cost = (costRate > 1 ? costRate : 1) * 1; // 1鏄粯璁ゆ秷鑰�
 
 
 
-				Debug.LogError("HandModeOperationAgent DoNext  3");
+				BattleDebug.LogError("HandModeOperationAgent DoNext  3");
 				byte reqType;
 
 				if (storyBattleField.battleState == StoryBattleState.Break)
@@ -66,11 +66,11 @@
 				}
 				else
 				{
-					Debug.LogError("unknown battle state");
+					BattleDebug.LogError("unknown battle state");
 					return;
 				}
 
-				Debug.LogError("HandModeOperationAgent DoNext  4   reqType is " + reqType);
+				BattleDebug.LogError("HandModeOperationAgent DoNext  4   reqType is " + reqType);
 
 				//	妫�鏌ヤ竴涓嬮敜瀛愮殑娑堣��
 				if (!ItemLogicUtility.CheckCurrencyCount(41, cost, true))
@@ -90,7 +90,7 @@
 		}
 		else
 		{
-			Debug.LogError("action doesnt finish, wait a moment please");
+			BattleDebug.LogError("action doesnt finish, wait a moment please");
 		}
 	}
 
diff --git a/Main/System/Battle/BattleField/OperationAgent/StopModeOperationAgent.cs b/Main/System/Battle/BattleField/OperationAgent/StopModeOperationAgent.cs
index d7f9f8f..42af530 100644
--- a/Main/System/Battle/BattleField/OperationAgent/StopModeOperationAgent.cs
+++ b/Main/System/Battle/BattleField/OperationAgent/StopModeOperationAgent.cs
@@ -19,5 +19,6 @@
         base.DoNext();
 
         battleField.AutoSetBattleMode();
+        battleField.operationAgent.DoNext();
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs b/Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs
new file mode 100644
index 0000000..6daa870
--- /dev/null
+++ b/Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+using System.Collections.Generic;
+using System;
+using LitJson;
+
+
+public class BattleEndAction : RecordAction
+{
+    //  濂栧姳鏁版嵁涔嬬被鐨�
+    protected JsonData endData;
+
+    protected Action onComplete;
+
+    public BattleEndAction(BattleField _battleField, JsonData _endData, Action _onComplete)
+        : base(RecordActionType.Death, _battleField, null)
+    {
+        endData = _endData;
+        onComplete = _onComplete;
+    }
+
+    public override void Run()
+    {
+        base.Run();
+
+        Debug.Log("Battle Ended");
+        onComplete?.Invoke();
+        isFinish = true;
+    }
+
+    public override bool IsFinished()
+    {
+        return isFinish;
+    }
+
+}
diff --git a/Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs.meta b/Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs.meta
new file mode 100644
index 0000000..7f6bdef
--- /dev/null
+++ b/Main/System/Battle/BattleField/RecordActions/BattleEndAction.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 874d81ccb0bf1804c9c459982190f4da
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs b/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs
index cccff52..af95296 100644
--- a/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs
+++ b/Main/System/Battle/BattleField/RecordActions/DeathRecordAction.cs
@@ -25,25 +25,35 @@
         if (!isRunOnce)
         {
             isRunOnce = true;
+            bool isLastOne = false;
+            int index = 0;
+            int total = deadPackList.Count;
             foreach (var deadPack in deadPackList)
             {
+                index++;
+                isLastOne = index >= total;
                 BattleObject deadObj = battleField.battleObjMgr.GetBattleObject((int)deadPack.ObjID);
-                deadObj.OnDeath(OnDeathAnimationEnd);
+                deadObj.OnDeath(() =>
+                {
+                    OnDeathAnimationEnd(deadObj);
+
+                    if (isLastOne)
+                    {
+                    	isFinish = true;
+                    }
+                });
             }
             return;
         }
         
     }
 
-    private void OnDeathAnimationEnd()
+    private void OnDeathAnimationEnd(BattleObject deadObj)
     {
         //  鍙湁涓荤嚎鎺夎惤鐗╁搧
         if (battleField.MapID == 1 || battleField.MapID == 2)
         {
-            battleObject.PerformDrop();
+            deadObj.PerformDrop();
         }
-        // 鎺夎惤鐗╁搧 澧炲姞缁忛獙
-
-    	isFinish = true;
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/BattleField/RecordActions/EditorSkillRecordAction.cs b/Main/System/Battle/BattleField/RecordActions/EditorSkillRecordAction.cs
index a5d1d07..1c7a907 100644
--- a/Main/System/Battle/BattleField/RecordActions/EditorSkillRecordAction.cs
+++ b/Main/System/Battle/BattleField/RecordActions/EditorSkillRecordAction.cs
@@ -24,7 +24,7 @@
 
 // 		if (null == skillConfig)
 // 		{
-// 			Debug.LogError("鎵句笉鍒版妧鑳介厤缃� " + SkillId);
+// 			BattleDebug.LogError("鎵句笉鍒版妧鑳介厤缃� " + SkillId);
 // 		}
 
 // 		skillBase = SkillFactory.CreateSkill(skillConfig);
@@ -42,7 +42,7 @@
 
 // 		if (null == skillConfig)
 // 		{
-// 			Debug.LogError("鎵句笉鍒版妧鑳介厤缃� " + SkillId);
+// 			BattleDebug.LogError("鎵句笉鍒版妧鑳介厤缃� " + SkillId);
 // 		}
 
 // 		skillBase = SkillFactory.CreateSkill(skillConfig);
diff --git a/Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs b/Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs
new file mode 100644
index 0000000..9edef71
--- /dev/null
+++ b/Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs
@@ -0,0 +1,73 @@
+using UnityEngine;
+using System.Collections.Generic;
+using System;
+
+#if UNITY_EDITOR
+
+public class TestSkillAction : RecordAction
+{
+
+    public HB427_tagSCUseSkill vNetData;
+
+    public TestSkillAction(BattleField _battleField, int skillId, int hurtIndex)
+        : base(RecordActionType.Skill, _battleField, null)
+    {
+        try
+        {
+            vNetData = new HB427_tagSCUseSkill();
+
+            BattleObject battleObj = battleField.battleObjMgr.redCampList[0];
+
+            vNetData.ObjID = (uint)battleObj.ObjID;
+            vNetData.SkillID = (uint)skillId;
+            vNetData.PMType = 0;
+            vNetData.BattleType = 0;
+            vNetData.CurHP = 100;
+            vNetData.CurHPEx = 0;
+            vNetData.HurtCount = 1;
+            vNetData.HurtList = new HB427_tagSCUseSkill.tagSCUseSkillHurt[vNetData.HurtCount];
+
+            //  浼ゅ鐨勫璞�
+            BattleObject hurtObj = battleField.battleObjMgr.GetBattleObjectByIndex(BattleCamp.Blue, hurtIndex);
+            var hurt = new HB427_tagSCUseSkill.tagSCUseSkillHurt();
+            hurt.ObjID = (uint)hurtObj.ObjID;
+            hurt.AttackTypes = 1; // 鏅�氫激瀹�
+            hurt.HurtHP = 2; // 浼ゅ鍊�
+            hurt.HurtHPEx = 0;
+            hurt.CurHP = 100;
+            hurt.CurHPEx = 0;
+            hurt.SuckHP = 0;
+            hurt.BounceHP = 0;
+
+            vNetData.HurtList[0] = hurt;
+        }
+        catch (Exception err)
+        {
+            BattleDebug.LogError("Error occurred while creating TestSkillAction: " + err.Message);
+        }
+        
+
+    }
+
+    public override bool IsFinished()
+    {
+        return isFinish;
+    }
+
+    public override void Run()
+    {
+        base.Run();
+
+        if (!isRunOnce)
+        {
+            isRunOnce = true;
+            CustomHB426CombinePack pack = CustomHB426CombinePack.CreateCustomPack(string.Empty, vNetData);
+            battleField.recordPlayer.PlayRecord(pack.CreateSkillAction());
+            isFinish = true;
+            return;
+        }
+    }
+
+}
+
+#endif
\ No newline at end of file
diff --git a/Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs.meta b/Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs.meta
new file mode 100644
index 0000000..ea4597c
--- /dev/null
+++ b/Main/System/Battle/BattleField/RecordActions/SkillTestAction.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bae3c8afb50af6f48977e93e0994dee5
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/BattleField/RecordActions/TestAction.cs b/Main/System/Battle/BattleField/RecordActions/TestAction.cs
new file mode 100644
index 0000000..23532b8
--- /dev/null
+++ b/Main/System/Battle/BattleField/RecordActions/TestAction.cs
@@ -0,0 +1,69 @@
+using UnityEngine;
+using System.Collections.Generic;
+using System;
+
+#if UNITY_EDITOR
+
+public class TestAction : RecordAction
+{
+    protected int targetIndex;
+    protected int selfIndex;
+    protected int distance = 100;
+    protected float duration = 2f;
+
+    public TestAction(BattleField _battleField, int _targetIndex, int _selfIndex, int _distance, float _duration)
+        : base(RecordActionType.Death, _battleField, null)
+    {
+        targetIndex = _targetIndex;
+        selfIndex = _selfIndex;
+        distance = _distance;
+        duration = _duration;
+    }
+
+    public override bool IsFinished()
+    {
+        return isFinish;
+    }
+
+    public override void Run()
+    {
+        base.Run();
+
+        if (!isRunOnce)
+        {
+            isRunOnce = true;
+
+            RectTransform target = battleField.GetTeamNode(BattleCamp.Blue, targetIndex);
+            MoveToTarget(target, new Vector2(distance, 0), duration, () =>
+            {
+                BattleDebug.LogError(" reach to the target ");
+                isFinish = true;
+            });
+
+            return;
+        }
+    }
+
+    protected void MoveToTarget(RectTransform target, Vector2 offset, float duration, Action onComplete = null)
+    {
+        try
+        {
+            BattleObject caster = battleField.battleObjMgr.GetBattleObjectByIndex(BattleCamp.Red, selfIndex);
+            BattleDebug.LogError("Move to target , target is " + target.name);
+            caster.motionBase.PlayAnimation(MotionName.run, true);
+            var tweener = BattleUtility.MoveToTarget(caster.heroRectTrans, target, offset, duration, () =>
+            {
+                caster.motionBase.PlayAnimation(MotionName.idle, true);
+                onComplete?.Invoke();
+            });
+            battleField.battleTweenMgr.OnPlayTween(tweener);
+        }
+        catch (Exception e)
+        {
+            BattleDebug.LogError("Error in MoveToTarget: " + e.Message);
+            isFinish = true;
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Main/System/Battle/BattleField/RecordActions/TestAction.cs.meta b/Main/System/Battle/BattleField/RecordActions/TestAction.cs.meta
new file mode 100644
index 0000000..dadf6c8
--- /dev/null
+++ b/Main/System/Battle/BattleField/RecordActions/TestAction.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c718ef62f36d7b240980acefa56958fd
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Battle/BattleField/StoryBattleField.cs b/Main/System/Battle/BattleField/StoryBattleField.cs
index bc28bb4..0101c88 100644
--- a/Main/System/Battle/BattleField/StoryBattleField.cs
+++ b/Main/System/Battle/BattleField/StoryBattleField.cs
@@ -104,7 +104,7 @@
             case 5://缁撴潫鐘舵�佹爣璁�
                 break;
             default:
-                Debug.LogError("recieve a unknown State");
+                BattleDebug.LogError("recieve a unknown State");
                 break;
         }
     }
@@ -142,12 +142,12 @@
         battleObjMgr.ReloadTeam(TeamManager.Instance.GetTeam(TeamType.Story), BattleCamp.Red);
     }
 
-    public override void OnBattleEnd(JsonData turnFightStateData)
-    {
-        base.OnBattleEnd(turnFightStateData);
+    // public override void OnBattleEnd(JsonData turnFightStateData)
+    // {
+    //     base.OnBattleEnd(turnFightStateData);
 
-        HaveRest();
-    }
+    //     // HaveRest();
+    // }
 
     // public override void Run()
     // {
diff --git a/Main/System/Battle/BattleManager.cs b/Main/System/Battle/BattleManager.cs
index 6ca51aa..3749ba5 100644
--- a/Main/System/Battle/BattleManager.cs
+++ b/Main/System/Battle/BattleManager.cs
@@ -168,7 +168,7 @@
             Debug.LogWarning($"杩炵画绌烘垬鏂楃墖娈靛皝鍖呮鏁帮細{continousEmptyCount}");
             if (continousEmptyCount >= MaxContinousEmptyCount)
             {
-                Debug.LogError("杩炵画澶氭娌℃湁鎴樻枟鐗囨灏佸寘锛岃嚜鍔ㄥ洖鍩庝紤鎭紒");
+                BattleDebug.LogError("杩炵画澶氭娌℃湁鎴樻枟鐗囨灏佸寘锛岃嚜鍔ㄥ洖鍩庝紤鎭紒");
                 MainFightRequest(0); // 0-鍋滄鎴樻枟鍥炲煄
                 continousEmptyCount = 0;
                 packQueue.Clear();
@@ -191,21 +191,32 @@
     {
         if (packQueue.Count > 0)
         {
-            GameNetPackBasic pack = packQueue.Dequeue();
+            GameNetPackBasic pack = packQueue.Peek();
+
+            bool dequeue = false;
 
             if (pack is CustomHB426CombinePack)
             {
                 CustomHB426CombinePack combinePack = pack as CustomHB426CombinePack;
+                packQueue.Dequeue();
                 combinePack.Distribute();
             }
             else if (pack is CustomB421ActionPack)
             {
                 CustomB421ActionPack actionPack = pack as CustomB421ActionPack;
-                actionPack.Distribute();
+
+                dequeue = !actionPack.Distribute();
             }
             else
             {
+                BattleDebug.LogError("distribute pack " + pack.GetType().Name);
+                packQueue.Dequeue();
                 PackageRegedit.Distribute(pack);
+            }
+
+            if (dequeue && packQueue.Count > 0)
+            {
+                packQueue.Dequeue();
             }
 
             return true;
@@ -287,17 +298,22 @@
 
         if (!battleReportDict.TryGetValue(guid, out queue))
         {
-            Debug.LogError("DistributeNextReportPackage could not find queue for guid : " + guid);
+            BattleDebug.LogError("DistributeNextReportPackage could not find queue for guid : " + guid);
             return;
         }
 
-        PackageRegedit.Distribute(queue.Dequeue());
+        var pack = queue.Dequeue();
+        BattleDebug.LogError("distribute pack " + pack.GetType().Name);
+
+        PackageRegedit.Distribute(pack);
 
         if (queue.Count <= 0)
         {
             battleReportDict.Remove(guid);
             battlePackRelationList.Remove(guid);
         }
+
+        BattleDebug.LogError("BattlePackage count is " + queue.Count);
     }
     #endregion
 
@@ -307,7 +323,7 @@
 
         if (battleFields.TryGetValue(guid, out battleField))
         {
-            Debug.LogError("鎴樺満宸插瓨鍦� 鍏堣繘琛岄攢姣�");
+            BattleDebug.LogError("鎴樺満宸插瓨鍦� 鍏堣繘琛岄攢姣�");
             battleField.Destroy();
         }
 
@@ -331,7 +347,7 @@
     {
         if (battleField == null)
         {
-            Debug.LogError("DestroyBattleField called with null battleField");
+            BattleDebug.LogError("DestroyBattleField called with null battleField");
             return;
         }
 
diff --git a/Main/System/Battle/BattleObject/BattleObjMgr.cs b/Main/System/Battle/BattleObject/BattleObjMgr.cs
index fccf934..2ae7298 100644
--- a/Main/System/Battle/BattleObject/BattleObjMgr.cs
+++ b/Main/System/Battle/BattleObject/BattleObjMgr.cs
@@ -217,6 +217,20 @@
         return blueCampList;
     }
 
+    public BattleObject GetBattleObjectByIndex(BattleCamp camp, int selfIndex)
+    {
+        if (camp == BattleCamp.Red)
+        {
+            redCampDict.TryGetValue(selfIndex, out BattleObject battleObj);
+            return battleObj;
+        }
+        else
+        {
+            blueCampDict.TryGetValue(selfIndex, out BattleObject battleObj);
+            return battleObj;
+        }
+    }
+
 #if UNITY_EDITOR_STOP_USING
     public void ReviveAll()
     {
diff --git a/Main/System/Battle/BattleObject/BattleObject.cs b/Main/System/Battle/BattleObject/BattleObject.cs
index 5fd4dee..e094fb1 100644
--- a/Main/System/Battle/BattleObject/BattleObject.cs
+++ b/Main/System/Battle/BattleObject/BattleObject.cs
@@ -110,7 +110,6 @@
 
     public virtual void Destroy()
     {
-
         motionBase.onAnimationComplete -= OnAnimationComplete;
 
         motionBase.Release();
@@ -139,7 +138,7 @@
                 teamHero.rage = (int)GeneralDefine.GetFactValue(_refreshInfo.Value, _refreshInfo.ValueEx);
                 break;
             default:
-                Debug.LogError("BattleObject.ObjInfoRefresh 鍑虹幇鎰忓绫诲瀷 " + _refreshInfo.RefreshType.ToString());
+                BattleDebug.LogError("BattleObject.ObjInfoRefresh 鍑虹幇鎰忓绫诲瀷 " + _refreshInfo.RefreshType.ToString());
                 break;
         }
     }
@@ -262,6 +261,7 @@
 
     public virtual void OnDeath(Action _onDeathAnimationComplete)
     {
+        BattleDebug.LogError(ObjID + " OnDeath called");
         onDeathAnimationComplete = _onDeathAnimationComplete;
         motionBase.PlayAnimation(MotionName.dead, false);
     }
@@ -326,7 +326,7 @@
         // YYL TODO
         //  浼戞伅鐘舵��
         //  澶氫竴涓獄zz鐨勪竴涓壒鏁�
-
+        heroGo.SetActive(true);
         motionBase.PlayAnimation(MotionName.idle, true);
         heroRectTrans.anchoredPosition = Vector2.zero;
     }
diff --git a/Main/System/Battle/BattleObject/BattleObjectFactory.cs b/Main/System/Battle/BattleObject/BattleObjectFactory.cs
index 2653acd..3982ef4 100644
--- a/Main/System/Battle/BattleObject/BattleObjectFactory.cs
+++ b/Main/System/Battle/BattleObject/BattleObjectFactory.cs
@@ -17,7 +17,7 @@
         HeroSkinConfig skinCfg = teamHero.skinConfig;
         if (skinCfg == null)
         {
-            Debug.LogError(teamHero.heroId + "BattleObjectFactory.CreateBattleObject: skinCfg is null for " + teamHero.SkinID);
+            BattleDebug.LogError(teamHero.heroId + "BattleObjectFactory.CreateBattleObject: skinCfg is null for " + teamHero.SkinID);
             return null;
         }
 
@@ -25,11 +25,11 @@
 
         if (battleGO == null)
         {
-            Debug.LogError("BattleObjectFactory.CreateBattleObject: battleGO is null for " + teamHero.heroId);
+            BattleDebug.LogError("BattleObjectFactory.CreateBattleObject: battleGO is null for " + teamHero.heroId);
             return null;
         }
 
-        Debug.LogError("1 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
+        BattleDebug.LogError("1 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
 
         GameObject goParent = posNodeList[teamHero.positionNum];
         BattleObject battleObject = new BattleObject(_battleField);
@@ -41,11 +41,11 @@
         var skeletonDataAsset = ResManager.Instance.LoadAsset<SkeletonDataAsset>("Hero/SpineRes/", skinCfg.SpineRes);
         if (skeletonDataAsset == null)
         {
-            Debug.LogError("BattleObjectFactory.CreateBattleObject: skeletonDataAsset is null for " + skinCfg.SpineRes);
+            BattleDebug.LogError("BattleObjectFactory.CreateBattleObject: skeletonDataAsset is null for " + skinCfg.SpineRes);
             return null;
         }
 
-        Debug.LogError("2 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
+        BattleDebug.LogError("2 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
 
         float finalScaleRate = modelScaleRate * teamHero.modelScale;
 
@@ -53,10 +53,11 @@
         skeletonGraphic.Initialize(true);
         realGO.name = battleObject.ObjID.ToString();
         realGO.transform.localScale = new Vector3(finalScaleRate, finalScaleRate, finalScaleRate);
-        (realGO.transform as RectTransform).anchoredPosition = Vector2.zero;
+        RectTransform rectTrans = realGO.GetComponent<RectTransform>();
+        rectTrans.anchoredPosition = Vector2.zero;
         battleObject.Init(realGO, teamHero, _Camp);
 
-        Debug.LogError(realGO.name +  " /3 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
+        BattleDebug.LogError(realGO.name +  " /3 BattleObjectFactory.CreateBattleObject: Creating BattleObject for " + teamHero.ObjID + " at position " + teamHero.positionNum);
 
 
         return battleObject;
@@ -64,7 +65,7 @@
 
     public static void DestroyBattleObject(int key, BattleObject battleObj)
     {
-        Debug.LogError("BattleObject destroy");
+        BattleDebug.LogError("BattleObject destroy");
         battleObj.Destroy();
         battleObj = null;
     }
diff --git a/Main/System/Battle/BattleUtility.cs b/Main/System/Battle/BattleUtility.cs
index a16cf6e..4a2c228 100644
--- a/Main/System/Battle/BattleUtility.cs
+++ b/Main/System/Battle/BattleUtility.cs
@@ -10,28 +10,110 @@
 {
     // 鍏朵粬閫氱敤鐨勬垬鏂楀伐鍏锋柟娉曞彲浠ユ斁鍦ㄨ繖閲�
 
-    public static TweenerCore<Vector2, Vector2, DG.Tweening.Plugins.Options.VectorOptions> MoveToTarget(RectTransform transform, RectTransform target, Vector2 offset, float duration, Action onComplete = null)
+
+    public static void MarkStartAndEnd(RectTransform startNode, RectTransform endNode)
     {
-        // 1. 鑾峰彇鐩爣鐨勬渶缁� anchoredPosition锛堝姞涓� offset锛�
-        Vector2 targetAnchoredPos = target.anchoredPosition + offset;
-        Vector3 worldAnchorPos = target.TransformPoint(targetAnchoredPos);
+        // 杩愯鏃舵墠鎵ц
+        if (!Application.isPlaying)
+        {
+            Debug.LogWarning("璇峰湪杩愯鏃朵娇鐢ㄨ鍔熻兘锛�");
+            return;
+        }
+
+        var battleField = BattleManager.Instance.storyBattleField;
+        if (battleField == null)
+        {
+            BattleDebug.LogError("BattleManager.storyBattleField 鏈垵濮嬪寲锛�");
+            return;
+        }
 
 
-        // 杞崲 target 鐨� anchoredPosition 鍒� sourceParent 鐨勫潗鏍囩郴
+        BattleWin battleWin = UIManager.Instance.GetUI<BattleWin>();
+
+        RectTransform canvasRect = battleWin.transform as RectTransform;
+
+        CreateMarker(canvasRect, startNode, "StartMarker");
+        CreateMarker(canvasRect, endNode, "EndMarker");
+    }
+
+    private static void CreateMarker(RectTransform canvasRect, RectTransform targetNode, string markerName)
+    {
+        // 鑾峰彇鐩爣鑺傜偣鐨勪笘鐣屽潗鏍囷紙涓績鐐癸級
+        Vector3 worldPos = targetNode.TransformPoint(targetNode.rect.center);
+
+        // 杞崲鍒癈anvas鏈湴鍧愭爣
         Vector2 localPoint;
         RectTransformUtility.ScreenPointToLocalPointInRectangle(
-            transform,
-            RectTransformUtility.WorldToScreenPoint(CameraManager.uiCamera, worldAnchorPos),
-            CameraManager.uiCamera,
+            canvasRect,
+            RectTransformUtility.WorldToScreenPoint(null, worldPos),
+            null,
             out localPoint);
 
-        // 3. DOTween 绉诲姩
+        // 鍒涘缓RawImage
+        GameObject marker = new GameObject(markerName, typeof(RawImage));
+        GameObject.Destroy(marker, 5f);
+        marker.transform.SetParent(canvasRect, false);
+        var rawImage = marker.GetComponent<RawImage>();
+        rawImage.color = Color.white;
+        rawImage.rectTransform.sizeDelta = new Vector2(100, 100);
+        rawImage.rectTransform.anchoredPosition = localPoint;
+    }
+
+
+    public static TweenerCore<Vector2, Vector2, DG.Tweening.Plugins.Options.VectorOptions> MoveToTarget(
+        RectTransform transform, RectTransform target, Vector2 offset, float duration, Action onComplete = null)
+    {
+
+        // 鑾峰彇鐩爣鑺傜偣鐨勪笘鐣屽潗鏍囷紙涓績鐐癸級
+        Vector3 worldPos = target.TransformPoint(target.rect.center + offset);
+
+        RectTransform canvasRect = transform.parent as RectTransform;
+
+        // 杞崲鍒癈anvas鏈湴鍧愭爣
+        Vector2 localPoint;
+        RectTransformUtility.ScreenPointToLocalPointInRectangle(
+            canvasRect,
+            RectTransformUtility.WorldToScreenPoint(null, worldPos),
+            null,
+            out localPoint);
+
+        // 鍒涘缓RawImage
+
         var tween = transform.DOAnchorPos(localPoint, duration).SetEase(Ease.Linear);
         tween.onComplete += () =>
         {
             onComplete?.Invoke();
         };
 
+        // MarkStartAndEnd(transform as RectTransform, target);
+
+
+        // // 1. 鑾峰彇鐩爣鐨勪笘鐣屽潗鏍囷紙鍔� offset锛�
+        // Vector3 targetWorldPos = target.TransformPoint(target.anchoredPosition + offset);
+
+        // // 2. 鑾峰彇婧愯妭鐐圭殑 parent
+        // RectTransform sourceParent = transform.parent as RectTransform;
+        // if (sourceParent == null)
+        // {
+        //     BattleDebug.LogError("婧愯妭鐐规病鏈夌埗鑺傜偣锛屾棤娉曡浆鎹㈠潗鏍囷紒");
+        //     return null;
+        // }
+
+        // // 3. 鎶婄洰鏍囦笘鐣屽潗鏍囪浆鎹㈠埌婧� parent 鐨勬湰鍦板潗鏍�
+        // Vector2 targetAnchoredPos;
+        // RectTransformUtility.ScreenPointToLocalPointInRectangle(
+        //     sourceParent,
+        //     RectTransformUtility.WorldToScreenPoint(CameraManager.uiCamera, targetWorldPos),
+        //     CameraManager.uiCamera,
+        //     out targetAnchoredPos);
+
+        // // 4. DOTween 绉诲姩
+        // var tween = transform.DOAnchorPos(targetAnchoredPos, duration).SetEase(Ease.Linear);
+        // tween.onComplete += () =>
+        // {
+        //     onComplete?.Invoke();
+        // };
+
         return tween;
     }
 
diff --git a/Main/System/Battle/BattleWin.cs b/Main/System/Battle/BattleWin.cs
index 1d4fe89..7655af1 100644
--- a/Main/System/Battle/BattleWin.cs
+++ b/Main/System/Battle/BattleWin.cs
@@ -24,13 +24,13 @@
 
     private void PauseGame()
     {
-        // Debug.LogError("PauseeGame");
+        // BattleDebug.LogError("PauseeGame");
         // if (null == battleField)
         //     return;
 
         // battleField.IsPause = !battleField.IsPause;
 
-        // Debug.LogError(" is pause " + battleField.IsPause.ToString());
+        // BattleDebug.LogError(" is pause " + battleField.IsPause.ToString());
 
         if (battleField != null)
         {
diff --git a/Main/System/Battle/Motion/MotionBase.cs b/Main/System/Battle/Motion/MotionBase.cs
index 1e5b32f..306e2d3 100644
--- a/Main/System/Battle/Motion/MotionBase.cs
+++ b/Main/System/Battle/Motion/MotionBase.cs
@@ -75,7 +75,7 @@
         }
         else
         {
-            Debug.LogError("缂哄皯SkeletonGraphic缁勪欢!");
+            BattleDebug.LogError("缂哄皯SkeletonGraphic缁勪欢!");
         }
         
 
@@ -138,12 +138,12 @@
         // 鍙傛暟鏍¢獙
         if (skillConfig == null)
         {
-            Debug.LogError("鎶�鑳介厤缃负绌猴紝鏃犳硶鎾斁鎶�鑳藉姩鐢�");
+            BattleDebug.LogError("鎶�鑳介厤缃负绌猴紝鏃犳硶鎾斁鎶�鑳藉姩鐢�");
             return null;
         }
         if (spineAnimationState == null || skeleton == null)
         {
-            Debug.LogError("SkeletonGraphic鎴朅nimationState鏈垵濮嬪寲锛屾棤娉曟挱鏀炬妧鑳藉姩鐢�");
+            BattleDebug.LogError("SkeletonGraphic鎴朅nimationState鏈垵濮嬪寲锛屾棤娉曟挱鏀炬妧鑳藉姩鐢�");
             return null;
         }
 
@@ -151,7 +151,7 @@
         Spine.Animation anim = skeleton.Data.FindAnimation(skillConfig.SkillMotionName);
         if (anim == null)
         {
-            Debug.LogError($"鎵句笉鍒板姩鐢�: {skillConfig.SkillMotionName}");
+            BattleDebug.LogError($"鎵句笉鍒板姩鐢�: {skillConfig.SkillMotionName}");
             return null;
         }
 
@@ -194,7 +194,7 @@
             }
 
             // 涓憞寮�濮嬶紙姣忚疆loop鐨勫紑濮嬶紝鍙Е鍙戜竴娆★級
-            if (!middleFrameStarted && trackTime >= middleBeginTime && curLoop < loopCount)
+            if (!middleFrameStarted && trackTime >= middleBeginTime && curLoop <= loopCount)
             {
                 middleFrameStarted = true;
                 skillBase.OnMiddleFrameStart(curLoop);
diff --git a/Main/System/Battle/RecordPlayer/RecordAction.cs b/Main/System/Battle/RecordPlayer/RecordAction.cs
index b34b071..f5fc24a 100644
--- a/Main/System/Battle/RecordPlayer/RecordAction.cs
+++ b/Main/System/Battle/RecordPlayer/RecordAction.cs
@@ -10,7 +10,6 @@
     //  鏈Action鐨勪富瑙�
     protected BattleObject battleObject;
 
-    //  缁欏瓙绫荤敤鐨� 骞朵笉浠h〃浜嬩欢鐨勭粨鏉熶笌鍚�
     protected bool isFinish = false;
 
     protected bool isRunOnce = false;
@@ -26,7 +25,7 @@
 
     public virtual bool IsFinished()
     {
-        return false;
+        return isFinish;
     }
 
     public virtual void Run()
diff --git a/Main/System/Battle/RecordPlayer/RecordPlayer.cs b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
index a385794..d25115e 100644
--- a/Main/System/Battle/RecordPlayer/RecordPlayer.cs
+++ b/Main/System/Battle/RecordPlayer/RecordPlayer.cs
@@ -11,7 +11,7 @@
 
     private bool isWaitingNextAction = false;
     private float waitTimer = 0f;
-    private const float waitInterval = 1f;
+    private const float waitInterval = 0.2f;
 
     public void Init(BattleField _battleField)
     {
@@ -25,7 +25,7 @@
 
     public void PlayRecord(RecordAction recordAction)
     {
-        Debug.LogError("Enqueue record action " + recordAction.GetType());
+        BattleDebug.LogError("Enqueue record action " + recordAction.GetType());
         recordActionQueue.Enqueue(recordAction);
     }
 
@@ -70,7 +70,7 @@
 
         if (currentRecordAction != null && currentRecordAction.IsFinished())
         {
-            Debug.LogError("record action " + currentRecordAction.GetType() + " play finished");
+            BattleDebug.LogError("record action " + currentRecordAction.GetType() + " play finished");
             currentRecordAction = null;
             isWaitingNextAction = true;
             waitTimer = 0f;
@@ -82,7 +82,7 @@
             if (recordActionQueue.Count > 0)
             {
                 currentRecordAction = recordActionQueue.Dequeue();
-                Debug.LogError("play record action " + currentRecordAction.GetType());
+                BattleDebug.LogError("play record action " + currentRecordAction.GetType());
             }
         }
     }
diff --git a/Main/System/Battle/Skill/DirectlyDamageSkill.cs b/Main/System/Battle/Skill/DirectlyDamageSkill.cs
index 844ecb9..ef12c38 100644
--- a/Main/System/Battle/Skill/DirectlyDamageSkill.cs
+++ b/Main/System/Battle/Skill/DirectlyDamageSkill.cs
@@ -7,7 +7,6 @@
 
 public class DirectlyDamageSkill : SkillBase
 {
-	protected SkillEffect skillEffect;
 
 	public DirectlyDamageSkill(BattleObject _caster, SkillConfig _skillCfg,
 			HB427_tagSCUseSkill _vNetData, List<GameNetPackBasic> _packList, BattleField _battleField)
@@ -15,38 +14,8 @@
 	{
 		foreach (var pack in packList)
 		{
-			Debug.LogError("directly damage skill pack type is " + pack.GetType());
+			BattleDebug.LogError("directly damage skill pack type is " + pack.GetType());
 		}
-	}
-
-	public override void Run()
-	{
-		if (null != skillEffect)
-		{
-			skillEffect.Run();
-		}
-
-		base.Run();
-	}
-
-	//	鎶�鑳藉紑濮�
-	public override void OnSkillStart()
-	{
-		skillEffect = SkillEffectFactory.CreateSkillEffect(
-				caster,
-				skillConfig,
-				tagUseSkillAttack
-			);
-		if (skillEffect != null)
-		{
-			skillEffect.Play(OnHitTargets);
-		}
-	}
-
-	//	鍓嶆憞缁撴潫
-	public override void OnStartSkillFrameEnd()
-	{
-		base.OnStartSkillFrameEnd();
 	}
 
 	protected override void OnHitTargets(int _hitIndex, List<HB427_tagSCUseSkill.tagSCUseSkillHurt> hitList)
@@ -54,29 +23,11 @@
 		base.OnHitTargets(_hitIndex, hitList);
 	}
 
-	protected override void OnHitEachTarget(BattleObject target, long totalDamage, List<long> damageList, ref HB427_tagSCUseSkill.tagSCUseSkillHurt hurt)
+	protected override void OnAllAttackMoveFinished()
 	{
-		base.OnHitEachTarget(target, totalDamage, damageList, ref hurt);
+		base.OnAllAttackMoveFinished();
+
+		OnSkillFinished();
 	}
 
-
-	public override void OnMiddleFrameStart(int times)
-	{
-		base.OnMiddleFrameStart(times);
-
-		skillEffect?.OnMiddleFrameStart(times);
-	}
-
-
-	//  涓憞缁撴潫(鍛戒腑甯�)
-	public override void OnMiddleFrameEnd(int times, int hitIndex)
-	{
-		skillEffect?.OnMiddleFrameEnd(times, hitIndex);
-	}
-
-	//	鍚庢憞缁撴潫
-	public override void OnFinalFrameEnd()
-	{
-
-	}
 }
\ No newline at end of file
diff --git a/Main/System/Battle/Skill/DirectlyHealSkill.cs b/Main/System/Battle/Skill/DirectlyHealSkill.cs
index 3b17992..bf4202e 100644
--- a/Main/System/Battle/Skill/DirectlyHealSkill.cs
+++ b/Main/System/Battle/Skill/DirectlyHealSkill.cs
@@ -14,7 +14,7 @@
 	{
 		foreach (var pack in packList)
 		{
-			Debug.LogError("directly heal skill pack type is " + pack.GetType());
+			BattleDebug.LogError("directly heal skill pack type is " + pack.GetType());
 		}
 	}
 
diff --git a/Main/System/Battle/Skill/SkillBase.cs b/Main/System/Battle/Skill/SkillBase.cs
index d74d76d..605ede7 100644
--- a/Main/System/Battle/Skill/SkillBase.cs
+++ b/Main/System/Battle/Skill/SkillBase.cs
@@ -9,6 +9,8 @@
 
 public class SkillBase
 {
+	const float moveTime = 0.5f;
+
 	protected SkillEffect skillEffect;
 
 	protected HB427_tagSCUseSkill tagUseSkillAttack;
@@ -54,6 +56,11 @@
 			curFrame++;
 		}
 
+		if (null != skillEffect)
+		{
+			skillEffect.Run();
+		}
+
 		if (otherSkillAction != null)
 		{
 			if (otherSkillAction.IsFinished())
@@ -86,12 +93,12 @@
 	// 1路绉诲姩鍒拌窛绂婚樀瀹逛綅缃畁鐮佺殑璺濈锛堝2鍙蜂綅锛�5鍙蜂綅锛夐噴鏀撅紙鍗虫垬鍦轰腑澶绫伙級
 	public virtual void Cast()
 	{
-		Debug.LogError(GetType().Name + " Skill Cast Start");
+		BattleDebug.LogError(GetType().Name + " Skill Cast Start");
 		//	楂樹寒鎵�鏈夋湰娆℃妧鑳界浉鍏崇殑鐩爣
 		HighLightAllTargets();
 
 		//	璺濈閰嶆垚璐熸暟瑕佽浆韬� TurnBack
-		Debug.LogError(GetType().Name + " Skill CastMode : " + skillConfig.castMode);
+		BattleDebug.LogError(GetType().Name + " Skill CastMode : " + skillConfig.castMode);
 		switch (skillConfig.castMode)
 		{
 			case SkillCastMode.Self:
@@ -110,7 +117,7 @@
 			// 	DashToTarget(() => BackToOrigin(OnSkillFinished));
 			// 	break;
 			default:
-				Debug.LogError("鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹傝鑱旂郴绛栧垝 鎶�鑳絠d:" + skillConfig.SkillID + " cast position " + skillConfig.CastPosition);
+				BattleDebug.LogError("鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹傝鑱旂郴绛栧垝 鎶�鑳絠d:" + skillConfig.SkillID + " cast position " + skillConfig.CastPosition);
 				OnSkillFinished();
 				break;
 		}
@@ -118,6 +125,14 @@
 
 	protected void MoveToTarget(RectTransform target, Vector2 offset, float duration, Action onComplete = null)
 	{
+		BattleDebug.LogError("Move to target , target is " + target.name);
+		//	鍘熷湴閲婃斁
+		if (skillConfig.CastDistance >= 9999)
+		{
+			onComplete?.Invoke();
+			return;
+		}
+
 		caster.motionBase.PlayAnimation(MotionName.run, true);
 		var tweener = BattleUtility.MoveToTarget(caster.heroRectTrans, target, offset, duration, () =>
 		{
@@ -141,7 +156,6 @@
 
 	protected void CastToEnemy()
 	{
-		const float moveTime = 0.5f;
 
 		RectTransform target = battleField.GetTeamNode(caster.GetEnemyCamp(), skillConfig);
 
@@ -161,6 +175,7 @@
 							{
 								TurnBack(null, 1f);
 								caster.motionBase.PlayAnimation(MotionName.idle, true);
+								OnAllAttackMoveFinished();
 							});
 						}
 					, -1f);
@@ -176,7 +191,7 @@
 		// 鐩爣鏄晫鏂逛富鐩爣
 		if (tagUseSkillAttack.HurtCount <= 0)
 		{
-			Debug.LogError("鎶�鑳芥敾鍑诲寘娌℃湁鐩爣 HurtCount <= 0");
+			BattleDebug.LogError("鎶�鑳芥敾鍑诲寘娌℃湁鐩爣 HurtCount <= 0");
 			OnSkillFinished();
 			return;
 		}
@@ -186,22 +201,85 @@
 		BattleObject mainTarget = battleField.battleObjMgr.GetBattleObject((int)mainHurt.ObjID);
 		if (mainTarget == null)
 		{
-			Debug.LogError("鐩爣涓虹┖ mainTarget == null ObjID : " + mainHurt.ObjID);
+			BattleDebug.LogError("鐩爣涓虹┖ mainTarget == null ObjID : " + mainHurt.ObjID);
 			OnSkillFinished();
 			return;
 		}
-		// MoveToTarget(mainTarget.Camp, mainTarget, _onComplete: () => TurnBack(() => CastImpl(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
+
+		MoveToTarget(mainTarget.heroRectTrans, new Vector2(skillConfig.CastDistance, 0), moveTime, () =>
+		{
+			//	鍒颁綅缃浆韬�(涓嶄竴瀹氶潪瑕佽浆韬� 浣嗘槸娴佺▼瑕佸啓)
+			TurnBack(() =>
+			{
+				//	鍒拌揪鐩爣浣嶇疆
+				CastImpl(() =>
+				{
+					TurnBack(
+						() =>
+						{
+							//	鍥炲埌鍘熸潵鐨勪綅缃�
+							MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.teamHero.positionNum), Vector2.zero, moveTime, () =>
+							{
+								TurnBack(null, 1f);
+								caster.motionBase.PlayAnimation(MotionName.idle, true);
+								OnAllAttackMoveFinished();
+							});
+						}
+					, -1f);
+				});
+			}, -1f);
+		});
+	}
+
+	protected virtual void OnAllAttackMoveFinished()
+	{
+		
 	}
 
 	protected void CastToAllies()
 	{
-		// MoveToTarget(caster.Camp, skillConfig, _onComplete: () => TurnBack(() => CastImpl(() => DoSkillLogic(() => { BackToOrigin(OnSkillFinished); }))));
+		RectTransform target = battleField.GetTeamNode(caster.Camp, skillConfig);
+
+		MoveToTarget(target, new Vector2(skillConfig.CastDistance, 0), moveTime, () =>
+		{
+			//	鍒颁綅缃浆韬�(涓嶄竴瀹氶潪瑕佽浆韬� 浣嗘槸娴佺▼瑕佸啓)
+			TurnBack(() =>
+			{
+				//	鍒拌揪鐩爣浣嶇疆
+				CastImpl(() =>
+				{
+					TurnBack(
+						() =>
+						{
+							//	鍥炲埌鍘熸潵鐨勪綅缃�
+							MoveToTarget(battleField.GetTeamNode(caster.Camp, caster.teamHero.positionNum), Vector2.zero, moveTime, () =>
+							{
+								TurnBack(null, 1f);
+								caster.motionBase.PlayAnimation(MotionName.idle, true);
+								OnAllAttackMoveFinished();
+							});
+						}
+					, -1f);
+				});
+			}, -1f);
+		});
 	}
 
+
+	//	鎵胯浇鎶�鑳藉ぇ閮ㄥ垎鐨勯�昏緫
 	protected TrackEntry CastImpl(Action onComplete = null)
 	{
 		// 鎾斁鏂芥硶鍔ㄤ綔
-		return caster.motionBase.PlaySkillAnimation(skillConfig, this, onComplete);//鏀诲嚮涓憞缁撴潫
+		//	onComplete鏄寚鏂芥硶鍔ㄤ綔鎾斁瀹岀殑鍥炶皟 涓嶄唬琛ㄦ槸鎶�鑳界粨鏉�
+		//	鍏蜂綋鎶�鑳界粨鏉熺殑鏃堕棿搴旇鐪嬫妧鑳藉搴旂殑閫昏緫
+		//	杩欓噷鍙彁渚�6涓姩浣滅浉鍏崇殑鍑芥暟
+		// OnSkillStart 鍔ㄤ綔绗竴甯�
+		// OnStartSkillFrameEnd 鍓嶆憞缁撴潫
+		// OnMiddleFrameStart 涓憞寮�濮�
+		// OnMiddleFrameEnd 涓憞缁撴潫
+		// OnFinalFrameStart 鍚庢憞寮�濮�
+		// OnFinalFrameEnd 鍚庢憞缁撴潫
+		return caster.motionBase.PlaySkillAnimation(skillConfig, this, onComplete);
 	}
 
 	//	鎶�鑳藉紑濮�
@@ -230,12 +308,12 @@
 	/// <param name="times"></param>
 	public virtual void OnMiddleFrameStart(int times)
 	{
-
+		skillEffect.OnMiddleFrameStart(times);
 	}
 
 	public virtual void OnMiddleFrameEnd(int times, int hitIndex)
 	{
-
+		skillEffect.OnMiddleFrameEnd(times, hitIndex);
 	}
 
 	/// <summary>
@@ -256,56 +334,6 @@
 
 
 
-	// public void MoveToTarget(BattleCamp camp, BattleObject target, float duration = 0.2f, Action _onComplete = null)
-	// {
-	// 	targetNode = battleField.GetTeamNode(camp, target);
-
-	// 	Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
-	// 	RectTransform selfRect = caster.heroRectTrans;
-	// 	RectTransform targetRect = targetNode;
-
-	// 	var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
-	// 	battleField.battleTweenMgr.OnPlayTween(tweener);
-	// }
-
-	// public void MoveToTarget(BattleCamp camp, SkillConfig skillCfg, float duration = 0.2f, Action _onComplete = null)
-	// {
-	// 	targetNode = battleField.GetTeamNode(camp, skillCfg);
-
-	// 	Vector2 offset = new Vector2(skillConfig.CastDistance, 0);
-	// 	RectTransform selfRect = caster.heroRectTrans;
-	// 	RectTransform targetRect = targetNode;
-
-	// 	var tweener = BattleUtility.MoveToTarget(selfRect, targetRect, offset, duration, _onComplete);
-	// 	battleField.battleTweenMgr.OnPlayTween(tweener);
-	// }
-
-	// public void TurnBack(Action _onComplete)
-	// {
-	// 	if (skillConfig.CastDistance < 0)
-	// 	{
-	// 		//	杞韩
-	// 		caster.heroGo.transform.localScale = new Vector3(-1, 1, 1);
-	// 	}
-	// 	_onComplete?.Invoke();
-	// }
-
-	// public void BackToOrigin(Action _onComplete = null)
-	// {
-	// 	RectTransform selfRect = caster.heroRectTrans;
-	// 	Vector2 targetAnchoredPos = Vector2.zero;
-	// 	var tween = selfRect.DOAnchorPos(targetAnchoredPos, 0.2f)
-	// 		.SetEase(Ease.Linear);
-
-	// 	tween.onComplete += () =>
-	// 	{
-	// 		//	杞垚姝g‘鏂瑰悜
-	// 		caster.heroGo.transform.localScale = Vector3.one;
-	// 		_onComplete?.Invoke();
-	// 	};
-
-	// 	battleField.battleTweenMgr.OnPlayTween(tween);
-	// }
 
 	protected void HighLightAllTargets()
 	{
@@ -328,7 +356,7 @@
 			BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
 			if (target == null)
 			{
-				Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+				BattleDebug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
 				continue;
 			}
 
@@ -349,11 +377,20 @@
 	protected void HandleDead()
 	{
 		var deadPackList = BattleUtility.FindDeadPack(packList);
+		int deadCount = deadPackList.Count;
+
+		if (deadCount <= 0)
+		{
+			//	濡傛灉娌℃浜″氨涓嶇敤绠�
+			return;
+		}
+
 		CheckAfterDeadhPack();
 
 		// 澶勭悊鎺夎惤鍖� 鎻愬墠distribute涔嬪悗 PackManager鎵嶆湁鎺夎惤鐗� 鎵�浠ヤ笉璺焌ssignexp涓�鏍穌istribute
 		foreach (var _dropPack in dropPackList)
 		{
+			BattleDebug.LogError("distribute pack " + _dropPack.GetType().Name);
 			PackageRegedit.Distribute(_dropPack);
 			packList.Remove(_dropPack);
 		}
@@ -366,7 +403,7 @@
 			where item != null && item.isAuction
 			select item);
 
-		int deadCount = deadPackList.Count;
+
 
 		// 鍒嗛厤鎺夎惤鍜岀粡楠�
 		var dropAssign = AssignDrops(itemList, deadCount);
@@ -378,7 +415,7 @@
 			BattleObject deadTarget = battleField.battleObjMgr.GetBattleObject((int)deadPackList[i].ObjID);
 			List<ItemModel> itemModelDrops = dropAssign[i];
 			List<int> itemModelDropsIndexList = new List<int>(
-				from item in itemModelDrops  select item.gridIndex);
+				from item in itemModelDrops select item.gridIndex);
 			BattleDrops battleDrops = new BattleDrops()
 			{
 				rectTransform = deadTarget.heroRectTrans,
@@ -389,12 +426,15 @@
 		}
 
 		// 鍒嗗彂姝讳骸鍖�
-		battleField.OnObjsDead(deadPackList);
+
+		battleField.OnObjsDead(new List<HB422_tagMCTurnFightObjDead>(deadPackList));
 		foreach (var deadPack in deadPackList)
 		{
 			packList.Remove(deadPack);
 		}
 		deadPackList.Clear();
+
+
 	}
 
 
@@ -447,16 +487,6 @@
 	{
 		target.Hurt(damageList, totalDamage, hurt.AttackTypes);
 
-		//	鍑讳腑鐩爣鐨勬椂鍊�,涓嶇杩戞垬杩滅▼ 閮界‘璁や竴涓嬫槸鍚︽湁鐖嗙偢鐗规晥 鐒跺悗鎾斁
-		if (skillConfig.ExplosionEffectId > 0)
-		{
-			// 鎾斁鐖嗙偢鐗规晥
-			target.battleField.battleEffectMgr.PlayEffect(
-				target.ObjID,
-				skillConfig.ExplosionEffectId,
-				target.heroGo.transform
-			);
-		}
 	}
 
 	protected void CheckAfterDeadhPack()
@@ -515,6 +545,14 @@
 	}
 	public virtual bool IsFinished()
 	{
+		if (skillEffect != null)
+		{
+			if (!skillEffect.IsFinished())
+			{
+				return false;
+			}
+		}
+
 		return isFinished;
 	}
 
@@ -525,8 +563,8 @@
 
 	public void OnSkillFinished()
 	{
-		Debug.LogError(GetType().Name + " Skill Finished");
-		if (packList.Count > 0)
+		BattleDebug.LogError(GetType().Name + " Skill Finished");
+		while (packList.Count > 0)
 		{
 			var pack = packList[0];
 			packList.RemoveAt(0);
@@ -540,7 +578,7 @@
 					return;
 				}
 			}
-
+			BattleDebug.LogError("distribute pack " + pack.GetType().Name);
 			PackageRegedit.Distribute(pack);
 		}
 
diff --git a/Main/System/Battle/Skill/SkillFactory.cs b/Main/System/Battle/Skill/SkillFactory.cs
index 631ce82..ad63b1b 100644
--- a/Main/System/Battle/Skill/SkillFactory.cs
+++ b/Main/System/Battle/Skill/SkillFactory.cs
@@ -65,7 +65,7 @@
 				// skill = new ReviveSkill(_skillConfig);
 				break;
 			default:
-				Debug.LogError("瓒呭嚭浜嗘妧鑳界被鍨嬭寖鍥� 璇锋鏌ラ厤缃�");
+				BattleDebug.LogError("瓒呭嚭浜嗘妧鑳界被鍨嬭寖鍥� 璇锋鏌ラ厤缃�");
 				break;
 		}
 
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs
index 32f90d1..778b489 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/BounceBulletCurve.cs
@@ -67,7 +67,7 @@
             }
             else
             {
-                Debug.LogError("寮瑰皠鎵句笉鍒颁笅涓�涓洰鏍�");
+                BattleDebug.LogError("寮瑰皠鎵句笉鍒颁笅涓�涓洰鏍�");
                 // 濡傛灉鐩爣涓㈠け锛岀洿鎺ョ敤涓婁竴涓猠nd
                 end = start;
             }
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs
index 7e315c8..8e77a6c 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurve.cs
@@ -27,6 +27,19 @@
         this.onHit = onHit;
         this.bulletTrans = bulletEffect.transform as RectTransform;
         this.hurts = tagUseSkillAttack.HurtList.ToList();
+
+        // 璁剧疆bulletTrans鍧愭爣涓篶aster.heroRectTrans鐨勪笘鐣屽潗鏍囪浆鎹㈠埌bulletTrans鐖惰妭鐐逛笅鐨勬湰鍦板潗鏍�
+        if (bulletTrans != null && caster.heroRectTrans != null)
+        {
+            var parent = bulletTrans.parent as RectTransform;
+            Vector2 localPoint;
+            RectTransformUtility.ScreenPointToLocalPointInRectangle(
+                parent,
+                RectTransformUtility.WorldToScreenPoint(null, caster.heroRectTrans.position),
+                null,
+                out localPoint);
+            bulletTrans.anchoredPosition = localPoint;
+        }
     }
 
     public virtual void Reset()
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs
index 1b14989..7d1e460 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/BulletCurveFactory.cs
@@ -18,18 +18,28 @@
         HB427_tagSCUseSkill tagUseSkillAttack,
         Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
     {
+        BulletCurve curve = null;
         switch (skillConfig.BulletPath)
         {
             case 1: // 鐩寸嚎娑堝け浜庣洰鏍�
-                return new StraightBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                curve = new StraightBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                break;
             case 2: // 鐩寸嚎璐┛娑堝け鍦ㄥ睆骞曞
-                return new PenetrateBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                curve = new PenetrateBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                break;
             case 3: // 鎶涚墿绾垮姬绾�
-                return new BezierBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                curve = new BezierBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                break;
             case 4: // 寮瑰皠
-                return new BounceBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                curve = new BounceBulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                break;
             default:
-                return new BulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                curve = new BulletCurve(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit);
+                break;
         }
+
+        curve.Reset();
+
+        return curve;
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs b/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
index 942c0a5..f67e214 100644
--- a/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
+++ b/Main/System/Battle/SkillEffect/BulletCurve/StraightBulletCurve.cs
@@ -8,25 +8,37 @@
     private Vector2 end;
 
     public StraightBulletCurve(BattleObject caster, SkillConfig skillConfig, BattleEffectPlayer bulletEffect, RectTransform target, HB427_tagSCUseSkill tagUseSkillAttack, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit)
-        : base(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit) { }
+        : base(caster, skillConfig, bulletEffect, target, tagUseSkillAttack, onHit)
+    { 
+        BattleDebug.LogError("StraightBulletCurve created bulletTrans is null = " + (bulletTrans == null).ToString());
+    }
 
     public override void Reset()
     {
         base.Reset();
         start = WorldToLocalAnchoredPosition(bulletTrans.position);
         end = WorldToLocalAnchoredPosition(target.position);
+
+        // BattleUtility.MarkStartAndEnd(bulletTrans, target);
     }
 
     public override void Run()
     {
         if (finished) return;
+
+        if (bulletTrans == null)
+        {
+            BattleDebug.LogError("BulletTrans is null, cannot run StraightBulletCurve");
+            return;
+        }
+
         elapsed += Time.deltaTime;
-        float t = Mathf.Clamp01(elapsed / duration);
+        float t = Mathf.Clamp01(elapsed / 0.3f);
         Vector2 pos = Vector2.Lerp(start, end, t);
         bulletTrans.anchoredPosition = pos;
 
         Vector2 dir = end - start;
-        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90f;
+        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
         bulletTrans.localRotation = Quaternion.Euler(0, 0, angle);
 
         if (t >= 1f)
diff --git a/Main/System/Battle/SkillEffect/BulletSkillEffect.cs b/Main/System/Battle/SkillEffect/BulletSkillEffect.cs
index 1b1b239..588a317 100644
--- a/Main/System/Battle/SkillEffect/BulletSkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/BulletSkillEffect.cs
@@ -19,11 +19,8 @@
 
     }
 
-
-
-    public override void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
+    public override void OnMiddleFrameStart(int times)
     {
-        base.Play(_onHit);
         //  寮瑰皠 鍙﹀鐨勫仛娉曚簡
         if (skillConfig.effectType == SkillEffectType.Bullet && skillConfig.BulletPath == 4)
         {
@@ -31,7 +28,7 @@
             BattleObject targetObject = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
             if (targetObject == null)
             {
-                Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                BattleDebug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
                 return;
             }
             ShotToTarget(targetObject);
@@ -47,7 +44,7 @@
             {
                 case SkillCastMode.Self:
                     onHitFormation?.Invoke(0, tagUseSkillAttack.HurtList.ToList());
-                    Debug.LogError("瀛愬脊鐨勭洰鏍囨槸鑷繁锛屾殏鏃朵笉鏀寔 鍗忓晢绋嬪簭瀹屾垚");
+                    BattleDebug.LogError("瀛愬脊鐨勭洰鏍囨槸鑷繁锛屾殏鏃朵笉鏀寔 鍗忓晢绋嬪簭瀹屾垚");
                     break;
                 case SkillCastMode.Enemy:
                     var targetNode = caster.battleField.GetTeamNode(caster.GetEnemyCamp(), skillConfig);
@@ -60,7 +57,7 @@
                         BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                         if (target == null)
                         {
-                            Debug.LogError("鐗规晥鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                            BattleDebug.LogError("鐗规晥鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
                             continue;
                         }
 
@@ -72,10 +69,17 @@
                     ShotToFormation(healNode, onHitFormation);
                     break;
                 default:
-                    Debug.LogError("鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹傝鑱旂郴绋嬪簭 " + skillConfig.SkillID);
+                    BattleDebug.LogError("鏆傛椂涓嶆敮鎸佸叾浠栫殑鏂瑰紡閲婃斁 鏈夐渶姹傝鑱旂郴绋嬪簭 " + skillConfig.SkillID);
                     break;
             }
         }
+    }
+
+
+    public override void Play(Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
+    {
+        base.Play(_onHit);
+
     }
 
     protected void ShotToFormation(RectTransform target, Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> _onHit)
@@ -98,12 +102,20 @@
                 BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                 if (targetObj == null)
                 {
-                    Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                    BattleDebug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
                     continue;
                 }
 
-                caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
-                caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform);
+                var effect1 = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
+                var effect2 = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform);
+                if (effect1 != null)
+                {
+                    effect1.transform.localRotation = effectTrans.localRotation;
+                }
+                if (effect2 != null)
+                {
+                    effect2.transform.localRotation = effectTrans.localRotation;
+                }
             }
 
         });
@@ -114,30 +126,45 @@
 
     protected void ShotToTarget(BattleObject target)
     {
+        BattleDebug.LogError("鍙戝皠瀛愬脊 " + skillConfig.BulletEffectId);
         BattleEffectPlayer effectPlayer = caster.battleField.battleEffectMgr.PlayEffect(caster.ObjID, skillConfig.BulletEffectId, caster.heroRectTrans);
-        RectTransform effectTrans = effectPlayer.transform as RectTransform;
+
 
         var bulletCurve = BulletCurveFactory.CreateBulletCurve(caster, skillConfig, effectPlayer, target.heroRectTrans, tagUseSkillAttack, (index, hitList) =>
         {
             // 琛ㄧ幇瀛愬脊椋炶鍒扮洰鏍囦綅缃�
             onHit?.Invoke(index, hitList);
 
-            // 鍑讳腑灏遍攢姣佸瓙寮�
-            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer);
+
+            BattleDebug.LogError("鍥炴敹瀛愬脊 " + skillConfig.BulletEffectId);
             // 鎾斁瀛愬脊鐖嗙偢鐗规晥
+
 
             foreach (var hurt in hitList)
             {
                 BattleObject targetObj = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
                 if (targetObj == null)
                 {
-                    Debug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                    BattleDebug.LogError("鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
                     continue;
                 }
 
-                caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
-                caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform);
+                if (skillConfig.ExplosionEffectId > 0)
+                {
+                    var eft = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffectId, targetObj.heroGo.transform);
+                    eft.transform.localRotation = effectPlayer.transform.localRotation;
+                }
+
+                if (skillConfig.ExplosionEffect2 > 0)
+                {
+                    var eft = caster.battleField.battleEffectMgr.PlayEffect(targetObj.ObjID, skillConfig.ExplosionEffect2, targetObj.heroGo.transform);
+                    eft.transform.localRotation = effectPlayer.transform.localRotation;
+                }
             }
+
+            // 鍑讳腑灏遍攢姣佸瓙寮�
+            caster.battleField.battleEffectMgr.RemoveEffect(skillConfig.BulletEffectId, effectPlayer);
+            isFinish = true;
         });
 
         bulletCurves.Add(bulletCurve);
@@ -153,4 +180,16 @@
                 bulletCurve.Run();
         }
     }
+
+    public override bool IsFinished()
+    {
+        bool isCurveFinish = false;
+
+        foreach (var bulletCurve in bulletCurves)
+        {
+            isCurveFinish |= bulletCurve.IsFinished;
+        }
+
+        return isCurveFinish && isFinish;
+    }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/NormalSkillEffect.cs b/Main/System/Battle/SkillEffect/NormalSkillEffect.cs
index 369704d..262720e 100644
--- a/Main/System/Battle/SkillEffect/NormalSkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/NormalSkillEffect.cs
@@ -37,21 +37,34 @@
 
     public override void OnMiddleFrameEnd(int times, int hitIndex)
     {
+        BattleDebug.LogError($" NormalSkillEffect OnMiddleFrameEnd times : {times}, hitIndex : {hitIndex}");
         for (int i = 0; i < tagUseSkillAttack.HurtList.Length; i++)
         {
             var hurt = tagUseSkillAttack.HurtList[i];
             BattleObject target = caster.battleField.battleObjMgr.GetBattleObject((int)hurt.ObjID);
             if (target == null)
             {
-                Debug.LogError("鐗规晥鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
+                BattleDebug.LogError("鐗规晥鐩爣涓虹┖ target == null ObjId : " + hurt.ObjID);
                 continue;
             }
 
+            /*var effect1 = */
             caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffectId, target.heroGo.transform);
+            /*var effect2 = */
             caster.battleField.battleEffectMgr.PlayEffect(target.ObjID, skillConfig.ExplosionEffect2, target.heroGo.transform);
+            // if (effect1 != null)
+            // {
+            //     effect1.transform.localRotation = effectTrans.localRotation;
+            // }
+            // if (effect2 != null)
+            // {
+            //     effect2.transform.localRotation = effectTrans.localRotation;
+            // }
         }
-        
+
+        //  涓轰粈涔堟病瑙﹀彂
         onHit?.Invoke(hitIndex, tagUseSkillAttack.HurtList.ToList());
+        isFinish = true;
     }
 
     public override void OnMiddleFrameStart(int times)
diff --git a/Main/System/Battle/SkillEffect/SkillEffect.cs b/Main/System/Battle/SkillEffect/SkillEffect.cs
index 9bd7c00..9bd1416 100644
--- a/Main/System/Battle/SkillEffect/SkillEffect.cs
+++ b/Main/System/Battle/SkillEffect/SkillEffect.cs
@@ -8,6 +8,8 @@
     protected BattleObject caster;
     protected HB427_tagSCUseSkill tagUseSkillAttack;// 鐩爣鍒楄〃
 
+    protected bool isFinish = false;
+
     protected Action<int, List<HB427_tagSCUseSkill.tagSCUseSkillHurt>> onHit;
 
     public SkillEffect(SkillConfig _skillConfig, BattleObject _caster, HB427_tagSCUseSkill _tagUseSkillAttack)
@@ -30,11 +32,16 @@
 
     public virtual void OnMiddleFrameEnd(int times, int hitIndex)
     {
-        
+
     }
 
     public virtual void OnMiddleFrameStart(int times)
     {
-        
+
+    }
+    
+    public virtual bool IsFinished()
+    {
+        return isFinish;
     }
 }
\ No newline at end of file
diff --git a/Main/System/Battle/SkillEffect/SkillEffectFactory.cs b/Main/System/Battle/SkillEffect/SkillEffectFactory.cs
index 39d5375..894ed7c 100644
--- a/Main/System/Battle/SkillEffect/SkillEffectFactory.cs
+++ b/Main/System/Battle/SkillEffect/SkillEffectFactory.cs
@@ -17,7 +17,7 @@
             // case SkillEffectType.StageEffect:
             //     return new StageSkillEffect(skillConfig, caster, targets);
             default:
-                UnityEngine.Debug.LogError("Unknown Skill Effect Type");
+                BattleDebug.LogError("Unknown Skill Effect Type");
                 break;
         }
         return null;
diff --git a/Main/System/Battle/TestMoveToTarget.cs b/Main/System/Battle/TestMoveToTarget.cs
new file mode 100644
index 0000000..2ed3b91
--- /dev/null
+++ b/Main/System/Battle/TestMoveToTarget.cs
@@ -0,0 +1,25 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+public class TestMoveToTarget : MonoBehaviour
+{
+    public RectTransform sourceRect;
+    public RectTransform targetRect;
+    public Vector2 offset = Vector2.zero;
+    public float duration = 1f;
+
+    [ContextMenu("Test MoveToTarget")]
+    public void TestMove()
+    {
+        if (sourceRect == null || targetRect == null)
+        {
+            BattleDebug.LogError("璇峰湪Inspector涓寚瀹歴ourceRect鍜宼argetRect锛�");
+            return;
+        }
+
+        BattleUtility.MoveToTarget(sourceRect, targetRect, offset, duration, () =>
+        {
+            Debug.Log("绉诲姩瀹屾垚锛�");
+        });
+    }
+}
\ No newline at end of file
diff --git a/Main/System/Battle/TestMoveToTarget.cs.meta b/Main/System/Battle/TestMoveToTarget.cs.meta
new file mode 100644
index 0000000..b9ae80b
--- /dev/null
+++ b/Main/System/Battle/TestMoveToTarget.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b5d256c2bd57a6a47aab490b2dc84a4d
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Main/System/Team/TeamHero.cs b/Main/System/Team/TeamHero.cs
index f28f8b9..ce19457 100644
--- a/Main/System/Team/TeamHero.cs
+++ b/Main/System/Team/TeamHero.cs
@@ -36,7 +36,7 @@
             NPCConfig npcConfig = NPCConfig.Get((int)fightObj.NPCID);
             Country = (HeroCountry)npcConfig.Country;
             SkinID = npcConfig.SkinID;
-            Debug.LogError("npc skin id is " + SkinID);
+            BattleDebug.LogError("npc skin id is " + SkinID);
             modelScale = npcConfig.ModelScale;
         }
         else
@@ -45,7 +45,7 @@
             var heroConfig = HeroConfig.Get(heroId);
             Country = (HeroCountry)heroConfig.Country;
             SkinID = (int)fightObj.SkinID;
-            Debug.LogError("normal hero skin id is " + SkinID);
+            BattleDebug.LogError("normal hero skin id is " + SkinID);
             modelScale = 1f;
         }
 

--
Gitblit v1.8.0