diff options
Diffstat (limited to 'game/server/cstrike/smokegrenade_projectile.cpp')
| -rw-r--r-- | game/server/cstrike/smokegrenade_projectile.cpp | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/game/server/cstrike/smokegrenade_projectile.cpp b/game/server/cstrike/smokegrenade_projectile.cpp new file mode 100644 index 0000000..82d8d7c --- /dev/null +++ b/game/server/cstrike/smokegrenade_projectile.cpp @@ -0,0 +1,189 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include "cbase.h" +#include "smokegrenade_projectile.h" +#include "sendproxy.h" +#include "particle_smokegrenade.h" +#include "cs_player.h" +#include "KeyValues.h" +#include "bot_manager.h" +#include "weapon_csbase.h" + +#define GRENADE_MODEL "models/Weapons/w_eq_smokegrenade_thrown.mdl" + + +LINK_ENTITY_TO_CLASS( smokegrenade_projectile, CSmokeGrenadeProjectile ); +PRECACHE_WEAPON_REGISTER( smokegrenade_projectile ); + +BEGIN_DATADESC( CSmokeGrenadeProjectile ) + DEFINE_THINKFUNC( Think_Detonate ), + DEFINE_THINKFUNC( Think_Fade ), + DEFINE_THINKFUNC( Think_Remove ) +END_DATADESC() + + +CSmokeGrenadeProjectile* CSmokeGrenadeProjectile::Create( + const Vector &position, + const QAngle &angles, + const Vector &velocity, + const AngularImpulse &angVelocity, + CBaseCombatCharacter *pOwner ) +{ + CSmokeGrenadeProjectile *pGrenade = (CSmokeGrenadeProjectile*)CBaseEntity::Create( "smokegrenade_projectile", position, angles, pOwner ); + + // Set the timer for 1 second less than requested. We're going to issue a SOUND_DANGER + // one second before detonation. + pGrenade->SetTimer( 1.5 ); + pGrenade->SetAbsVelocity( velocity ); + pGrenade->SetupInitialTransmittedGrenadeVelocity( velocity ); + pGrenade->SetThrower( pOwner ); + pGrenade->SetGravity( 0.55 ); + pGrenade->SetFriction( 0.7 ); + pGrenade->m_flDamage = 100; + pGrenade->ChangeTeam( pOwner->GetTeamNumber() ); + pGrenade->ApplyLocalAngularVelocityImpulse( angVelocity ); + pGrenade->SetTouch( &CBaseGrenade::BounceTouch ); + + pGrenade->SetGravity( BaseClass::GetGrenadeGravity() ); + pGrenade->SetFriction( BaseClass::GetGrenadeFriction() ); + pGrenade->SetElasticity( BaseClass::GetGrenadeElasticity() ); + pGrenade->m_bDidSmokeEffect = false; + + pGrenade->m_pWeaponInfo = GetWeaponInfo( WEAPON_SMOKEGRENADE ); + + return pGrenade; +} + + +void CSmokeGrenadeProjectile::SetTimer( float timer ) +{ + SetThink( &CSmokeGrenadeProjectile::Think_Detonate ); + SetNextThink( gpGlobals->curtime + timer ); + + TheBots->SetGrenadeRadius( this, 0.0f ); +} + +void CSmokeGrenadeProjectile::Think_Detonate() +{ + if ( GetAbsVelocity().Length() > 0.1 ) + { + // Still moving. Don't detonate yet. + SetNextThink( gpGlobals->curtime + 0.2 ); + return; + } + + TheBots->SetGrenadeRadius( this, SmokeGrenadeRadius ); + + // Ok, we've stopped rolling or whatever. Now detonate. + ParticleSmokeGrenade *pGren = (ParticleSmokeGrenade*)CBaseEntity::Create( PARTICLESMOKEGRENADE_ENTITYNAME, GetAbsOrigin(), QAngle(0,0,0), NULL ); + if ( pGren ) + { + pGren->FillVolume(); + pGren->SetFadeTime( 15, 20 ); + pGren->SetAbsOrigin( GetAbsOrigin() ); + + //tell the hostages about the smoke! + CBaseEntity *pEntity = NULL; + variant_t var; //send the location of the smoke? + var.SetVector3D( GetAbsOrigin() ); + while ( ( pEntity = gEntList.FindEntityByClassname( pEntity, "hostage_entity" ) ) != NULL) + { + //send to hostages that have a resonable chance of being in it while its still smoking + if( (GetAbsOrigin() - pEntity->GetAbsOrigin()).Length() < 1000 ) + pEntity->AcceptInput( "smokegrenade", this, this, var, 0 ); + } + + // tell the bots a smoke grenade has exploded + CCSPlayer *player = ToCSPlayer(GetThrower()); + if ( player ) + { + IGameEvent * event = gameeventmanager->CreateEvent( "smokegrenade_detonate" ); + if ( event ) + { + event->SetInt( "userid", player->GetUserID() ); + event->SetFloat( "x", GetAbsOrigin().x ); + event->SetFloat( "y", GetAbsOrigin().y ); + event->SetFloat( "z", GetAbsOrigin().z ); + gameeventmanager->FireEvent( event ); + } + } + } + + m_hSmokeEffect = pGren; + m_bDidSmokeEffect = true; + + EmitSound( "BaseSmokeEffect.Sound" ); + + m_nRenderMode = kRenderTransColor; + SetNextThink( gpGlobals->curtime + 5 ); + SetThink( &CSmokeGrenadeProjectile::Think_Fade ); +} + + +// Fade the projectile out over time before making it disappear +void CSmokeGrenadeProjectile::Think_Fade() +{ + SetNextThink( gpGlobals->curtime ); + + color32 c = GetRenderColor(); + c.a -= 1; + SetRenderColor( c.r, c.b, c.g, c.a ); + + if ( !c.a ) + { + TheBots->RemoveGrenade( this ); + + SetModelName( NULL_STRING );//invisible + SetNextThink( gpGlobals->curtime + 20 ); + SetThink( &CSmokeGrenadeProjectile::Think_Remove ); // Spit out smoke for 10 seconds. + SetSolid( SOLID_NONE ); + } +} + + +void CSmokeGrenadeProjectile::Think_Remove() +{ + if ( m_hSmokeEffect.Get() ) + UTIL_Remove( m_hSmokeEffect ); + + TheBots->RemoveGrenade( this ); + + SetModelName( NULL_STRING );//invisible + SetSolid( SOLID_NONE ); + SetMoveType( MOVETYPE_NONE ); +} + +//Implement this so we never call the base class, +//but this should never be called either. +void CSmokeGrenadeProjectile::Detonate( void ) +{ + Assert(!"Smoke grenade handles its own detonation"); +} + + +void CSmokeGrenadeProjectile::Spawn() +{ + SetModel( GRENADE_MODEL ); + BaseClass::Spawn(); +} + + +void CSmokeGrenadeProjectile::Precache() +{ + PrecacheModel( GRENADE_MODEL ); + PrecacheScriptSound( "BaseSmokeEffect.Sound" ); + PrecacheScriptSound( "SmokeGrenade.Bounce" ); + BaseClass::Precache(); +} + +void CSmokeGrenadeProjectile::BounceSound( void ) +{ + if ( !m_bDidSmokeEffect ) + { + EmitSound( "SmokeGrenade.Bounce" ); + } +} |