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

📄 basecharacter.cpp

📁 Blood 2全套源码
💻 CPP
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : BaseCharacter.cpp
//
// PURPOSE : Base class for player and AI
//
// CREATED : 10/6/97
//
// ----------------------------------------------------------------------- //

#include "BaseCharacter.h"
#include "objectutilities.h"
#include "VolumeBrush.h"
#include "ClientServerShared.h"
#include "SParam.h"
#include "PlayerObj.h"
#include <stdio.h>


//#define FLAG_BASECHARACTER		1
//#define FLAG_PLAYER				2

#define LADDER_STOP_TIME			0.2f
#define SWIM_STOP_TIME				1.0f


BEGIN_CLASS(CBaseCharacter)
	ADD_DESTRUCTABLE_AGGREGATE()
END_CLASS_DEFAULT(CBaseCharacter, B2BaseClass, NULL, NULL)


CBaseCharacter::CBaseCharacter(DBYTE nType) : B2BaseClass(nType)
{
 	AddAggregate(&m_damage);
	AddAggregate(&m_InventoryMgr);
	AddAggregate(&m_MoveObj);

	m_eContainerCode			= CC_NOTHING;
	m_eLastContainerCode		= CC_NOTHING;
	m_bBodyInLiquid				= DFALSE;
	m_bBodyOnLadder				= DFALSE;
	m_bSwimmingOnSurface		= DFALSE;

	m_dwSurfType				= SURFTYPE_FLESH;

	m_fSwimVel					= DEFAULT_SWIM_VEL;
	m_fLadderVel				= DEFAULT_LADDER_VEL;

	m_nTrapped					= 0;
	m_bTrappedGrav				= DTRUE;
}



DDWORD CBaseCharacter::EngineMessageFn(DDWORD messageID, void *pData, DFLOAT fData)
{
	switch(messageID)
	{
		case MID_UPDATE:
			m_eLastContainerCode = m_eContainerCode;
			break;

		case MID_MODELSTRINGKEY:
		{
			OnStringKey((ArgList*)pData);
			break;
		}

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

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

		case MID_INITIALUPDATE:
			{
				if (fData != INITIALUPDATE_SAVEGAME)
				{
					// Set some flags that all basecharacters should have
					// Doing it here for now since I don't want to change every AI file - GK 3/18
					DDWORD dwFlags = g_pServerDE->GetObjectFlags(m_hObject);
					g_pServerDE->SetObjectFlags(m_hObject, dwFlags | FLAG_MODELGOURAUDSHADE | FLAG_ANIMTRANSITION);
					g_pServerDE->SetObjectUserFlags(m_hObject, USERFLG_NIGHTGOGGLESGLOW );

					dwFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
					dwFlags |= ((m_dwSurfType << 24) + USRFLG_SAVEABLE | USRFLG_SINGULARITY_ATTRACT);
	 				g_pServerDE->SetObjectUserFlags(m_hObject, dwFlags);
				}
			}
			break;

		default : break;
	}

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

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::OnStringKey()
//
//	PURPOSE:	Handle animation command
//
// ----------------------------------------------------------------------- //

void CBaseCharacter::OnStringKey(ArgList* pArgList)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !pArgList || !pArgList->argv || pArgList->argc == 0) return;

	char* pKey = pArgList->argv[0];
	if (!pKey) return;

	// get rotation
	DRotation rRot;
    DVector m_vUp, m_vRight, m_vForward;
    
	VEC_INIT(m_vUp);
	VEC_INIT(m_vRight);
	VEC_INIT(m_vForward);

	char szTemp[32];

	//check for direction change for velocity 
	if(Sparam_Get(szTemp,pKey,"RotY"))
	{
		DFLOAT fTurn = (DFLOAT)atof(szTemp);

		pServerDE->GetObjectRotation(m_hObject, &rRot);
		pServerDE->EulerRotateY(&rRot, fTurn);
		pServerDE->SetObjectRotation(m_hObject, &rRot);	
	}

	//check for forward/backward velocity
	if(Sparam_Get(szTemp,pKey,"ForwVel"))
	{
		pServerDE->GetObjectRotation(m_hObject, &rRot);
		pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);

		DVector vVel;
		VEC_MULSCALAR(vVel, m_vForward, (DFLOAT)atof(szTemp));

		pServerDE->SetVelocity(m_hObject, &vVel);
	}

	//check for right/left velocity
	if(Sparam_Get(szTemp,pKey,"RightVel"))
	{
		pServerDE->GetObjectRotation(m_hObject, &rRot);
		pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);

		DVector vVel;
		VEC_MULSCALAR(vVel, m_vRight, (DFLOAT)atof(szTemp));

		pServerDE->SetVelocity(m_hObject, &vVel);
	}


	//check for up/down velocity
	if(Sparam_Get(szTemp,pKey,"UpVel"))
	{
		pServerDE->GetObjectRotation(m_hObject, &rRot);
		pServerDE->GetRotationVectors(&rRot, &m_vUp, &m_vRight, &m_vForward);

		DVector vVel;
		VEC_MULSCALAR(vVel, m_vUp, (DFLOAT)atof(szTemp));

		pServerDE->SetVelocity(m_hObject, &vVel);
	}

	//check for position change
	if(Sparam_Get(szTemp,pKey,"AddX"))
	{
		DVector vPos,vNewPos;
		char szY[10],szZ[10];

		Sparam_Get(szY,pKey,"AddY");
		Sparam_Get(szZ,pKey,"AddZ");

		VEC_INIT(vPos);
		VEC_SET(vNewPos, atof(szTemp), atof(szY), atof(szZ));
		pServerDE->GetObjectPos(m_hObject, &vPos);
		VEC_ADD(vPos,vPos,vNewPos);

		//apply new dims
		pServerDE->MoveObject(m_hObject, &vPos);
	}

	//check for dims change
	if(Sparam_Get(szTemp,pKey,"DimsX"))
	{
		DVector vDims;
		char szY[10],szZ[10];

		Sparam_Get(szY,pKey,"DimsY");
		Sparam_Get(szZ,pKey,"DimsZ");

		VEC_INIT(vDims);
		VEC_SET(vDims, atof(szTemp), atof(szY), atof(szZ));
		
		//apply new dims
		pServerDE->SetObjectDims(m_hObject, &vDims);
	}

	return;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::Trap
//
//	PURPOSE:	Don't allow a player to move (with or without gravity)
//
// ----------------------------------------------------------------------- //

DBOOL CBaseCharacter::Trap(char nTrap, DBOOL bGravity)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !m_hObject) return DFALSE;

	// Modify the trapped counter...
	if(nTrap == -1)
	{
		m_nTrapped = 0;
		nTrap = 0;
	}
	else if(nTrap)
		m_nTrapped++;
	else
		m_nTrapped--;

	// Don't let the trapped counter drop below zero...
	if(m_nTrapped < 0)
		m_nTrapped = 0;

	// Zero out the current velocity
	if(nTrap)
	{
		DVector vTemp;
		VEC_INIT(vTemp);

		if(!bGravity)
		{
			pServerDE->GetVelocity(m_hObject, &vTemp);
			vTemp.x = vTemp.z = 0.0f;
		}

		pServerDE->SetVelocity(m_hObject, &vTemp);
		pServerDE->SetNextUpdate(m_hObject, 0.0001f);
	}

	// Trap the client if it's a player
	if(IsPlayer(m_hObject))
	{
		CPlayerObj *pHit = (CPlayerObj*)pServerDE->HandleToObject(m_hObject);

		HMESSAGEWRITE hMsg = pServerDE->StartMessage(pHit->GetClient(), SMSG_TRAPPED);
		pServerDE->WriteToMessageByte(hMsg, (DBYTE)m_nTrapped);
		pServerDE->WriteToMessageByte(hMsg, 1);
		pServerDE->EndMessage2(hMsg, MESSAGE_GUARANTEED | MESSAGE_NAGGLE);
	}

	// Save or restore the original gravity setting if needed
/*	if(bGravity)
	{
		DDWORD	dwFlags;
		dwFlags = pServerDE->GetObjectFlags(m_hObject);

		if(nTrap && (m_nTrapped == 1))
		{
			m_bTrappedGrav = (DBOOL)(dwFlags & FLAG_GRAVITY);
			pServerDE->SetObjectFlags(m_hObject, dwFlags & ~FLAG_GRAVITY);
		}
		else if(!nTrap && !m_nTrapped && m_bTrappedGrav)
		{
			pServerDE->SetObjectFlags(m_hObject, dwFlags | FLAG_GRAVITY);
		}
	}*/

	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::UpdateInLiquid
//
//	PURPOSE:	Update movement when in liquid
//
// ----------------------------------------------------------------------- //

void CBaseCharacter::UpdateInLiquid(VolumeBrush* pBrush, ContainerPhysics* pCPStruct)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !pBrush || !pCPStruct) return;

	m_bBodyInLiquid = DTRUE;

	DBOOL bHeadInLiquid = IsLiquid(m_eContainerCode);

	// Undo viscosity dampening done in brush (we'll do our own)...

	pBrush->UndoViscosityCalculation(pCPStruct);


	// Do REAL friction dampening (i.e., actually change our velocity)...

	DVector vVel;
	pServerDE->GetVelocity(m_hObject, &vVel);

	DFLOAT fTimeDelta = pServerDE->GetFrameTime();

	DVector vCurVel;
	VEC_COPY(vCurVel, vVel);

	if (VEC_MAG(vCurVel) > 1.0f)
	{
		DVector vDir;
		VEC_COPY(vDir, vCurVel);
		VEC_NORM(vDir);

		DFLOAT fAdjust = pServerDE->GetFrameTime()*(m_fSwimVel/SWIM_STOP_TIME);

		VEC_MULSCALAR(vVel, vDir, fAdjust);

		if (VEC_MAG(vVel) < VEC_MAG(vCurVel))
		{
			VEC_SUB(vVel, vCurVel, vVel);
		}
		else
		{
			VEC_INIT(vVel);
		}
	}


	// Handle floating around on the surface...

	if (m_bSwimmingOnSurface)
	{
		DBOOL bMoving = ((VEC_MAG(pCPStruct->m_Acceleration) > 0.01f) ||
						 (VEC_MAG(pCPStruct->m_Velocity) > 0.01f));
	
		pCPStruct->m_Flags &= ~FLAG_GRAVITY;  // Turn gravity off

		if (bMoving)  // Turn off y acceleration and velocity
		{
			if (vVel.y > 0.0f || pCPStruct->m_Acceleration.y > 0.0f)
			{
				vVel.y						= 0.0f;
				pCPStruct->m_Velocity.y		= 0.0f;
				pCPStruct->m_Acceleration.y = 0.0f;
			}
		}
		else // Pull us down if we're not moving (fast enough)
		{
			pCPStruct->m_Acceleration.y += pBrush->GetGravity();
		}
	}
	else if (IsLiquid(m_eContainerCode))
	{
		pCPStruct->m_Flags &= ~FLAG_GRAVITY;
		pCPStruct->m_Acceleration.y += pBrush->GetGravity();
	}

	// If we're trapped, don't move...
	if(m_nTrapped)
		{ VEC_INIT(vVel); }

	pServerDE->SetVelocity(m_hObject, &vVel);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::UpdateOnLadder
//
//	PURPOSE:	Update movement when on a ladder
//
// ----------------------------------------------------------------------- //

void CBaseCharacter::UpdateOnLadder(VolumeBrush* pBrush, ContainerPhysics* pCPStruct)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !pBrush || !pCPStruct) return;

	m_bBodyOnLadder = DTRUE;

	// Do REAL friction dampening (i.e., actually change our velocity)...

	DVector vVel;
	pServerDE->GetVelocity(m_hObject, &vVel);

	DVector vCurVel;
	VEC_COPY(vCurVel, vVel);

	if (VEC_MAG(vCurVel) > 1.0f)
	{
		DVector vDir;
		VEC_COPY(vDir, vCurVel);
		VEC_NORM(vDir);

		DFLOAT fAdjust = pServerDE->GetFrameTime()*(m_fLadderVel/LADDER_STOP_TIME);

		VEC_MULSCALAR(vVel, vDir, fAdjust);

		if (VEC_MAG(vVel) < VEC_MAG(vCurVel))
		{
			VEC_SUB(vVel, vCurVel, vVel);
		}
		else
		{
			VEC_INIT(vVel);
		}

		// If we're trapped, don't move...
		if(m_nTrapped)
			{ VEC_INIT(vVel); }

		pServerDE->SetVelocity(m_hObject, &vVel);
	}

	pCPStruct->m_Flags &= ~FLAG_GRAVITY;  // Turn gravity off
}



// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::Save
//
//	PURPOSE:	Save the object
//
// ----------------------------------------------------------------------- //

void CBaseCharacter::Save(HMESSAGEWRITE hWrite, DDWORD dwSaveFlags)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !hWrite) return;

}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBaseCharacter::Load
//
//	PURPOSE:	Load the object
//
// ----------------------------------------------------------------------- //

void CBaseCharacter::Load(HMESSAGEREAD hRead, DDWORD dwLoadFlags)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !hRead) return;

}

⌨️ 快捷键说明

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