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

134 lines
3.0 KiB
C++

#include "stdafx.h"
#include <Timer.h>
#include "RetreatState.h"
#include "GameField.h"
#include <PacketStruct_CG.h>
#include <SinTable.h>
#include <3DEngine/3DTerrain/PathExplorer.h>
#include <math.h>
#include "AIParamParser.h"
#include "PublicMath.h"
RetreatState::RetreatState()
{
m_bFindDestPos = false;
m_bTrialCount = 0;
m_fMaxDistance = 0;
}
RetreatState::~RetreatState()
{
}
void
RetreatState::Init()
{
}
void
RetreatState::OnEnter(LPARAM param1, LPARAM param2, LPARAM param3)
{
m_bFindDestPos = false;
m_bTrialCount = 0;
if (param1)
m_fMaxDistance = static_cast<float>(param1);
else
m_fMaxDistance = m_pNPC->GetAttackRange();
m_bIdleAfterRetreat = (BOOL)param2;
State::OnEnter(param1, param2, param3);
}
void
RetreatState::OnExit()
{
State::OnExit();
}
BOOL
RetreatState::OnUpdate(DWORD dwDeltaTick)
{
__UNUSED(dwDeltaTick);
// 목적지를 찾았으면
if (m_bFindDestPos)
{
// 이동이 끝날 때까지 기다린다.
if (!m_pNPC->IsMoving())
{
if (m_bIdleAfterRetreat == false && m_pNPC->GetTargetChar())
m_pNPC->ChangeState(STATE_ID_ATTACK);
else
m_pNPC->ChangeState(STATE_ID_IDLE);
}
}
// 못 찾았으면 다시 시도한다.
else
{
Retreat();
}
return true;
}
void
RetreatState::Retreat()
{
// 타겟이 없으면 Idle상태로 돌아간다.
Character* pTargetChar = m_pNPC->GetTargetChar();
if (pTargetChar == NULL)
{
SUNLOG(eFULL_LOG, "[Retreat] m_pTargetChar is NULL!");
m_pNPC->ChangeState(STATE_ID_IDLE);
return;
}
++m_bTrialCount;
const WzVector& vCurPos = *m_pNPC->GetPosPtr();
const WzVector& vTargetPos = *pTargetChar->GetPosPtr();
WzVector vNormal;
VectorNormalize(&vNormal, &(vCurPos - vTargetPos));
// 이동 거리를 구한다.
float fMinDistance = m_fMaxDistance *
AIParamParser::AICommonInfo.m_fRETREAT_MIN_DISTANCE_LIMIT_RATIO;
float fDistance = (float)dRandom(fMinDistance, m_fMaxDistance);
// 이동해야할 방향의 30*m_bTrialCount도 안팍으로 랜덤한 위치를 얻어온다.
int iHalfAngle = min(180, 30 * m_bTrialCount);
int iRotateAngle = random(0, iHalfAngle * 2);
if (iRotateAngle > iHalfAngle)
iRotateAngle = 360 + iHalfAngle - iRotateAngle;
WzVector vTrackPos;
// in out in
Math_ZRotateVector(&vNormal, vTrackPos, iRotateAngle);
vTrackPos = vTargetPos + vTrackPos * fDistance;
if (m_pNPC->MoveAndBroadcast(&vTrackPos, CMS_RUN))
{
m_bFindDestPos = true;
}
}
void
RetreatState::OnMsgForceAttack(const AI_MSG* pMsg)
{
const AI_MSG_FORCE_ATTACK* pAttackMsg = static_cast<const AI_MSG_FORCE_ATTACK*>(pMsg);
// 현재 공격하고 있는 대상이라면 원래상태를 유지한다.
Character* pCurTarget = m_pNPC->GetTargetChar();
if (pCurTarget && pCurTarget->GetObjectKey() == pAttackMsg->dwTargetKey)
{
return;
}
State::OnMsgForceAttack(pMsg);
}