#define	E3DEMO

#include "weapons.h"
#include "midas.h"

/////////////////////////////////////////////////////////////////////
// exports
/////////////////////////////////////////////////////////////////////

DllExport	void	weapon_midas (userEntity_t *self);

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

void	midas_use(userInventory_s *ptr, userEntity_t *self);
void	midas_select (userEntity_t *self);
void	midas_give (userEntity_t *self);
void	midas_reload (userEntity_t *self);
void    midas_ammo(userEntity_t *self);

///////////////////////////////////////////////////////////////////
// standard weapon interface routines
//
// each weapon must have these routines so that they can "plug-in"
// to Daikatana with minimum effort -- modularity is the goal
///////////////////////////////////////////////////////////////////

static	char			*weapon_name;
static	char			*weapon_netname;
static  char            *weapon_model;

static	int	readyFirst		[1];
static	int	readyLast		[1];

static	int	shootFirst		[1];
static	int	shootLast		[1];

static	int	reloadFirst		[1];
static	int	reloadLast		[1];

static	int	changeFirst		[1];
static	int	changeLast		[1];
			
/////////////////////////////////
// midas_load_init
//
// should be called from dll_Load
/////////////////////////////////

int midas_load_init (void)
{
	// host_initialized has not been set yet
	// so everything here is perm
	weapon_name = "weapon_midas";
	weapon_netname = "Midas' Glove";
	weapon_model = "models/midas/midasglove.md2";

	// add spawn command
	gstate->AddCommand ("select_midas", midas_select);
	gstate->AddCommand (weapon_name, midas_give);
	// we need to precache an item's resources here
	gstate->InventoryPrecache("weapon_midas", "needicon", weapon_model);

	return (sizeof(userEntity_t) + sizeof(serverState_t));
}

/////////////////////////////////
// midas_load_init
//
// should be called from dll_LoadLevel
/////////////////////////////////

void midas_level_init (void)
{
	userEntity_t *temp;

	gstate->Precache_Sound ("weapons/midas/midastouch.wav");
	gstate->Precache_Model(weapon_model);

	////////////////////////////////////////////////////////////////////
	// spawn a temp entity to pull out the frame sequence data
	////////////////////////////////////////////////////////////////////

	temp = gstate->SpawnEntity ();
	gstate->SetModel (temp, weapon_model);
	
	com->GetFrames (temp, "goaway", &changeFirst [0], &changeLast [0]);
	com->GetFrames (temp, "reload", &reloadFirst [0], &reloadLast [0]);
	com->GetFrames (temp, "shoot", &shootFirst [0], &shootLast [0]);
	com->GetFrames (temp, "ready", &readyFirst [0], &readyLast [0]);
	
	gstate->RemoveEntity (temp);
}

/////////////////////////////////////////////////////////////////////
/// weapon_midas
/////////////////////////////////////////////////////////////////////

/*
=============
midas_command
=============
*/
//You can use this to tell the weapon to do just about anything
static	void *midas_command (struct userInventory_s *ptr, char *commandStr, void *data)
{
	ammo_t	*ammo = (ammo_t *) ptr;
	
	if (!stricmp (commandStr, "death_msg"))
	{
		killerInfo_t	*ki = (killerInfo_t *) data;
		char			msg [80];

		if (rnd () < 0.5)
			sprintf (msg, "%s takes %s's midas to the head.\n", ki->victim->netname, ki->attacker->netname);
		else
			sprintf (msg, "%s shoves an midas up %s's yam! (and he likes it! HEHE) .\n", ki->attacker->netname, ki->victim->netname);

		gstate->bprint (msg);	
	}
	else if (!stricmp (commandStr, "suicide_msg"))
	{
		killerInfo_t	*ki = (killerInfo_t *) data;
		char			msg [80];

		sprintf (msg, "%s shoves an midas up %s's yam! (and he likes it! HEHE) .\n", ki->attacker->netname, ki->victim->netname);

		gstate->bprint (msg);
	}
	else if (!stricmp (commandStr, "rating"))
	{
		// return a value between 0 and 1000
		*(int *) data = 150;
	}
	else if (!stricmp (commandStr, "change"))
	{
		//	play goaway sequence
		weapon_animate ((userEntity_t *)data, changeFirst [0], changeLast [0], 0.05);
	}
	else if (!stricmp (commandStr, "change_time"))
	{
		//	return length of time to play putaway sequence
		*(float *) data = (changeLast [0] - changeFirst [0]) * 0.05;
	}

	return NULL;
}

/*
=============
ammo_command

make sure you use standard command names when modifying/adding weapons:
  give_ammo
  take_ammo
  death_msg
=============
*/

static	void *ammo_command (userInventory_t *ptr, char *commandStr, void *data)
{
	return NULL;
}

/*
=============
ammo_create

creates an inventory item of ammo type
=============
*/

static ammo_t *ammo_create (void)
{
	ammo_t	*ammo;

	// use malloc since the inventory is here for good
	ammo = (ammo_t *) com->malloc (sizeof (ammo_t), MEM_MALLOC);

	// init the inventory struct to 0's
	memset (ammo, 0x00, sizeof (ammo_t));
	//ammo->name = strdup (ammo_name);
	ammo->use  = NULL;
	ammo->command = ammo_command;

	return ammo;
}

/*
=============
midas_create

creates a inventory item of weapon type
=============
*/

static weapon_t *midas_create (void)
{
	weapon_t	*weapon;

	// use malloc since the inventory is here for good
	weapon = (weapon_t *) com->malloc (sizeof (weapon_t), MEM_MALLOC);

	// init the inventory struct to 0's
	memset (weapon, 0x00, sizeof (weapon_t));
	weapon->name = strdup (weapon_name);
	weapon->use  = midas_use;
	weapon->command = midas_command;
	
	return weapon;
}

//////////////////////////
// midas_pixie_damn_dust
//////////////////////////

static	void	midas_pixie_damn_dust (userEntity_t *self)
{
	Vector			dir, org, end;

	dir = Vector (self->owner->client->v_angle);
	dir.AngleVectors (forward, right, up);
	dir = forward * 4.0 + up * -1.0;

	org = Vector (self->owner->s.origin) + forward * 32.0;
	org.z += 20.0;
	end = org + forward * 16.0;
	gstate->TraceLine (org.vec (), end.vec (), FALSE, self, &trace);

	if (trace.ent)
	{
		if (trace.ent->flags & FL_MONSTER || trace.ent->flags & FL_BOT)
		{
			trace.ent->nextthink = gstate->time + 10.0;
			gstate->sound (self->owner, CHAN_VOICE, "weapons/midas/midastouch.wav", 255, ATTN_NORM);
		}
	}

//	gstate->particle (org.vec (), dir.vec (), gstate->global_yellow, 100);

	gstate->RemoveEntity (self);
}

/*
================
midas_use
================
*/

static	void	midas_use (userInventory_s *ptr, userEntity_t *self)
{
	playerHook_t	*phook;
	weapon_t        *midasp;
	int				hit;
	userEntity_t	*temp;

	phook = (playerHook_t *) self->userHook;
	phook->attack_finished = gstate->time + 1.1;

	temp = gstate->SpawnEntity ();
	temp->owner = self;
	temp->think = midas_pixie_damn_dust;
	temp->nextthink = gstate->time + 0.7;

	weapon_animate (self, shootFirst [0], shootLast [0], 0.05);
}

/*
=============
midas_select_finish

set the midas as the players current weapon if it is in the 
inventory
=============
*/

static	void	midas_select_finish (userEntity_t *self)
{
	playerHook_t		*hook = (playerHook_t *) self->userHook;
	userInventory_t		*invItem;
	userEntity_t		*temp;

	invItem = gstate->InventoryFindItem (self->inventory, weapon_name);

	if (!invItem)
		return;

	self->curWeapon = invItem;
	// this must be here to stop the sling from screwing up the firing of other weapons
	self->flags = self->flags - (self->flags & FL_ATTACKHOLD);

	weapon_animate (self, readyFirst [0], readyLast [0], 0.05);	
	
	//place a delay in the next time to attack so the weapon
	//can cycle through its "select" sequence
	hook->attack_finished = gstate->time + 1.30;
}

///////////////////////////////
//	midas_select
//
//	set the midas as the players current weapon if it is in the 
//	inventory
///////////////////////////////

static	void	midas_select (userEntity_t *self)
{
	playerHook_t		*hook = (playerHook_t *) self->userHook;
	weapon_t			*weapon;
	userInventory_t		*invItem;
	float				seq_time;

	invItem = gstate->InventoryFindItem (self->inventory, weapon_name);

	if (!invItem)
		return;
	//	tell the user's current weapon to go away
	weapon = (weapon_t *) self->curWeapon;
	if (weapon)
	{
		weapon->command (self->curWeapon, "change", self);
		weapon->command (self->curWeapon, "change_time", &seq_time);

		//	make sure the client's frame flags tell us to go to next weapon
		hook->vm_frameFlags |= FRAME_WEAPONSWITCH;
	
		//	set client's next weapon to this weapon
		hook->weapon_next = midas_select_finish;

		//	make sure we can't shoot!
		hook->attack_finished = gstate->time + seq_time;
	}
	else
		midas_select_finish (self);
}

/*
=============
midas_give

puts a midas in the inventory
=============
*/

static	void	midas_give (userEntity_t *self)
{
	weapon_t		*weapon;
	ammo_t			*ammo;
	userInventory_t	*invItem;
	int				ammo_count;
	////////////////////////////////
	// set up names for this weapon
	////////////////////////////////

	weapon_name = "weapon_midas";
	weapon_netname = "midas";
	//ammo_name = "ammo_bullets";
	//ammo_netname = "bullets";
		// make sure weapon is not already in inventory	
	invItem = gstate->InventoryFindItem (self->inventory, weapon_name);

	if (invItem)
	{
		gstate->Con_Printf ("You already have a %s.\n", weapon_netname);
		return;
	}

	// create new inventory item
	if ((weapon = midas_create ()) == NULL)
	{
		gstate->Con_Printf("Unable to malloc %s.\n", weapon_netname);
		return;
	}

	// add the weapon to the player's inventory list
	if (!gstate->InventoryAddItem (self->inventory, (userInventory_t *) weapon))
	{
		gstate->Con_Printf ("Could not add %s to inventory.\n", weapon_netname);
		return;
	}
	
	gstate->sprint (self, "You got the %s!\n", weapon_netname);
}

#if 0
/*
=================
weapon_midas
=================
*/

void	weapon_midas (userEntity_t *self)
{

	gstate->Precache_Model("models/midas/g_rock2.md2");
	gstate->SetModel(self, "models/midas/g_rock2.md2");

	self->touch   = (touch_t)weapon_touch;
	self->netname = "Midas' Glove";
	self->className = weapon_name;

	gstate->SetSize(self, -16.0, -16.0, 0.0, 16.0, 16.0, 56.0);

	self->flags    = FL_ITEM;
	self->solid    = SOLID_TRIGGER;
	self->movetype = MOVETYPE_TOSS;

	// set this so weapon_touch knows what select function to call
	// when the weapon is picked up
	self->use = (use_t)midas_give;
	self->die = (die_t)midas_select;
}
#endif