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

	Bubble Fight EX
	relminator
	http://rel.betterwebber.com


	Tentakill class


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

#include "Tentakill.h"

#define MIN_X ( -100 << 12 )
#define MIN_Y ( -18 << 12 )

#define MAX_TENTAKILLS 4


//------------------------------------------------------------------------------
//	Tentakill Enemy
//------------------------------------------------------------------------------
Tentakill::Tentakill()
{
	x = 300 << 12;
	y = 96 << 12;
	Dx = -floattof32(0.5);
	Dy = 0;
	
	Frame = 0;
	RotDir = -1;
	Active = false;
	Hp = 16;
	DrawMode = EN_NORMAL;
	
	for( int i = 0; i < TENTAKILL_MAX_SEGMENTS; i++ )
	{
		Segments[i][0].x  = i * 7;
		Segments[i][0].y  = 0;

		Segments[i][1].x  = 0;
		Segments[i][1].y  = i * 7;

		Segments[i][2].x  = -i * 7;
		Segments[i][2].y  = 0;

		Segments[i][3].x  = 0;
		Segments[i][3].y  = -i * 7;
	}
	
	
}

Tentakill::~Tentakill()
{
}


void Tentakill::Update()
{
	// Update spline
	//Points.Update();
	
	x += Dx;
	Dy = sinLerp( Counter * 230 ) * Radius;
	y = Sy + Dy;

	if( x < MIN_X )
	{
		Active = false;
		x = 300 << 12;
		y = 96 << 12;
	}
	
	Counter++;
	Rotation += RotDir;
	
	// animate
	if( ( Counter & 3 ) == 0 )
	{
		Frame = (Frame + 1) & 3;
	}

	for( int i = 0; i < TENTAKILL_MAX_SEGMENTS; i ++)
	{
		s32 t =  (Rotation*128) + (sinLerp((Rotation*512)+(i*2048)));
		for( int j = 0; j < 4; j++ )
		{
			Segments2[i][j].x = Segments[i][j].x * cosLerp(t) - Segments[i][j].y * sinLerp(t);
			Segments2[i][j].y = Segments[i][j].y * cosLerp(t) + Segments[i][j].x * sinLerp(t);
		}	
	}
	
}



//------------------------------------------------------------------------------
//	Tentakill Container
//------------------------------------------------------------------------------
//--------------------------------------
//	Ctor and Dtor
//--------------------------------------
TentakillContainer::TentakillContainer()
{
}
	
TentakillContainer::~TentakillContainer()
{
	Tentakills.clear();				// clear the bullets
}


void TentakillContainer::Init( int Palette, glImage* const Sprites )
{
	ColorTable = Palette;		// init needed data for drawing
	Images = Sprites;
	Tentakills.resize( MAX_TENTAKILLS/2 );			// 1/2 of max (speed of iteration)
	Tentakills.reserve( MAX_TENTAKILLS );		// reserve max for speed.  No need to do this for enemies
}

//--------------------------------------
//	Virtual Functions
//--------------------------------------
void TentakillContainer::UpdateEntities()
{
	
	std::vector<Tentakill>::iterator iter;
	for( iter = Tentakills.begin(); iter != Tentakills.end(); ++iter )
	{
		if( iter->Active )
			iter->Update();
	}
	
}

void TentakillContainer::DrawEntities()
{
	
	glColorTable( GL_RGB16, ColorTable );
	numEntities = 0;
	std::vector<Tentakill>::iterator iter;
	for( iter = Tentakills.begin(); iter != Tentakills.end(); ++iter )
	{
		if( iter->Active )
		{
			numEntities++;
			if( (iter->DrawMode == EN_WHITE) )
			{
				iter->DrawMode = EN_NORMAL;
				glColorTable( GL_RGB256, Palettes::Instance()->Red() );
				int f = iter->Frame;
				for( int i = 0; i < TENTAKILL_MAX_SEGMENTS; i ++)
				{
					int ff =  (f + i) & 3; 
					for( int j = 0; j < 4; j++ )
					{
						s32 tx = iter->Segments2[i][j].x;
						s32 ty = iter->Segments2[i][j].y;
						glSprite( ((iter->x >> 12) - 4) + (tx >> 12),
								  ((iter->y >> 12) - 4) + (ty >> 12), 
								  GL_FLIP_NONE, &Images[ff] 
								);
					}	
				}
				glColorTable( GL_RGB16, ColorTable );
			}
			else
			{
				int f = iter->Frame;
				for( int i = 0; i < TENTAKILL_MAX_SEGMENTS; i ++)
				{
					int ff =  (f + i) & 3; 
					for( int j = 0; j < 4; j++ )
					{
						s32 tx = iter->Segments2[i][j].x;
						s32 ty = iter->Segments2[i][j].y;
						glSprite( ((iter->x >> 12) - 4) + (tx >> 12),
								  ((iter->y >> 12) - 4) + (ty >> 12), 
								  GL_FLIP_NONE, &Images[ff] 
								);
					}	
				}
				
			}  // end if color table
						
			
		}  // end if active test
	}
	
}

bool TentakillContainer::Collide( StarFighter &Star )
{
	std::vector<Tentakill>::iterator iter;
	for( iter = Tentakills.begin(); iter != Tentakills.end(); ++iter )
	{
		if( iter->Active )
		{
			for( int i = 0; i < TENTAKILL_MAX_SEGMENTS; i ++)
			{
				for( int j = 0; j < 4; j++ )
				{
					int tx = ( iter->Segments2[i][j].x >> 12 ) + ( iter->x >> 12 );
					int ty = ( iter->Segments2[i][j].y >> 12 ) + ( iter->y >> 12 );
					int rad2 = 4 * 4;
					int cx = (tx) - (Star.x >> 12);
					int cy = (ty) - (Star.y >> 12);
					if( ( (cx * cx) + (cy * cy) ) < (rad2 * (1+Star.IsBursting())) )
					{
						if( Star.IsBursting() )
						{
							iter->Hp--;
							if( (iter->Hp & 3) == 0 ) Sound::Instance()->PlaySFX(E_SFX_HIT);
							if( iter->Hp < 0 )
							{
								iter->Active = false;
								Star.Score += 512;
								Sound::Instance()->PlaySFX(E_SFX_MEDEXP1);
								// Add some nice explosions
								for( int k = 0; k < TENTAKILL_MAX_SEGMENTS; k ++)
								{
									for( int l = 0; l < 4; l++ )
									{
										int xx = (iter->Segments2[k][l].x >> 12) + ( iter->x >> 12 );
										int yy = (iter->Segments2[k][l].y >> 12) + ( iter->y >> 12 );
										Explosion::Instance()->Spawn( xx,
													   yy,
													   0,
													   0,
													   EX_SMALL_4
													 );
									}
								}
								iter->x = 600 << 12;
								iter->y = 96 << 12;
								
						
							}
							if( iter->DrawMode == EN_NORMAL )
							{
								if( (iter->Counter & 1) ) iter->DrawMode = EN_WHITE;
							}
						}
						else
						{
							// kill star
							if( !Star.IsInvincible() ) Star.Kill();
						}
						
						return true;
					}
				}	
			}
			
			
		}
	}
	
	return false;
}


void TentakillContainer::KillAllEntities()
{
	std::vector<Tentakill>::iterator iter;
	for( iter = Tentakills.begin(); iter != Tentakills.end(); ++iter )
	{
		if( iter->Active )
		{
			iter->Active = false;
			iter->x = 600 << 12;
			iter->y = 96 << 12;
		}
	}
	
}


//--------------------------------------
//	Non-Virtual Functions
//--------------------------------------
void TentakillContainer::Spawn( int _x, int _sy, s32 speed, int _radius, int _rotation )
{
	static int rotdir = -1;
	rotdir = -rotdir;
	
	bool SlotFull = true;      		// value to check if all the slots are occupied
	
	std::vector<Tentakill>::iterator iter;
	for( iter = Tentakills.begin(); iter != Tentakills.end(); ++iter )
	{
		if( !iter->Active )		// insert a bullet on a free slot
		{
			iter->x = _x << 12;
			iter->Sy = _sy << 12;
			iter->Dx = speed;
			iter->Radius = _radius;
			iter->Active = true;
			iter->Frame = 0;
			iter->Counter = 0;
			iter->Rotation = _rotation;
			iter->RotDir = rotdir;
			iter->Hp = 16;
			SlotFull = false;			// there's a free slot so we dont execute the code below
			break;
		
		}
	}
	
	// All the slots are full
	// Only push back a bullet if the slot is full and we have less than numbullets
	if( SlotFull && (Tentakills.size() < MAX_TENTAKILLS) )
	{
		Tentakill tentakill;
		tentakill.x = _x << 12;
		tentakill.Sy = _sy << 12;
		tentakill.Dx = speed;
		tentakill.Radius = _radius;
		tentakill.Active = true;
		tentakill.Frame = 0;
		tentakill.Counter = 0;
		tentakill.Rotation = _rotation;
		tentakill.RotDir = rotdir;
		tentakill.Hp = 16;
		Tentakills.push_back(tentakill);
	}
	
}


	