// player.h: Beispielspieler für bobjects
// Harald Bögeholz / c't
#define ADDRESS DWORD

static const int MAX_BOBJECTS = 110;
static const int MAX_VXY = 50;			// Maximale Geschwindigkeit auf X- bzw. Y-Achse
static const int TARGET_LOCKED = 5;
static const int SHOT_SPEED = 8;

static const int TYPE_INV =  0;
static const int ASTR_1   =  1;
static const int ASTR_2   =  2;
static const int ASTR_3   =  3;
static const int ASTR_4   =  4;
static const int SHOT_X   =  5;


class BallisticObject
{
public:
	//bool valid;
	bool found;
	int	 step;
	int type;			// 0 - unbelegt/ungültig; 1 ... 4 - BallisticObject (äußere Form); 5 - Rakete

	int sf;				// scale factor: 0 = groß, 15 = mittel, 14 = klein (nur für Asteroiden)
	int x0, y0;			// Startposition (erste Koordinaten)
	int lastx, lasty;   // Aktuelle (letzte) Koordinaten
	int aimx, aimy;		// Koordinaten zum Zielen
	//int vx, vy;			// Geschwindigkeit
	int nxy1;			// Anzahl der 2. Koordinaten
	int x1[MAX_BOBJECTS], y1[MAX_BOBJECTS]; // Zwischenspeicher für alle plausiblen zweiten Koordinaten

	bool valid(void);
	void set(int x, int y, int type, int sf);		// Nur beim 1. Setzen verwendet
	int update(int fx, int fy, int ftype, int fsf); // Rückgabe: 0 - passt nicht; 1 - passt vielleicht; 2 - passt sicher
	int collides(int x, int y, int tolerance);
	int interpolate_x(int t);
	int interpolate_y(int t);
	bool getimpactpos(int sx, int sy, float angship, int *x, int *y); // Berechnet die Position, in der ein Schuss, der jetzt abgefeuert wird, und der Asteroid kollidieren würden
	float vx(void);
	float vy(void);
	float v(void);
};

class GameStatus
{
public:
	bool ship_present;  // Schiff sichtbar
	int ship_x;         // Mittelpunkt des Schiffs
	int ship_y;
	int ship_dx;        // Blickrichtung des Schiffes
	int ship_dy;
	float angship;
	bool saucer_present;// UFO sichtbar
	bool small_saucer;  // kleines UFO
	bool large_saucer;  // großes UFO
	int saucer_x;       // Mittelpunkt des UFOs
	int saucer_y;
	int saucer_size;    // Größe: 15 = groß, 14 = klein

	// Temporäre Asteroiden und Schüsse (Zwischenspeicher für Ast. und Schüsse auf dem Schirm)
	int ntmpbobjs; // Anzahl Asteroiden
	BallisticObject tmpbobjs[MAX_BOBJECTS];
	// "Ballistische Objekte" mit Flugbahn
	BallisticObject bobjects[MAX_BOBJECTS];

	float totspeeds[6];
	int spdcount[6];
	
	void clear(void);
	void init(void);
	int asteroidcount(void);
};

#pragma pack(1)
struct FramePacket
{
	char vectorram[1024];
	char frameno;  // wird bei jedem Frame inkrementiert
	char ping;     // Der Server schickt das letzte empfangene ping-Byte zurück
};

class KeysPacket
{
private:
	static const char KEY_HYPERSPACE = 1;
	static const char KEY_FIRE = 2;
	static const char KEY_THRUST = 4;
	static const char KEY_RIGHT = 8;
	static const char KEY_LEFT = 0x10;

	char signature[6];
	char keys;
public:
	char ping;     // wird vom Server bei nächster Gelegenheit zurückgeschickt. Für Latenzmessung.

	KeysPacket(void);
	void clear(void);         // alle Tasten loslassen
	void hyperspace(bool b);  // Hyperspace drücken (true) oder loslassen (false)
	void fire(bool b);        // Feuerknopf drücken (true) oder loslassen (false)
	void thrust(bool b);      // Beschleunigen ...
	void right(bool b);       // rechts drehen ...
	void left(bool b);        // links drehen
};
#pragma pack()

class Player
{
public:
	Player(SOCKET sd, ADDRESS server_ip) : sd(sd), server_ip(server_ip) {};
	void Run(void);
	void InterpretScreen(FramePacket &packet, GameStatus& game);
	void UpdateBObjects(GameStatus& game);
	void ReceivePacket(FramePacket &packet);
	void SendPacket(KeysPacket &packet);
private:
	SOCKET sd;
	ADDRESS server_ip;
};

