/*  TA3D, a remake of Total Annihilation
    Copyright (C) 2005  Roland BROCHARD

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA*/

/*-----------------------------------------------------------------------------------\
|                                      weapons.cpp                                   |
|   Ce module contient les structures, classes et fonctions nécessaires à la lecture |
| des fichiers tdf du jeu totalannihilation concernant les armes utilisées par les   |
| unités du jeu.                                                                     |
|                                                                                    |
\-----------------------------------------------------------------------------------*/

#include <allegro.h>
#include <alleggl.h>
#include <GL/glu.h>
#include "ta3dbase.h"
#include "EngineClass.h"
#include "3do.h"
#include "weapons.h"
#include "tdf.h"

WEAPON_MANAGER		weapon_manager;
INGAME_WEAPONS		weapons;
FX_MANAGER			fx_manager;

void WEAPON_MANAGER::load_tdf(char *data,int size)
{
	char *pos=data;
	char *ligne=NULL;
	int nb=0;
	int index=0;
	int	first=nb_weapons;
	char *limit=data+size;
	char *f;
	int n_pos=0;
	do {
		do
		{
			nb++;
			if(ligne)
				delete ligne;
			ligne=get_line(pos);
			strlwr(ligne);
			while(pos[0]!=0 && pos[0]!=13 && pos[0]!=10)	{	pos++;	n_pos++;	}
			while(pos[0]==13 || pos[0]==10)	{	pos++;	n_pos++;	}

			if(strstr(ligne,"//") || strstr(ligne,"/*") || strstr(ligne,"{")) { }		// Saute les commentaires
			else if(ligne[0]=='[') {
				if(strstr(ligne,"]"))
					*(strstr(ligne,"]"))=0;
				index=add_weapon(ligne+1);
				}
			else if(f=strstr(ligne,"[damage]")) {		// Si on a trouvé un paragraphe référant aux dégats
				do {				// Parcour le paragraphe
					nb++;
					if(ligne)
						delete ligne;
					ligne=get_line(pos);
					strlwr(ligne);
					while(pos[0]!=0 && pos[0]!=13 && pos[0]!=10)	pos++;
					while(pos[0]==13 || pos[0]==10)	pos++;

					if(f=strstr(ligne,"default=")) {
						if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
						weapon[index].damage=atoi(f+8);
						}
				} while(strstr(ligne,"}")==NULL && nb<1000 && pos<limit);
				}
			else if(f=strstr(ligne,"name=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].name=strdup(f+5);
				}
			else if(f=strstr(ligne,"id=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].weapon_id=atoi(f+3);
				}
			else if(f=strstr(ligne,"rendertype=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].rendertype=atoi(f+11);
				}
			else if(f=strstr(ligne,"ballistic=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].ballistic=(f[10]=='1');
				}
			else if(f=strstr(ligne,"turret=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].turret=(f[7]=='1');
				}
			else if(f=strstr(ligne,"range=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].range=atoi(f+6);
				}
			else if(f=strstr(ligne,"reloadtime=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].reloadtime=atof(f+11);
				if(weapon[index].duration==-1.0f)
					weapon[index].duration=weapon[index].reloadtime;
				}
			else if(f=strstr(ligne,"weaponvelocity=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].weaponvelocity=atoi(f+15);
				}
			else if(f=strstr(ligne,"areaofeffect=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].areaofeffect=atoi(f+13);
				}
			else if(f=strstr(ligne,"startsmoke=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].startsmoke=(f[11]=='1');
				}
			else if(f=strstr(ligne,"endsmoke=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].endsmoke=(f[9]=='1');
				}
			else if(f=strstr(ligne,"firestarter=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].firestarter=(f[12]=='1');
				}
			else if(f=strstr(ligne,"accuracy=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].accuracy=atoi(f+9);
				}
			else if(f=strstr(ligne,"aimrate=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].aimrate=atoi(f+8);
				}
			else if(f=strstr(ligne,"tolerance=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].tolerance=atoi(f+9);
				}
			else if(f=strstr(ligne,"holdtime=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].holdtime=atoi(f+8);
				}
			else if(f=strstr(ligne,"energypershot=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].energypershot=atoi(f+14);
				}
			else if(f=strstr(ligne,"metalpershot=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].metalpershot=atoi(f+13);
				}
			else if(f=strstr(ligne,"minbarrelangle=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].minbarrelangle=atoi(f+15);
				}
			else if(f=strstr(ligne,"unitsonly=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].unitsonly=(f[10]=='1');
				}
			else if(f=strstr(ligne,"edgeeffectiveness=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].edgeeffectiveness=atof(f+18);
				}
			else if(f=strstr(ligne,"lineofsight=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].lineofsight=(f[12]=='1');
				}
			else if(f=strstr(ligne,"soundtrigger=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].soundtrigger=strdup(f+13);
				}
			else if(f=strstr(ligne,"color=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				int c=atoi(f+6);
				weapon[index].color[0]=makecol(pal[c].r<<2,pal[c].g<<2,pal[c].b<<2);
				}
			else if(f=strstr(ligne,"color2=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				int c=atoi(f+7);
				weapon[index].color[1]=makecol(pal[c].r<<2,pal[c].g<<2,pal[c].b<<2);
				}
			else if(f=strstr(ligne,"burstrate=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].edgeeffectiveness=atof(f+10);
				}
			else if(f=strstr(ligne,"duration=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].duration=atof(f+9);
				}
			else if(f=strstr(ligne,"beamweapon=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].beamweapon=(f[11]=='1');
				}
			else if(f=strstr(ligne,"startvelocity=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].startvelocity=atoi(f+14);
				}
			else if(f=strstr(ligne,"weapontimer=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].weapontimer=atof(f+12);
				}
			else if(f=strstr(ligne,"weaponacceleration=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].weaponacceleration=atoi(f+19);
				}
			else if(f=strstr(ligne,"turnrate=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].turnrate=atoi(f+9);
				}
			else if(f=strstr(ligne,"model=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].model=model_manager.get_model(f+6);
				}
			else if(f=strstr(ligne,"smokedelay=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].smokedelay=atof(f+11);
				}
			else if(f=strstr(ligne,"guidance=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].guidance=(f[9]=='1');
				}
			else if(f=strstr(ligne,"tracks=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].tracks=(f[7]=='1');
				}
			else if(f=strstr(ligne,"selfprop=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].selfprop=(f[9]=='1');
				}
			else if(f=strstr(ligne,"waterweapon=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].waterweapon=(f[12]=='1');
				}
			else if(f=strstr(ligne,"smoketrail=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].smoketrail=(f[11]=='1');
				}
			else if(f=strstr(ligne,"noautorange=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].noautorange=(f[12]=='1');
				}
			else if(f=strstr(ligne,"flighttime=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].flighttime=atoi(f+11);
				}
			else if(f=strstr(ligne,"vlaunch=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].vlaunch=(f[8]=='1');
				}
			else if(f=strstr(ligne,"stockpile=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].stockpile=(f[10]=='1');
				}
			else if(f=strstr(ligne,"targetable=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].targetable=(f[11]=='1');
				}
			else if(f=strstr(ligne,"commandfire=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].commandfire=(f[12]=='1');
				}
			else if(f=strstr(ligne,"cruise=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].cruise=(f[7]=='1');
				}
			else if(f=strstr(ligne,"propeller=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].propeller=(f[10]=='1');
				}
			else if(f=strstr(ligne,"twophase=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].twophase=(f[9]=='1');
				}
			else if(f=strstr(ligne,"dropped=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].dropped=(f[8]=='1');
				}
			else if(f=strstr(ligne,"shakemagnitude=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].shakemagnitude=atoi(f+15);
				}
			else if(f=strstr(ligne,"shakeduration=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].shakeduration=atof(f+14);
				}
			else if(f=strstr(ligne,"waterexplosiongaf=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].waterexplosiongaf=strdup(f+18);
				}
			else if(f=strstr(ligne,"waterexplosionart=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].waterexplosionart=strdup(f+18);
				}
			else if(f=strstr(ligne,"lavaexplosiongaf=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].lavaexplosiongaf=strdup(f+17);
				}
			else if(f=strstr(ligne,"lavaexplosionart=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].lavaexplosionart=strdup(f+17);
				}
			else if(f=strstr(ligne,"explosiongaf=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].explosiongaf=strdup(f+13);
				}
			else if(f=strstr(ligne,"explosionart=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].explosionart=strdup(f+13);
				}
			else if(f=strstr(ligne,"soundhit=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].soundhit=strdup(f+9);
				}
			else if(f=strstr(ligne,"soundstart=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].soundstart=strdup(f+11);
				}
			else if(f=strstr(ligne,"soundwater=")) {
				if((strstr(ligne,";")))	*(strstr(ligne,";"))=0;
				weapon[index].soundwater=strdup(f+11);
				}
			else {
				if(strlen(ligne)>1 && strstr(ligne,"{")==NULL && strstr(ligne,"}")==NULL)
					printf("(arme) inconnu: %s\n",ligne);
				}

		} while(strstr(ligne,"}")==NULL && nb<1000 && pos<limit);
		delete ligne;
		ligne=NULL;
	} while(nb<1000 && pos<limit);
}

void load_all_weapons_in_hpi(char *filename)
{
	HPI_FILE hpi;
	hpi.load(filename);
	char *file;
	int n[10];
	int d_index=0;
	char *dir[10];
	int size;
	dir[0]=strdup("/Weapons");
	n[0]=0;
	while(d_index>-1) {
		while(file=hpi.find(dir[d_index],n[d_index]++)) {
			if(hpi.is_dir(file)) {
				dir[++d_index]=strdup(file);
				n[d_index]=0;
				}
			if(strstr(strlwr(file),".tdf")!=NULL) {			// Si le fichier est au bon format
				char *data=(char*)hpi.extract_memory_file(file,&size);
				if(data) {
					weapon_manager.load_tdf(data,size);
					free(data);
					}
				}
			delete file;
			}
		free(dir[d_index--]);
		}

	hpi.destroy();
}

void WEAPON::move(float dt,MAP *map)				// Anime les armes
{
	smoke_time+=dt;
	f_time-=dt;
	a_time+=dt;
	if(!dying && weapon_manager.weapon[weapon_id].twophase && a_time>=weapon_manager.weapon[weapon_id].weapontimer && phase==1)		// Entre dans la seconde phase
		phase=2;
	if(weapon_manager.weapon[weapon_id].twophase && phase==1 && weapon_manager.weapon[weapon_id].vlaunch) {
		V.x=0.0f;
		V.z=0.0f;
		V.y=weapon_manager.weapon[weapon_id].startvelocity;
		}
	if(!dying && weapon_manager.weapon[weapon_id].selfprop && f_time<=0.0f)	dying=true;
	if(weapon_manager.weapon[weapon_id].smoketrail && weapon_manager.weapon[weapon_id].smokedelay<smoke_time) {		// Trainée de fumée des missiles
		POINTF O;
		O.x=O.y=O.z=0.0f;
		smoke_time=0.0f;
		particle_engine.make_smoke(O+Pos,0,1,0.0f,-1.0f);
		}

	VECTOR hit_vec;
	if(!dying)
		hit_vec=map->hit(Pos,V,!weapon_manager.weapon[weapon_id].waterweapon);
	VECTOR OPos=Pos;

	if(!dying && weapon_manager.weapon[weapon_id].waterweapon && Pos.y>map->sealvl)		// Une arme aquatique ne sort pas de l'eau
		hit_vec=Pos;

	if(dying)
		killtime-=dt;
	else {
		VECTOR A;
		A.x=A.y=A.z=0.0f;
		if(weapon_manager.weapon[weapon_id].lineofsight) {}
		else if(weapon_manager.weapon[weapon_id].ballistic || weapon_manager.weapon[weapon_id].dropped)		// Arme soumise à la gravité
			A.y-=9.8;
		Pos=Pos+dt*(V+dt*(0.33333333f*A+0.16666666667f*Ac));
		V=V+dt*0.5f*(A+Ac);
		Ac=A;
//		V=V+dt*A;
//		Pos=Pos+dt*V;
		stime+=dt;
		}

	bool hit=false;
	if(!dying)
		hit=((hit_vec-Pos)%V)<=0.0f;
	bool u_hit=false;

	int hit_idx=-1;
	if(!dying) {
		int idx=-1;
		int py=((int)(OPos.z+map->map_h*0.5f))>>3;
		int px=((int)(OPos.x+map->map_w*0.5f))>>3;
		int oidx=-1;
		for(int y=-5;y<=5;y++)
			for(int x=-5;x<=5;x++) {
				if(px+x<0 || px+x>=(map->bloc_w<<1))	continue;
				if(py+y<0 || py+y>=(map->bloc_h<<1))	continue;
				idx=map->map_data[py+y][px+x].unit_idx;
				if(idx>=0 && idx!=shooter_idx && idx!=hit_idx && idx!=oidx) {
					VECTOR Dir=V;
					Dir.Unit();
					VECTOR t_vec;
					t_vec.x=t_vec.y=t_vec.z=0.0f;
					u_hit=units.unit[idx].hit(OPos,Dir,&t_vec);
					if(u_hit) {
						if((t_vec-Pos)%V<=0.0f) {			// Touché
							if(!hit) {
								hit_vec=t_vec;
								hit_idx=idx;
								}
							else if((hit_vec-OPos)%Dir>=(t_vec-OPos)%Dir) {
								hit_vec=t_vec;
								hit_idx=idx;
								}
							else
								u_hit=false;
							}
						else
							u_hit=false;
						}
					hit|=u_hit;
					}
				if(idx!=-1)
					oidx=idx;
				}
			if(hit_idx>=0) {
				units.unit[hit_idx].hp-=weapon_manager.weapon[weapon_id].damage;		// L'unité touchée encaisse les dégats
				units.unit[hit_idx].launch_script(units.unit[hit_idx].get_script_index("hitbyweapon"));
				}
		}

	if(hit && weapon_manager.weapon[weapon_id].areaofeffect>0) {			// Domages colatéraux
		int idx=-1;
		int py=((int)(OPos.z+map->map_h*0.5f))>>3;
		int px=((int)(OPos.x+map->map_w*0.5f))>>3;
		int s=weapon_manager.weapon[weapon_id].areaofeffect/16;
		int d=weapon_manager.weapon[weapon_id].areaofeffect*weapon_manager.weapon[weapon_id].areaofeffect>>2;
		int oidx[s*s+2*s+1];
		int nb=0;
		for(int y=-s;y<=s;y++)
			for(int x=-s;x<=s;x++) {
				if(px+x<0 || px+x>=(map->bloc_w<<1))	continue;
				if(py+y<0 || py+y>=(map->bloc_h<<1))	continue;
				idx=map->map_data[py+y][px+x].unit_idx;
				bool already=(idx==hit_idx || idx==-1);
				if(!already)
					for(int i=0;i<nb;i++)
						if(idx==oidx[i]) {
							already=true;
							break;
							}
				if(!already)
					if((units.unit[idx].Pos-Pos).Sq()<=d) {
						oidx[nb++]=idx;
						units.unit[idx].hp-=weapon_manager.weapon[weapon_id].damage*weapon_manager.weapon[weapon_id].edgeeffectiveness;		// L'unité touchée encaisse les dégats
						units.unit[idx].launch_script(units.unit[idx].get_script_index("hitbyweapon"));
						}
				}
		}

	if((stime>2.0f*weapon_manager.weapon[weapon_id].range/weapon_manager.weapon[weapon_id].weaponvelocity || hit) && !dying) {
		if(hit)
			Pos=hit_vec;
		sound_manager.play(weapon_manager.weapon[weapon_id].soundhit,Pos);
		if(hit && weapon_manager.weapon[weapon_id].explosiongaf!=NULL && weapon_manager.weapon[weapon_id].explosionart!=NULL)
			fx_manager.add(weapon_manager.weapon[weapon_id].explosiongaf,weapon_manager.weapon[weapon_id].explosionart,Pos,1.0f);
		if(weapon_manager.weapon[weapon_id].endsmoke) {
			POINTF O;
			O.x=O.y=O.z=0.0f;
			particle_engine.make_smoke(O+Pos,0,1,0.0f,-1.0f);
			}
		if(weapon_manager.weapon[weapon_id].rendertype==RENDER_TYPE_LASER) {
			dying=true;
			killtime=weapon_manager.weapon[weapon_id].duration;
			}
		else
			weapon_id=-1;
		}
	else if(dying && killtime<=0.0f)
		weapon_id=-1;
}

void WEAPON::draw(CAMERA *cam)				// Dessine les objets produits par les armes
{
	if(cam)
		cam->SetView();
	switch(weapon_manager.weapon[weapon_id].rendertype)
	{
	case RENDER_TYPE_LASER:						// Dessine le laser
		{
		VECTOR P=Pos;
		float length=weapon_manager.weapon[weapon_id].duration;
		if(weapon_manager.weapon[weapon_id].duration>stime)
			length=stime;
		if(dying && length>killtime)
			length=killtime;
		P=P-length*V;
		glDisable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		int color0=weapon_manager.weapon[weapon_id].color[0];
		int color1=weapon_manager.weapon[weapon_id].color[1];
		float coef=(cos(stime)+1.0f)*0.5f;
		float r=(coef*((color0>>16)&0xFF)+coef*((color1>>16)&0xFF))/255.0f;
		float g=(coef*((color0>>8)&0xFF)+coef*((color1>>8)&0xFF))/255.0f;
		float b=(coef*(color0&0xFF)+coef*(color1&0xFF))/255.0f;
		glColor4f(r,g,b,1.0f);
		glBegin(GL_LINES);
			glVertex3f(Pos.x,Pos.y,Pos.z);
			glVertex3f(P.x,P.y,P.z);
		glEnd();
		}
		break;
	case RENDER_TYPE_MISSILE:					// Dessine le missile
		glTranslatef(Pos.x,Pos.y,Pos.z);
		{
			VECTOR I,J,K,Dir,Dir2;
			I.x=I.y=I.z=0.0f;
			J=K=I;
			I.x=1.0f;
			J.z=-1.0f;
			K.y=1.0f;
			Dir=-V;
			Dir.Unit();
			Dir2=Dir;
			Dir2.y=0.0f;
			Dir2.Unit();
			float theta=acos(Dir%Dir2)*RAD2DEG;
			float phi=acos(Dir2%J)*RAD2DEG;
			if(Dir%I<0.0f)	phi=-phi;
			if(Dir2%K<0.0f)	theta=-theta;
			glRotatef(-phi,0.0f,1.0f,0.0f);
			glRotatef(theta,0.0f,0.0f,1.0f);
		}
		glEnable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		if(weapon_manager.weapon[weapon_id].model)
			weapon_manager.weapon[weapon_id].model->draw();
		break;
	case RENDER_TYPE_BITMAP:
		glDisable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		glColor4f(1.0f,1.0f,1.0f,1.0f);
		if(weapon_manager.cannonshell.nb_bmp>0) {
			anim_sprite=(anim_sprite+1)%weapon_manager.cannonshell.nb_bmp;
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D,weapon_manager.cannonshell.glbmp[anim_sprite]);
			VECTOR A,B,C,D;
			A=Pos+((-0.5f*weapon_manager.cannonshell.h[anim_sprite]-weapon_manager.cannonshell.ofs_y[anim_sprite])*cam->Up+(-0.5f*weapon_manager.cannonshell.w[anim_sprite]-weapon_manager.cannonshell.ofs_x[anim_sprite])*cam->Side);
			B=Pos+((-0.5f*weapon_manager.cannonshell.h[anim_sprite]-weapon_manager.cannonshell.ofs_y[anim_sprite])*cam->Up+(0.5f*weapon_manager.cannonshell.w[anim_sprite]-weapon_manager.cannonshell.ofs_x[anim_sprite])*cam->Side);
			C=Pos+((0.5f*weapon_manager.cannonshell.h[anim_sprite]-weapon_manager.cannonshell.ofs_y[anim_sprite])*cam->Up+(-0.5f*weapon_manager.cannonshell.w[anim_sprite]-weapon_manager.cannonshell.ofs_x[anim_sprite])*cam->Side);
			D=Pos+((0.5f*weapon_manager.cannonshell.h[anim_sprite]-weapon_manager.cannonshell.ofs_y[anim_sprite])*cam->Up+(0.5f*weapon_manager.cannonshell.w[anim_sprite]-weapon_manager.cannonshell.ofs_x[anim_sprite])*cam->Side);
			glBegin(GL_QUADS);
				glTexCoord2f(0.0f,0.0f);		glVertex3f(A.x,A.y,A.z);
				glTexCoord2f(1.0f,0.0f);		glVertex3f(B.x,B.y,B.z);
				glTexCoord2f(1.0f,1.0f);		glVertex3f(D.x,D.y,D.z);
				glTexCoord2f(0.0f,1.0f);		glVertex3f(C.x,C.y,C.z);
			glEnd();
			}
		else {
			glBegin(GL_QUADS);
				glVertex3f(Pos.x-2.5f,Pos.y-2.5f,Pos.z);
				glVertex3f(Pos.x+2.5f,Pos.y-2.5f,Pos.z);
				glVertex3f(Pos.x+2.5f,Pos.y+2.5f,Pos.z);
				glVertex3f(Pos.x-2.5f,Pos.y+2.5f,Pos.z);
			glEnd();
			}
		glEnable(GL_LIGHTING);
		break;
	case RENDER_TYPE_BOMB:
		glTranslatef(Pos.x,Pos.y,Pos.z);
		{
			VECTOR I,J,K,Dir,Dir2;
			I.x=I.y=I.z=0.0f;
			J=K=I;
			I.x=1.0f;
			J.z=-1.0f;
			K.y=1.0f;
			Dir=-V;
			Dir.Unit();
			Dir2=Dir;
			Dir2.y=0.0f;
			Dir2.Unit();
			float theta=acos(Dir%Dir2)*RAD2DEG;
			float phi=acos(Dir2%J)*RAD2DEG;
			if(Dir%I<0.0f)	phi=-phi;
			if(Dir2%K<0.0f)	theta=-theta;
			glRotatef(-phi,0.0f,1.0f,0.0f);
			glRotatef(theta,0.0f,0.0f,1.0f);
		}
		glEnable(GL_LIGHTING);
		glEnable(GL_TEXTURE_2D);
		if(weapon_manager.weapon[weapon_id].model)
			weapon_manager.weapon[weapon_id].model->draw();
		break;
	case RENDER_TYPE_LIGHTNING:
		{
		VECTOR P=Pos;
		float length=weapon_manager.weapon[weapon_id].duration;
		if(weapon_manager.weapon[weapon_id].duration>stime)
			length=stime;
		if(dying && length>killtime)
			length=killtime;
		P=P-length*V;
		glDisable(GL_LIGHTING);
		glDisable(GL_TEXTURE_2D);
		int color0=weapon_manager.weapon[weapon_id].color[0];
		int color1=weapon_manager.weapon[weapon_id].color[1];
		float coef=(cos(stime)+1.0f)*0.5f;
		float r=(coef*((color0>>16)&0xFF)+coef*((color1>>16)&0xFF))/255.0f;
		float g=(coef*((color0>>8)&0xFF)+coef*((color1>>8)&0xFF))/255.0f;
		float b=(coef*(color0&0xFF)+coef*(color1&0xFF))/255.0f;
		glColor4f(r,g,b,1.0f);
		glBegin(GL_LINE_STRIP);
			for(int i=0;i<10;i++) {
				float x,y,z;
				if(i>0 && i<9) {
					x=((rand()%2001)-1000)*0.005f;
					y=((rand()%2001)-1000)*0.005f;
					z=((rand()%2001)-1000)*0.005f;
					}
				else
					x=y=z=0.0f;
				glVertex3f(Pos.x+(P.x-Pos.x)*i/9+x,Pos.y+(P.y-Pos.y)*i/9+y,Pos.z+(P.z-Pos.z)*i/9+z);
				}
		glEnd();
		}
		break;
	};
}

void load_weapons()				// Charge toutes les armes
{
	al_ffblk search;

	if(al_findfirst("*.hpi",&search,FA_RDONLY | FA_ARCH)==0)
	do
	{
		load_all_weapons_in_hpi(search.name);
	}while(al_findnext(&search)==0);
	al_findclose(&search);
	if(al_findfirst("*.ufo",&search,FA_RDONLY | FA_ARCH)==0)
	do
	{
		load_all_weapons_in_hpi(search.name);
	}while(al_findnext(&search)==0);
	al_findclose(&search);
	if(al_findfirst("*.ccx",&search,FA_RDONLY | FA_ARCH)==0)
	do
	{
		load_all_weapons_in_hpi(search.name);
	}while(al_findnext(&search)==0);
	al_findclose(&search);

	load_all_weapons_in_hpi("rev31.gp3");

	byte *data=load_file("/anims/fx.gaf");			// Charge les animations des armes
	if(data) {
		weapon_manager.cannonshell.load_gaf(data,get_gaf_entry_index(data,"cannonshell"));
		weapon_manager.cannonshell.convert(false,true);
		weapon_manager.cannonshell.clean();
		free(data);
		}
}
