#include "stdafx.h" #include "SMonsterStateMachine.h" #include "SGameInput.h" #include "SGameMessage.h" #include "SGameAvatarEx.h" #include "SkillBase.h" #include "ErrorCode/ErrorCode.h" #include "SDebug_Util.h" using namespace GAME_INPUT; void SMonsterStateMachine::OnNetInput( struct SGameMessage * pMsg ) { m_idState = SObjectState::ID::STATE_NONE; m_infoState = SStateInfo(); m_infoState.hSelf = m_pReceiver->GetArID(); m_infoState.vSelfPos = *m_pReceiver->GetPosition(); m_infoState.fRange = m_pReceiver->GetAttackRange(); switch( pMsg->nType ) { case MSG_ATTACK : { SMSG_ATTACK * pAttack = static_cast(pMsg); m_infoState.hSelf = pAttack->attacker_handle; m_infoState.hTarget = pAttack->target_handle; m_infoState.vTargetPos = pAttack->pos_target; //이동 할 위치 m_infoState.dwSpeed = pAttack->attack_speed; // ms m_infoState.attack_action = pAttack->attack_action; m_infoState.attack_flag = pAttack->attack_flag; if( pAttack->attack_action == TS_ATTACK_EVENT::ATTACK_END ) m_idState = SObjectState::STATE_IDLE; else m_idState = SObjectState::STATE_ATTACK; for ( int i=0 ; i < pAttack->count ; ++i ) { m_infoState.vAttackInfoList.push_back( pAttack->m_vAttackInfoList[i] ); } } break; case MSG_MOVE : { SMSG_MOVE * pMove = static_cast(pMsg); m_infoState.bIsMovePos = true; m_infoState.vTargetPos = pMove->pos_target; //이동 할 위치 m_infoState.dwSpeed = pMove->speed; m_idState = SObjectState::STATE_MOVE; if ( m_idNextState != SObjectState::STATE_NONE ) { m_infoState = m_infoNext; m_infoState.dwSpeed = pMove->speed; //추적 Speed 는 그대로 사용 m_idState = SObjectState::STATE_CHASE; } } break; case MSG_SKILL_EVENT : { SMSG_SKILL_EVENT * pSkillEvent = static_cast(pMsg); switch( pSkillEvent->status_type ) { case TS_SC_SKILL::FIRE: { m_idState = SObjectState::STATE_FIRE; m_infoState.dwDuration = 1500; //발사 후 지속 시간 m_infoState.nRepeat = pSkillEvent->fire.count; // 갯수 m_infoState.bMultiple = pSkillEvent->fire.bMultiple; // true 실시간 연타 m_infoState.range = pSkillEvent->fire.range; // 스킬 효과 범위 m_infoState.target_count = pSkillEvent->fire.target_count;// 타겟 수 m_infoState.fire_count = pSkillEvent->fire.fire_count; //m_infoState.target_name = pSkillEvent->target_name; // Fraun performance tweak m_hTargetHandle = pSkillEvent->target; //기존 데이타 삭제 한다. if( !m_infoState.vSkillResult.empty() ) m_infoState.vSkillResult.erase( m_infoState.vSkillResult.begin(), m_infoState.vSkillResult.end() ); for ( int i=0 ; i< (int)pSkillEvent->vSkillResult.size() ; ++i ) { SkillResult skillresult; skillresult = pSkillEvent->vSkillResult[i]; m_infoState.vSkillResult.push_back( skillresult ); if( skillresult.GetType() == SkillResult::RUSH ) { if( skillresult.rush.bResult ) { m_idNextState = SObjectState::STATE_ATTACK; m_infoState.hTarget = skillresult.rush.hTarget; m_infoState.vTargetPos = K3DVector( skillresult.rush.x, skillresult.rush.y, 0.0f ); } } } } OutputDebugString("SMonsterStateMachine::OnNetInput - fire\n"); break; case TS_SC_SKILL::CASTING: { if ( pSkillEvent->cast.nErrorCode == 0 ) { m_idState = SObjectState::STATE_CAST; m_infoState.dwSpeed = pSkillEvent->cast.tm; } else { m_idState = SObjectState::STATE_SKILL_END; return; } OutputDebugString("SMonsterStateMachine::OnNetInput - casting\n"); } break; case TS_SC_SKILL::CANCEL: { m_idState = SObjectState::STATE_CAST_CANCEL; return; } case TS_SC_SKILL::CASTING_UPDATE: { } break; case TS_SC_SKILL::REGION_FIRE: { } break; case TS_SC_SKILL::COMPLETE: { m_idState = SObjectState::STATE_SKILL_END; OutputDebugString("SMonsterStateMachine::OnNetInput - complete\n"); } break; } m_infoState.nSkillID = pSkillEvent->skill_id; m_infoState.nSkillLv = pSkillEvent->skill_level; m_infoState.hTarget = pSkillEvent->target; } break; case MSG_RESULT: { SMSG_RESULT* pResult = static_cast(pMsg); if( pResult->request_msg_id == TM_CS_SKILL ) { if( pResult->result != RESULT_SUCCESS) m_idState = SObjectState::STATE_SKILL_END; } else if( pResult->request_msg_id == TM_CS_USE_ITEM ) { if( pResult->result != RESULT_SUCCESS ) { if( m_pReceiver->IsUsingSkill() || m_pReceiver->IsAttack() ) return; m_idState = SObjectState::STATE_SKILL_END; } } return; } break; default: return; } } //============================================================================================================================ SLocalMonsterStateMachine::SLocalMonsterStateMachine() { AddState( CreateIdleState() ); AddState( CreateAttackState() ); AddState( CreateMoveState() ); AddState( CreateChaseState() ); AddState( CreateCastState() ); AddState( CreateCastCancelState() ); AddState( CreateFireState() ); AddState( CreateSkillEndState() ); // AddState()가 다 끝난 뒤에 호출할 것 SStateInfo info; SetDefaultState( SObjectState::STATE_IDLE, info ); } SObjectState* SLocalMonsterStateMachine::CreateIdleState() { SObjectState* pState = new SObjectState( SObjectState::STATE_IDLE ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_ATTACK, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_FORBIDDEN ); return pState; } SObjectState* SLocalMonsterStateMachine::CreateAttackState() { SObjectState* pState = new SObjectState( SObjectState::STATE_ATTACK ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_ATTACK, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_FORBIDDEN ); return pState; } SObjectState* SLocalMonsterStateMachine::CreateMoveState() { SObjectState* pState = new SObjectState( SObjectState::STATE_MOVE ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_ATTACK, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_FORBIDDEN ); return pState; } SObjectState* SLocalMonsterStateMachine::CreateChaseState() { SObjectState* pState = new SObjectState( SObjectState::STATE_CHASE ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_ATTACK, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_FORBIDDEN ); return pState; } SObjectState* SLocalMonsterStateMachine::CreateCastState() { SObjectState* pState = new SObjectState( SObjectState::STATE_CAST ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_ATTACK, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_CAST_CANCEL, SObjectState::PERMIT_IMMEDIATELY ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_FORBIDDEN ); return pState; } SObjectState* SLocalMonsterStateMachine::CreateFireState() { SObjectState* pState = new SObjectState( SObjectState::STATE_FIRE ); pState->SetMotionCancelInfo( true ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_ATTACK, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_CAST_CANCEL, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_IMMEDIATELY ); return pState; } SObjectState* SLocalMonsterStateMachine::CreateSkillEndState() { SObjectState* pState = new SObjectState( SObjectState::STATE_SKILL_END ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_ATTACK_END, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_CAST_CANCEL, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_PENDING ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_FORBIDDEN ); return pState; } SObjectState* SLocalMonsterStateMachine::CreateCastCancelState() { SObjectState* pState = new SObjectState( SObjectState::STATE_CAST_CANCEL ); pState->AddRequestCommand( SObjectState::STATE_IDLE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_ATTACK, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_MOVE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_CHASE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_CAST, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_CAST_CANCEL, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_FIRE, SObjectState::PERMIT_FORBIDDEN ); pState->AddRequestCommand( SObjectState::STATE_SKILL_END, SObjectState::PERMIT_FORBIDDEN ); return pState; } void SLocalMonsterStateMachine::SendServerReq( SObjectState::ID state, const SStateInfo &infoState ) { switch( state ) { case SObjectState::STATE_NONE: // 없음 (사용되지 않음) case SObjectState::STATE_IDLE:// 아이들 StartNewState( state, infoState ); break; case SObjectState::STATE_ATTACK: // 공격 (1회) _oprint( "Creature attack: %u\n", infoState.hTarget ); m_pReceiver->ReqAttack( infoState.hTarget ); break; case SObjectState::STATE_MOVE: // 이동 case SObjectState::STATE_CHASE: // 추격 m_pReceiver->ReqMove( infoState.hSelf, ArPosition( infoState.vTargetPos.x, infoState.vTargetPos.y ) ); break; } } //사용자 입력(키보드, 마우스) void SLocalMonsterStateMachine::OnInput( class SGameInput * pInput ) { SObjectState::ID idState; SStateInfo infoState; infoState.hSelf = m_pReceiver->GetArID(); infoState.vSelfPos = *m_pReceiver->GetPosition(); m_idNextState = SObjectState::STATE_NONE; switch( pInput->GetInputID() ) { case RQ_MOVE: { SInputMove* pMove = static_cast(pInput); idState = SObjectState::STATE_MOVE; infoState.bIsMovePos = true; infoState.vTargetPos = pMove->GetTargetPos(); break; } case RQ_ATTACK : { SInputAttack* pAttack = static_cast (pInput); idState = SObjectState::STATE_ATTACK; infoState.hTarget = pAttack->GetTargetHandle(); infoState.fRange = m_pReceiver->GetAttackRange(); break; } case RQ_CAST : { SInputSkill* pCast = static_cast (pInput); idState = SObjectState::STATE_CAST; infoState.hTarget = pCast->GetTargetHandle(); infoState.nSkillID = pCast->GetSkillID(); infoState.nSkillLv = pCast->GetSkillLv(); infoState.fRange = pCast->GetCastRange(); infoState.fSpellRange = pCast->GetSpellRange(); break; } } //타겟이 있는가? if ( infoState.hTarget != 0 ) { SGameObject *pTarget = NULL; pTarget = m_pReceiver->GetGameObject( infoState.hTarget ); if ( pTarget == NULL ) return; //오브젝트가 없으면, 입력은 무효다 infoState.bIsMovePos = false; infoState.vTargetPos = *pTarget->GetPosition(); } //새로운 상태 요청 RequestNewState( idState, infoState ); } //사용자 입력 응답(Server) void SLocalMonsterStateMachine::OnNetInput( struct SGameMessage * pMsg ) { SMonsterStateMachine::OnNetInput( pMsg ); if( m_idState == SObjectState::ID::STATE_NONE ) return; if ( m_infoState.hTarget != 0 ) { SGameObject *pTarget = m_pReceiver->GetGameObject( m_infoState.hTarget ); if ( pTarget == NULL ) return; m_infoState.bIsMovePos = false; m_infoState.vTargetPos = *pTarget->GetPosition(); } StartNewState( m_idState, m_infoState ); } //============================================================================================================================ void SOtherMonsterStateMachine::OnNetInput( struct SGameMessage * pMsg ) { SMonsterStateMachine::OnNetInput( pMsg ); m_pReceiver->OnChangeState( m_idState, m_infoState ); }