class CShip
{
private:
	int num;
	float x,y;
	float dx,dy;
	float angle,anglev;			//angle is in rads
	float accel,angle_accel;
	float damp,angle_damp;
	BITMAP *pic;
	CAnim sheild_pic;
	SAMPLE *hit;
	int life;
	int max_life;
	int alive;

	CWep wep[20];				//ten possible weapons
	int current_wep;			//current weapon selected
	int number_of_weapons;		//total weapons the ship has

	int lives;
	int weapon_switch_timer;

	float old_dx, old_dy;

	int sheild_on;
	float sheild_angle;

	int disability_counter;
	int disability;

	int game_mode;
	float it_counter;

	int ai;			//0 means it is controlled by the player, 1 means it is ai controlled
	int walls_hurt;	//0 means walls don't hurt, 1 means they do

	int shoot_wait;

	int turn_dir;	//1 is left, 2 is right, 0 is straight
	int turn_time;	//the amount of time left to turn
	int move_time;

	int invincible_counter;

public:
	int it;

	void init(BITMAP *_pic, int _lives, int _num, CAnim _sheild_pic, SAMPLE *_hit, int _ai);
	void turn_left(void);
	void turn_right(void);
	void move_forward(void);
	void move(void);

	void draw(BITMAP *backgr, float sx, float sy);
	void set_pos(float _x, float _y);

	void destroy(void);
	void adjust_life(int amount);
	int check_dead(void);

	float ret_x(int centre);	//1 for centre means return pos of centre, otherwise top left
	float ret_y(int centre);

	float ret_dx(void);
	float ret_dy(void);

	void create_exaust(CParts *parts);

	void add_wep(BITMAP *pic, int damage, float speed, int type, int max_ammo, int max_cool, char *name,
		SAMPLE *launch);
	void shoot(CProjs *projs);

	void check_col_with_projs(CProjs *projs, CParts *parts);
	int check_col_with_powerups(CPowerups *powerups, CParts *parts);

	void draw_life(BITMAP *backgr, int x, int y, FONT *f, RGB colour);

	void check_col_with_walls(CWalls *walls);

	int respawn(float _x, float _y);

	void life_down(int amount, float d_angle);

	//checks to see if the ship is colliding with the given ship
	//handels all neccessay physics if they are touching
	int check_col_with_ship(CShip *ship);

	//returns 1 if the ship is colliding with the given rectangle
	int check_col_with_rect(float x1, float y1, float x2, float y2);

	void switch_weapon(void);

	void adjust_d(float _dx, float _dy);

	float ret_old_dx(void);
	float ret_old_dy(void);
	void update_old_d(void);

	void set_disability(int n);

	void set_ammo(int wep_no, int ammo);

	void toggle_it(void);
	void set_game_mode(int n);
	float ret_it_counter(void);

	void set_lives(int n);
	void up_lives(void);

	void set_ai(int n);
	int ret_ai(void);
	//void set_walls_hurt(int n);

	void ai_shoot(int wait, CProjs *projs);
	void ai_rotate(void);

    void run_complete_ai(CShip *enim, CProjs *projs);

	void drone_move(void);

	void set_life(int n);
	int ret_life(void);

	void check_col_with_asteroids(CAsteroids *ast, CParts *parts);

	int is_alive(void);

};

void CShip::run_complete_ai(CShip *enim, CProjs *projs)
{
    int tempx,tempy;
    float tx,ty;
    float temp_a;

    tx = enim->ret_x(1) + enim->ret_dx();
    ty = enim->ret_y(1) + enim->ret_dy();

	tempx = (int)(tx-x);
	tempy=  (int)(ty-y);

	temp_a = atan2(tempy, tempx);

	temp_a+=M_PI/2;

    /*if(angle < temp_a)
        turn_right();
    else if(angle > temp_a)
        turn_left();*/
    angle = temp_a;

    move_forward();
}

//returns the alive status of the ship (1=alive, 0=not alive)
int CShip::is_alive(void)
{
	return alive;
}

int CShip::ret_life(void)
{
	return life;
}

void CShip::up_lives(void)
{
	lives++;
}

void CShip::check_col_with_asteroids(CAsteroids *ast, CParts *parts)
{
	int ret=0;

	if(alive==1 && invincible_counter==0)
	{
		ret=ast->check_col_with_bmp(pic,x,y,parts);

		if(ret==1)
		{
			life-=200;
		}
	}
}

void CShip::set_life(int n)
{
	life=n;
}

void CShip::drone_move(void)
{
	if(turn_dir==1)
		turn_left();
	else if(turn_dir==2)
		turn_right();

	move_forward();


	if(turn_time==0)	//when turn timer hit zero, choose a new direction
	{
		turn_dir=rand()%2;
		if(turn_dir==1 || turn_dir==2)
			turn_time=8;
		else if(turn_dir==0)
			turn_time=20;
	}
}

void CShip::ai_rotate(void)
{
	angle+=Degree*3;
}

void CShip::ai_shoot(int wait, CProjs *projs)
{
	if(shoot_wait==0)
	{
		switch_weapon();
		shoot(projs);
		shoot_wait=wait;
	}
}


int CShip::ret_ai(void)
{
	return ai;
}

void CShip::set_ai(int n)
{
	ai=n;
	if(ai==1)
		walls_hurt=0;
	else 
		walls_hurt=1;
}



void CShip::set_lives(int n)
{
	lives=n;
}

float CShip::ret_it_counter(void)
{
	return it_counter;
}

void CShip::set_game_mode(int n)
{
	game_mode=n;
}

void CShip::toggle_it(void)
{
	if(it==0)
		it=1;
	else if(it==1)
		it=0;
}

void CShip::set_ammo(int wep_no, int ammo)
{
	wep[wep_no].set_ammo(ammo);
}

void CShip::set_disability(int n)
{
	disability=n;
	if(disability==1)
		disability_counter=stun_length;
}

float CShip::ret_old_dx(void)
{
	return old_dx;
}

float CShip::ret_old_dy(void)
{
	return old_dy;
}

void CShip::update_old_d(void)
{
	old_dx=dx;
	old_dy=dy;
}

void CShip::adjust_d(float _dx, float _dy)
{
	dx+=_dx;
	dy+=_dy;
}

void CShip::switch_weapon(void)
{
	int once=0;	//limits the number of times it will circle around checking for weapons with
	//ammo

	if(weapon_switch_timer==0 && game_mode!=1 && game_mode!=8)	//can't shoot in tag or asteroids avoid
	{
		do
		{
			current_wep++;
			if(current_wep>=number_of_weapons)
			{
				current_wep=0;
				once++;
			}
		}
		while(wep[current_wep].ret_ammo()==0 && once!=2);

		weapon_switch_timer=8;
	}
}

int CShip::check_col_with_rect(float x1,float y1, float x2, float y2)
{
	int ret=0;

	if(alive==1)
	{

	rectangle temp={(int)x1,(int)y1,(int)x2,(int)y2};
	rectangle me={(int)x,(int)y,(int)x+pic->w,(int)y+pic->h};

	ret=bounding_col(me,temp);

	}

	return ret;
}

void CShip::life_down(int amount, float d_angle)
{
	life-=amount;

	sheild_on=10;
	sheild_angle=d_angle;

	play_sample(hit,250,125,1000,FALSE);

}

int CShip::respawn(float _x, float _y)
{
	x=_x;
	y=_y;
	angle=0;
	life=max_life;
	alive=1;

	disability=0;
	sheild_on=0;

	invincible_counter=invincible_length;

	if(lives<=0)
	{
		alive=0;
		return 1;
	}
	else
		return 0;
}

int CShip::check_col_with_ship(CShip *ship)
{
	int ret=0;

	if(alive==1 && invincible_counter<=0)
	{

	
	if( ship->check_col_with_rect(x-6,y-4,x,y+pic->h+4) ==1 )
	{

		//the ship is colliding along the x axis, so make it move back a bit along the x axis
		//so that the two ships won't get stuch in each other
		x-=dx*2;

		//adjust the ship movement a bit for account for the other's ship's movement
		dx-=ship->ret_old_dx()/4;	//the ship is also affected by the other's ship momentum
		dy-=ship->ret_old_dy()/4;

		//adjust the other ship's movement to account for this ship's movement (before being
		//adjusted)
		ship->adjust_d(old_dx/4,old_dy/4);

		//if the other ship is not computer controlled (not a drone)
		if(ship->ret_ai()==0)
			//it's life goes down
			ship->life_down(5,0);

		dx*=-1.0;				//the ship bounces off
		

		if(walls_hurt==1)
			life_down(5,Degree*270);

		ret=1;
	}

	if( ship->check_col_with_rect(x+pic->w,y-4,x+pic->w+6,y+pic->h+4) ==1 )
	{

		x-=dx*2;
	//	y-=dy*2;
		
		dx-=ship->ret_old_dx()/4;
		dy-=ship->ret_old_dy()/4;


		ship->adjust_d(old_dx/4,old_dy/4);

		if(ship->ret_ai()==0)
			ship->life_down(5,0);

		dx*=-1.0;

		if(walls_hurt==1)
			life_down(5,Degree*90);

		ret=1;
	}

	if( ship->check_col_with_rect(x-4,y-6,x+pic->w+4,y) ==1 )
	{

	//	x-=dx*2;
		y-=dy*2;


		dx-=ship->ret_old_dx()/4;
		dy-=ship->ret_old_dy()/4;

		ship->adjust_d(old_dx/4,old_dy/4);

		if(ship->ret_ai()==0)
			ship->life_down(5,0);

		dy*=-1.0;

		if(walls_hurt==1)
			life_down(5,0);

		ret=1;
	}

	if( ship->check_col_with_rect(x-4,y+pic->h,x+pic->w+4,y+pic->h+6) ==1 )
	{

	//	x-=dx*2;
		y-=dy*2;

		dx-=ship->ret_old_dx()/4;
		dy-=ship->ret_old_dy()/4;

		ship->adjust_d(old_dx/4,old_dy/4);

		if(ship->ret_ai()==0)
			ship->life_down(5,0);

		dy*=-1.0;
		
		if(walls_hurt==1)
			life_down(5,Degree*180);

		ret=1;
	}

	}
/*	if(ret==1)	//ships hit
		if(game_mode==1)	//playing tag
			toggle_it();*/

	return ret;
}

void CShip::check_col_with_walls(CWalls *walls)
{
	//if it hits a wall make the ship bounce off in the correct direction
	//it's speed it also increased by 0.5 so that a ship does not get caught on the wall
	if(alive==1)
	{

	if( walls->check_col_with_rect((int)x-6,(int)y-4,(int)x,(int)y+pic->h+4) ==1 )
	{
		x-=dx*2;

		dx*=-1.0;
		if(walls_hurt==1)
			life_down(5,Degree*270);
	}

	if( walls->check_col_with_rect((int)x+pic->w,(int)y-4,(int)x+pic->w+6,(int)y+pic->h+4) ==1 )
	{
		x-=dx*2;
	//	y-=dy*2;

		dx*=-1.0;
		if(walls_hurt==1)
			life_down(5,Degree*90);
	}

	if( walls->check_col_with_rect((int)x-4,(int)y-6,(int)x+pic->w+4,(int)y) ==1 )
	{
	//	x-=dx*2;
		y-=dy*2;

		dy*=-1.0;
		if(walls_hurt==1)
			life_down(5,0);
	}

	if( walls->check_col_with_rect((int)x-4,(int)y+pic->h,(int)x+pic->w+4,(int)y+pic->h+6) ==1 )
	{
	//	x-=dx*2;
		y-=dy*2;
		
		dy*=-1.0;
		if(walls_hurt==1)
			life_down(5,Degree*180);
	}

	}
}

void CShip::draw_life(BITMAP *backgr, int x, int y, FONT *f, RGB colour)
{
	textprintf_ex(backgr,f,x,y,makecol(colour.r,colour.g,colour.b),-1,"%d",wep[current_wep].ret_ammo());
	textprintf_ex(backgr,f,x,y+20,makecol(colour.r,colour.g,colour.b),-1,"%d",life);

	if(game_mode==1)
		textprintf_ex(backgr,f,x+50,y+20,makecol(colour.r,colour.g,colour.b),-1,"%0.2f",it_counter);

	else
		textprintf_ex(backgr,f,x+50,y+20,makecol(colour.r,colour.g,colour.b),-1,"%d",lives);


	wep[current_wep].write_name(backgr,x+50,y,f,colour);

}

void CShip::check_col_with_projs(CProjs *projs, CParts *parts)
{
	int down=0;

	if(alive==1 && invincible_counter==0)
	{

	//life goes down by the amount of damage done
	down-=projs->check_col_with_bitmap(pic,(int)x,(int)y,num,parts);

	if(down==-1000)	//stun shot hit it
		set_disability(1);

	else if(down!=0)
		life_down(-down,/*projs->ret_angle()-M_PI*/angle);

	}
}

int CShip::check_col_with_powerups(CPowerups *powerups, CParts *parts)
{
	int num;
	int type=0,value=0;
	int ret=0;

	if(alive==1)
	{

	//life goes down by the amount of damage done
	num=powerups->check_col_with_bitmap(pic,x,y,parts);

	type=powerups->ret_type(num);
	value=powerups->ret_value(num);

	if(type>=1 && type<=12)		//types 1-12 are ammo
		wep[type].set_ammo(wep[type].ret_ammo()+value);

	ret=type;

	}
	return ret;
}


void CShip::shoot(CProjs *projs)
{
	if(game_mode!=1)	//can't shoot in tag
		if(number_of_weapons>0)	//only fire if the ship has some weapons
			//fires the shot from the centre of the ship using it's current angle
			wep[current_wep].shoot(projs,ret_x(1),ret_y(1),angle);
}

void CShip::add_wep(BITMAP *pic, int damage, float speed, int type, int max_ammo, int max_cool, char *name,
					SAMPLE *launch)
{
	if(number_of_weapons<=19)
	{
		wep[number_of_weapons].create(pic,damage,speed,type,max_ammo,max_cool,num,name,launch);
		number_of_weapons++;
	}
}


void CShip::create_exaust(CParts *parts)
{
	RGB col={150,150,150};

	float mx=0,my=0;
	float ang=0;
	float speed=0;
	int col_amount;

	for(int n=0 ; n<5 ; n++)
	{

		ang=rand()%2000;
		ang-=100;
		ang/=100;
		ang/=Rad2AllegroDeg;

		speed=rand()%10;
		speed+=2;
		speed/=10;

		col_amount=rand()%100;
		col_amount+=50;

		col.r=col_amount;
		col.g=col_amount;
		col.b=col_amount;

		ang+=angle;

		mx = sin(ang);  
		my = -cos(ang);

		parts->create_new(x+pic->w/2,y+pic->h/2,col,-mx,-my, speed ,1);
	}

}


float CShip::ret_x(int centre)
{
	if(centre==1)
		return(x + (pic->w/2) );
	else
		return x;
}

float CShip::ret_y(int centre)
{
	if(centre==1)
		return(y + (pic->h/2) );
	else
		return y;
}

float CShip::ret_dx(void)
{
	return dx;
}

float CShip::ret_dy(void)
{
	return dy;
}

int CShip::check_dead(void)
{
	//returns 1 only at the time when it dies
	if(life<=0 && alive==1)
	{
		alive=0;
		lives--;

		dx=0;
		dy=0;
		angle=0;
		anglev=0;

		return 1;
	}
	else 
		return 0;
}

void CShip::adjust_life(int amount)
{
	life+=amount;
}

void CShip::destroy(void)
{
	//destroy_bitmap(pic);
	sheild_pic.dest();
	//destroy_sample(hit);
	for(int n=0 ; n<number_of_weapons ; n++)
		wep[n].dest();
}

void CShip::set_pos(float _x, float _y)
{
	x=_x;
	y=_y;
	angle=0;
}


void CShip::draw(BITMAP *backgr, float sx, float sy)
{
	int on;
	if(alive==1)
	{
		if(invincible_counter%5==0)
			rotate_sprite(backgr,pic,(int)x-(int)sx, (int)y-(int)sy,itofix((int)(angle*Rad2AllegroDeg)));

		if(sheild_on>0)
		{
			//draw_trans_sprite(backgr,sheild_pic,(int)x-(int)sx, (int)y-(int)sy);
			set_trans_blender(200,200,200,150);
			if(sheild_pic.draw_anim(backgr,(int)x-(int)sx,(int)y-(int)sy,2,1,3)==1000)
				sheild_on=0;
		}
		else if(disability==1)
		{
			set_trans_blender(0,255,0,255);
			sheild_pic.draw_anim(backgr,(int)x-(int)sx,(int)y-(int)sy,2,1,3);
		}

		if(it==1)
		{
			circle(backgr,(int)x+pic->w/2,(int)y+pic->h/2,8,makecol(255,10,0));
		}

	}
}

void CShip::move_forward(void)
{
	if(alive==1 && disability!=1)	//disability 1 means ship is stunned (can't move fwrd)
	{
		dx += accel * sin(angle);  
		dy -= accel * cos(angle);
	}

}

void CShip::move(void)
{
	if(alive==1)
	{
		anglev*=angle_damp;
		angle+=anglev;

		if(angle>2*M_PI)
			angle=0;
		if(angle<0)
			angle=2*M_PI;

		dx *=damp;
		dy *=damp;
		x+=dx;
		y+=dy;


		//if ship goes off of the edge of the screen it move it to the opposite side
		if(x>630-pic->w)
			x=10;

		else if(x<10)
			x=630-pic->w;

		if(y>420-pic->h)
			y=10;
		else if(y<10)
			y=420-pic->h;

		if(weapon_switch_timer>0)
			weapon_switch_timer--;

		//if(sheild_on>0)
		//	sheild_on--;

		if(disability_counter>0)
			disability_counter--;
		else
			disability=0;

		//goes through all of the ship's weapons and counts down the cooldown time left
		for(int n=0 ; n<number_of_weapons ; n++)
			wep[n].count();

		if(it==1)
			it_counter+=0.025;

		if(shoot_wait>0)
			shoot_wait--;

		if(turn_time>0)
			turn_time--;

		if(move_time>0)
			move_time--;

		if(invincible_counter>0)
			invincible_counter--;
	}
}

void CShip::turn_left(void)
{
	if(alive==1 && disability!=1)
		anglev-=angle_accel;
}

void CShip::turn_right(void)
{
	if(alive==1 && disability!=1)
		anglev+=angle_accel;
}

void CShip::init(BITMAP *_pic, int _lives, int _num, CAnim _sheild_pic, SAMPLE *_hit, int _ai)
{
	x=0;
	y=0;
	dx=0;
	dy=0;
	angle=0;
	anglev=0;

	accel=0.06;			//ship accel 0.05 is good for a damp of 0.99, 0.06 for 0.98
	damp =0.985;			//speed ship stops(ie friction) 0.99 stops slowly, 0.98 stops med 
	angle_accel=0.02;	//speed ship turns at 0.01 is good, 0.02 is too fast
	angle_damp=0.90;	//speed ship stops turning	.90 is good
	pic=_pic;
	life=100;
	max_life=100;
	alive=1;
	current_wep=0;
	number_of_weapons=0;

	lives=_lives;
	num=_num;

	weapon_switch_timer=0;

	old_dx=0;
	old_dy=0;

	sheild_pic=_sheild_pic;
	hit=_hit;

	sheild_on=0;

	//lives=10;
	it=0;
	it_counter=0;

	ai=_ai;

	if(ai==1)
		walls_hurt=0;
	else 
		walls_hurt=1;

	shoot_wait=0;

	turn_time=0;
	turn_dir=0;
	move_time=0;

	invincible_counter=invincible_length;

}

