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

📄 corpse.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#include <stdio.h>
#include "corpse.h"
#include "ObjectUtilities.h"
#include "weapon.h"
#include "SFXMsgIds.h"
#include "ClientServerShared.h"
#include "ClientGibFX.h"
#include "ClientSplatFX.h"
#include "sparam.h"
#include "PlayerObj.h"
#include "VoiceMgrDefs.h"
#include "BloodServerShell.h"

BEGIN_CLASS(CCorpse)
END_CLASS_DEFAULT_FLAGS(CCorpse, B2BaseClass, NULL, NULL, CF_HIDDEN)

extern CPlayerObj* g_pPlayerObj;


#define CORPSE_REMOVETIME		30.0f


// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CCorpse::Setup()
//
//	PURPOSE:	Setup
//
// --------------------------------------------------------------------------- //

void CCorpse::Setup(HOBJECT hFireObj, DBOOL bLimbLoss)
{
	CServerDE* g_pServerDE = GetServerDE();
	if (!g_pServerDE) return;

	if(hFireObj)
	{
		m_hFireSource = hFireObj;

		DVector		offset;
		VEC_SET(offset, 0.0f, 0.0f, 0.0f);

		HMESSAGEWRITE hMessage = g_pServerDE->StartInstantSpecialEffectMessage(&offset);
		g_pServerDE->WriteToMessageByte(hMessage, SFX_OBJECTFX_ID);
		g_pServerDE->WriteToMessageObject(hMessage, m_hFireSource);
		g_pServerDE->WriteToMessageVector(hMessage, &offset);
		g_pServerDE->WriteToMessageFloat(hMessage, 3.0f);
		g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_SCALENUMPARTICLES);
		g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_FLAMING_2);
		g_pServerDE->WriteToMessageDWord(hMessage, 0);
		g_pServerDE->EndMessage(hMessage);

		DRotation rRot;
		ROT_INIT(rRot);

		g_pServerDE->CreateAttachment(m_hObject, m_hFireSource, "torso", &offset, &rRot, &m_hAttach);

		m_fBurnStart = g_pServerDE->GetTime();

		//play ambient looping sound
		PlaySoundInfo playSoundInfo;
		PLAYSOUNDINFO_INIT( playSoundInfo );

		playSoundInfo.m_dwFlags = PLAYSOUND_3D | PLAYSOUND_ATTACHED | PLAYSOUND_GETHANDLE | PLAYSOUND_REVERB;
		playSoundInfo.m_dwFlags |= PLAYSOUND_LOOP | PLAYSOUND_CTRL_VOL;
		
		_mbsncpy((unsigned char*)playSoundInfo.m_szSoundName, (const unsigned char*)"sounds\\weapons\\fireloop.wav", _MAX_PATH );
		playSoundInfo.m_hObject = m_hObject;
		playSoundInfo.m_nPriority = SOUNDPRIORITY_AI_MEDIUM;
		playSoundInfo.m_fOuterRadius = 1000;
		playSoundInfo.m_fInnerRadius = 1000 * 0.2f;
		playSoundInfo.m_nVolume = 60;
		
		g_pServerDE->PlaySound( &playSoundInfo );
		m_hLoopSound = playSoundInfo.m_hSound;

		//create the smoke object
		ObjectCreateStruct ocStruct;
		INIT_OBJECTCREATESTRUCT(ocStruct);

		ocStruct.m_ObjectType = OT_NORMAL;
		ocStruct.m_NextUpdate = 0.01f;
		g_pServerDE->GetModelNodeTransform(m_hObject, "torso",&ocStruct.m_Pos,&ocStruct.m_Rotation);
		ocStruct.m_Flags = FLAG_FORCECLIENTUPDATE;
		
		HCLASS hClass = g_pServerDE->GetClass("BaseClass");
		BaseClass* pObj = g_pServerDE->CreateObject(hClass, &ocStruct);

		if(pObj)
		{
			m_hSmokeSource = pObj->m_hObject;
		}
	}

	m_bLimbLoss = bLimbLoss;

	return;
}

// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CCorpse::EngineMessageFn()
//
//	PURPOSE:	Handler for engine messages
//
// --------------------------------------------------------------------------- //

DDWORD CCorpse::EngineMessageFn(DDWORD messageID, void *pData, float fData)
{
	switch(messageID)
	{
		case MID_UPDATE:
		{
				if (!Update())
				g_pServerDE->RemoveObject( m_hObject );

			break;
		}

		case MID_PRECREATE:
		{
			DDWORD dwRet = B2BaseClass::EngineMessageFn(messageID, pData, fData);

			if (fData == PRECREATE_WORLDFILE || fData == PRECREATE_STRINGPROP)
			{
				ReadProp((ObjectCreateStruct*)pData);
			}

			PostPropRead((ObjectCreateStruct*)pData);

			return dwRet;
		}

		case MID_INITIALUPDATE:
		{
			if (fData != INITIALUPDATE_SAVEGAME)
			{
				InitialUpdate((DVector *)pData);
			}
			if (fData == INITIALUPDATE_WORLDFILE)
			{
				MoveObjectToGround(m_hObject);
			}

			break;
		}

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

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

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

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

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CCorpse::ObjectMessageFn
//
//	PURPOSE:	Handle object-to-object messages
//
// ----------------------------------------------------------------------- //

DDWORD CCorpse::ObjectMessageFn( HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead )
{
	CServerDE* g_pServerDE = GetServerDE();
	if (!g_pServerDE) return 0;

	switch(messageID)
	{
		case MID_DAMAGE:
		{
			B2BaseClass::ObjectMessageFn(hSender, messageID, hRead);

			DVector vDir,vPos;
			DFLOAT fDamage;
			DBYTE  nType;
				
			g_pServerDE->ReadFromMessageVector(hRead, &vDir);
			fDamage = g_pServerDE->ReadFromMessageFloat(hRead);
			nType	= g_pServerDE->ReadFromMessageByte(hRead);
			HOBJECT hObj = g_pServerDE->ReadFromMessageObject(hRead);
			g_pServerDE->ReadFromMessageVector(hRead, &vPos);

			VEC_MULSCALAR(vDir,vDir,-1.0f);

			if (!m_bDead)
				return HandleDamage(vDir, fDamage, nType, vPos);
			else
				return 0;
		}

		default : break;
	}

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

// --------------------------------------------------------------------------- //
//
//	ROUTINE:	CCorpse::ReadProp()
//
//	PURPOSE:	Reads properties
//
// --------------------------------------------------------------------------- //

DBOOL CCorpse::ReadProp(ObjectCreateStruct *pStruct)
{
	CServerDE* pServerDE = GetServerDE();
	if (!pServerDE || !pStruct) return DFALSE;

	return DTRUE;
}

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

void CCorpse::PostPropRead(ObjectCreateStruct *pStruct)
{
	if (!pStruct) return;

	pStruct->m_Flags = FLAG_VISIBLE | FLAG_RAYHIT | FLAG_GRAVITY | FLAG_MODELKEYS | FLAG_REMOVEIFOUTSIDE;

	if(pStruct->m_UserData)
		_mbscpy((unsigned char*)m_szSoundDir, (const unsigned char*)pStruct->m_UserData);

	return;
}

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

void CCorpse::InitialUpdate(DVector *pMovement)
{
	if (!g_pServerDE) return;

	m_damage.Init( m_hObject );

	// Setup damage stats...
	m_damage.SetMass( m_fMass );
	m_damage.SetHitPoints( m_fHitPoints );
	m_damage.SetMaxHitPoints( m_fHitPoints );
	m_damage.SetArmorPoints( 0.0f );
	m_damage.SetMaxArmorPoints( 0.0f );
	m_damage.SetApplyDamagePhysics(DFALSE);

	GenerateHitSpheres();

	DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(m_hObject);
	dwFlags |= (SURFTYPE_FLESH << 24);

	dwFlags |= USRFLG_SAVEABLE  | USRFLG_SINGULARITY_ATTRACT;

	g_pServerDE->SetObjectUserFlags(m_hObject, dwFlags);

	g_pServerDE->SetNextUpdate( m_hObject, 0.01f );

	return;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CCorpse::Update
//
//	PURPOSE:	Update until the death anim is done..
//
// ----------------------------------------------------------------------- //

DBOOL CCorpse::Update()
{
	if (m_bDead || !g_pServerDE) return DFALSE;

	DDWORD dwState	= g_pServerDE->GetModelPlaybackState(m_hObject);
	DFLOAT fTime = g_pServerDE->GetTime();

	if(m_fRemoveTime && m_fRemoveTime <= fTime) return DFALSE;

	if(m_fSmokeStart == 0.0f && m_hFireSource && fTime - m_fBurnStart > 5.0f)
	{
		g_pServerDE->RemoveAttachment(m_hAttach);
		g_pServerDE->RemoveObject(m_hFireSource);

		m_hFireSource = DNULL;

		if(m_hLoopSound)
		{
			g_pServerDE->KillSound(m_hLoopSound);
			m_hLoopSound = DNULL;
		}

		//create the smoke
		DVector		offset;
		VEC_SET(offset, 0.0f, 0.0f, 0.0f);

		HMESSAGEWRITE hMessage = g_pServerDE->StartInstantSpecialEffectMessage(&offset);
		g_pServerDE->WriteToMessageByte(hMessage, SFX_OBJECTFX_ID);
		g_pServerDE->WriteToMessageObject(hMessage, m_hSmokeSource);
		g_pServerDE->WriteToMessageVector(hMessage, &offset);
		g_pServerDE->WriteToMessageFloat(hMessage, 3.0f);
		g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_SCALENUMPARTICLES);
		g_pServerDE->WriteToMessageDWord(hMessage, OBJFX_SMOKING_2);
		g_pServerDE->WriteToMessageDWord(hMessage, 0);
		g_pServerDE->EndMessage(hMessage);

		DRotation rRot;
		ROT_INIT(rRot);

		g_pServerDE->CreateAttachment(m_hObject, m_hSmokeSource, "torso", &offset, &rRot, &m_hAttach);

		m_fSmokeStart = fTime;

		g_pServerDE->DebugOut("SmokeStart: %f\r\n", m_fSmokeStart);
	}
	else if(m_hFireSource == DNULL && m_hSmokeSource && fTime - m_fSmokeStart > 5.0f)
	{
		g_pServerDE->DebugOut("SmokeEnd: %f\r\n", fTime);

		g_pServerDE->RemoveAttachment(m_hAttach);
		g_pServerDE->RemoveObject(m_hSmokeSource);

		m_hSmokeSource = DNULL;
		m_hAttach = DNULL;
	}

	// Done with any death animation
	if (dwState & MS_PLAYDONE)
	{
		CreateBloodPool();

		if (g_pBloodServerShell->IsMultiplayerGame())
			m_fRemoveTime = fTime + CORPSE_REMOVETIME - 0.1f;

		if(m_hAttach == DNULL)
		{
			if (g_pBloodServerShell->IsMultiplayerGame())
				g_pServerDE->SetNextUpdate(m_hObject, CORPSE_REMOVETIME);
			else
				g_pServerDE->SetNextUpdate(m_hObject, 0.0f);
		}
		else
			g_pServerDE->SetNextUpdate(m_hObject, 0.1f);
	}
	else
	{
		g_pServerDE->SetNextUpdate(m_hObject, 0.1f);
	}
	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CCorpse::HandleDamage
//
//	PURPOSE:
//
// ----------------------------------------------------------------------- //

DBOOL CCorpse::HandleDamage(DVector vDir, DFLOAT fDamage, int nType, DVector vPos)
{

//	int nNodeHit = SetProperNode(CalculateHitLimb(vDir,vPos));
	if (!m_hObject) return DFALSE;

	int nNodeHit = -1;

	if(m_bLimbLoss)
	{
		nNodeHit = SetProperNode(CalculateHitLimb(vDir,vPos));

		//sanity check
		if(nNodeHit == -1 && !(nType & DAMAGE_TYPE_EXPLODE))
			return DFALSE;
	}

	if (m_damage.IsDead()) 
	{
		m_bDead = DTRUE;
		CreateGibs(vDir, ((int)m_damage.GetMass())>>5, nType, fDamage);
		// Set update to remove on next frame.
		g_pServerDE->SetNextUpdate(m_hObject, 0.1f);

		if(m_hAttach)
			g_pServerDE->RemoveAttachment(m_hAttach);

		if(m_hFireSource)
		{
			g_pServerDE->RemoveObject(m_hFireSource);
			m_hFireSource = DNULL;
		}

		if(m_hLoopSound)
		{
			g_pServerDE->KillSound(m_hLoopSound);
			m_hLoopSound = DNULL;
		}

		if (IsRandomChance(7))
		{
			g_pPlayerObj->PlayVoiceGroupEventOnClient(VME_BIGGIB, DTRUE);	// [blg]
		}
	}
	else if (nNodeHit >= 0 && nNodeHit < NUM_ALL_NODES && m_bLimbLoss)
	{
		if(IsRandomChance(50) && AIShared.HideLimb(m_hObject,nNodeHit))
		{
			AIShared.CreateLimb(m_hObject, nNodeHit, vDir);
//			AIShared.CreateLimb(vDir);

			//Create an arterial blood spurt
//			CreateBloodSpurt(nNodeHit);
		}
	}

	return DTRUE;
}



// ----------------------------------------------------------------------- //
//
// ROUTINE		: CCorpse::CalculateHitLimb

⌨️ 快捷键说明

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