#ifndef __HOVERBIKE_H__
#define __HOVERBIKE_H__

#include "g_local.h"
#include "entity.h"
#include "item.h"
#include "weapon.h"
#include "misc.h"
#include "sentient.h"

// weapon defines
#define NUM_HOVERWEAPONS    3
#define HWMODE_ROCKETS      0
#define HWMODE_CHAINGUN     1
#define HWMODE_MINES        2

// guage defines
#define HBGUAGE_SPEEDBAR    1
#define HBGUAGE_SPEEDNUM    2
#define HBGUAGE_TURBOBAR    3
#define HBGUAGE_HEALTHBAR   4
#define HBGUAGE_AMMONUM     5
#define HBGUAGE_WEAPONICON  6

// the extra bounding boxes for a hoverbike
class EXPORT_FROM_DLL HoverbikeBox : public Entity
{
public:
	float offset; // forward offset from the main hoverbike entity
	EntityPtr bike; // pointer to owner hoverbike

	CLASS_PROTOTYPE( HoverbikeBox );

	HoverbikeBox();
	virtual void BikeUse( Event *ev );
	virtual void BikeDamage( Event *ev );

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

inline EXPORT_FROM_DLL void HoverbikeBox::Archive( Archiver &arc )
{
	Entity::Archive( arc );

	arc.WriteFloat( offset );
	arc.WriteSafePointer( bike );
}

inline EXPORT_FROM_DLL void HoverbikeBox::Unarchive( Archiver &arc )
{
	Entity::Unarchive( arc );

	arc.ReadFloat( &offset );
	arc.ReadSafePointer( &bike );
}

template class EXPORT_FROM_DLL SafePtr<HoverbikeBox>;
typedef SafePtr<HoverbikeBox> HoverbikeBoxPtr;

// control guages
class EXPORT_FROM_DLL HoverbikeGuage : public Entity
{
private:
	int guagetype; // the kind of guage that it is

public:
	CLASS_PROTOTYPE( HoverbikeGuage );

	virtual void Setup( Entity *owner, int type );
	virtual void SetValue( int value );

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

inline EXPORT_FROM_DLL void HoverbikeGuage::Archive( Archiver &arc )
{
	Entity::Archive( arc );

	arc.WriteInteger( guagetype );
}

inline EXPORT_FROM_DLL void HoverbikeGuage::Unarchive( Archiver &arc )
{
	Entity::Unarchive( arc );

	arc.ReadInteger( &guagetype );
}

template class EXPORT_FROM_DLL SafePtr<HoverbikeGuage>;
typedef SafePtr<HoverbikeGuage> HoverbikeGuagePtr;

class Player;

class EXPORT_FROM_DLL Hoverbike : public Entity
{
public:
	HoverbikeBoxPtr frontbox; // pointer to front bounding box
	HoverbikeBoxPtr backbox; // pointer to back bounding box

	SentientPtr rider; // pointer to riding player
	qboolean player; // true when the rider is a player

	HoverbikeGuagePtr speed_bar;
	HoverbikeGuagePtr speed_number;
	HoverbikeGuagePtr turbo_bar;
	HoverbikeGuagePtr health_bar;
	HoverbikeGuagePtr ammo_number;
	HoverbikeGuagePtr weapon_icon;

	Vector spawnspot; // place where it was spawned
	Vector spawnangles; // angles at which it was spawned
	float respawntimer; // timmer for respawning
	float damagetimer;
	float getontimer; // use debounce timer for when getting on

	float bobsin; // for rider view bobbing
	float bobfrac; // for rider view bobbing

	WeaponPtr oldweapon;
	int rockets;
	int bullets;
	int mines;

	float forwardmove;
	float sidemove;
	float upmove;

	Vector move_angles;
	float airpitch_timmer;
	float speed;
	int forward_speed;
	float strafingroll;
	float boosttimmer;
	float turbo;

	int weaponmode; // bike's current weapon mode

	int sndflags; // hovering sound flags
	str currsound; // alias of current hovering sound

	qboolean controlled; // true if controlled by script
	qboolean scriptturboing;
	float scripttargetyaw;
	float scriptturnspeed;

	float effectstimmer;
	float soundtimmer;

	CLASS_PROTOTYPE( Hoverbike );

	Hoverbike();

	virtual void RespawnSetup( Vector spot, Vector ang, float respawndelay, int grav );
	virtual void BikeRespawn( Event *ev );

	virtual void SetRiderAngles( Vector angles );
	virtual void SetRiderYaw( float yawangle );
	virtual void BikeUse( Event *ev );
	virtual void BikeGetOff( void );
	virtual void BikePain( Event *ev );
	virtual void BikeKilled( Event *ev );
	virtual void GiveExtraFrag( Entity *attacker );

	virtual qboolean Ride( usercmd_t *ucmd );
	virtual void RiderMove( usercmd_t *ucmd );
	virtual void Postthink( void );
	virtual void Hover( void );
	virtual void ApplyControls( void );
	virtual void ApplyMoveAngles( void );
	void SetGravityAxis( int axis );

	virtual void WeaponChangeSound( void );
	virtual void WeaponNoAmmoSound( void );
	virtual void SetHoverSound( void );
	virtual void CollisionSound( Vector before, Vector after );

	virtual void NextWeapon( void );
	virtual void PreviousWeapon( void );
	virtual void SelectWeapon( int weapon );

	virtual void MakeGuages( void );
	virtual void KillGuages( void );
	virtual void UpdateGuages( void );
	virtual void GuagesViewerOn( void );
	virtual void GuagesViewerOff( void );

	// script responces
	virtual void ControlledEvent( Event *ev );
	virtual void UncontrolledEvent( Event *ev );
	virtual void ReleaseRider( Event *ev );
	virtual void ControlsEvent( Event *ev );
	virtual void YawSpeedEvent( Event *ev );
	virtual void TargetYawEvent( Event *ev );

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

inline EXPORT_FROM_DLL void Hoverbike::Archive( Archiver &arc )
{
	Entity::Archive( arc );

	arc.WriteSafePointer( frontbox );
	arc.WriteSafePointer( backbox );

	arc.WriteSafePointer( rider );
	arc.WriteBoolean( player );

	arc.WriteSafePointer( speed_bar );
	arc.WriteSafePointer( speed_number );
	arc.WriteSafePointer( turbo_bar );
	arc.WriteSafePointer( health_bar );
	arc.WriteSafePointer( ammo_number );
	arc.WriteSafePointer( weapon_icon );

	arc.WriteVector( spawnspot );
	arc.WriteVector( spawnangles );
	arc.WriteFloat( respawntimer );
	arc.WriteFloat( damagetimer );
	arc.WriteFloat( getontimer );

	arc.WriteFloat( bobsin );
	arc.WriteFloat( bobfrac );

	arc.WriteSafePointer( oldweapon );
	arc.WriteInteger( rockets );
	arc.WriteInteger( bullets );
	arc.WriteInteger( mines );

	arc.WriteFloat( forwardmove );
	arc.WriteFloat( sidemove );
	arc.WriteFloat( upmove );

	arc.WriteVector( move_angles );
	arc.WriteFloat( airpitch_timmer );
	arc.WriteFloat( speed );
	arc.WriteInteger( forward_speed );
	arc.WriteFloat( strafingroll );
	arc.WriteFloat( boosttimmer );
	arc.WriteFloat( turbo );

	arc.WriteInteger( weaponmode );

	arc.WriteInteger( sndflags );
	arc.WriteString( currsound );

	arc.WriteBoolean( controlled );
	arc.WriteBoolean( scriptturboing );

	arc.WriteFloat( effectstimmer );
	arc.WriteFloat( soundtimmer );
}

inline EXPORT_FROM_DLL void Hoverbike::Unarchive( Archiver &arc )
{
	Entity::Unarchive( arc );

	arc.ReadSafePointer( &frontbox );
	arc.ReadSafePointer( &backbox );

	arc.ReadSafePointer( &rider );
	arc.ReadBoolean( &player );

	arc.ReadSafePointer( &speed_bar );
	arc.ReadSafePointer( &speed_number );
	arc.ReadSafePointer( &turbo_bar );
	arc.ReadSafePointer( &health_bar );
	arc.ReadSafePointer( &ammo_number );
	arc.ReadSafePointer( &weapon_icon );

	arc.ReadVector( &spawnspot );
	arc.ReadVector( &spawnangles );
	arc.ReadFloat( &respawntimer );
	arc.ReadFloat( &damagetimer );
	arc.ReadFloat( &getontimer );

	arc.ReadFloat( &bobsin );
	arc.ReadFloat( &bobfrac );

	arc.ReadSafePointer( &oldweapon );
	arc.ReadInteger( &rockets );
	arc.ReadInteger( &bullets );
	arc.ReadInteger( &mines );

	arc.ReadFloat( &forwardmove );
	arc.ReadFloat( &sidemove );
	arc.ReadFloat( &upmove );

	arc.ReadVector( &move_angles );
	arc.ReadFloat( &airpitch_timmer );
	arc.ReadFloat( &speed );
	arc.ReadInteger( &forward_speed );
	arc.ReadFloat( &strafingroll );
	arc.ReadFloat( &boosttimmer );
	arc.ReadFloat( &turbo );

	arc.ReadInteger( &weaponmode );

	arc.ReadInteger( &sndflags );
	arc.ReadString( &currsound );

	arc.ReadBoolean( &controlled );
	arc.ReadBoolean( &scriptturboing );

	arc.ReadFloat( &effectstimmer );
	arc.ReadFloat( &soundtimmer );
}

template class EXPORT_FROM_DLL SafePtr<Hoverbike>;
typedef SafePtr<Hoverbike> HoverbikePtr;

int SV_Physics_Hoverbike( Hoverbike *bike );

#endif /* hoverbike.h */
