#include "stdafx.h" #include #include "RetreatState.h" #include "GameField.h" #include #include #include <3DEngine/3DTerrain/PathExplorer.h> #include #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(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(pMsg); // ÇöÀç °ø°ÝÇϰí ÀÖ´Â ´ë»óÀ̶ó¸é ¿ø·¡»óŸ¦ À¯ÁöÇÑ´Ù. Character* pCurTarget = m_pNPC->GetTargetChar(); if (pCurTarget && pCurTarget->GetObjectKey() == pAttackMsg->dwTargetKey) { return; } State::OnMsgForceAttack(pMsg); }