// ----------------------------------------------------------------------- //
//
// MODULE  : WeaponFXLow.cpp
//
// PURPOSE : Weapon special FX - Low detail Implementation
//
// CREATED : 8/22/98
//
// ----------------------------------------------------------------------- //

#include "WeaponFX.h"
#include "cpp_client_de.h"
#include "ClientUtilities.h"
#include "WeaponFXTypes.h"
#include "RiotClientShell.h"
#include "RiotMsgIDs.h"
#include "ParticleExplosionFX.h"
#include "SpriteFX.h"
#include "ExplosionFX.h"
#include "DebrisFX.h"

extern CRiotClientShell* g_pRiotClientShell;


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowBullgutFX
//
//	PURPOSE:	Create the bullgut fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowBullgutFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	// Create explosion sprite...

	SPRITECREATESTRUCT sc;

	DVector vPos;
	VEC_MULSCALAR(vPos, m_vDir, -20.0f);
	VEC_ADD(vPos, vPos, m_vPos);

	VEC_COPY(sc.vPos, vPos);
	VEC_SET(sc.vVel, 0.0f, 15.0f, 0.0f);

	VEC_SET(sc.vInitialScale, 0.5f, 0.5f, 1.0f);
	VEC_SET(sc.vFinalScale, 1.0f, 1.0f, 1.0f);

	sc.dwFlags			= FLAG_VISIBLE | FLAG_SPRITEBIAS | FLAG_NOLIGHT; 
	sc.fLifeTime		= 1.5f;
	sc.fInitialAlpha	= 1.0f;
	sc.fFinalAlpha		= 0.0f;
	sc.pFilename		= "Sprites\\weapons\\BllgtExp.spr";

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_SPRITE_ID, &sc);
	if (pFX) pFX->Update();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CratePulseRifleFX
//
//	PURPOSE:	Create the pulse rifle fx
//
// ----------------------------------------------------------------------- //


void CWeaponFX::CreateLowPulseRifleFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	// Create impact sprite...

	SPRITECREATESTRUCT sc;

	VEC_COPY(sc.vPos, m_vPos);
	ROT_COPY(sc.rRot, m_rSurfaceRot);

	VEC_SET(sc.vVel, 0.0f, 0.0f, 0.0f);
	VEC_SET(sc.vInitialScale, 0.1f, 0.1f, 1.0f);
	VEC_SET(sc.vFinalScale, 1.0f, 1.0f, 1.0f);

	sc.dwFlags			= FLAG_VISIBLE | FLAG_ROTATEABLESPRITE | FLAG_NOLIGHT; 
	sc.fLifeTime		= 0.3f;
	sc.fInitialAlpha	= 1.0f;
	sc.fFinalAlpha		= 0.0f;
	sc.pFilename		= "Sprites\\PulseImpact.spr";

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_SPRITE_ID, &sc);
	if (pFX) pFX->Update();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowShredderFX
//
//	PURPOSE:	Create the shredder fx
//
// ----------------------------------------------------------------------- //
#pragma optimize ( "", off ) // this is a incorrectly optimized function!

void CWeaponFX::CreateLowShredderFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	// Create explosion sprite...

	SPRITECREATESTRUCT sc;

	VEC_COPY(sc.vPos, m_vPos);
	sc.vPos.y += 50.0f;

	VEC_SET(sc.vVel, 0.0f, 0.0f, 0.0f);
	VEC_SET(sc.vInitialScale, 0.5f, 0.5f, 1.0f);
	VEC_SET(sc.vFinalScale, 1.0f, 1.0f, 1.0f);

	sc.dwFlags			= FLAG_VISIBLE | FLAG_SPRITEBIAS | FLAG_NOLIGHT; 
	sc.fLifeTime		= 1.0f;
	sc.fInitialAlpha	= 1.0f;
	sc.fFinalAlpha		= 0.0f;
	sc.pFilename		= "Sprites\\weapons\\ShrddrExp.spr";

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_SPRITE_ID, &sc);
	if (pFX) pFX->Update();
}
#pragma optimize ( "", off )

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowSpiderFX
//
//	PURPOSE:	Create the spider fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowSpiderFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	// Create model explosion...

	EXCREATESTRUCT ex;
	VEC_COPY(ex.vPos, m_vPos);

	DFLOAT fRadius = (DFLOAT)GetWeaponDamageRadius(m_nWeaponId, m_eSize);

	VEC_SET(ex.vVel, 0.0f, 0.0f, 0.0f);
	VEC_SET(ex.vInitialScale, fRadius, fRadius, fRadius);
	VEC_SET(ex.vFinalScale, fRadius, fRadius, fRadius);
	VEC_SET(ex.vInitialColor, 1.0f, 1.0f, 1.0f);
	VEC_SET(ex.vFinalColor, 1.0f, 1.0f, 1.0f);
	ex.bUseUserColors = DTRUE;

	ex.dwFlags			= FLAG_VISIBLE | FLAG_MODELGOURAUDSHADE | FLAG_NOLIGHT;
	ex.fLifeTime		= 1.0f;
	ex.fInitialAlpha	= 1.0f;
	ex.fFinalAlpha		= 0.0f;
	ex.pFilename		= "Models\\PV_Weapons\\SpiderExplosionCore.abc";
	ex.pSkin			= "SpecialFX\\Explosions\\SpiderCore.dtx";
	ex.bLoop			= DTRUE;

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_EXPLOSION_ID, &ex);
	if (pFX) pFX->Update();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowSniperRifleFX
//
//	PURPOSE:	Create the sniper rifle fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowSniperRifleFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	if (m_eSurfaceType == ST_LIQUID) return;

	DVector vVelMin, vVelMax;
	VEC_SET(vVelMin, -100.0f, 150.0f, -100.0f)
	VEC_SET(vVelMax, 100.0f, 200.0f, 100.0f)

	if (m_eSurfaceType == ST_FLESH)
	{
		VEC_SET(vVelMin, -10.0f, 200.0f, -10.0f)
		VEC_SET(vVelMax, 10.0f, 350.0f, 10.0f)
		DFLOAT fRange = 125.0f;

		CreateLowVectorBloodFX(vVelMin, vVelMax, fRange);
		return;
	}

	if (GetRandom(1, 3) != 1) return;

	// Create a some debris...

	DEBRISCREATESTRUCT debris;

	if (m_eSurfaceType == ST_MECHA)
	{
		ROT_COPY(debris.rRot, m_rDirRot);
	}
	else
	{
		ROT_COPY(debris.rRot, m_rSurfaceRot);
	}

	VEC_COPY(debris.vPos, m_vPos);
	VEC_COPY(debris.vMinVel, vVelMin);
	VEC_COPY(debris.vMaxVel, vVelMax);
	debris.fLifeTime		= GetRandom(0.5f, 1.0f);
	debris.fFadeTime		= 1.0f;
	debris.nNumDebris		= GetRandom(1, 3);
	debris.bRotate			= DFALSE;
	debris.fMinScale		= 2.0f;
	debris.fMaxScale		= 5.0f;
	debris.nDebrisType		= GetVectorDebrisType(m_eSurfaceType);
	debris.bForceRemove		= DTRUE;

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_DEBRIS_ID, &debris);
	if (pFX) pFX->Update();
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowTOWFX
//
//	PURPOSE:	Create the tow fx
//
// ----------------------------------------------------------------------- //
#pragma optimize ( "", off ) // this is a incorrectly optimized function!

void CWeaponFX::CreateLowTOWFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	DFLOAT fFactor = m_eSize == MS_SMALL ? 0.2f : (m_eSize == MS_LARGE ? 5.0f : 1.0f);

	// Create explosion sprite...

	SPRITECREATESTRUCT sc;

	VEC_COPY(sc.vPos, m_vPos);
	sc.vPos.y += 50.0f;

	VEC_SET(sc.vVel, 0.0f, 0.0f, 0.0f);
	VEC_SET(sc.vInitialScale, 1.0f, 1.0f, 1.0f);
	VEC_MULSCALAR(sc.vInitialScale, sc.vInitialScale, fFactor);
	VEC_SET(sc.vFinalScale, 2.5f, 2.5f, 1.0f);
	VEC_MULSCALAR(sc.vFinalScale, sc.vFinalScale, fFactor);

	sc.vVel.y += GetRandom(10.0f, 15.0f);
	sc.dwFlags			= FLAG_VISIBLE | FLAG_SPRITEBIAS | FLAG_NOLIGHT; 
	sc.fLifeTime		= 0.75f;
	sc.fInitialAlpha	= 1.0f;
	sc.fFinalAlpha		= 0.0f;
	sc.pFilename		= "Sprites\\weapons\\BllgtExp.spr";

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_SPRITE_ID, &sc);
	if (pFX) pFX->Update();
}
#pragma optimize ( "", on )

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowEnergyGrenadeFX
//
//	PURPOSE:	Create the energy grenade fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowEnergyGrenadeFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	// Create model explosions...

	EXCREATESTRUCT ex;
	VEC_COPY(ex.vPos, m_vPos);

	DFLOAT fRadius = GetWeaponDamageRadius(m_nWeaponId, m_eSize) * 2.0f;

	VEC_SET(ex.vVel, 0.0f, 0.0f, 0.0f);
	VEC_SET(ex.vInitialScale, fRadius/5.0f, fRadius/5.0f, fRadius/5.0f);
	VEC_SET(ex.vFinalScale, fRadius, fRadius, fRadius);
	VEC_SET(ex.vInitialColor, 1.0f, 1.0f, 1.0f);
	VEC_SET(ex.vFinalColor, 1.0f, 1.0f, 1.0f);
	ex.bUseUserColors = DTRUE;

	ex.dwFlags			= FLAG_VISIBLE | FLAG_MODELGOURAUDSHADE | FLAG_NOLIGHT;
	ex.fLifeTime		= 0.5f;

	DVector vUp;
	VEC_SET(vUp, 1.0f, 0.0f, 1.0f);
	m_pClientDE->AlignRotation(&(ex.rRot), &vUp, DNULL);

	ex.fInitialAlpha	= 0.9f;
	ex.fFinalAlpha		= 0.2f;
	ex.pFilename		= "Models\\PV_Weapons\\EnergyGrenadeExplosionCore.abc";
	ex.pSkin			= "SpecialFX\\Explosions\\EnergyGrenadeCore.dtx";

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_EXPLOSION_ID, &ex);
	if (pFX) pFX->Update();
}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowTantoFX
//
//	PURPOSE:	Create the tanto fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowTantoFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	if (m_eSurfaceType == ST_LIQUID) return;

	CSpecialFX* pFX;

	DVector vVelMin, vVelMax;
	VEC_SET(vVelMin, -100.0f, 150.0f, -100.0f);
	VEC_SET(vVelMax, 100.0f, 200.0f, 100.0f);

	if (m_eSurfaceType == ST_FLESH)
	{
		VEC_SET(vVelMin, -10.0f, 200.0f, -10.0f);
		VEC_SET(vVelMax, 10.0f, 300.0f, 10.0f);
		DFLOAT fRange = 100.0f;

		CreateLowVectorBloodFX(vVelMin, vVelMax, fRange);
		return;
	}

	if (GetRandom(1, 2) != 1) return;

	// Create a some debris...

	DEBRISCREATESTRUCT debris;

	ROT_COPY(debris.rRot, m_rSurfaceRot);

	VEC_COPY(debris.vPos, m_vPos);
	VEC_COPY(debris.vMinVel, vVelMin);
	VEC_COPY(debris.vMaxVel, vVelMax);
	debris.fLifeTime		= GetRandom(0.5f, 1.5f);
	debris.fFadeTime		= 1.0f;
	debris.nNumDebris		= GetRandom(3, 5);
	debris.bRotate			= DTRUE;
	debris.fMinScale		= 1.0f;
	debris.fMaxScale		= 2.0f;
	debris.nDebrisType		= GetVectorDebrisType(m_eSurfaceType);

	pFX = psfxMgr->CreateSFX(SFX_DEBRIS_ID, &debris);
	if (pFX) pFX->Update();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowAssaultRifleFX
//
//	PURPOSE:	Create the assault rifle fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowAssaultRifleFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

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

	if (m_eSurfaceType == ST_LIQUID) return;

	DVector vVelMin, vVelMax;
	VEC_SET(vVelMin, -50.0f, 50.0f, -50.0f)
	VEC_SET(vVelMax, 50.0f, 100.0f, 50.0f)

	if (m_eSurfaceType == ST_FLESH)
	{
		VEC_SET(vVelMin, -10.0f, 200.0f, -10.0f)
		VEC_SET(vVelMax, 10.0f, 400.0f, 10.0f)
		DFLOAT fRange = 150.0f;

		CreateLowVectorBloodFX(vVelMin, vVelMax, fRange);
		return;
	}

	if (GetRandom(1, 3) != 1) return;

	// Create a some debris...

	DEBRISCREATESTRUCT debris;

	if (m_eSurfaceType == ST_MECHA)
	{
		ROT_COPY(debris.rRot, m_rDirRot);
	}
	else
	{
		ROT_COPY(debris.rRot, m_rSurfaceRot);
	}

	VEC_COPY(debris.vPos, m_vPos);
	VEC_COPY(debris.vMinVel, vVelMin);
	VEC_COPY(debris.vMaxVel, vVelMax);
	debris.fLifeTime		= GetRandom(0.5f, 1.5f);
	debris.fFadeTime		= 1.0f;
	debris.nNumDebris		= 1;
	debris.bRotate			= DTRUE;
	debris.fMinScale		= 1.0f;
	debris.fMaxScale		= 4.0f;
	debris.nDebrisType		= GetVectorDebrisType(m_eSurfaceType);
	debris.bForceRemove		= DTRUE;

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_DEBRIS_ID, &debris);
	if (pFX) pFX->Update();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowVectorBloodFX
//
//	PURPOSE:	Create the blood trail, splats, etc.
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowVectorBloodFX(DVector & vVelMin, DVector & vVelMax, DFLOAT fRange)
{
	if (!m_pClientDE || !g_pRiotClientShell) return;

	CRiotSettings* pSettings = g_pRiotClientShell->GetSettings();
	if (!pSettings || !pSettings->Gore()) return;

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

	char* szBlood[4] = { "SpecialFX\\ParticleTextures\\Blood_1.dtx", 
						 "SpecialFX\\ParticleTextures\\Blood_2.dtx",
						 "SpecialFX\\ParticleTextures\\Alien_Blood_1.dtx",
						 "SpecialFX\\ParticleTextures\\Alien_Blood_2.dtx"};


	// Create a particle trails...

	PESCREATESTRUCT pe;

	VEC_COPY(pe.vPos, m_vPos);
	ROT_COPY(pe.rSurfaceRot, m_rDirRot);
	VEC_SET(pe.vColor1, 255.0f, 255.0f, 255.0f);
	VEC_SET(pe.vColor2, 255.0f, 255.0f, 255.0f);
	VEC_COPY(pe.vMinVel, vVelMin);
	VEC_COPY(pe.vMaxVel, vVelMax);
	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		= 0.5f;
	pe.fFadeTime		= 0.25f;
	pe.fOffsetTime		= 0.0f;
	pe.fRadius			= 300.0f;
	pe.fGravity			= -100.0f;
	pe.nNumPerPuff		= 2;
	pe.nNumEmmitters	= 2;
	pe.bIgnoreWind		= DTRUE;

	if (m_eSurfaceType == ST_ALIENFLESH)
	{
		pe.pFilename		= szBlood[GetRandom(2, 3)];
	}
	else
	{
		pe.pFilename		= szBlood[GetRandom(0, 1)];
	}

	pe.nSurfaceType		= m_eSurfaceType;
	pe.nNumSteps		= 6;

	CSpecialFX* pFX = psfxMgr->CreateSFX(SFX_PARTICLEEXPLOSION_ID, &pe);
	if (pFX) pFX->Update();
}