#include "playback.cpp"
#include "physics.cpp"
#include <fstream.h>
#include <math.h>

#define pi 3.1415926535

BITMAP *buf;
BITMAP *bg;
BITMAP *sky;
BITMAP *ground;
BITMAP *mousebmp;
BITMAP *scorch;
BITMAP *explosionanim[16];
BITMAP *explosionsmallanim[24];
BITMAP *smokeanim[24];
BITMAP *redanim[24];
BITMAP *yellowanim[24];
BITMAP *whiteanim[24];
BITMAP *splashanim[6];
BITMAP *misstrailanim[9];
BITMAP *tankbarrelanim[10];
BITMAP *exptemp;
BITMAP *bombbmp;
BITMAP *missilebmp;
BITMAP *shell;
BITMAP *debrisr[4];
BITMAP *debrisrm[4];
BITMAP *debris1;
BITMAP *debriso1;
BITMAP *grounddebris1;


BITMAP *tankbase;
BITMAP *tankbasee;
BITMAP *tankd;
BITMAP *tankde;

BITMAP *planeunoc;
BITMAP *planeocc;
BITMAP *planefiring;
BITMAP *planeexp;
BITMAP *planedamaged;
BITMAP *planedamagedo;
BITMAP *planedamagedf;

BITMAP *planeunoce;
BITMAP *planeocce;
BITMAP *planefiringe;
BITMAP *planeexpe;
BITMAP *planedamagede;
BITMAP *planedamagedoe;
BITMAP *planedamagedfe;

BITMAP *heliunoc;
BITMAP *heliocc;
BITMAP *helifiring;
BITMAP *heliexp;
BITMAP *helidamaged;
BITMAP *helidamagedo;
BITMAP *helidamagedf;

BITMAP *heliunoce;
BITMAP *heliocce;
BITMAP *helifiringe;
BITMAP *heliexpe;
BITMAP *helidamagede;
BITMAP *helidamagedoe;
BITMAP *helidamagedfe;


FILE *debug;

movie *script;

long tmpkeys;
bool recording;

MIDI *music;
SAMPLE *mgun;
SAMPLE *explode;
SAMPLE *explodesmall;
SAMPLE *engine;
SAMPLE *prop;
SAMPLE *enginestart;
SAMPLE *propstart;
SAMPLE *death1;
SAMPLE *bombdrop;
SAMPLE *aagunfire;
SAMPLE *tankfire;
SAMPLE *gurgle;
SAMPLE *splash;

atom *center;

int path[4000];
int debrislev[4000];

extern int magenta;
int mx, my, slx;
int omouse_x, omouse_y;
int nmouse_x, nmouse_y;

float convk;
float convk2;
float lx, rx;
int numsplashes;

extern int COMPFRAMES;

extern atom *structure[100][100];

#define LEFT 0
#define RIGHT 1
#define MAXBULLETS 100
#define MAXBOMBS 10
#define MAXSOLDIERS 50
#define MAXCOMPSOLDIERS 50
#define MAXANIMATIONS 1000
#define MAXTRAILANIMS 300
#define MAXAAGUNS 10
#define MAXJEEPS 10
#define MAXPLANES 10
#define MAXHELIS 10
#define MAXTANKS 10
#define ENEMY 1
#define FRIEND 0
#define BOMB 0
#define MISSILE 1

#define DRAWING 1
#define WINDOWED 0

bool tmplevels[MAXLEVELS];

int level;
int frame;
int drawframe;
int waterlevel;

bool dispframe;

int screencenterx;			//Center of window / screen
int pan;
int vol;

/*		**LEVELS**

  0: Nothing interacts with this. Used for debris
  1: The human player
  2: The upper part of buildings (that the player cannot walk through)
  3: The human's bullets
  4: The lower part of buildings (that the player can walk through)
  5: Enemy soldiers
  6: Enemy bullets
  7: Empty vehicles
  8: Corpses
  9: Acts like bullets (bomb bullets)
  10: Personnel bullets
  11: Friendly controlled vehicles
  12: Enemy controlled vehicles
  13: Friendly bombs
  14: Enemy bombs
  15: Gravity-less, non-interacting atoms (Plane's wheel)
 
*/

void dopan(float x) {
	pan = (x - screencenterx) * 0.2 + 128;
	if(pan > 255) pan = 255;
	if(pan < 0) pan = 0;
}

void dovol(float x, float k) {
	vol = 255 - abs(x - screencenterx) * k;
	if(vol < 0) vol = 0;
}

void dopanvol(float x, float k) {
	pan = (x - screencenterx) * 0.2 + 128;
	if(pan > 255) pan = 255;
	if(pan < 0) pan = 0;
	vol = 255 - abs(x - screencenterx) * k;
	if(vol < 0) vol = 0;
}

void setupgrid(float aposx[100][100], float aposy[100][100]) {
	int x, y;
	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			aposx[x][y] = x * 10;
			aposy[x][y] = y * 10;
		}
	}
}

void setupmass(float amass[100][100]) {
	int x, y;
	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			amass[x][y] = 1;
		}
	}
}

void settmplevels() {
	int i;	
	for(i = 1; i < MAXLEVELS; i++) {
		tmplevels[i] = true;
	}
	tmplevels[0] = false;
	tmplevels[8] = false;
	tmplevels[10] = false;
	tmplevels[15] = false;
}

void cleartmplevels() {
	int i;	
	for(i = 0; i < MAXLEVELS; i++) {
		tmplevels[i] = false;
	}
}

void adddebris(atom *a, bool accrue) {
	//destroyatom(a);
	//return;
	if(a->fixed) return;
	debrisitem *d;
	int i;

	d = &(debris[0]);
	for(i = 0; i < MAXDEBRIS; i++) {
		if(!d->on) {
			d->me = a;
			d->on = true;
			d->me->debris = true;
			d->me->level = 0;
			d->me->d = d;
			//if(d->me->bmp == NULL) exit(0);
			d->accrue = accrue;
			for(i = 0; i < MAXLEVELS; i++) {
				d->me->levels[i] = false;
			}
			break;
		}
		d++;
	}
}

struct bullet {
	atom *me;
	int life;
	bool drew;
	bool todraw;
	int width;
	int color;

	bullet() {
		init();
	}

	void init() {
		me = NULL;
		life = -1;
		drew = false;
		todraw = true;
		width = 1;
		color = black;
	}

	void update() {
		if(me == NULL) return;
		me->iy -= GRAVITY;
		life--;
		//if(life < 1000 && change > 1.5 || (abs((int)me->ix) < .1 && abs((int)me->iy) < .1)) life = 0;
		if((fabs(me->ix) * me->rmdt < .5 && fabs(me->iy) * me->rmdt < .5)) life = 0;
		if(life <= 0) {
			destroyatom(me);
			me = NULL;
			life = -1;
		}
	}

	void draw() {
		if(!todraw || color == -1) return;

		if(width != 1) {
			int points[8];
			int p1x, p2x, p1y, p2y;
			float m = -me->ix / me->iy;
			float ox, oy, od;
			ox = 1; oy = m;
			od = sqrt(ox * ox + oy * oy);
			ox = ox / od;
			oy = oy / od;
			ox *= width * 0.5;
			oy *= width * 0.5;
			p1x = me->x;
			p1y = me->y;
			p2x = p1x - me->ix * 10 * me->rmdt;
			p2y = p1y - me->iy * 10 * me->rmdt;
			
			points[0] = p1x - ox;
			points[1] = p1y - oy;
			points[2] = p1x + ox;
			points[3] = p1y + oy;
			points[4] = p2x + ox;
			points[5] = p2y + oy;
			points[6] = p2x - ox;
			points[7] = p2y - oy;

			polygon(buf, 4, points, color);
			line(buf, points[0], points[1], points[2], points[3], black);
			line(buf, points[2], points[3], points[4], points[5], black);
			line(buf, points[4], points[5], points[6], points[7], black);
			line(buf, points[6], points[7], points[0], points[1], black);
			drew = true;
		}
		else {
			//float m = me->iy / me->ix;
			int p1x, p2x, p1y, p2y;
			p1x = me->x;
			p1y = me->y;
			p2x = p1x - me->ix * 2;
			p2y = p1y - me->iy * 2;
			if((p1x > lx && p1x < rx) || (p2x > lx && p2x < rx)) {
				line(buf, p1x, p1y, p2x, p2y, color);
				drew = true;
			}
		}
	}

	void erase() {
		if(!todraw) return;
		if(width == 1) {
			//float m = me->iy / me->ix;
			if(!drew) return;
			int p1x, p2x, p1y, p2y;
			p1x = me->x;
			p1y = me->y;
			p2x = p1x - me->ix * 2;
			p2y = p1y - me->iy * 2;
			do_line(buf, p1x, p1y, p2x, p2y, 0, cleanline);
			drew = false;
		}
		else {
			int p1x, p2x, p1y, p2y, nx, ny, nw, nh;
			p1x = me->x;
			p1y = me->y;
			p2x = p1x - me->ix * 4;
			p2y = p1y - me->iy * 4;
			nx = findlow(p1x, p2x) - 2 * width;
			ny = findlow(p1y, p2y) - 2 * width;
			nw = findhigh(p1x, p2x) - nx + 4 * width;
			nh = findhigh(p1y, p2y) - ny + 4 * width;
			blit(bg, buf, nx, ny, nx, ny, nw, nh);
		}			
	}
};

bullet bullets[MAXBULLETS];

bullet *addbullet(float, float, float, float, int, int, float, int, int, bool);

void addanimation(BITMAP **newframes, int newnumframes, int newx, int newy, bool trans, float dy, int delay, int rand);

struct bomb {
	atom *me;
	BITMAP *bmp;
	bool drew;
	bool on;
	bool dud;

	bomb() {
		init();
	}

	void init() {
		me = NULL;
		drew = false;
		on = false;
		dud = true;
	}

	void update() {
		if(!on) return;
		float cx, cy, cd;
		cx = me->ix - me->oix;
		cy = me->iy - me->oiy;

		cy -= GRAVITY;
		cd = sqrt(cx * cx + cy * cy);
		cd = fabs(cd);
		
		if(cd > 0.05) {
			bullet *b;
			on = false;
			float ang = 0;
			int py;
			float ca, sa;
			atom *a;
			int count = 0;

			py = path[(int)me->x];

			for(ang = 0; ang < 2*pi; ang += (2*pi) / 10) {
				count++;
				ca = cos(ang);
				sa = sin(ang);
				if(!dud) {
					b = addbullet(me->x, me->y, 20 * ca, 20 * sa, 3, 10, 20, 1, gray, false);
					if(b && b->me) {
						b->me->dmult = 100;
					}
					b = addbullet(me->x, me->y, 20 * ca, 20 * sa, 3, 30, 20, 1, -1, true);
					if(b && b->me) {
						b->me->dmult = 100;
					}
				}
				if(me->y > py - 20) {
					cleartmplevels();
					a = addatom(me->x, py - 15, tmplevels, 0);
					a->ix = (rand() % 10 / 10.0) * ca;
					a->iy = (rand() % 10 / 10.0) * sa;
					a->bmp = create_bitmap(14, 14);
					blit(grounddebris1, a->bmp, 0, 0, 0, 0, 14, 14);
					adddebris(a, false);
				}
				if(count % 1 == 0) {
					tmplevels[1] = true;
					tmplevels[5] = true;
					a = addatom(me->x, me->y, tmplevels, 10);
					//a->ix = (rand() % 10 / 3.0) * ca;
					//a->iy = (rand() % 10 / 3.0) * sa;
					a->ix = 1.5 * ca;
					a->iy = 1.5 * sa;
					a->life = 40;
					a->draw = true;
					a->color = magenta;
					//a->bmp = create_bitmap(14, 14);
//void addtrailanim(atom *a, BITMAP **anim, int frames, int mod, int modoff, int life, float dy, int rand, bool trans, int delay);
					addtrailanim(a, explosionsmallanim, 24, 5, 0, 100, -2, 5, false, -3);
					//blit(bombdebris1, a->bmp, 0, 0, 0, 0, 14, 14);
					adddebris(a, false);
				}
			}
			addanimation(explosionanim, 16, me->x - 32, me->y - 37, true, 0, 1, 0);
			dopanvol(me->x, 0.1);
			play_sample(explode, vol, pan, 1000, 0);

			if(me->y > py - 5) {				
				BITMAP *tmp;
				int py, pyr, nx;
				tmp = create_bitmap(60, 60);
				blit(bg, tmp, me->x - 27, me->y - 19, 0, 0, 60, 60);
				draw_trans_sprite(tmp, scorch, 0, 0);
				for(int xp = 0; xp < 60; xp++) {
					nx = (int)xp + (int)me->x - 27;
					if(nx > 0 && nx < buf->w - 1) {
						py = path[(int)xp + (int)me->x - 27] + 1;
						pyr = py - me->y + 20 + 1;
						blit(tmp, bg, xp, pyr, xp + me->x - 27, py, 1, 60 - pyr);
						blit(tmp, buf, xp, pyr, xp + me->x - 27, py, 1, 60 - pyr);
					}
					//blit(tmp, buf, xp, 0, xp + a->x - 27, a->y - 20, 1, path[(int)xp] - (a->y - 22));
				}
				destroy_bitmap(tmp);
				tmp = NULL;
			}

			destroyatom(me);
			me = NULL;
		}
	}

	void draw() {
		if(!on) return;
		if(me->x + 5 > lx && me->x - 5 < rx) {
			float angle;
			angle = atan2(me->iy, me->ix);
			angle *= convk;
			if(bmp == bombbmp) rotate_sprite(buf, bmp, me->x - 5, me->y - 2, itofix(angle));
			else pivot_sprite(buf, bmp, me->x, me->y, 0, 3, itofix(angle));
			drew = true;
		}
	}

	void erase() {
		if(!on) return;
		if(!drew) return;
		drew = false;
		if(bmp == bombbmp) blit(bg, buf, me->x - 8, me->y - 8, me->x - 8, me->y - 8, 16, 16);
		else blit(bg, buf, me->x - 15, me->y - 15, me->x - 15, me->y - 15, 30, 30);
	}
};

bomb bombs[MAXBOMBS];
int numbombs;

bullet *addbullet(float x, float y, float ix, float iy, int comp, int life, float dmult, int width, int color, bool personnel) {
	bullet *b;
	int i;
	int level;

	settmplevels();
	if(personnel) {
		cleartmplevels();
		tmplevels[1] = true;
		tmplevels[5] = true;
		tmplevels[13] = false;
		tmplevels[14] = false;
		level = 10;
	}
	else if(comp == 0) {
		tmplevels[1] = false;
		tmplevels[3] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		tmplevels[9] = false;
		tmplevels[11] = false;
		tmplevels[13] = false;
		tmplevels[14] = false;
		level = 3;
	}
	else if(comp == 1) {
		tmplevels[2] = false;
		tmplevels[3] = false;
		tmplevels[4] = false;
		tmplevels[5] = false;
		tmplevels[6] = false;
		tmplevels[9] = false;
		tmplevels[12] = false;
		tmplevels[13] = false;
		tmplevels[14] = false;
		level = 6;
	}
	else if(comp == 3) {
		tmplevels[9] = false;
		tmplevels[13] = false;
		tmplevels[14] = false;
		level = 9;
	}

	b = &(bullets[0]);
	for(i = 0; i < MAXBULLETS; i++) {
		if(b->life < 0) {
			b->life = life;
			b->me = addatom(x, y, tmplevels, level);
			if(comp != 3) {
				//ix *= 0.2;
				//iy *= 0.2;
			}
			b->me->ix = ix;
			b->me->iy = iy;
			b->me->dmult = dmult;
			b->width = width;
			b->todraw = true;
			b->color = color;
			if(comp != 3) {
				b->me->rmdt = 1;
			}
			else {
				b->todraw = false;
				b->me->rmdt = 0.1;
			}
			return b;
			break;
		}
		b++;
	}
	return NULL;
}

bomb *addbomb(float x, float y, float ix, float iy, bool comp, BITMAP *bmp, int bombtype) {
	bomb *b;
	int level;
	int i;
	bool dud;

	settmplevels();

	if(rand() % 3 == 0) dud = false;
	else dud = true;
	
	dud = false;

	if(dud) {
		cleartmplevels();
		level = 0;
	}
	else if(!comp) {
		tmplevels[1] = false;
		tmplevels[3] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		tmplevels[9] = false;
		tmplevels[10] = false;
		tmplevels[11] = false;
		tmplevels[13] = false;
		tmplevels[14] = false;
		level = 13;
	}
	else {
		tmplevels[2] = false;
		tmplevels[3] = false;
		tmplevels[4] = false;
		tmplevels[5] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		tmplevels[9] = false;
		tmplevels[10] = false;
		tmplevels[12] = false;
		tmplevels[13] = false;
		tmplevels[14] = false;
		level = 14;
	}

	b = &(bombs[0]);
	i = 0;
	while(i < MAXBOMBS && b->on) {b++; i++;}
	if(i >= MAXBOMBS) return NULL;
	b->on = true;
	b->me = addatom(x, y, tmplevels, level);
	if(bombtype == MISSILE) b->me->mass = 0;
	b->me->ix = ix;
	b->me->iy = iy;
	b->me->oix = ix;
	if(bombtype == BOMB) b->me->oiy = iy + GRAVITY;
	else b->me->oiy = iy;
	b->me->rmdt = 1;
	b->bmp = bmp;
	b->dud = dud;
	if(b == &(bombs[numbombs]))
		numbombs++;
	return b;
}

typedef struct soldier soldier;

struct animation {
	BITMAP **frames;
	int aframe;
	int numframes;
	float x, y;
	bool on;
	bool drew;
	bool trans;
	int w, h;
	float dy;
	int delay;
	int randoff;

	animation() {
		reset();
	}

	void reset() {
		aframe = 0;
		on = false;
		trans = false;
		delay = 1;
	}

	void init(BITMAP **newframes, int newnumframes, int newx, int newy, float newdy, int newdelay, int newrand) {
		frames = newframes;
		numframes = newnumframes;
		aframe = 0;
		x = newx;
		y = newy;
		w = frames[0]->w;
		h = frames[0]->h;
		on = true;
		dy = newdy;
		delay = newdelay;
		randoff = newrand;
	}

	void draw() {
		if(!on) return;
		if(aframe == numframes) {
			on = false;
		}
		else if(x + w > lx && x < rx) {
			drew = true;
			y += dy;
			if(dy != 0) {
				x += rand() % randoff * 0.1 - 0.05 * randoff;
				y += rand() % randoff * 0.1 - 0.05 * randoff;
			}
			if(trans) draw_trans_sprite(buf, frames[aframe], x, y);
			else draw_sprite(buf, frames[aframe], x, y);
			if(delay < 0) {
				aframe += -delay;
				if(aframe > numframes) aframe = numframes;
			}
			else if(delay == 1 || drawframe % delay == 0) {
				aframe++;
			}
		}
		else if(delay == 1 || drawframe % delay == 0) {
			y += dy;
			aframe++;
		}
	}

	void erase() {
		if(!on || !drew) return;
		blit(bg, buf, x, y, x, y, w, h);
		drew = false;
	}
};

animation animations[MAXANIMATIONS];
int numanimations;

void addanimation(BITMAP **newframes, int newnumframes, int newx, int newy, bool trans, float dy, int delay, int rand) {
	animation *a;
	int i;
	a = &(animations[0]);
	i = 0;
	while(i < MAXANIMATIONS && a->on) {a++; i++;}
	if(i >= MAXANIMATIONS) return;
	a->init(newframes, newnumframes, newx, newy, dy, delay, rand);
	a->trans = trans;
	if(a == &(animations[numanimations]))
		numanimations++;
}

void drawanimations() {
	animation *a;
	int i;

	a = &(animations[0]);
	for(i = 0; i < numanimations; i++) {
		a->draw();
		a++;
	}
}

void eraseanimations() {
	animation *a;
	int i;

	a = &(animations[0]);
	for(i = 0; i < numanimations; i++) {
		a->erase();
		a++;
	}
}

struct trailanim {
	int life;
	atom *me;
	int mod;
	int modoff;
	BITMAP **anim;
	int animframes;
	float dy;
	int randoff;
	bool trans;
	int wot, hot;
	int delay;

	trailanim() {
		reset();
	}
	
	void reset() {
		life = 0;
		me = NULL;
		mod = 100;
		modoff = 0;
		anim = NULL;
		animframes = 0;
		trans = false;
		wot = 0;
		hot = 0;
	}

	void init(atom *newme, BITMAP **newanim, int newanimframes, int newmod, int newmodoff, int newlife, float newdy, int newrandoff, bool newtrans, int newdelay) {
		me = newme;
		anim = newanim;
		animframes = newanimframes;
		mod = newmod;
		modoff = newmodoff;
		life = newlife;
		dy = newdy;
		randoff = newrandoff;
		trans = newtrans;
		wot = (newanim[0])->w * 0.5;
		hot = (newanim[0])->h * 0.5;
		delay = newdelay;
	}

	void update() {
		if(life <= 0) return;
		life--;
		if(me->on == false)
			life = 0;
		else {
			if((frame + modoff) % mod == 0) {
				
				//init(BITMAP **newframes, int newnumframes, int newx, int newy, float newdy, int newdelay, int newrand) {
				addanimation(anim, animframes, me->x + rand() % (2 * randoff) - randoff - wot, me->y + rand() % (2 * randoff) - randoff - hot, trans, dy, delay, 1);
			}
		}
	}
};

trailanim trailanims[MAXTRAILANIMS];
int numtrailanims;

void addtrailanim(atom *a, BITMAP **anim, int frames, int mod, int modoff, int life, float dy, int rand, bool trans, int delay) {
	trailanim *t;
	int i;
	t = &(trailanims[0]);
	i = 0;
	while(i < MAXTRAILANIMS && t->life > 0) {i++; t++;}
	if(i < MAXTRAILANIMS) {
		t->init(a, anim, frames, mod, modoff, life, dy, rand, trans, delay);
		if(t == &(trailanims[numtrailanims]))
			numtrailanims++;
	}
}

void updatetrailanims() {
	trailanim *a;
	int i;

	a = &(trailanims[0]);
	for(i = 0; i < numtrailanims; i++) {
		a->update();
		a++;
	}
}

struct aagun {
	BITMAP *hold;
	BITMAP *barrel;
	BITMAP *base;
	BITMAP *baseo;
	BITMAP *baseoe;
	BITMAP *gunbg;
	float angle;
	float fangle;
	float dangle;
	float x, y;
	int offx, offy;
	int w, h;
	float speed;
	bool direction;
	bool occupied;
	bool destroyed;
	soldier *driver;
	int fired;
	float bulletforce;
	int numfired;
	bool drew;

	bool *fire;
	float tx, ty;

	aagun() {
		hold = NULL;
		reset();
	}

	void reset() {
		angle = 192;
		fangle = 192;
		dangle = 0;
		speed = 0.1;
		direction = RIGHT;
		occupied = false;
		destroyed = false;
		tx = ty = 0;
		fired = 0;
		bulletforce = 15;
		numfired = 0;
		if(hold != NULL) clear_to_color(hold, magenta);
		drew = false;
	}


	void init(float nx, float ny) {
		x = nx;
		y = ny;
		offx = 8;
		offy = 26;
		w = 63;
		h = 43;
		hold = create_bitmap(w, h);
		clear_to_color(hold, magenta);
		tx = x + 10;
		ty = y;
	}

	void getin(soldier *newdriver) {
		driver = newdriver;
		if(destroyed) return;
		if(occupied == false) {
			occupied = true;
		}
		else {
			occupied = false;
		}
	}

	void update();

	void draw();

	void erase() {
		if(!drew) return;
		blit(bg, buf, x, y, x, y, w, h);
		drew = false;
	}
};

aagun aaguns[MAXAAGUNS];
int numaaguns;

aagun *addaagun(float x, float y) {
	aagun *a;
	a = &(aaguns[numaaguns]);
	numaaguns++;
	a->init(x, y);
	return a;
}

void drawaaguns() {
	aagun *a;
	int i;
	a = &(aaguns[0]);
	for(i = 0; i < numaaguns; i++) {
		a->draw();
		a++;
	}
}

void updateaaguns() {
	aagun *a;
	int i;
	a = &(aaguns[0]);
	for(i = 0; i < numaaguns; i++) {
		a->update();
		a++;
	}
}	

void eraseaaguns() {
	aagun *a;
	int i;
	a = &(aaguns[0]);
	for(i = 0; i < numaaguns; i++) {
		a->erase();
		a++;
	}
}

struct jeep {
	rigidbody *me;
	bool occupied;
	float strength;
	object *myobj;
	BITMAP *unoc;
	BITMAP *unocl;
	BITMAP *occ;
	BITMAP *occl;
	BITMAP *exp;
	BITMAP *expl;
	float damage;
	soldier *driver;

	volatile char *keyleft;
	volatile char *keyright;
	volatile char *keyup;
	volatile char *keydown;

	bool direction;
	int engvoice;
	int engstartvoice;
	bool engstarted;
	bool destroyed;
	bool on;

	jeep() {
		reset();
	}

	void reset() {
		occupied = false;
		//strength = 0.06;
		strength = 0.1;
		keyleft = &(key[KEY_A]);
		keyright = &(key[KEY_D]);
		keyup = &(key[KEY_W]);
		keydown = &(key[KEY_S]);
		direction = RIGHT;
		destroyed = false;
		damage = 0;
		driver = NULL;
		on = false;
	}

	void init() {
		dovoices();
	}

	void killvoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = NULL;
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = NULL;
	}

	void dovoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = allocate_voice(engine);
		voice_set_playmode(engvoice, PLAYMODE_LOOP);
		voice_start(engvoice);
		voice_set_volume(engvoice, 0);
		voice_set_priority(engvoice, 255);
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = allocate_voice(enginestart);
		voice_stop(engstartvoice);
	}

	void getin(soldier *newdriver) {
		driver = newdriver;
		if(destroyed) return;
		if(occupied == false) {
			occupied = true;
			if(voice_check(engstartvoice) != enginestart) dovoices();
			voice_start(engstartvoice);
			dopanvol(me->x, 0.5);
			voice_set_pan(engstartvoice, pan);
			voice_set_volume(engstartvoice, vol);
			release_voice(engstartvoice);
			engstarted = false;
			voice_set_position(engstartvoice, 0);
			//voice_ramp_volume(engvoice, 100, 255);
			if(direction == RIGHT)
				myobj->obj = occ;
			else
				myobj->obj = occl;
		}
		else {
			voice_ramp_volume(engvoice, 100, 0);
			occupied = false;
			engstarted = false;
			if(direction == RIGHT)
				myobj->obj = unoc;
			else
				myobj->obj = unocl;
		}
	}

	void dokeys() {
		if(destroyed) return;
		float appstrength;
		float dx, dy, d;

		if(!engstarted && voice_get_position(engstartvoice) >= 10000) {
			voice_ramp_volume(engvoice, 100, 255);
			engstarted = true;
		}

		dx = me->atomlist[3]->x - me->atomlist[0]->x;
		dy = me->atomlist[3]->y - me->atomlist[0]->y;
		d = sqrt(dx * dx + dy * dy);
		dx = dx / d;
		dy = dy / d;

		appstrength = strength * COMPFRAMES;

		dx *= appstrength;
		dy *= appstrength;		

		if(me->y > path[(int)me->x] - 20) {

			/*
			if(*keydown && !*keyup) {
				if(direction == RIGHT) {
					me->ix -= dx;
					me->iy -= dy;
				}
				else {
					me->ix += dx;
					me->iy += dy;
				}
			}
			else if(*keyup && !*keydown) {
				if(direction == LEFT) {
					me->ix -= dx;
					me->iy -= dy;
				}
				else {
					me->ix += dx;
					me->iy += dy;
				}
			}
			*/
			if(*keyleft && !*keyright && !*keydown) {
				me->ix -= dx;
				me->iy -= dy;
				if(direction != LEFT) {
					direction = LEFT;
					myobj->obj = occl;
				}
			}
			else if(*keyright && !*keyleft && !*keydown) {
				me->ix += dx;
				me->iy += dy;
				if(direction != RIGHT) {
					direction = RIGHT;
					myobj->obj = occ;
				}
			}
			else if(*keydown && !*keyleft && !*keyright) {
				if(direction == LEFT) {
					me->ix += dx;
					me->iy += dy;
				}
				else if(direction == RIGHT) {
					me->ix -= dx;
					me->iy -= dy;
				}
			}
			else {
				dx *= 0.4;
				dy *= 0.4;
				if(me->ix > dx) {
					me->ix -= dx;
					if(me->iy > dy)
						me->iy -= dy;
					else if(me->iy < -dy)
						me->iy += dy;
					else
						me->iy = 0;
				}
				else if(me->ix < -dx) {
					me->ix += dx;
					if(me->iy > dy)
						me->iy -= dy;
					else if(me->iy < -dy)
						me->iy += dy;
					else
						me->iy = 0;
				}
				else {
					me->ix = 0;
					if(me->iy > dy)
						me->iy -= dy;
					else if(me->iy < -dy)
						me->iy += dy;
					else
						me->iy = 0;
				}
			}
		}
	}

	void update();
};

jeep jeeps[MAXJEEPS];
int numjeeps;



void addjeep(float nx, float ny) {
	jeep *j;
	rigidbody *r;
	int x, y;

	j = &(jeeps[0]);
	while(j->on) j++;

	settmplevels();
	tmplevels[1] = false;
	tmplevels[3] = false;
	tmplevels[4] = false;
	tmplevels[7] = false;
	tmplevels[11] = false;
	tmplevels[12] = false;
	j->on = true;
	r = addrigidobject("jeepu.pcx", nx, ny, false, tmplevels, 7, 0.025, 0.001, 70, 1);
	r->afric = 0.95;
	j->me = r;
	j->myobj = &(objects[numobjects - 1]);
	r->imult = 3;
	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				structure[x][y]->damage = &(j->damage);
			}
		}
	}
	j->init();
	if(j == &(jeeps[numjeeps]))
		numjeeps++;
}

void updatejeeps() {
	jeep *j;
	int i;
	j = &(jeeps[0]);
	for(i = 0; i < numjeeps; i++) {
		j->update();
		j++;
	}
}

jeep *byjeep(float x, float y) {
	jeep *j;
	int i;

	j = &(jeeps[0]);
	for(i = 0; i < numjeeps; i++) {
		if(	!j->destroyed && j->me != NULL && x < j->me->x + 8 && x > j->me->x - 8 &&
			y < j->me->y + 15 && y >= j->me->y) {
			return j;
		}
		j++;
	}
	return NULL;
}

struct tank {
	rigidbody *me;
	bool occupied;
	float strength;
	float engspeed;
	object *myobj;
	BITMAP *base;
	BITMAP *barrel;
	BITMAP *exp;
	/*
	BITMAP *base;
	BITMAP *basel;
	BITMAP *gunu;
	BITMAP *gunul;
	BITMAP *guno;
	BITMAP *gunol;
	BITMAP *exp;
	BITMAP *expl;
	BITMAP *barrel;
	BITMAP *barrell;
	*/
	float damage;
	soldier *driver;

	volatile char *keyleft;
	volatile char *keyright;
	volatile char *keyup;
	volatile char *keydown;
	float tx, ty;
	bool *fire;

	//bool direction;
	//bool barreldirection;
	int engvoice;
	int engstartvoice;
	bool engstarted;
	bool destroyed;
	bool on;

	float speed;
	float barrelang;
	float goalang;
	//float cx, cy, 
	float x, y, ox, oy;
	float barrelspeed;
	float ca, sa, rca, rsa, oca, osa;
	float mk;				//just there for holdovers draw--dokeys

	int fired;
	int firing;

	float engramp;
	float engdir;

	tank() {
		reset();
	}

	void reset() {
		occupied = false;
		//strength = 2.5;
		//strength = 2.5;
		strength = 2.5;
		engspeed = 1;
		keyleft = &(key[KEY_A]);
		keyright = &(key[KEY_D]);
		keyup = &(key[KEY_W]);
		keydown = &(key[KEY_S]);
		destroyed = false;
		damage = 0;
		driver = NULL;
		on = false;
		speed = 0;
		barrelspeed = 1;
		fired = 0;
		barrel = tankbarrelanim[0];
		firing = 0;
		barrelang = 0;
		ca = 1;
		sa = 0;
		mk = 0;
		goalang = 0;
	}

	void init() {
		dovoices();
		barrel = tankbarrelanim[0];
		myobj->obj = base;
	}

	void killvoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = NULL;
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = NULL;
	}

	void dovoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = allocate_voice(engine);
		voice_set_playmode(engvoice, PLAYMODE_LOOP);
		voice_start(engvoice);
		voice_set_volume(engvoice, 0);
		voice_set_priority(engvoice, 255);
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = allocate_voice(enginestart);
		voice_stop(engstartvoice);
	}

	void getin(soldier *);

	void draw();

	void erase() {
		if(destroyed) return;
		//if(barreldirection == RIGHT) {
			//blit(bg, buf, x - 35, y - 35, x - 35, y - 35, 70, 70);
		//}
		blit(bg, buf, ox - 25, oy - 25, ox - 25, oy - 25, 50, 35);
		//rectfill(buf, x - 15, y - 17, x + 15, y - 5, magenta);
	}

	void dokeys();

	void update();
};

tank tanks[MAXTANKS];
int numtanks;

tank *addtank(float nx, float ny, bool comp) {
	tank *j;
	rigidbody *r;
	int x, y;

	j = &(tanks[0]);
	while(j->on) j++;

	settmplevels();
	tmplevels[1] = false;
	tmplevels[3] = false;
	tmplevels[4] = false;
	tmplevels[5] = false;
	tmplevels[7] = false;
	tmplevels[9] = false;
	tmplevels[11] = false;
	tmplevels[12] = false;
	j->on = true;
	//r = addrigidobject("tanku.pcx", nx, ny, false, tmplevels, 7, 0.005, 0.0001, 100, 1);
	//r = addrigidobject("tanku.pcx", nx, ny, false, tmplevels, 7, 0.025, 0.001, 70, 1);
	if(!comp) r = addrigidobject("tankd.pcx", nx, ny, false, tmplevels, 7, 0.005, 0.0001, 600, 1);
	else r = addrigidobject("tankde.pcx", nx, ny, false, tmplevels, 7, 0.005, 0.0001, 600, 1);
	r->grmult = 15;
	r->grounddamagethreshold = 20;

	//r->afric = 0.95;
	//r->gfric = 0.007;
	r->imult = 0.5;

	if(!comp) {
		j->base = tankbase;
		j->exp = tankd;
	}
	else {
		j->base = tankbasee;
		j->exp = tankde;
	}

	j->me = r;
	j->myobj = &(objects[numobjects - 1]);
	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				structure[x][y]->damage = &(j->damage);
			}
		}
	}
	j->init();
	if(j == &(tanks[numtanks]))
		numtanks++;
	return j;
}

void updatetanks() {
	tank *j;
	int i;
	j = &(tanks[0]);
	for(i = 0; i < numtanks; i++) {
		j->update();
		j++;
	}
}

void drawtanks() {
	tank *j;
	int i;
	j = &(tanks[0]);
	for(i = 0; i < numtanks; i++) {
		j->draw();
		j++;
	}
}

void erasetanks() {
	tank *j;
	int i;
	j = &(tanks[0]);
	for(i = 0; i < numtanks; i++) {
		j->erase();
		j++;
	}
}

tank *bytank(float x, float y) {
	tank *j;
	int i;

	j = &(tanks[0]);
	for(i = 0; i < numtanks; i++) {
		if(!j->occupied && !j->destroyed && j->me != NULL && x < j->me->x + 8 && x > j->me->x - 8 &&
			y < j->me->y + 15 && y >= j->me->y) {
			return j;
		}
		j++;
	}
	return NULL;
}

int calcdiff(float a, float b) {
    float d1 = abs(a - b);
    float d2 = 256 - d1;
    if(d1 < d2) {
        if(a > b) return -d1;
        else return d1;
    }
    else {
        if(a < b) return -d2;
        else return d2;
    }
}

struct plane {
	rigidbody *me;
	bool occupied;
	float strength;
	float force;
	object *myobj;
	BITMAP *unoc;
	BITMAP *occ;
	BITMAP *firing;
	BITMAP *exp;
	BITMAP *damaged;
	BITMAP *damagedo;
	BITMAP *damagedf;
	float damage;
	soldier *driver;

	volatile char *keyleft;
	volatile char *keyright;
	volatile char *keyslow;
	volatile char *keyup;
	volatile char *keydown;

	bool direction;
	int engvoice;
	int engstartvoice;
	bool engstarted;
	bool destroyed;
	bool on;
	float speed;
	float engspeed, goalspeed;
	float proprot;
	float dx, dy, rx, ry;
	int fired;
	int bfired;
	float sadd;
	float turning;
	float turnang;
	bool inturn;
	float tcos;
	bool noturn;
	bool isdamaged;
	float xch, ych;
	float oldspeed;
	float tx, ty;
	bool *fire;
	bool *dropbomb;

	bool drew;

	float engramp;
	float engdir;

	int engstartcount;

	plane() {
		reset();
	}

	void reset() {
		engstartcount = 0;
		occupied = false;
		strength = 0.3;
		force = 40;
		keyleft = &(key[KEY_A]);
		keyright = &(key[KEY_D]);
		keyup = &(key[KEY_W]);
		keydown = &(key[KEY_S]);
		direction = RIGHT;
		destroyed = false;
		damage = 0;
		driver = NULL;
		on = false;
		engspeed = 0;
		goalspeed = 0;
		proprot = pi / 2;
		goalspeed = 0;
		fired = 0;
		sadd = 0;
		turning = 0;
		direction = RIGHT;
		tcos = 1;
		noturn = false;
		turning = 0;
		turnang = 0;
		inturn = false;
		isdamaged = false;
		xch = ych = 0;
		tx = ty = 0;
		fire = NULL;
		dropbomb = NULL;
		engramp = engdir = 0;
	}

	void init() {
		myobj->obj = unoc;
		dovoices();
		//addtrailanim(me->atomlist[1], smokeanim, 8, 3, rand()% 3, 100000, 0, 1, true, 3);
		//addtrailanim(me->atomlist[1], smokeanim, 8, 10, rand()% 10, 100000, 0, 1, true, 10);
		//addtrailanim(me->atomlist[1], smokeanim, 8, 10, rand()% 10, 100000, 0, 1, true, 10);
	}

	void killvoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = NULL;
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = NULL;
	}

	void dovoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = allocate_voice(prop);
		voice_set_playmode(engvoice, PLAYMODE_LOOP);
		voice_start(engvoice);
		voice_set_volume(engvoice, 0);
		voice_set_priority(engvoice, 255);
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = allocate_voice(propstart);
		voice_stop(engstartvoice);
	}

	void getin(soldier *newdriver);

	void draw() {
		if(me == NULL) return;

		//fprintf(debug, "%f, %f, %f\n", lx, ::rx, (float)me->x);

		if(me->x + 20 > lx && me->x - 20 < ::rx) {
			float cx, cy, ox, oy, o;
			int points[14];
			cx = me->polylistx[16] + dx*2*tcos + rx*1;
			cy = me->polylisty[16] + dy*2*tcos + ry*1;
			o = sin(proprot);
			ox = o * rx;
			oy = o * ry;

			points[0] = (int)(cx);
			points[1] = (int)(cy);
			points[2] = (int)(cx - 7*ox - .5*dx);
			points[3] = (int)(cy - 7*oy - .5*dy);
			points[4] = (int)(cx - 7*ox + .5*dx);
			points[5] = (int)(cy - 7*oy + .5*dy);
			points[6] = (int)(cx);
			points[7] = (int)(cy);
			points[8] = (int)(cx + 7*ox - .5*dx);
			points[9] = (int)(cy + 7*oy - .5*dy);
			points[10] = (int)(cx + 7*ox + .5*dx);
			points[11] = (int)(cy + 7*oy + .5*dy);
			points[12] = (int)(cx);
			points[13] = (int)(cy);

			/*
			points[0] = (int)(cx + 0.5*dx);
			points[1] = (int)(cy + 0.5*dy);
			points[2] = (int)(cx - 7*ox);
			points[3] = (int)(cy - 7*oy);
			points[4] = (int)(cx - 7*ox + 1*dx);
			points[5] = (int)(cy - 7*oy + 1*dy);
			points[6] = (int)(cx + 0.5*dx);
			points[7] = (int)(cy + 0.5*dy);
			points[8] = (int)(cx + 7*ox);
			points[9] = (int)(cy + 7*oy);
			points[10] = (int)(cx + 7*ox + 1*dx);
			points[11] = (int)(cy + 7*oy + 1*dy);
			points[12] = (int)(cx + 0.5*dx);
			points[13] = (int)(cy + 0.5*dy);
			*/
			polygon(buf, 7, points, black);

			//lx = cx;
			//ly = cy;
			if(engstarted || !occupied)
				proprot += 0.02 * (0.5 * engspeed + sadd);

			if(destroyed) return; 

			atom *wa, *sa;

			wa = me->atomlist[me->mynumatoms - 2];
			sa = me->atomlist[me->mynumatoms - 1];

			line(buf, wa->x - rx*10, wa->y - ry*10, wa->x, wa->y, black);
			circlefill(buf, wa->x, wa->y, 2, gray);
			circle(buf, wa->x, wa->y, 2, black);

			line(buf, sa->x - rx*10, sa->y - ry*10, sa->x, sa->y, black);

			drew = true;
		}

		//line(buf, lx, ly, ux, uy, gray);

	}

	void erase() {
		if(drew == true) {
			if(me == NULL) return;
			float ox, oy;
			ox = me->atomlist[16]->x - me->x;
			oy = me->atomlist[16]->y - me->y;
			ox *= tcos;
			oy *= tcos;		
			blit(bg, buf, me->x + ox - 10, me->y + oy - 10, me->x + ox - 10, me->y + oy - 10, 20, 20);
			blit(bg, buf, me->atomlist[18]->x - 5, me->atomlist[18]->y - 5, me->atomlist[18]->x - 5, me->atomlist[18]->y - 5, 10, 10);
			blit(bg, buf, me->atomlist[19]->x - 5, me->atomlist[19]->y - 5, me->atomlist[19]->x - 5, me->atomlist[19]->y - 5, 10, 10);
			drew = false;
		}
	}

	void dokeys();

	void setdirection(bool newdir);

	void update();
};

plane planes[MAXPLANES];
int numplanes;


struct heli {
	rigidbody *me;
	bool occupied;
	float strength;
	float force;
	object *myobj;
	BITMAP *unoc;
	BITMAP *occ;
	BITMAP *firing;
	BITMAP *exp;
	BITMAP *damaged;
	BITMAP *damagedo;
	BITMAP *damagedf;
	float damage;
	soldier *driver;

	volatile char *keyleft;
	volatile char *keyright;
	volatile char *keyup;
	volatile char *keydown;

	bool direction;
	int engvoice;
	int engstartvoice;
	bool engstarted;
	int engstartcount;
	bool destroyed;
	bool on;
	float speed;
	float engspeed, goalspeed;
	float proprot;
	float dx, dy, rx, ry;
	int fired;
	int bfired;
	float sadd;
	float turning;
	float turnang;
	bool inturn;
	float tcos;
	bool noturn;
	bool isdamaged;
	float xch, ych;
	float oldspeed;
	float tx, ty;
	bool *fire;
	bool *dropbomb;
	float accx, accy;

	float engramp;
	float engdir;

	heli() {
		reset();
	}

	void reset() {
		accx = accy = 0;
		occupied = false;
		strength = 0.3;
		force = 40;
		keyleft = &(key[KEY_A]);
		keyright = &(key[KEY_D]);
		keyup = &(key[KEY_W]);
		keydown = &(key[KEY_S]);
		direction = RIGHT;
		destroyed = false;
		damage = 0;
		driver = NULL;
		on = false;
		engspeed = 0;
		goalspeed = 0;
		proprot = pi / 2;
		goalspeed = 0;
		fired = 0;
		sadd = 0;
		turning = 0;
		direction = RIGHT;
		tcos = 1;
		noturn = false;
		turning = 0;
		turnang = 0;
		inturn = false;
		isdamaged = false;
		xch = ych = 0;
		tx = ty = 0;
		fire = NULL;
		dropbomb = NULL;
		engstartcount = 0;
	}

	void init() {
		myobj->obj = unoc;
		dovoices();
		//addtrailanim(me->atomlist[1], smokeanim, 8, 3, rand()% 3, 100000, 0, 1, true, 3);
		//addtrailanim(me->atomlist[1], smokeanim, 8, 10, rand()% 10, 100000, 0, 1, true, 10);
		//addtrailanim(me->atomlist[1], smokeanim, 8, 10, rand()% 10, 100000, 0, 1, true, 10);
	}

	void killvoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = NULL;
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = NULL;
	}

	void dovoices() {
		if(engvoice != NULL) deallocate_voice(engvoice);
		engvoice = allocate_voice(prop);
		voice_set_playmode(engvoice, PLAYMODE_LOOP);
		voice_start(engvoice);
		voice_set_volume(engvoice, 0);
		voice_set_priority(engvoice, 255);
		if(engstartvoice != NULL) deallocate_voice(engstartvoice);
		engstartvoice = allocate_voice(propstart);
		voice_stop(engstartvoice);
	}

	void getin(soldier *newdriver);

	void draw() {
		if(me == NULL) return;
		float cx, cy, ox, oy, o;
		int points[14];
		float bx, by;
		bx = me->polylistx[13] + dx*2*tcos + rx*2;
		by = me->polylisty[13] + dy*2*tcos + ry*2;
		cx = me->polylistx[13] + dx*2*tcos;
		cy = me->polylisty[13] + dy*2*tcos;
		o = sin(proprot);
		ox = o * dx;
		oy = o * dy;

		points[0] = (int)(cx);
		points[1] = (int)(cy);
		points[2] = (int)(cx - 20*ox - .5*rx);
		points[3] = (int)(cy - 20*oy - .5*ry);
		points[4] = (int)(cx - 20*ox + .5*rx);
		points[5] = (int)(cy - 20*oy + .5*ry);
		points[6] = (int)(cx);
		points[7] = (int)(cy);
		points[8] = (int)(cx + 20*ox - .5*rx);
		points[9] = (int)(cy + 20*oy - .5*ry);
		points[10] = (int)(cx + 20*ox + .5*rx);
		points[11] = (int)(cy + 20*oy + .5*ry);
		points[12] = (int)(cx);
		points[13] = (int)(cy);
		line(buf, points[0], points[1], bx, by, black);
		/*
		points[0] = (int)(cx + 0.5*dx);
		points[1] = (int)(cy + 0.5*dy);
		points[2] = (int)(cx - 7*ox);
		points[3] = (int)(cy - 7*oy);
		points[4] = (int)(cx - 7*ox + 1*dx);
		points[5] = (int)(cy - 7*oy + 1*dy);
		points[6] = (int)(cx + 0.5*dx);
		points[7] = (int)(cy + 0.5*dy);
		points[8] = (int)(cx + 7*ox);
		points[9] = (int)(cy + 7*oy);
		points[10] = (int)(cx + 7*ox + 1*dx);
		points[11] = (int)(cy + 7*oy + 1*dy);
		points[12] = (int)(cx + 0.5*dx);
		points[13] = (int)(cy + 0.5*dy);
		*/
		polygon(buf, 7, points, black);

		//lx = cx;
		//ly = cy;
		if(engstarted || !occupied)
			proprot += 0.02 * (80 * engspeed + sadd);

		if(destroyed) return;
	}

	void erase() {
		if(me == NULL) return;
		float cx, cy;
		cx = me->polylistx[13] + dx*2*tcos - rx*1;
		cy = me->polylisty[13] + dy*2*tcos - ry*1;		
		dx = fabs(dx);
		dy = fabs(dy);
		rx = fabs(rx);
		ry = fabs(ry);
		blit(bg, buf, cx - 25*dx - 5*rx, cy - 25*dy - 5*ry, cx - 25*dx - 5*rx, cy - 25*dy - 5*ry, 50*dx + 10*rx, 50*dy + 10*ry);
	}

	void dokeys();

	void setdirection(bool newdir);

	void update();
};

heli helis[MAXHELIS];
int numhelis;

heli *byheli(float x, float y) {
	heli *j;
	int i;

	j = &(helis[0]);
	for(i = 0; i < numhelis; i++) {
		if(	!j->destroyed && !j->occupied && x < j->me->x + 25 && x > j->me->x + 5 &&
			y < j->me->y + 15 && y >= j->me->y - 5) {
			return j;
		}
		j++;
	}
	return NULL;
}

heli *addheli(float nx, float ny, bool side) {
	heli *j;
	rigidbody *r;
	int x, y;

	j = &(helis[0]);
	while(j->on) j++;

	ny -= 100;
	settmplevels();
	tmplevels[1] = false;
	tmplevels[3] = false;
	tmplevels[4] = false;
	tmplevels[5] = false;
	tmplevels[7] = false;
	tmplevels[9] = false;
	tmplevels[11] = false;
	tmplevels[12] = false;
	j->on = true;
	
	//addmodrigidobject(fn, fnt, sx, sy, fixed, levels, level, lmod, rm, ram, gm, aposx,  aposy);
	//r = addrigidobject("planed.pcx", nx, ny, false, tmplevels, 7, 0.025, 0.0003, 70, 1.1);

	float aposx[100][100];
	float aposy[100][100];
	float amass[100][100];

	setupmass(amass);

	for(x = 0; x <= 2; x++) {
		for(y = 0; y < 100; y++) {
			amass[x][y] = 0;
		}
	}

	setupgrid(aposx, aposy);

	aposx[1][0] = 3;
	aposx[3][0] = 31;
	aposy[3][0] = 7;
	aposy[4][0] = 5;
	aposx[5][0] = 48;
	aposy[5][0] = 5;
	aposx[6][0] = 55;
	aposy[6][0] = 9;

	aposy[6][1] = 12;

	aposy[1][2] = 13;
	aposy[2][2] = 13;
	aposx[3][2] = 28;

	aposx[2][3] = 26;
	aposy[2][3] = 28;
	aposx[3][3] = 33;
	aposy[3][3] = 28;
	aposy[4][3] = 28;
	aposy[5][3] = 28;
	aposy[6][3] = 28;
	/*
	aposx[1][0] = 9;
	aposy[1][0] = 1;
	//aposx[2][0] = 7;
	aposy[2][0] = 6;
	aposx[3][0] = 28;
	aposy[3][0] = 3;
	aposx[4][0] = 37;
	aposy[4][0] = 5;
	aposy[5][0] = 4;
	aposy[5][1] = 12;
	*/

	//r = addrigidobject("heli.pcx", nx, ny, false, tmplevels, 7, 0.1, 0.001, 40, 1.1);
	if(side == FRIEND) r = addmodrigidobject("helid.pcx", NULL, nx, ny, false, tmplevels, 7, 1.1, 0.025, 0.0003, 35, aposx, aposy, amass);
	else r = addmodrigidobject("helide.pcx", NULL, nx, ny, false, tmplevels, 7, 1.1, 0.025, 0.0003, 35, aposx, aposy, amass);

	if(side == FRIEND) {
		j->unoc = heliunoc;
		j->occ = heliocc;
		j->firing = helifiring;
		j->exp = heliexp;
		j->damaged = helidamaged;
		j->damagedo = helidamagedo;
		j->damagedf = helidamagedf;
	}
	else {
		j->unoc = heliunoce;
		j->occ = heliocce;
		j->firing = helifiringe;
		j->exp = heliexpe;
		j->damaged = helidamagede;
		j->damagedo = helidamagedoe;
		j->damagedf = helidamagedfe;
	}

	r->pathoffset = 20;	
	r->gmmult = 30;
	r->afric = 0.995;
	//r->gfric = 0.01;
	j->me = r;
	j->myobj = &(objects[numobjects - 1]);
	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				structure[x][y]->damage = &(j->damage);
			}
		}
	}
	j->init();
	j->dovoices();
	if(j == &(helis[numhelis]))
		numhelis++;
	return j;
}

aagun *byaagun(float x, float y) {
	aagun *j;
	int i;

	j = &(aaguns[0]);
	for(i = 0; i < numaaguns; i++) {
		putpixel(bg, j->x, j->y, green);
		putpixel(buf, j->x, j->y, green);
		if(	!j->destroyed && x < j->x + 39 && x > j->x + 19 &&
			y < j->y + 46 && y >= j->y + 31) {
			return j;
		}
		j++;
	}
	return NULL;
}

plane *addplane(float nx, float ny, bool side) {
	plane *j;
	rigidbody *r;
	int x, y;

	j = &(planes[0]);
	while(j->on) j++;

	ny -= 100;
	settmplevels();
	tmplevels[1] = false;
	tmplevels[3] = false;
	tmplevels[4] = false;
	tmplevels[5] = false;
	tmplevels[7] = false;
	tmplevels[9] = false;
	tmplevels[11] = false;
	tmplevels[12] = false;
	j->on = true;
	
	//addmodrigidobject(fn, fnt, sx, sy, fixed, levels, level, lmod, rm, ram, gm, aposx,  aposy);
	//r = addrigidobject("planed.pcx", nx, ny, false, tmplevels, 7, 0.025, 0.0003, 70, 1.1);

	float aposx[100][100];
	float aposy[100][100];

	setupgrid(aposx, aposy);

	aposx[1][0] = 9;
	aposy[1][0] = 1;
	//aposx[2][0] = 7;
	aposy[2][0] = 6;
	aposx[3][0] = 28;
	aposy[3][0] = 3;
	aposx[4][0] = 37;
	aposy[4][0] = 5;
	aposy[5][0] = 4;
	aposy[5][1] = 12;
	
	if(side == FRIEND) r = addmodrigidobject("planed.pcx", NULL, nx, ny, false, tmplevels, 7, 1.1, 0.025, 0.0003, 70, aposx, aposy, NULL);
	else r = addmodrigidobject("planede.pcx", NULL, nx, ny, false, tmplevels, 7, 1.1, 0.025, 0.0003, 70, aposx, aposy, NULL);

	if(side == FRIEND) {
		j->unoc = planeunoc;
		j->occ = planeocc;
		j->firing = planefiring;
		j->exp = planeexp;
		j->damaged = planedamaged;
		j->damagedo = planedamagedo;
		j->damagedf = planedamagedf;
	}
	else {
		j->unoc = planeunoce;
		j->occ = planeocce;
		j->firing = planefiringe;
		j->exp = planeexpe;
		j->damaged = planedamagede;
		j->damagedo = planedamagedoe;
		j->damagedf = planedamagedfe;
	}
	//r = addrigidobject("planed.pcx", nx, ny, false, tmplevels, 7, 0.025, 0.0001, 70, 1.1);

	//11 - 14

	/*
	atom *a;
	float ax, ay;
	int yh;
	yh = 3;
	ax = r->atomlist[14]->x;//(r->atomlist[11]->x + r->atomlist[17]->x) * 0.5;
	ay = r->atomlist[14]->y + yh;
	cleartmplevels();
	a = addatom(ax, ay, tmplevels, 15);
	addlink(a, r->atomlist[11], sqrt(10 * 10 + yh * yh), 35);
	addlink(a, r->atomlist[17], sqrt(10 * 10 + yh * yh), 35);
	//addlink(a, r->atomlist[10], sqrt(5 * 5 + (yh + 10) * (yh + 10)), 35);
	//addlink(a, r->atomlist[16], sqrt(5 * 5 + (yh + 10) * (yh + 10)), 35);
	addlink(a, r->atomlist[14], yh, 35);
	addlink(a, r->atomlist[13], yh + 10, 35);
	a->rmdt = 1;
	*/
	atom *a;
	float ax, ay;
	int yh;
	yh = 3;
	ax = r->atomlist[14]->x;//(r->atomlist[11]->x + r->atomlist[17]->x) * 0.5;
	ay = r->atomlist[14]->y + yh;
	cleartmplevels();
	a = addatom(ax, ay, tmplevels, 0);
	r->addatom(a);
	r->complete();
	
	yh = 1;
	ax = r->atomlist[5]->x;//(r->atomlist[11]->x + r->atomlist[17]->x) * 0.5;
	ay = r->atomlist[5]->y + yh;
	cleartmplevels();
	a = addatom(ax, ay, tmplevels, 0);
	r->addatom(a);
	r->complete();
	r->pathoffset = 20;	

	r->afric = FLUIDFRICTION;
	r->afric = 0.995;
	j->me = r;
	j->myobj = &(objects[numobjects - 1]);
	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				structure[x][y]->damage = &(j->damage);
			}
		}
	}
	j->init();
	j->dovoices();
	if(j == &(planes[numplanes]))
		numplanes++;
	return j;
}

void updatehelis() {
	heli *j;
	int i;
	j = &(helis[0]);
	for(i = 0; i < numhelis; i++) {
		j->update();
		j++;
	}
}

void drawhelis() {
	heli *j;
	int i;
	j = &(helis[0]);
	for(i = 0; i < numhelis; i++) {
		j->draw();
		j++;
	}
}

void erasehelis() {
	heli *j;
	int i;
	j = &(helis[0]);
	for(i = 0; i < numhelis; i++) {
		j->erase();
		j++;
	}
}

void updateplanes() {
	plane *j;
	int i;
	j = &(planes[0]);
	for(i = 0; i < numplanes; i++) {
		j->update();
		j++;
	}
}

void drawplanes() {
	plane *j;
	int i;
	j = &(planes[0]);
	for(i = 0; i < numplanes; i++) {
		j->draw();
		j++;
	}
}

void eraseplanes() {
	plane *j;
	int i;
	j = &(planes[0]);
	for(i = 0; i < numplanes; i++) {
		j->erase();
		j++;
	}
}

plane *byplane(float x, float y) {
	plane *j;
	int i;

	j = &(planes[0]);
	for(i = 0; i < numplanes; i++) {
		if(	!j->destroyed && j->me != NULL && x < j->me->x + 8 && x > j->me->x - 8 &&
			y < j->me->y + 15 && y >= j->me->y) {
			return j;
		}
		j++;
	}
	return NULL;
}

typedef struct compsoldier compsoldier;

struct soldier {
	atom *me;
	atom *abody;
	BITMAP *bodyl;
	BITMAP *bodyr;
	BITMAP *body;
	BITMAP *arm;
	BITMAP *armbuf;
	BITMAP *head;
	BITMAP *headbuf;
	BITMAP *transbuf;
	compsoldier *controller;

	volatile char *keyleft;
	volatile char *keyright;
	volatile char *keyup;
	volatile char *keydown;
	volatile char *keygetin;

	float force;
	float strength;
	float jumpstrength;
	float bulletforce;
	int firedelay;

	float angle, fangle;
	float tmp1, tmp2;
	int offx, offy, bodyw, bodyh;
	bool direction;
	bool tmp;
	bool invehicle;
	bool gotin;
	bool *fire;
	int fired;
	float tx, ty;
	bool comp;
	bool side;
	bool drew;
	float damage;
	float health;
	bool dead;
	int gunvoice;
	jeep *injeep;
	tank *intank;
	plane *inplane;
	aagun *inaagun;
	heli *inheli;
	int walkframe;
	
	float gunramp;
	float gunrampdir;

	bool firing;

	soldier() {
		reset();
	}

	void reset() {
		controller = NULL;
		keyleft = &(key[KEY_A]);
		keyright = &(key[KEY_D]);
		keyup = &(key[KEY_W]);
		keydown = &(key[KEY_S]);
		keygetin = &(key[KEY_SPACE]);

		gunramp = 0;
		gunrampdir = 0;

		force = 1.7;
		strength = .015;
		jumpstrength = 0.5;
		bulletforce = 3;
		me = NULL;
		firing = false;

		offx = offy = 0;
		direction = RIGHT;
		angle = 0;
		firedelay = 30;
		fired = 0;
		invehicle = false;
		gotin = false;
		comp = false;
		fire = false;
		dead = false;

		tx = ty = 0;
		health = 100;
		gunvoice = -1;
		damage = 0;
		drew = false;
		injeep = NULL;
		intank = NULL;
		inheli = NULL;
		inplane = NULL;
		inaagun = NULL;
		walkframe = 0;
	}

	void killvoices() {
		if(gunvoice != NULL) deallocate_voice(gunvoice);
		gunvoice = NULL;
	}

	void dovoices() {
		if(gunvoice != NULL) deallocate_voice(gunvoice);
		gunvoice = allocate_voice(mgun);
		voice_set_playmode(gunvoice, PLAYMODE_LOOP);
		voice_set_volume(gunvoice, 255);
		//play_sample(mgun, 255, 122, 1000, 0);
		//voice_set_frequency(gunvoice, 8000);
		voice_stop(gunvoice);
	}

	void init(atom *newme, bool newside) {
		me = newme;
		me->draw = false;
		me->damage = &damage;
		side = newside;
		
		if(side == FRIEND) {
			head = load_bitmap("soldierhead.pcx", NULL);
			arm = load_bitmap("soldierarm.pcx", NULL);
			bodyr = load_bitmap("soldierbody.pcx", NULL);
		}
		else {
			head = load_bitmap("soldierheade.pcx", NULL);
			arm = load_bitmap("soldierarme.pcx", NULL);
			bodyr = load_bitmap("soldierbodye.pcx", NULL);
		}
		bodyl = create_bitmap(bodyr->w, bodyr->h);
		clear_to_color(bodyl, magenta);
		draw_sprite_h_flip(bodyl, bodyr, 0, 0);

		bodyw = 28;
		bodyh = 28;
		offx = -bodyw / 2;
		offy = -bodyh + 8;
		body = bodyr;

		transbuf = create_bitmap(bodyh, bodyh);
		clear_to_color(transbuf, magenta);
		armbuf = create_bitmap(26, 26);
		clear_to_color(armbuf, magenta);
		headbuf = create_bitmap(head->h + 8, head->h + 10);
		clear_to_color(transbuf, magenta);

		abody = addatom(me->x, me->y - 12, me->levels, me->level);
		abody->draw = false;
		abody->levels[2] = false;
		abody->damage = &damage;
		dovoices();
	}

	void draw() {
		//if(dead) return;
		if(invehicle || dead) return;
		if(me->x + 5 > lx && me->x - 5 < rx) {
			clear_to_color(transbuf, magenta);
			clear_to_color(headbuf, magenta);
			clear_to_color(armbuf, magenta);

			if(!comp) {
				angle = atan2(my - me->y + 8, mx - me->x);
			}
			else {
				angle = atan2(ty - me->y + 8, tx - me->x);
			}

			fangle = angle * convk;
			
			if(fangle < -64 || fangle > 64) {
				direction = LEFT;
				fangle = 128 - fangle;
				if(fangle > 128) fangle -= 256;
			}
			else {
				direction = RIGHT;
			}

			//if(angle < 128 && angle > 64) angle = 64;
			//else if(angle < 200) angle = 200;
			if(fangle > 50) fangle = 50;
			if(fangle < -64) fangle = -64;

			//draw_sprite(transbuf, body, 10, 9);
			blit(body, transbuf, walkframe * 19, 0, 5, 9, 19, 19);
			pivot_sprite(armbuf, arm, 15, 13, 3, 2, itofix((int)fangle));
			pivot_sprite(headbuf, head, 9, 9, 4, 7, itofix((int)fangle));
			draw_sprite(transbuf, armbuf, 0, 0);
			draw_sprite(transbuf, headbuf, 5, 0);
			if(direction == RIGHT)
				draw_sprite(buf, transbuf, me->x + offx, me->y + offy);
			else
				draw_sprite_h_flip(buf, transbuf, me->x + offx, me->y + offy);
			drew = true;
		}
	}

	void erase() {
		if(!drew) return;
		if(invehicle || dead) return;
		blit(bg, buf, me->x + offx, me->y + offy, me->x + offx, me->y + offy, bodyw, bodyh);
		drew = false;
	}

	void dokeys() {
		if(dead) return;

		float appstrength;
		float cx, cy, cd;

		cx = me->ix - me->oix;
		cy = me->iy - me->oiy;

		cy -= GRAVITY;
		cd = sqrt(cx * cx + cy * cy);
		cd = fabs(cd);
		//if(cd > 1) {
			//health -= (cd - 1);
		//}
		
		if(comp)
			health -= 20 * damage;
		else
			health -= 5 * damage;
		damage = 0;

		if(health <= 0 || me->y > waterlevel) {
			health = 0;
			dead = true;
			dopanvol(me->x, 0.2);
			play_sample(death1, vol, pan, 1000, 0);
			deallocate_voice(gunvoice);
			voice_ramp_volume(gunvoice, 50, 0);
			gunramp = 0;
			gunrampdir = -0.1;
			gunvoice = NULL;
			if(invehicle) {
				if(injeep != NULL) injeep->getin(this);
				if(intank != NULL) intank->getin(this);
				if(inheli != NULL) inheli->getin(this);
				if(inplane != NULL) inplane->getin(this);
				if(inaagun != NULL) inaagun->getin(this);
			}
			cleartmplevels();
			//tmplevels[8] = true;
			if(side == ENEMY) {
				if(direction == RIGHT)
					addobject("soldierder.pcx", NULL, me->x - 20, me->y - 27, 0, tmplevels, 8, 1000);
				else
					addobject("soldierdel.pcx", NULL, me->x - 20, me->y - 27, 0, tmplevels, 8, 1000);
			}
			else {
				if(direction == RIGHT)
					addobject("soldierdr.pcx", NULL, me->x - 20, me->y - 27, 0, tmplevels, 8, 1000);
				else
					addobject("soldierdl.pcx", NULL, me->x - 20, me->y - 27, 0, tmplevels, 8, 1000);
			}
			structure[1][0]->ix = me->ix * 0.4;
			structure[2][0]->ix = me->ix * 0.4;
			structure[1][1]->ix = me->ix * 0.2;
			structure[2][1]->ix = me->ix * 0.2;
			if(me->y < waterlevel) {
				structure[1][0]->iy = me->ix * 0.2 - 1;
				structure[2][0]->iy = me->ix * 0.2 - 1;
				structure[1][1]->iy = me->ix * 0.1 - 1;
				structure[2][1]->iy = me->ix * 0.1 - 1;
			}
			else {
				structure[1][0]->iy = me->iy * 0.2;
				structure[2][0]->iy = me->iy * 0.2;
				structure[1][1]->iy = me->iy * 0.1;
				structure[2][1]->iy = me->iy * 0.1;
			}
			if((structure[1][0]->ix > -0.2 && structure[1][0]->ix < 0.2)) {// || (structure[1][0]->ix < -1 || structure[1][0]->ix > 1)) {
				if(direction == RIGHT) {
					structure[1][0]->ix = -.4;
					structure[2][0]->ix = -.4;
					structure[1][1]->ix = -.2;
					structure[2][1]->ix = -.2;
				}
				else {
					structure[1][0]->ix = .4;
					structure[2][0]->ix = .4;
					structure[1][1]->ix = .2;
					structure[2][1]->ix = .2;
				}
			}
			erase();
			if(me != center)
				destroyatom(me);
			else {
				center->rmdt = 0.00001;
				center->fixed = true;
				center->level = 0;
				for(int i = 0; i < MAXLEVELS; i++) {
					center->levels[i] = false;
				}
			}
			destroyatom(abody);
			me = NULL;
			abody = NULL;
			return;
		}

		appstrength = strength * COMPFRAMES;


		if(!gotin && injeep == NULL && inplane == NULL && intank == NULL && inaagun == NULL && inheli == NULL && *keygetin) {//!jeep1.destroyed 
			injeep = byjeep(me->x, me->y);
			if(injeep != NULL) {
				invehicle = true;
				injeep->getin(this);
				gotin = true;
			}
			else {				
				inaagun = byaagun(me->x, me->y);
				if(inaagun != NULL) {
					invehicle = true;
					inaagun->getin(this);
					gotin = true;
				}
				else {
					inplane = byplane(me->x, me->y);
					if(inplane != NULL) {
						invehicle = true;
						inplane->getin(this);
						gotin = true;
					}
					else {
						intank = bytank(me->x, me->y);
						if(intank != NULL) {
							invehicle = true;
							intank->getin(this);
							gotin = true;
						}
						else {
							inheli = byheli(me->x, me->y);
							if(inheli != NULL) {
								invehicle = true;
								inheli->getin(this);
								gotin = true;
							}
						}
					}
				}
			}
			
			/*&& *keygetin && 
			me->x < jeep1.me->x + 8 && me->x > jeep1.me->x - 8 &&

			me->y < jeep1.me->y + 15 && me->y >= jeep1.me->y			
			) {
			invehicle = !invehicle;
			jeep1.getin(this);
			gotin = true;
			*/
		}
		else if(!gotin && injeep != NULL && *keygetin) {
			injeep->getin(this);
			invehicle = false;
			gotin = true;
			injeep = NULL;
		}
		else if(!gotin && inplane != NULL && *keygetin) {
			inplane->getin(this);
			invehicle = false;
			gotin = true;
			inplane = NULL;
		}
		else if(!gotin && inaagun != NULL && *keygetin) {
			inaagun->getin(this);
			invehicle = false;
			gotin = true;
			inaagun = NULL;
		}
		else if(!gotin && intank != NULL && *keygetin) {
			intank->getin(this);
			invehicle = false;
			gotin = true;
			intank = NULL;
		}
		else if(!gotin && inheli != NULL && *keygetin) {
			inheli->getin(this);
			invehicle = false;
			gotin = true;
			inheli = NULL;
		}
		else if(!*keygetin) {
			gotin = false;
		}

		if(invehicle) return;

		/*
		if(dispframe && (*keyleft ||*keyright)) {
			walkframe++;
			if(walkframe >= 8) walkframe = 0;
		}
		*/

		if(me->y > path[(int)(me->x)] - 6) {
			if(*keyleft && !*keyright) {
				if(me->ix > -force + appstrength) {
					me->ix -= appstrength;
				}
				else if(me->ix > -force) {
					me->ix = -force;
				}
				if(dispframe) walkframe++;
			}
			else if(*keyright && !*keyleft) {
				if(me->ix < force - appstrength) {
					me->ix += appstrength;
				}
				else if(me->ix < force) {
					me->ix = force;
				}
				if(dispframe) walkframe++;
			}
			else {
				if(me->ix < -appstrength) {
					me->ix += appstrength;
				}
				else if(me->ix > appstrength) {
					me->ix -= appstrength;
				}
				else {
					me->ix = 0;
				}
				walkframe = 0;
			}
			if(walkframe >= 8) walkframe = 0;

			if(*keyup) {
				me->iy -= jumpstrength * COMPFRAMES;
				if(*keyleft && !*keyright && me->ix > -15 * appstrength) {
					me->ix -=  3 * appstrength;
				}
				else if(*keyright && !*keyleft && me->ix < 15 * appstrength) {
					me->ix += 3 * appstrength;
				}
			}
		}

		if(((!comp && mouse_b & 1) || (comp && *fire)) && fired <= 0) {
			if(voice_check(gunvoice) != mgun) dovoices();
			gunrampdir = 0.1;
			voice_set_playmode(gunvoice, PLAYMODE_LOOP);
			firing = true;
			tmp1 = cos(angle);
			tmp2 = sin(angle);
			addbullet(me->x + 13 * tmp1, me->y - 8 + 13 * tmp2, bulletforce * tmp1, bulletforce * tmp2, side, 100, 1, 1, gray, false);
			fired = firedelay;
			voice_start(gunvoice);
		}
		if(fired > -10) fired--;
		if(fired < -5) {
			voice_ramp_volume(gunvoice, 50, 0);
			firing = false;
			//voice_set_playmode(gunvoice, 0);//, PLAYMODE_BACKWARD);
			//if(voice_get_position(gunvoice) <= 10) voice_stop(gunvoice);
			//voice_set_position(gunvoice, 0);
		}
	}

	void update() {
		if(dead) return;

		if(gunrampdir > 0) {
			gunramp += gunrampdir;
			if(gunramp >= 1) {
				gunrampdir = 0;
				gunramp = 1;
			}
		}
		else if(gunrampdir < 0) {
			gunramp += gunrampdir;
			if(gunramp <= 0) {
				gunrampdir = 0;
				gunramp = 0;
			}
		}

		if(firing) {
			dopanvol(me->x, 0.3);
			voice_set_pan(gunvoice, pan);
			voice_set_volume(gunvoice, vol * gunramp);
		}

		if(invehicle) {
			if(injeep != NULL) {
				me->x = injeep->me->x;
				me->y = injeep->me->y;
				me->ix = injeep->me->ix * 0.1;
				me->iy = injeep->me->iy * 0.1;
			}
			else if(intank != NULL) {
				me->x = intank->me->x;
				me->y = intank->me->y;
				me->ix = intank->me->ix * 0.0;
				me->iy = intank->me->iy * 0.0;
			}
			else if(inplane != NULL) {
				me->x = inplane->me->x;
				me->y = inplane->me->y;
				me->ix = 0;
				me->iy = 0;
			}
			else if(inheli != NULL) {
				me->x = inheli->me->x;
				me->y = inheli->me->y;
				me->ix = 0;
				me->iy = 0;
			}
			else if(inaagun != NULL) {
				me->x = inaagun->x + 29;
				me->y = inaagun->y + 36;
				me->ix = 0;
				me->iy = 0;
			}
			abody->x = me->x;
			abody->y = me->y - 12;
			abody->ix = 0;
			abody->iy = 0;
		}
		else {
			me->ix += abody->ix;
			abody->ix = 0;
			abody->iy = 0;
			abody->x = me->x;
			abody->y = me->y - 12;
		}
		dokeys();
	}
};

soldier soldiers[MAXSOLDIERS];
int numsoldiers;
soldier *human;


struct compsoldier {
	soldier *me;

	volatile char goleft;
	volatile char goright;
	volatile char goup;
	volatile char godown;
	volatile char getin;
	bool fire;
	bool dropbomb;
	float personality;
	bool side;
	
	//BEHAVIORS:

	//Script
	bool script;
	movie *myscript;
	int myactorno;
	int frameoff;

	//Hunt
	bool hunt;

	//Patrol
	bool patrol;
	int patrolzonel;
	int patrolzoner;
	bool patroldirection;

	//Trippatrol (Patrols until sights enemy)
	bool trippatrol;

	//Wait
	bool wait;

	//			**AAGUN**
	//Aagunner
	bool aagunner;
	aagun *mygun;

	//			**TANK**
	//Tankdriver
	bool tankdriver;
	bool intank;
	tank *mytank;

	//			**AIRPLANE**
	//Planepilot
	bool planepilot;
	bool inplane;
	float cruisealt;
	float planeoffdist;
	plane *myplane;
	
	//Takeoff
	bool takeoff;

	//Startrun
	bool startrun;

	//Inrun
	bool inrun;

	//Planehunt

	//Flyto
	bool flyto;
	float dest;
	bool *action;

	compsoldier() {
		reset();
	}

	void reset() {
		me = NULL;
		goleft = goright = goup = godown = getin = fire = dropbomb = false;
		fire = false;
		script = patrol = hunt = startrun = inrun = flyto = tankdriver= planepilot = false;
		intank = false;
		inplane = false;
		trippatrol = false;
		wait = false;
		side = ENEMY;
		side = FRIEND;
		cruisealt = 100;
		takeoff = false;
		personality = (rand() % 100) / 100.0;
		planeoffdist = 500;
	}

	void init(soldier *s, bool newside) {
		personality = (rand() % 100) / 100.0;
		me = s;
		me->keyleft = &goleft;
		me->keyright = &goright;
		me->keyup = &goup;
		me->keydown = &godown;
		me->keygetin = &getin;
		me->fire = &fire;
		me->comp = true;
		me->invehicle = false;
		me->controller = this;
		goleft = goright = goup = godown = getin = fire = dropbomb = false;
		side = newside;
	}

	void doscript(movie *newscript, int newactorno, int newframeoff) {
		script = true;
		myscript = newscript;
		myactorno = newactorno;
		frameoff = newframeoff;
		patrol = hunt = startrun = inrun = flyto = tankdriver = planepilot = false;
	}

	void dohunt() {
		hunt = true;
	}

	void dopatrol(int l, int r) {
		hunt = false;
		patrol = true;
		patrolzonel = l;
		patrolzoner = r;
		patroldirection = RIGHT;
	}

	void dotrippatrol(int l, int r) {
		hunt = false;
		patrol = true;
		trippatrol = true;
		patrolzonel = l;
		patrolzoner = r;
		patroldirection = RIGHT;
	}

	void dowait() {
		wait = true;
		hunt = false;
	}

	void doaagunner(aagun *a) {
		mygun = a;
		aagunner = true;
	}

	void dotankdriver(tank *t) {
		mytank = t;
		tankdriver = true;
		intank = false;
	}

	void doplanepilot(plane *p) {
		myplane = p;
		planepilot = true;
		inplane = false;
	}

	void doflyto(float newdest, bool *newaction) {
		flyto = true;
		dest = newdest;
		action = newaction;
	}

	void update() {
		if(me->dead) return;

		goleft = goright = goup = godown = getin = fire = dropbomb = false;

		if(script) {
			if(frame + frameoff > myscript->lastframe) {
				script = false;
				//exit(0);
			}
			else {
				int tmx, tmy;
				tmx = tmy = 0;
				tmpkeys = 0;
				goleft = goright = goup = godown = getin = fire = dropbomb = false;
				movie_getkeys(myscript, myactorno, frame + frameoff, tmpkeys, tmx, tmy);
				me->tx = tmx;
				me->ty = tmy;
				if(tmpkeys & M_W)
					goup = true;
				if(tmpkeys & M_S)
					godown = true;
				if(tmpkeys & M_A)
					goleft = true;
				if(tmpkeys & M_D)
					goright = true;
				if(tmpkeys & M_MOUSE1)
					fire = true;
				if(tmpkeys & M_MOUSE2)
					dropbomb = true;
				if(tmpkeys & M_SPACE) {
					getin = true;
				}
				if(me->invehicle && me->intank != NULL) {
					me->intank->tx = tmx;
					me->intank->ty = tmy;
				}
				if(me->invehicle && me->inplane != NULL) {
					me->inplane->tx = tmx;
					me->inplane->ty = tmy;
				}
				if(me->invehicle && me->inheli != NULL) {
					me->inheli->tx = tmx;
					me->inheli->ty = tmy;
				}
				return;
			}
		}

		if(drawframe % 100 == 0)		
			personality = (rand() % 100) / 100.0;

		/*
		if(human->dead) {
			goleft = goright = goup = godown = fire = false;
			me->dokeys();
			return;
		}
		*/

		float tx, ty;
		float ex, ey;
		float eix, eiy;
		float x, y;
		int i;
		bool edead;
		float closest;
		soldier *s, *cs;
		x = me->me->x;
		y = me->me->y;
		closest = 100000;

		ex = 1000;
		ey = 400;
		eix = eiy = 0;
		edead = true;

		cs = NULL;
		if(side == ENEMY) {
			s = &(soldiers[0]);
			for(i = 0; i < numsoldiers; i++) {
				if(s->side == FRIEND && !s->dead) {
					if(fabs(x - s->me->x) < closest) {
						cs = s;
						closest = fabs(x - s->me->x);
					}
				}
				s++;
			}
		}
		else if(side == FRIEND) {
			s = &(soldiers[0]);
			for(i = 0; i < numsoldiers; i++) {
				if(s->side == ENEMY && !s->dead) {
					if(fabs(x - s->me->x) < closest) {
						cs = s;
						closest = fabs(x - s->me->x);
					}
				}
				s++;
			}
		}
		if(cs != NULL) {
			ex = cs->me->x;
			ey = cs->me->y;
			eix = cs->me->ix;
			eiy = cs->me->iy;
		}
		edead = false;

		if(hunt && !inplane) {
			int offdist;
			bool missing = false;
			tx = ex;
			if(intank) ty = ey - fabs(x - ex) * 0.15;
			else ty = ey - 8;
			if(intank) offdist = 250;
			else offdist = 50;
			offdist = (0.5 + 1.5 * personality) * offdist;
			if(intank && (mytank->goalang == -128 || mytank->goalang == 0)) {
				offdist = 10;
				missing = true;
			}

			if(!(tankdriver && !intank)) {
				if(me->tx < me->me->x - offdist) {
					goleft = true;
					goright = false;
					if(patrol) patroldirection = LEFT;
				}
				else if(me->tx > me->me->x + offdist) {
					goright = true;
					goleft = false;
					if(patrol) patroldirection = RIGHT;
				}
				else {
					goleft = goright = false;
				}
			}
			if((fabs(tx - x) <= offdist + 20 || (!missing && fabs(tx - x) < 200 + 200 * personality)) && (!intank || mytank->fired <= 0)) {
				if(intank) ty += 60 * (rand() % 100) * 0.01 - 30;
				else ty += 30 * (rand() % 100) * 0.01 - 15;
				fire = true;
			}
			else fire = false;
		}
		if(patrol) {
			if(abs(x - ex) < 200) {
				hunt = true;
				if(trippatrol) {
					patrol = false;
					trippatrol = false;
				}
			}
			else if(abs(x - ex) > 300) hunt = false;

			if(x >= patrolzoner) {
				patroldirection = LEFT;
				goright = false;
			}
			else if(x <= patrolzonel) {
				patroldirection = RIGHT;
				goleft = false;
			}
			if(!hunt && patroldirection == RIGHT) {
				goright = true;
				goleft = false;
				if(intank) {
					tx = x + 5;
					ty = y;
				}
				else {
					tx = x + 5;
					ty = y - 8;
				}
				fire = false;
			}
			else if(!hunt && patroldirection == LEFT) {
				goleft = true;
				goright = false;
				if(intank) {
					tx = x - 5;
					ty = y;
				}
				else {
					tx = x - 5;
					ty = y - 8;
				}
				fire = false;
			}
		}
		if(wait) {			
			if(abs(x - ex) < 600) {
				hunt = true;
				wait = false;
			}
		}
		if(aagunner && !edead) {
			if(!me->invehicle) {
				if(mygun->x  + 26 < x - 5)
					goleft = true;
				else if(mygun->x + 26> x + 5)
					goright = true;
				else {
					mygun->getin(me);
					me->invehicle = true;
					me->inaagun = mygun;
					mygun->fire = &fire;
				}
			}
			else {
				float dx, dy, dist;
				dx = ex - x;
				dy = ey - y;
				dy *= 1;
				if(dx > 500) dx = 500;
				else if(dx < -500) dx = -500;
				dist = (dx * dx + dy * dy);
				if(eix > 0) {
					mygun->tx = ex + 0.0008 * dist;
					//mygun->tx = ex + 0.85 * fabs(y - ey) + 0.0005 * fabs(x - ex) * fabs(y - ey);
				}
				else {
					mygun->tx = ex - 0.0008 * dist;
					//mygun->tx = ex - 0.85 * fabs(y - ey) - 0.0005 * fabs(x - ex) * fabs(y - ey);
				}
				mygun->ty = ey;
				//mygun->ty += 0.5 * dist;

				//mygun->ty = ey + 15 * eiy;
				if(fabs(x - ex) < 500 && fabs(mygun->fangle - mygun->angle) < 1) {
					fire = true;
				}
			}
		}
		if(tankdriver) {
			if(mytank->destroyed) {
				tankdriver = false;
				hunt = true;
				intank = false;
			}
			else {
				if(!me->invehicle) {
					intank = false;
					if(mytank->x < x - 5) {
						goleft = true;
					}
					else if(mytank->x > x + 5) {
						goright = true;
					}
					else if(!mytank->occupied) {
						mytank->getin(me);
						me->invehicle = true;
						me->intank = mytank;
						mytank->fire = &fire;
						mytank->keyleft = &goleft;
						mytank->keyright = &goright;
						mytank->keyup = &goup;
						mytank->keydown = &godown;
						intank = true;
					}
				}
				else {					
					mytank->tx = tx;
					mytank->ty = ty;
				}
			}
		}		
		if(planepilot) {
			float px, py, pix, piy;
			if(myplane->destroyed) {
				planepilot = false;
				hunt = true;
				inplane = false;
			}
			else {
				px = myplane->me->x;
				py = myplane->me->y - 0;
				pix = myplane->me->ix;
				piy = myplane->me->iy;
				goleft = goright = goup = godown = fire = dropbomb = false;
				if(!me->invehicle) {
					inplane = false;
					if(px < x - 5) {
						goleft = true;
					}
					else if(px > x + 5) {
						goright = true;
					}
					else if(!myplane->occupied) {
						myplane->getin(me);
						me->invehicle = true;
						me->inplane = myplane;
						myplane->fire = &fire;
						myplane->dropbomb = &dropbomb;
						myplane->keyleft = &goleft;
						myplane->keyright = &goright;
						myplane->keyup = &goup;
						myplane->keydown = &godown;
						inplane = true;
						takeoff = true;
					}
				}
				else {
					//textprintf(buf, font, screencenterx - 300, 70, white, "%i,%i,%i,%i", takeoff, flyto, startrun, inrun);

					float cutoff = 0.00000001 * py * py * py * py;
					float ta;
					float gy;
					gy = path[(int)px];
					ta = myplane->me->ang * convk - 64;
					if(myplane->direction == LEFT) ta += 128;
					if(ta > 256) ta -= 256;
					if(ta < -64 || ta > 64) ta = 64;
					cutoff += 4.5 * (64 - fabs(ta));
					if(myplane->direction == LEFT) {
						cutoff = findlow(gy, path[(int)(px - 50)], path[(int)(px + 5 * pix)]) - cutoff;
					}
					else {
						cutoff = findlow(gy, path[(int)(px + 50)], path[(int)(px + 5 * pix)]) - cutoff;
					}


					if(py < ey && py < gy - 50 && fabs((px + pix*myplane->me->rm*(ey-py)*0.8) - ex) < 20) {
						dropbomb = true;
					}

					if(takeoff) {
						goup = true;
						if(px > buf->w - 200)
							goleft = true;
						else if(px < 200)
							goright = true;
						if(py > gy - 50) {
							if(myplane->direction == RIGHT) {
								tx = px + 10;
								ty = py - 2;
							}
							else {
								tx = px - 10;
								ty = py - 2;
							}
						}						
						else if(py > cruisealt) {
							if(myplane->direction == RIGHT) {
								tx = px + 10;
								ty = py - 6;
							}
							else {
								tx = px - 10;
								ty = py - 6;
							}
						}
						else {
							takeoff = false;
							if(flyto == false) startrun = true;
							//startrun = true;
							//doflyto(2000, &hunt);
						}
					}
					else if(py > gy - 50 && 0) {
						inrun = false;
						startrun = false;
						flyto = false;
						takeoff = true;
					}
					else if(piy > 0 && py > cutoff) {
						inrun = false;
						startrun = true;
						flyto = false;
						takeoff = false;
					}
					if(startrun) {
						if(fabs(ex - px) < planeoffdist) {
							if(myplane->direction == LEFT) 
								doflyto(ex - planeoffdist, &startrun);
							else
								doflyto(ex + planeoffdist, &startrun);
							startrun = false;
						}
						else {
							if(ex < px) {
								goleft = true;
							}
							else {
								goright = true;
							}
							startrun = false;
							inrun = true;
						}
					}
					if(flyto) {
						tx = dest;
						ty = cruisealt - 50;
						if(myplane->direction == LEFT) tx -= 100;
						else tx += 100;
						if(px > buf->w - 200) {
							goleft = true;
							flyto = false;
							startrun = true;
						}
						else if(px < 200) {
							goright = true;
							flyto = false;
							startrun = true;
						}
						else {
							if(tx < px)
								goleft = true;
							else
								goright = true;
							if(fabs(dest - px) < 100) {
								flyto = false;
								*action = true;
							}
						}
					}
					if(inrun) {
						int offdist = 500;
						float dx, dy, dist;
						dx = px - ex;
						dy = py - ey;
						dist = sqrt(dx * dx + dy * dy);
						tx = ex + eix * dist * 0.08;
						ty = ey - 5;
						if((tx < px && myplane->direction == RIGHT) || (tx > px && myplane->direction == LEFT)) {
							takeoff = true;
							hunt = false;
						}
						if(fabs(tx - x) <= offdist) {
							fire = true;
							tx += rand() % 60 - 30;
						}
						else fire = false;
					}
					myplane->tx = tx;
					myplane->ty = ty;
				}
			}
		}

		me->tx = tx;
		me->ty = ty;
	}
};

compsoldier compsoldiers[MAXCOMPSOLDIERS];
int numcompsoldiers;

void aagun::update() {
	float dx, dy;
	int tmpv;
	bullet *b;

	if(occupied) {
		float goalangle;
		
		if(!driver->comp) {
			if(direction == RIGHT) {
				goalangle = atan2(my + 3 - (y + 30), mx - (x + 30));
			}
			else {
				goalangle = atan2(my + 3 - (y + 30), mx - (x + 36));
			}
		}
		else {
			if(direction == RIGHT) {
				goalangle = atan2(ty + 3 - (y + 30), tx - (x + 30));
			}
			else {
				goalangle = atan2(ty + 3 - (y + 30), tx - (x + 36));
			}
		}
		fangle = goalangle * convk;

		if(direction == RIGHT && angle <= 128) {//(angle < -64 || angle > 64)) {			
			direction = LEFT;
		}
		else if(direction == LEFT && angle > 128) {//(angle < -64 || angle > 64)) {			
			direction = RIGHT;
		}

		fangle += 192;
		if(fangle > 256) fangle -= 256;

		if(fangle < 45) fangle = 45;
		if(fangle > 211) fangle = 211;

		if(angle - speed < fangle) {
			angle += speed;
		}
		else if(angle + speed > fangle) {
			angle -= speed;
		}

		dangle = angle - 192;
		if(direction == LEFT) dangle = 128 - dangle;
		if(dangle < 0) dangle += 256;
	}
	if(occupied || (!occupied && numfired > 0)) {
		if(fired <= 0 && (numfired > 0 || (occupied && driver->comp && *fire) || (occupied && !driver->comp && mouse_b & 1))) {
			dx = cos((angle + 64) * convk2);
			dy = sin((angle + 64) * convk2);
			//if(voice_check(driver->gunvoice) != mgun) driver->dovoices();
			//voice_ramp_volume(driver->gunvoice, 50, 255);
			//voice_set_playmode(driver->gunvoice, PLAYMODE_LOOP);
			if(direction == RIGHT)
				b = addbullet(x + 29 + 36 * dx, y + 28 + 36 * dy, bulletforce * dx, bulletforce * dy, (occupied && driver->comp), 400, 1, 3, yellow, false);
			else
				b = addbullet(x + 35 + 36 * dx, y + 28 + 36 * dy, bulletforce * dx, bulletforce * dy, (occupied && driver->comp), 400, 1, 3, yellow, false);
			if(b != NULL) {
				b->me->rmdt = 0.1;
				b->me->dmult = 100;
			}
			//myobj->obj = firing;
			//voice_start(driver->gunvoice);
			if(numfired == 0) {
				tmpv = allocate_voice(aagunfire);
				voice_set_priority(tmpv, 255);
				voice_start(tmpv);
				release_voice(tmpv);
			}
			numfired++;
			if(numfired == 6) {
				fired = 200;
				numfired = 0;
			}
			else {
				fired = 35;
			}
		}
		if(fired > -10) fired--;
		/*
		if(fired <= 5 && myobj->obj == firing) {
			if(occupied) myobj->obj = occ;
			else myobj->obj = unoc;
		}
		if(fired < -5) {
			voice_ramp_volume(driver->gunvoice, 50, 0);
		}
		*/
	}
}
	
void aagun::draw() {
	if(x + w > lx && x < rx) {
		clear_to_color(hold, magenta);
		
		/*

		//if(angle < 128 && angle > 64) angle = 64;
		//else if(angle < 200) angle = 200;
		if(fangle > 50) fangle = 50;
		if(fangle < -64) fangle = -64;
		*/

		//draw_sprite(transbuf, barrel, 10, 9);
		//pivot_sprite(barrelbuf, barrel, 15, 13, 3, 2, itofix((int)fangle));
		draw_sprite(hold, gunbg, offx, offy);
		pivot_sprite(hold, barrel, 22 + offx, 5 + offy, 13, 4, itofix((int)dangle));
		if(!occupied)
			draw_sprite(hold, base, offx, offy - 1);
		else if(occupied && driver->comp == false)
			draw_sprite(hold, baseo, offx, offy - 1);
		else if(occupied && driver->comp == true)
			draw_sprite(hold, baseoe, offx, offy - 1);
		if(direction == RIGHT) {
			draw_sprite(buf, hold, x, y);
		}
		else {
			draw_sprite_h_flip(buf, hold, x, y);
		}
		drew = true;
	}
}

void jeep::update() {
	int tmpv;

	if(destroyed) return;
	if(occupied) {
		dokeys();
		if(me->ix > 40 || me->ix < -40) me->ix *= 0.9;
		if(me->iy > 0)
			voice_set_frequency(engvoice, (fabs(me->ix) + me->iy) * 100 + 10000);
		else
			voice_set_frequency(engvoice, fabs(me->ix) * 100 + 10000);
		//if(voice_check(engstartvoice) != enginestart) dovoices();
	}
	if(damage > 150) {
		if(occupied) {
			driver->me->iy -= 15;
			driver->me->ix = me->ix * 0.4;
			driver->health -= 50;
			driver->injeep = NULL;
			driver->invehicle = false;
			occupied = false;
		}
		if(direction == LEFT) {
			myobj->obj = expl;
		}
		else if(direction == RIGHT) {
			myobj->obj = exp;
		}
		addanimation(explosionanim, 16, me->x - 32, me->y - 32, true, 0, 1, 0);
		me->y -= 5;
		me->update();
		destroyvehiclerigidbody(me);
		me = NULL;
		destroyed = true;
		tmpv = allocate_voice(explode);
		voice_set_priority(tmpv, 255);
		voice_start(tmpv);
		release_voice(tmpv);
		deallocate_voice(engvoice);
		engvoice = NULL;
	}
}

void tank::getin(soldier *newdriver) {
	atom *a;
	driver = newdriver;
	if(destroyed) return;
	if(occupied == false) {
		occupied = true;
		//driver->me->levels[me->atomlist[0]->level] = false;
		driver->me->dtmult = 0;
		driver->abody->dtmult = 0;
		if(voice_check(engstartvoice) != enginestart) dovoices();
		voice_start(engstartvoice);
		dopanvol(me->x, 0.5);
		voice_set_pan(engstartvoice, pan);
		voice_set_volume(engstartvoice, vol);
		release_voice(engstartvoice);
		engstarted = false;
		voice_set_position(engstartvoice, 0);
		if(driver->side == ENEMY) {
			a = me->atomlist[0];
			for(int i = 0; i < me->mynumatoms; i++) {
				a->levels[1] = true;
				a->levels[5] = false;
				a->levels[14] = false;
				a->level = 12;
				a++;
			}
		}
		else {
			a = me->atomlist[0];
			for(int i = 0; i < me->mynumatoms; i++) {
				a->levels[1] = false;
				a->levels[5] = true;
				a->levels[13] = false;
				a->level = 11;
				a++;
			}			
			keyleft = &(key[KEY_A]);
			keyright = &(key[KEY_D]);
			keyup = &(key[KEY_W]);
			keydown = &(key[KEY_S]);
		}
		//voice_ramp_volume(engvoice, 100, 255);
		/*
		if(direction == RIGHT)
			myobj->obj = occ;
		else
			myobj->obj = occl;
			*/
	}
	else {
		driver->me->dtmult = 1;
		driver->abody->dtmult = 1;
		voice_ramp_volume(engvoice, 100, 0);
		engramp = 0;
		engdir = 0;
		//engdir = -0.03;
		occupied = false;
		engstarted = false;
		a = me->atomlist[0];
		for(int i = 0; i < me->mynumatoms; i++) {
			a->levels[1] = false;
			a->levels[5] = false;
			a->level = 7;
			a++;
		}
		/*
		if(direction == RIGHT)
			myobj->obj = unoc;
		else
			myobj->obj = unocl;
			*/
	}
}
 

void tank::draw() {
	if(destroyed) return;

	float offset;
	float tmp;

	if(firing != 0) {
		if(firing == 20) {
			barrel = tankbarrelanim[0];
			firing = 0;
		}
		else if(firing % 2 == 0) {
			barrel = tankbarrelanim[int(firing * 0.5)];
			firing++;
		}
		else {
			firing++;
		}

		float offset = 18;
		/*
		if(firing == 10) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -0.1, 1, 1);
		}
		else if(firing == 12) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -0.4, 1, 5);
		}
		else if(firing == 14) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -0.8, 1, 15);
		}
		else if(firing == 16) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -1.2, 1, 25);
		}
		else if(firing == 18) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -1.5, 1, 30);
		}
		*/
		if(firing == 2) {
			int tmpv;
			tmpv = allocate_voice(tankfire);
			voice_set_priority(tmpv, 255);
			voice_start(tmpv);
			dopanvol(me->x, 0.15);
			voice_set_pan(tmpv, pan);
			voice_set_volume(tmpv, vol);
			release_voice(tmpv);
			me->ix -= 500 * cos(barrelang * convk2);
			me->gfric = 0.007;
		}
		if(firing == 6) {
			me->gfric = 0.001;
		}

		if(firing == 10) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -0.1, 1, 1);
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -0.4, 1, 5);
		}
		else if(firing == 11) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -0.8, 1, 15);
		}
		else if(firing == 12) {
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -1.2, 1, 25);
			addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -1.5, 1, 30);
		}
		
		if(firing == 6) {
			
			float bulletforce = 3;
			offset = 25;
			addbomb(x + offset * oca, y + offset * osa, bulletforce * oca, bulletforce * osa, driver->side, shell, BOMB);
			offset -= 4;
			/*
			offset -= 4;
			addanimation(redanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, 0, 1, 5);
			offset += 5;
			addanimation(yellowanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, 0, 1, 15);
			offset += 5;
			addanimation(yellowanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, 0, 1, 25);
			offset -= 15;
			*/
		}

	}

	offset = 6.5;
	tmp = 3 - 0.6 * abs((barrelang + 64) * 0.08);
	if(tmp > 0) offset -= tmp;
	pivot_sprite(buf, barrel, x + offset * ca, y + offset * sa, 0, 4, itofix(barrelang + mk));
	/*
	float ca, sa, rca, rsa;
	float mk;
	float goalang;
	mk = me->ang * convk;
	ca = cos(me->ang);
	sa = sin(me->ang);
	rca = -sa;
	rsa = ca;
	cx = me->x - 0;
	cy = me->y - 0;
	if(barreldirection == RIGHT) {
		x = cx + 29*ca - 8 * rca;
		y = cy + 29*sa - 8 * rsa;
		goalang = atan2(my - y, mx - x) * convk;
		goalang -= mk;
		if(goalang < -32) goalang = -32;
		if(goalang > 0) goalang = 0;
		if(barrelang < -32) barrelang = -32;
		if(barrelang > 0) barrelang = 0;
	}
	else {
		x = cx - 27*ca - 8 * rca;
		y = cy - 27*sa - 8 * rsa;
		goalang = atan2(my - y, mx - x) * convk;
		goalang -= mk;
		if(goalang > 0) goalang = -128;
		if(goalang > -96) goalang = -96;
		if(goalang < -128) goalang = -128;
		if(barrelang > 0) barrelang = -128;
		if(barrelang > -96) barrelang = -96;
		if(barrelang < -128) barrelang = -128;
	}
	if(barrelang + barrelspeed < goalang) {
		barrelang += barrelspeed;
	}
	else if(barrelang - barrelspeed > goalang) {
		barrelang -= barrelspeed;
	}
	else {
		barrelang = goalang;
	}
	
	if(barreldirection == RIGHT) pivot_sprite(buf, barrel, x, y, 0, 2, itofix(barrelang + mk));
	else pivot_sprite(buf, barrell, x, y, 0, 2, itofix(barrelang + mk));

	goalang = atan2(my - me->y, mx - me->x) * convk - mk;
	if(goalang < -64 && barreldirection == RIGHT) {
		barreldirection = LEFT;
		barrelang = -128 - barrelang;
	}
	else if(goalang > -64 && barreldirection == LEFT) {
		barrelang = -128 - barrelang;
		barreldirection = RIGHT;
	}
	*/
}

void tank::dokeys() {
	if(destroyed) return;
	float appstrength;
	float dx, dy, d, dtx, dty;
	//float rx, ry;
	int motors[5] = {2, 6, 10, 14, 17};
	int i;
	atom *a;

	//offset = 0;


	if(!engstarted && voice_get_position(engstartvoice) >= 10000) {
		engdir = 0.02;
		engramp = 0;
		engstarted = true;
	}

	tx = mx;
	ty = my;

	dx = me->atomlist[4]->x - me->atomlist[0]->x;
	dy = me->atomlist[4]->y - me->atomlist[0]->y;
	//rx = -dy;
	//ry = dx;
	d = sqrt(dx * dx + dy * dy);
	dx = dx / d;
	dy = dy / d;

	appstrength = strength * COMPFRAMES;

	dx *= appstrength * 0.05;
	dy *= appstrength * 0.05;

	dtx = tx - me->x;
	dty = ty - me->x;


	speed = sqrt(me->ix * me->ix + me->iy * me->iy);

	for(i = 0; i < 5; i++) {
		a = me->atomlist[motors[i]];
		if(a->y > path[(int)a->x] - 5) {
			//me->ix += dx * 0.05;
			//me->iy += dy * 0.05;
			engspeed = 100;
			if(*keyleft && !*keyright && !*keydown && (speed < engspeed || (dx > 0 && me->ix > 0) || (dx < 0 && me->ix < 0))) {
				me->ix -= dx;
				me->iy -= dy;
			}
			else if(*keyright && !*keyleft && !*keydown && (speed < engspeed || (dx > 0 && me->ix < 0) || (dx < 0 && me->ix > 0))) {
				me->ix += dx;
				me->iy += dy;
			}
			else if(!*keyright && !*keyleft) {
				//me->imult = 0;

				if(me->ix < -dx) me->ix += dx;
				else if(me->ix > dx) me->ix -= dx;
				else {
					me->ix = 0;
				}

				/*
				if(me->iy < -dy) me->iy += dy;
				else if(me->iy > dy) me->iy -= dy;
				else {
					me->iy = 0;
				}
				*/

				me->mx = 0;
				//me->my = 0;
				
				if(a->ix < -dx) a->ix += dx;
				else if(a->ix > dx) a->ix -= dx;
				else {
					a->ix = 0;
				}

				/*
				if(a->iy < -dy) a->iy += dy;
				else if(a->iy > dy) a->iy -= dy;
				else {
					a->iy = 0;
				}
				*/
				
				a->mx = 0;
				//a->my = 0;
			}
			/*
			else {
				dx *= 0.4;
				dy *= 0.4;
				if(me->ix > dx) {
					me->ix -= dx;
					if(me->iy > dy)
						me->iy -= dy;
					else if(me->iy < -dy)
						me->iy += dy;
					else
						me->iy = 0;
				}
				else if(me->ix < -dx) {
					me->ix += dx;
					if(me->iy > dy)
						me->iy -= dy;
					else if(me->iy < -dy)
						me->iy += dy;
					else
						me->iy = 0;
				}
				else {
					me->ix = 0;
					if(me->iy > dy)
						me->iy -= dy;
					else if(me->iy < -dy)
						me->iy += dy;
					else
						me->iy = 0;
				}
			}
			*/
		}
	}

	if(fired <= 0 && ((occupied && !driver->comp && mouse_b & 1) || (occupied && driver->comp && *fire))) {
		//if(voice_check(driver->gunvoice) != mgun) driver->dovoices();
		//voice_ramp_volume(driver->gunvoice, 50, 255);
		//voice_set_playmode(driver->gunvoice, PLAYMODE_LOOP);
		//if(direction == RIGHT)
		//addbullet(me->x + 28 * dx + 8 * rx, me->y + 28 * dy + 8 * ry, bulletforce * dx + 0.025 * me->ix, bulletforce * dy + 0.025 * me->iy, 0, 150, 1, 1, black);
		//x + offset * ca, y + offset * sa
		//addbomb(me->x + 15 * rx, me->y + 15 * ry, me->ix * 0.025, me->iy * 0.02, 0);
		//addbullet(x + offset * ca, y + offset * sa, bulletforce * ca, bulletforce * sa, 0, 150, 1, 1, black);
		//else
			//addbullet(me->x - 28 * dx + 8 * rx, me->y - 28 * dy + 8 * ry, -bulletforce * dx + 0.025 * me->ix, -bulletforce * dy + 0.025 * me->iy, 0, 150, 1, 1, black);
		//if(!isdamaged) myobj->obj = firing;
		//else myobj->obj = damagedf;
		//voice_start(driver->gunvoice);
		fired = 300;			
		firing = 1;
		oca = ca;
		osa = sa;
	}
	fired--;


	/*
	if(dtx < 0 && barreldirection == RIGHT) {
		barreldirection = LEFT;
		barrelang = -128 - barrelang;
	}
	else if(dtx > 0 && barreldirection == LEFT) {
		barrelang = -128 - barrelang;
		barreldirection = RIGHT;
	}
	*/

		/*
	if(me->y > path[(int)me->x] - 10 || me->y > path[(int)me->x + 10] - 10 || me->y > path[(int)me->x + 10] - 10) {

		if(*keyleft && !*keyright && !*keydown) {
			me->ix -= dx;
			me->iy -= dy;
			if(direction != LEFT) {
				direction = LEFT;
				//myobj->obj = occl;
			}
		}
		else if(*keyright && !*keyleft && !*keydown) {
			me->ix += dx;
			me->iy += dy;
			if(direction != RIGHT) {
				direction = RIGHT;
				//myobj->obj = occ;
			}
		}
		else if(*keydown && !*keyleft && !*keyright) {
			if(direction == LEFT) {
				me->ix += dx;
				me->iy += dy;
			}
			else if(direction == RIGHT) {
				me->ix -= dx;
				me->iy -= dy;
			}
		}
		else {
			dx *= 0.4;
			dy *= 0.4;
			if(me->ix > dx) {
				me->ix -= dx;
				if(me->iy > dy)
					me->iy -= dy;
				else if(me->iy < -dy)
					me->iy += dy;
				else
					me->iy = 0;
			}
			else if(me->ix < -dx) {
				me->ix += dx;
				if(me->iy > dy)
					me->iy -= dy;
				else if(me->iy < -dy)
					me->iy += dy;
				else
					me->iy = 0;
			}
			else {
				me->ix = 0;
				if(me->iy > dy)
					me->iy -= dy;
				else if(me->iy < -dy)
					me->iy += dy;
				else
					me->iy = 0;
			}
		}
	}
	*/

	int w = 128, h = 64;

	/*
	if(direction == RIGHT) {
		blit(base, myobj->obj, 0, 0, 0, 0, w, h);
		if(barreldirection == RIGHT)
			draw_sprite(myobj->obj, gunu, 0, 0);
		else
			draw_sprite(myobj->obj, gunul, 0, 0);
	}
	else {
		blit(basel, myobj->obj, 0, 0, 0, 0, w, h);
		if(barreldirection == RIGHT)
			draw_sprite(myobj->obj, gunu, 0, 0);
		else
			draw_sprite(myobj->obj, gunul, 0, 0);
	}
	*/
}

void tank::update() {
	int tmpv;

	if(destroyed) return;

	if(engdir > 0) {
		engramp += engdir;
		if(engramp >= 1) {
			engdir = 0;
			engramp = 1;
		}
	}
	else if(engdir < 0) {
		engramp += engdir;
		if(engramp <= 0) {
			engdir = 0;
			engramp = 0;
		}
	}

	if(occupied) {
		ca = cos(me->ang);
		sa = sin(me->ang);
		rca = -sa;
		rsa = ca;
		ox = x;
		oy = y;
		x = me->x + 0.5 * ca - 4 * rca;
		y = me->y + 0.5 * sa - 4 * rsa;
		mk = me->ang;

		if(!driver->comp) {
			tx = mx;
			ty = my;
		}

		goalang = atan2(ty - y, tx - x) - mk;
		
		if(goalang > pi) goalang -= 2*pi;
		if(goalang > pi * 0.5) goalang = -pi;
		else if(goalang > 0) goalang = 0;
		else if(goalang < -pi) goalang = -pi;
		ca = cos(goalang + mk);
		sa = sin(goalang + mk);
		goalang *= convk;
		mk *= convk;
	}
	else {
		ca = cos(me->ang);
		sa = sin(me->ang);
		rca = -sa;
		rsa = ca;
		ox = x;
		oy = y;
		x = me->x + 0.5 * ca - 4 * rca;
		y = me->y + 0.5 * sa - 4 * rsa;
		mk = me->ang;
		ca = cos(goalang * convk2 + mk);
		sa = sin(goalang * convk2 + mk);
		mk *= convk;
	}

	if(occupied) {
		barrelang = goalang;
		dokeys();
		if(speed > 200) {me->ix *= 0.9; me->iy *= 0.9;}
		if(drawframe % 15 == 0) {
			if(me->iy > 0)
				voice_set_frequency(engvoice, speed * 10 + 10000);
			else
				voice_set_frequency(engvoice, speed * 10 + 10000);
			
			dopanvol(me->x, 0.5);
			voice_set_pan(engvoice, pan);
			voice_set_volume(engvoice, vol * engramp);
		}
		//*/
		//if(voice_check(engstartvoice) != enginestart) dovoices();
	}
	
	if(damage > 700 || me->y > waterlevel) {
		if(occupied) {
			driver->me->iy -= 15;
			driver->me->ix = me->ix * 0.06;
			driver->health -= 50;
			driver->intank = NULL;
			driver->invehicle = false;
			occupied = false;
			driver->me->dtmult = 1;
			driver->abody->dtmult = 1;
		}
		myobj->obj = exp;
		addanimation(explosionanim, 16, me->x - 32, me->y - 32, true, 0, 1, 0);
		addscorch((int)me->x, (int)me->y);
		me->y -= 5;
		me->update();
		destroyvehiclerigidbody(me);
		me = NULL;
		destroyed = true;
		tmpv = allocate_voice(explode);
		voice_set_priority(tmpv, 255);
		voice_start(tmpv);
		release_voice(tmpv);
		deallocate_voice(engvoice);
		engvoice = NULL;
	}
}

//addanimation(explosionsmallanim, 15, me->x, me->y);

void plane::getin(soldier *newdriver) {
	atom *a;
	noturn = true;
	driver = newdriver;
	me->afric = FLUIDFRICTION;
	if(destroyed) return;
	if(occupied == false) {
		engstartcount = 0;
		driver->me->dtmult = 0;
		driver->abody->dtmult = 0;
		me->gfric = 0.001;
		sadd = 20;
		me->ram = 0.0003;
		occupied = true;
		if(voice_check(engstartvoice) != propstart) dovoices();
		voice_start(engstartvoice);
		dopanvol(me->x, 0.5);
		voice_set_pan(engstartvoice, pan);
		voice_set_volume(engstartvoice, vol);
		release_voice(engstartvoice);
		engstarted = false;
		voice_set_position(engstartvoice, 0);
		//voice_ramp_volume(engvoice, 100, 255);
		if(!isdamaged) myobj->obj = occ;
		else myobj->obj = damagedo;
		if(driver->side == ENEMY) {
			a = me->atomlist[0];
			for(int i = 0; i < me->mynumatoms; i++) {
				a->levels[1] = true;
				a->levels[5] = false;
				a->levels[14] = false;
				a->level = 12;
				a++;
			}
		}
		else {
			a = me->atomlist[0];
			for(int i = 0; i < me->mynumatoms; i++) {
				a->levels[1] = false;
				a->levels[5] = true;
				a->levels[13] = false;
				a->level = 11;
				a++;
			}			
			keyleft = &(key[KEY_A]);
			keyright = &(key[KEY_D]);
			keyup = &(key[KEY_W]);
			keydown = &(key[KEY_S]);
		}
	}
	else {
		engramp = 0;
		engdir = 0;
		driver->me->dtmult = 1;
		driver->abody->dtmult = 1;
		me->gfric = 0.001;
		me->ram = 0.00005;
		me->ix *= 2;
		me->iy *= 2;
		engspeed += sadd;
		sadd = 0;
		voice_ramp_volume(engvoice, 100, 0);
		occupied = false;
		engstarted = false;
		if(!isdamaged) myobj->obj = unoc;
		else myobj->obj = damaged;
		a = me->atomlist[0];
		for(int i = 0; i < me->mynumatoms; i++) {
			a->levels[1] = false;
			a->levels[5] = false;
			a->levels[7] = false;
			a->level = 7;
			a++;
		}
	}
}

void plane::dokeys() {
	if(destroyed) return;

	if(occupied) {
		//float dx, dy;
		/*
		float astrength = 100;
		float aforce = 3;
		float app;
		float ox, oy, od;
		float ang;
		float goalang;
		float dif;
		*/
		//float speed;
		float tk;
		float rammult;
		rammult = 1;

		if(!engstarted && engstartcount > 100) {
			//voice_ramp_volume(engvoice, 300, 255);
			engdir = 0.02;
			engramp = 0;
			engstarted = true;
		}
		else
			engstartcount++;

		if(engstarted) {
			if(*keyup && !*keydown && goalspeed < 0.105) {
				goalspeed += 0.001;
			}
			else if(*keydown && !*keyup && goalspeed > 0.001) {
				goalspeed -= 0.001;
			}
			else if(*keydown && !*keyup) {
				goalspeed = 0;
			}
		}

		me->gmult = 20;

		//engspeed = 0.105;

		
		if(me->y > path[(int)me->x] - 15) {
			//engspeed = 0.2;
			//engspeed = goalspeed * 1.9;
			engspeed = goalspeed;
			//tk = 0.03;
			//tk = 0.001;
			tk = 0.0001 * rammult;
		}
		else {
			engspeed = goalspeed;
			//engspeed = 0.105;
			//tk = 0.0002;
			tk = 0.00015 * rammult;
		}
		if(engspeed == 0.0) {
			me->gfric = 0.001;
		}
		else {
			me->gfric = 0;
		}

		speed = sqrt(me->ix * me->ix + me->iy * me->iy);
		//if(cos(turnang) != 0) speed /= cos(turnang);

		float ang = me->ang * convk;

		if(!inturn) {
			if(direction == RIGHT ) {
				if(speed < 38 && speed > 5) {
					float add = 38 - speed;
					if(ang < -64 || ang > 64) {
						me->ia -= 0.015 * add * rammult;
						//me->ia -= 0.3;
					}
					else {
						me->ia += 0.015 * add * rammult;
						//me->ia += 0.3;
					}
				}
			}
			else {
				if(speed < 38 && speed > 5) {
					float add = 38 - speed;
					if(ang < -64 || ang > 64) {
						me->ia += 0.015 * add * rammult;
						//me->ia += 0.3;
					}
					else {
						me->ia -= 0.015 * add * rammult;
						//me->ia -= 0.3;
					}
				}
			}
		}

		//me->ix += engspeed * dx;
		//me->iy += engspeed * dy;

		if(!inturn) {
			//if(direction == RIGHT) {
				me->ix += engspeed * dx;
				me->iy += engspeed * dy;
			//}
			//else {
				//me->ix -= engspeed * dx;
				//me->iy -= engspeed * dy;
			//}
		}
		else {
			if(direction == RIGHT) {
				me->ix += engspeed * dx * cos(turnang);
				me->iy += engspeed * dy * cos(turnang);
			}
			else {
				me->ix -= engspeed * dx * cos(turnang);
				me->iy -= engspeed * dy * cos(turnang);
			}
		}

		float xs = fabs(me->ix);

		/*
		if(xs < 65) {
			me->iy -= (50 / 65) * xs * GRAVITY;
			4(screen, 0, 0, 10, magenta);
		}
		else {
			me->iy -= 50 * GRAVITY;a
		}
		*/

		//if(me->y > path[(int)me->x] - 10) {me->y = path[(int)me->x] - 10; me->iy = 0;}

		me->ix *= 0.999;
		me->iy *= 0.999;

		float p1, p2, c1, c2;
		float a;
		p1 = me->atomlist[1]->x - me->atomlist[0]->x;
		p2 = me->atomlist[1]->y - me->atomlist[0]->y;
		p1 *= 0.14;
		p2 *= 0.14;

		a = me->ix * p1 + me->iy * p2;
		if(!inturn && speed < 45 && speed > 15) a *= (speed - 15) / 30;
		else if(!inturn && speed < 15) a = 0;
		//a *= 0.08;
		a *= 0.10;
		c1 = -0.5 * a * p1;
		c2 = -0.5 * a * p2;
		me->ix += c1;
		me->iy += c2;

		if(!driver->comp) {
			tx = mx;
			ty = my;
		}
		float goalang, ox, oy;
		ox = tx - me->x;
		oy = ty - me->y;
		if(direction == RIGHT) {
			goalang = atan2(oy, ox);
		}
		else {
			goalang = atan2(-oy, -ox);
		}
		if(me->ang > pi) me->ang -= 2*pi;
		if(me->ang < -pi) me->ang += 2*pi;

		float dif;
		dif = me->ang - goalang;
		if(fabs(dif * convk) > 128) dif = (pi - dif);

		//me->ia = 0;

		/*
		if(fabs(dif) > 0.005 && engspeed > 5) {
			if(dif < 0) {
				me->ang += 0.008;
			}
			else {
				me->ang -= 0.008;
			}
		}
		*/

		me->ia *= 0.99;

		if(!inturn) {
			if(dif < 0) {
				me->ia += tk * speed * speed;
			}
			else {
				me->ia -= tk * speed * speed;
			}
		}
		else {
			if(dif < 0) {
				me->ia += tk * oldspeed * oldspeed * 0.5;
			}
			else {
				me->ia -= tk * oldspeed * oldspeed * 0.5;
			}
		}

		if(!noturn && !inturn && *keyleft && !*keyright) {
			if(direction == RIGHT) {
				direction = LEFT;
				inturn = true;
				float msx, cx;
				mx = 2*me->x - mx;
				msx = (mx - center->x + 600) * (2.0 / 3.0);
				cx = mx - msx;
				if(cx < 0) {
					msx += cx;
				}
				else if(cx > buf->w - 800) {
					msx += (cx - (buf->w - 800));
					//msx -= cx - buf->w + 800;
				}
				if(!driver->comp) position_mouse(msx, 2*me->y - my);
				xch = -(me->ix) / 250;
				ych = -(me->iy) / 250 - 0.1;
				oldspeed = speed;
			}
		}
		else if(!noturn && !inturn && *keyright && !*keyleft) {
			if(direction == LEFT) {
				direction = RIGHT;
				inturn = true;
				float msx, cx;
				mx = 2*me->x - mx;
				msx = (mx - center->x + 600) * (2.0 / 3.0);
				cx = mx - msx;
				if(cx < 0) {
					msx += cx;
				}
				else if(cx > buf->w - 800) {
					msx += (cx - (buf->w - 800));
					//msx -= cx - buf->w + 800;
				}
				if(!driver->comp) position_mouse(msx, 2*me->y - my);
				xch = -(me->ix) / 250;
				ych = -(me->iy) / 250 - 0.1;
				oldspeed = speed;
			}
		}
		else if(!inturn && !*keyleft && !*keyright)
			noturn = false;

		if(inturn) speed = oldspeed;

		/*
		if(*keyup && !*keydown) {
			me->ia += 0.002 * speed;
		}
		else if(*keydown && !*keyup) {
			me->ia -= 0.002 * speed;
		}
		*/

		//speed += 100000000000;
		//speed = 10;
		/*
		me->afric = FLUIDFRICTION;
		
		if(me->y > path[(int)me->x] - 20) {
			me->afric = 0.95;
			me->ix *= 0.995;
		}

		me->ix = 0;
		me->iy = 0;

		if(me->ix > 40) me->ix = 40;
		if(me->ix < -40) me->ix = -40;

		ox = mx - me->x;
		oy = my - me->y;
		od = sqrt(ox * ox + oy * oy);
		if(direction == RIGHT) {
			goalang = atan2(oy, ox);
		}
		else {
			goalang = atan2(-oy, -ox);
		}
		if(me->ang > pi) me->ang -= 2*pi;
		if(me->ang < -pi) me->ang += 2*pi;

		dif = me->ang - goalang;
		if(fabs(dif * convk) > 128) dif = (pi - dif);

		me->ia = 0;

		if(fabs(dif) > 0.005 && engspeed > 5) {
			if(dif < 0) {
				me->ang += 0.008;
			}
			else {
				me->ang -= 0.008;
			}
		}

		if(!inturn) {
			if(direction == RIGHT) {
				me->ix += engspeed * dx;
				me->iy += engspeed * dy;
			}
			else {
				me->ix -= engspeed * dx;
				me->iy -= engspeed * dy;
			}
		}
		else {
			me->ix += engspeed * dx * cos(turnang);
			me->iy += engspeed * dy * cos(turnang);
		}

		if((!inturn && direction == RIGHT) || (inturn && direction == LEFT && turning < 0.5) || (inturn && direction == RIGHT && turning > 0.5)) {
			if(dy < 0)
				engspeed += 0.15 * dy;
			else
				engspeed += 0.3 * dy;
		}
		else {
			if(dy < 0)
				engspeed -= 0.3 * dy;
			else
				engspeed -= 0.15 * dy;
		}

		//if(oy < 0) {
		if(engspeed < goalspeed)
			engspeed += 0.1;
		else if(engspeed > goalspeed)
			engspeed -= 0.1;
		//} 
		engspeed *= 0.9995;

		speed = me->ix * dx + me->iy * dy;

		if(speed > 40) speed = 40;
		if(speed < -40) speed = -40;

		app = fabs(me->ix);
		if(oy > 0)
			app = speed;

		if(speed > 0)
			 me->iy -= 1.75 * (app) * GRAVITY;

		if(me->ang > pi) me->ang -= 2*pi;
		if(me->ang < -pi) me->ang += 2*pi;

		dif = me->ang - goalang;
		if(fabs(dif * convk) > 128) dif = (pi - dif);

		me->ia = 0;

		if(fabs(dif) > 0.005 && engspeed > 5) {
			if(dif < 0) {
				me->ang += 0.008;
			}
			else {
				me->ang -= 0.008;
			}
		}
		else if(engspeed > 5) {
			me->ia = goalang;
		}

		if(!inturn) {
			if(direction == RIGHT ) {
				if(engspeed < 38 && engspeed > 5) {
					float add = 38 - engspeed;
					if(ang < -64 || ang > 64) {
						me->ang -= 0.001 * add;
					}
					else {
						me->ang += 0.001 * add;
					}
				}
			}
			else {
				if(engspeed < 38 && engspeed > 5) {
					float add = 38 - engspeed;
					if(ang < -64 || ang > 64) {
						me->ang += 0.001 * add;
					}
					else {
						me->ang -= 0.001 * add;
					}
				}
			}
		}

		speed = 2 * engspeed + 3 * sadd;

		if(!noturn && !inturn && *keyleft && !*keyright) {
			if(direction == RIGHT) {
				direction = LEFT;
				inturn = true;
				float msx, cx;
				mx = 2*me->x - mx;
				msx = (mx - center->x + 600) * (2.0 / 3.0);
				cx = mx - msx;
				if(cx < 0) {
					msx += cx;
				}
				else if(cx > buf->w - 800) {
					msx += (cx - (buf->w - 800));
					//msx -= cx - buf->w + 800;
				}
				position_mouse(msx, 2*me->y - my);
			}
		}
		else if(!noturn && !inturn && *keyright && !*keyleft) {
			if(direction == LEFT) {
				direction = RIGHT;
				inturn = true;
				float msx, cx;
				mx = 2*me->x - mx;
				msx = (mx - center->x + 600) * (2.0 / 3.0);
				cx = mx - msx;
				if(cx < 0) {
					msx += cx;
				}
				else if(cx > buf->w - 800) {
					msx += (cx - (buf->w - 800));
					//msx -= cx - buf->w + 800;
				}
				position_mouse(msx, 2*me->y - my);
			}
		}
		else if(!inturn && !*keyleft && !*keyright)
			noturn = false;
		*/
		
		if(((mouse_b & 2 && !driver->comp) || (driver->comp && *dropbomb)) && bfired <= 0 && !inturn) {
			float bulletforce = 3;
			if(direction == RIGHT)
				addbomb(me->x + 15 * rx, me->y + 15 * ry, me->ix * 0.025, me->iy * 0.02, driver->side, bombbmp, BOMB);
			else
				addbomb(me->x + 15 * rx, me->y + 15 * ry, me->ix * 0.025, me->iy * 0.02, driver->side, bombbmp, BOMB);
			dopanvol(me->x, 0.25);
			play_sample(bombdrop, vol * .78, pan, 1000, 0);
			bfired = 150;
			//bfired = 60;
		}
		bfired--;

		if(((mouse_b & 1 && !driver->comp) || (driver->comp && *fire)) && fired <= 0 && !inturn) {
			float bulletforce = 3;
			if(voice_check(driver->gunvoice) != mgun) driver->dovoices();
			voice_ramp_volume(driver->gunvoice, 50, 255);
			voice_set_playmode(driver->gunvoice, PLAYMODE_LOOP);
			//if(direction == RIGHT)
				addbullet(me->x + 28 * dx + 6 * rx, me->y + 28 * dy + 6 * ry, bulletforce * dx + 0.025 * me->ix, bulletforce * dy + 0.025 * me->iy, 0, 150, 1, 1, black, driver->side);
			//else
				//addbullet(me->x - 28 * dx + 8 * rx, me->y - 28 * dy + 8 * ry, -bulletforce * dx + 0.025 * me->ix, -bulletforce * dy + 0.025 * me->iy, 0, 150, 1, 1, black, false);
			if(!isdamaged) myobj->obj = firing;
			else myobj->obj = damagedf;
			voice_start(driver->gunvoice);
			fired = 30;
		}
		fired--;
		if(fired <= 5 && myobj->obj == firing) {
			if(occupied) myobj->obj = occ;
			else myobj->obj = unoc;
		}
		else if(fired <= -5 && myobj->obj == damagedf) {
			if(occupied) myobj->obj = damagedo;
			else myobj->obj = damaged;
		}
		if(fired < -5) {
			voice_ramp_volume(driver->gunvoice, 50, 0);
		}
	}
	/*
	else {
		me->afric = 0.95;
		if(me->y > path[(int)me->x] - 20) {
			me->ix *= 0.995;
		}
	}
	*/
}

void plane::setdirection(bool newdir) {	
	atom *a;
	int i;
	float dist;
	float tdx, tdy, m, om, ox, oy, od;
	if(newdir != direction) {
		direction = newdir;
		for(i = 0; i < me->mynumatoms - 2; i++) {
			a = me->atomlist[i];
			//dx = a->x - me->x;
			//dy = a->y - me->y;
			tdx = -me->offset[i][0];
			tdy = me->offset[i][1];

			me->offset[i][0] = tdx;
			me->offset[i][1] = tdy;
			dist = sqrt(tdx * tdx + tdy * tdy);
			me->ol[i] = dist;
			m = tdy / tdx;
			if(m != 0) {
				om = (-1) / m;
				ox = 1;
				oy = om;
			}
			else {
				om = 0;
				ox = 0;
				oy = 1;
			}
			od = sqrt(1 + oy * oy);
			ox = ox / od;
			oy = oy / od;
			if(tdy > 0) {
				ox = -ox;
				oy = -oy;
			}
			me->ouv[i][0] = ox;
			me->ouv[i][1] = oy;
		}

		turning = 1;
		//me->ix += xch;
		//me->iy += ych;
		turnang = turning * pi + pi;
		tcos = cos(turnang);
		me->turning = tcos;
		if(turning >= 1) {
			turning = 0;
			inturn = false;
		}
		i = 18;
		a = me->atomlist[i];
		//dx = a->x - me->x;
		//dy = a->y - me->y;
		if(direction == LEFT) turnang -= pi;
		tdx = 15 * cos(turnang);
		tdy = 11;

		me->offset[i][0] = tdx;
		me->offset[i][1] = tdy;
		dist = sqrt(tdx * tdx + tdy * tdy);
		me->ol[i] = dist;
		m = tdy / tdx;
		if(m != 0) {
			om = (-1) / m;
			ox = 1;
			oy = om;
		}
		else {
			om = 0;
			ox = 0;
			oy = 1;
		}
		od = sqrt(1 + oy * oy);
		ox = ox / od;
		oy = oy / od;
		if(tdy > 0) {
			ox = -ox;
			oy = -oy;
		}
		me->ouv[i][0] = ox;
		me->ouv[i][1] = oy;

		
		i = 19;		
		a = me->atomlist[i];
		//dx = a->x - me->x;
		//dy = a->y - me->y;
		tdx = -15 * cos(turnang);
		//if(direction == LEFT) tdx = -tdx;
		tdy = 9;
		me->offset[i][0] = tdx;
		me->offset[i][1] = tdy;
		dist = sqrt(tdx * tdx + tdy * tdy);
		me->ol[i] = dist;
		m = tdy / tdx;
		if(m != 0) {
			om = (-1) / m;
			ox = 1;
			oy = om;
		}
		else {
			om = 0;
			ox = 0;
			oy = 1;
		}
		od = sqrt(1 + oy * oy);
		ox = ox / od;
		oy = oy / od;
		if(tdy > 0) {
			ox = -ox;
			oy = -oy;
		}
		me->ouv[i][0] = ox;
		me->ouv[i][1] = oy;
		//a->r = this;
	}
}

void plane::update() {
	int tmpv;

	if(destroyed) return;
	dx = me->atomlist[5]->x - me->atomlist[2]->x;
	dy = me->atomlist[5]->y - me->atomlist[2]->y;
	rx = me->atomlist[2]->x - me->atomlist[1]->x;
	ry = me->atomlist[2]->y - me->atomlist[1]->y;
	dx *= 0.1;
	dy *= 0.1;
	rx *= 0.1;
	ry *= 0.1;
	dokeys();

	if(engdir > 0) {
		engramp += engdir;
		if(engramp >= 1) {
			engdir = 0;
			engramp = 1;
		}
	}
	else if(engdir < 0) {
		engramp += engdir;
		if(engramp <= 0) {
			engdir = 0;
			engramp = 0;
		}
	}

	/*
	if(me->y > waterlevel) {
		me->iy -= 70 * GRAVITY;
	}
	else {
		me->iy += 70 * GRAVITY;
	}
	*/

	if(inturn) {
		atom *a;
		int i;
		float dist;
		float tdx, tdy, m, om, ox, oy, od;
		if(turning == 0) {
			for(i = 0; i < me->mynumatoms - 2; i++) {
				a = me->atomlist[i];
				//dx = a->x - me->x;
				//dy = a->y - me->y;
				tdx = -me->offset[i][0];
				tdy = me->offset[i][1];

				me->offset[i][0] = tdx;
				me->offset[i][1] = tdy;
				dist = sqrt(tdx * tdx + tdy * tdy);
				me->ol[i] = dist;
				m = tdy / tdx;
				if(m != 0) {
					om = (-1) / m;
					ox = 1;
					oy = om;
				}
				else {
					om = 0;
					ox = 0;
					oy = 1;
				}
				od = sqrt(1 + oy * oy);
				ox = ox / od;
				oy = oy / od;
				if(tdy > 0) {
					ox = -ox;
					oy = -oy;
				}
				me->ouv[i][0] = ox;
				me->ouv[i][1] = oy;
			}
		}

		turning += 0.002;
		me->ix += xch;
		me->iy += ych;
		if(turning > 1) turning = 1;
		//if(direction == LEFT) {
			//turnang = turning * pi;
		//}
		//else if(direction == RIGHT) {
			turnang = turning * pi + pi;
		//}
		tcos = cos(turnang);
		me->turning = tcos;
		if(turning >= 1) {
			turning = 0;
			inturn = false;
		}


		i = 18;
		a = me->atomlist[i];
		//dx = a->x - me->x;
		//dy = a->y - me->y;
		if(direction == LEFT) turnang -= pi;
		tdx = 15 * cos(turnang);
		tdy = 11;

		me->offset[i][0] = tdx;
		me->offset[i][1] = tdy;
		dist = sqrt(tdx * tdx + tdy * tdy);
		me->ol[i] = dist;
		m = tdy / tdx;
		if(m != 0) {
			om = (-1) / m;
			ox = 1;
			oy = om;
		}
		else {
			om = 0;
			ox = 0;
			oy = 1;
		}
		od = sqrt(1 + oy * oy);
		ox = ox / od;
		oy = oy / od;
		if(tdy > 0) {
			ox = -ox;
			oy = -oy;
		}
		me->ouv[i][0] = ox;
		me->ouv[i][1] = oy;

		
		i = 19;		
		a = me->atomlist[i];
		//dx = a->x - me->x;
		//dy = a->y - me->y;
		tdx = -15 * cos(turnang);
		//if(direction == LEFT) tdx = -tdx;
		tdy = 9;
		me->offset[i][0] = tdx;
		me->offset[i][1] = tdy;
		dist = sqrt(tdx * tdx + tdy * tdy);
		me->ol[i] = dist;
		m = tdy / tdx;
		if(m != 0) {
			om = (-1) / m;
			ox = 1;
			oy = om;
		}
		else {
			om = 0;
			ox = 0;
			oy = 1;
		}
		od = sqrt(1 + oy * oy);
		ox = ox / od;
		oy = oy / od;
		if(tdy > 0) {
			ox = -ox;
			oy = -oy;
		}
		me->ouv[i][0] = ox;
		me->ouv[i][1] = oy;
		//a->r = this;
	}

	/*
	if(engspeed < 38) {
		float dif;
		dif = 38 - engspeed;
		if(dif > 15) dif = 15;
		me->y += 0.03 * dif;
	}
	*/

	if(occupied) {
		//if(me->ix * me->ix + me->iy * me->iy > 1600) me->ix *= 0.9;
		//if(me->iy > 0)
			//voice_set_frequency(engvoice, (speed + me->iy) * 100 + 10000);
		//else

		if(drawframe % 15 == 0 || (engramp <  1 && drawframe % 3 == 0)) {
			voice_set_frequency(engvoice, speed * 100 + 8000);
			
			dopanvol(me->x, 0.2);
			voice_set_pan(engvoice, pan);
			voice_set_volume(engvoice, vol * engramp);
		}

		//if(voice_check(engstartvoice) != propstart) dovoices();
	}
	else {
		engspeed -= 0.1;
		if(engspeed < 0) engspeed = 0;
		goalspeed = 0;
	}
	if(me->y >= waterlevel - 5) {
		if(occupied) {
			driver->me->iy -= 1;
			driver->me->ix = me->ix * 0.1;
			//driver->health -= 50;
			driver->inplane = NULL;
			driver->invehicle = false;
			driver->me->dtmult = 1;
			driver->abody->dtmult = 1;
			occupied = false;
		}
		myobj->obj = exp;
		/*
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addanimation(explosionanim, 16, me->x - 32, me->y - 32, true, 0, 1, 0);
		*/
		me->y -= 5;
		me->update();
		me->gmult = 70;
		me->ix *= 0.3;
		me->iy *= 0.3;
		destroyvehiclerigidbody(me);
		me = NULL;
		destroyed = true;
		tmpv = allocate_voice(gurgle);
		voice_set_priority(tmpv, 255);
		voice_start(tmpv);
		release_voice(tmpv);
		deallocate_voice(engvoice);
		engvoice = NULL;
	}
	else if(damage > 200) {
		if(occupied) {
			driver->me->dtmult = 1;
			driver->abody->dtmult = 1;
			driver->me->iy -= 5;
			driver->me->ix = me->ix * 0.3;
			driver->health -= 50;
			driver->inplane = NULL;
			driver->invehicle = false;
			occupied = false;
		}
		myobj->obj = exp;
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addanimation(explosionanim, 16, me->x - 32, me->y - 32, true, 0, 1, 0);
		me->y -= 5;
		me->update();
		me->gmult = 70;
		for(int i = 0; i < me->mynumatoms; i++) {
			me->atomlist[i]->levels[me->atomlist[i]->level] = true;
		}
		destroyvehiclerigidbody(me);
		destroyatom(me->atomlist[17]);
		destroyatom(me->atomlist[18]);
		me = NULL;
		destroyed = true;
		tmpv = allocate_voice(explode);
		voice_set_priority(tmpv, 255);
		voice_start(tmpv);
		release_voice(tmpv);
		deallocate_voice(engvoice);
		engvoice = NULL;
	}
	else if(damage > 100 && isdamaged == false) {
		isdamaged = true;
		if(occupied) myobj->obj = damagedo;
		else myobj->obj = damaged;
	}
	if(!destroyed && isdamaged && dispframe) addanimation(smokeanim, 24, me->polylistx[1] - 15 + 3*rx, me->polylisty[1] - 15 + 3*ry, true, -1, 1, 20);//addanimation(smokeanim, 24, me->polylistx[1] - 15 - 3*dx*tcos + 3*rx, me->polylisty[1] - 15 - 3*dy*tcos + 3*ry, true, -1, 1, 20);
}


void heli::dokeys() {
	if(destroyed) return;

	if(occupied) {
		//float dx, dy;
		/*
		float astrength = 100;
		float aforce = 3;
		float app;
		float ox, oy, od;
		float ang;
		float goalang;
		float dif;
		*/
		//float speed;

		

		float tk;
		float rammult;
		rammult = 1;

		if(driver->comp) fprintf(debug, "heli: (frame %i) %i,%i,%i,%i,%f,%f\n", frame, *keyup,*keydown,*keyleft,*keyright,tx,ty);
		else fprintf(debug, "heli: (frame %i) %i,%i,%i,%i,%f,%f\n", frame, -*keyup,-*keydown,-*keyleft,-*keyright,tx,ty);

		if(!engstarted && engstartcount > 80) {//voice_get_position(engstartvoice) >= 15000) {
			//voice_ramp_volume(engvoice, 300, 255);
			engdir = 0.02;
			engramp = 0;
			engstarted = true;
			engstartcount = 0;
		}
		else if(!engstarted)
			engstartcount++;
		//engstarted = true;

		if(engstarted) {
			if(*keyup && !*keydown && goalspeed < 0.2) {
				goalspeed += 0.001;
			}
			else if(*keydown && !*keyup && goalspeed > 0.001) {
				goalspeed -= 0.001;
			}
			else if(*keydown && !*keyup) {
				goalspeed = 0;
			}
		}

		//me->gmult = 20;

		engspeed = goalspeed;
		tk = 0.5 * rammult;

		/*
		if(engspeed == 0.0) {
			me->gfric = 0.001;
		}
		else {
			me->gfric = 0;
		}
		*/

		speed = engspeed + 0.002*sqrt(me->ix * me->ix + me->iy * me->iy);

		float ang = me->ang * convk;

		me->ix -= engspeed * rx;
		me->iy -= engspeed * ry;

		me->ix *= 0.999;
		me->iy *= 0.999;

		if(!driver->comp) {
			tx = mx;
			ty = my;
		}
		float goalang, ox, oy;

		ox = tx - me->x;
		oy = ty - me->y;
		if(direction == RIGHT) {
			goalang = atan2(oy, ox);
		}
		else {
			goalang = atan2(-oy, -ox);
		}
		if(me->ang > pi) me->ang -= 2*pi;
		if(me->ang < -pi) me->ang += 2*pi;

		float dif;
		dif = me->ang - goalang;
		if(fabs(dif * convk) > 128) dif = (pi - dif);

		me->ia *= 0.99;

		if(dif < 0) {
			me->ia += tk;
		}
		else {
			me->ia -= tk;
		}

		if(!noturn && !inturn && *keyleft && !*keyright) {
			if(direction == RIGHT) {
				direction = LEFT;
				inturn = true;
				float msx, cx;
				mx = 2*me->x - mx;
				msx = (mx - center->x + 600) * (2.0 / 3.0);
				cx = mx - msx;
				if(cx < 0) {
					msx += cx;
				}
				else if(cx > buf->w - 800) {
					msx += (cx - (buf->w - 800));
					//msx -= cx - buf->w + 800;
				}
				if(!driver->comp) position_mouse(msx, my);//2*me->y - my);
				xch = -(me->ix) / 250;
				ych = -(me->iy) / 250 - 0.1;
			}
		}
		else if(!noturn && !inturn && *keyright && !*keyleft) {
			if(direction == LEFT) {
				direction = RIGHT;
				inturn = true;
				float msx, cx;
				mx = 2*me->x - mx;
				msx = (mx - center->x + 600) * (2.0 / 3.0);
				cx = mx - msx;
				if(cx < 0) {
					msx += cx;
				}
				else if(cx > buf->w - 800) {
					msx += (cx - (buf->w - 800));
					//msx -= cx - buf->w + 800;
				}
				if(!driver->comp) position_mouse(msx, my);//2*me->y - my);
				xch = -(me->ix) / 250;
				ych = -(me->iy) / 250 - 0.1;
			}
		}
		else if(!inturn && !*keyleft && !*keyright)
			noturn = false;

		if(((mouse_b & 2 && !driver->comp) || (driver->comp && *dropbomb)) && bfired <= 0 && !inturn) {
			float bulletforce = 3;
			bomb *b;

			/*
			if(direction == RIGHT)
				b = addbomb(me->x + 0 * dx + 6 * rx, me->y + 0 * dy + 6 * ry, me->ix * 0.025 + 4 * dx, me->iy * 0.02 + 4 * dy, driver->side, missilebmp, MISSILE);
			else
				b = addbomb(me->x + 0 * dx + 6 * rx, me->y + 0 * dy + 6 * ry, me->ix * 0.025 + 4 * dx, me->iy * 0.02 + 4 * dy, driver->side, missilebmp, MISSILE);
			*/
			if(direction == RIGHT)
				b = addbomb(me->x + 0 * dx + 6 * rx, me->y + 0 * dy + 6 * ry, 4 * dx, 4 * dy, driver->side, missilebmp, MISSILE);
			else
				b = addbomb(me->x + 0 * dx + 6 * rx, me->y + 0 * dy + 6 * ry, 4 * dx, 4 * dy, driver->side, missilebmp, MISSILE);
			
			//addtrailanim(a, anim, frames, mod, modoff, life, dy, rand, trans, delay);
			//addtrailanim(b->me, misstrailanim, 9, 5, 0, 500, 0, 1, false, 1);
			addtrailanim(b->me, whiteanim, 24, 1, 0, 500, 0, 1, true, -2);
			
			//addanimation(whiteanim, 24, x + offset * ca - 15, y + offset * sa - 15, true, -0.1, 1, 1);

			dopanvol(me->x, 0.25);
			play_sample(bombdrop, vol * .78, pan, 1000, 0);
			bfired = 150;
			//bfired = 60;
		}
		bfired--;

		if(((mouse_b & 1 && !driver->comp) || (driver->comp && *fire)) && fired <= 0 && !inturn) {
			float bulletforce = 3;
			if(voice_check(driver->gunvoice) != mgun) driver->dovoices();
			voice_ramp_volume(driver->gunvoice, 50, 255);
			voice_set_playmode(driver->gunvoice, PLAYMODE_LOOP);
			//if(direction == RIGHT)
				addbullet(me->x + 28 * dx + 6 * rx, me->y + 28 * dy + 6 * ry, bulletforce * dx + 0.025 * me->ix, bulletforce * dy + 0.025 * me->iy, 0, 150, 1, 1, black, driver->side);
			if(!isdamaged) myobj->obj = firing;
			else myobj->obj = damagedf;
			voice_start(driver->gunvoice);
			fired = 30;
		}
		fired--;
		if(fired <= 5 && myobj->obj == firing) {
			if(occupied) myobj->obj = occ;
			else myobj->obj = unoc;
		}
		else if(fired <= -5 && myobj->obj == damagedf) {
			if(occupied) myobj->obj = damagedo;
			else myobj->obj = damaged;
		}
		if(fired < -5) {
			voice_ramp_volume(driver->gunvoice, 50, 0);
		}
	}
}

void heli::getin(soldier *newdriver) {
	atom *a;
	noturn = true;
	driver = newdriver;
	me->afric = FLUIDFRICTION;
	if(destroyed) return;
	if(occupied == false) {
		engramp = 0;
		driver->me->dtmult = 0;
		driver->abody->dtmult = 0;
		//me->gfric = 0.001;
		sadd = 20;
		me->ram = 0.0003;
		occupied = true;
		if(voice_check(engstartvoice) != propstart) dovoices();
		voice_start(engstartvoice);
		engstartcount = 0;
		dopanvol(me->x, 0.5);
		voice_set_pan(engstartvoice, pan);
		voice_set_volume(engstartvoice, vol);
		release_voice(engstartvoice);
		engstarted = false;
		voice_set_position(engstartvoice, 0);
		//voice_ramp_volume(engvoice, 100, 255);
		if(!isdamaged) myobj->obj = occ;
		else myobj->obj = damagedo;
		if(driver->side == ENEMY) {
			a = me->atomlist[0];
			for(int i = 0; i < me->mynumatoms; i++) {
				a->levels[1] = true;
				a->levels[5] = false;
				a->levels[14] = false;
				a->level = 12;
				a++;
			}
		}
		else {
			a = me->atomlist[0];
			for(int i = 0; i < me->mynumatoms; i++) {
				a->levels[1] = false;
				a->levels[5] = true;
				a->levels[13] = false;
				a->level = 11;
				a++;
			}			
			keyleft = &(key[KEY_A]);
			keyright = &(key[KEY_D]);
			keyup = &(key[KEY_W]);
			keydown = &(key[KEY_S]);
		}
		if(driver->comp) {
			dropbomb = &(driver->controller->dropbomb);
			keyleft = &(driver->controller->goleft);
			keyright = &(driver->controller->goright);
			keyup = &(driver->controller->goup);
			fire = &(driver->controller->fire);
			keydown = &(driver->controller->godown);
		}
	}
	else {
		engramp = 0;
		engdir = 0;
		driver->me->dtmult = 1;
		driver->abody->dtmult = 1;
		//me->gfric = 0.001;
		me->ram = 0.00005;
		me->ix *= 2;
		me->iy *= 2;
		engspeed += sadd;
		sadd = 0;
		voice_ramp_volume(engvoice, 100, 0);
		occupied = false;
		engstarted = false;
		if(!isdamaged) myobj->obj = unoc;
		else myobj->obj = damaged;
		a = me->atomlist[0];
		for(int i = 0; i < me->mynumatoms; i++) {
			a->levels[1] = false;
			a->levels[5] = false;
			a->levels[7] = false;
			a->level = 7;
			a++;
		}
	}
}

void heli::setdirection(bool newdir) {	
	atom *a;
	int i;
	float dist;
	float tdx, tdy, m, om, ox, oy, od;
	if(newdir != direction) {
		direction = newdir;
		for(i = 0; i < me->mynumatoms - 2; i++) {
			a = me->atomlist[i];

			tdx = -me->offset[i][0];
			tdy = me->offset[i][1];

			me->offset[i][0] = tdx;
			me->offset[i][1] = tdy;
			dist = sqrt(tdx * tdx + tdy * tdy);
			me->ol[i] = dist;
			m = tdy / tdx;
			if(m != 0) {
				om = (-1) / m;
				ox = 1;
				oy = om;
			}
			else {
				om = 0;
				ox = 0;
				oy = 1;
			}
			od = sqrt(1 + oy * oy);
			ox = ox / od;
			oy = oy / od;
			if(tdy > 0) {
				ox = -ox;
				oy = -oy;
			}
			me->ouv[i][0] = ox;
			me->ouv[i][1] = oy;
		}

		turning = 1;
		//me->ix += xch;
		//me->iy += ych;
		turnang = turning * pi + pi;
		tcos = cos(turnang);
		me->turning = tcos;
		if(turning >= 1) {
			turning = 0;
			inturn = false;
		}
		i = 18;
		a = me->atomlist[i];
		//dx = a->x - me->x;
		//dy = a->y - me->y;
		if(direction == LEFT) turnang -= pi;
		tdx = 15 * cos(turnang);
		tdy = 11;

		me->offset[i][0] = tdx;
		me->offset[i][1] = tdy;
		dist = sqrt(tdx * tdx + tdy * tdy);
		me->ol[i] = dist;
		m = tdy / tdx;
		if(m != 0) {
			om = (-1) / m;
			ox = 1;
			oy = om;
		}
		else {
			om = 0;
			ox = 0;
			oy = 1;
		}
		od = sqrt(1 + oy * oy);
		ox = ox / od;
		oy = oy / od;
		if(tdy > 0) {
			ox = -ox;
			oy = -oy;
		}
		me->ouv[i][0] = ox;
		me->ouv[i][1] = oy;

		
		i = 19;		
		a = me->atomlist[i];
		//dx = a->x - me->x;
		//dy = a->y - me->y;
		tdx = -15 * cos(turnang);
		//if(direction == LEFT) tdx = -tdx;
		tdy = 9;
		me->offset[i][0] = tdx;
		me->offset[i][1] = tdy;
		dist = sqrt(tdx * tdx + tdy * tdy);
		me->ol[i] = dist;
		m = tdy / tdx;
		if(m != 0) {
			om = (-1) / m;
			ox = 1;
			oy = om;
		}
		else {
			om = 0;
			ox = 0;
			oy = 1;
		}
		od = sqrt(1 + oy * oy);
		ox = ox / od;
		oy = oy / od;
		if(tdy > 0) {
			ox = -ox;
			oy = -oy;
		}
		me->ouv[i][0] = ox;
		me->ouv[i][1] = oy;
		//a->r = this;
	}
}

void heli::update() {
	int tmpv;

	if(destroyed) return;
	dx = me->atomlist[4]->x - me->atomlist[1]->x;
	dy = me->atomlist[4]->y - me->atomlist[1]->y;
	rx = me->atomlist[1]->x - me->atomlist[0]->x;
	ry = me->atomlist[1]->y - me->atomlist[0]->y;
	dx *= 0.1;
	dy *= 0.1;
	rx *= 0.1;
	ry *= 0.1;
	dokeys();

	if(engdir > 0) {
		engramp += engdir;
		if(engramp >= 1) {
			engdir = 0;
			engramp = 1;
		}
	}
	else if(engdir < 0) {
		engramp += engdir;
		if(engramp <= 0) {
			engdir = 0;
			engramp = 0;
		}
	}

	if(occupied && !driver->comp && 0) {
		accx += mouse_x - omouse_x;
		accy += mouse_y - omouse_y;

		nmouse_x = me->x + accx;
		nmouse_y = me->y + accy;
		//position_mouse(me->x + accx - lx, me->y + accy);

		omouse_x = mouse_x;
		omouse_y = mouse_y;
	}

		//accx -= (int)(accx - 1.5);
		//accy -= (int)(accy - 1.5);

		//accx = accy = .5;
		//accy = 0.5;
		//accx = 0;



	//}

	/*
	if(me->y > waterlevel) {
		me->iy -= 70 * GRAVITY;
	}
	else {
		me->iy += 70 * GRAVITY;
	}
	*/

	if(inturn) {
		atom *a;
		int i;
		float dist;
		float tdx, tdy, m, om, ox, oy, od;
		if(turning == 0) {
			for(i = 0; i < me->mynumatoms; i++) {
				a = me->atomlist[i];
				//dx = a->x - me->x;
				//dy = a->y - me->y;
				tdx = -me->offset[i][0];
				tdy = me->offset[i][1];

				me->offset[i][0] = tdx;
				me->offset[i][1] = tdy;
				dist = sqrt(tdx * tdx + tdy * tdy);
				me->ol[i] = dist;
				m = tdy / tdx;
				if(m != 0) {
					om = (-1) / m;
					ox = 1;
					oy = om;
				}
				else {
					om = 0;
					ox = 0;
					oy = 1;
				}
				od = sqrt(1 + oy * oy);
				ox = ox / od;
				oy = oy / od;
				if(tdy > 0) {
					ox = -ox;
					oy = -oy;
				}
				me->ouv[i][0] = ox;
				me->ouv[i][1] = oy;
			}
		}

		turning += 0.002;

		//me->ix += xch;

		if(turning > 1) turning = 1;
		
		turnang = turning * pi + pi;
		tcos = cos(turnang);
		me->turning = tcos;
		if(turning >= 1) {
			turning = 0;
			inturn = false;
		}
	}

	if(occupied) {
		if(drawframe % 15 == 0 || (engramp <  1 && drawframe % 3 == 0)) {
			voice_set_frequency(engvoice, speed * 10000 + 8000);
			
			dopanvol(me->x, 0.2);
			voice_set_pan(engvoice, pan);
			voice_set_volume(engvoice, vol * engramp);
		}
	}
	else {
		engspeed -= 0.1;
		if(engspeed < 0) engspeed = 0;
		goalspeed = 0;
	}
	if(me->y >= waterlevel - 5) {
		if(occupied) {
			driver->me->iy -= 1;
			driver->me->ix = me->ix * 0.1;
			//driver->health -= 50;
			driver->inheli = NULL;
			driver->invehicle = false;
			driver->me->dtmult = 1;
			driver->abody->dtmult = 1;
			occupied = false;
		}
		myobj->obj = exp;
		/*
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addanimation(explosionanim, 16, me->x - 32, me->y - 32, true, 0, 1, 0);
		*/
		me->y -= 5;
		me->update();
		//me->gmult = 70;
		me->ix *= 0.3;
		me->iy *= 0.3;
		destroyvehiclerigidbody(me);
		me = NULL;
		destroyed = true;
		tmpv = allocate_voice(gurgle);
		voice_set_priority(tmpv, 255);
		voice_start(tmpv);
		release_voice(tmpv);
		deallocate_voice(engvoice);
		engvoice = NULL;
	}
	else if(damage > 200) {
		if(occupied) {
			driver->me->dtmult = 1;
			driver->abody->dtmult = 1;
			driver->me->iy -= 5;
			driver->me->ix = me->ix * 0.3;
			driver->health -= 50;
			driver->inheli = NULL;
			driver->invehicle = false;
			occupied = false;
		}
		myobj->obj = exp;
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[7], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addtrailanim(me->atomlist[10], explosionsmallanim, 24, 10, rand() % 10, 1500 + rand() % 1500, -2, 5, false, 1);
		addanimation(explosionanim, 16, me->x - 32, me->y - 32, true, 0, 1, 0);
		me->y -= 5;
		me->update();
		//me->gmult = 70;
		for(int i = 0; i < me->mynumatoms; i++) {
			me->atomlist[i]->levels[me->atomlist[i]->level] = true;
		}
		destroyvehiclerigidbody(me);
		destroyatom(me->atomlist[17]);
		destroyatom(me->atomlist[18]);
		me = NULL;
		destroyed = true;
		tmpv = allocate_voice(explode);
		voice_set_priority(tmpv, 255);
		voice_start(tmpv);
		release_voice(tmpv);
		deallocate_voice(engvoice);
		engvoice = NULL;
	}
	else if(damage > 100 && isdamaged == false) {
		isdamaged = true;
		if(occupied) myobj->obj = damagedo;
		else myobj->obj = damaged;
	}
	if(!destroyed && isdamaged && dispframe) addanimation(smokeanim, 24, me->polylistx[15] - 15, me->polylisty[15] - 15, true, -2, 1, 20);//addanimation(smokeanim, 24, me->polylistx[1] - 15 - 3*dx*tcos + 3*rx, me->polylisty[1] - 15 - 3*dy*tcos + 3*ry, true, -1, 1, 20);
}

void updatesoldiers() {
	int i;
	soldier *s;
	
	s = &(soldiers[0]);
	for(i = 0; i < numsoldiers; i++) {
		s->update();
		s++;
	}
}

void updatecompsoldiers() {
	int i;
	compsoldier *s;
	
	s = &(compsoldiers[0]);
	for(i = 0; i < numcompsoldiers; i++) {
		s->update();
		s++;
	}
}

void drawsoldiers() {
	int i;
	soldier *s;
	
	s = &(soldiers[0]);
	for(i = 0; i < numsoldiers; i++) {
		s->draw();
		s++;
	}
}

void erasesoldiers() {
	int i;
	soldier *s;
	
	s = &(soldiers[0]);
	for(i = 0; i < numsoldiers; i++) {
		s->erase();
		s++;
	}
}

soldier *addsoldier() {
	soldier *s;
	s = &(soldiers[numsoldiers]);
	numsoldiers++;
	return s;
}

compsoldier *addcompsoldier() {
	compsoldier *c;
	c = &(compsoldiers[numcompsoldiers]);
	numcompsoldiers++;
	return c;
}

compsoldier *addcompsoldier(float x, float y, bool side) {
	soldier *s;
	atom *a;
	compsoldier *c;
	settmplevels();
	if(side == ENEMY) {
		tmplevels[1] = false;
		tmplevels[4] = false;
		tmplevels[5] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		tmplevels[12] = false;
		tmplevels[14] = false;
		a = addatom(x, y, tmplevels, 5);
	}
	else if(side == FRIEND) {
		tmplevels[1] = false;
		tmplevels[3] = false;
		tmplevels[4] = false;
		tmplevels[5] = false;
		tmplevels[7] = false;
		tmplevels[11] = false;
		tmplevels[13] = false;
		a = addatom(x, y, tmplevels, 1);
	}
	s = addsoldier();
	c = addcompsoldier();
	a->rmdt = 0.23;
	s->comp = true;
	s->init(a, side);
	c->init(s, side);
	return c;
}

void initlevel();

void init_graphics() {
	allegro_init();
	set_color_depth(16);
	if(DRAWING) {
		if(!WINDOWED) set_gfx_mode(GFX_AUTODETECT, 800, 600, 0, 0);//set_gfx_mode(GFX_AUTODETECT, 800, 600, 0, 0);
		else set_gfx_mode(GFX_AUTODETECT_WINDOWED, 300, 300, 0, 0);
	}
	install_timer();
	install_keyboard();
	install_mouse();
	reserve_voices(64, 1);
	set_volume_per_voice(5);
	install_sound(DIGI_AUTODETECT, MIDI_NONE, "moo");
	set_volume(100, 65);
	//set_volume(50, 50);
	set_alpha_blender();
	set_color_conversion(COLORCONV_EXPAND_256);
	set_alpha_blender();
}

void readpath(char *file) {
     ifstream iff;
     iff.open(file);
     
     int read = 0, last = -1, pos = 0;

     int tmp;
     iff >> tmp;
     while(pos < tmp) {
         last = read;
         iff >> read;
         path[pos] = (600.0 / 480.0) * read;
         debrislev[pos] = (600.0 / 480.0) * read - 7;
         pos++;
     }

	 iff.close();
}

void updatebombs() {
	bomb *b;
	int i;
	b = &(bombs[0]);
	for(i = 0; i < numbombs; i++) {
		if(b->on) {
			b->update();
		}
		b++;
	}
}

void update() {
	bullet *b;
	int i;

	updaterigidbodies();
	physics_update();
	updatetrailanims();
	updatecompsoldiers();
	updatesoldiers();
	updateaaguns();
	updatejeeps();
	updatetanks();
	updateplanes();
	updatehelis();
	updatebombs();
	b = &(bullets[0]);
	for(i = 0; i < MAXBULLETS; i++) {
		b->update();
		b++;
	}
}

void drawdebris() {
	debrisitem *d;
	int i;
	d = &(debris[0]);
	for(i = 0; i < MAXDEBRIS; i++) {
		if(d->on) {
			d->draw();
		}
		d++;
	}
}

void erasedebris() {
	debrisitem *d;
	int i;
	d = &(debris[0]);
	for(i = 0; i < MAXDEBRIS; i++) {
		if(d->on) {
			d->erase();
		}
		d++;
	}
}

void drawbombs() {
	bomb *b;
	int i;
	b = &(bombs[0]);
	for(i = 0; i < numbombs; i++) {
		if(b->on) {
			b->draw();
		}
		b++;
	}
}

void erasebombs() {
	bomb *b;
	int i;
	b = &(bombs[0]);
	for(i = 0; i < numbombs; i++) {
		if(b->on) {
			b->erase();
		}
		b++;
	}
}

void drawbullets() {
	bullet *b;
	int i;
	b = &(bullets[0]);
	for(i = 0; i < MAXBULLETS; i++) {
		if(b->life > 0) {
			b->draw();
		}
		b++;
	}
}

void erasebullets() {
	bullet *b;
	int i;
	b = &(bullets[0]);
	for(i = 0; i < MAXBULLETS; i++) {
		if(b->life > 0) {
			b->erase();
		}
		b++;
	}
}

#define MAXGUIBARS 4

BITMAP *guibars[MAXGUIBARS];
//BITMAP *guibarsbuf[10];
float guibarposx[MAXGUIBARS];
float guibarposy[MAXGUIBARS];
bool guibaron[MAXGUIBARS];
BITMAP *guitemp;
BITMAP *digits[10];
BITMAP *inf;
bool updateguibars[MAXGUIBARS];
int numguibars;

//0 - human
//1 - machine gun
//2 - heli rockets
//3 - heli

void initguibars() {
	BITMAP *tmp;
	int x;
	tmp = load_bitmap("digits.pcx", NULL);
	for(x = 0; x < 10; x++) {
		digits[x] = create_bitmap(16, 17);
		blit(tmp, digits[x], x * 16, 0, 0, 0, 16, 17);
	}
	destroy_bitmap(tmp);
	inf = load_bitmap("inf.pcx", NULL);

	guibars[0] = load_bitmap("guibar_soldier.tga", NULL);
	guibars[1] = load_bitmap("guibar_weapgun.tga", NULL);
	guibars[2] = load_bitmap("guibar_weaphelirocket.tga", NULL);
	guibars[3] = load_bitmap("guibar_heli.tga", NULL);

	guibarposx[0] = 0;
	guibarposy[0] = 0;
	guibarposx[1] = 700;
	guibarposy[1] = 0;
	guibarposx[2] = 700;
	guibarposy[2] = 0;
	guibarposx[3] = 0;
	guibarposy[3] = 40;
	guibaron[0] = true;
	guibaron[1] = true;
	guibaron[2] = false;
}

void doguinumbers(float num, int nodigits, float x, float y) {
	int i;
	int dig;
	for(i = nodigits; i > 0; i--) {
		if(num >= pow(10, i - 1)) {
			dig = (int)(num * pow(10, -i + 1)) % 10;
			draw_sprite(buf, digits[dig], x + (nodigits - i) * 16, y);
		}
	}
}

void drawguibars() {
	if(human->invehicle && human->inheli != NULL) {
		guibarposx[1] = 600;
		guibaron[2] = true;
		guibaron[3] = true;
	}
	else {
		guibarposx[1] = 700;
		guibaron[2] = false;
		guibaron[3] = false;
	}

	if(guibaron[0]) {
		draw_trans_sprite(buf, guibars[0], lx + guibarposx[0], guibarposy[0]);
		doguinumbers(human->health, 3, lx + guibarposx[0] + 59, guibarposy[0] + 11);
	}

	if(guibaron[1]) {
		draw_trans_sprite(buf, guibars[1], lx + guibarposx[1], guibarposy[1]);
		draw_sprite(buf, inf, lx + guibarposx[1] + 63, guibarposy[1] + 14);
	}

	if(guibaron[2]) {
		draw_trans_sprite(buf, guibars[2], lx + guibarposx[2], guibarposy[2]);
		draw_sprite(buf, inf, lx + guibarposx[2] + 65, guibarposy[2] + 14);
	}

	if(guibaron[3]) {
		draw_trans_sprite(buf, guibars[3], lx + guibarposx[3], guibarposy[3]);
		doguinumbers(100 - human->inheli->damage * 0.5, 3, lx + guibarposx[3] + 59, guibarposy[3] + 11);
	}
}

void eraseguibars() {
	int i;
	for(i = 0; i < MAXGUIBARS; i++)
		if(guibaron[i])
			blit(bg, buf, lx + guibarposx[i], guibarposy[i], lx + guibarposx[i], guibarposy[i], guibars[i]->w, guibars[i]->h);
}

//MAINDRAW

void draw() {
	float cx, mdx, mdy;

	if(center->fixed) {
		if(mouse_x < 100 && center->x > 400) {
			center->x -= (100 - mouse_x) * 0.2;
		}
		else if(mouse_x > 700 && center->x < ground->w - 400) {
			center->x += (mouse_x - 700) * 0.2;
		}
	}

	//cx = (400 + mouse_x) * 0.5 + center->x - 800;//((center->x - 400) + (mouse_x - 400)) * 0.5;
	cx = 0.5 * mouse_x + center->x - 600;
	if(cx < 0) cx = 0;
	if(cx > ground->w - 800) cx = ground->w - 800;
	lx = cx;
	rx = cx + 800;
	mx = mouse_x + cx;
	my = mouse_y - mousebmp->h / 2;
	mdx = mx - mousebmp->w / 2;
	mdy = my - mousebmp->h / 2;
	//position_mouse(nmouse_x - lx, nmouse_y);
	//omouse_x = mouse_x;
	//omouse_y = mouse_y;
	
	//textprintf(buf, font, cx + 10, 10, white, "Health: %f", human->health);
	//textprintf(buf, font, cx + 10, 30, white, "Jeep damage: %f", jeep1.damage);

	drawaaguns();
	drawplanes();
	drawhelis();
	drawatoms();
	drawlinks();
	drawpolys();
	drawtanks();
	drawbullets();
	drawbombs();
	drawdebris();
	drawsoldiers();
	drawanimations();
	drawguibars();

	//if(!human->invehicle)
	draw_sprite(buf, mousebmp, mdx, mdy);

	//save_bitmap("sshot.pcx", buf, NULL);
	//exit(0);
	if(DRAWING) {
	
		vsync();
	
	
		if(!WINDOWED) blit(buf, screen, cx, 0, 0, 0, 800, 600);
		else blit(buf, screen, center->x - 150, center->y - 150, 0, 0, 300, 300);
	}
	//blit(buf, screen, center->x - 50, center->y - 50, 0, 0, 100, 100);
	screencenterx = cx + 400;


	//blit(buf, screen, 1800, 400, 0, 0, 200, 200);

	blit(bg, buf, cx, 10, cx, 10, 200, 10);

	eraseatoms();
	eraselinks();
	erasepolys();
	eraseaaguns();
	eraseplanes();
	erasehelis();
	erasebullets();
	erasetanks();
	erasebombs();
	erasedebris();
	erasesoldiers();
	eraseanimations();
	eraseguibars();
	blit(bg, buf, mdx, mdy, mdx, mdy, mousebmp->w, mousebmp->h);
}

bool boxadded;
bool saved;
bool loaded;

void dokeys() {
	if(key[KEY_R]) {
		int i;
		reset();
		destroy_bitmap(ground);
		destroy_bitmap(buf);
		destroy_bitmap(sky);
		destroy_bitmap(bg);
		ground = buf = sky = bg = NULL;
		for(i = 0; i < numjeeps; i++) {
			jeeps[i].killvoices();
			jeeps[i].reset();
			//jeeps[i].init();
		}
		numjeeps = 0;
		for(i = 0; i < numtanks; i++) {
			tanks[i].killvoices();
			tanks[i].reset();
		}
		numtanks = 0;
		for(i = 0; i < numplanes; i++) {
			planes[i].killvoices();
			planes[i].reset();
			//planes[i].init();
		}
		numplanes = 0;
		for(i = 0; i < numhelis; i++) {
			helis[i].killvoices();
			helis[i].reset();
			//planes[i].init();
		}
		numhelis = 0;
		for(i = 0; i < MAXBULLETS; i++) {
			bullets[i].life = 0;
			bullets[i].update();
			bullets[i].init();
		}
		for(i = 0; i < MAXBOMBS; i++) {
			bombs[i].on = false;
			bombs[i].init();
		}
		numbombs = 0;
		for(i = 0; i < MAXDEBRIS; i++) {
			debris[i].on = false;
			debris[i].init();
		}
		for(i = 0; i < numsoldiers; i++) {
			soldiers[i].killvoices();
			soldiers[i].reset();
		}
		numsoldiers = 0;
		for(i = 0; i < numcompsoldiers; i++) {
			compsoldiers[i].reset();
		}
		numcompsoldiers = 0;
		for(i = 0; i < numanimations; i++) {
			animations[i].reset();
		}
		numanimations = 0;
		for(i = 0; i < MAXTRAILANIMS; i++) {
			trailanims[i].reset();
		}
		numtrailanims = 0;
		for(i = 0; i < numaaguns; i++) {
			aaguns[i].reset();
		}
		numaaguns = 0;
		initlevel();
		while(key[KEY_R]) ;
		frame = 0;
	}

	if(key[KEY_F6] && !saved) {
		//savestate("quicksave.dat");
		//fprintf(debug, "SAVING STATE AT FRAME %i\n", frame);
		//movie_savemovie(script, "quickscript.mvi");
		compsoldiers[0].doscript(script, 0, -frame);
		saved = true;
	}
	else if(!key[KEY_F6]) {
		saved = false;
	}

	if(key[KEY_F7] && !loaded) {
		//loadstate("quicksave.dat");
		//savemovie(script, "quickscript.mvi");
		movie_savemovie(script, "quickscript.mvi");
		/*
		movie_loadmovie(script, "quickscript.mvi");
		recording = false;
		compsoldiers[0].doscript(script, 0, -frame + 1);
		*/
		loaded = true;
	}
	else if(!key[KEY_F7]) {
		loaded = false;
	}

	if(key[KEY_B] && !boxadded) {
		addbox();
		boxadded = true;
	}
	else if(!key[KEY_B])
		boxadded = false;
}

void initvars() {
	int i;
	BITMAP *tmp;
	boxadded = false;
	mousebmp = load_bitmap("target.pcx", NULL);
	black = makecol16(0,0,0);
	green = makecol16(0,255,0);
	white = makecol16(255,255,255);
	magenta = makecol16(255, 0, 255);
	gray = makecol16(122, 122, 122);
	yellow = makecol16(220, 220, 0);
	convk = 128.0 / pi;
	convk2 = pi / 128.0;
	COMPFRAMES = 6;
	//srand(time(NULL));
	settmplevels();
	mgun = load_sample("mgun.wav");
	bombdrop = load_sample("bombdrop.wav");
	aagunfire = load_sample("aagun.wav");
	tankfire = load_sample("tankfire.wav");
	gurgle = load_sample("gurgle.wav");
	splash = load_sample("splash.wav");
	engine = load_sample("engine.wav");
	enginestart = load_sample("enginestart.wav");
	prop = load_sample("prop.wav");
	propstart = load_sample("propstart.wav");
	death1 = load_sample("death1.wav");
	//play_sample(mgun, 255, 122, 1000, 0);
	explode = load_sample("explodelarge.wav");
	explodesmall = load_sample("explodesm.wav");
	music = load_midi("lev1.mid");
	initguibars();
	script = movie_createmovie();
	recording = false;

	//play_midi(music, true);
	numanimations = 0;
	numtrailanims = 0;
	numbombs = 0;
	jeep *j;
	for(i = 0; i < MAXJEEPS; i++) {
		j = &(jeeps[i]);
		j->unoc = load_bitmap("jeepu.pcx", NULL);
		j->unocl = load_bitmap("jeepul.pcx", NULL);
		j->occ = load_bitmap("jeepo.pcx", NULL);
		j->occl = load_bitmap("jeepol.pcx", NULL);
		j->exp = load_bitmap("jeepd.pcx", NULL);
		j->expl = load_bitmap("jeepdl.pcx", NULL);
	}

	tankbase = load_bitmap("tanku.pcx", NULL);
	tankbasee = load_bitmap("tankue.pcx", NULL);
	tankd = load_bitmap("tankd.pcx", NULL);
	tankde = load_bitmap("tankde.pcx", NULL);

	planeunoc = load_bitmap("planeu.pcx", NULL);
	planeocc = load_bitmap("planeo.pcx", NULL);
	planefiring = load_bitmap("planef.pcx", NULL);
	planeexp = load_bitmap("planed.pcx", NULL);
	planedamaged = load_bitmap("planeh.pcx", NULL);
	planedamagedo = load_bitmap("planeho.pcx", NULL);
	planedamagedf = load_bitmap("planehf.pcx", NULL);

	planeunoce = load_bitmap("planeue.pcx", NULL);
	planeocce = load_bitmap("planeoe.pcx", NULL);
	planefiringe = load_bitmap("planefe.pcx", NULL);
	planeexpe = load_bitmap("planede.pcx", NULL);
	planedamagede = load_bitmap("planehe.pcx", NULL);
	planedamagedoe = load_bitmap("planehoe.pcx", NULL);
	planedamagedfe = load_bitmap("planehfe.pcx", NULL);

	heliunoc = load_bitmap("heliu.pcx", NULL);
	heliocc = load_bitmap("helio.pcx", NULL);
	helifiring = load_bitmap("helif.pcx", NULL);
	heliexp = load_bitmap("helid.pcx", NULL);
	helidamaged = load_bitmap("helih.pcx", NULL);
	helidamagedo = load_bitmap("heliho.pcx", NULL);
	helidamagedf = load_bitmap("helihf.pcx", NULL);

	heliunoce = load_bitmap("heliue.pcx", NULL);
	heliocce = load_bitmap("helioe.pcx", NULL);
	helifiringe = load_bitmap("helife.pcx", NULL);
	heliexpe = load_bitmap("helide.pcx", NULL);
	helidamagede = load_bitmap("helihe.pcx", NULL);
	helidamagedoe = load_bitmap("helihoe.pcx", NULL);
	helidamagedfe = load_bitmap("helihfe.pcx", NULL);

	/*
	tank *t;
	for(i = 0; i < MAXTANKS; i++) {
		t = &(tanks[i]);
		t->base = tankbase;
		t->exp = tankd;
	}
	
	plane *p;
	for(i = 0; i < MAXPLANES; i++) {
		p = &(planes[i]);
		p->unoc = load_bitmap("planeu.pcx", NULL);
		p->occ = load_bitmap("planeo.pcx", NULL);
		p->firing = load_bitmap("planef.pcx", NULL);
		p->exp = load_bitmap("planed.pcx", NULL);
		p->expl = load_bitmap("planedl.pcx", NULL);
		p->damaged = load_bitmap("planeh.pcx", NULL);
		p->damagedo = load_bitmap("planeoh.pcx", NULL);
		p->damagedf = load_bitmap("planehf.pcx", NULL);
	}

	heli *h;
	for(i = 0; i < MAXHELIS; i++) {
		h = &(helis[i]);
		h->unoc = load_bitmap("heliu.pcx", NULL);
		h->occ = load_bitmap("helio.pcx", NULL);
		h->firing = load_bitmap("helif.pcx", NULL);
		h->exp = load_bitmap("helid.pcx", NULL);
		h->expl = load_bitmap("helid.pcx", NULL);
		h->damaged = load_bitmap("heli.pcx", NULL);
		h->damagedo = load_bitmap("helio.pcx", NULL);
		h->damagedf = load_bitmap("helif.pcx", NULL);
	}
	*/

	aagun *a;
	for(i = 0; i < MAXAAGUNS; i++) {
		a = &(aaguns[i]);
		a->barrel = load_bitmap("aagunbarrel.pcx", NULL);
		a->gunbg = load_bitmap("aagunbg.pcx", NULL);
		a->base = load_bitmap("aagunbase.pcx", NULL);
		a->baseo = load_bitmap("aagunbaseo.pcx", NULL);
		a->baseoe = load_bitmap("aagunbaseoe.pcx", NULL);
	}
	debris1 = load_bitmap("debris1.tga", NULL);
	debriso1 = load_bitmap("debriso1.tga", NULL);
	grounddebris1 = load_bitmap("grounddebris1.pcx", NULL);
	debrisr[0] = load_bitmap("debrisr1.tga", NULL);
	debrisr[1] = load_bitmap("debrisr2.tga", NULL);
	debrisr[2] = load_bitmap("debrisr3.tga", NULL);
	debrisr[3] = load_bitmap("debrisr4.tga", NULL);
	debrisrm[0] = load_bitmap("debrisrm1.tga", NULL);
	debrisrm[1] = load_bitmap("debrisrm2.tga", NULL);
	debrisrm[2] = load_bitmap("debrisrm3.tga", NULL);
	debrisrm[3] = load_bitmap("debrisrm4.tga", NULL);
	scorch = load_bitmap("scorch.tga", NULL);
	bombbmp = load_bitmap("bomb.pcx", NULL);
	missilebmp = load_bitmap("missile.pcx", NULL);
	shell = load_bitmap("shell.pcx", NULL);
	tmp = load_bitmap("explosion.tga", NULL);
	int x, y;

	for(x = 0; x < 4; x++) {
		for(y = 0; y < 4; y++) {
			explosionanim[x + y*4] = create_bitmap_ex(32, 64, 64);
			blit(tmp, explosionanim[x + y*4], x * 64, y * 64, 0, 0, 64, 64);
		}
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("explosionsmall.pcx", NULL);
	for(x = 0; x < 24; x++) {
		explosionsmallanim[x] = create_bitmap(9, 9);
		blit(tmp, explosionsmallanim[x], x * 9, 0, 0, 0, 9, 9);
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("tankbarrel.pcx", NULL);
	for(y = 0; y < 10; y++) {
		tankbarrelanim[y] = create_bitmap(17, 8);
		blit(tmp, tankbarrelanim[y], 0, y * 8, 0, 0, 17, 8);
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("smoke.tga", NULL);
	for(x = 0; x < 24; x++) {
		smokeanim[x] = create_bitmap_ex(32, 30, 30);
		blit(tmp, smokeanim[x], x * 30, 0, 0, 0, 30, 30);
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("redpart.tga", NULL);
	for(x = 0; x < 24; x++) {
		redanim[x] = create_bitmap_ex(32, 30, 30);
		blit(tmp, redanim[x], x * 30, 0, 0, 0, 30, 30);
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("yellowpart.tga", NULL);
	for(x = 0; x < 24; x++) {
		yellowanim[x] = create_bitmap_ex(32, 30, 30);
		blit(tmp, yellowanim[x], x * 30, 0, 0, 0, 30, 30);
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("whitepart.tga", NULL);
	for(x = 0; x < 24; x++) {
		whiteanim[x] = create_bitmap_ex(32, 30, 30);
		blit(tmp, whiteanim[x], x * 30, 0, 0, 0, 30, 30);
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("splash.pcx", NULL);
	for(x = 0; x < 6; x++) {
		splashanim[x] = create_bitmap(9, 4);
		blit(tmp, splashanim[x], x * 9, 0, 0, 0, 9, 4);
	}

	destroy_bitmap(tmp);
	tmp = load_bitmap("trail.pcx", NULL);
	for(x = 0; x < 9; x++) {
		misstrailanim[x] = create_bitmap(20, 20);
		blit(tmp, misstrailanim[x], x * 20, 0, 0, 0, 20, 20);
	}

	destroy_bitmap(tmp);
}

void initlevel() {
	if(level == 0) {
		ground = load_bitmap("lev0.pcx", NULL);
		readpath("lev0.pat");
		waterlevel = 600;
	}
	else if(level == 1) {
		ground = load_bitmap("lev1.pcx", NULL);
		readpath("lev1.pat");
		waterlevel = 600;
	}
	else if(level == 2) {
		ground = load_bitmap("lev2.pcx", NULL);
		readpath("lev2.pat");
		waterlevel = 524;
	}
	sky = load_bitmap("sky.pcx", NULL);
	bg = create_bitmap(ground->w, ground->h);
	buf = create_bitmap(ground->w, ground->h);
	draw_sprite(bg, sky, 0, 0);
	draw_sprite(bg, ground, 0, 0);
	draw_sprite(buf, bg, 0, 0);
	settmplevels();
	tmplevels[1] = false;
	tmplevels[0] = false;
	tmplevels[6] = false;
	tmplevels[7] = false;
	//addobject("building.pcx", 100, 234, true, tmplevels, 2, 1);

	//tmplevels[2] = false;

	//exptemp = create_bitmap_ex(32, 

	compsoldier *e;
	aagun *a;
	tank *t;
	plane *p;
	
	if(level == 0) {


		//cleartmplevels();
		//addobject("heli.pcx", NULL, 100, 400, false, tmplevels, 7, 1);
		//addobject("heli.pcx", NULL, 400, 400, false, tmplevels, 7, 1);


		tmplevels[1] = false;
		tmplevels[0] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		addobject("building4.pcx", NULL, 1700, 231, true, tmplevels, 2, 0.98);

		//addheli(100.1, 512, FRIEND);
		addheli(300.1, 512, FRIEND);

		//addplane(300, 512, FRIEND);
		//addplane(300, 512, FRIEND);

		//t = addtank(2000, 412, true);
		//e = addcompsoldier(2000, 400, ENEMY);
		//e->dotankdriver(t);
		//e->dohunt();

		e = addcompsoldier(300, 440, FRIEND);
		//human = e->me;
		//center = e->me->me;

		settmplevels();
		tmplevels[1] = false;
		tmplevels[0] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		//addobject("building.pcx", "buildingt.tga", 2300, 231, true, tmplevels, 2, 1);

		settmplevels();
		tmplevels[1] = false;
		tmplevels[4] = false;
		tmplevels[3] = false;
		tmplevels[7] = false;
		tmplevels[10] = true;
		tmplevels[11] = false;
		tmplevels[13] = false;

		center = addatom(300, 440, tmplevels, 1);
		center->rmdt = 0.23;
		human = addsoldier();
		human->init(center, FRIEND);
	}
	else if(level == 1) {
		bool madness = false;
		if(!madness && 1 && 0) {
			e = addcompsoldier(1100, 400, ENEMY);
			e->dohunt();
			e = addcompsoldier(1130, 400, ENEMY);
			e->dohunt();
			e = addcompsoldier(1160, 400, ENEMY);
			e->dohunt();
			e = addcompsoldier(1190, 400, ENEMY);
			e->dohunt();
		}

		//addplane(125, 512);
		e = addcompsoldier(2950, 100, ENEMY);
		p = addplane(2950, 100, ENEMY);
		p->setdirection(LEFT);
		e->doplanepilot(p);


		//e = addcompsoldier(125, 512, FRIEND);
		//p = addplane(125, 512);
		//e->doplanepilot(p);

		e = addcompsoldier(840, 250, FRIEND);
		e->dopatrol(840, 940);

		e = addcompsoldier(100, 444, FRIEND);
		e->dohunt();
		e = addcompsoldier(200, 444, FRIEND);
		e->dohunt();
		e = addcompsoldier(300, 473, FRIEND);
		e->dohunt();
		e = addcompsoldier(400, 473, FRIEND);
		e->dohunt();

		e = addcompsoldier(2000, 444, ENEMY);
		e->dohunt();
		e = addcompsoldier(2100, 444, ENEMY);
		e->dohunt();
		e = addcompsoldier(2200, 473, ENEMY);
		e->dohunt();
		e = addcompsoldier(2150, 473, ENEMY);
		e->dohunt();
		e = addcompsoldier(1850, 473, ENEMY);
		e->dohunt();
		e = addcompsoldier(1900, 473, ENEMY);
		e->dohunt();

		t = addtank(400, 412, false);
		e = addcompsoldier(500, 400, FRIEND);
		e->dotankdriver(t);
		e->dohunt();

		t = addtank(600, 412, false);
		e = addcompsoldier(600, 400, FRIEND);
		e->dotankdriver(t);
		e->dohunt();

		t = addtank(2000, 412, true);
		e = addcompsoldier(2000, 400, ENEMY);
		e->dotankdriver(t);
		e->dohunt();
		
		t = addtank(1700, 412, true);
		e = addcompsoldier(2100, 400, ENEMY);
		e->dotankdriver(t);
		e->dohunt();
		
		/*
		t = addtank(1800, 412, true);
		e = addcompsoldier(2100, 400, ENEMY);
		e->dotankdriver(t);
		e->dohunt();
		
		t = addtank(1900, 412, true);
		e = addcompsoldier(2100, 400, ENEMY);
		e->dotankdriver(t);
		//e->dohunt();
		e->dowait();
		*/

		/*
		e = addcompsoldier(500, 400);
		e = addcompsoldier(510, 400);
		e = addcompsoldier(520, 400);
		e = addcompsoldier(530, 400);	
		*/

		///*
		e = addcompsoldier(1670, 444, ENEMY);
		e->dopatrol(1670, 1760);
		e = addcompsoldier(1770, 444, ENEMY);
		e->dopatrol(1770, 1940);
		e = addcompsoldier(1950, 473, ENEMY);
		e->dopatrol(1950, 2320);
		e = addcompsoldier(1950, 473, ENEMY);
		e->dopatrol(1950, 2020);
		e = addcompsoldier(1950, 473, ENEMY);
		e->dopatrol(2200, 2320);
		e = addcompsoldier(1950, 473, ENEMY);
		e->dopatrol(2630, 2720);
		//e = addcompsoldier(1950, 473);
		//e->dopatrol(2730, 2820);
		e = addcompsoldier(2050, 473, ENEMY);
		e->dopatrol(2920, 2990);
		//*/

		settmplevels();
		tmplevels[1] = false;
		tmplevels[0] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		addobject("building.pcx", "buildingt.tga", 2157, 320, true, tmplevels, 2, 1);
		if(!madness) {
			addobject("building.pcx", "buildingt.tga", 2640, 020, true, tmplevels, 2, 1.015);
		}
		else {
			addobject("building.pcx", "buildingt.tga", 2740, 020, true, tmplevels, 2, 1.015);
		}
		if(madness) {
			aagun *a;
			//addplane(10, 502);
			addtank(10, 302, false);
			a = addaagun(1680, 412);
			e = addcompsoldier(1680, 473, ENEMY);
			e->doaagunner(a);
			a = addaagun(1960, 442);
			e = addcompsoldier(1960, 423, ENEMY);
			e->doaagunner(a);
			a = addaagun(2725, 183);
			e = addcompsoldier(2700, 170, ENEMY);
			e->doaagunner(a);
		}
		else {
			//addtank(150, 412, false);
			addtank(300, 412, false);

			addheli(100.1, 512, FRIEND);

			//addjeep(300, 402);
			//addplane(125, 512, ENEMY);
			//addplane(125, 512);
			//settmplevels();
			//addobject("tankcomp.pcx", NULL, 450, 390, 0, tmplevels, 2, 1);
		}
		settmplevels();
		tmplevels[1] = false;
		tmplevels[4] = false;
		tmplevels[3] = false;
		tmplevels[7] = false;
		tmplevels[10] = true;
		tmplevels[11] = false;
		tmplevels[13] = false;
		if(!madness) {
			center = addatom(300, 440, tmplevels, 1);
		}
		else {
			center = addatom(10, 440, tmplevels, 1);
		}
		center->rmdt = 0.23;
		human = addsoldier();
		human->init(center, FRIEND);
	}
	else if(level == 2) {
		settmplevels();
		tmplevels[1] = false;
		tmplevels[0] = false;
		tmplevels[6] = false;
		tmplevels[7] = false;
		addobject("building.pcx", "buildingt.tga", 2000, 254, true, tmplevels, 2, 1);
		//addobject("building.pcx", "buildingt.tga", 2300, 254, true, tmplevels, 2, 1);
		//addobject("building2.pcx", "building2t.tga", 2000, 219, true, tmplevels, 2, 1);
		//addobject("building3.pcx", "building3t.tga", 2000, 262, true, tmplevels, 2, 1);
		//addobject("building4.pcx", "building4t.tga", 2000, 253, true, tmplevels, 2, 1);
		//addobject("building4.pcx", NULL, 2300, 253, true, tmplevels, 2, 1);

		e = addcompsoldier(1900, 500, ENEMY);
		e->dopatrol(1900, 2000);
		e = addcompsoldier(1900, 500, ENEMY);
		e->dopatrol(2300, 2500);
		
		a = addaagun(1876, 419);
		e = addcompsoldier(1900, 500, ENEMY);
		e->doaagunner(a);

		/*
		e = addcompsoldier(300, 573, ENEMY);
		p = addplane(300, 573, ENEMY);
		e->doplanepilot(p);
		e = addcompsoldier(200, 573, ENEMY);
		p = addplane(300, 573, ENEMY);
		e->doplanepilot(p);
		e = addcompsoldier(100, 573, ENEMY);
		p = addplane(300, 573, ENEMY);
		e->doplanepilot(p);

		e = addcompsoldier(350, 573, ENEMY);
		p = addplane(350, 573, ENEMY);
		e->doplanepilot(p);
		e = addcompsoldier(300, 573, ENEMY);
		p = addplane(350, 573, ENEMY);
		e->doplanepilot(p);
		e = addcompsoldier(250, 573, ENEMY);
		p = addplane(300, 573, ENEMY);
		e->doplanepilot(p);
		*/

		//addplane(300, 573);
		//addheli(300.1, 512, FRIEND);
		addplane(300, 563, FRIEND);


		//addtank(300, 450);
		settmplevels();
		tmplevels[1] = false;
		tmplevels[4] = false;
		tmplevels[3] = false;
		tmplevels[7] = false;
		tmplevels[10] = true;
		tmplevels[11] = false;
		tmplevels[13] = false;
		//center = addatom(1876, 485, tmplevels, 1);
		center = addatom(400, 485, tmplevels, 1);
		center->rmdt = 0.23;
		human = addsoldier();
		human->init(center, FRIEND);
	}
}

int main() {
	int compframe = 0;//, frame = 0;
	bool boxadded = false;

	level = 1;

	init_graphics();
	initvars();
	physics_initvars();
	physics_initialize();
	initlevel();

	frame = 0;
	drawframe = 0;
	dispframe = false;

	//time_t timestart, timenow;
	//timestart = time(&timenow);

	recording = false;

	if(!recording && 0) {
		movie_loadmovie(script, "quickscript.mvi");
		compsoldiers[0].doscript(script, 0, 0);
	}

	while(!key[KEY_Q] && !key[KEY_ESC]) {
		compframe++;

		if(compframe == COMPFRAMES) {
			draw();
			compframe = 0;
			//frame++;
			drawframe++;
			dispframe = true;
			if(numsplashes > 0 && drawframe % 10 == 0) numsplashes--;
		}
		update();

		dispframe = false;

		/*
		if(time(&timenow) - timestart >= 1) {
			textprintf(buf, font, 10, 50, white, "Framerate: %i", frame);
			frame = 0;
			timestart = time(&timenow);
		}
		*/

		if(recording) {
			//fprintf(debug, "RECORDING!!!");
			tmpkeys = 0;
			if(key[KEY_W]) tmpkeys = (tmpkeys | M_W);
			if(key[KEY_A]) tmpkeys = (tmpkeys | M_A);
			if(key[KEY_S]) tmpkeys = (tmpkeys | M_S);
			if(key[KEY_D]) tmpkeys = (tmpkeys | M_D);
			if(key[KEY_SPACE]) tmpkeys = (tmpkeys | M_SPACE);
			if(mouse_b & 1) tmpkeys = (tmpkeys | M_MOUSE1);
			if(mouse_b & 2) tmpkeys = (tmpkeys | M_MOUSE2);
			movie_recordactorframe(script, 0, frame, tmpkeys, mx, my);
		}

		dokeys();

		frame++;
	}
	return 1;
}

END_OF_MAIN();