//-----------------------------------------------------------------------------
//
//  $Logfile:: /game/weapon.h                                                 $
// $Revision:: 2                                                              $
//   $Author:: Burgermac                                                      $
//     $Date:: 12/27/00 6:40 PM                                               $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// DESCRIPTION:
// Header file for Weapon class.  The weapon class is the base class for
// all weapons in Sin.  Any entity created from a class derived from the weapon
// class will be usable by any Sentient (players and monsters) as a weapon.
//

#ifndef __WEAPON_H__
#define __WEAPON_H__

#include "g_local.h"
#include "item.h"
#include "sentient.h"
#include "ammo.h"
#include "queue.h"

extern Event EV_Weapon_Shoot;
extern Event EV_Weapon_FinishAttack;
extern Event EV_Weapon_DoneLowering;
extern Event EV_Weapon_DoneRaising;
extern Event EV_Weapon_DoneFiring;
extern Event EV_Weapon_Idle;
extern Event EV_Weapon_MuzzleFlash;
extern Event EV_Weapon_SecondaryUse;
extern Event EV_Weapon_DoneReloading;
extern Event EV_Weapon_SetMaxRange;
extern Event EV_Weapon_SetMinRange;
extern Event EV_Weapon_SetProjectileSpeed;
extern Event EV_Weapon_ActionIncrement;
extern Event EV_Weapon_PutAwayAndRaise;
extern Event EV_Weapon_NotDroppable;

typedef enum
{
	WEAPON_READY,
	WEAPON_FIRING,
	WEAPON_LOWERING,
	WEAPON_RAISING,
	WEAPON_HOLSTERED,
	WEAPON_RELOADING,
	WEAPON_CHANGING
} weaponstate_t;

typedef enum
{
	WEAPON_MELEE,               // For hands only weapons
	WEAPON_1HANDED,             // For short, lightweight weapons fired high (Magnum, pistols, etc.)
	WEAPON_2HANDED_HI,          // For long, aimed weapons fired high (sniper rifle, shotgun, etc.)
	WEAPON_2HANDED_LO               // For long, heavy weapons fired low (rocket launcher)
} weapontype_t;

typedef enum
{
	PRIMARY,
	SECONDARY
} weaponmode_t;

class Weapon : public Item
{
private:
	qboolean attached;
	float nextweaponsoundtime;

protected:
	float maxrange;                                     // maximum effective firing distance (for AI)
	float minrange;                                     // minimum safe firing distance (for AI)
	float projectilespeed;                              // speed of the projectile (0 == infinite speed)

	float attack_finished;
	float flashtime;
	float flashdecay;
	weaponstate_t weaponstate;
	weaponmode_t weaponmode;
	qboolean dualmode;
	str primary_ammo_type;
	str secondary_ammo_type;
	str viewmodel;
	str worldmodel;
	str ammotype;
	int ammorequired;
	int secondary_ammorequired;
	int startammo;
	int rank;
	int order;
	int ammo_clip_size;
	int ammo_in_clip;
	float last_attack_time;
	weapontype_t weapontype;
	SentientPtr last_owner;
	float last_owner_trigger_time;
	int kick;
	int action_level_increment;
	qboolean silenced;
	qboolean notdroppable;
	int aimanim;
	int aimframe;

	// CTF
	qboolean alternate_fire;

	void                        SetMaxRangeEvent( Event* ev );
	void                        SetMinRangeEvent( Event* ev );
	void                        SetProjectileSpeedEvent( Event* ev );
	void                 SetSecondaryAmmo( const char* type, int amount, int startamount );

	virtual void            DetachGun( void );
	virtual void            AttachGun( void );

	virtual void            PickupWeapon( Event* ev );
	virtual void            DoneLowering( Event* ev );
	virtual void            DoneRaising( Event* ev );
	virtual void            DoneFiring( Event* ev );
	virtual void            Idle( Event* ev );
	virtual qboolean        CheckReload( void );
	virtual void            DoneReloading( Event* ev );
	virtual void            FinishAttack( Event* ev );
	virtual void            EventMuzzleFlash( Event* ev );
	virtual void            MuzzleFlash( float r, float g, float b, float radius, float decay, float life );
	virtual void            BulletHole( trace_t* trace );
	virtual void         SetAimAnim( Event* ev );

public:

	CLASS_PROTOTYPE( Weapon );

	Weapon();
	virtual ~Weapon();

	virtual void         CreateSpawnArgs( void );

	virtual int             Rank( void );
	virtual int             Order( void );
	virtual void            SetRank( int order, int rank );

	virtual void            SetType( weapontype_t type );
	virtual weapontype_t GetType( void );

	float                       GetMaxRange( void );
	float                       GetMinRange( void );
	float                       GetProjectileSpeed( void );

	void                        SetMaxRange( float val );
	void                        SetMinRange( float val );
	void                        SetProjectileSpeed( float val );

	virtual void         ForceIdle( void );
	virtual void         NextAttack( double rate );

	virtual void            SetAmmo( const char* type, int amount, int startamount );
	virtual void            SetAmmoAmount( int amount );
	virtual void         UseAmmo( int amount );
	virtual void            SetAmmoClipSize( Event* ev );
	virtual void            SetModels( const char* world, const char* view );

	virtual void            SetOwner( Sentient* ent );

	virtual int             AmmoAvailable( void );
	virtual qboolean     UnlimitedAmmo( void );
	virtual qboolean        HasAmmo( void );
	virtual qboolean     HasAmmoInClip( void );
	virtual qboolean        AttackDone( void );
	virtual qboolean        ReadyToFire( void );
	virtual qboolean        ReadyToChange( void );
	virtual qboolean     ReadyToUse( void );
	virtual qboolean        ChangingWeapons( void );
	virtual qboolean        Reloading( void );
	virtual qboolean     WeaponRaising( void );
	virtual qboolean     WeaponPuttingAway( void );

	virtual void            PutAway( void );
	virtual void            ReadyWeapon( void );
	virtual qboolean        Drop( void );
	virtual void            Fire( void );
	virtual void            ReleaseFire( float holdfiretime );

	virtual qboolean       Removable( void );
	virtual qboolean     Pickupable( Entity* other );
	virtual void         DetachFromOwner( void );
	virtual void         AttachToOwner( void );

	virtual void            WeaponSound( Event* ev );

	virtual Vector          MuzzleOffset( void );
	virtual void            GetMuzzlePosition( Vector* position, Vector* forward = NULL, Vector* right = NULL, Vector* up = NULL );

	virtual qboolean     AutoChange( void );
	virtual int          ClipAmmo( void );
	virtual qboolean     ForceReload( void );

	virtual void         ProcessWeaponCommandsEvent( Event* ev );
	virtual void         SetKick( Event* ev );
	virtual void         SecondaryUse( Event* ev );
	virtual void         PrimaryMode( Event* ev );
	virtual void         SecondaryMode( Event* ev );

	virtual qboolean     IsDroppable( void );
	virtual int          ActionLevelIncrement( void );
	virtual void         SetActionLevelIncrement( Event* ev );
	virtual void         PutAwayAndRaise( Event* ev );
	virtual void         Raise( Event* ev );
	virtual qboolean     IsSilenced( void );
	virtual void         ForceState( weaponstate_t state );
	virtual void         NotDroppableEvent( Event* ev );

	virtual void         Archive( Archiver& arc );
	virtual void         Unarchive( Archiver& arc );

	// CTF
	void                 SetPrimaryMode( void );
	void                 SetSecondaryMode( void );
	virtual void         TakeAllAmmo( void );
	qboolean             AlternateFire( void )
	{
		return alternate_fire;
	}
};

typedef SafePtr<Weapon> WeaponPtr;

void ResetBulletHoles( void );

#endif /* weapon.h */
