464 lines
13 KiB
C++
464 lines
13 KiB
C++
#pragma once
|
|
|
|
#include <windows.h>
|
|
#include <assert.h>
|
|
//#include <vector>
|
|
#include <map>
|
|
#include <queue>
|
|
#include <mmo/ArType.h>
|
|
#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<SkillResult> 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<REQCOMMAND_INFO> 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<SObjectState::ID, SObjectState*> 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;
|
|
};
|