466 lines
18 KiB
C#
466 lines
18 KiB
C#
using System;
|
|
|
|
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 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 CECPlayerActionPlayPolicy(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, bool[] pActFlag = null, uint dwFlagMode = 0)
|
|
{
|
|
return m_actionPlayPolicy != null
|
|
&& m_actionPlayPolicy.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, pActFlag, dwFlagMode);
|
|
}
|
|
|
|
public bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime = 200, bool bForceStopPrevAct = false, bool bNoFx = false, bool bResetSpeed = false, bool bResetActFlag = false, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
|
|
{
|
|
return m_actionPlayPolicy != null
|
|
&& m_actionPlayPolicy.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, pNewActFlag, 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, bool[] pActFlag = null, uint dwFlagMode = 0)
|
|
{
|
|
if (m_actionPlayPolicy != null
|
|
&& m_actionPlayPolicy.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, pActFlag, 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, bool[] pNewActFlag = null, uint dwNewFlagMode = 0)
|
|
{
|
|
return m_actionPlayPolicy != null
|
|
&& m_actionPlayPolicy.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, pNewActFlag, 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;
|
|
}
|
|
}*/
|
|
public class CECPlayerActionPlayPolicy
|
|
{
|
|
protected readonly CECPlayer m_pPlayer;
|
|
protected readonly CECModel m_pPlayerModel;
|
|
|
|
// 简单状态记录以支持“是否在施法中”的判断
|
|
// Simple state to support IsPlayingCastingSkillAction
|
|
private bool m_isCastingSkill;
|
|
|
|
public CECPlayerActionPlayPolicy(CECPlayer pPlayer, CECModel pPlayerModel)
|
|
{
|
|
m_pPlayer = pPlayer;
|
|
m_pPlayerModel = pPlayerModel;
|
|
m_isCastingSkill = false;
|
|
}
|
|
|
|
public virtual bool CanCombineWithMoveForSkill(int idSkill)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public CECPlayer GetPlayer()
|
|
{
|
|
return m_pPlayer;
|
|
}
|
|
|
|
public CECModel GetModel()
|
|
{
|
|
return m_pPlayerModel;
|
|
}
|
|
|
|
public bool IsMoving()
|
|
{
|
|
return IsPlayingMoveAction() && (m_pPlayer != null && m_pPlayer.IsWorkMoveRunning());
|
|
}
|
|
|
|
public static bool IsMoveAction(int action)
|
|
{
|
|
return action == (int)PLAYER_ACTION_TYPE.ACT_RUN
|
|
|| action == (int)PLAYER_ACTION_TYPE.ACT_WALK
|
|
|| action == (int)PLAYER_ACTION_TYPE.ACT_FLY
|
|
|| action == (int)PLAYER_ACTION_TYPE.ACT_FLY_SWORD
|
|
|| action == (int)PLAYER_ACTION_TYPE.ACT_SWIM
|
|
|| action == (int)PLAYER_ACTION_TYPE.ACT_SWIM_FOR_MOVESKILL;
|
|
}
|
|
|
|
public bool IsPlayingCastingSkillAction()
|
|
{
|
|
return m_isCastingSkill;
|
|
}
|
|
|
|
// Non-skill action
|
|
public virtual bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart, int nTransTime, bool bNoFx, CECAttackEvent attackEvent, uint dwFlagMode)
|
|
{
|
|
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
|
|
{
|
|
return false;
|
|
}
|
|
int iTransTime = 0;
|
|
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName,iTransTime));
|
|
return true;
|
|
}
|
|
|
|
public virtual bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime, bool bForceStopPrevAct, bool bNoFx, bool bResetSpeed, bool bResetActFlag, CECAttackEvent attackEvent = null, uint dwNewFlagMode = 0)
|
|
{
|
|
// 当前实现:直接播放(队列行为由上层系统处理)
|
|
// Current: just play, queue behavior handled by upper systems
|
|
return PlayNonSkillActionWithName(iAction, szActName, false, nTransTime, bNoFx, attackEvent, dwNewFlagMode);
|
|
}
|
|
|
|
// Skill actions
|
|
public virtual bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX)
|
|
{
|
|
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
|
|
{
|
|
return false;
|
|
}
|
|
if (IsMoving())
|
|
{
|
|
return false;
|
|
}
|
|
m_isCastingSkill = true;
|
|
int iTransTime = 200;
|
|
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName,iTransTime));
|
|
return true;
|
|
}
|
|
|
|
public virtual bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX, CECAttackEvent attackEvent, uint dwFlagMode)
|
|
{
|
|
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
|
|
{
|
|
return false;
|
|
}
|
|
if (IsMoving())
|
|
{
|
|
return false;
|
|
}
|
|
m_isCastingSkill = true;
|
|
int iTransTime = 200;
|
|
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName,iTransTime));
|
|
return true;
|
|
}
|
|
|
|
public virtual bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime, bool bNoFX, bool bResetSpeed, bool bResetActFlag, CECAttackEvent attackEvent, uint dwNewFlagMode)
|
|
{
|
|
return PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, attackEvent, dwNewFlagMode);
|
|
}
|
|
|
|
public virtual bool PlayWoundActionWithName(string szActName)
|
|
{
|
|
if (m_pPlayer == null || string.IsNullOrEmpty(szActName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int iTransTime = 0;
|
|
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new PlayActionEvent(szActName,iTransTime));
|
|
return true;
|
|
}
|
|
|
|
public virtual void ClearComActFlagAllRankNodes(bool bSignalCurrent)
|
|
{
|
|
if (m_pPlayer != null)
|
|
{
|
|
EventBus.PublishChannel(m_pPlayer.GetPlayerInfo().cid, new ClearComActFlagAllRankNodesEvent(bSignalCurrent));
|
|
}
|
|
}
|
|
|
|
public virtual void StopChannelAction()
|
|
{
|
|
// 在C#端没有底层通道概念,做成清旗标即可
|
|
// No channel concept here; clear act flags as a substitute
|
|
ClearComActFlagAllRankNodes(true);
|
|
}
|
|
|
|
public virtual void StopSkillAction()
|
|
{
|
|
m_isCastingSkill = false;
|
|
StopChannelAction();
|
|
}
|
|
|
|
public virtual bool IsPlayingAction(int iAction)
|
|
{
|
|
// C#动画系统由上层驱动,这里不跟踪具体动作,统一返回false
|
|
// Not tracked here; return false by default
|
|
return false;
|
|
}
|
|
|
|
public virtual bool IsPlayingMoveAction()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public virtual int GetLowerBodyAction()
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
class CECPlayerActionPlayDefaultPolicy : CECPlayerActionPlayPolicy{
|
|
public CECPlayerActionPlayDefaultPolicy(CECPlayer pPlayer, CECModel pPlayerModel): base(pPlayer, pPlayerModel){}
|
|
|
|
public override bool PlayNonSkillActionWithName(int iAction, string szActName, bool bRestart, int nTransTime, bool bNoFx, CECAttackEvent attackEvent, uint dwFlagMode)
|
|
{
|
|
ClearComActFlagAllRankNodes(true);
|
|
bool check = GetModel()!=null
|
|
&& GetModel().PlayActionByName(szActName, 1.0f, bRestart, nTransTime, true, (uint)iAction , bNoFx, attackEvent, dwFlagMode);
|
|
if (!check)
|
|
{
|
|
// BMLogger.LogError($"Fall back to base implementation: {szActName} failed");
|
|
//fallback to base implementation(which is non policy based)
|
|
base.PlayNonSkillActionWithName(iAction, szActName, bRestart, nTransTime, bNoFx, attackEvent, dwFlagMode);
|
|
}
|
|
return check;
|
|
}
|
|
public override bool QueueNonSkillActionWithName(int iAction, string szActName, int nTransTime, bool bForceStopPrevAct, bool bNoFx, bool bResetSpeed, bool bResetActFlag, CECAttackEvent attackEvent = null, uint dwNewFlagMode = 0)
|
|
{
|
|
bool check = GetModel()!=null
|
|
&& GetModel().QueueAction(szActName, nTransTime, (uint)iAction, bForceStopPrevAct, false, bNoFx, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode);
|
|
if (!check)
|
|
{
|
|
// BMLogger.LogError($"Fall back to base implementation: {szActName} failed");
|
|
//fallback to base implementation(which is non policy based)
|
|
base.QueueNonSkillActionWithName(iAction, szActName, nTransTime, bForceStopPrevAct, bNoFx, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode);
|
|
}
|
|
return check;
|
|
}
|
|
public override bool PlaySkillCastActionWithName(int idSkill, string szActName, bool bNoFX){
|
|
if (IsMoving()){
|
|
return false;
|
|
}
|
|
ClearComActFlagAllRankNodes(true);
|
|
bool check = GetModel()!=null
|
|
&& GetModel().PlayActionByName(szActName, 1.0f, true, 200, true);
|
|
if (!check)
|
|
{
|
|
// BMLogger.LogError($"Fall back to base implementation: {szActName} failed");
|
|
//fallback to base implementation(which is non policy based)
|
|
base.PlaySkillCastActionWithName(idSkill, szActName, bNoFX);
|
|
}
|
|
return check;
|
|
}
|
|
public override bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX, CECAttackEvent attackEvent, uint dwFlagMode){
|
|
if (IsMoving()){
|
|
return false;
|
|
}
|
|
//LOG_DEBUG_INFO(AString().Format("PlaySkillAttackActionWithName:%s", szActName));
|
|
ClearComActFlagAllRankNodes(true);
|
|
bool check = GetModel() != null
|
|
&& GetModel().PlayActionByName(szActName, 1.0f, true, 200, true, (uint)PLAYER_ACTION_TYPE.ACT_CASTSKILL, bNoFX, attackEvent, dwFlagMode);
|
|
if (!check)
|
|
{
|
|
//BMLogger.LogError($"Fall back to base implementation: {szActName} failed");
|
|
//fallback to base implementation(which is non policy based)
|
|
base.PlaySkillAttackActionWithName(idSkill, szActName, bNoFX, attackEvent, dwFlagMode);
|
|
}
|
|
return check;
|
|
}
|
|
|
|
public override bool QueueSkillAttackActionWithName(int idSkill, string szActName, int nTransTime, bool bNoFX, bool bResetSpeed, bool bResetActFlag, CECAttackEvent attackEvent, uint dwNewFlagMode){
|
|
//LOG_DEBUG_INFO(AString().Format("QueueSkillAttackActionWithName:%s", szActName));
|
|
bool check = GetModel()!=null
|
|
&& GetModel().QueueAction(szActName, nTransTime, (int)PLAYER_ACTION_TYPE.ACT_CASTSKILL, false, false, bNoFX, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode);
|
|
if (!check)
|
|
{
|
|
//BMLogger.LogError($"Fall back to base implementation: {szActName} failed");
|
|
//fallback to base implementation(which is non policy based)
|
|
base.QueueSkillAttackActionWithName(idSkill, szActName, nTransTime, bNoFX, bResetSpeed, bResetActFlag, attackEvent, dwNewFlagMode);
|
|
}
|
|
return check;
|
|
}
|
|
public override bool PlayWoundActionWithName(string szActName){
|
|
// TOdo; add channel support for animation
|
|
// return GetModel()
|
|
// && GetModel().PlayActionByName(szActName, (int)ActionChannel.ACTCHA_WOUND, 1, 0, false);
|
|
return true;
|
|
// //LOG_DEBUG_INFO(AString().Format("PlayWoundActionWithName:%s", szActName));
|
|
}
|
|
public override void ClearComActFlagAllRankNodes(bool bSignalCurrent){
|
|
if (GetModel()!=null){
|
|
GetModel().ClearComActFlagAllRankNodes(bSignalCurrent);
|
|
}
|
|
}
|
|
public override void StopChannelAction(){
|
|
if (GetModel()!=null){
|
|
ClearComActFlagAllRankNodes(true);
|
|
GetModel().StopChannelAction(0, true);
|
|
}
|
|
}
|
|
public override void StopSkillAction(){
|
|
if (GetModel()!=null && IsPlayingCastingSkillAction()){
|
|
StopChannelAction();
|
|
}
|
|
}
|
|
public override bool IsPlayingAction(int iAction){
|
|
if (GetModel()!=null){
|
|
return (int)GetModel().GetCurActionUserData() == iAction;
|
|
}
|
|
return false;
|
|
}
|
|
public override bool IsPlayingMoveAction(){
|
|
if (GetModel()!=null){
|
|
var userData = GetModel().GetCurActionUserData();
|
|
return IsMoveAction((int)userData);
|
|
}
|
|
return false;
|
|
}
|
|
public override int GetLowerBodyAction(){
|
|
if (GetModel()!=null){
|
|
return GetModel().GetCurActionUserData();
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
}
|