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

📄 civilianai.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : CivilianAI.cpp
//
// PURPOSE : CivilianAI - Definition
//
// CREATED : 12/15/97
//
// ----------------------------------------------------------------------- //

// 10.4 Incidental Creatures
// This section covers benign creatures whose only purpose 
// in the game is atmosphere or target practice.

// 1.1.310.4.3 Civilians
// Target practice.  We should be able to get away with creating two models
// (male and female) and doing 2-3 skins for each to cover a large variety of Civilians.



#include <stdio.h>
#include "CivilianAI.h"
#include "cpp_server_de.h"

BEGIN_CLASS(CivilianAI)
    ADD_REALPROP(RandomHitPoints, 0.0f) \
	ADD_STRINGPROP(AIState, "IDLE")     \
	ADD_STRINGPROP(AIWeapon1, "NONE")   \
	ADD_BOOLPROP(Male, DTRUE) \
	ADD_BOOLPROP(LabTech, DFALSE) \
	ADD_BOOLPROP(Scared, DFALSE) \
	ADD_VECTORPROP_VAL_FLAG(Dims, 21.0f, 37.0f, 21.0f, PF_DIMS | PF_LOCALDIMS | PF_HIDDEN) \
	ADD_BOOLPROP(SororitySkin, DFALSE)
END_CLASS_DEFAULT(CivilianAI, AI_Mgr, NULL, NULL)

//static data member initialization
DBOOL		CivilianAI::m_bFemaleAnims = DTRUE;
CAnim_Sound	CivilianAI::m_Female_Anim_Sound;
DBOOL		CivilianAI::m_bMaleAnims = DTRUE;
CAnim_Sound	CivilianAI::m_Male_Anim_Sound;

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	
//
//	PURPOSE:	Constructor
//
// ----------------------------------------------------------------------- //

CivilianAI::CivilianAI() : AI_Mgr()
{
	m_fHearingDist	= 2000.0f;
	m_fSensingDist	= 200.0f;
	m_fSmellingDist	= 0.0f;
	m_fSeeingDist	= 2000.0f;

	m_fWalkSpeed	= 75.0f;
	m_fRunSpeed		= 180.0f;
	m_fRollSpeed	= 3.5f;

	m_fAIMass		= AI_DEFAULT_MASS;

	m_nAIStrength	= 5;

	m_nState = STATE_Idle; 
	m_nLastState = STATE_Idle; 
	m_dwFlags = FLAG_ALWAYSRECOIL;

	m_bMale = DTRUE;
	m_bCabal = DTRUE;

	// [blg]
	m_fAIHitPoints   = 30;
	m_fAIRandomHP    = 0;

	m_fAICharges	 = 100.0f;		//for Coleman's wacky scientist

	_mbscpy((unsigned char*)m_szAIState, (const unsigned char*)"IDLE");

	m_bMale = DTRUE;
	m_bLabTech = DFALSE;
	m_bScared = DFALSE;
	m_bSororitySkin = DFALSE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	EngineMessageFn
//
//	PURPOSE:	Handle engine messages
//
// ----------------------------------------------------------------------- //

DDWORD CivilianAI::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
	switch(messageID)
	{
		case MID_PRECREATE:
		{
			// Need to call base class to have the object name read in before
			// we call PostPropRead()

			DDWORD dwRet = AI_Mgr::EngineMessageFn(messageID, pData, fData);

			if (fData == 1.0)
			{
				GetServerDE()->GetPropBool("Male", &m_bMale);
				GetServerDE()->GetPropBool("LabTech", &m_bLabTech);
				GetServerDE()->GetPropBool("Scared", &m_bScared);
				GetServerDE()->GetPropBool("SororitySkin", &m_bSororitySkin);
			}

			if(fData != PRECREATE_SAVEGAME)
				PostPropRead((ObjectCreateStruct*)pData);

			return dwRet;
		}
		break;
        
		case MID_INITIALUPDATE:
		{
			InitialUpdate((DVector *)pData);
			CacheFiles();
			break;
		}

		case MID_SAVEOBJECT:
			Save((HMESSAGEWRITE)pData, (DDWORD)fData);
			break;

		case MID_LOADOBJECT:
			Load((HMESSAGEREAD)pData, (DDWORD)fData);
			break;

		default : break;
	}


	return AI_Mgr::EngineMessageFn(messageID, pData, fData);
}

// ----------------------------------------------------------------------- //
// ROUTINE		: CivilianAI::ObjectMessageFn
// DESCRIPTION	: Handle inter-object messages
// RETURN TYPE	: DDWORD 
// PARAMS		: HOBJECT hSender
// PARAMS		: DDWORD messageID
// PARAMS		: HMESSAGEREAD hRead
// ----------------------------------------------------------------------- //

DDWORD CivilianAI::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead)
{
	switch(messageID)
	{
 		case MID_TRIGGER:
		{
			HSTRING hMsg = m_pServerDE->ReadFromMessageHString(hRead);
			char *pCommand = m_pServerDE->GetStringData(hMsg);

			/* 01/15/1999 Be VERY sure we should run this. -- Loki */
			if ((m_nState != STATE_Escape_Hide) && 
				(m_nState != STATE_Script) && 
				(m_nState != STATE_Special1) &&
				(m_nState != STATE_Special2) &&
				(m_nState != STATE_Special3) &&
				(m_nState != STATE_Special4) &&
				(m_nState != STATE_Special5) &&
				(m_nState != STATE_Special6) &&
				(m_nState != STATE_Special7) &&
				(m_nState != STATE_Special8) &&
				(m_nState != STATE_Special9) &&
				(_mbscmp((const unsigned char*)pCommand, (const unsigned char*)"TRIGGER") == 0))
			{
				m_hTarget = hSender;

				if(m_bLabTech)
					SetNewState(STATE_Escape_Hide);
				else
					SetNewState(STATE_Special1);
			}

			g_pServerDE->FreeString( hMsg );

			break;
		}

		case MID_DAMAGE:
		{
			AI_Mgr::ObjectMessageFn(hSender, messageID, hRead);
			SetNewState(STATE_Escape_RunAway);

			return 0;
		}

		default : break;
	}

	return AI_Mgr::ObjectMessageFn(hSender, messageID, hRead);
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	PostPropRead()
//
//	PURPOSE:	Update properties
//
// ----------------------------------------------------------------------- //

void CivilianAI::PostPropRead(ObjectCreateStruct *pStruct)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !pStruct) return;

	char* pFilename= DNULL;
	char* pSkin = DNULL;

	DFLOAT fDetail = 4;	//m_pServerDE->GetVarValueFloat(m_pServerDE->GetGameConVar("GlobalDetail"));

	if(StateStrToInt(m_szAIState) == STATE_Special8)
	{
		pFilename = "Models\\Enemies\\m_civilian1.abc";
		pSkin = "Skins\\Enemies\\m_civilian4.dtx";
	}
	else if (m_bSororitySkin)
	{
		pFilename = "Models\\Enemies\\f_civilian1.abc";
		pSkin     = "Skins_ao\\Enemies_ao\\f_civilian3.dtx";
	}
	else if(m_bLabTech)
	{
		pFilename = "Models\\Enemies\\labtech.abc";

		if(fDetail <= 0)
		{
			pSkin = "Skins\\Enemies\\labtech1.dtx";
		}
		else
		{
			switch(pServerDE->IntRandom(1,3))
			{
				case 1:		pSkin = "Skins\\Enemies\\labtech1.dtx";	break;
				case 2:		pSkin = "Skins\\Enemies\\labtech2.dtx";	break;
				case 3:		pSkin = "Skins\\Enemies\\labtech3.dtx";	break;
				default:	pSkin = "Skins\\Enemies\\labtech1.dtx";	break;
			}
		}
	}
	else if(m_bMale)
	{
		pFilename = "Models\\Enemies\\m_civilian1.abc";

		if(fDetail <= 0)
		{
			pSkin = "Skins\\Enemies\\m_civilian1.dtx";
		}
		else
		{
			switch(pServerDE->IntRandom(1,3))
			{
				case 1:		pSkin = "Skins\\Enemies\\m_civilian1.dtx";	break;
				case 2:		pSkin = "Skins\\Enemies\\m_civilian2.dtx";	break;
				case 3:		pSkin = "Skins\\Enemies\\m_civilian3.dtx";	break;
				default:	pSkin = "Skins\\Enemies\\m_civilian1.dtx";	break;
			}
		}
	}
	else
	{
		pFilename = "Models\\Enemies\\f_civilian1.abc";

		if(fDetail <= 0)
		{
			pSkin = "Skins\\Enemies\\f_civilian1.dtx";
		}
		else
		{
			switch(pServerDE->IntRandom(1,3))
			{
				case 1:		pSkin = "Skins\\Enemies\\f_civilian1.dtx";	break;
				case 2:		pSkin = "Skins\\Enemies\\f_civilian1.dtx";	break;
				case 3:		pSkin = "Skins\\Enemies\\f_civilian1.dtx";	break;
				default:	pSkin = "Skins\\Enemies\\f_civilian1.dtx";	break;
			}
		}
	}
	
	_mbscpy((unsigned char*)pStruct->m_Filename, (const unsigned char*)pFilename);
	_mbscpy((unsigned char*)pStruct->m_SkinName, (const unsigned char*)pSkin);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	InitialUpdate()
//
//	PURPOSE:	Handle initial update
//
// ----------------------------------------------------------------------- //

DBOOL CivilianAI::InitialUpdate(DVector *pMovement)
{
	m_pServerDE = BaseClass::GetServerDE();
	if (!m_pServerDE) return DFALSE;

	//Load up animation indexes if first model instance
	if(m_bMale || m_bLabTech && m_bMaleAnims)
	{
		m_Male_Anim_Sound.SetAnimationIndexes(m_hObject);
		m_Male_Anim_Sound.GenerateHitSpheres(m_hObject);

		m_Male_Anim_Sound.SetSoundRoot("sounds\\enemies\\civilian");
		m_bMaleAnims = DFALSE;
	}

	if(!m_bMale && m_bFemaleAnims)
	{
		m_Female_Anim_Sound.SetAnimationIndexes(m_hObject);
		m_Female_Anim_Sound.GenerateHitSpheres(m_hObject);

		m_Female_Anim_Sound.SetSoundRoot("sounds\\enemies\\f_civ");
		m_bFemaleAnims = DFALSE;
	}

	if(m_bMale || m_bLabTech)
		AI_Mgr::InitStatics(&m_Male_Anim_Sound);
	else
		AI_Mgr::InitStatics(&m_Female_Anim_Sound);

	return DTRUE;
}

// ----------------------------------------------------------------------- //
// ROUTINE		: CivilianAI::ComputeState
// DESCRIPTION	: Compute actual substate
// RETURN TYPE	: void 
// ----------------------------------------------------------------------- //

void CivilianAI::ComputeState(int nStimType)
{
	int nStim = nStimType;

	if(nStimType == -1)
		nStim = ComputeStimuli();

	if(!nStim)
	{
		SetNewState(StateStrToInt(m_szAIState));
	}
	else
	{
		if(m_nState == STATE_Escape_Hide)
		{
			SetNewState(STATE_Escape_Hide);
		}
		else if(m_bScared || (m_fStimuli[HEALTH] < 1.0f))
		{
			m_bScared = DTRUE;
			SetNewState(STATE_Escape_RunAway);
		}
		else
			SetNewState(StateStrToInt(m_szAIState));
	}

	return;
}

// ----------------------------------------------------------------------- //
// ROUTINE		: CivilianAI::AI_STATE_Escape_RunAway
// DESCRIPTION	: 
// RETURN TYPE	: void 
// ----------------------------------------------------------------------- //

void CivilianAI::AI_STATE_Escape_RunAway()
{
	DVector vDims;
	m_pServerDE->GetObjectDims(m_hObject,&vDims);
	DFLOAT fDim = (DFLOAT)sqrt((vDims.x * vDims.x) + (vDims.z * vDims.z)) + 0.1f;

	switch(Metacmd)
	{
		case 1:		
		{
					m_hTrackObject = FindObjectInRadius(m_pServerDE->GetClass("ExitHint"), m_fSeeingDist, FIND_VISIBLE);

					if(m_hTrackObject)
					{
						m_pServerDE->GetObjectPos(m_hTrackObject,&m_vTrackObjPos);

						DFLOAT fDist = VEC_DIST(m_vTrackObjPos, m_MoveObj.GetPos());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -