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

📄 gameprojectiles.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : GameProjectile.cpp
//
// PURPOSE : Game Projectile classs - implementation
//
// CREATED : 10/3/97
//
// ----------------------------------------------------------------------- //

#include "GameProjectiles.h"
#include "cpp_server_de.h"
#include "SharedDefs.h"
#include "ObjectUtilities.h"
#include "ClientSparksSFX.h"
#include "VolumeBrushTypes.h"
#include "Gib.h"
#include "ClientServerShared.h"
#include "ClientExplosionSFX.h"
#include "SFXMsgIds.h"
#include "destructable.h"
#include "PlayerObj.h"

#include "zealotai.h"

#include "stdio.h"
void BPrint(char*);

BEGIN_CLASS(CGrenade)
END_CLASS_DEFAULT_FLAGS(CGrenade, CProjectile, NULL, NULL, CF_HIDDEN)

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGrenade::CGrenade()
//
//	PURPOSE:	Constructor
//
// ----------------------------------------------------------------------- //

CGrenade::CGrenade() : CProjectile()
{
	m_bShockwave			= DFALSE;
	m_bExplosion			= DTRUE;
	m_fLifeTime				= 3.0f;

	m_pProjectileFilename	= "Models\\Ammo\\Grenade.abc";
	m_pProjectileSkin		= "Skins\\Ammo\\Grenade.dtx";

	m_nDamageType			= DAMAGE_TYPE_EXPLODE;

	VEC_SET(m_vShockwaveScaleMin, 0.1f, 0.1f, 0.0f);
	VEC_SET(m_vShockwaveScaleMax, 2.0f, 2.0f, 0.0f);

	m_dwFlags = m_dwFlags | FLAG_GRAVITY;

	// Set up angular velocities
	m_fPitchVel = m_fYawVel = 0.0f;
	m_fPitch	= m_fYaw = 0.0f;
	m_nBounceCount = 5;

	m_hSound		= 0;

	m_dwTrailFXID	= OBJFX_SMOKETRAIL_1;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGrenade::Update()
//
//	PURPOSE:	Do update
//
// ----------------------------------------------------------------------- //

DBOOL CGrenade::Update(DVector *pMovement)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return DFALSE;

	// Play a sound if we don't have one playing already
	if(!m_hSound)
		m_hSound = PlaySoundFromObject(m_hObject, "Sounds\\Weapons\\assault\\projectile.wav", 600.0f, 
			SOUNDPRIORITY_MISC_MEDIUM, DTRUE, DTRUE, DFALSE, 100, DFALSE, DFALSE);

	// Save position for bounce calculations
	pServerDE->GetObjectPos(m_hObject, &m_LastPos);
	DBOOL bRet = CProjectile::Update(pMovement);

	DVector vVel;
	DRotation rRot;

	pServerDE->GetVelocity( m_hObject ,&vVel );
	pServerDE->GetObjectRotation( m_hObject, &rRot );

	// If velocity slows enough, just stop bouncing and just wait to expire.
	if (VEC_MAG(vVel) < 5.0)
	{
		m_fPitchVel = 0;
		m_fYawVel = 0;

		// Stop the spinning
		pServerDE->SetupEuler(&rRot, 0, m_fYaw, 0);
		pServerDE->SetObjectRotation(m_hObject, &rRot);	
	}
	else
	{
		if (m_fPitchVel != 0 || m_fYawVel != 0)
		{
			DFLOAT fDeltaTime = pServerDE->GetFrameTime();

			m_fPitch += m_fPitchVel * fDeltaTime;
			m_fYaw += m_fYawVel * fDeltaTime;

			pServerDE->SetupEuler(&rRot, m_fPitch, m_fYaw, 0.0f);
			pServerDE->SetObjectRotation(m_hObject, &rRot);	
		}
	}

	// We've expired, explode now if we're a grenade.
	if (!bRet && m_dwFlags & FLAG_GRAVITY || m_damage.IsDead())
	{
		if(m_hSound)
			{ pServerDE->KillSound(m_hSound); m_hSound = 0; }

		Explode();
	}

	return bRet;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGrenade::HandleTouch()
//
//	PURPOSE:	Handle touch notify message
//
// ----------------------------------------------------------------------- //

void CGrenade::HandleTouch(HOBJECT hObj)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return;

	if ((m_nBounceCount == 5) && pServerDE->IsKindOf(pServerDE->GetObjectClass(hObj), pServerDE->GetClass("CBaseCharacter")))
	{
		CBaseCharacter *pObj = (CBaseCharacter*)pServerDE->HandleToObject(hObj);
		if(pObj->IsDead())	return;

		CProjectile::HandleTouch(hObj);	// Explode on impact type.
	}
	else  // Gravity on, so it's a regular grenade.. bounce it off of stuff
	{
		if (hObj == m_hFiredFrom) return; // Let it get out of our bounding box...

		// return if it hit a non solid object
		if (hObj != pServerDE->GetWorldObject() && !(pServerDE->GetObjectFlags(hObj) & FLAG_SOLID)) // Ignore non-solid objects
			return;

		if (m_nBounceCount <= 0) return;

 		// Cast a ray from our last known position to see what we hit
		DVector vVel, vPos;

		pServerDE->GetVelocity(m_hObject, &vVel);
		pServerDE->GetObjectPos( m_hObject, &vPos );

		CollisionInfo colInfo;
		pServerDE->GetLastCollision( &colInfo );

		// Compute new velocity reflected off of the surface.
		DVector vNormal;
		if( colInfo.m_hPoly )
		{
			VEC_COPY(vNormal, colInfo.m_Plane.m_Normal);

			DFLOAT r = ( VEC_DOT(vVel, vNormal) * 0.3f );
			VEC_MULSCALAR(vNormal, vNormal, r);

			// Play a bounce sound...
			PlaySoundFromObject(m_hObject, "Sounds\\Weapons\\assault\\altbounce.wav", 750, SOUNDPRIORITY_MISC_MEDIUM);

			VEC_SUB(vVel, vVel, vNormal);

			// Adjust the bouncing..
			m_fPitchVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE);
			m_fYawVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE);

			VEC_MULSCALAR(vVel, vVel, 0.5f);	// Lose some energy in the bounce.
			pServerDE->SetVelocity(m_hObject, &vVel);

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

			// Play a bounce sound...
			PlaySoundFromObject(m_hObject, "Sounds\\Weapons\\assault\\altbounce.wav", 750, SOUNDPRIORITY_MISC_MEDIUM);

		}
		m_nBounceCount--;
	}
}

#ifdef _ADD_ON

BEGIN_CLASS(CGasGrenade)
END_CLASS_DEFAULT_FLAGS(CGasGrenade, CProjectile, NULL, NULL, CF_HIDDEN)

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGasGrenade::CGasGrenade()
//
//	PURPOSE:	Constructor
//
// ----------------------------------------------------------------------- //

CGasGrenade::CGasGrenade() : CProjectile()
{
	m_bShockwave			= DFALSE;
	m_bExplosion			= DTRUE;
	m_fLifeTime				= 3.0f;

	m_pProjectileFilename	= "Models\\Ammo\\Grenade.abc";
	m_pProjectileSkin		= "Skins\\Ammo\\Grenade.dtx";

	m_nDamageType			= DAMAGE_TYPE_EXPLODE;

	VEC_SET(m_vShockwaveScaleMin, 0.1f, 0.1f, 0.0f);
	VEC_SET(m_vShockwaveScaleMax, 2.0f, 2.0f, 0.0f);

	m_dwFlags = m_dwFlags | FLAG_GRAVITY;

	// Set up angular velocities
	m_fPitchVel = m_fYawVel = 0.0f;
	m_fPitch	= m_fYaw = 0.0f;
	m_nBounceCount	= 5;

	m_bSmoking			= DFALSE;
	m_fSmokeTime		= 0.0f;
	m_hSound			= 0;

	m_dwTrailFXID		= OBJFX_GREEN_SMOKE;
	m_fLastWonkyTime	= 0.0f;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGasGrenade::Update()
//
//	PURPOSE:	Do update
//
// ----------------------------------------------------------------------- //

DBOOL CGasGrenade::Update(DVector *pMovement)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return DFALSE;

	// Play a sound if we don't have one playing already
	if(!m_hSound && !m_bSmoking)
		m_hSound = PlaySoundFromObject(m_hObject, "Sounds\\Weapons\\assault\\projectile.wav", 600.0f, SOUNDPRIORITY_MISC_MEDIUM, DTRUE, DTRUE, DFALSE, 100, DFALSE, DFALSE);

	// See if we should blow up yet...
	pServerDE->SetNextUpdate(m_hObject, (DFLOAT)0.001);

	// Damage anyone who gets close to the smoke and give them wonky vision
	// **** NOTE: THIS MUST BE BEFORE THE NEXT TWO CHECKS ****
	if(m_bSmoking)
	{
		DFLOAT fTime = pServerDE->GetTime();

		if(fTime > (m_fSmokeTime + GAS_GRENADE_SMOKE_TIME))
			return DFALSE;

		if(fTime > (m_fLastWonkyTime + GAS_GRENADE_DAMAGE_DELAY))
		{
			m_fLastWonkyTime = fTime;
			DamageAndWonky(WONKY_VISION_DEFAULT_TIME);
		}

		return DTRUE;
	}

	if((m_fLifeTime > 0) && (pServerDE->GetTime() > (m_fStartTime + m_fLifeTime)))
		m_bExplode = DTRUE;

	if(m_bExplode || m_damage.IsDead())
	{
		if(m_hSound)
			{ pServerDE->KillSound(m_hSound); m_hSound = 0; }

		m_bSmoking = DTRUE;
		m_fSmokeTime = pServerDE->GetTime();
		Explode();

		// Turn off the gravity for the object and make it invisible
		DDWORD	dwFlags = pServerDE->GetObjectFlags(m_hObject);
		dwFlags &= ~(FLAG_GRAVITY | FLAG_VISIBLE);
		pServerDE->SetObjectFlags(m_hObject, dwFlags);

		// Stop the object in its current position
		DVector vVel;
		VEC_INIT(vVel);
		pServerDE->SetVelocity( m_hObject, &vVel );
	}

	// Save position for bounce calculations
	pServerDE->GetObjectPos(m_hObject, &m_LastPos);
	DBOOL bRet = CProjectile::Update(pMovement);

	DVector vVel;
	DRotation rRot;

	pServerDE->GetVelocity( m_hObject ,&vVel );
	pServerDE->GetObjectRotation( m_hObject, &rRot );

	// If velocity slows enough, just stop bouncing and just wait to expire.
	if (VEC_MAG(vVel) < 5.0)
	{
		m_fPitchVel = 0;
		m_fYawVel = 0;

		// Stop the spinning
		pServerDE->SetupEuler(&rRot, 0, m_fYaw, 0);
		pServerDE->SetObjectRotation(m_hObject, &rRot);	
	}
	else
	{
		if (m_fPitchVel != 0 || m_fYawVel != 0)
		{
			DFLOAT fDeltaTime = pServerDE->GetFrameTime();

			m_fPitch += m_fPitchVel * fDeltaTime;
			m_fYaw += m_fYawVel * fDeltaTime;

			pServerDE->SetupEuler(&rRot, m_fPitch, m_fYaw, 0.0f);
			pServerDE->SetObjectRotation(m_hObject, &rRot);	
		}
	}

	return DTRUE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGasGrenade::HandleTouch()
//
//	PURPOSE:	Handle touch notify message
//
// ----------------------------------------------------------------------- //

void CGasGrenade::HandleTouch(HOBJECT hObj)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return;

	if (hObj == m_hFiredFrom) return; // Let it get out of our bounding box...

	// return if it hit a non solid object
	if (hObj != pServerDE->GetWorldObject() && !(pServerDE->GetObjectFlags(hObj) & FLAG_SOLID)) // Ignore non-solid objects
		return;

	// See if we hit the sky...
	HCLASS hClassObj	= pServerDE->GetObjectClass(hObj);
	HCLASS hClassWorld  = pServerDE->GetObjectClass(pServerDE->GetWorldObject());
	if (pServerDE->IsKindOf(hClassObj, hClassWorld))
	{
		CollisionInfo info;
		pServerDE->GetLastCollision(&info);

		SurfaceType eType = GetSurfaceType(info.m_hObject, info.m_hPoly);

		if (eType == SURFTYPE_SKY)
		{
			pServerDE->RemoveObject(m_hObject);
			return;
		}
	}

	// Handle the special case of directly hitting a base character in mid air
	if ((m_nBounceCount == 5) && pServerDE->IsKindOf(pServerDE->GetObjectClass(hObj), pServerDE->GetClass("CBaseCharacter")))
	{
		CBaseCharacter *pObj = (CBaseCharacter*)pServerDE->HandleToObject(hObj);
		if(pObj->IsDead())	return;

		m_bExplode = DTRUE;
		m_hHitObject = hObj;
	}
	else  // Gravity on, so it's a regular grenade.. bounce it off of stuff
	{
		if (m_nBounceCount <= 0) return;

 		// Cast a ray from our last known position to see what we hit
		DVector vVel, vPos;

		pServerDE->GetVelocity(m_hObject, &vVel);
		pServerDE->GetObjectPos( m_hObject, &vPos );

		CollisionInfo colInfo;
		pServerDE->GetLastCollision( &colInfo );

		// Compute new velocity reflected off of the surface.
		DVector vNormal;
		if( colInfo.m_hPoly )
		{
			VEC_COPY(vNormal, colInfo.m_Plane.m_Normal);

			DFLOAT r = ( VEC_DOT(vVel, vNormal) * 0.3f );
			VEC_MULSCALAR(vNormal, vNormal, r);

			// Play a bounce sound...
			PlaySoundFromObject(m_hObject, "Sounds\\Weapons\\assault\\altbounce.wav", 750, SOUNDPRIORITY_MISC_MEDIUM);

			VEC_SUB(vVel, vVel, vNormal);

			// Adjust the bouncing..
			m_fPitchVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE);
			m_fYawVel = pServerDE->Random(-MATH_CIRCLE, MATH_CIRCLE);

			VEC_MULSCALAR(vVel, vVel, 0.5f);	// Lose some energy in the bounce.
			pServerDE->SetVelocity(m_hObject, &vVel);

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

			// Play a bounce sound...
			PlaySoundFromObject(m_hObject, "Sounds\\Weapons\\assault\\altbounce.wav", 750, SOUNDPRIORITY_MISC_MEDIUM);

		}

		m_nBounceCount--;
	}
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGasGrenade::AddExplosion()
//
//	PURPOSE:	Add an explosion
//
// ----------------------------------------------------------------------- //

void CGasGrenade::AddExplosion(DVector vPos, DVector vNormal)
{
	CServerDE* pServerDE = BaseClass::GetServerDE();
	if (!pServerDE) return;

	DDWORD		nType = EXP_GAS_GRENADE;
	DVector		vUp;
	VEC_SET(vUp, 0.0f, 1.0f, 0.0f);

	HMESSAGEWRITE hMessage = pServerDE->StartInstantSpecialEffectMessage(&vPos);
	pServerDE->WriteToMessageByte(hMessage, SFX_EXPLOSIONFX_ID);

	pServerDE->WriteToMessageVector(hMessage, &vPos);
	pServerDE->WriteToMessageVector(hMessage, &vUp);
	pServerDE->WriteToMessageDWord(hMessage, nType);

	pServerDE->EndMessage2(hMessage, MESSAGE_GUARANTEED);

	PlaySoundFromPos(&vPos, "Sounds\\Weapons\\c4\\explosion_1.wav", 1000.0f, SOUNDPRIORITY_MISC_MEDIUM);

⌨️ 快捷键说明

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