summaryrefslogtreecommitdiff
path: root/game/shared/tf2/grenade_antipersonnel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/tf2/grenade_antipersonnel.cpp')
-rw-r--r--game/shared/tf2/grenade_antipersonnel.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/game/shared/tf2/grenade_antipersonnel.cpp b/game/shared/tf2/grenade_antipersonnel.cpp
new file mode 100644
index 0000000..21ecd9b
--- /dev/null
+++ b/game/shared/tf2/grenade_antipersonnel.cpp
@@ -0,0 +1,211 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "tf_player.h"
+#include "tf_basecombatweapon.h"
+#include "basegrenade_shared.h"
+#include "engine/IEngineSound.h"
+#include "tf_shareddefs.h"
+#include "IEffects.h"
+#include "Sprite.h"
+#include "grenade_antipersonnel.h"
+
+// Damage CVars
+ConVar weapon_antipersonnel_grenade_damage( "weapon_antipersonnel_grenade_damage","0", FCVAR_NONE, "Anti-personnel grenade maximum damage" );
+ConVar weapon_antipersonnel_grenade_radius( "weapon_antipersonnel_grenade_radius","0", FCVAR_NONE, "Anti-personnel grenade splash radius" );
+
+#if !defined( CLIENT_DLL )
+// Server Only
+ConVar weapon_antipersonnel_grenade_force( "weapon_antipersonnel_grenade_force","225.0", FCVAR_NONE, "Grenade explosive force modifier." );
+#endif
+
+
+IMPLEMENT_SERVERCLASS_ST(CGrenadeAntiPersonnel, DT_GrenadeAntiPersonnel)
+END_SEND_TABLE()
+
+LINK_ENTITY_TO_CLASS( grenade_antipersonnel, CGrenadeAntiPersonnel );
+PRECACHE_WEAPON_REGISTER(grenade_antipersonnel);
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CGrenadeAntiPersonnel::CGrenadeAntiPersonnel()
+{
+ UseClientSideAnimation();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGrenadeAntiPersonnel::Precache( void )
+{
+ BaseClass::Precache( );
+
+ PrecacheModel( "models/weapons/w_grenade.mdl" );
+ PrecacheModel( "sprites/redglow1.vmt" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGrenadeAntiPersonnel::Spawn( void )
+{
+ Precache();
+
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
+ SetSolid( SOLID_BBOX );
+ SetGravity( 1.0 );
+ SetFriction( 0.9 );
+ SetElasticity( 2.0f );
+ SetModel( "models/weapons/w_grenade.mdl" );
+ UTIL_SetSize(this, vec3_origin, vec3_origin);
+ SetTouch( BounceTouch );
+ SetCollisionGroup( TFCOLLISION_GROUP_GRENADE );
+
+ m_flDetonateTime = gpGlobals->curtime + 3.0;
+ SetThink( TumbleThink );
+ SetNextThink( gpGlobals->curtime + 0.1f );
+
+ // Set my damages to the cvar values
+ SetDamage( weapon_antipersonnel_grenade_damage.GetFloat() );
+ SetDamageRadius( weapon_antipersonnel_grenade_radius.GetFloat() );
+
+ // Create a green light
+ m_pLiveSprite = CSprite::SpriteCreate( "sprites/redglow1.vmt", GetLocalOrigin() + Vector(0,0,1), false );
+ m_pLiveSprite->SetTransparency( kRenderGlow, 0, 255, 0, 128, kRenderFxNoDissipation );
+ m_pLiveSprite->SetBrightness( 255 );
+ m_pLiveSprite->SetScale( 1 );
+ m_pLiveSprite->SetAttachment( this, 0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CGrenadeAntiPersonnel::UpdateOnRemove( void )
+{
+ // Remove our live sprite
+ if ( m_pLiveSprite )
+ {
+ UTIL_Remove( m_pLiveSprite );
+ m_pLiveSprite = NULL;
+ }
+
+ // Chain at end to mimic destructor unwind order
+ BaseClass::UpdateOnRemove();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Allow shield parry's
+//-----------------------------------------------------------------------------
+void CGrenadeAntiPersonnel::BounceTouch( CBaseEntity *pOther )
+{
+ // Don't blow up on trigger brushes
+ Assert( pOther );
+ if ( !pOther->IsSolid() )
+ return;
+
+ if ( pOther->GetCollisionGroup() == TFCOLLISION_GROUP_SHIELD )
+ {
+ // Move away from the shield...
+ // Fling it out a little extra along the plane normal
+ Vector vecCenter;
+ AngleVectors( pOther->GetAbsAngles(), &vecCenter );
+
+ // Bounce off the ground if it's on the ground...
+ Vector vecNewVelocity = GetAbsVelocity();
+ VectorMultiply( vecCenter, 400.0f, vecNewVelocity );
+ if ((GetFlags() & FL_ONGROUND) && vecNewVelocity.z <= 100.0f)
+ {
+ vecNewVelocity.z = 100.0f;
+ }
+ SetAbsVelocity( vecNewVelocity );
+ }
+
+ // If we're set to explode on contact, and we just hit an enemy, go kaboom
+ if ( m_bExplodeOnContact && !InSameTeam(pOther) && pOther->m_takedamage != DAMAGE_NO )
+ {
+ Detonate();
+ return;
+ }
+
+ BaseClass::BounceTouch( pOther );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return the radius for the screenshake
+//-----------------------------------------------------------------------------
+float CGrenadeAntiPersonnel::GetShakeRadius( void )
+{
+ return (m_DmgRadius * 2);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Create a missile
+//-----------------------------------------------------------------------------
+void CGrenadeAntiPersonnel::Detonate( void )
+{
+ BaseClass::Detonate();
+
+ // iterate on all entities in the vicinity and find vehicles
+ CBaseEntity *pEntity = NULL;
+ for ( CEntitySphereQuery sphere( GetAbsOrigin(), m_DmgRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
+ {
+ // Check team.
+ if ( pEntity->GetTeam() == GetTeam() )
+ continue;
+
+ if ( pEntity->GetServerVehicle() )
+ {
+ IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject();
+ if ( pPhysObject )
+ {
+ // Rocket the vehicle in the direction of the incoming rocket.
+ Vector vecForceDir = pEntity->GetAbsOrigin() - GetAbsOrigin();
+ float flDistance = VectorNormalize( vecForceDir );
+
+ if ( flDistance >= 0.0f && flDistance < m_DmgRadius )
+ {
+ vecForceDir.z = 1.0f;
+ VectorNormalize( vecForceDir );
+
+ float flForce = pPhysObject->GetMass();
+ flForce += ( 4 * 500.0f ); // Wheels
+ flForce *= weapon_antipersonnel_grenade_force.GetFloat();
+ flForce *= ( 1.0f - ( flDistance / m_DmgRadius ) );
+
+ vecForceDir *= flForce;
+
+ pPhysObject->ApplyForceOffset( vecForceDir, GetAbsOrigin() );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Create a missile
+//-----------------------------------------------------------------------------
+CGrenadeAntiPersonnel *CGrenadeAntiPersonnel::Create( const Vector &vecOrigin, const Vector &vecForward, CBasePlayer *pOwner )
+{
+ CGrenadeAntiPersonnel *pGrenade = (CGrenadeAntiPersonnel*)CreateEntityByName("grenade_antipersonnel");
+
+ UTIL_SetOrigin( pGrenade, vecOrigin );
+ pGrenade->Spawn();
+ pGrenade->ChangeTeam( pOwner->GetTeamNumber() );
+ pGrenade->SetOwnerEntity( pOwner );
+ pGrenade->SetThrower( pOwner );
+ pGrenade->SetAbsVelocity( vecForward );
+ QAngle angles;
+ VectorAngles( vecForward, angles );
+ pGrenade->SetLocalAngles( angles );
+ pGrenade->SetLocalAngularVelocity( RandomAngle(-500,500) );
+
+ return pGrenade;
+}
+
+
+