diff --git a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs
index c2b9ba5fc1..8043d711de 100644
--- a/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs
+++ b/Assets/PerfectWorld/Scripts/Move/CECPlayer.cs
@@ -24,7 +24,7 @@ using BrewMonster.Scripts.ECModel;
namespace BrewMonster
{
- public abstract partial class CECPlayer : CECObject
+ public abstract partial class CECPlayer : CECObject, ITickable
{
[SerializeField] protected Transform parentModel;
[SerializeField] protected TextMeshProUGUI txtName;
@@ -360,6 +360,21 @@ namespace BrewMonster
m_iShape = 0;
m_aEquips = new int[(int)IndexOfIteminEquipmentInventory.SIZE_ALL_EQUIPIVTR];
queueActionEvent = new QueueActionEvent("", null, false, null, 200);
+ TickInvoker.Instance.RegisterTickable(this);
+ }
+
+ protected virtual void OnDestroy()
+ {
+ TickInvoker.Instance.UnregisterTickable(this);
+ }
+
+ public override bool Tick(uint dwDeltaTime)
+ {
+ if(m_pPlayerCECModel != null)
+ {
+ m_pPlayerCECModel.Tick(dwDeltaTime);
+ }
+ return true;
}
/// This function will get the coressponding model player for the player based on the profession and gender
@@ -1336,6 +1351,11 @@ namespace BrewMonster
}
return PlayActionWithConfig(iAction, m_PlayerActions[iAction], bRestart, iTransTime, bQueue);
}
+
+
+ const int COMACT_FLAG_MODE_NONE = 0;
+ const int COMACT_FLAG_MODE_ONCE = 1;
+ const int COMACT_FLAG_MODE_ONCE_IGNOREGFX = 2;
const int COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX = 3;
private bool PlayActionWithConfig(int iAction, in PLAYER_ACTION actionConfig,
bool bRestart = true, int iTransTime = 200, bool bQueue = false)
diff --git a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs
index f3db65e1b6..b341406efa 100644
--- a/Assets/PerfectWorld/Scripts/NPC/CECModel.cs
+++ b/Assets/PerfectWorld/Scripts/NPC/CECModel.cs
@@ -13,6 +13,7 @@ using ECModelHookMap = System.Collections.Generic.Dictionary;
using ActQueue = System.Collections.Generic.List;
using BrewMonster;
using BrewMonster.Scripts.ECModel;
+using Cysharp.Threading.Tasks;
using Unity.VisualScripting.FullSerializer;
public enum ECMScript
{
@@ -54,13 +55,243 @@ public enum ActionChannel
};
public class A3DCombActDynData
{
- public A3DCombinedAction combinedAction;
- public int nChannel;
- public int m_dwUserData;
- public bool IsAllActionFinished => m_EventNames.Count == 0;
- public List m_EventNames = new List();
+ protected A3DCombinedAction m_pAct;
+ protected CECModel m_pECModel;
+ protected int m_dwTimeSpan;
+ protected float m_fWeight;
+ protected int m_nTransTime;
+ protected int m_dwUserData;
+ protected bool m_bAbsTrack;
+ protected bool m_bNoFx;
+ //ALISTPOSITION m_CurEventPos;
+ //const ChildActInfo* m_pParentInfo;
+ //CECModel* m_pParentModel;
+ protected int m_dwDeltaTime;
+ protected bool m_bStopPrevAct;
+ //important
+ //FxBindBaseList m_ActFxArray;
+ protected int m_nChannel;
+
+ protected int m_dwEventMask;
+ //ActDynArray m_arrActLoopNum;
+ protected int m_nCurActIndex;
+ protected int m_dwDynComActSpan;
+ protected bool m_bIsInfiniteComAct;
+
+ //important
+ //EventInfoMap m_mapDynAddedInfo;
+
+ /// Attack event tied to this combined action, if any. / 与此组合动作绑定的攻击事件(若有)
+ /// this is alternative for m_IdCaster to m_IsAttackAct in c++
+ ///
+ public CECAttackEvent ActiveAttackEvent;
+
+ public bool m_bResetPSWhenActionStop;
+ public bool m_bSetSpeedWhenActStart;
+ public float m_fModelScale;
+
+
+ public List m_ActionNames = new List();
+ public List m_SFXNames = new List();
+ public bool IsActionStopped() { return m_ActionNames.Count == 0; }
+ /// True when there is no attack or damage has been applied. / 无攻击事件或已造成伤害则为 true
+ public bool IsAllEventFinished() { return (ActiveAttackEvent == null || ActiveAttackEvent.m_bDoDamaged); }
+ /// Animations finished and attack-event phase finished. / 动画与攻击事件阶段均结束
+ public bool IsAllFinished()
+ {
+ if(IsActionStopped() && IsAllEventFinished())
+ {
+ return true;
+ }
+ return false;
+ }
+ public A3DCombActDynData(A3DCombinedAction pAct, CECModel pECModel, CECAttackEvent attackEvent)
+ {
+ m_pAct = pAct;
+ m_pECModel = pECModel;
+ // m_nCurLoop = 0;
+ // m_nCurActLoop = 0;
+ m_dwTimeSpan = 0;
+ m_fWeight = 1.0f;
+ m_nTransTime = 200;
+ m_dwUserData = 0;
+ m_bAbsTrack = false;
+ m_bNoFx = false;
+ // m_CurEventPos = 0;
+ // m_pParentInfo = 0;
+ // m_pParentModel = 0;
+ m_bStopPrevAct = false;
+ m_dwDeltaTime = 0;
+ m_nChannel = 0;
+ m_dwEventMask = -1;
+ //use active attack event instead of idCaster to m_IsAttackAct
+ ActiveAttackEvent = attackEvent;
+ // m_idCaster = 0;
+ // m_idCastTarget = 0;
+ // m_ptFixed = 0;
+ // m_SerialId = 0;
+ // m_IsAttackAct = false;
+ m_nCurActIndex = -1;
+ m_dwDynComActSpan = 0;
+ m_bIsInfiniteComAct = false;
+ m_bResetPSWhenActionStop = false;
+ 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();
+ // }
+ }
+
+ ///
+ /// When true, publishes for Animancer, tracks ,
+ /// and plays combined-action sound FX from data (unless suppresses audio).
+ /// / 为 true 时发布 PlayActionEvent、维护 m_EventNames,并按数据播放组合动作音效(bNoFx 时跳过音效)。
+ ///
+ public void Play(int nChannel, float fWeight, int nTransTime, int dwEventMask, bool bRestart, bool bAbsTrack, bool bNoFx,
+ bool bForceStopPrevious = false, byte channelRank = 0)
+ {
+ m_nChannel = nChannel;
+ m_fWeight = fWeight;
+ m_nTransTime = nTransTime;
+ m_dwEventMask = dwEventMask;
+ m_bAbsTrack = bAbsTrack;
+ m_bNoFx = bNoFx;
+
+ // if (bRestart)
+ // m_nCurLoop = 0;
+
+ m_fModelScale = 1; //Vm_pECModel.GetAllRootBonesScale();
+
+ PublishVisual(bForceStopPrevious, channelRank);
+ if (!m_bNoFx)
+ TriggerSFxFromEventList();
+ // Resume();
+ // UpdateAct(0);
+ // #ifdef _ANGELICA21
+ // UpdateEvent(0, 0);
+ // #endif
+ }
+
+ ///
+ /// Notify visual layer and fire combined-action audio using data on this instance.
+ /// / 通知表现层并根据本实例数据触发组合动作音效。
+ ///
+ void PublishVisual(bool bForceStopPrevious, byte channelRank)
+ {
+ if (m_pECModel == null || m_pAct == null)
+ return;
+
+ var actionInfos = m_pAct.m_ActLst;
+ if (actionInfos != null && actionInfos.Count > 0 && !string.IsNullOrEmpty(actionInfos[0].m_strName))
+ {
+ ChannelAct channelAct = m_pECModel.GetChannelAct(m_nChannel);
+ if (channelAct != null)
+ {
+ bool isLoop = m_pAct.m_nLoops == 1;
+ 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++)
+ {
+ 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);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Sound events embedded in combined action; skip gfx paths. / 组合动作内嵌音效事件;跳过 gfx 路径。
+ ///
+ void TriggerSFxFromEventList()
+ {
+ if (m_bNoFx || m_pAct == null)
+ return;
+
+ var eventInfoList = m_pAct.m_EventInfoLst;
+ if (eventInfoList == null || eventInfoList.Count == 0)
+ return;
+
+ foreach (var eventInfo in eventInfoList)
+ {
+ if (eventInfo is FX_BASE_INFO sfx)
+ {
+ 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);
+ try
+ {
+ SFXManager.Instance
+ .PlaySkillSfxAtPointAsync(soundpath, Vector3.zero).Forget();
+ }
+ finally
+ {
+ // remove AFTER sound finished
+ m_SFXNames.Remove(soundpath);
+ }
+ }
+ }
+ }
+ }
+ public void Stop(bool bStopAct, bool bForceStopFx = false )
+ {
+ // FlushDamageInfo();
+
+ // ClearParentInfo();
+ // m_nCurLoop = 0;
+ // m_nCurActLoop = 0;
+
+ // RemoveAllActiveFx(bForceStopFx);
+ // A3DSkinModel* pSkinModel = m_pECModel->GetA3DSkinModel();
+
+ // m_pECModel->GetStaticData()->OnScriptEndAction(m_pECModel, m_nChannel, m_pAct->GetName());
+
+ // if (IsResetPSWhenActStop())
+ // {
+ // m_pECModel->RemoveReplaceShader();
+ // SetResetPSWhenActStop(false);
+ // }
+
+ // if (m_pAct->GetResetMaterialScale())
+ // m_pECModel->ResetMaterialScale();
+
+ // if (m_pAct->GetStopChildrenAct())
+ // m_pECModel->StopChildrenAct();
+
+ // if (pSkinModel == NULL || !bStopAct)
+ // return;
+
+ // A3DSMActionChannel* pChannel = pSkinModel->GetActionChannel(m_nChannel);
+
+ // if (pChannel)
+ // pChannel->StopAction(m_pAct->GetRank(m_nChannel));
+ }
+
public void SetUserData(int dwUserData) { m_dwUserData = dwUserData; }
+ public void SetTransTime(int nTransTime) { m_nTransTime = nTransTime; }
+ public void SetStopPrevAct(bool bStopPrevAct) { m_bStopPrevAct = bStopPrevAct; }
+ public void SetNoFxFlag(bool bNoFx) { m_bNoFx = bNoFx; }
+ public void SetSpeedWhenActStart(bool bResetSpeed) { m_bSetSpeedWhenActStart = bResetSpeed; }
+ public bool GetStopPrevAct() { return m_bStopPrevAct; }
public int GetUserData() { return m_dwUserData; }
+ public int GetTransTime() { return m_nTransTime; }
+ public bool GetNoFxFlag() { return m_bNoFx; }
+ public bool IsSetSpeedWhenActStart() { return m_bSetSpeedWhenActStart; }
+ public A3DCombinedAction GetComAct() { return m_pAct; }
}
public class ChannelActNode
{
@@ -68,22 +299,22 @@ public class ChannelActNode
public A3DCombActDynData m_pActive;
public bool m_pActFlag;
public int m_dwFlagMode;
- public ActQueue m_ActQueue;
+ public ActQueue m_QueuedActs;
public ChannelActNode()
{
m_Rank = 0;
m_pActive = null;
m_pActFlag = false;
m_dwFlagMode = 0;
- if(m_ActQueue == null)
+ if(m_QueuedActs == null)
{
- m_ActQueue = new ActQueue();
+ m_QueuedActs = new ActQueue();
}
- m_ActQueue.Clear();
+ m_QueuedActs.Clear();
}
public void RemoveQueuedActs()
{
- m_ActQueue.Clear();
+ m_QueuedActs.Clear();
}
}
public class ChannelAct
@@ -478,14 +709,27 @@ public class CECModel
private int m_nId = 0;
public GameObject m_pPlayerModel;
private const uint COMACT_FLAG_MODE_NONE = 0;
+ private const uint COMACT_FLAG_MODE_ONCE_IGNOREGFX = 2;
+ private const uint COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX = 3;
protected CECModelStaticData m_pMapModel = new CECModelStaticData();
public SkeletonBuilder m_skeletonBuilder;
private Dictionary m_hookCache = new Dictionary();
private Dictionary m_hangerPositionCache = new Dictionary();
private Dictionary m_childModels = new Dictionary();
private Transform m_transform;
+ private bool m_bAbsTrack = false;
public bool InheritParentId() => m_bInheritParentId;
public void SetId(int nId) => m_nId = nId;
+ public int GetId() => m_nId;
+
+ /// Channel playback container for combined actions. / 组合动作通道容器。
+ public ChannelAct GetChannelAct(int nChannel)
+ {
+ if (nChannel < 0 || nChannel >= m_ChannelActs.Length)
+ return null;
+ return m_ChannelActs[nChannel];
+ }
+
//16 is
ChannelAct[] m_ChannelActs = InitChannelActs();
private static ChannelAct[] InitChannelActs()
@@ -783,54 +1027,19 @@ public class CECModel
{
return false;
}
- var actionInfos = combinedAction.m_ActLst;
- var isLoop = combinedAction.m_nLoops == 1;
- var node = m_ChannelActs[nChannel].GetNodeByRank(0);
- if (node == null)
+ var pNode = m_ChannelActs[nChannel].GetNodeByRank(0);
+ if (pNode == null)
{
- node = new ChannelActNode { m_Rank = 0 };
- m_ChannelActs[nChannel].m_RankNodes.Add(node);
- }
- var actData = new A3DCombActDynData
- {
- combinedAction = combinedAction,
- nChannel = nChannel,
- m_dwUserData = (int)dwUserData
- };
- EventBus.PublishChannel(m_nId, new PlayActionEvent(ref m_ChannelActs[nChannel], actionInfos[0].m_strName, nTransTime, bForceStop, attackEvent, isLoop, node.m_Rank));
- actData.m_EventNames.Add(actionInfos[0].m_strName);
-
- for(int i = 1; i < actionInfos.Count; i++)
- {
- EventBus.PublishChannelClass(m_nId, new QueueActionEvent(ref m_ChannelActs[nChannel], actionInfos[i].m_strName, null, false, attackEvent, nTransTime, false, isLoop, node.m_Rank));
- actData.m_EventNames.Add(actionInfos[i].m_strName);
+ pNode = new ChannelActNode { m_Rank = 0 };
+ m_ChannelActs[nChannel].m_RankNodes.Add(pNode);
}
+ pNode.m_pActive = new A3DCombActDynData(combinedAction, this, attackEvent);
+ pNode.m_pActive.SetUserData((int)dwUserData);
+ pNode.m_pActive.Play(nChannel, fWeight, nTransTime, 0, bRestart, m_bAbsTrack, bNoFx, bForceStop,pNode.m_Rank);
+ m_bAbsTrack = false;
+ pNode.m_pActFlag = false;
+ pNode.m_dwFlagMode = 2;//COMACT_FLAG_MODE_ONCE_IGNOREGFX;
- node.m_pActive = actData;
-
- //Todo: should move those event logic to channel act because their control the animation life span.
- var eventInfoList = combinedAction.m_EventInfoLst;
- if(eventInfoList != null && eventInfoList.Count > 0)
- {
- foreach(var eventInfo in eventInfoList)
- {
- //0 is sound event
- if (eventInfo is FX_BASE_INFO sfx)
- {
- if(sfx.m_strFilePaths != null && sfx.m_strFilePaths.Count > 0)
- {
- string soundpath = AFile.NormalizePath(sfx.m_strFilePaths[0],true);
- //we need to determine sfx and gfx. now we dont have logic for this path
- if(soundpath.Contains("gfx"))
- {
- continue;
- }
- soundpath = soundpath.ToLower();
- SFXManager.Instance.PlaySkillSfxAtPointAsync(soundpath, Vector3.zero).Forget();
- }
- }
- }
- }
return true;
}
public A3DCombinedAction GetComActByName(string szActName)
@@ -847,28 +1056,28 @@ public class CECModel
{
return false;
}
- A3DCombinedAction combinedAction = GetComActByName(szActName);
- if(combinedAction == null)
- {
+ A3DCombinedAction pComAct = GetComActByName(szActName);
+
+ if (pComAct == null)
return false;
- }
- var actionInfos = combinedAction.m_ActLst;
- var isLoop = combinedAction.m_nLoops == 1;
- var node = new ChannelActNode { m_Rank = (byte)m_ChannelActs[nChannel].m_RankNodes.Count};
- m_ChannelActs[nChannel].m_RankNodes.Add(node);
- var actData = new A3DCombActDynData
- {
- // combinedAction = combinedAction, // not needed now
- nChannel = nChannel,
- m_dwUserData = (int)dwUserData
- };
- EventBus.PublishChannelClass(m_nId, new QueueActionEvent(ref m_ChannelActs[nChannel], actionInfos[0].m_strName, null, false, attackEvent, nTransTime, bForceStopPrevAct, isLoop, node.m_Rank));
- for(int i = 1; i < actionInfos.Count; i++)
- {
- EventBus.PublishChannelClass(m_nId, new QueueActionEvent(ref m_ChannelActs[nChannel], actionInfos[i].m_strName, null, false, attackEvent, nTransTime, false, isLoop, node.m_Rank));
- actData.m_EventNames.Add(actionInfos[i].m_strName);
- }
- node.m_pActive = actData;
+
+ ChannelAct ca = m_ChannelActs[nChannel];
+ ChannelActNode pNode = ca.GetNodeByRank(0);
+
+ A3DCombActDynData pDynData = new A3DCombActDynData(pComAct, this, attackEvent);
+ pDynData.SetUserData((int)dwUserData);
+ pDynData.SetTransTime(nTransTime);
+ pDynData.SetStopPrevAct(bForceStopPrevAct);
+ pDynData.SetNoFxFlag(bNoFx);
+ pDynData.SetSpeedWhenActStart(bResetSpeed);
+ pNode.m_QueuedActs.Add(pDynData);
+
+ // EventBus.PublishChannelClass(m_nId, new QueueActionEvent(ref m_ChannelActs[nChannel], actionInfos[0].m_strName, null, false, attackEvent, nTransTime, bForceStopPrevAct, isLoop, node.m_Rank));
+ // for(int i = 1; i < actionInfos.Count; i++)
+ // {
+ // EventBus.PublishChannelClass(m_nId, new QueueActionEvent(ref m_ChannelActs[nChannel], actionInfos[i].m_strName, null, false, attackEvent, nTransTime, false, isLoop, node.m_Rank));
+ // actData.m_EventNames.Add(actionInfos[i].m_strName);
+ // }
//todo: should add sfx and gfx logic to channel act. currently we dont have logic for queue action. only available for play action.
return true;
}
@@ -880,11 +1089,12 @@ public class CECModel
return false;
}
- public int GetCurActionUserData()
+ public int GetCurActionUserData(int channel = 0)
{
var returnValue = -1;
- if (m_ChannelActs[0].GetHighestRankNode() != null)
- returnValue = m_ChannelActs[0].GetHighestRankNode().m_pActive.GetUserData();
+ var nodeCh0 = m_ChannelActs[channel].GetHighestRankNode();
+ if (nodeCh0 != null)
+ returnValue = nodeCh0.m_pActive.GetUserData();
return returnValue;
}
public bool QueueAction(CECNPC.INFO iNFO, string szActName, ref bool pNewActFlag, int nTransTime = 200, uint dwUserData = 0, bool bForceStopPrevAct = false, bool bCheckTailDup = false, bool bNoFx = false, bool bResetSpeed = false
@@ -911,6 +1121,85 @@ public class CECModel
AnimationName = animationName;
}
}
+ public bool Tick(uint dwDeltaTime)
+ {
+ UpdateChannelActs(dwDeltaTime);
+ return true;
+ }
+ void UpdateChannelActs(uint dwUpdateTime)
+ {
+ if (dwUpdateTime == 0)
+ return;
+
+ for (int i = 0; i < (int)ActionChannel.ACTCHA_MAX; i++)
+ {
+ ChannelAct ca = m_ChannelActs[i];
+ var rankNodes = ca.m_RankNodes;
+ for (int n = rankNodes.Count - 1; n >= 0; n--)
+ {
+ var node = rankNodes[n];
+ bool bActFinished = false;
+ if (node.m_dwFlagMode == COMACT_FLAG_MODE_ONCE_IGNOREGFX || node.m_dwFlagMode == COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX)
+ bActFinished = node.m_pActive.IsActionStopped();
+ else
+ bActFinished = node.m_pActive.IsAllFinished();
+
+ if (bActFinished)
+ {
+ if (node.m_dwFlagMode != COMACT_FLAG_MODE_NONE && node.m_pActFlag)
+ {
+ node.m_pActFlag = true;
+
+ if (node.m_dwFlagMode != COMACT_FLAG_MODE_ONCE_MULTIIGNOREGFX)
+ node.m_dwFlagMode = (int)COMACT_FLAG_MODE_NONE;
+
+ node.m_pActFlag = false;
+ }
+ if (node.m_QueuedActs.Count > 0)
+ {
+ A3DCombActDynData pNext = node.m_QueuedActs[0];
+ node.m_QueuedActs.RemoveAt(0);
+
+ if (pNext.GetStopPrevAct())
+ {
+ node.m_pActive.Stop(true);
+ //StopChildrenAct();
+ }
+ else
+ node.m_pActive.Stop(false);
+
+ // script
+ //m_pMapModel->OnScriptPlayAction(this, i, pNext->GetComAct()->GetName());
+
+ // Èç¹ûQueueActionµÄʱºòÉèÖÃÁËResetSpeed£¬ÔòÕâÀォËÙ¶ÈÉèÖÃÖØÖã¬Ä¬ÈÏÇé¿öϸñê־Ϊfalse
+ //by2021 ÕâÀï¿ÉÐÞ¸Ä
+ if (pNext.IsSetSpeedWhenActStart())
+ SetPlaySpeedByChannel(i, pNext.GetComAct());
+
+ node.m_pActive = null;
+ node.m_pActive = pNext;
+ node.m_pActive.Play(i, 1f, node.m_pActive.GetTransTime(), 0/**m_EventMasks[i]*/, true, m_bAbsTrack, pNext.GetNoFxFlag());
+ //pNext.UpdateAct(dwUpdateTime);
+ m_bAbsTrack = false;
+ }
+ else
+ {
+ node.m_pActive.Stop(false);
+ rankNodes.RemoveAt(n);
+ }
+ }
+ // else
+ // node.m_pActive.UpdateAct(dwUpdateTime);
+ }
+ }
+ }
+ void SetPlaySpeedByChannel(int nChannel, A3DCombinedAction pComAct)
+ {
+ // if (m_nMainChannel == nChannel || 0 == nChannel)
+ // {
+ // m_fPlaySpeed = m_fDefPlaySpeed * pComAct.GetPlaySpeed();
+ // }
+ }
public void PlayGfx(string szPath, string szHook, float fScale, bool bFadeOut, A3DVECTOR3 vOffset, float fPitch, float fYaw, float fRot, bool bUseECMHook, uint dwFadeOutTime)
{
if (!bFadeOut)
diff --git a/Assets/PerfectWorld/Scripts/NPC/NPCVisual.cs b/Assets/PerfectWorld/Scripts/NPC/NPCVisual.cs
index 894f70cc04..a7e2754672 100644
--- a/Assets/PerfectWorld/Scripts/NPC/NPCVisual.cs
+++ b/Assets/PerfectWorld/Scripts/NPC/NPCVisual.cs
@@ -27,8 +27,11 @@ public class NPCVisual : MonoBehaviour
// BMLogger.LogMono(this, "HoangDev: namedAnimancerIsPlaying == null1: " + animationName);
_currentState = namedAnimancer.TryPlay(animationName, fadeTime);
if (isHit)
- {
- _currentState.Events.OnEnd = () => SetHitOnEnd(cECAttackEvent);
+ {
+ if(_currentState != null)
+ {
+ _currentState.Events.OnEnd = () => SetHitOnEnd(cECAttackEvent);
+ }
}
// if (_currentState != null)
// BMLogger.LogMono(this, "HoangDev: _currentState != null1: " + _currentState.Clip.name);
diff --git a/Assets/Scripts/PlayerVisual.cs b/Assets/Scripts/PlayerVisual.cs
index e79b9b083e..b9b52a7665 100644
--- a/Assets/Scripts/PlayerVisual.cs
+++ b/Assets/Scripts/PlayerVisual.cs
@@ -59,7 +59,7 @@ namespace BrewMonster
}
previousAnimationName = @event.AnimationName;
InternalPlayAnimation(@event.AnimationName, @event.ITransTime, FadeMode, @event.IsLoop);
- ApplyAnimationEndCallbacks(@event.AttackEvent, @event.ChannelAct, @event.Rank);
+ ApplyAnimationEndCallbacks(@event.AttackEvent, @event.ChannelAct, @event.Rank, @event.AnimationName);
}
public void InitPlayerEventDoneHandler()
{
@@ -228,21 +228,20 @@ namespace BrewMonster
_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);
+ ApplyAnimationEndCallbacks(animationQueue.AttackEvent, animationQueue.ChannelAct, animationQueue.Rank, animationQueue.AnimationName);
}
- private void ApplyAnimationEndCallbacks(CECAttackEvent attackEvent, ChannelAct channelAct, int rank)
+ private void ApplyAnimationEndCallbacks(CECAttackEvent attackEvent, ChannelAct channelAct, int rank, string animationName)
{
if (_currentState == null) return;
_currentState.Events.OnEnd = () =>
{
if (attackEvent != null)
attackEvent.m_bSignaled = true;
- channelAct.GetNodeByRank((byte)rank).m_pActive.m_EventNames.Remove(_currentAnimationName);
- if(channelAct.GetNodeByRank((byte)rank).m_pActive.IsAllActionFinished)
- {
- //channelAct.RemoveNodeByRank((byte)rank);
- }
+ if (channelAct == null || string.IsNullOrEmpty(animationName))
+ return;
+ var node = channelAct.GetNodeByRank((byte)rank);
+ node?.m_pActive?.m_ActionNames?.Remove(animationName);
};
}
void ApplyDamage()