#pragma once #include #include //#include #include #include #include #include "K3DTypes.h" #include "SkillBase.h" #include "CreatureBase.h" #include "SGameInput.h" // 2010.06.15 - prodongi #include "GameDefine.h" #define Mode_Normal (1 << 0) #define Mode_Attack (1 << 1) #define Mode_Mount (1 << 2) #define Mode_All ((1 << 3) - 1) // 2010.06.15 GameDefine.h로 옮김 - prodongi //#define FORCE_CHIP_SKILL_ID 6008 using namespace GAME_INPUT; struct SStateInfo { SStateInfo() { Reset(); } ~SStateInfo() { vAttackInfoList.clear(); vSkillResult.clear(); } void Reset() { hItemUseTarget = 0; hTarget = 0; hSelf = 0; hItem = 0; bIsMovePos = true; nSkillID = 0; nSkillLv = 0; nRepeat = 0; dwStartTime = dwDuration = 0; bMultiple = false; fRange = 0.f; target_count = 0; fire_count = 0; fSpellRange = 0.f; dwSpeed = 0; SpeedSync = true; UnMountFlag = 0; vSelfPos = K3DVector(0,0,0); vTargetPos = K3DVector(0,0,0); attack_action = 0; attack_flag = 0; count = 0; autoattack = false; chase = false; // 2010.05.24 - prodongi isValidToCorpse = false; /// 2010.10.21 - prodongi isRegionTarget = false; vRegionTargetPos = K3DVector(0, 0, 0); vAttackInfoList.clear(); vSkillResult.clear(); } std::string strItemUseText; AR_HANDLE hItemUseTarget; ///< 보이지 않는 타겟에게 아이템 사용 시 설정 AR_HANDLE hTarget; AR_HANDLE hSelf; AR_HANDLE hItem; K3DVector vSelfPos; K3DVector vTargetPos; bool bIsMovePos; int nSkillID; int nSkillLv; bool bMultiple; ///< true 실시간 연타, 일반 공격일때 이도류 인지 판별 AR_UNIT range; ///< 스킬 효과 범위 unsigned char target_count; ///< 타겟 갯수 unsigned char fire_count; int nRepeat; ///< 갯수 AR_UNIT fRange; ///< 사거리 AR_UNIT fSpellRange; ///< 마거리 DWORD dwStartTime; ///< 시작시간 DWORD dwDuration; ///< 지속 시간 bool SpeedSync; ///< 플레이어와 속도를 맞출지 체크 char UnMountFlag; ///< 언마운트 관련 DWORD dwSpeed; ///< 이속, 공속 std::vector vSkillResult; ///< 스킬 데미지 char attack_action; char attack_flag; char count; std::vector< ATTACK_INFO > vAttackInfoList; bool autoattack; bool chase; std::string target_name; // 2010.05.24 - prodongi bool isValidToCorpse; bool isRegionTarget; /// 2010.10.21 - prodongi K3DVector vRegionTargetPos; }; struct PENDING_INPUT_STATE { SStateInfo sInfostate; int nInputID; PENDING_INPUT_STATE( SStateInfo* infostate, int inputid ) : nInputID( inputid ) { sInfostate.hItemUseTarget = infostate->hItemUseTarget; sInfostate.hSelf = infostate->hSelf; sInfostate.vSelfPos = infostate->vSelfPos; sInfostate.bIsMovePos = infostate->bIsMovePos; sInfostate.vTargetPos = infostate->vTargetPos; sInfostate.hTarget = infostate->hTarget; sInfostate.fRange = infostate->fRange; sInfostate.hItem = infostate->hItem; sInfostate.hTarget = infostate->hTarget; sInfostate.nSkillID = infostate->nSkillID; sInfostate.nSkillLv = infostate->nSkillLv; sInfostate.fRange = infostate->fRange; sInfostate.fSpellRange = infostate->fSpellRange; } }; class SObjectStateMachine; class SObjectState { public: /// 상태 enum ID { STATE_NONE = 0, ///< 없음 (사용되지 않음) STATE_IDLE, ///< 아이들 STATE_ATTACK, ///< 공격 (1회) STATE_MOVE, ///< 이동 STATE_CHASE, ///< 추격 STATE_CAST, ///< 캐스팅 STATE_THROW, ///< 던지기 STATE_FIRE, ///< 시전 STATE_SKILL_END, ///< 시전 종료 STATE_SIT, ///< 앉기 STATE_STAND_UP, ///< 서기 //추가 해야 한다. STATE_TAKEITEM, ///< 아이템 줍기 //추가 해야 한다. STATE_USEITEM, ///< 아이템 사용 STATE_CAST_CANCEL, ///< 캐스팅 취소 STATE_AIMING, ///< 활 조준 STATE_SHOOTING, ///< 활쏘기 STATE_ATTACK_END, ///< 공격 종료 STATE_MOUNT, ///< 올라탄상태 STATE_UNMOUNT, ///< 내리기 }; /// 다른 명령 요청시 허용 여부 enum REQCOMMAND_PERMIT { PERMIT_IMMEDIATELY, ///< 즉시 허용 PERMIT_FORBIDDEN, ///< 불가 PERMIT_PENDING, ///< 대기 }; /// Initialize SObjectState( ID State ) : m_State( State ) , m_bMotionCancelInfo( false ) { } virtual ~SObjectState() { } struct REQCOMMAND_INFO { ID m_ReqCommand; REQCOMMAND_PERMIT m_Permission; REQCOMMAND_INFO( ID ReqCommand, REQCOMMAND_PERMIT Permission ) : m_ReqCommand( ReqCommand ), m_Permission( Permission ) { } }; void AddRequestCommand( ID ReqCommand, REQCOMMAND_PERMIT Permission ) { for( REQCOMINFO_VECTOR::iterator it = m_RequestCommandInfo.begin(); it != m_RequestCommandInfo.end(); it++ ) if( (*it).m_ReqCommand == ReqCommand ) { (*it).m_Permission = Permission; return; } m_RequestCommandInfo.push_back( REQCOMMAND_INFO( ReqCommand, Permission ) ); } /// Methods REQCOMMAND_PERMIT GetRequestPermission( ID ReqCommand ) const { for( REQCOMINFO_VECTOR::const_iterator it = m_RequestCommandInfo.begin(); it != m_RequestCommandInfo.end(); it++ ) if( (*it).m_ReqCommand == ReqCommand ) return (*it).m_Permission; assert( false ); return PERMIT_IMMEDIATELY; } bool GetMotionCancelInfo( ) { return m_bMotionCancelInfo; } void SetMotionCancelInfo( bool bMotionCancel ) { m_bMotionCancelInfo = bMotionCancel; } ID GetID() const { return m_State; } void SetInfo( const SStateInfo &info ) { m_infoState = info; } const SStateInfo &GetInfo() const { return m_infoState; } bool CheckModePermission( unsigned long cur_mode ) { return (GetMode() & cur_mode) ? true : false ; } void SetMode( unsigned long nModeBitVector ) { m_nModeBitVector = nModeBitVector; } unsigned long GetMode() { return m_nModeBitVector; } private: ID m_State; SStateInfo m_infoState; unsigned long m_nModeBitVector; ///< Mode Flag bool m_bMotionCancelInfo; typedef std::vector REQCOMINFO_VECTOR; REQCOMINFO_VECTOR m_RequestCommandInfo; friend SObjectStateMachine; }; class SGameObject; class SGameAvatarEx; class SObjectStateMachine { public: SObjectStateMachine(); virtual ~SObjectStateMachine(); /// 처리 안된 사용자 입력 virtual void PendingInput( struct PENDING_INPUT_STATE* pPendinginputstate ) {} /// 사용자 입력(키보드, 마우스) virtual void OnInput( class SGameInput * pInput ) = 0; /// 사용자 입력 응답(Server) virtual void OnNetInput( struct SGameMessage * pMsg ) = 0; /// Receiver Setting void SetReceiver( SGameAvatarEx *pObject ) { m_pReceiver = pObject; } SGameAvatarEx *GetReceiver() { return m_pReceiver; } /// 상태 체크 SObjectState::REQCOMMAND_PERMIT CheckNextPermission( SObjectState::ID state ); /// 현재 상태 SObjectState::ID GetCurrentState() const { return m_idCurState; } const SStateInfo &GetCurrentStateInfo() const { return m_infoCurrent; } SObjectState::ID GetPrevState() const { return m_idPrevState; } bool CheckMovingState( SObjectState::ID id ) const { return ( id == SObjectState::STATE_CHASE || id == SObjectState::STATE_MOVE ); } /// 특정 행동을 할경우 그 행동이 지금 가능한가를 검사한다 bool IsPossible() { } bool IsMoving() const { return (m_idCurState == SObjectState::STATE_CHASE || m_idCurState == SObjectState::STATE_MOVE); } bool IsCasting() const { return (m_idCurState == SObjectState::STATE_CAST || m_idCurState == SObjectState::STATE_AIMING || m_idCurState == SObjectState::STATE_SHOOTING ); } bool IsAttack() const { return ( m_idCurState == SObjectState::STATE_ATTACK ); } /// 올라타는 중이거나 내려오는 중일때 bool IsMount() const { return (m_idCurState == SObjectState::STATE_MOUNT || m_idCurState == SObjectState::STATE_UNMOUNT); } /// 완전히 올라탄 상태 bool IsMountMode() const { return (m_nMode == MODE_MOUNT); } /// 대기 중인 다음 상태 SObjectState::ID GetPendingState() const { return m_idPendingState; } /// 현재 상태가 시작된 시간 DWORD GetCurrentStateStartTime() const { return m_dwCurrentStateStartTime; } /// 새로운 상태 시작 요청 bool RequestNewState( SObjectState::ID NewState, const SStateInfo &infoState ); /// 현재 상태 중지 ( 대기 중인 다음 상태로 넘어가도록 한다. ) void StopCurrentState(); /// 특정 상태에 다음 상태를 설정해 준다. ( 예> chase인 경우 ) void SetNextState( SObjectState::ID State, const SStateInfo &NextState ); SObjectState::ID GetNextStateID() { return m_idNextState; } const SStateInfo &GetNextStateInfo() { return m_infoNext; } void ClearNextState() { m_idNextState = SObjectState::STATE_NONE; } virtual void Process( DWORD dwTime ); /// 유틸 float GetTargetDist( SGameObject *pTarget ); K3DVector GetChasePos( SGameAvatarEx* pTarget, K3DVector* pTargetPos, float fTargetSize, const SStateInfo &infoState, SObjectState::ID NewState ); //K3DVector GetChasePos( SGameObject *pTarget, K3DVertex vTarget, float fRange ); K3DVector GetChasePos(); bool IsRange( K3DVector & my_pos, float fmy_size, const K3DVector & pos, float ftarget_size, float fRange, bool bCollisionToLine, int & fResultLength ); /// 모드, 또는 Layer 라고도 함. enum { MODE_NORMAL = (1 << 0), ///< 기본 MODE_ATTACK = (1 << 1), ///< 공격 상태 MODE_MOUNT = (1 << 2), ///< 크리쳐 마운트 상태 }; void SetMode( int nMode ) { if( m_idCurState == SObjectState::STATE_MOUNT || m_idCurState == SObjectState::STATE_UNMOUNT ) { if( nMode == MODE_ATTACK || nMode == MODE_NORMAL) { int x = 0; } } m_nMode = nMode; m_dwAttackTime = 0; } int GetMode() { return m_nMode; } void SetAttackLock( bool bAttackLock ); bool IsAttackLock() { return m_bLockAttack; } AR_HANDLE GetTargetHandle() { return m_hTargetHandle; } AR_HANDLE GetAttackTarget() { return m_hAttackTarget; } void SetDefaultPrevState() { m_idPrevState = SObjectState::STATE_IDLE; } SObjectState::ID GetCreatureState() const { return m_idCreatureState; } bool IsCombatState( SObjectState::ID newstate ); void Dead(); void ClearPendingNextState(); void InputFreezing(); void InputThawing(); void ClearInfo(); protected: virtual void SendServerReq( SObjectState::ID state, const SStateInfo &infoState ) = 0; bool ProximityAttack( SObjectState::ID stateId ); bool NotProximityAttack( SObjectState::ID stateId ); bool IsBowAttack(); AR_UNIT GetSize( SGameAvatarEx *pObject ); void ClearAllState(); typedef std::map OBJSTATE_MAP; OBJSTATE_MAP m_StateMap; SGameAvatarEx* m_pReceiver; SObjectState* m_pCurrentState; SObjectState::ID m_idCurState; SStateInfo m_infoCurrent; SObjectState::ID m_idPendingState; SStateInfo m_infoPending; SObjectState::ID m_idDefaultState; SStateInfo m_infoDefault; SObjectState::ID m_idNextState; SStateInfo m_infoNext; SObjectState::ID m_idCreatureState; ///< 크리처 전용( StartNewState 에서 바뀐 상태만 저장한다 ) SObjectState::ID m_idPrevState; ///< 이전 상태를(SKILL EVENT 제외) 저장한다 bool m_bLockAttack; AR_HANDLE m_hTargetHandle; AR_HANDLE m_hAttackTarget; ///< 공격 중인 대상 DWORD m_dwTime; DWORD m_dwCurrentStateStartTime; //전투 대기 중 일때 영향 받는 리스트 알아 두자. int m_nMode; ///< 전투대기 상태 , 공격을 받거나, 내가 공격 시작하면 설정 된다. DWORD m_dwAttackTime; ///< 전투대기 지속 시간, 지속시간은 30초 SObjectState* GetObjState( const SObjectState::ID State ) const; void StartNewState( SObjectState::ID state, const SStateInfo &infoState ); void SetPendingState( SObjectState::ID state, const SStateInfo &infoState ); void ClearPending(); void AddState( SObjectState* pObjState ); void RemoveState( const SObjectState::ID State ); /// 반드시 AddState()가 다 끝난 뒤에 호출해야 한다. void SetDefaultState( const SObjectState::ID State, const SStateInfo &info ); K3DVector GetCreatureChasePos( SGameAvatarEx* pReceiver, SGameAvatarEx* pTarget, K3DVector* pTargetPos, const SStateInfo &infoState, SObjectState::ID NewState ); // 2010.06.15 - prodongi void setAutoAttack(bool autoAttack); enum { NEED_STOP_POS = 0, INSPECTED_STOP_POS, NOT_NEED_STOP_POS, }; int m_nNeedStopPos; ///< 정지할 위치가 필요한가 DWORD m_dwFindDetour; queue< PENDING_INPUT_STATE > m_queInputState; bool m_bAutoAttack; DWORD m_dwAttackDelayTime; bool m_bInputFreezing; };