⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 npc.cpp

📁 奇迹世界 部分源代码奇迹世界 部分源代码奇迹世界 部分源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// 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 + -