From dda7b1c0db34f237e65d74efddf9b592909f3d24 Mon Sep 17 00:00:00 2001 From: Tran Hai Nam Date: Mon, 11 May 2026 11:00:04 +0700 Subject: [PATCH] Fix annimation not loop --- .../Common/A3DCombinedAction.cs | 19 +++++- Assets/PerfectWorld/Scripts/NPC/CECModel.cs | 55 +++++++++++------- Assets/Scripts/PlayerVisual.cs | 58 +++++++++---------- 3 files changed, 82 insertions(+), 50 deletions(-) diff --git a/Assets/ModelRenderer/Scripts/A3DModelReader/Common/A3DCombinedAction.cs b/Assets/ModelRenderer/Scripts/A3DModelReader/Common/A3DCombinedAction.cs index 82d0bf8026..929612ae24 100755 --- a/Assets/ModelRenderer/Scripts/A3DModelReader/Common/A3DCombinedAction.cs +++ b/Assets/ModelRenderer/Scripts/A3DModelReader/Common/A3DCombinedAction.cs @@ -127,6 +127,8 @@ namespace ModelViewer.Common public int m_nMinLoops; public int m_nMaxLoops; + public bool IsInfinite() { return m_nMinLoops == -1 || m_nMaxLoops == -1; } + public int CalcLoopNum() { return IsInfinite() ? -1 : Random.Range(m_nMinLoops, m_nMaxLoops); } public bool Load(FileStream fileStream, StreamReader file, uint dwVersion) { bool isBinary = fileStream != null; @@ -174,6 +176,21 @@ namespace ModelViewer.Common } } + + public class ACTIONDYN_DATA + { + private int m_nLoopNum; + ACTION_INFO m_pInfo; + public ACTIONDYN_DATA(int nLoopNum = 0, ACTION_INFO pInfo = null) + { + m_nLoopNum = nLoopNum; + m_pInfo = pInfo; + } + public int GetLoopNum() { return m_nLoopNum; } + public ACTION_INFO GetActInfo() { return m_pInfo; } + public int GetTimeSpan() { return 1/*m_pInfo.GetTimeSpan()*/; } + public int GetTotalTime() { return GetLoopNum() * GetTimeSpan(); } + } [System.Serializable] public class EVENT_INFO { @@ -487,7 +504,7 @@ namespace ModelViewer.Common public string m_strName; public int m_nLoops; - + public bool IsLooping() { if (m_ActLst.Count == 0) diff --git a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs index b341406efa..3bec2da856 100644 --- a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs +++ b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Runtime.InteropServices; using BrewMonster.Scripts; using CSNetwork.GPDataType; @@ -138,18 +139,11 @@ public class A3DCombActDynData m_bSetSpeedWhenActStart = false; m_fModelScale = 1.0f; var actInfoList = pAct.m_ActLst; - // { - // ActInfoList& actInfoList = pAct->m_ActLst; - // ALISTPOSITION pos = actInfoList.GetHeadPosition(); - // while (pos) - // { - // PACTION_INFO pAct = actInfoList.GetNext(pos); - // int nDynLoopNum = pAct->CalcLoopNum(); - // m_arrActLoopNum.Add(ACTIONDYN_DATA(nDynLoopNum, pAct)); - // if (!m_bIsInfiniteComAct && nDynLoopNum < 0) m_bIsInfiniteComAct = true; - // } - // CalcDynComActSpan(); - // } + foreach(var actInfo in actInfoList) + { + int nDynLoopNum = actInfo.CalcLoopNum(); + if (!m_bIsInfiniteComAct && nDynLoopNum < 0) m_bIsInfiniteComAct = true; + } } /// @@ -197,12 +191,13 @@ public class A3DCombActDynData ChannelAct channelAct = m_pECModel.GetChannelAct(m_nChannel); if (channelAct != null) { - bool isLoop = m_pAct.m_nLoops == 1; + bool isLoop = m_bIsInfiniteComAct; int ownerId = m_pECModel.GetId(); EventBus.PublishChannel(ownerId, new PlayActionEvent(ref channelAct, actionInfos[0].m_strName, m_nTransTime, bForceStopPrevious, ActiveAttackEvent, isLoop, channelRank)); m_ActionNames.Add(actionInfos[0].m_strName); for(int i = 1; i < actionInfos.Count; i++) { + isLoop = m_bIsInfiniteComAct; EventBus.PublishChannelClass(ownerId, new QueueActionEvent(ref channelAct, actionInfos[i].m_strName, null, false, null, m_nTransTime, false, isLoop, channelRank)); m_ActionNames.Add(actionInfos[i].m_strName); } @@ -228,21 +223,41 @@ public class A3DCombActDynData { if (sfx.m_strFilePaths != null && sfx.m_strFilePaths.Count > 0) { - string soundpath = AFile.NormalizePath(sfx.m_strFilePaths[0], true); - if (soundpath.Contains("gfx")) - continue; - soundpath = soundpath.ToLower(); - m_SFXNames.Add(soundpath); + string path = AFile.NormalizePath(sfx.m_strFilePaths[0], true); + if (path.Contains("gfx")) + goto GFX; + + path = path.ToLower(); + m_SFXNames.Add(path); try { SFXManager.Instance - .PlaySkillSfxAtPointAsync(soundpath, Vector3.zero).Forget(); + .PlaySkillSfxAtPointAsync(path, Vector3.zero).Forget(); } finally { // remove AFTER sound finished - m_SFXNames.Remove(soundpath); + m_SFXNames.Remove(path); } + goto END; + GFX: + { + var gfxLogPath = Path.Combine(Application.dataPath, "PerfectWorld", "Scripts", "NPC", "GFXLOG.txt"); + var lines = new List(); + if (File.Exists(gfxLogPath)) + { + foreach (var line in File.ReadAllLines(gfxLogPath)) + { + if (string.Equals(line.Trim(), path, StringComparison.OrdinalIgnoreCase)) + continue; + lines.Add(line); + } + } + lines.Add(path); + File.WriteAllLines(gfxLogPath, lines); + } + END: + continue; } } } diff --git a/Assets/Scripts/PlayerVisual.cs b/Assets/Scripts/PlayerVisual.cs index b9b52a7665..121e6e0d86 100644 --- a/Assets/Scripts/PlayerVisual.cs +++ b/Assets/Scripts/PlayerVisual.cs @@ -46,20 +46,27 @@ namespace BrewMonster } if (_animationQueue.Count > 0) { - _animationQueue.Enqueue(new AnimationQueue + if(@event.IsForceStopPrevious) { - AnimationName = @event.AnimationName, - IsForceStopPrevious = @event.IsForceStopPrevious, - AttackEvent = @event.AttackEvent, - ChannelAct = @event.ChannelAct, - Rank = @event.Rank - }); - _animationList = _animationQueue.Select(q => q.AnimationName).ToList(); - return; + _animationQueue.Clear(); + } + else + { + _animationQueue.Enqueue(new AnimationQueue + { + AnimationName = @event.AnimationName, + IsForceStopPrevious = @event.IsForceStopPrevious, + AttackEvent = @event.AttackEvent, + ChannelAct = @event.ChannelAct, + Rank = @event.Rank + }); + _animationList = _animationQueue.Select(q => q.AnimationName).ToList(); + return; + } } previousAnimationName = @event.AnimationName; - InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode, @event.IsLoop); - ApplyAnimationEndCallbacks(@event.AttackEvent, @event.ChannelAct, @event.Rank, @event.AnimationName); + InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode); + ApplyAnimationEndCallbacks(@event.AttackEvent, @event.ChannelAct, @event.Rank, @event.AnimationName, @event.IsLoop); } public void InitPlayerEventDoneHandler() { @@ -195,6 +202,7 @@ namespace BrewMonster AttackEvent = null, IsLoop = true }); + Debug.Log($"EnqueueAnimationForLooping: {animationName}, _animationQueue: {string.Join(", ", _animationList)}"); _animationList = _animationQueue.Select(q => q.AnimationName).ToList(); return true; } @@ -205,14 +213,6 @@ namespace BrewMonster { return; } - else - { - string animationQueueString = ""; - foreach(var animation in _animationQueue) - { - animationQueueString += animation.AnimationName + ", "; - } - } if (_animationQueue.Peek().IsForceStopPrevious) { @@ -227,21 +227,26 @@ namespace BrewMonster var animationQueue = _animationQueue.Dequeue(); _animationList = _animationQueue.Select(q => q.AnimationName).ToList(); previousAnimationName = animationQueue.AnimationName; - InternalPlayAnimation(animationQueue.AnimationName, animationQueue.ITransTime, FadeMode, animationQueue.IsLoop); - ApplyAnimationEndCallbacks(animationQueue.AttackEvent, animationQueue.ChannelAct, animationQueue.Rank, animationQueue.AnimationName); + InternalPlayAnimation(animationQueue.AnimationName, animationQueue.ITransTime, FadeMode); + ApplyAnimationEndCallbacks(animationQueue.AttackEvent, animationQueue.ChannelAct, animationQueue.Rank, animationQueue.AnimationName,animationQueue.IsLoop); } - private void ApplyAnimationEndCallbacks(CECAttackEvent attackEvent, ChannelAct channelAct, int rank, string animationName) + private void ApplyAnimationEndCallbacks(CECAttackEvent attackEvent, ChannelAct channelAct, int rank, string animationName, bool isLoop) { if (_currentState == null) return; _currentState.Events.OnEnd = () => { if (attackEvent != null) attackEvent.m_bSignaled = true; + if(isLoop) + { + EnqueueAnimationForLooping(animationName); + } if (channelAct == null || string.IsNullOrEmpty(animationName)) return; var node = channelAct.GetNodeByRank((byte)rank); node?.m_pActive?.m_ActionNames?.Remove(animationName); + }; } void ApplyDamage() @@ -271,7 +276,7 @@ namespace BrewMonster /// /// /// - private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode, bool isLoop = false) + private void InternalPlayAnimation(string animationName, float duration = FadeTime, FadeMode fadeMode = FadeMode) { if (namedAnimancer == null) { @@ -281,13 +286,8 @@ namespace BrewMonster if (isState) { _currentState = namedAnimancer.TryPlay(animationName, duration / 1000, fadeMode); + _currentState.Time = 0; _currentAnimationName = animationName; - //if the animation is looping and the current state is not looping, play the animation again - if(isLoop == true && _currentState.IsLooping == false) - { - _currentState.Time = 0; - _currentState.Events.OnEnd = () => EnqueueAnimationForLooping(animationName); - } return; } //BMLogger.LogError($"Null name animation: {animationName}");