//---------------------------------------------------------------------------
// POSEIDONS TRIDENT
//---------------------------------------------------------------------------
#include "weapons.h"
#include "trident.h"

// model defs
#define MDL_TIP               MDL_SPECIAL+0

// sound defs
#define SND_FIRE              0
#define SND_RELOAD            1
#define SND_AMBIENT			  2

// frame defs

// weapon info def
weaponInfo_t tridentWeaponInfo = {
      // names, net names, icon
      "weapon_trident",
      "Poseidon's Trident",
      "ammo_tritips",
      "Trident Tips",
      "iconname",

      // model files
      {"models/trident/trident.md2",
       "models/tritip/tritip.md2",
       NULL},

      // sound files
      {"weapons/trident/tridentfire2.wav",
       "weapons/trident/tridentreload2.wav",
       "weapons/trident/tridentambient.wav",
       NULL},

      // frame names
      {MDL_WEAPON_STD,"ready",0,0,
               -1,"away",0,0,
               -1,"shoota",0,0,
               -1,"amba",0,0,
       0,NULL},

      // commands
      {"weapon_trident",(void (*)())give,
       "select_trident",(void (*)())select,
       NULL},

       use,
       command,
       sizeof(trident_t),

      500,
      FL_LOOPAMBIENT,
	   SND_AMBIENT
};

// local weapon info access
static weaponInfo_t *winfo=&tridentWeaponInfo;

//---------------------------------------------------------------------------
// give()
//---------------------------------------------------------------------------
static userInventory_t *give(userEntity_t *self)
{
   return(weaponGive(self,winfo,99));
}

//---------------------------------------------------------------------------
// select()
//---------------------------------------------------------------------------
static void select(userEntity_t *self)
{
   weaponSelect(self,winfo);
}

//---------------------------------------------------------------------------
// command()
//---------------------------------------------------------------------------
static void *command(struct userInventory_s *inv, char *commandStr, void *data)
{
	ammo_t *ammo=(ammo_t *)inv;
   userEntity_t *self=(userEntity_t *)data;
   playerHook_t *phook=(playerHook_t *)self->userHook;
	
	if (!stricmp(commandStr, "death_msg"))
	{
		killerInfo_t	*ki = (killerInfo_t *) data;
		char			msg [80];

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

	return(NULL);
}

//---------------------------------------------------------------------------
// use()
//---------------------------------------------------------------------------
static void use(userInventory_s *ptr, userEntity_t *self)
{
   playerHook_t *phook=(playerHook_t *)self->userHook;

   if (weaponUseAmmo(self->curWeapon,0) < 3)
      return;

   winfoPlay(SND_FIRE,255);

   winfoAnimDelay(self,winfo,ANIM_SHOOT_STD,0.05);

// phook->fxFrameNum=winfoFirstFrame(ANIM_SHOOT_STD)+10;
// phook->fxFrameFunc=shootFunc;

   shootFunc(self);
}

//---------------------------------------------------------------------------
// shootFunc()
//---------------------------------------------------------------------------
static void shootFunc(userEntity_t *self)
{
   #define TRI_BASE_XOFS   -3

   playerHook_t *phook=(playerHook_t *)self->userHook;
   float midx=4;

   shootTip(self,Vector(midx+TRI_BASE_XOFS-14, 34, 12));
   shootTip(self,Vector(midx+TRI_BASE_XOFS,    34, 18));
   shootTip(self,Vector(midx+TRI_BASE_XOFS+14, 34, 16));

   winfoPlay(SND_RELOAD,255);

   phook->fxFrameFunc=NULL;
}

//---------------------------------------------------------------------------
// shootTip()
//---------------------------------------------------------------------------
static void shootTip(userEntity_t *self,Vector &pos)
{
   userEntity_t *ent;
   int pc;

   weaponUseAmmo(self->curWeapon,1);

   ent=weapon_spawn_projectile(self,pos,1200,0,winfo->ammoName);
   ent->movetype=MOVETYPE_FLY;
   ent->think=think_tip;
   ent->nextthink=gstate->time+.1;
   ent->touch=touch_tip;
   ent->s.effects=EF_MAGIC_ARROW;
   com->SetVector(self->s.render_scale,TRI_TIP_SIZE,TRI_TIP_SIZE,TRI_TIP_SIZE);
   winfoSetModel(ent,MDL_TIP);

  	pc=gstate->PointContents(self->s.origin);
	if (pc & CONTENTS_WATER)
      com->SetVector(self->s.render_scale,TRI_TIP_SIZE*2,TRI_TIP_SIZE*2,TRI_TIP_SIZE*2);
}

//---------------------------------------------------------------------------
// think_tip()
//---------------------------------------------------------------------------
static void think_tip(userEntity_t *self)
{
   int pc;

	pc=gstate->PointContents(self->s.origin);
	if (pc & CONTENTS_WATER)
      com->SetVector(self->s.render_scale,TRI_TIP_SIZE*2,TRI_TIP_SIZE*2,TRI_TIP_SIZE*2);
   else
      com->SetVector(self->s.render_scale,TRI_TIP_SIZE,TRI_TIP_SIZE,TRI_TIP_SIZE);

   self->nextthink=gstate->time+.1;
}

//---------------------------------------------------------------------------
// touch_tip()
//---------------------------------------------------------------------------
static void touch_tip(userEntity_t *self, userEntity_t *other,cplane_t *plane, csurface_t *surf)
{
   short damage;

   if (other->takedamage==DAMAGE_NO || (surf && (surf->flags & SURF_SKY)))
   {

      if (!(surf && (surf->flags & SURF_SKY)))
      {
         gstate->WriteByte(SVC_TEMP_ENTITY);
         gstate->WriteByte(TE_SHIELD_SPARKS);
         gstate->WritePosition(self->s.origin);
         gstate->WriteDir(plane->normal);
         gstate->MultiCast(self->s.origin,MULTICAST_ALL);
      }
   
      gstate->RemoveEntity(self);
      return;
   }

   if (entityHuman(other))
   {
      gstate->WriteByte(SVC_TEMP_ENTITY);
      gstate->WriteByte(TE_BLOOD);
      gstate->WritePosition(self->s.origin);
      gstate->WriteDir(plane->normal);
      gstate->MultiCast(self->s.origin,MULTICAST_ALL);
   }
   else
   {
      gstate->WriteByte(SVC_TEMP_ENTITY);
      gstate->WriteByte(TE_SHIELD_SPARKS);
      gstate->WritePosition(self->s.origin);
      gstate->WriteDir(plane->normal);
      gstate->MultiCast(self->s.origin,MULTICAST_ALL);
   }

   damage=20;
	if (gstate->PointContents(self->s.origin) & CONTENTS_WATER)
      damage *= 2;

   com->Damage(other,self,self,other->s.origin,other->s.angles,damage,DAMAGE_INERTIAL);
   gstate->RemoveEntity(self);
}
