📄 npc.cpp
字号:
// NPC.cpp: implementation of the NPC class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "NPC.h"
#include "State.h"
#include "Field.h"
#include "AIMessageQueue.h"
#include "AITypes.h"
#include <Timer.h>
#include "ObjectGroup.h"
#include <PacketStruct_CG.h>
#include <3DEngine/3DTerrain/3DTerrain.h>
#include "CharacterFormula.h"
#include "Map.h"
#include "SkillInfoParser.h"
#include "SummonedNPCs.h"
#include <Global.h>
#include <PublicMath.h>
#include "Party.h"
#include "PartyManager.h"
#include "ObjectGroupManager.h"
#include "SummonManager.h"
#include "GameZone.h"
#include "GameRoom.h"
#include "AIParamParser.h"
#include "StatusManager.h"
#include "EtcStatus.h"
#include "StatusManager.h"
#include "RecoverStatus.h"
#include "Summoned.h"
#include "MoveStateControl.h"
#include "NPCStateManager.h"
#include "Battle.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
NPC::NPC() : m_pObjectGroup(NULL)
{
SetObjectType( NPC_OBJECT );
m_pAIMessageQueue = new AIMessageQueue;
m_pTempMessageQueue = new AIMessageQueue;
m_pBattleRecord = new BattleRecord;
m_pAggroTimer = new util::Timer;
m_pSkillSelectTimer = new util::Timer;
m_pNPCStatusManager = new NPCStateManager(this);
m_Attr.SetOwner( this );
m_pAggroTimer->SetTimer( AIParamParser::Instance()->GetInfo().m_wAGGRO_TIME );
}
NPC::~NPC()
{
SAFE_DELETE( m_pAIMessageQueue );
SAFE_DELETE( m_pTempMessageQueue );
SAFE_DELETE( m_pBattleRecord );
SAFE_DELETE( m_pAggroTimer );
SAFE_DELETE( m_pSkillSelectTimer );
SAFE_DELETE( m_pNPCStatusManager );
}
VOID NPC::Release()
{
// OnDead俊辑 窍搁 磷篮 饶俊 何劝捞 救等促. 鞍篮 利阑 傍拜窍带 局甫 何劝矫虐扁 锭巩俊..
SetTargetChar( NULL );
Character::Release();
m_Attr.Clear();
m_SkillSelector.Release();
// AIMessage 檬扁拳
m_pAIMessageQueue->Clear();
m_pTempMessageQueue->Clear();
SCCharacter::FreeCoolTime( TRUE );
}
BOOL NPC::Init()
{
m_pTargetChar = NULL;
m_iTrackSlot = -1;
m_SelectedSkillCode = SKILLCODE_INVALID;
m_wSelectedSkillDelay = 0;
m_KillerType = MAX_OBJECT;
m_dwKillerObjectKey = 0;
// FSM 檬扁拳
SetInitialState( STATE_ID_IDLE );
// 胶农赋飘俊辑 掘绢柯 胶乔靛绰 0.001阑 蚌秦霖促.
m_pMoveStateControl->Init( this, CMS_WALK );
SetHP( m_pBaseInfo->m_dwMaxHP );
SetMP( m_pBaseInfo->m_dwMaxMP );
m_pBattleRecord->Init();
// 酿鸥烙 汲沥(胶懦阑 啊瘤绊 乐阑 版快俊父 汲沥)
if( m_pBaseInfo->m_wSkillUpdateTime )
{
SCCharacter::SetCoolTime( TRUE );
}
if (!Character::Init())
{
return FALSE;
}
// 荤侩 啊瓷茄 胶懦甸阑 殿废茄促.
AddDefaultSkill();
return TRUE;
}
VOID NPC::SetBaseInfo( BASE_NPCINFO* pNPCInfo )
{
SASSERT( pNPCInfo != NULL, "pNPCInfo == NULL" );
m_pBaseInfo = pNPCInfo;
// HP, MP 雀汗伏
int iRecoverHP = 0; int iRecoverMP = 0;
if( IsHPMPRegenNPC() )
{
iRecoverHP = CalcNPCHPRecover( m_pBaseInfo->m_dwMaxHP );
iRecoverMP = CalcNPCMPRecover( m_pBaseInfo->m_dwMaxMP );
}
m_pSkillSelectTimer->SetTimer( m_pBaseInfo->m_wSkillUpdateTime );
m_Attr.SetCharInfo( m_pBaseInfo, iRecoverHP, iRecoverMP );
m_Attr.Update();
}
BOOL NPC::IsHPMPRegenNPC()
{
if( !m_pBaseInfo ) return FALSE;
if( m_pBaseInfo->m_byGrade == eNPC_GENERAL ) return FALSE;
if( m_pBaseInfo->m_byGrade == eNPC_MAPOBJECT_NPC ) return FALSE;
return TRUE;
}
VOID NPC::GetNPCRenderInfo( MONSTER_RENDER_INFO * OUT pRenderInfo )
{
pRenderInfo->m_dwObjectKey = GetObjectKey();
pRenderInfo->m_dwMonsterCode = GetBaseInfo()->m_MonsterCode;
GetPos( &pRenderInfo->m_wvPos );
pRenderInfo->m_dwHP = GetHP();
pRenderInfo->m_wMoveSpeedRatio = m_Attr.GetMoveSpeedRatio();
pRenderInfo->m_wAttSpeedRatio = m_Attr.GetAttSpeedRatio();
// STATE_INFO甫 盲款促.
STATE_INFO *pStateInfo = (STATE_INFO*)( (BYTE*)pRenderInfo + sizeof(MONSTER_RENDER_INFO) );
pRenderInfo->m_byCount = GetStatusManager()->GetAllStatusInfo( pStateInfo );
}
VOID NPC::Update( DWORD dwDeltaTick )
{
Character::Update( dwDeltaTick );
// 阁胶磐 捞悼
if( !IsMoving() ) return;
float fMoveSpeed = m_pMoveStateControl->GetMoveSpeed();
// 捞悼 傈 冀磐 牢郸胶
DWORD dwPrevSectorIndex = GetSectorIndex();
// 捞悼阑 茄促.
PathProgress( (float)dwDeltaTick * fMoveSpeed );
// 捞悼 饶 冀磐 牢郸胶
WzVector wvCurPos; GetPos( &wvCurPos );
DWORD dwAfterSectorIndex = GetField()->GetSectorIndex( &wvCurPos );
// Sector啊 函版登菌阑 版快
if( dwPrevSectorIndex != dwAfterSectorIndex )
{
SetOldSectorIndex( dwPrevSectorIndex );
SetSectorIndex( dwAfterSectorIndex );
GetField()->ChangeSector( this );
}
}
VOID NPC::SelectBestTarget()
{
BattleRecord *pBattleRecord = GetBattleRecord();
Character *pNewTargetChar = pBattleRecord->SelectBestTarget( this );
// 货肺款 鸥百阑 茫篮 版快俊父 官槽促.
if( pNewTargetChar && pNewTargetChar != m_pTargetChar )
{
// 利焙牢瘤 眉农茄促.
if( !IsFriend( pNewTargetChar ) )
{
// 鸥百函版 犬伏阑 利侩茄促.
if( random(0,100) <= m_pBaseInfo->m_byChangeTargetRatio )
{
SetTargetChar( pNewTargetChar );
}
}
}
}
Character* NPC::SelectSkillTarget( SLOTCODE SkillCode, BOOL bHeal )
{
SkillScriptInfo *pSkillInfo = SkillInfoParser::Instance()->GetSkillInfo( SkillCode );
if( !pSkillInfo ) return NULL;
Field *pField = GetField();
if( !pField ) return NULL;
// 唱吝俊 荐沥粱 毫具窃...
switch( pSkillInfo->m_byTarget )
{
case SKILL_TARGET_ENEMY: case SKILL_TARGET_REACHABLE_ENEMY:
// 措惑捞 利老 版快 泅犁 鸥百阑 弊措肺 蜡瘤茄促.
return m_pTargetChar;
case SKILL_TARGET_FRIEND: case SKILL_TARGET_REACHABLE_FRIEND:
if( bHeal ) return pField->SearchTarget( this, eRARGET_SEARCH_LOW_HPRATIO, SKILL_TARGET_FRIEND );
else return pField->SearchTarget( this, eRARGET_SEARCH_LOW_HPRATIO, SKILL_TARGET_FRIEND );
case SKILL_TARGET_ME: case SKILL_TARGET_REACHABLE_ME:
return this;
case SKILL_TARGET_FRIEND_CORPSE:
return pField->SearchTarget( this, eRARGET_SEARCH_CORPSE, SKILL_TARGET_FRIEND );
case SKILL_TARGET_SUMMON:
// 家券阑 且 版快 蝶肺 鸥百捞 鞘夸啊 绝栏哥 泅犁 鸥百阑 弊措肺 蜡瘤窍搁 等促.
return m_pTargetChar;
default :
ASSERT( ! "[NPC::SelectSkillTarget] Invalid TargetType!" );
SUNLOG( eFULL_LOG, "[NPC::SelectSkillTarget] Invalid TargetType[%d] ", pSkillInfo->m_byTarget );
}
return m_pTargetChar;
}
VOID NPC::ChangeState( DWORD dwStateID, LPARAM param1, LPARAM param2, LPARAM param3 )
{
m_pNPCStatusManager->ChangeState( dwStateID, param1, param2, param3 );
}
float NPC::GetDistToTarget() const
{
return GetDist( m_pTargetChar );
}
float NPC::GetDistToNewTarget( Character* pNewTargetChar ) const
{
return GetDist( pNewTargetChar );
}
VOID NPC::SetInitialState( DWORD dwStateID, LPARAM param1 )
{
m_pNPCStatusManager->Release();
// 肯傈 沥瘤屈
if( m_pBaseInfo->m_wMoveAttitude == eMOVE_ATTITUDE_ETERNAL_STOP )
{
m_pNPCStatusManager->AddStateObject( STATE_ID_IDLE, STATE_ID_STOP_IDLE );
m_pNPCStatusManager->AddStateObject( STATE_ID_WANDER, STATE_ID_STOP_IDLE );
m_pNPCStatusManager->AddStateObject( STATE_ID_TRACK, STATE_ID_STOP_IDLE );
m_pNPCStatusManager->AddStateObject( STATE_ID_HELP, STATE_ID_STOP_IDLE );
m_pNPCStatusManager->AddStateObject( STATE_ID_ATTACK, STATE_ID_ATTACK );
m_pNPCStatusManager->AddStateObject( STATE_ID_DEAD, STATE_ID_DEAD );
m_pNPCStatusManager->AddStateObject( STATE_ID_KNOCKDOWN, STATE_ID_KNOCKDOWN );
m_pNPCStatusManager->AddStateObject( STATE_ID_CHAOS, STATE_ID_CHAOS );
}
// 胶迄 沥瘤屈
else if( m_pBaseInfo->m_wMoveAttitude == eMOVE_ATTITUDE_SPAWN_STOP )
{
m_pNPCStatusManager->AddStateObject( STATE_ID_IDLE, STATE_ID_SPAWN_IDLE );
m_pNPCStatusManager->AddStateObject( STATE_ID_WANDER, STATE_ID_RETURN );
m_pNPCStatusManager->AddStateObject( STATE_ID_TRACK, STATE_ID_TRACK );
m_pNPCStatusManager->AddStateObject( STATE_ID_ATTACK, STATE_ID_ATTACK );
m_pNPCStatusManager->AddStateObject( STATE_ID_HELP, STATE_ID_HELP );
m_pNPCStatusManager->AddStateObject( STATE_ID_DEAD, STATE_ID_DEAD );
m_pNPCStatusManager->AddStateObject( STATE_ID_THRUST, STATE_ID_THRUST );
m_pNPCStatusManager->AddStateObject( STATE_ID_FLYING, STATE_ID_FLYING );
m_pNPCStatusManager->AddStateObject( STATE_ID_KNOCKDOWN, STATE_ID_KNOCKDOWN );
m_pNPCStatusManager->AddStateObject( STATE_ID_JUMP, STATE_ID_JUMP );
m_pNPCStatusManager->AddStateObject( STATE_ID_FALL_APART, STATE_ID_FALL_APART );
m_pNPCStatusManager->AddStateObject( STATE_ID_RETURN, STATE_ID_RETURN );
m_pNPCStatusManager->AddStateObject( STATE_ID_RETREAT, STATE_ID_RETREAT );
m_pNPCStatusManager->AddStateObject( STATE_ID_RUNAWAY, STATE_ID_RUNAWAY );
m_pNPCStatusManager->AddStateObject( STATE_ID_CHAOS, STATE_ID_CHAOS );
}
// 菩飘费
else if( m_pBaseInfo->m_wMoveAttitude == eMOVE_ATTITUDE_PATROL )
{
m_pNPCStatusManager->AddStateObject( STATE_ID_IDLE, STATE_ID_PATROL );
m_pNPCStatusManager->AddStateObject( STATE_ID_WANDER, STATE_ID_PATROL );
m_pNPCStatusManager->AddStateObject( STATE_ID_TRACK, STATE_ID_TRACK );
m_pNPCStatusManager->AddStateObject( STATE_ID_ATTACK, STATE_ID_ATTACK );
m_pNPCStatusManager->AddStateObject( STATE_ID_HELP, STATE_ID_HELP );
m_pNPCStatusManager->AddStateObject( STATE_ID_DEAD, STATE_ID_DEAD );
m_pNPCStatusManager->AddStateObject( STATE_ID_THRUST, STATE_ID_THRUST );
m_pNPCStatusManager->AddStateObject( STATE_ID_FLYING, STATE_ID_FLYING );
m_pNPCStatusManager->AddStateObject( STATE_ID_KNOCKDOWN, STATE_ID_KNOCKDOWN );
m_pNPCStatusManager->AddStateObject( STATE_ID_JUMP, STATE_ID_JUMP );
m_pNPCStatusManager->AddStateObject( STATE_ID_FALL_APART, STATE_ID_FALL_APART );
m_pNPCStatusManager->AddStateObject( STATE_ID_RETURN, STATE_ID_RETURN );
m_pNPCStatusManager->AddStateObject( STATE_ID_RETREAT, STATE_ID_RETREAT );
m_pNPCStatusManager->AddStateObject( STATE_ID_RUNAWAY, STATE_ID_RUNAWAY );
m_pNPCStatusManager->AddStateObject( STATE_ID_CHAOS, STATE_ID_CHAOS );
}
// 磊蜡 捞悼屈 寇 扁鸥
else
{
m_pNPCStatusManager->AddStateObject( STATE_ID_IDLE, STATE_ID_IDLE );
m_pNPCStatusManager->AddStateObject( STATE_ID_WANDER, STATE_ID_WANDER );
m_pNPCStatusManager->AddStateObject( STATE_ID_TRACK, STATE_ID_TRACK );
m_pNPCStatusManager->AddStateObject( STATE_ID_ATTACK, STATE_ID_ATTACK );
m_pNPCStatusManager->AddStateObject( STATE_ID_HELP, STATE_ID_HELP );
m_pNPCStatusManager->AddStateObject( STATE_ID_DEAD, STATE_ID_DEAD );
m_pNPCStatusManager->AddStateObject( STATE_ID_THRUST, STATE_ID_THRUST );
m_pNPCStatusManager->AddStateObject( STATE_ID_FLYING, STATE_ID_FLYING );
m_pNPCStatusManager->AddStateObject( STATE_ID_KNOCKDOWN, STATE_ID_KNOCKDOWN );
m_pNPCStatusManager->AddStateObject( STATE_ID_JUMP, STATE_ID_JUMP );
m_pNPCStatusManager->AddStateObject( STATE_ID_FALL_APART, STATE_ID_FALL_APART );
m_pNPCStatusManager->AddStateObject( STATE_ID_RETURN, STATE_ID_RETURN );
m_pNPCStatusManager->AddStateObject( STATE_ID_RETREAT, STATE_ID_RETREAT );
m_pNPCStatusManager->AddStateObject( STATE_ID_RUNAWAY, STATE_ID_RUNAWAY );
m_pNPCStatusManager->AddStateObject( STATE_ID_CHAOS, STATE_ID_CHAOS );
// 漂沥康开 快急八祸
if( m_pBaseInfo->m_wMoveAttitude == eMOVE_ATTITUDE_SEARCH_AREA )
{
m_pNPCStatusManager->AddStateObject( STATE_ID_TRACK_AREA, STATE_ID_TRACK_AREA );
// 漂沥康开栏肺 崔妨啊具 窍骨肺 檬扁惑怕甫 崔妨啊绰 惑怕肺 汲沥茄促.
dwStateID = STATE_ID_TRACK_AREA;
}
}
// 檬扁惑怕 汲沥
m_pNPCStatusManager->Init( dwStateID, param1 );
}
BOOL NPC::SearchAreaPos( WzVector &vDestPos )
{
Field *pField = GetField();
if( !pField ) return FALSE;
WzSpecialArea *pBaseAreaInfo = pField->GetFieldInfo()->GetAreaInfo( m_pBaseInfo->m_dwMoveAreaID );
if( !pBaseAreaInfo )
{
SUNLOG( eFULL_LOG, "[SearchAreaPos] MonsterCode[%d] MoveAreaInfo doesn't exist!", m_pBaseInfo->m_MonsterCode );
return FALSE;
}
//康开 沥焊
DWORD dwAreaTileCnt = pBaseAreaInfo->m_wbvRegion.m_BvPathTileIndex.m_nCount;
if( !dwAreaTileCnt )
{
SUNLOG( eFULL_LOG, "[SearchAreaPos] MonsterCode[%d] dwAreaTileCnt is Zero!", m_pBaseInfo->m_MonsterCode );
return FALSE;
}
DWORD *pdwTileIndex = pBaseAreaInfo->m_wbvRegion.m_BvPathTileIndex.m_pdwData;
// 捞 康开狼 鸥老 府胶飘 吝 窍唱甫 急琶
DWORD dwSelectedTile = (WORD)(rand() % dwAreaTileCnt);
// 急琶等 鸥老 救俊辑 罚待 谅钎甫 掘绢柯促.
vDestPos = pField->GetFieldInfo()->GetWorldBase()->GetRandomPosInTile( pdwTileIndex[dwSelectedTile] );
return TRUE;
}
VOID NPC::SendAIMessage( AI_MSG *pMsg, WORD wSize, DWORD dwDelay )
{
m_pAIMessageQueue->SendAIMessage( pMsg, wSize, dwDelay );
}
VOID NPC::SendAIMessageToGroupExceptMe( AI_MSG *pMsg, WORD wSize, DWORD dwDelay )
{
M_OBJECT_LIST_ITR it;
NPC* pNPC = NULL;
for(it = m_pObjectGroup->begin(); it != m_pObjectGroup->end(); it++)
{
ASSERT( NULL != it->second );
pNPC = (NPC*)it->second;
if( GetObjectKey() == pNPC->GetObjectKey() )
{
continue;
}
pNPC->SendAIMessage( pMsg, wSize, dwDelay );
}
}
VOID NPC::SendAIMessageAroundExceptMe( AI_MSG *pMsg, WORD wSize, DWORD dwDelay )
{
Field *pField = GetField();
if( !pField ) return;
pField->SendAIMessageAroundExceptMe( this, pMsg, wSize, dwDelay );
}
BOOL NPC::HasEnemy() const
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -