Files
Sun1602/Server/GameServer/Npcai/RunAwayState.cpp
T
2022-10-26 12:25:11 +08:00

181 lines
5.1 KiB
C++

#include "stdafx.h"
#include "RunAwayState.h"
#include <Timer.h>
#include <SinTable.h>
#include <AIParamParser.h>
#include <PacketControl/WarMessages_Sync.h>
#include "GameField.h"
#include "Player.h"
RunAwayState::RunAwayState()
{
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
m_dwTargetKey = 0;
m_abilityID = eABILITY_INVALID;
#endif // _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
}
RunAwayState::~RunAwayState()
{
}
void
RunAwayState::Init()
{
__noop;
}
void
RunAwayState::OnEnter(LPARAM param1, LPARAM param2, LPARAM param3)
{
State::OnEnter(param1, param2, param3);
m_vTargetPos = *m_pNPC->GetPosPtr();
m_bTouchedSomething = false;
// 도망가야할 적을 찾아서 타겟과 위치를 셋팅한다.
DWORD target_key = static_cast<DWORD>(param1);
Player* pTarget = PlayerManager::Instance()->FindPlayerByObjKey(target_key);
if (pTarget)
{
m_pNPC->SetTargetChar(pTarget);
m_vTargetPos = *pTarget->GetPosPtr();
}
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
DWORD delay = m_pAITypeInfo->m_wRUNAWAY_TIME;
const AI_MSG_RUNAWAY* pRecvMsg = reinterpret_cast<const AI_MSG_RUNAWAY*>(param2);
if (param1 != NULL && pRecvMsg != NULL)
{
delay = pRecvMsg->dwRunAwayTime;
m_abilityID = pRecvMsg->abilityID;
}
m_dwTargetKey = target_key;
#else // _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
// 도망가야할 시간을 셋팅한다.
DWORD delay = param1 ? static_cast<DWORD>(param2) : m_pAITypeInfo->m_wRUNAWAY_TIME;
#endif // _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
m_RunAwayTimer.SetTimer(delay);
//__NA_S00015_20080828_NEW_HOPE_SHADOW
m_wStateID = static_cast<WORD>(param3); // TODO : need check boundary
}
void
RunAwayState::OnExit()
{
State::OnExit();
}
BOOL
RunAwayState::OnUpdate(DWORD dwDeltaTick)
{
__UNUSED(dwDeltaTick);
if (!m_pNPC->IsMoving())
{
RunAway();
}
if (m_RunAwayTimer.IsExpired())
{
if (m_pNPC->GetTargetChar())
{
m_pNPC->ChangeState(STATE_ID_HELP);
}
else
{
m_pNPC->SetTargetChar(NULL);
m_pNPC->ChangeState(STATE_ID_IDLE);
}
}
return true;
}
void
RunAwayState::RunAway()
{
// 이동할 거리를 구한다.
float MOVE_DISTANCE = (float)dRandom(AIParamParser::AICommonInfo.m_fMIN_MOVE_DISTANCE,
AIParamParser::AICommonInfo.m_fMAX_MOVE_DISTANCE);
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
if (m_abilityID == eABILITY_CHARMED) // 매혹
{
Player* pTarget = PlayerManager::Instance()->FindPlayerByObjKey(m_dwTargetKey); // 타겟 위치 갱신
if (pTarget)
{
m_pNPC->SetTargetChar(pTarget);
m_vTargetPos = *pTarget->GetPosPtr();
}
MOVE_DISTANCE = 1; // 1을 이동할때마다 타겟의 위치를 갱신하도록 한다
MOVE_DISTANCE *= -1; // 방향 설정
}
#endif // _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
const WzVector& wvCurPos = *m_pNPC->GetPosPtr();
GameField* pField = m_pNPC->GetField();
if (pField == NULL)
return;
WzVector wvMovement;
// 이전 길찾기에서 무언가에 닿은 경우 60도 회전시키고, 그렇지 않다면 랜덤한 방향으로 포인팅
if (m_bTouchedSomething)
{
m_bTouchedSomething = false;
wvMovement = m_wvRotatedVector;
}
else
{
VectorNormalize(&wvMovement, &(wvCurPos - m_vTargetPos));
wvMovement.x *= MOVE_DISTANCE;
wvMovement.y *= MOVE_DISTANCE;
}
wvMovement.z = 2.f;
WzVector& wvDestPos = wvCurPos + wvMovement;
if (!pField->FindPath(m_pNPC, &wvDestPos, (eCHAR_STATE_TYPE)m_wStateID))
{
// 장애물에 닿았다는 표시를 하고 지금 가려는 방향에서 60도 회전시킨 벡터를 구해둔다.
m_bTouchedSomething = true;
const WzVector& wvDistanceWantToMove = wvDestPos - wvCurPos;
m_wvRotatedVector.x = wvDistanceWantToMove.x *
g_SinTable.FCOS(AIParamParser::AICommonInfo.m_wSEARCH_ROTATE_ANGLE) +
wvDistanceWantToMove.y *
g_SinTable.FSIN(AIParamParser::AICommonInfo.m_wSEARCH_ROTATE_ANGLE);
m_wvRotatedVector.y = -wvDistanceWantToMove.x *
g_SinTable.FSIN(AIParamParser::AICommonInfo.m_wSEARCH_ROTATE_ANGLE) +
wvDistanceWantToMove.y *
g_SinTable.FCOS(AIParamParser::AICommonInfo.m_wSEARCH_ROTATE_ANGLE);
m_wvRotatedVector.z = 0.0f;
return;
}
m_pNPC->SetMoveState(CMS_RUN);
{
MSGSUB_SYNC_MOVE_THRUST_BRD msg;
msg.m_dwObjectKey = m_pNPC->GetObjectKey();
msg.m_byState = CMS_RUN;
msg.m_wTileIndex = m_pNPC->GetPathExplorer()->GetTile();
msg.m_byState = CMS_RUN; //캐릭터의 경우는 무조건 뛰기만 존재!!(몬스터와 같이 쓰는 패킷이므로 값은 넣어줌)
msg.m_wvCurPos = wvCurPos;
msg.m_wvDestPos = wvDestPos;
m_pNPC->SendPacketAroundForSync(&msg);
};
}
// 도망상태가 끝나면 Follow(Idle)상태로 복귀한다.
void
RunAwayState::OnMsgCommandFollow(const AI_MSG* pMsg)
{
m_pNPC->SetTargetChar(NULL);
}