diff options
Diffstat (limited to 'game/shared/tf/tf_weapon_grenade_gas.cpp')
| -rw-r--r-- | game/shared/tf/tf_weapon_grenade_gas.cpp | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/game/shared/tf/tf_weapon_grenade_gas.cpp b/game/shared/tf/tf_weapon_grenade_gas.cpp new file mode 100644 index 0000000..9e0cfd1 --- /dev/null +++ b/game/shared/tf/tf_weapon_grenade_gas.cpp @@ -0,0 +1,260 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: TF Gas Grenade. +// +//=============================================================================// +#include "cbase.h" +#include "tf_weaponbase.h" +#include "tf_gamerules.h" +#include "npcevent.h" +#include "engine/IEngineSound.h" +#include "tf_weapon_grenade_gas.h" + +// Server specific. +#ifdef GAME_DLL +#include "tf_player.h" +#include "items.h" +#include "tf_weaponbase_grenadeproj.h" +#include "soundent.h" +#include "KeyValues.h" +#endif + +#define GRENADE_GAS_TIMER 3.0f //Seconds + +//============================================================================= +// +// TF Gas Grenade tables. +// + +IMPLEMENT_NETWORKCLASS_ALIASED( TFGrenadeGas, DT_TFGrenadeGas ) + +BEGIN_NETWORK_TABLE( CTFGrenadeGas, DT_TFGrenadeGas ) +END_NETWORK_TABLE() + +BEGIN_PREDICTION_DATA( CTFGrenadeGas ) +END_PREDICTION_DATA() + +LINK_ENTITY_TO_CLASS( tf_weapon_grenade_gas, CTFGrenadeGas ); +PRECACHE_WEAPON_REGISTER( tf_weapon_grenade_gas ); + +//============================================================================= +// +// TF Gas Grenade functions. +// + +// Server specific. +#ifdef GAME_DLL + +BEGIN_DATADESC( CTFGrenadeGas ) +END_DATADESC() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFWeaponBaseGrenadeProj *CTFGrenadeGas::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, + AngularImpulse angImpulse, CBasePlayer *pPlayer, float flTime, int iflags ) +{ + return CTFGrenadeGasProjectile::Create( vecSrc, vecAngles, vecVel, angImpulse, + pPlayer, GetTFWpnData(), flTime ); +} + +#endif + +//============================================================================= +// +// TF Gas Grenade Projectile functions (Server specific). +// +#ifdef GAME_DLL + +#define GRENADE_MODEL "models/weapons/w_models/w_grenade_gas.mdl" + +LINK_ENTITY_TO_CLASS( tf_weapon_grenade_gas_projectile, CTFGrenadeGasProjectile ); +PRECACHE_WEAPON_REGISTER( tf_weapon_grenade_gas_projectile ); + + +BEGIN_DATADESC( CTFGrenadeGasProjectile ) + DEFINE_THINKFUNC( Think_Emit ), + DEFINE_THINKFUNC( Think_Fade ), +END_DATADESC() +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFGrenadeGasProjectile* CTFGrenadeGasProjectile::Create( const Vector &position, const QAngle &angles, + const Vector &velocity, const AngularImpulse &angVelocity, + CBaseCombatCharacter *pOwner, const CTFWeaponInfo &weaponInfo, float timer, int iFlags ) +{ + CTFGrenadeGasProjectile *pGrenade = static_cast<CTFGrenadeGasProjectile*>( CTFWeaponBaseGrenadeProj::Create( "tf_weapon_grenade_gas_projectile", position, angles, velocity, angVelocity, pOwner, weaponInfo, timer, iFlags ) ); + if ( pGrenade ) + { + pGrenade->ApplyLocalAngularVelocityImpulse( angVelocity ); + } + + return pGrenade; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGrenadeGasProjectile::Spawn() +{ + SetModel( GRENADE_MODEL ); + + BaseClass::Spawn(); + + m_hGasEffect = NULL; +} + +CTFGrenadeGasProjectile::~CTFGrenadeGasProjectile() +{ + if ( m_hGasEffect.Get() ) + { + UTIL_Remove( m_hGasEffect ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGrenadeGasProjectile::Precache() +{ + PrecacheModel( GRENADE_MODEL ); + PrecacheParticleSystem( "spy_gasgrenade" ); + BaseClass::Precache(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGrenadeGasProjectile::BounceSound( void ) +{ + EmitSound( "Weapon_Grenade_Gas.Bounce" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGrenadeGasProjectile::DetonateThink( void ) +{ + // if we're past the detonate time but still moving, delay the detonate + if ( gpGlobals->curtime > GetDetonateTime() && VPhysicsGetObject() ) + { + Vector vel; + VPhysicsGetObject()->GetVelocity( &vel, NULL ); + + if ( vel.Length() > 35.0 ) + { + SetTimer( gpGlobals->curtime + 0.5 ); + } + } + + BaseClass::DetonateThink(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFGrenadeGasProjectile::Detonate() +{ + if ( ShouldNotDetonate() ) + { + RemoveGrenade(); + return; + } + + // start emitting gas + VPhysicsGetObject()->EnableMotion( false ); + + m_hGasEffect = ( CTFGasGrenadeEffect * )CreateEntityByName("tf_gas_grenade_effect"); + CBaseEntity *pGasEffect = m_hGasEffect.Get(); + if ( pGasEffect ) + { + DispatchSpawn( pGasEffect ); + pGasEffect->SetAbsOrigin( GetAbsOrigin() ); + } + + EmitSound( "BaseSmokeEffect.Sound" ); + + // damage / hallucination effect in waves + m_nPulses = 20; + + SetThink( &CTFGrenadeGasProjectile::Think_Emit ); + SetNextThink( gpGlobals->curtime + 0.1f ); +} + +//----------------------------------------------------------------------------- +// Purpose: Emit gas pulses +//----------------------------------------------------------------------------- +void CTFGrenadeGasProjectile::Think_Emit( void ) +{ + Vector vecOrigin = GetAbsOrigin(); + float flDamage = 10; + CTakeDamageInfo info( this, GetThrower(), vec3_origin, vecOrigin, flDamage, DMG_NERVEGAS | DMG_PREVENT_PHYSICS_FORCE ); + + CBaseEntity* pEntity = NULL; + while ( ( pEntity = gEntList.FindEntityInSphere( pEntity, vecOrigin, TF_HALLUCINATION_RADIUS ) ) != NULL ) + { + // check for valid player + if ( !pEntity->IsPlayer() ) + continue; + + pEntity->TakeDamage( info ); + } + + m_nPulses--; + + if ( m_nPulses <= 0 ) + { + // Fade out + SetThink( &CTFGrenadeGasProjectile::Think_Fade ); + } + + SetNextThink( gpGlobals->curtime + 0.75 ); +} + +//----------------------------------------------------------------------------- +// Fade the projectile out over time before making it disappear +//----------------------------------------------------------------------------- +void CTFGrenadeGasProjectile::Think_Fade() +{ + color32 c = GetRenderColor(); + c.a -= 1; + SetRenderColor( c.r, c.b, c.g, c.a ); + + if ( !c.a ) + { + UTIL_Remove( this ); + } + + SetNextThink( gpGlobals->curtime ); +} + +#endif + + +IMPLEMENT_NETWORKCLASS_ALIASED( TFGasGrenadeEffect, DT_TFGasGrenadeEffect ) + +BEGIN_NETWORK_TABLE(CTFGasGrenadeEffect, DT_TFGasGrenadeEffect ) +END_NETWORK_TABLE() + +#ifndef CLIENT_DLL + LINK_ENTITY_TO_CLASS( tf_gas_grenade_effect, CTFGasGrenadeEffect ); +#endif + +#ifndef CLIENT_DLL + + int CTFGasGrenadeEffect::UpdateTransmitState( void ) + { + return SetTransmitState( FL_EDICT_PVSCHECK ); + } + +#else + + void CTFGasGrenadeEffect::OnDataChanged( DataUpdateType_t updateType ) + { + if ( updateType == DATA_UPDATE_CREATED && m_pGasEffect == NULL ) + { + m_pGasEffect = ParticleProp()->Create( "spy_gasgrenade", PATTACH_ABSORIGIN ); + } + } + +#endif // CLIENT_DLL |