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

	Space Impakto DS
	relminator
	http://rel.betterwebber.com


	Cturret class

Notes:

1. max_spawn_delay -> is the delay between waves for multi-bullet spawns
				it's also the delay for non-wave bullets
2. max_wave_delay -> delay between bullets on a wave. No effect on non-wave bullets

ie. 
	turret.angle_speed = 32768/12;
	turret.bullets_per_shot = 8;
	turret.max_wave = 3;
	turret.max_wave_delay = 8;
	turret.spread_angle = 32768/32;
	
	turret.spawn_delay = 0;
	turret.max_spawn_delay = 40; 
	turret.wave_counter = 0;
	
	* 8 bullets per shots, 3 waves of bullets before changing angle (32768/12)
	* 8 frames of delay before each bullet wave and each bullet is spread around at angle (32768/32)
	* after 3 waves, next wave is at 40 frames
	
	o  o  o  o  o  o  o  o  \
							  > 8 frames between waves
	   o o o o o o o o		/
		
		  oooooooo
								>>>>>> wait 40 frames to spawn another wave
		     T 

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


#include <nds.h>
#include <math.h>
#include <vector>

#include "Cvector2df32.h"
#include "Csound.h"

#include "cearn_atan.h"
#include "Cbullet.h"


#ifndef Cturret__H
#define Cturret__H



#define  BRAD_PI 16384 

#define  B_MIN_X (-20 << 12)
#define  B_MIN_Y (-20 << 12)
#define  B_MAX_X (256 << 12)
#define  B_MAX_Y (192 << 12)



enum E_WAVE_MODE
{
    EWM_SINGLE = 0,
	EWM_SPRAY_NORMAL,
    EWM_SPRAY_CENTERED,
    EWM_SPREAD_OFFSET,
    EWM_SPRAY_TARGET
};




using namespace std;

struct Tbullet_params
{
	
	s32				speed;
	s32				speed_delta;// if the bullet speed per wave is variable
	s32				offset;		// angle offset of each alternate bullet wave
	s32 			gx;
	s32 			gy;
	int 			delay;		// for changing behavior. ie: normal to target (note that EB_NORMAL can be targeting at start via turret)
	int 			energy;		// non-fp
	E_BULLET_TYPE	state;		// normal, accelerator or inv accelerator
	bool			smart;		// targeting or not (after counter == delay); 			
	
	int 			width;
	int				height;
	int				start_frame;// non-fp
	int				num_frames;	// non-fp
	int				anim_delay;
	int				death_ID;	// non-fp
	
	
};

struct Tturret_params
{

	int				active_time;
	int				active;					// non-fp
	bool			smart;					// if targeting or not
	int				x_radius;				// non-fp
	int				y_radius;				// non-fp
	s32				angle;
	s32				min_angle;
	s32				max_angle;
	s32				angle_speed;			// + rotation speed
	int				angle_dir;				// -1 or +1  determines rotation direction
	s32				spread_angle;			// distance of each bullet on a spread
	int				bullets_per_shot;
	int 			rotation_type;			// non-fp, whether back anf forth or not
	int				spawn_delay;			// non-fp
	int				max_spawn_delay;		// non-fp
	
	E_WAVE_MODE		wavemode;
	
	int				wave_counter;				// non-fp
	int 			max_wave;				// non-fp maximum bullets per wave
	int 			max_wave_delay;			// non-fp maximum delay for next shot in a wave
	
	Tbullet_params	bp;	
};


class Cturret
{
	public:
	Cturret();
	~Cturret();
	
	void update(Csound *_sound);
	void update();
	void init(Tturret_params &_tp, Cbullet *bullets);
	void reset(Tturret_params &_tp);
	void kill();
	void destroy();
	void copy_params(Tturret_params &_tp);
	void set_mode();
	void set_rotation();
	void shoot(Csound *sound);
	void shoot();
	void (*do_wave)(Cturret *t);
	void (*rotate)(Cturret *t);
	inline void set_target(Cvector2df32 *_target);
	inline void set_target(int _x, int _y);
	inline void set_position(Cvector2df32 *_pos);
	inline void set_position(int _x, int _y);
	
	int						active_time;	// numframes before index increments (countdown from max to zero)
	unsigned int			index;			// current index in vector turret params
	vector<Tturret_params>	parameters;		// array of turret behavior
	
	bool			active;					// non-fp
	bool			smart;					// if targeting or not
	Cvector2df32	default_coord;			// non-fp; safety reference pos and target initially points to
	Cvector2df32	default_pos;			// fp
	Cvector2df32	*pos;					// fp; should point to parent enemy or emitter
	Cvector2df32	*target;				// non-fp; should be a ptr to ship Cvector2df32
	s32				x;
	s32				y;
	s32 			dx;
	s32 			dy;
	int				x_radius;				// non-fp
	int				y_radius;				// non-fp
	s32				angle;
	s32				min_angle;
	s32				max_angle;
	s32				angle_speed;			// + rotation speed
	int				angle_dir;				// -1 or +1  determines rotation direction
	s32				spread_angle;			// distance of each bullet on a spread
	int				bullets_per_shot;
	int				rotation_type;			// non-fp, whether back anf forth or not
	int				spawn_delay;			// non-fp
	int				max_spawn_delay;		// non-fp
	
	
	E_WAVE_MODE		wavemode;
	
	int				wave_counter;			// non-fp
	int 			max_wave;				// non-fp maximum bullets per wave
	int 			max_wave_delay;			// non-fp maximum delay for next shot in a wave
	
	Tbullet_params	bp;	
	
	Cbullet			*p_bullets;				// ptr to Cbullet_array's p_bullet member
	
};

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

_target should point to ship

******************************************************************************/
inline void Cturret::set_target(Cvector2df32 *_target)
{
	target = _target;
}


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

_x and _y are absolute coords
user wants the target to point to

******************************************************************************/
inline void Cturret::set_target(int _x, int _y)
{
	default_coord.x = _x;
	default_coord.y = _y;
	target = &default_coord;
}


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

_pos should point to entity holding the turret with a Cvector2df32 pos member

******************************************************************************/
inline void Cturret::set_position(Cvector2df32 *_pos)
{
	pos = _pos;
}

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

	x and y are absolute coords

******************************************************************************/
inline void Cturret::set_position(int _x, int _y)
{
	default_pos.x = _x << 12;
	default_pos.y = _y << 12;
	pos = &default_pos;

}




#endif