Files
test/Assets/PerfectWorld/Scripts/Players/CECPlayerActionPlayPolicy.cs
T
Tran Hai Nam ef5689055e Add requirement for play skill
Merge from develop
2026-05-27 12:16:38 +07:00

450 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 IsPlayingAction((int)PLAYER_ACTION_TYPE.ACT_CASTSKILL);
}
// 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;
}
BMLogger.Log("[DefaultPolicy] PlaySkillCastActionWithName:" + szActName);
ClearComActFlagAllRankNodes(true);
bool check = GetModel()!=null
&& GetModel().PlayActionByName(szActName, 1.0f, true, 200, true, (uint)PLAYER_ACTION_TYPE.ACT_CASTSKILL, bNoFX);
return check;
}
public override bool PlaySkillAttackActionWithName(int idSkill, string szActName, bool bNoFX, CECAttackEvent attackEvent, uint dwFlagMode){
if (IsMoving()){
return false;
}
BMLogger.Log("[DefaultPolicy] Checking PlaySkillAttackActionWithName:" + szActName);
ClearComActFlagAllRankNodes(true);
bool check = GetModel() != null
&& GetModel().PlayActionByName(szActName, 1.0f, true, 200, true, (uint)PLAYER_ACTION_TYPE.ACT_CASTSKILL, 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){
bool check = GetModel()!=null
&& GetModel().QueueAction(szActName, nTransTime, (int)PLAYER_ACTION_TYPE.ACT_CASTSKILL, false, false, 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){
BMLogger.Log("[DefaultPolicy]StopChannelAction: " + GetModel().GetCurActionUserData());
ClearComActFlagAllRankNodes(true);
GetModel().StopChannelAction(0, true);
}
}
public override void StopSkillAction(){
if (GetModel()!=null && IsPlayingCastingSkillAction()){
BMLogger.Log("[DefaultPolicy]StopSkillAction: " + GetModel().GetCurActionUserData());
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;
}
}
}