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

📄 gibfx.cpp

📁 Blood 2全套源码
💻 CPP
字号:

// ----------------------------------------------------------------------- //
//
// MODULE  : GibFX.cpp
//
// PURPOSE : Gib special FX - Implementation
//
// CREATED : 8/3/98
//
// ----------------------------------------------------------------------- //

#include "gibfx.h"
#include "cpp_client_de.h"
#include "dlink.h"
#include "BloodClientShell.h"
#include "ClientUtilities.h"
#include "bloodsplatfx.h"
#include "ParticleExplosionFX.h"
#include "SoundTypes.h"

#define GIBS_FLESH		8
#define GIBS_WOOD		4
#define GIBS_GLASS		3
#define GIBS_METAL		5
#define GIBS_PLASTIC	5
#define GIBS_STONE		9
#define GIBS_TERRAIN	5

#define SOUNDS_FLESH	5
#define SOUNDS_WOOD		5
#define SOUNDS_GLASS	5
#define SOUNDS_METAL	5
#define SOUNDS_PLASTIC	5
#define SOUNDS_STONE	5
#define SOUNDS_TERRAIN	5




// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGibFX::Init
//
//	PURPOSE:	Create the gib
//
// ----------------------------------------------------------------------- //

DBOOL CGibFX::Init(SFXCREATESTRUCT* psfxCreateStruct)
{
	if (!psfxCreateStruct) return DFALSE;

	CSpecialFX::Init(psfxCreateStruct);

	GIBCREATESTRUCT* pGib = (GIBCREATESTRUCT*)psfxCreateStruct;

	VEC_COPY( m_vPos, pGib->m_Pos);
	VEC_COPY( m_vDir, pGib->m_Dir);
	VEC_COPY( m_vDims, pGib->m_Dims);
	m_dwFlags = pGib->m_dwFlags;
	m_fScale = pGib->m_fScale;

	m_nBounceCount = 1;

	DFLOAT fVel = VEC_MAG(m_vDir);

	VEC_MULSCALAR(m_vDims, m_vDims, 0.8f);
	if (m_vDims.x)
		m_vPos.x += GetRandom(-m_vDims.x, m_vDims.x);
	if (m_vDims.z)
		m_vPos.z += GetRandom(-m_vDims.z, m_vDims.z);

	m_nType = (m_dwFlags & TYPE_MASK) * 10;

	VEC_NORM(m_vDir);

	// Don't blow glass straight up quite so much
	if (m_nType == SURFTYPE_GLASS)
	{
		VEC_SET(m_vMinVel, -fVel, 0, -fVel)
		VEC_SET(m_vMaxVel, fVel, fVel*2, fVel)

		if (m_vDims.y)
			m_vPos.y += GetRandom(-m_vDims.y, m_vDims.y);
	}
	else
	{
		VEC_SET(m_vMinVel, -fVel, 0, -fVel)
		VEC_SET(m_vMaxVel, fVel, fVel*4, fVel)

		if (m_vDims.y)
			m_vPos.y += GetRandom(-m_vDims.y/2, m_vDims.y);
	}


	m_fPitchVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE);
	m_fYawVel	= GetRandom(-MATH_CIRCLE, MATH_CIRCLE);

	if (m_dwFlags & TYPEFLAG_CUSTOM)
	{
		m_hstrModel = pGib->m_hstrModel;
		m_hstrSkin  = pGib->m_hstrSkin;
		m_hstrSound = pGib->m_hstrSound;
	}

	return DTRUE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGibFX::Term
//
//	PURPOSE:	Term
//
// ----------------------------------------------------------------------- //

DBOOL CGibFX::Term()
{
	m_bFade = DTRUE;

	return DFALSE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGibFX::CreateObject
//
//	PURPOSE:	Create object associated with the mark
//
// ----------------------------------------------------------------------- //

DBOOL CGibFX::CreateObject(CClientDE *pClientDE)
{
	if (!CSpecialFX::CreateObject(pClientDE)) return DFALSE;

	CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
	if (!pShell) return DFALSE;
	CSFXMgr* psfxMgr = pShell->GetSFXMgr();
	if (!psfxMgr) return DFALSE;

	m_pClientDE->AlignRotation(&m_Rotation, &m_vDir, DNULL);

	// Determine the filenames to use
	int index;
	DBOOL bRandomizeScale = DFALSE;

	moveObj.m_PhysicsFlags = MO_HALFGRAVITY;

	ObjectCreateStruct createStruct;
	INIT_OBJECTCREATESTRUCT(createStruct);
	createStruct.m_ObjectType = OT_MODEL;

	char szSound[MAX_CS_FILENAME_LEN+1];
	char szFilename[MAX_CS_FILENAME_LEN+1];
	_mbscpy((unsigned char*)szFilename, (const unsigned char*)"");

	// Determine the file to use
	if (!(m_dwFlags & TYPEFLAG_CUSTOM))
	{
		switch (m_nType)
		{
			case SURFTYPE_FLESH:
				{
					index = GetRandom(1, NRES(GIBS_FLESH));
					sprintf(szFilename, "flesh\\gib%d", index);
					bRandomizeScale = DTRUE;
					m_nBounceCount = (GetRandom(0, 4) == 4) ? 1 : 0;	// Stick the wall 20% of the time
					moveObj.m_PhysicsFlags |= MO_STICKY;

					index = GetRandom(1, NRES(SOUNDS_FLESH));
					sprintf(szSound, "sounds\\gibs\\flesh\\gib_impact%d.wav", index);
				}
				break;

			case SURFTYPE_GLASS:
				{
					index = GetRandom(1, NRES(GIBS_GLASS));
					sprintf(szFilename, "glass\\gib%d", index);
					bRandomizeScale = DTRUE;
					m_nBounceCount = 1;

					index = GetRandom(1, NRES(SOUNDS_GLASS));
					sprintf(szSound, "sounds\\gibs\\glass\\gib_impact%d.wav", index);
				}
				break;

			case SURFTYPE_WOOD:
				{
					index = GetRandom(1, NRES(GIBS_WOOD));
					sprintf(szFilename, "wood\\gib%d", index);
					bRandomizeScale = DFALSE;
					m_nBounceCount = 1;

					index = GetRandom(1, NRES(SOUNDS_WOOD));
					sprintf(szSound, "sounds\\gibs\\wood\\gib_impact%d.wav", index);
				}
				break;

			case SURFTYPE_STONE:
				{
					index = GetRandom(1, NRES(GIBS_STONE));
					sprintf(szFilename, "stone\\gib%d", index);
					bRandomizeScale = DTRUE;
					m_nBounceCount = 2;

					index = GetRandom(1, NRES(SOUNDS_STONE));
					sprintf(szSound, "sounds\\gibs\\stone\\gib_impact%d.wav", index);
				}
				break;

			case SURFTYPE_PLASTIC:
				{
					index = GetRandom(1, NRES(GIBS_PLASTIC));
					sprintf(szFilename, "plastic\\gib%d", index);
					bRandomizeScale = DTRUE;
					m_nBounceCount = 2;

					index = GetRandom(1, NRES(SOUNDS_PLASTIC));
					sprintf(szSound, "sounds\\gibs\\plastic\\gib_impact%d.wav", index);
				}
				break;

			case SURFTYPE_TERRAIN:
				{
					index = GetRandom(1, NRES(GIBS_TERRAIN));
					sprintf(szFilename, "terrain\\gib%d", index);
					bRandomizeScale = DTRUE;
					m_nBounceCount = 2;

					index = GetRandom(1, NRES(SOUNDS_TERRAIN));
					sprintf(szSound, "sounds\\gibs\\terrain\\gib_impact%d.wav", index);
				}
				break;

			case SURFTYPE_METAL:
			default:
				{
					index = GetRandom(1, NRES(GIBS_METAL));
					sprintf(szFilename, "metal\\gib%d", index);
					bRandomizeScale = DFALSE;
					m_nBounceCount = 1;

					index = GetRandom(1, NRES(SOUNDS_METAL));
					sprintf(szSound, "sounds\\gibs\\metal\\gib_impact%d.wav", index);
				}
				break;
		}

		if (!szFilename)
			return DFALSE;

		if (bRandomizeScale)
		{
			if (m_nType == SURFTYPE_FLESH)
			{
				VEC_SET(createStruct.m_Scale, GetRandom(0.8f, 1.35f), GetRandom(0.8f, 1.35f), GetRandom(0.8f, 1.35f));
			}
			else
			{
				VEC_SET(createStruct.m_Scale, GetRandom(0.5f, 1.25f), GetRandom(0.5f, 1.25f), GetRandom(0.5f, 1.25f));
			}
		}

		VEC_MULSCALAR(createStruct.m_Scale, createStruct.m_Scale, m_fScale);

		if (_mbstrlen(szSound) && !m_hstrSound)
		{
			m_hstrSound = m_pClientDE->CreateString(szSound);
		}
	}

	// Custom or normal?
	if (m_hstrModel)
		_mbscpy((unsigned char*)createStruct.m_Filename, (const unsigned char*)m_pClientDE->GetStringData(m_hstrModel));
	else
		sprintf(createStruct.m_Filename, "models\\gibs\\%s.abc", szFilename);		
	
	if (m_hstrSkin)
		_mbscpy((unsigned char*)createStruct.m_SkinName, (const unsigned char*)m_pClientDE->GetStringData(m_hstrSkin));
	else
		sprintf(createStruct.m_SkinName, "skins\\gibs\\%s.dtx", szFilename);

	createStruct.m_Flags	  = FLAG_VISIBLE;
	VEC_COPY(createStruct.m_Pos, m_vPos);

	m_hObject = pClientDE->CreateObject(&createStruct);

	// Make glass transparent
	if (m_nType == SURFTYPE_GLASS)
		m_pClientDE->SetObjectColor(m_hObject, 0.0f, 0.0f, 0.0f, 0.4f);
	
	if(m_dwFlags & TRAIL_BLOOD)
	{
		m_bBlood = DTRUE;
	}
	else if(m_dwFlags & TRAIL_SMOKE)
	{
		m_bSmoke = DTRUE;
	}

	//initialize velocity
	DVector vVelMin, vVelMax, vTemp, vU, vR, vF;
	VEC_SET(vVelMin, 1.0f, 1.0f, 1.0f);
	VEC_SET(vVelMax, 1.0f, 1.0f, 1.0f);

	m_pClientDE->GetRotationVectors(&m_Rotation, &vU, &vR, &vF);

	if (vF.y <= -0.95f || vF.y >= 0.95f)
	{
		vF.y = vF.y > 0.0f ? 1.0f : -1.0f;
		VEC_SET(vR, 1.0f, 0.0f, 0.0f);
		VEC_SET(vU, 0.0f, 0.0f, 1.0f);
	}
	else if (vF.x <= -0.95f || vF.x >= 0.95f)
	{
		vF.x = vF.x > 0.0f ? 1.0f : -1.0f;
		VEC_SET(vR, 0.0f, 1.0f, 0.0f);
		VEC_SET(vU, 0.0f, 0.0f, 1.0f);
	}
	else if (vF.z <= -0.95f || vF.z >= 0.95f)
	{
		vF.z = vF.z > 0.0f ? 1.0f : -1.0f;
		VEC_SET(vR, 1.0f, 0.0f, 0.0f);
		VEC_SET(vU, 0.0f, 1.0f, 0.0f);
	}

	VEC_MULSCALAR(vVelMin, vF, m_vMinVel.y); 
	VEC_MULSCALAR(vVelMax, vF, m_vMaxVel.y); 

	VEC_MULSCALAR(vTemp, vR, m_vMinVel.x);
	VEC_ADD(vVelMin, vVelMin, vTemp);

	VEC_MULSCALAR(vTemp, vR, m_vMaxVel.x);
	VEC_ADD(vVelMax, vVelMax, vTemp);

	VEC_MULSCALAR(vTemp, vU, m_vMinVel.z);
	VEC_ADD(vVelMin, vVelMin, vTemp);

	VEC_MULSCALAR(vTemp, vU, m_vMaxVel.z);
	VEC_ADD(vVelMax, vVelMax, vTemp);

	DVector vStartVel;
	VEC_SET(vStartVel, GetRandom(vVelMin.x, vVelMax.x), 
					   GetRandom(vVelMin.y, vVelMax.y), 
					   GetRandom(vVelMin.z, vVelMax.z));

	InitMovingObject(&moveObj, &m_vPos, &vStartVel);

	if (m_bBlood)
		CreateBloodSpurt(&vStartVel);

	return DTRUE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGibFX::Update
//
//	PURPOSE:	Update the mark
//
// ----------------------------------------------------------------------- //

DBOOL CGibFX::Update()
{
	if(!m_hObject || !m_pClientDE) return DFALSE;

	//fade the object out of existence
	if(m_bFade)
	{
		if(m_fScaleCount >= 150.0f)
			return DFALSE;

		DFLOAT fAlpha = 0.0f;
		DVector vColor;
		
		m_pClientDE->GetObjectColor(m_hObject,&vColor.x, &vColor.y, &vColor.z, &fAlpha);
		m_pClientDE->SetObjectColor(m_hObject,vColor.x,vColor.y,vColor.z,1.0f - (m_fScaleCount/150.0f));
		m_fScaleCount++;

		return DTRUE;
	}

	DBOOL bBounced = DFALSE;

	ClientIntersectInfo info;

	if(moveObj.m_PhysicsFlags & MO_RESTING)
	{
		return DTRUE;
	}
	else if(bBounced = UpdateMovement(&moveObj, &info))
	{

		PlaySoundFromPos(&moveObj.m_Pos, m_pClientDE->GetStringData(m_hstrSound), 750.0f,SOUNDPRIORITY_MISC_LOW);

		if (m_bBlood)
			CreateBloodSplat(&moveObj.m_Pos, &info);

		// Don't count bounces off the ceiling
		if (info.m_Plane.m_Normal.y > 0)
		{
			if (m_nBounceCount <= 0)
			{
				moveObj.m_PhysicsFlags |= MO_RESTING;
			}
			m_nBounceCount--;
		}
		else
		{
			moveObj.m_PhysicsFlags &= ~MO_RESTING;
		}

		m_pClientDE->SetObjectPos(m_hObject, &(moveObj.m_Pos));

		// Adjust due to the bounce...

		m_fPitchVel = GetRandom(-MATH_CIRCLE, MATH_CIRCLE);
		m_fYawVel	= GetRandom(-MATH_CIRCLE, MATH_CIRCLE);
	}
	else
	{
		//rotate the object
		if (m_fPitchVel != 0 || m_fYawVel != 0)
		{
			DFLOAT fDeltaTime = m_pClientDE->GetFrameTime();

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

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

		m_pClientDE->SetObjectPos(m_hObject, &(moveObj.m_Pos));

		if(m_bBlood)
		{
		}
	}

	return DTRUE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGibFX::UpdateMovement
//
//	PURPOSE:	Update position
//
// ----------------------------------------------------------------------- //

DBOOL CGibFX::UpdateMovement(MovingObject* pObject, ClientIntersectInfo* pInfo)
{	
	if (!m_pClientDE || !pObject || pObject->m_PhysicsFlags & MO_RESTING) return DFALSE;

	DBOOL bRet = DFALSE;

	DVector vNewPos;

	if (UpdateMovingObject(DNULL, pObject, &vNewPos))
	{
//		SurfaceType eType = SURFTYPE_UNKNOWN;
//		bRet = BounceMovingObject(DNULL, pObject, &vNewPos, pInfo, &eType);
		bRet = BounceMovingObject(DNULL, pObject, &vNewPos, pInfo);

		VEC_COPY(pObject->m_LastPos, pObject->m_Pos);
		VEC_COPY(pObject->m_Pos, vNewPos);

		if (m_pClientDE->GetPointStatus(&vNewPos) != DE_INSIDE)
		{
			pObject->m_PhysicsFlags |= MO_RESTING;
		}
	}

	return bRet;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGibFX::UpdateMovement
//
//	PURPOSE:	Update position
//
// ----------------------------------------------------------------------- //

DBOOL CGibFX::CreateBloodSpurt(DVector *pvDir)
{
	CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
	if (!pShell) return DFALSE;
	CSFXMgr* psfxMgr = pShell->GetSFXMgr();
	if (!psfxMgr) return DFALSE;

	char* szBlood[4] = { "spritetextures\\particles\\blooddrop_1.dtx", 
						 "spritetextures\\particles\\blooddrop_2.dtx",
						 "spritetextures\\particles\\blooddrop_3.dtx",
						 "spritetextures\\particles\\blooddrop_4.dtx"};

	PESCREATESTRUCT pe;

	VEC_MULSCALAR(pe.vMinVel, *pvDir, 0.6f);
	VEC_MULSCALAR(pe.vMaxVel, *pvDir, 0.6f);

	VEC_COPY(pe.vPos, m_vPos);
//	ROT_COPY(pe.rSurfaceRot, m_rRotation);
	VEC_SET(pe.vColor1, 128.0f, 128.0f, 128.0f);
	VEC_SET(pe.vColor2, 128.0f, 128.0f, 128.0f);
	VEC_SET(pe.vMinDriftOffset, 0.0f, -10.0f, 0.0f);
	VEC_SET(pe.vMaxDriftOffset, 0.0f, -5.0f, 0.0f);
	pe.bSmall			= DFALSE;
	pe.fLifeTime		= 2.0f;
	pe.fFadeTime		= 0.5f;
	pe.fOffsetTime		= 0.0f;
	pe.fRadius			= 200.0f;
	pe.fGravity			= -100.0f;
	pe.nNumPerPuff		= 2;
	pe.nNumEmitters		= 1; //GetRandom(1,4);
	pe.nEmitterFlags	= MO_HALFGRAVITY;
	pe.bIgnoreWind		= DTRUE;
	pe.pFilename		= szBlood[GetRandom(0,2)];
	pe.nSurfaceType		= SURFTYPE_FLESH;
	pe.nNumSteps		= 6;
	pe.bBounce			= DFALSE;


	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_PARTICLEEXPLOSION_ID, &pe, DFALSE, this);
	if (pFX) 
	{
		CBaseParticleSystemFX* pBasePS = (CBaseParticleSystemFX*)pFX;
		pBasePS->m_bSetSoftwareColor = DFALSE;

		pFX->Update();
		m_pClientDE->SetSoftwarePSColor(pFX->GetObject(), 1.0f, 0.0f, 0.0f);
	}

	return DTRUE;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CGibFX::CreateBloodSplat
//
//	PURPOSE:	Create a blood splat
//
// ----------------------------------------------------------------------- //

void CGibFX::CreateBloodSplat(DVector *pvPos, ClientIntersectInfo *pInfo)
{
	CBloodClientShell *pShell = (CBloodClientShell*)g_pClientDE->GetClientShell();
	if (!pShell) return;
	CSFXMgr* psfxMgr = pShell->GetSFXMgr();
	if (!psfxMgr) return;

	BSCREATESTRUCT splat;
	char* pSplatSprite = DNULL;

	switch(GetRandom(1,3))
	{
		case 1:		pSplatSprite = "sprites\\blood1.spr";	break;
		case 2:		pSplatSprite = "sprites\\blood2.spr";	break;
		case 3:		pSplatSprite = "sprites\\blood3.spr";	break;
		default:	pSplatSprite = "sprites\\blood1.spr";	break;
	}

	VEC_COPY(splat.m_Pos, *pvPos);
	m_pClientDE->AlignRotation(&splat.m_Rotation, &pInfo->m_Plane.m_Normal, &pInfo->m_Plane.m_Normal);
	splat.m_fScale = 0.14f + GetRandom(-0.1f,0.1f);
	splat.m_hstrSprite = m_pClientDE->CreateString(pSplatSprite);
	
	if(pInfo->m_Plane.m_Normal.y >= 0.5f)
		splat.m_fGrowScale = 0.01f;

	psfxMgr->CreateSFX(SFX_BLOODSPLAT_ID, &splat, DFALSE, this);
	g_pClientDE->FreeString( splat.m_hstrSprite );
}

⌨️ 快捷键说明

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