From 09bc892c7283df8757a07b646d5af21ddaa263d1 Mon Sep 17 00:00:00 2001
From: lcy <1459594991@qq.com>
Date: 星期四, 06 十一月 2025 18:22:34 +0800
Subject: [PATCH] 164 天子的考验-客户端

---
 Main/System/Battle/Motion/MotionBase.cs |  221 +++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 196 insertions(+), 25 deletions(-)

diff --git a/Main/System/Battle/Motion/MotionBase.cs b/Main/System/Battle/Motion/MotionBase.cs
index bcd142e..3a21f7c 100644
--- a/Main/System/Battle/Motion/MotionBase.cs
+++ b/Main/System/Battle/Motion/MotionBase.cs
@@ -5,7 +5,7 @@
 
 public class MotionBase
 {
-    public static float MotionTimeScale = 1f;
+    public float MotionTimeScale = 1f;
     public static List<string> AttackMotionList = new List<string>
     {
         MotionName.attack.ToString().ToLower(),
@@ -23,12 +23,23 @@
     protected Spine.Skeleton skeleton;
     protected float defaultMixDuration = 0f;
     private Spine.TrackEntry currentTrack;
+    private Dictionary<int, Spine.TrackEntry> activeSkillTracks = new Dictionary<int, Spine.TrackEntry>();
+    
+    // 瀛愭妧鑳借建閬撴睜绠$悊锛堝湪Init涓垵濮嬪寲锛屼笉瑕佸湪杩欓噷鍒濆鍖栵級
+    private Queue<int> availableSubTracks;
+    private Dictionary<SkillBase, int> subSkillTrackMap = new Dictionary<SkillBase, int>();
+    
     private SkeletonIllusionShadow illusionShadow;
     private bool playingSkillAnim = false;
 
-    private float pauseTime = 0f;
+    private bool isUnderControl = false;
 
+    private float pauseTime = 0f;
     private float resumeTime = 0f;
+
+    // 鏂板锛氱疮绉殏鍋滄椂闀匡紝鐢ㄤ簬瀵归潪鍔ㄧ敾璺緞(Time.time)杩涜绋冲畾鐨勬椂闂翠慨姝�
+    private float pausedAccumulated = 0f;
+    private float pauseStart = 0f;
 
     public virtual void Init(SkeletonAnimation skelAnim)
     {
@@ -46,6 +57,11 @@
         if (animState != null)
             animState.Data.DefaultMix = defaultMixDuration;
 
+        // 鍒濆鍖栧瓙鎶�鑳借建閬撴睜
+        availableSubTracks = new Queue<int>();
+        for (int i = 1; i <= 8; i++)
+            availableSubTracks.Enqueue(i);
+
         PlayAnimation(MotionName.idle, true);
         SetupAnimationHandlers();
         
@@ -56,6 +72,9 @@
     public virtual void Release()
     {
         trackEntryCallbacks.Clear();
+        activeSkillTracks.Clear();
+        availableSubTracks?.Clear();
+        subSkillTrackMap.Clear();
         if (animState != null)
         {
             animState.Complete -= OnAnimationComplete;
@@ -102,6 +121,7 @@
             return null;
         }
 
+        // 濡傛灉娌℃湁鍔ㄧ敾鍚嶇О锛屼娇鐢ㄦ棤鍔ㄧ敾妯″紡
         if (string.IsNullOrEmpty(skillConfig.SkillMotionName))
         {
             PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
@@ -121,7 +141,6 @@
     private Spine.TrackEntry ExecuteSkillAnim(SkillConfig skillConfig, SkillBase skillBase, Action onComplete,
         Spine.Animation targetAnim, bool hasAnim, bool isSubSkill)
     {
-
         bool isPangdeSkill = 1003020 == skillConfig.SkillID;
 
         int loopCount = skillConfig.LoopCount;
@@ -129,11 +148,47 @@
         int frameCount = activeFrames.Length;
         float recoveryFrame = skillConfig.RecoveryFrames;
 
+        // 杞ㄩ亾鍒嗛厤绛栫暐锛氫富鎶�鑳界敤 track 0锛屽瓙鎶�鑳戒粠杞ㄩ亾姹犲垎閰�
+        int trackIndex = 0;
+        if (isSubSkill)
+        {
+            if (availableSubTracks != null && availableSubTracks.Count > 0)
+            {
+                trackIndex = availableSubTracks.Dequeue();
+                subSkillTrackMap[skillBase] = trackIndex;
+            }
+            else
+            {
+                // 杞ㄩ亾姹犺�楀敖鎴栨湭鍒濆鍖栵紝鍥為��鍒版棤鍔ㄧ敾妯″紡
+                Debug.LogWarning($"瀛愭妧鑳借建閬撴睜宸叉弧鎴栨湭鍒濆鍖栵紝鎶�鑳絳skillConfig.SkillID}浣跨敤鏃犲姩鐢绘ā寮�");
+                PlaySkillNoAnim(skillConfig, skillBase, onComplete, isSubSkill);
+                return null;
+            }
+        }
+        
         Spine.TrackEntry skillTrack = null;
+        
         if (hasAnim)
         {
-            skillTrack = animState.SetAnimation(0, targetAnim, false);
-            currentTrack = skillTrack;
+            skillTrack = animState.SetAnimation(trackIndex, targetAnim, false);
+            if (null == skillTrack)
+            {
+                Debug.LogError($"鎶�鑳� {skillConfig.SkillID} 鍔ㄧ敾璁剧疆澶辫触");
+                // 濡傛灉鏄瓙鎶�鑳戒笖鍒嗛厤浜嗚建閬擄紝闇�瑕佸洖鏀�
+                if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+                {
+                    if (availableSubTracks != null)
+                        availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+                    subSkillTrackMap.Remove(skillBase);
+                }
+                return null;
+            }
+            
+            // 鍙湁涓绘妧鑳芥墠鏇存柊 currentTrack
+            if (!isSubSkill)
+                currentTrack = skillTrack;
+            
+            activeSkillTracks[trackIndex] = skillTrack;
         }
         
         playingSkillAnim = true;
@@ -141,7 +196,12 @@
         int currentLoop = 0, triggerCount = 0, failCount = 0;
         bool beginTriggered = false, finalStarted = false, finalEnded = false, middleStarted = false;
         bool[] triggeredFrames = new bool[frameCount];
-        float startTime = hasAnim ? 0 : Time.time;
+
+        // 鏂板锛氳褰曟妧鑳藉紑濮嬫椂鐨� pausedAccumulated 鍩虹嚎锛岀敤浜庡悗缁绠楄鎶�鑳借嚜韬殑鏆傚仠鏃堕暱
+        float pausedAccumulatedAtStart = pausedAccumulated;
+
+        // startTime 琛ㄧず鎶�鑳�"鏈湴閫昏緫鏃堕棿"鐨勮捣鐐癸紙浠� Time.time 涓哄熀鍑嗭級
+        float startTime = hasAnim ? 0f : Time.time;
 
         skillBase.OnSkillStart();
 
@@ -150,12 +210,30 @@
         {
             if (skillBase.IsFinished())
             {
-                playingSkillAnim = false;
+                // 娓呯悊骞堕��鍑猴紙淇濊瘉鐘舵�佷竴鑷达級
+                if (skillTrack != null && activeSkillTracks.ContainsKey(trackIndex))
+                {
+                    if (activeSkillTracks[trackIndex] == skillTrack)
+                        activeSkillTracks.Remove(trackIndex);
+                }
+                
+                // 鍥炴敹瀛愭妧鑳借建閬�
+                if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+                {
+                    if (availableSubTracks != null)
+                        availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+                    subSkillTrackMap.Remove(skillBase);
+                }
+                
+                // 鍙湁褰撴病鏈夊叾浠栨椿璺冩妧鑳芥椂鎵嶅浣� playingSkillAnim
+                if (activeSkillTracks.Count == 0)
+                    playingSkillAnim = false;
+                
                 RemoveAction(frameHandler);
                 return;
             }
 
-            float trackTime = 0f; //hasAnim ? skillTrack.TrackTime * skillTrack.TimeScale : (Time.time - startTime) * MotionTimeScale;
+            float trackTime = 0f;
 
             if (hasAnim)
             {
@@ -163,40 +241,65 @@
             }
             else
             {
+                // 浣跨敤 pausedAccumulatedAtStart 鏉ヨ绠�"杩欎釜鎶�鑳借嚜寮�濮嬩互鏉ョ殑鏆傚仠鎬绘椂闀�"
                 float adjustedTime = Time.time;
-                if (pauseTime > 0f && resumeTime > pauseTime)
-                {
-                    startTime = startTime + (resumeTime - pauseTime);
-                    pauseTime = 0f;
-                    resumeTime = 0f;
-                }
-                trackTime = (adjustedTime - startTime) * MotionTimeScale;
+                float thisSkillPaused = pausedAccumulated - pausedAccumulatedAtStart;
+                if (thisSkillPaused < 0f) thisSkillPaused = 0f; // 淇濋櫓闃叉姢
+
+                // 閫昏緫杩愯鏃堕棿 = 褰撳墠鏃堕棿 - startTime - 鏈妧鑳藉凡鏆傚仠鏃堕暱
+                trackTime = (adjustedTime - startTime - thisSkillPaused) * MotionTimeScale;
             }
 
             float currentFrame = trackTime * BattleConst.skillMotionFps;
 
             if (hasAnim)
             {
-                if (currentTrack != skillTrack)
+                // 妫�鏌ュ綋鍓嶈建閬撴槸鍚﹁鏂版妧鑳借鐩�
+                if (!activeSkillTracks.ContainsKey(trackIndex) || activeSkillTracks[trackIndex] != skillTrack)
                 {
                     Debug.LogError("鎶�鑳藉姩鐢昏鎵撴柇锛屽己鍒剁粨鏉� " + skillConfig.SkillID);
                     skillBase.ForceFinished();
+
+                    // 娓呯悊骞剁‘淇濈姸鎬佸浣�
                     RemoveAction(frameHandler);
-                    playingSkillAnim = false;
+                    
+                    // 鍥炴敹瀛愭妧鑳借建閬�
+                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+                    {
+                        if (availableSubTracks != null)
+                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+                        subSkillTrackMap.Remove(skillBase);
+                    }
+                    
+                    if (activeSkillTracks.Count == 0)
+                        playingSkillAnim = false;
                     return;
                 }
-                
+
                 if (skillTrack.TrackTime == 0) failCount++;
                 if (failCount > 100)
                 {
                     Debug.LogError("鎶�鑳藉姩鐢绘挱鏀惧け璐ワ紝寮哄埗缁撴潫 " + skillConfig.SkillID);
                     skillBase.ForceFinished();
                     RemoveAction(frameHandler);
-                    playingSkillAnim = false;
+                    if (activeSkillTracks.ContainsKey(trackIndex))
+                        activeSkillTracks.Remove(trackIndex);
+                    
+                    // 鍥炴敹瀛愭妧鑳借建閬�
+                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+                    {
+                        if (availableSubTracks != null)
+                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+                        subSkillTrackMap.Remove(skillBase);
+                    }
+                    
+                    if (activeSkillTracks.Count == 0)
+                        playingSkillAnim = false;
                     return;
                 }
             }
 
+            // 鍚勯樁娈靛洖璋冿紙鍘熸湁閫昏緫锛�
             if (!beginTriggered && currentFrame >= skillConfig.StartupFrames && currentLoop == 0)
             {
                 beginTriggered = true;
@@ -231,9 +334,15 @@
                     if (BattleConst.skillMotionFps > 0)
                     {
                         if (hasAnim)
+                        {
                             skillTrack.TrackTime = skillConfig.StartupFrames / BattleConst.skillMotionFps;
+                        }
                         else
+                        {
+                            // 涓轰笅涓� loop 閲嶇疆 startTime锛屽苟涓旀洿鏂� pausedAccumulatedAtStart锛堜互淇濇寔鍩虹嚎锛�
                             startTime = Time.time - (skillConfig.StartupFrames / BattleConst.skillMotionFps);
+                            pausedAccumulatedAtStart = pausedAccumulated;
+                        }
                     }
                     beginTriggered = false;
                 }
@@ -254,10 +363,26 @@
                 if (finalStarted && !finalEnded && currentFrame >= recoveryFrame)
                 {
                     finalEnded = true;
-                    if (!isSubSkill)
+
+                    // 娓呯悊鎶�鑳借建閬�
+                    if (skillTrack != null && activeSkillTracks.ContainsKey(trackIndex))
                     {
-                        playingSkillAnim = false;
+                        if (activeSkillTracks[trackIndex] == skillTrack)
+                            activeSkillTracks.Remove(trackIndex);
                     }
+
+                    // 鍥炴敹瀛愭妧鑳借建閬�
+                    if (isSubSkill && subSkillTrackMap.ContainsKey(skillBase))
+                    {
+                        if (availableSubTracks != null)
+                            availableSubTracks.Enqueue(subSkillTrackMap[skillBase]);
+                        subSkillTrackMap.Remove(skillBase);
+                    }
+
+                    // 鍙湁褰撴病鏈夊叾浠栨椿璺冩妧鑳芥椂鎵嶅浣� playingSkillAnim
+                    if (activeSkillTracks.Count == 0)
+                        playingSkillAnim = false;
+
                     RemoveAction(frameHandler);
                     onComplete?.Invoke();
                     skillBase.OnFinalFrameEnd();
@@ -305,7 +430,7 @@
     protected virtual void OnAnimationComplete(Spine.TrackEntry trackEntry)
     {
         if (trackEntry?.Animation?.Name == null) return;
-        
+
         string animName = trackEntry.Animation.Name.ToLower();
 
         if (AttackMotionList.Contains(animName))
@@ -318,12 +443,33 @@
             OnHitAnimationComplete?.Invoke();
             PlayAnimation(MotionName.idle, true);
         }
-        
+
         if (trackEntryCallbacks.TryGetValue(trackEntry, out var callback))
         {
             trackEntryCallbacks.Remove(trackEntry);
             callback?.Invoke();
         }
+    }
+
+    public void SetControledAnimation()
+    {
+        //  鍙楀埌纭帶鐨勬椂鍊欙紝淇濇寔鍙楀嚮鍔ㄧ敾鐨勭涓夊抚锛岀洿鍒版帶鍒剁粨鏉� 鎴栬�呮渶鍚庝竴鍑绘浜★紝绉婚櫎鎺у埗鏁堟灉鍚庯紝鎭㈠鍒板緟鏈虹姸鎬佹垨鑰呮挱鏀炬浜″姩鐢�
+        //  杩欓噷鏄彈鍒扮‖鎺ф椂鍊� 闇�瑕佽〃鐜扮殑鍔ㄧ敾
+
+        var entry = PlayAnimation(MotionName.hit, false);
+        float threeFrameTrackTime = 3f / BattleConst.skillMotionFps;
+        entry.TrackTime = threeFrameTrackTime;
+        entry.TimeScale = 0;
+
+        isUnderControl = true;
+
+    }
+    
+    public void CancelControledAnimation()
+    {
+        //  纭帶缁撴潫锛屾仮澶嶅姩鐢绘挱鏀�
+        isUnderControl = false;
+        PlayAnimation(MotionName.idle, true);
     }
 
     public virtual void Run()
@@ -337,12 +483,25 @@
     public virtual void Pause()
     {
         if (skeletonAnim != null) skeletonAnim.timeScale = 0f;
+
+        // 璁板綍鍗曟鏆傚仠寮�濮嬫椂鍒�
+        pauseStart = Time.time;
+        // 鍏煎鏃у瓧娈碉紙淇濈暀浣嗕笉鍐嶇敤浜庣疮绉�昏緫锛�
         pauseTime = Time.time;
     }
 
     public virtual void Resume()
     {
         if (skeletonAnim != null) skeletonAnim.timeScale = MotionTimeScale;
+
+        // 绱Н鏆傚仠鏃堕暱锛堝鏋滄浘璁板綍杩� pauseStart锛�
+        if (pauseStart > 0f)
+        {
+            pausedAccumulated += (Time.time - pauseStart);
+            pauseStart = 0f;
+        }
+
+        // 淇濇寔鏃у瓧娈典互鍏煎鐜版湁浠g爜锛堜絾瀹為檯鏃堕棿淇浣跨敤 pausedAccumulated锛�
         resumeTime = Time.time;
     }
 
@@ -350,6 +509,18 @@
     {
         trackEntryCallbacks.Clear();
         runningActions.Clear();
+        activeSkillTracks.Clear();
+        
+        // 閲嶇疆瀛愭妧鑳借建閬撴睜
+        if (availableSubTracks == null)
+            availableSubTracks = new Queue<int>();
+        else
+            availableSubTracks.Clear();
+            
+        subSkillTrackMap.Clear();
+        for (int i = 1; i <= 8; i++)
+            availableSubTracks.Enqueue(i);
+        
         playingSkillAnim = false;
         PlayAnimation(MotionName.idle, true);
     }
@@ -360,12 +531,12 @@
         if (skeletonAnim != null) skeletonAnim.timeScale = ratio;
     }
 
-    public void ShowIllusionShadow(bool isVisible)
+    public void ShowIllusionShadow(bool isVisible, Color color = default)
     {
         if (illusionShadow != null)
         {
             illusionShadow.SetSkeletonAnimation(skeletonAnim);
-            illusionShadow.Show(isVisible);
+            illusionShadow.Show(isVisible, color);
         }
     }
 }
\ No newline at end of file

--
Gitblit v1.8.0