using System; // CECPlayerActionController // 玩家动作控制器 / Player action controller namespace BrewMonster { public class CECPlayerActionController { // Action channels for split-body animation (kept for parity with C++) // 动作通道(保留与C++一致的接口语义) / Channels kept to mirror C++ API public const int ACT_CHANNEL_UPPERBODY = 0; public const int ACT_CHANNEL_LOWERBODY = 1; public const int ACT_CHANNEL_WOUND = 2; private CECPlayer m_pPlayer; private CECModel m_pPlayerModel; private bool m_bSupportCastSkillWhenMove; private CECPlayerActionPlayPolicy m_actionPlayPolicy; private bool m_bSkillAttackActionPlayed; public CECModel PlayerModel => m_pPlayerModel; public CECPlayerActionController() { m_pPlayer = null; m_pPlayerModel = null; m_bSupportCastSkillWhenMove = false; m_actionPlayPolicy = null; m_bSkillAttackActionPlayed = false; } ~CECPlayerActionController() { ReleaseActionPlayPolicy(); } public void Bind(CECPlayer player, CECModel playerModel) { if (player == null) { return; } if (player == m_pPlayer && playerModel == m_pPlayerModel) { return; } ReleaseActionPlayPolicy(); m_pPlayer = player; m_pPlayerModel = playerModel; // 是否支持移动中施法(当前C#端未实现,统一设为false) // Support cast-while-move (not implemented in C# port -> false) m_bSupportCastSkillWhenMove = false; if (!m_bSupportCastSkillWhenMove) { // 如果不支持,仍保留“受击”通道逻辑钩子(在C#里留空) // If not supported, keep the hook for wound channel (no-op in C#) } InitializeActionPlayPolicy(); } public bool SupportCastSkillWhenMove() { return m_bSupportCastSkillWhenMove; } public bool CanCombineWithMoveForSkill(int idSkill) { return m_actionPlayPolicy != null && m_actionPlayPolicy.CanCombineWithMoveForSkill(idSkill); } private void InitializeActionPlayPolicy() { // 当前C#只提供默认策略(不拆分上下半身) // Use default policy in this C# port m_actionPlayPolicy = new CECPlayerActionPlayDefaultPolicy(m_pPlayer, m_pPlayerModel); } private void ReleaseActionPlayPolicy() { m_actionPlayPolicy = null; } // Build channels (C# no-op, return false to indicate not supported here) // 构建动作通道(C#未实现,返回false) private bool BuildChannelForCastSkillWhenMove() { return false; } public bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart = true, int nTransTime = 200, bool bNoFx = false, CECAttackEvent attackEvent = null, uint dwFlagMode = 0) { return m_actionPlayPolicy != null && m_actionPlayPolicy.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, attackEvent, dwFlagMode); } public bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime = 200, bool bForceStopPrevAct = false, bool bNoFx = false, bool bResetSpeed = false, bool bResetActFlag = false, CECAttackEvent attackEvent = null, uint dwNewFlagMode = 0) { return m_actionPlayPolicy != null && m_actionPlayPolicy.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode); } public bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX = false) { if (m_actionPlayPolicy != null && m_actionPlayPolicy.PlaySkillCastActionWithName(idSkill, szActName, bNoFX)) { m_bSkillAttackActionPlayed = false; return true; } return false; } public bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX = false, CECAttackEvent attackEvent = null, uint dwFlagMode = 0) { bool? pActFlag = null; if (m_actionPlayPolicy != null && m_actionPlayPolicy.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, attackEvent, dwFlagMode)) { m_bSkillAttackActionPlayed = true; return true; } return false; } public bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime = 200, bool bNoFX = false, bool bResetSpeed = false, bool bResetActFlag = false, CECAttackEvent attackEvent = null, uint dwNewFlagMode = 0) { bool? pNewActFlag = null; return m_actionPlayPolicy != null && m_actionPlayPolicy.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode); } public bool PlayWoundActionWithName(string szActName) { return m_actionPlayPolicy != null && m_actionPlayPolicy.PlayWoundActionWithName(szActName); } public void ClearComActFlagAllRankNodes(bool bSignalCurrent) { if (m_actionPlayPolicy != null) { m_actionPlayPolicy.ClearComActFlagAllRankNodes(bSignalCurrent); } } public void StopChannelAction() { if (m_actionPlayPolicy != null) { m_actionPlayPolicy.StopChannelAction(); } } public void StopSkillCastAction() { if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && !m_bSkillAttackActionPlayed) { m_actionPlayPolicy.StopSkillAction(); // LOG kept minimal in C# } } public void StopSkillAttackAction() { if (m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction() && m_bSkillAttackActionPlayed) { m_actionPlayPolicy.StopSkillAction(); // LOG kept minimal in C# } } public bool IsPlayingAction(int iAction) { return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingAction(iAction); } public bool IsPlayingCastingSkillAction() { return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingCastingSkillAction(); } public bool IsPlayingMoveAction() { return m_actionPlayPolicy != null && m_actionPlayPolicy.IsPlayingMoveAction(); } public int GetLowerBodyAction() { return m_actionPlayPolicy != null ? m_actionPlayPolicy.GetLowerBodyAction() : -1; } } }