You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
6.7 KiB
211 lines
6.7 KiB
//========= 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; |
|
} |
|
|
|
|
|
|
|
|