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

📄 objectfx.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : ObjectFX.cpp
//
// PURPOSE : General object special FX - Implementation
//
// CREATED : 8/25/98
//
// ----------------------------------------------------------------------- //

#include "ObjectFX.h"
#include "SFXMsgIds.h"
#include "cpp_client_de.h"
#include "ClientUtilities.h"
#include "BloodClientShell.h"

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CObjectParticleFX::Init
//
//	PURPOSE:	Init the system
//
// ----------------------------------------------------------------------- //

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

	OBJECTPARTICLEFXCS* pPS = (OBJECTPARTICLEFXCS*)psfxCreateStruct;

	m_hObj				= pPS->hObj;
	VEC_COPY(m_vOffset, pPS->vOffset);
	m_fRampUpTime		= pPS->fRampUpTime;
	m_fRampDownTime		= pPS->fRampDownTime;
	m_fDuration			= pPS->fDuration;
	m_fAddDelay			= pPS->fAddDelay;
	m_fRadius			= pPS->fRadius;
	m_fGravity			= pPS->fGravity;
	VEC_COPY(m_vRotations, pPS->vRotations);
	m_fPosRadius		= pPS->fPosRadius;
	m_nEmitType			= pPS->nEmitType;
	m_nNumParticles		= pPS->nNumParticles;
	m_fDensity			= pPS->fDensity;
	m_fAlpha			= pPS->fAlpha;
	VEC_COPY(m_vColor1, pPS->vMinColor);
	VEC_COPY(m_vColor2, pPS->vMaxColor);
	m_fMinVelocity		= pPS->fMinVelocity;
	m_fMaxVelocity		= pPS->fMaxVelocity;
	m_fMinLifetime		= pPS->fMinLifetime;
	m_fMaxLifetime		= pPS->fMaxLifetime;
	m_nRampUpType		= pPS->nRampUpType;
	m_nRampDownType		= pPS->nRampDownType;
	m_nFXFlags			= pPS->nFXFlags;
	m_szParticle		= pPS->szParticle;
	VEC_INIT(m_vPos);

	m_bMove				= DTRUE;
	m_bFirstStop		= DTRUE;
	m_fStopTime			= 0.0f;
	return DTRUE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CObjectParticleFX::CreateObject
//
//	PURPOSE:	Create object associated the particle system.
//
// ----------------------------------------------------------------------- //

DBOOL CObjectParticleFX::CreateObject(CClientDE *pClientDE)
{
	if(!pClientDE || !m_hObj) return DFALSE;

	if(m_szParticle)	m_pTextureName = pClientDE->GetStringData(m_szParticle);
		else			m_pTextureName = "SpriteTextures\\smoke64_2.dtx";

	DBOOL bRet = CBaseParticleSystemFX::CreateObject(pClientDE);

//	pClientDE->SetObjectClientFlags(m_hObj, pClientDE->GetObjectClientFlags(m_hObj)|CF_NOTIFYREMOVE);

	// Setup the initial position variables for the object
	m_pClientDE->GetObjectPos(m_hObj, &m_vPos);
	m_pClientDE->SetObjectPos(m_hObject, &m_vPos);

//	m_pClientDE->GetObjectRotation(m_hObj, &m_rLastRot);

	VEC_COPY(m_vLastPos, m_vPos);
	VEC_COPY(m_vLastObjPos, m_vPos);
	VEC_COPY(m_vOrigin, m_vPos);

	m_fStartTime = m_pClientDE->GetTime();
	return bRet;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CObjectParticleFX::Update
//
//	PURPOSE:	Update the particles
//
// ----------------------------------------------------------------------- //

DBOOL CObjectParticleFX::Update()
{
	if(!m_hObject || !m_pClientDE || !m_hObj || !m_hServerObject)
		return DFALSE;

	DFLOAT		fTime = m_pClientDE->GetTime() - m_fStartTime;
	DVector		vU, vR, vF;
	DRotation	rRot;

	// Initialize some data during the first update...
	if(m_bFirstUpdate)
	{
		m_fLastAddTime = 0.0f;
		m_bFirstUpdate = 0;
		return DTRUE;
	}

	// See if we should delete the FX
	if(m_fDuration)
	{
		if(m_fDuration < fTime)
			return DFALSE;
	}
	else
	{
		if(!g_pBloodClientShell->IsMultiplayerGame())
		{
			DVector	vPos;
			m_pClientDE->GetObjectPos(m_hObj, &vPos);

			if(m_nFXFlags & OBJPSFX_REMOVESTOPPED)
			{
				DVector	vVel;
				VEC_SUB(vVel, vPos, m_vLastObjPos);

				if((vVel.x == 0.0f) && (vVel.y == 0.0f) && (vVel.z == 0.0f))
				{
					m_bMove = DFALSE;

					if(m_nFXFlags & OBJPSFX_RAMPDOWNSTOPPED)
						m_fDuration = fTime + m_fRampDownTime + m_fMaxLifetime;
					else
						return DFALSE;
				}
			}

			VEC_COPY(m_vLastObjPos, vPos);
		}
		else
		{
			DVector	vPos;
			m_pClientDE->GetObjectPos(m_hObj, &vPos);

			if(m_nFXFlags & OBJPSFX_REMOVESTOPPED)
			{
				DVector	vVel;
				VEC_SUB(vVel, vPos, m_vLastObjPos);

				if((vVel.x == 0.0f) && (vVel.y == 0.0f) && (vVel.z == 0.0f))
				{
					m_bMove = DFALSE;

					if(m_bFirstStop)
					{
						m_fStopTime = m_pClientDE->GetTime();
						m_bFirstStop = DFALSE;
					}

					if(m_pClientDE->GetTime() > m_fStopTime + 1.0f)
					{
						if(m_nFXFlags & OBJPSFX_RAMPDOWNSTOPPED)
							m_fDuration = fTime + m_fRampDownTime + m_fMaxLifetime;
						else
							return DFALSE;
					}
				}
				else
				{
					m_bFirstStop = DTRUE;
					m_bMove = DTRUE;
				}
			}

			VEC_COPY(m_vLastObjPos, vPos);
		}
	}

	//*********************************************************************
	// Set the ramp state and ratio
	//*********************************************************************

	if(m_nRampUpType && m_fDuration && (fTime <= m_fRampUpTime))
	{
		m_fRampRatio = fTime / m_fRampUpTime;
		m_bRampState = OBJPSFX_RAMPUP;
		if(m_fRampRatio > 1.0f)		m_fRampRatio = 1.0f;
	}
	else if(m_nRampDownType && m_fDuration && (fTime >= m_fDuration - m_fRampDownTime))
	{
		m_fRampRatio = (m_fDuration - fTime) / m_fRampDownTime;
		m_bRampState = OBJPSFX_RAMPDOWN;
		if(m_fRampRatio < 0.0f)		m_fRampRatio = 0.0f;
	}
	else
	{
		m_fRampRatio = 1.0f;
		m_bRampState = 0;
	}

	//*********************************************************************
	// Handle the location and rotation of the system
	//*********************************************************************

	if(m_bMove)
	{
		m_pClientDE->GetObjectPos(m_hObj, &m_vPos);
		m_pClientDE->GetObjectRotation(m_hObj, &rRot);
		m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);

		VEC_MULSCALAR(vU, vU, m_vOffset.x);
		VEC_MULSCALAR(vR, vR, m_vOffset.y);
		VEC_MULSCALAR(vF, vF, m_vOffset.z);
		VEC_ADD(m_vPos, m_vPos, vU);
		VEC_ADD(m_vPos, m_vPos, vR);
		VEC_ADD(m_vPos, m_vPos, vF);
	}

	// Update the position of the object if we should
	if(!(m_nFXFlags & OBJPSFX_MOVINGSOURCE))
		m_pClientDE->SetObjectPos(m_hObject, &m_vPos);

	// Update the rotation of the system with the object
	if(m_nFXFlags & OBJPSFX_ALIGNROTATION)
	{
		m_pClientDE->GetObjectRotation(m_hObj, &m_rRot);
		m_pClientDE->GetRotationVectors(&m_rRot, &vU, &vR, &vF);
		m_pClientDE->GetObjectRotation(m_hObject, &m_rRot);
		m_pClientDE->AlignRotation(&m_rRot, &vF, &vU);
	}
	else
		m_pClientDE->GetObjectRotation(m_hObject, &m_rRot);

	// Rotate the object if it has rotation values
	DVector		vRotate;
	VEC_COPY(vRotate, m_vRotations);

	if(((m_bRampState == OBJPSFX_RAMPUP) && (m_nRampUpType & OBJPSFX_RAMPROTATION)) ||
	  ((m_bRampState == OBJPSFX_RAMPDOWN) && (m_nRampDownType & OBJPSFX_RAMPROTATION)))
		VEC_MULSCALAR(vRotate, vRotate, m_fRampRatio);

	if(m_vRotations.x || m_vRotations.y || m_vRotations.z)
	{
		if(m_vRotations.x)	m_pClientDE->EulerRotateX(&m_rRot, vRotate.x * MATH_PI);
		if(m_vRotations.y)	m_pClientDE->EulerRotateY(&m_rRot, vRotate.y * MATH_PI);
		if(m_vRotations.z)	m_pClientDE->EulerRotateZ(&m_rRot, vRotate.z * MATH_PI);
	}

	if(!(m_nFXFlags & OBJPSFX_ROTATINGSOURCE))
		m_pClientDE->SetObjectRotation(m_hObject, &m_rRot);

	//*********************************************************************
	// Handle the alpha ramp values and add more particles
	//*********************************************************************

	if(((m_bRampState == OBJPSFX_RAMPUP) && (m_nRampUpType & OBJPSFX_RAMPALPHA)) ||
	  ((m_bRampState == OBJPSFX_RAMPDOWN) && (m_nRampDownType & OBJPSFX_RAMPALPHA)))
	{
		// Fade in the particles
		DFLOAT		r, g, b, a;
		m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a);
		a = m_fAlpha * m_fRampRatio;
		m_pClientDE->SetObjectColor(m_hObject, r, g, b, a);
	}

	// Add more particles if it's time to
	if(m_pClientDE->GetTime() - m_fLastAddTime >= m_fAddDelay)
	{
		m_fLastAddTime = m_pClientDE->GetTime();
		AddParticles();

		VEC_COPY(m_vLastPos, m_vPos);
		ROT_COPY(m_rLastRot, m_rRot);
	}

	return DTRUE;
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CObjectParticleFX::AddParticles
//
//	PURPOSE:	Add a new batch of particles
//
// ----------------------------------------------------------------------- //

void CObjectParticleFX::AddParticles()
{
	if(!m_pClientDE) return;

	// Add the particles to the system
	DDWORD		i, j = (DDWORD)m_fDensity;
	DFLOAT		life;
	DVector		start, vel, color, vUp, vU, vR, vF;
	DRotation	rRot;

	VEC_SET(vUp, 0.0f, 1.0f, 0.0f);
	ROT_COPY(rRot, m_rRot);

	switch(m_nEmitType)
	{
		case	OBJPSFX_EMITLOCATION:
		{
			m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);

			VEC_SET(start, 0.0f, 0.0f, 0.0f);
			VEC_NORM(vF);

			if(m_nFXFlags & OBJPSFX_MOVINGSOURCE)
			{
				VEC_SUB(color, m_vPos, m_vOrigin);
				VEC_ADD(start, start, color);
			}

			if(m_nFXFlags & OBJPSFX_MOVINGSTREAM)
			{
				DVector		dif;
				DFLOAT		mag;
				DDWORD		count, num;

				VEC_SUB(dif, m_vLastPos, m_vPos);
				mag = VEC_MAG(dif);
				num = (DDWORD)(mag / (m_fDensity * m_fRadius / 1000.0f));
				VEC_DIVSCALAR(dif, dif, (DFLOAT)num);

				for(count = 0; count < num; count++)
				{
					VEC_MULSCALAR(vel, vF, GetRandom(m_fMinVelocity, m_fMaxVelocity));
					GetRandomColor(color);
					life = GetRandom(m_fMinLifetime, m_fMaxLifetime);
					m_pClientDE->AddParticle(m_hObject, &start, &vel, &color, life);
					VEC_ADD(start, start, dif);
				}
			}
			else
			{
				VEC_MULSCALAR(vel, vF, GetRandom(m_fMinVelocity, m_fMaxVelocity));
				GetRandomColor(color);
				life = GetRandom(m_fMinLifetime, m_fMaxLifetime);
				m_pClientDE->AddParticle(m_hObject, &start, &vel, &color, life);
			}
			break;
		}

		case	OBJPSFX_EMITRING:
		case	OBJPSFX_EMITFILLEDRING:
		case	OBJPSFX_EMITSPHERE:
		case	OBJPSFX_EMITFILLEDSPHERE:
		{
			DVector		dif, offset;
			DFLOAT		mag;
			DDWORD		count, num = 1;

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

			if(m_nFXFlags & OBJPSFX_MOVINGSTREAM)
			{
				VEC_SUB(dif, m_vLastPos, m_vPos);
				mag = VEC_MAG(dif);
				num = (DDWORD)(mag / (m_fDensity * m_fRadius / 1000.0f));
				VEC_DIVSCALAR(dif, dif, (DFLOAT)num);
			}

			for(count = 0; count < num; count++)
			{
				for(i = 0; i < m_nNumParticles; i++)
				{
					m_pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);

					if((m_nEmitType == OBJPSFX_EMITSPHERE) || (m_nEmitType == OBJPSFX_EMITFILLEDSPHERE))
					{
						m_pClientDE->RotateAroundAxis(&rRot, &vF, GetRandom(-MATH_PI, MATH_PI));
						m_pClientDE->RotateAroundAxis(&rRot, &vR, GetRandom(-MATH_PI, MATH_PI));
					}
					else
						m_pClientDE->RotateAroundAxis(&rRot, &vF, GetRandom(-MATH_PI, MATH_PI));

					VEC_NORM(vR);
					VEC_COPY(start, vR);
					VEC_COPY(vel, vR);
					VEC_MULSCALAR(vel, vel, GetRandom(m_fMinVelocity, m_fMaxVelocity));

					if((m_nEmitType == OBJPSFX_EMITFILLEDRING) || (m_nEmitType == OBJPSFX_EMITFILLEDSPHERE))
						{ VEC_MULSCALAR(start, start, GetRandom(0.0f, m_fPosRadius)); }
					else
						{ VEC_MULSCALAR(start, start, m_fPosRadius); }

					if(m_nFXFlags & OBJPSFX_MOVINGSOURCE)
					{
						VEC_SUB(color, m_vPos, m_vOrigin);
						VEC_ADD(start, start, color);
					}

					if(m_nFXFlags & OBJPSFX_MOVINGSTREAM)
					{
						VEC_ADD(start, start, offset);
					}

					GetRandomColor(color);
					life = GetRandom(m_fMinLifetime, m_fMaxLifetime);

					m_pClientDE->AddParticle(m_hObject, &start, &vel, &color, life);
				}

				VEC_ADD(offset, offset, dif);
			}
			break;
		}

		case	OBJPSFX_EMITCYLINDER:
		case	OBJPSFX_EMITFILLEDCYLINDER:
		{
			DVector		dif, offset, up;
			DRotation	tempRot;

⌨️ 快捷键说明

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