// ----------------------------------------------------------------------- //
//
// MODULE  : LOFWeaponFXLow.cpp
//
// PURPOSE : LOF Weapon special FX Low detail - Implementation
//
// CREATED : 18/12/98 - by Ewen Vowels for Anarchy-Arts
//
// ----------------------------------------------------------------------- //

#include "WeaponFX.h"
#include "cpp_client_de.h"
#include "ClientUtilities.h"
#include "WeaponFXTypes.h"
#include "RiotClientShell.h"
#include "MarkSFX.h"
#include "SparksFX.h"
#include "DynamicLightFX.h"
#include "BulletTrailFX.h"
#include "RiotMsgIDs.h"
#include "JuggernautFX.h"
#include "ShellCasingFX.h"
#include "ParticleExplosionFX.h"
#include "SpriteFX.h"
#include "ExplosionFX.h"
#include "DebrisFX.h"
#include "LineBallFX.h"
#include "CMoveMgr.h"

extern CRiotClientShell* g_pRiotClientShell;

#define	DEFAULT_WATER_IMPACT_SOUND_RADIUS	2000.0f
#define	DEFAULT_IMPACT_SOUND_RADIUS			500.0f

static DDWORD s_nNumShells = 0;

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowShochiFX
//
//	PURPOSE:	Create the Shochi fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowShochiFX()
{
	if (!m_pClientDE || !g_pRiotClientShell) return;
#pragma message ( "LOFFIXME - Need Medium Shochi Effects, file: " __FILE__ )

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

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

	DVector vVelMin, vVelMax;
	VEC_SET(vVelMin, -200.0f, 200.0f, -200.0f)
	VEC_MULSCALAR(vVelMin, vVelMin, fFactor)
	VEC_SET(vVelMax, 200.0f, 400.0f, 200.0f)
	VEC_MULSCALAR(vVelMax, vVelMax, fFactor)

	// Create a particle explosion...

	PESCREATESTRUCT pe;

	pe.bCreateDebris	= DFALSE;
	pe.bRotateDebris	= DFALSE;
	ROT_COPY(pe.rSurfaceRot, m_rSurfaceRot);
	VEC_COPY(pe.vPos, m_vPos);
	VEC_SET(pe.vColor1, 200.0f, 200.0f, 200.0f);
	VEC_SET(pe.vColor2, 230.0f, 230.0f, 230.0f);
	VEC_COPY(pe.vMinVel, vVelMin);
	VEC_COPY(pe.vMaxVel, vVelMax);
	pe.bSmall			= DFALSE;
	pe.fLifeTime		= 1.5f;
	pe.fFadeTime		= 0.5f;
	pe.fOffsetTime		= 0.0f;
	pe.fRadius			= 4000.0f * fFactor;
	pe.fGravity			= 0.0f;
	pe.nNumPerPuff		= 1;
	pe.nNumEmmitters	= 4;
	pe.pFilename		= "Sprites\\SmokeTest.spr";

	if (IsLiquid(m_eCode))
	{
		GetLiquidColorRange(m_eCode, &pe.vColor1, &pe.vColor2);
		pe.pFilename = "SpecialFX\\ParticleTextures\\GreySphere_1.dtx";
	}

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

	VEC_MULSCALAR(pe.vMinVel, pe.vMinVel, 1.25f);
	VEC_MULSCALAR(pe.vMaxVel, pe.vMaxVel, 1.25f);
	pe.vPos.y += 20.0f * fFactor;
	pe.fLifeTime		= 1.0f;
	pe.fFadeTime		= 0.5f;
	pe.fRadius			= 3000.0f * fFactor;

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

	VEC_MULSCALAR(pe.vMinVel, pe.vMinVel, 1.2f);
	VEC_MULSCALAR(pe.vMaxVel, pe.vMaxVel, 1.2f);
	pe.vPos.y += 20.0f * fFactor;
	pe.fLifeTime		= 2.0f;
	pe.fFadeTime		= 0.5f;
	pe.fRadius			= 1500.0f;

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



// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowMORTFX
//
//	PURPOSE:	Create the MORT fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowMORTFX()
{
	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::CreateLowHWARFX
//
//	PURPOSE:	Create the HWAR fx
//
// ----------------------------------------------------------------------- //

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

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

	CSpecialFX* pFX;

	DFLOAT	fLifeTime = 0.65f;

	// Create model explosion...

	EXCREATESTRUCT ex;
	ROT_COPY(ex.rRot, m_rDirRot);
	VEC_COPY(ex.vPos, m_vPos);

	DFLOAT fRadius = GetWeaponDamageRadius(m_nWeaponId, m_eSize) / 1.25f;

	VEC_SET(ex.vVel, 0.0f, 0.0f, 0.0f);
	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		= fLifeTime * 2.0f;
	ex.pFilename		= "Models\\PV_Weapons\\RedRiotExplosion.abc";
	ex.pSkin			= "SpecialFX\\Explosions\\HWARCore.dtx";

	VEC_SET(ex.vInitialScale, 50.0f, 50.0f, 50.0f);
	VEC_SET(ex.vFinalScale, fRadius, fRadius, fRadius);
	ex.fInitialAlpha	= 0.4f;
	ex.fFinalAlpha		= 0.8f;
	ex.fDelayTime		= 0.35f;
	pFX = psfxMgr->CreateSFX(SFX_EXPLOSION_ID, &ex);
	if (pFX) pFX->Update();
	
	// Create shockwave sprite...

	SPRITECREATESTRUCT sc;

	VEC_COPY(sc.vPos, m_vPos);
	m_pClientDE->SetupEuler(&(sc.rRot), MATH_HALFPI, 0.0f, 0.0f);
	VEC_SET(sc.vVel, 0.0f, 0.0f, 0.0f);
	VEC_SET(sc.vInitialScale, 1.0f, 1.0f, 1.0f);
	VEC_SET(sc.vFinalScale, 7.5f, 7.5f, 1.0f);

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

	sc.fDelayTime = fLifeTime / 2.0f;
	pFX = psfxMgr->CreateSFX(SFX_SPRITE_ID, &sc);
	if (pFX) pFX->Update();
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowEMSFX
//
//	PURPOSE:	Create the EMS fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowEMSFX()
{
	// new ev - 4/12/98 copied from 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, 0.75f, 0.75f, 1.0f); // new ev - changed was 1.0,1.0,1.0

	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::CreateLowRASGFX
//
//	PURPOSE:	Create the RASG fx
//
// ----------------------------------------------------------------------- //

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

	if (m_eSurfaceType == ST_LIQUID) return;

	CSFXMgr* psfxMgr = g_pRiotClientShell->GetSFXMgr();
	if (!psfxMgr) 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 || m_eSurfaceType == ST_ALIENFLESH)
	{
		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.5f);
	debris.fFadeTime		= 1.0f;
	debris.nNumDebris		= 1;
	debris.bRotate			= DTRUE;
	debris.fMinScale		= 2.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::CreateLowAgumaFX
//
//	PURPOSE:	Create the Aguma fx
//
// ----------------------------------------------------------------------- //

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

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

	if (m_eSurfaceType == ST_LIQUID) return;

	if (GetRandom(1, 4) != 1) 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 || m_eSurfaceType == ST_ALIENFLESH)
	{
		VEC_SET(vVelMin, -10.0f, 200.0f, -10.0f)
		VEC_SET(vVelMax, 10.0f, 350.0f, 10.0f)
		DFLOAT fRange = 75.0f;

		CreateLowVectorBloodFX(vVelMin, vVelMax, fRange);
		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		= 2.0f;
	debris.nDebrisType		= GetVectorDebrisType(m_eSurfaceType);
	debris.bForceRemove		= DTRUE;

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

}

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CWeaponFX::CreateLowMinigunFX
//
//	PURPOSE:	Create the Minigun fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowMinigunFX()
{
	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 || m_eSurfaceType == ST_ALIENFLESH)
	{
		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::CreateLowProximityMineFX
//
//	PURPOSE:	Create the proximity mine fx
//
// ----------------------------------------------------------------------- //

void CWeaponFX::CreateLowProximityMineFX()
{
	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();
}
