#ifndef __SYSTATEBASE_H__ #define __SYSTATEBASE_H__ #include "StateBase.h" struct SYPoint3 { float x; float y; float z; inline SYPoint3 operator=(const NiPoint3& niPoint) { x = niPoint.x; y = niPoint.y; z = niPoint.z; return *this; } inline NiPoint3 GetNiPoint3() const { return NiPoint3(x,y,z); } }; enum ESYActionID { ACTION_IDLE = 0, ACTION_ATTACK = 1, ACTION_NORMAL_ATTACK = ACTION_ATTACK, ACTION_SKILL_ATTACK = 3, ACTION_MOVE = 4, ACTION_KEYBOARDMOVE = 5, ACTION_PICKITEM = 6, ACTION_TRADE = 7, // }; // 我的想法是: Action --> State --> Sync Client State By State Param. // 因此将各动作/状态所对应的参数分别定义为一系列结构, 在服务器端支持的情况下 // 我们只需要通过这些结构来保证C-S之间的同步. struct AttackParam { SYObjID TargetID; // 目标对象ID, 对于范围型技能, 此处为-1. SYPoint3 TargetPos; // 目标区域中心位置(如果为射线,则为起点位置) float Radius; // 半径 DWORD SkillID; // 技能 -1 : 普通攻击 DWORD SerialKey; BYTE TargetIsObject; // 目标是否为单体对象,否则为范围中心 }; struct SpellParam { int spellid; //SpellCastTargets target; uint32 m_targetMask; uint64 m_unitTarget; uint64 m_itemTarget; float m_srcX, m_srcY, m_srcZ; float m_destX, m_destY, m_destZ; }; struct MOVEParam { SYPoint3 vecSrcPos; SYPoint3 vecDestPos; UINT uState; }; struct IDELParam { SYPoint3 vecPos; }; struct PickParam { SYObjID TargetID; // 物品ID,用于删除 }; struct SYStateAction : public StateAction { union { IDELParam IDEL; MOVEParam MOVE; AttackParam ATTACK; SpellParam SPELL; PickParam PICKITEM; struct TradeParam { SYObjID TargetID; SYPoint3 TargetPos; }TRADE; }; }; typedef std::queue SYActionQueue; /* 关于本地玩家和动作队列: 本地玩家的输入事件也可以当作动作压入动作队列, 比如当前本地玩家正在进行攻击状态, 我们可以根据玩家的移动行为 压入一个移动的动作, 在攻击状态更新过程中, 会进行检测, 在这个情况下, 本地玩家会判断条件并终止攻击操作开始进 行移动. 如果在攻击停止之前,玩家输入2个事件 移动 交易 那么这2个动作的处理都必须等待攻击处理完成之后依次处理. 而实际上, 我们不希望这种事情发生, 而是直接进入交易. 也就是说玩家的很多输入事件都是暂时性的, 而不是像格斗游戏那样严格捕捉玩家的任何输入. 所以对于玩家输入事件我们在INPUTMANAGER 中处理, 而不压入队列. */ class SYStateActorBase : public IStateActor { public: SYStateActorBase(void); virtual ~SYStateActorBase(void); void InitState(); void ResetState(); // 实现 //virtual State GetCurState() { return m_CurState; } //virtual void SetCurState(State s) { m_CurState = s; } //virtual State GetNextState() { return m_NextState; } //virtual IStateProxy* GetCurStateProxy() { return NULL; } virtual BOOL SetNextState(State eNextState, DWORD dwTime); virtual IStateProxy* ForceStateChange(State eNextState, DWORD dwTime); State GetCurPostureState() const; State GetCurActionState() const; State GetNextPosetureState() const; State GetNextActionState() const; void SetNextPosetureState(State eState); void SetNextActionState(State eState); virtual IStateProxy* GetStateInstance(State eState) = 0; // 清空动作队列 virtual void ClearActionQueue(); virtual BOOL ProcessAction(const StateAction* Action); virtual void PushAction(const StateAction* QueueAction); virtual BOOL ProcessNextAction(); virtual INT GetNumQueueAction(); void UpdateState(float fTime, float fDelta, StateLayer eLayer); void UpdateState(float fTime, float fDelta); bool IsLayerBlocked(StateLayer eLayer) { NIASSERT(eLayer >= SL_Poseture && eLayer < SL_Max); return m_bBlocked[eLayer]; } void SetLayerBlock(StateLayer eLayer, bool block=true) { NIASSERT(eLayer >= SL_Poseture && eLayer < SL_Max); m_bBlocked[eLayer] = block; } // 可以用这个来保存当前状态的参数. 分析并尝试中... 目前不要依赖! void SetCurAction(const StateAction* QueueAction); const SYStateAction* GetCurAction() const { return &m_CurAction;} private: BOOL CommitStateChange(DWORD dwTime, StateLayer eLayer); protected: SYStateAction m_CurAction; SYActionQueue m_ActionQueue; State m_eCurAtionState; State m_eNextActionState; State m_eCurPostureState; State m_eNextPosetureState; bool m_bBlocked[SL_Max]; }; inline State SYStateActorBase::GetCurPostureState() const { return m_eCurPostureState; } inline State SYStateActorBase::GetCurActionState() const { return m_eCurAtionState; } inline State SYStateActorBase::GetNextPosetureState() const { return m_eNextPosetureState; } inline State SYStateActorBase::GetNextActionState() const { return m_eNextActionState; } inline void SYStateActorBase::SetNextPosetureState(State eState) { StateLayer eLayer = GetStateInstance(eState)->GetLayer(); NIASSERT(eLayer == SL_Poseture); m_eNextPosetureState = eState; } inline void SYStateActorBase::SetNextActionState(State eState) { StateLayer eLayer = GetStateInstance(eState)->GetLayer(); NIASSERT(eLayer == SL_Action); m_eNextActionState = eState; } #endif