// ---------------------------------------------------------------
// BubbleMod
// 
// AUTHOR
//        Tyler Lund <halflife@bubblemod.org>
//
// LICENSE                                                            
//                                                                    
//        Permission is granted to anyone to use this  software  for  
//        any purpose on any computer system, and to redistribute it  
//        in any way, subject to the following restrictions:          
//                                                                    
//        1. The author is not responsible for the  consequences  of  
//           use of this software, no matter how awful, even if they  
//           arise from defects in it.                                
//        2. The origin of this software must not be misrepresented,  
//           either by explicit claim or by omission.                 
//        3. Altered  versions  must  be plainly marked as such, and  
//           must  not  be  misrepresented  (by  explicit  claim  or  
//           omission) as being the original software.                
//        3a. It would be nice if I got  a  copy  of  your  improved  
//            version  sent to halflife@bubblemod.org. 
//        4. This notice must not be removed or altered.              
//                                                                    
// ---------------------------------------------------------------

#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#include "BMOD_flyingcrowbar.h"

LINK_ENTITY_TO_CLASS( flying_crowbar, CFlyingCrowbar );

void CFlyingCrowbar::Spawn( )
{
   Precache( );

   // The flying crowbar is MOVETYPE_TOSS, and SOLID_BBOX.
   // We want it to be affected by gravity, and hit objects
   // within the game.
   pev->movetype = MOVETYPE_TOSS;
   pev->solid = SOLID_BBOX;

   // Use the world crowbar model.
   SET_MODEL(ENT(pev), "models/w_crowbar.mdl");

   // Set the origin and size for the HL engine collision
   // tables.
   UTIL_SetOrigin( pev, pev->origin );
   UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4));

   // Store the owner for later use. We want the owner to be able 
   // to hit themselves with the crowbar. The pev->owner gets cleared
   // later to avoid hitting the player as they throw the crowbar. 
   if ( pev->owner )
      m_hOwner = Instance( pev->owner );

   // Set the think funtion. 
   SetThink( BubbleThink );
   pev->nextthink = gpGlobals->time + 0.25;

   // Set the touch function.
   SetTouch( SpinTouch );
}


void CFlyingCrowbar::Precache( )
{
   PRECACHE_MODEL ("models/w_crowbar.mdl");
   PRECACHE_SOUND ("weapons/cbar_hitbod1.wav");
   PRECACHE_SOUND ("weapons/cbar_hit1.wav");
   PRECACHE_SOUND ("weapons/cbar_miss1.wav");
}


void CFlyingCrowbar::SpinTouch( CBaseEntity *pOther )
{
   // We touched something in the game. Look to see if the object
   // is allowed to take damage. 
   if (pOther->pev->takedamage)
   {
      // Get the traceline info to the target.
      TraceResult tr = UTIL_GetGlobalTrace( );
   
      // Apply damage to the target. If we have an owner stored, use that one, 
      // otherwise count it as self-inflicted.
      ClearMultiDamage( );
      pOther->TraceAttack(pev, 90, pev->velocity.Normalize(), &tr, 
                          DMG_NEVERGIB ); 
      if (m_hOwner != NULL)
         ApplyMultiDamage( pev, m_hOwner->pev );
      else
         ApplyMultiDamage( pev, pev );
   }

   // If we hit a player, make a nice squishy thunk sound. Otherwise
   // make a clang noise and throw a bunch of sparks. 
   if (pOther->IsPlayer())
      EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "weapons/cbar_hitbod1.wav", 
                     1.0, ATTN_NORM, 0, 100);
   else 
   {
      EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "weapons/cbar_hit1.wav", 
                     1.0, ATTN_NORM, 0, 100);
      if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
      {
         UTIL_Sparks( pev->origin );
         UTIL_Sparks( pev->origin );
         UTIL_Sparks( pev->origin );
      }
   }

   // Don't draw the flying crowbar anymore. 
   pev->effects |= EF_NODRAW;
   pev->solid = SOLID_NOT;

   // Spawn a crowbar weapon
   CBasePlayerWeapon *pItem = (CBasePlayerWeapon *)Create( "weapon_crowbar", 
                               pev->origin , pev->angles, edict() );

   // Spawn a weapon box
   CWeaponBox *pWeaponBox = (CWeaponBox *)CBaseEntity::Create( 
                  "weaponbox", pev->origin, pev->angles, edict() );

   // don't let weapon box tilt.
   pWeaponBox->pev->angles.x = 0;
   pWeaponBox->pev->angles.z = 0;

   // remove the weapon box after 4 mins.
   pWeaponBox->pev->nextthink = gpGlobals->time + 240; 
   pWeaponBox->SetThink( CWeaponBox::Kill );

   // Pack the crowbar in the weapon box
   pWeaponBox->PackWeapon( pItem );

   // *** Start BubbleMod Rune code ***
   // Check to see if the crowbar rune is active on the owner,
   // if it is, then remove this crowbar after 3 seconds
   // instead if 2 mins. This prevents too many crowbars from
   // piling up on the server.  
   //
   // REMOVE THIS IF YOU ARE NOT USING THE RUNE CODE
   if (m_pPlayer->m_RuneFlags == RUNE_CROWBAR)
      pWeaponBox->pev->nextthink = gpGlobals->time + 3;
   // *** End BubbleMod Rune Code ***

   // Get the unit vector in the direction of motion.
   Vector vecDir = pev->velocity.Normalize( );

   // Trace a line along the velocity vector to get the normal at impact.
   TraceResult tr;
   UTIL_TraceLine(pev->origin, pev->origin + vecDir * 100, 
                  dont_ignore_monsters, ENT(pev), &tr);

   // Throw the weapon box along the normal so it looks kinda
   // like a ricochet. This would be better if I actually 
   // calcualted the reflection angle, but I'm lazy. :)
   pWeaponBox->pev->velocity = tr.vecPlaneNormal * 300;

   // Remove this flying_crowbar from the world.
   SetThink ( SUB_Remove );
   pev->nextthink = gpGlobals->time + .1;
}

void CFlyingCrowbar::BubbleThink( void )
{
   // We have no owner. We do this .25 seconds AFTER the crowbar
   // is thrown so that we don't hit the owner immediately when throwing
   // it. If is comes back later, we want to be able to hit the owner.
   pev->owner = NULL;

   // Only think every .25 seconds. 
   pev->nextthink = gpGlobals->time + 0.25;

   // Make a whooshy sound. 
   EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/cbar_miss1.wav", 
                  1, ATTN_NORM, 0, 120);

   // If the crowbar enters water, make some bubbles. 
   if (pev->waterlevel)
	   UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1, pev->origin, 1 );
}
