//============================================================
// Program:		CGFWeaponSystem
// Description:	Class for handling weapons
// Author:		Benjamin Gottemoller
// Website:		http://www.particlefield.com
// Date:		who knows
// Legal:		Licensed under the gnu GPL (see gpl.txt for details)
//============================================================

#include "GameFrameWeaponSystem.h"
#include "GameFrameCamera.h"
#include "GameFrame.h"

CGFWeaponSystem::CGFWeaponSystem()
{
	GFParent = NULL;
	Camera = NULL;
	CurrentPrimary = 0;
	CurrentSecondary = 0;
	NumPrimary = 0;
	NumPrimaryUsed = 0;
	PrimaryWeapons = NULL;
	NumSecondary = 0;
	NumSecondaryUsed = 0;
	SecondaryWeapons = NULL;
}

CGFWeaponSystem::~CGFWeaponSystem()
{
	Destroy();
}

int CGFWeaponSystem::Initialize(GameFrame *gfparent, CGFCamera *camera, int num_nodes)
{
	int i = 0;

	GFParent = gfparent;
	Camera = camera;
	CurrentPrimary = 0;
	CurrentSecondary = 0;

	if(num_nodes > 0)
	{
		if((PrimaryWeapons != NULL) || (SecondaryWeapons != NULL)) Destroy();

		PrimaryWeapons = new WEAPON[num_nodes];
		NumPrimary = num_nodes;
		NumPrimaryUsed = 0;
		memset(PrimaryWeapons, 0, sizeof(WEAPON) * NumPrimary);

		SecondaryWeapons = new WEAPON[num_nodes];
		NumSecondary = num_nodes;
		NumSecondaryUsed = 0;
		memset(SecondaryWeapons, 0, sizeof(WEAPON) * NumSecondary);

		if((PrimaryWeapons != NULL) || (SecondaryWeapons != NULL)) return 1;
	}

	return 0;
}

int  CGFWeaponSystem::AddPrimaryWeapon(WEAPON *obj)
{
	int result = -1;
	if((NumPrimary <= 0) || (PrimaryWeapons == NULL) || (GFParent == NULL)) return -1;

	if(NumPrimaryUsed >= NumPrimary)
	{
		int i = 0;
		WEAPON *tmp = NULL;
		tmp = new WEAPON[NumPrimary * 2];
		if(tmp == NULL) return -1;

		for(i=0; i<NumPrimary; i++)
		{
			memcpy(&(tmp[i]), &(PrimaryWeapons[i]), sizeof(WEAPON));
		}

		delete[] PrimaryWeapons;
		PrimaryWeapons = tmp;
		tmp = NULL;
		NumPrimary *= 2;
	}

	memcpy(&(PrimaryWeapons[NumPrimaryUsed]), obj, sizeof(WEAPON));
	result = NumPrimaryUsed;
	NumPrimaryUsed++;

	return result;
}

int  CGFWeaponSystem::AddSecondaryWeapon(WEAPON *obj)
{
	int result = -1;
	if((NumSecondary <= 0) || (SecondaryWeapons == NULL) || (GFParent == NULL)) return -1;

	if(NumSecondaryUsed >= NumSecondary)
	{
		int i = 0;
		WEAPON *tmp = NULL;
		tmp = new WEAPON[NumSecondary * 2];
		if(tmp == NULL) return -1;

		for(i=0; i<NumSecondary; i++)
		{
			memcpy(&(tmp[i]), &(SecondaryWeapons[i]), sizeof(WEAPON));
		}

		delete[] SecondaryWeapons;
		SecondaryWeapons = tmp;
		tmp = NULL;
		NumSecondary *= 2;
	}

	memcpy(&(SecondaryWeapons[NumSecondaryUsed]), obj, sizeof(WEAPON));
	result = NumSecondaryUsed;
	NumSecondaryUsed++;

	return result;
}

void CGFWeaponSystem::Destroy(void)
{
	int i = 0;

	GFParent = NULL;
	Camera = NULL;
	CurrentPrimary = 0;
	CurrentSecondary = 0;

	NumPrimary = 0;
	NumPrimaryUsed = 0;
	SAFE_DELETE_ARRAY(PrimaryWeapons);

	NumSecondary = 0;
	NumSecondaryUsed = 0;
	SAFE_DELETE_ARRAY(SecondaryWeapons);
}

void CGFWeaponSystem::NextPrimary(void)
{
	CurrentPrimary++;
	if(CurrentPrimary >= NumPrimaryUsed) CurrentPrimary = 0;
}

void CGFWeaponSystem::PreviousPrimary(void)
{
	CurrentPrimary--;
	if(CurrentPrimary < 0) CurrentPrimary = (NumPrimaryUsed - 1);
}

void CGFWeaponSystem::NextSecondary(void)
{
	CurrentSecondary++;
	if(CurrentSecondary >= NumSecondaryUsed) CurrentSecondary = 0;
}

void CGFWeaponSystem::PreviousSecondary(void)
{
	CurrentSecondary--;
	if(CurrentSecondary < 0) CurrentSecondary = (NumSecondaryUsed - 1);
}

void CGFWeaponSystem::FirePrimary()
{
	if(GFParent->IsGamePaused || GFParent->IsGameLocked) return;
	WEAPON *tmp = NULL;
	tmp = &(PrimaryWeapons[CurrentPrimary]);
	float time_diff = GFParent->GetTime() - tmp->LastShotTime;

	if((time_diff > tmp->SecondsPerRound) && (tmp->RoundsRemaining > 0))
	{
		D3DXVECTOR3 V, Pos;
		
		V.x = Camera->XVec + Camera->Look_Vector.x * tmp->Speed;
		V.y = Camera->YVec + Camera->Look_Vector.y * tmp->Speed;
		V.z = Camera->ZVec + Camera->Look_Vector.z * tmp->Speed;

		Pos.x = Camera->X + tmp->ShiftX * Camera->Right_Vector.x + 
							tmp->ShiftY * Camera->Up_Vector.x + 
							tmp->ShiftZ * Camera->Look_Vector.x;

		Pos.y = Camera->Y + tmp->ShiftX * Camera->Right_Vector.y + 
							tmp->ShiftY * Camera->Up_Vector.y + 
							tmp->ShiftZ * Camera->Look_Vector.y;

		Pos.z = Camera->Z + tmp->ShiftX * Camera->Right_Vector.z + 
							tmp->ShiftY * Camera->Up_Vector.z + 
							tmp->ShiftZ * Camera->Look_Vector.z;

		GFParent->ParticleSystem.AddParticle(1000 + CurrentPrimary, tmp->ParticleType, Pos.x, Pos.y, Pos.z, 
											 V.x, V.y, V.z, 1.0f, 0, tmp->Color, tmp->DeltaColor, tmp->MaxAge); 

		tmp->LastShotTime = GFParent->GetTime();
		tmp->RoundsRemaining--;

		if(tmp->FireSoundLibIndex != -1)
		{
			GFParent->Sound.PlaySound(tmp->FireSoundLibIndex);
		}

		if(tmp->modifier != NULL)
		{
			tmp->modifier(tmp, GFParent);
		}
	}
}

void CGFWeaponSystem::FireSecondary()
{
	if(GFParent->IsGamePaused || GFParent->IsGameLocked) return;
	WEAPON *tmp = NULL;
	tmp = &(SecondaryWeapons[CurrentSecondary]);
	float time_diff = GFParent->GetTime() - tmp->LastShotTime;

	if((time_diff > tmp->SecondsPerRound) && (tmp->RoundsRemaining > 0))
	{
		D3DXVECTOR3 V, Pos;
		
		V.x = Camera->XVec + Camera->Look_Vector.x * tmp->Speed;
		V.y = Camera->YVec + Camera->Look_Vector.y * tmp->Speed;
		V.z = Camera->ZVec + Camera->Look_Vector.z * tmp->Speed;

		Pos.x = Camera->X + tmp->ShiftX * Camera->Right_Vector.x + 
							tmp->ShiftY * Camera->Up_Vector.x + 
							tmp->ShiftZ * Camera->Look_Vector.x;

		Pos.y = Camera->Y + tmp->ShiftX * Camera->Right_Vector.y + 
							tmp->ShiftY * Camera->Up_Vector.y + 
							tmp->ShiftZ * Camera->Look_Vector.y;

		Pos.z = Camera->Z + tmp->ShiftX * Camera->Right_Vector.z + 
							tmp->ShiftY * Camera->Up_Vector.z + 
							tmp->ShiftZ * Camera->Look_Vector.z;

		GFParent->ParticleSystem.AddParticle(1000 + CurrentSecondary, tmp->ParticleType, Pos.x, Pos.y, Pos.z, 
											 V.x, V.y, V.z, 1.0f, 0, tmp->Color, tmp->DeltaColor, tmp->MaxAge); 

		tmp->LastShotTime = GFParent->GetTime();
		tmp->RoundsRemaining--;

		if(tmp->FireSoundLibIndex != -1)
		{
			GFParent->Sound.PlaySound(tmp->FireSoundLibIndex);
		}

		if(tmp->modifier != NULL)
		{
			tmp->modifier(tmp, GFParent);
		}
	}
}

/**************************Weapon Modifier Section************************/

void AlternateSidesModifier(WEAPON *weapon, GameFrame *gfparent)
{
	weapon->ShiftX = -weapon->ShiftX;
}

void RotateModifier(WEAPON *weapon, GameFrame *gfparent)
{
	static float angle = 0;

	weapon->ShiftX = weapon->Extra2 * (float)cos(angle);
	weapon->ShiftY = weapon->Extra2 * (float)sin(angle);

	angle += weapon->Extra1;
}

void ShiftXModifier(WEAPON *weapon, GameFrame *gfparent)
{
	static float angle = 0;
	weapon->ShiftX = weapon->Extra2 * (float)sin(angle);
	angle += weapon->Extra1;
}

void ShiftYModifier(WEAPON *weapon, GameFrame *gfparent)
{
	static float angle = 0;
	weapon->ShiftY = weapon->Extra2 * (float)sin(angle);
	angle += weapon->Extra1;
}

