#ifndef _WEAPONFUNCS_H
#define _WEAPONFUNCS_H

#define DllExport	extern "C"	__declspec( dllexport )

//////////////////////////////
// macros
//////////////////////////////

#define WEAPON_UNLIMITED_AMMO    0

// handedness values
#define RIGHT_HANDED       0
#define LEFT_HANDED        1
#define CENTER_HANDED      2

#define UNICAST_ENT        127

#define winfoModel(num)             winfo->models[(short)(num)]
#define winfoSound(num)             winfo->sounds[(short)(num)]
#define winfoAnim(ent,num,delay)    weapon_animate(ent,winfo->frames[(short)(num)].first,winfo->frames[(short)(num)].last,delay)
#define winfoFirstFrame(num)        (winfo->frames[(short)(num)].first)
#define winfoLastFrame(num)         (winfo->frames[(short)(num)].last)
#define winfoNumFrames(num)         (winfoLastFrame(num) - winfoFirstFrame(num) + 1)
#define winfoPlay(num,vol)          gstate->sound(self,CHAN_AUTO,winfo->sounds[(short)(num)],vol,ATTN_NORM)
#define winfoSetModel(ent,num)      {ent->s.modelindex=gstate->ModelIndex(winfoModel(num));}
#define dk2SetModel(ent,str)        {ent->s.modelindex=gstate->ModelIndex(str);}


//////////////////////////////
// typedefs
//////////////////////////////

typedef enum weaponStd_t {
   // standard model positions (in winfo list)
   MDL_WEAPON_STD=0,

   MDL_SPECIAL,                  // start additional models here

   // standard anim positions (in winfo list)
   ANIM_READY_STD=0,
   ANIM_AWAY_STD,
   ANIM_SHOOT_STD,
   ANIM_AMBIENT_STD,

   ANIM_SPECIAL,                 // start additional anims here
} weaponStd_t;

typedef struct trackInfo_s {
   userEntity_t *ent;                     // entity to be tracked by srcent
   userEntity_t *srcent,*dstent;          // track from src, to dst entity
   vec3_t fru;                            // fwd, rt, up offsets from src (compressed into vec3_t)
   vec3_t dstpos;                         // dst position (used if dstent==NULL)
   long flags;                            // uses RF_xxxx flags -AND- TEF_xxxx flags (so they can't overlap)
   float length;
} trackInfo_t;

typedef struct	weaponListNode_s
{
	weaponListNode_s	*prev;
	weaponListNode_s	*next;

	userEntity_t		*ent;	// the entity that this node refers to
} weaponListNode_t;

typedef	struct	weaponListHeader_s
{
	weaponListNode_t	*head;
	weaponListNode_t	*tail;

	int					count;
} weaponListHeader_t;

typedef	struct	killerInfo_s
{
	userEntity_t	*attacker;
	userEntity_t	*victim;
} killerInfo_t;

typedef userInventory_t *(*weaponGive_t) (userEntity_t *self);

typedef struct weaponCommand_s {
   char *text;                      // name of command
   void (*func)(void);              // function to run
} weaponCmd_t;

typedef struct weaponFrame_s {
   char model;                      // model num this frame is in
   char *name;                      // name of anim
   int first,last;                  // first/last frame of anim
} weaponFrame_t;

typedef struct weaponInfo_s {
   char *weaponName;                // weapon name
   char *weaponNetName;             // weapon net name
   char *ammoName;                  // ammo name
   char *ammoNetName;               // ammo net name
   char *iconName;                  // icon def
   char *models[10];                // model files used by this weapon
   char *sounds[20];                // sound files used by this weapon
   weaponFrame_t frames[20];        // frame info -- weapon "ready" should always be first
   weaponCmd_t command[10];         // commands used by this weapon

   void (*use_func)(userInventory_s *ptr, userEntity_t *self);
   void *(*cmd_func)(struct userInventory_s *inv, char *commandStr, void *data);

   short weapon_t_size;             // size to allocate for weapon_t structure
   short rating;                    // value between 0 and 1000
   int flags;                       // entity flags (just handles EF_LOOPAMBIENT now)
   int	flags2;						// more entity flags
} weaponInfo_t;

//////////////////////////////
// globals
//////////////////////////////

extern int mike;
extern float mikef;

//////////////////////////////
// prototypes
//////////////////////////////

float		crnd				(void);
float		lim_rand			(int limit);
void		weapon_animate		(userEntity_t *self, int start, int end, float frametime);
int			weapon_trace_attack ( userEntity_t *self, int damage, int num_bullets, int distance);
void		weapon_touch		(userEntity_t *self, userEntity_t *other);
ammo_t		*weapon_check_ammo	(userEntity_t *self, char *ammo_name, int ammo_count);

void		spawn_sprite_explosion (userEntity_t *self, vec3_t org, int play_sound);
void		spawn_ring_explosion (userEntity_t *self, vec3_t org, int play_sound);
void		spawn_smoke_trail (userEntity_t *self, vec3_t org, int play_sound);

////////////////////////////////////////////////////////////////////////////////////
//	weapon_list functions
////////////////////////////////////////////////////////////////////////////////////

weaponListHeader_t	*weapon_list_init		(weaponListHeader_t *list);
void				weapon_list_add			(userEntity_t *self, weaponListHeader_t *list);
void				weapon_list_delete_node	(weaponListHeader_t *list, weaponListNode_t *node);
void				weapon_list_remove		(userEntity_t *self, weaponListHeader_t *list);
userEntity_t		*weapon_list_ent		(weaponListNode_t *node);
weaponListNode_t	*weapon_list_node_next	(weaponListNode_t *node);
weaponListNode_t	*weapon_list_node_prev	(weaponListNode_t *node);

////////////////////////////////////////////////////////////////////////////////////
//	projectile functions
////////////////////////////////////////////////////////////////////////////////////

void			weapon_face_velocity		(userEntity_t *self);
userEntity_t	*weapon_spawn_projectile	(userEntity_t *self, Vector &org, float xy_vel, float z_vel, char *className);


//---------------------------------------------------------------------------
// general functions
//---------------------------------------------------------------------------
int weaponDllInit(weaponInfo_t *winfo);
void weaponLevelInit(weaponInfo_t *winfo);
weapon_t *weaponCreateInv(weaponInfo_t *winfo, void (*use_func)(), void *(*cmd_func)(), short struct_size);
ammo_t *ammoCreate(weaponInfo_t *winfo);
ammo_t *ammoAdd(userEntity_t *self,int amount,weaponInfo_t *winfo);
void *weaponGenericCommand(userInventory_t *inv,char *commandStr,void *data);
void *winfoGenericCommand(weaponInfo_t *winfo,userInventory_t *inv,char *commandStr,void *data);
void *ammoGenericCommand(userInventory_t *ptr,char *commandStr,void *data);
Vector weaponHandVector(userEntity_t *ent,Vector &fpos,Vector &hpos);
userEntity_t *selectWeapon(userEntity_t *owner,char *weaponName,char *modelName);
void new_weapon_animate (userEntity_t *self, int start, int end, float frametime);
void winfoAnimDelay(userEntity_t *self,weaponInfo_t *winfo,short animNum,float delay);
void trackEntity(trackInfo_t *tinfo,short broadcasttype);
void untrackEntity(userEntity_t *ent,userEntity_t *to,short broadcasttype);
short weaponUseAmmo(userInventory_t *weapon,int count);
userInventory_t *weaponGive(userEntity_t *self,weaponInfo_t *winfo,short ammoCount);
void weaponSelect(userEntity_t *self,weaponInfo_t *winfo);
void weaponSelectFinish(userEntity_t *self);
qboolean entityHuman(userEntity_t *self);
void winfoClientExplosion(weaponInfo_t *winfo,Vector pos,Vector angle,float scale,short model,short anim);
void trackLight(userEntity_t *ent,float size,float r,float g,float b);
void untrackLight(userEntity_t *ent);

int ai_infront(userEntity_t *self, userEntity_t *target);
int ai_visible(userEntity_t *self, userEntity_t *targ);

#endif