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

📄 explosionfx.cpp

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

	m_fStartTime = pClientDE->GetTime();

	return DTRUE;
}

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

DBOOL CExplosionLightFX::Update()
{
	if(!m_hObject || !m_pClientDE) return DFALSE;
	DFLOAT		fTime = m_pClientDE->GetTime() - m_fStartTime;
	DFLOAT		fRatio = fTime / m_fDuration;

	if(m_fDelay)
	{
		if(fTime >= m_fDelay)
		{
			m_pClientDE->SetLightRadius(m_hObject, m_fRadius1);
			m_fStartTime = m_pClientDE->GetTime();
			m_fDelay = 0.0f;
		}
		return	DTRUE;
	}

	if(m_bChangeColor)
	{
		DVector		vColor;
		VEC_SUB(vColor, m_vColor2, m_vColor1);
		VEC_MULSCALAR(vColor, vColor, fRatio);
		VEC_ADD(vColor, vColor, m_vColor1);
		m_pClientDE->SetLightColor(m_hObject, vColor.x, vColor.y, vColor.z);
	}

	if(m_bScale)
	{
		DFLOAT		radius;
		radius = m_fRadius1 + ((m_fRadius2 - m_fRadius1) * fRatio);
		m_pClientDE->SetLightRadius(m_hObject, radius);
	}

	return (fTime < m_fDuration);
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CExplosionFragFX::Init
//
//	PURPOSE:	Init the fragment
//
// ----------------------------------------------------------------------- //

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

	EXPLOSIONFRAGCS* pEFCS = (EXPLOSIONFRAGCS*)psfxCreateStruct;

	VEC_COPY(m_vPos, pEFCS->vPos);
	VEC_COPY(m_vLastPos, pEFCS->vPos);
	VEC_COPY(m_vNormal, pEFCS->vNormal);
	VEC_COPY(m_vScale, pEFCS->vScale);
	VEC_COPY(m_vRotateMax, pEFCS->vRotateMax);

	m_fSpread			= pEFCS->fSpread;
	m_fDuration			= pEFCS->fDuration;
	m_fVelocity			= pEFCS->fVelocity;
	m_fBounceMod		= pEFCS->fBounceMod;
	m_fGravity			= pEFCS->fGravity;
	m_fFadeTime			= pEFCS->fFadeTime;
	m_fInitAlpha		= pEFCS->fInitAlpha;
	m_bRandDir			= pEFCS->bRandDir;
	m_bSpawnExp			= pEFCS->bSpawnExp;
	m_nSpawnType		= pEFCS->nSpawnType;
	m_nTrailType		= pEFCS->nTrailType;

	if( m_szModel )
		g_pClientDE->FreeString( m_szModel );
	m_szModel			= g_pClientDE->CopyString( pEFCS->szModel );
	if( m_szSkin )
		g_pClientDE->FreeString( m_szSkin );
	m_szSkin			= g_pClientDE->CopyString( pEFCS->szSkin );

	if(m_vRotateMax.x || m_vRotateMax.y || m_vRotateMax.z)
		m_bRotate = 1;

	return DTRUE;
}

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

DBOOL CExplosionFragFX::CreateObject(CClientDE *pClientDE)
{
	if (!pClientDE ) return DFALSE;
	m_pClientDE = pClientDE;

	ObjectCreateStruct	ocStruct;
	INIT_OBJECTCREATESTRUCT(ocStruct);

	ocStruct.m_ObjectType = OT_MODEL;
	ocStruct.m_Flags = FLAG_VISIBLE;

	VEC_COPY(ocStruct.m_Pos, m_vPos);

	if(m_bRandDir)
	{
		DVector vDir;
		VEC_SET(vDir, GetRandom(-10.0f, 10.0f), GetRandom(-10.0f, 10.0f), GetRandom(-10.0f, 10.0f));
		VEC_NORM(vDir);
		VEC_MULSCALAR(m_vVelocity, vDir, m_fVelocity);
	}
	else
	{
		DVector		vUp, vU, vR, vF;
		DRotation	rRot;

		VEC_SET(vUp, 0.0f, 1.0f, 0.0f);
		pClientDE->AlignRotation(&rRot, &m_vNormal, &vUp);
		pClientDE->RotateAroundAxis(&rRot, &m_vNormal, GetRandom(-MATH_PI, MATH_PI));
		pClientDE->GetRotationVectors(&rRot, &vU, &vR, &vF);

		VEC_MULSCALAR(m_vVelocity, m_vNormal, m_fVelocity);
		VEC_MULSCALAR(vR, vR, m_fSpread);
		VEC_ADD(m_vVelocity, m_vVelocity, vR);
		VEC_NORM(m_vVelocity);
		VEC_MULSCALAR(m_vVelocity, m_vVelocity, m_fVelocity);
	}

	VEC_SET(m_vGravity, 0.0f, -1.0f, 0.0f);
	VEC_MULSCALAR(m_vGravity, m_vGravity, m_fGravity);

	if(m_bRotate)
	{
		fPitch = GetRandom(-m_vRotateMax.x, m_vRotateMax.x);
		fYaw = GetRandom(-m_vRotateMax.y, m_vRotateMax.y);
		fRoll = GetRandom(-m_vRotateMax.z, m_vRotateMax.z);
	}

	if(m_szModel)	_mbscpy((unsigned char*)ocStruct.m_Filename, (const unsigned char*)pClientDE->GetStringData(m_szModel));
		else		_mbscpy((unsigned char*)ocStruct.m_Filename, (const unsigned char*)"Models\\Explosions\\exp_sphere.abc");

	if(m_szSkin)	_mbscpy((unsigned char*)ocStruct.m_SkinName, (const unsigned char*)pClientDE->GetStringData(m_szSkin));
		else		_mbscpy((unsigned char*)ocStruct.m_SkinName, (const unsigned char*)"Skins\\Explosions\\Explosion_1.dtx");

	m_hObject = pClientDE->CreateObject(&ocStruct);

	DDWORD dwFlags = pClientDE->GetObjectFlags(m_hObject);
	pClientDE->SetObjectFlags(m_hObject, dwFlags | FLAG_MODELGOURAUDSHADE | FLAG_NOLIGHT);

	pClientDE->SetObjectScale(m_hObject, &m_vScale);

	DFLOAT	r, g, b, a;
	pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a);
	pClientDE->SetObjectColor(m_hObject, r, g, b, m_fInitAlpha);

	//**************************************************************//

	if(m_nTrailType)
	{
		CBloodClientShell *pShell = (CBloodClientShell*)pClientDE->GetClientShell();
		if (!pClientDE || !pShell) return DFALSE;

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

		OBJECTFXCS		ops;

		ops.hObj			= m_hObject;
		VEC_SET(ops.vOffset, 0.0f, 0.0f, 0.0f);
		ops.fScale			= 0.0f;
		ops.nScaleFlags		= 0;
		ops.nFXType			= m_nTrailType;
		ops.nFXFlags		= 0;

		psfxMgr->CreateSFX(SFX_OBJECTFX_ID, &ops, DFALSE, this);
	}

	//**************************************************************//

	m_fStartTime = pClientDE->GetTime();

	return DTRUE;
}

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

DBOOL CExplosionFragFX::Update()
{
	if(!m_hObject || !m_pClientDE) return DFALSE;
	DFLOAT		fTime = m_pClientDE->GetTime() - m_fStartTime;
	DBOOL		bMove = 1;
	
	if((VEC_MAG(m_vVelocity) < 1.0f) && (m_vLastNormal.y > 0.9f))
		bMove = 0;

	// Rotate the object if it has a rotation flag and is moving
	if(m_bRotate && bMove)
	{
		DRotation	rRot;
		m_fPitch += fPitch;
		m_fYaw += fYaw;
		m_fRoll += fRoll;
		m_pClientDE->SetupEuler(&rRot, m_fPitch, m_fYaw, m_fRoll);
		m_pClientDE->SetObjectRotation(m_hObject, &rRot);
	}

	// Fade out at the end of the duration if there is a fade out time
	if((fTime > m_fDuration - m_fFadeTime) && (fTime < m_fDuration))
	{
		DFLOAT	alpha = m_fInitAlpha - ((fTime - (m_fDuration - m_fFadeTime)) / m_fFadeTime);
		DFLOAT	r, g, b, a;

		m_pClientDE->GetObjectColor(m_hObject, &r, &g, &b, &a);
		m_pClientDE->SetObjectColor(m_hObject, r, g, b, alpha);
	}

	// If the object is moving, check for collisions and set the position and velocity
	if(bMove)
	{
		// Adjust the last and current position data
		VEC_COPY(m_vLastPos, m_vPos);
		VEC_ADD(m_vVelocity, m_vVelocity, m_vGravity);
		VEC_ADD(m_vPos, m_vPos, m_vVelocity);

		// Setup the data to test for a collision
		ClientIntersectQuery	iq;
		ClientIntersectInfo		ii;
		iq.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID | INTERSECT_HPOLY;
		VEC_COPY(iq.m_From, m_vLastPos);
		VEC_MULSCALAR(iq.m_To, m_vVelocity, 1.1f);
		VEC_ADD(iq.m_To, iq.m_To, iq.m_From);

		if(m_pClientDE->IntersectSegment(&iq, &ii))
		{
			DVector		vLift, vVel, vNorm;
			DFLOAT		r = VEC_MAG(m_vVelocity);
			DFLOAT		dot;

			// Make some temporary vectors for calculations
			VEC_COPY(vVel, m_vVelocity);
			VEC_COPY(vNorm, ii.m_Plane.m_Normal);
			VEC_COPY(m_vLastNormal, vNorm);
			VEC_NORM(vNorm);
			VEC_NORM(vVel);

			// Calculate a reflection vector
			dot = VEC_DOT(vNorm, vVel);
			VEC_MULSCALAR(vLift, vNorm, 2.0f * -dot);
			VEC_ADD(vLift, vVel, vLift);

			// Set the velocity of the reflection and decrease it a little
			VEC_MULSCALAR(m_vVelocity, vLift, r * m_fBounceMod);

			// Place the object at the collision point... a little off the surface
			VEC_ADD(m_vPos, ii.m_Point, vNorm);

			// Spawn and new explosion
			if(m_bSpawnExp >= 2)
			{
				CBloodClientShell *pShell = (CBloodClientShell*)m_pClientDE->GetClientShell();
				if (!pShell) return DFALSE;

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

				EXPLOSIONFXCS		expCS;
				expCS.hServerObj = 0;
				VEC_COPY(expCS.vPos, m_vPos);
				VEC_COPY(expCS.vNormal, m_vLastNormal);
				expCS.nType = m_nSpawnType;

				psfxMgr->CreateSFX(SFX_EXPLOSIONFX_ID, &expCS, DFALSE, this);
				if(m_bSpawnExp == 2)	return	DFALSE;
			}

			// Slow the rotation for every impact
			fPitch *= 0.5f;
			fYaw *= 0.5f;
			fRoll *= 0.5f;
		}

		m_pClientDE->SetObjectPos(m_hObject, &m_vPos);
	}

	// Check to see if the object should continue to exist...
	if(fTime < m_fDuration)
		return	DTRUE;
	else
	{
		if((m_bSpawnExp == 1) || (m_bSpawnExp == 4))
		{
			CBloodClientShell *pShell = (CBloodClientShell*)m_pClientDE->GetClientShell();
			if (!pShell) return DFALSE;

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

			EXPLOSIONFXCS		expCS;
			expCS.hServerObj = 0;
			VEC_COPY(expCS.vPos, m_vPos);
			VEC_COPY(expCS.vNormal, m_vLastNormal);
			expCS.nType = m_nSpawnType;

			psfxMgr->CreateSFX(SFX_EXPLOSIONFX_ID, &expCS, DFALSE, this);
		}
		return	DFALSE;
	}
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CExplosionFX::Init
//
//	PURPOSE:	Init the FX location and type
//
// ----------------------------------------------------------------------- //

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

	EXPLOSIONFXCS* pEFXCS = (EXPLOSIONFXCS*)psfxCreateStruct;

	VEC_COPY(m_vPos, pEFXCS->vPos);
	VEC_COPY(m_vNormal, pEFXCS->vNormal);
	VEC_NORM(m_vNormal);
	m_nExpID = pEFXCS->nType;

	return DTRUE;
}

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

DBOOL CExplosionFX::CreateObject(CClientDE *pClientDE)
{
	CBloodClientShell *pShell = (CBloodClientShell*)pClientDE->GetClientShell();
	if (!pClientDE || !pShell) return DFALSE;

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

	HCONSOLEVAR hVar = pClientDE->GetConsoleVar("ExplosionsDetail");
	DBYTE	detail = (DBYTE)pClientDE->GetVarValueFloat(hVar);

	if(detail >= 2)
	{
		switch(m_nExpID)
		{
			case	EXP_DEFAULT_SMALL:
			{
				EXPLOSIONMODELCS	emCS;
				EXPLOSIONSPRITECS	esCS;
				EXPLOSIONRINGCS		erCS, erCS2;
				EXPLOSIONLIGHTCS	elCS;
				DVector				temp;

				// Model
				VEC_COPY(emCS.vNormal, m_vNormal);
				VEC_COPY(emCS.vPos, m_vPos);
				VEC_MULSCALAR(temp, m_vNormal, 10.0f);
				VEC_ADD(emCS.vPos, m_vPos, temp);
				VEC_SET(emCS.vScale1, 25.0f, 25.0f, 25.0f);
				VEC_SET(emCS.vScale2, 200.0f, 200.0f, 200.0f);
				emCS.fDuration		= 0.5f;
				emCS.fAlpha		= 0.75f;
				emCS.bWaveForm	= GetRandom(0,2);
				emCS.bFadeType	= 1;
				emCS.bRandomRot	= 1;
				emCS.szModel	= 0;
				emCS.szSkin		= 0;

				psfxMgr->CreateSFX(SFX_EXPLOSION_ID, &emCS, DFALSE, this);

				// Sprite
				VEC_COPY(esCS.vNormal, m_vNormal);
				VEC_MULSCALAR(temp, m_vNormal, 25.0f);
				VEC_ADD(esCS.vPos, m_vPos, temp);
				VEC_SET(esCS.vScale1, 0.25f, 0.25f, 0.0f);
				VEC_SET(esCS.vScale2, 0.25f, 0.25f, 0.0f);
				esCS.fDuration		= 1.5f;
				esCS.fAlpha		= 1.0f;
				esCS.bWaveForm	= 0;
				esCS.bFadeType	= 1;
				esCS.bAlign		= 0;
				esCS.szSprite	= pClientDE->CreateString("Sprites\\fireball2.spr");

				psfxMgr->CreateSFX(SFX_EXPLOSIONSPRITE_ID, &esCS, DFALSE, this);

				g_pClientDE->FreeString( esCS.szSprite );
				esCS.szSprite = DNULL;

				// Ring
				VEC_COPY(erCS.vNormal, m_vNormal);
				VEC_MULSCALAR(temp, m_vNormal, 25.0f);
				VEC_ADD(erCS.vPos, m_vPos, temp);
				VEC_SET(erCS.vColor, 1.0f, 1.0f, 1.0f);
				erCS.fRadius	= 4000.0f;
				erCS.fPosRadius	= 10.0f;
				erCS.fVelocity	= 400.0f;
				erCS.fGravity	= 0.0f;
				erCS.nParticles	= 32;
				erCS.fDuration	= 0.5f;
				erCS.fAlpha		= 1.0f;
				erCS.fDelay		= 0.0f;
				erCS.bFadeType	= 1;
				erCS.bAlign		= 0;

⌨️ 快捷键说明

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