summaryrefslogtreecommitdiff
path: root/game/shared/cstrike/basecsgrenade_projectile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/cstrike/basecsgrenade_projectile.cpp')
-rw-r--r--game/shared/cstrike/basecsgrenade_projectile.cpp346
1 files changed, 346 insertions, 0 deletions
diff --git a/game/shared/cstrike/basecsgrenade_projectile.cpp b/game/shared/cstrike/basecsgrenade_projectile.cpp
new file mode 100644
index 0000000..5d6641b
--- /dev/null
+++ b/game/shared/cstrike/basecsgrenade_projectile.cpp
@@ -0,0 +1,346 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+#include "basecsgrenade_projectile.h"
+
+float GetCurrentGravity( void );
+
+
+#ifdef CLIENT_DLL
+
+ #include "c_cs_player.h"
+
+#else
+
+ #include "bot_manager.h"
+ #include "cs_player.h"
+ #include "soundent.h"
+ #include "te_effect_dispatch.h"
+ #include "KeyValues.h"
+
+ BEGIN_DATADESC( CBaseCSGrenadeProjectile )
+ DEFINE_THINKFUNC( DangerSoundThink ),
+ END_DATADESC()
+
+#endif
+
+
+IMPLEMENT_NETWORKCLASS_ALIASED( BaseCSGrenadeProjectile, DT_BaseCSGrenadeProjectile )
+
+BEGIN_NETWORK_TABLE( CBaseCSGrenadeProjectile, DT_BaseCSGrenadeProjectile )
+ #ifdef CLIENT_DLL
+ RecvPropVector( RECVINFO( m_vInitialVelocity ) )
+ #else
+ SendPropVector( SENDINFO( m_vInitialVelocity ),
+ 20, // nbits
+ 0, // flags
+ -3000, // low value
+ 3000 // high value
+ )
+ #endif
+END_NETWORK_TABLE()
+
+
+#ifdef CLIENT_DLL
+
+
+ void CBaseCSGrenadeProjectile::PostDataUpdate( DataUpdateType_t type )
+ {
+ BaseClass::PostDataUpdate( type );
+
+ if ( type == DATA_UPDATE_CREATED )
+ {
+ // Now stick our initial velocity into the interpolation history
+ CInterpolatedVar< Vector > &interpolator = GetOriginInterpolator();
+
+ interpolator.ClearHistory();
+ float changeTime = GetLastChangeTime( LATCH_SIMULATION_VAR );
+
+ // Add a sample 1 second back.
+ Vector vCurOrigin = GetLocalOrigin() - m_vInitialVelocity;
+ interpolator.AddToHead( changeTime - 1.0, &vCurOrigin, false );
+
+ // Add the current sample.
+ vCurOrigin = GetLocalOrigin();
+ interpolator.AddToHead( changeTime, &vCurOrigin, false );
+ }
+ }
+
+ int CBaseCSGrenadeProjectile::DrawModel( int flags )
+ {
+ // During the first half-second of our life, don't draw ourselves if he's
+ // still playing his throw animation.
+ // (better yet, we could draw ourselves in his hand).
+ if ( GetThrower() != C_BasePlayer::GetLocalPlayer() )
+ {
+ if ( gpGlobals->curtime - m_flSpawnTime < 0.5 )
+ {
+ C_CSPlayer *pPlayer = dynamic_cast<C_CSPlayer*>( GetThrower() );
+ if ( pPlayer && pPlayer->m_PlayerAnimState->IsThrowingGrenade() )
+ {
+ return 0;
+ }
+ }
+ }
+
+ return BaseClass::DrawModel( flags );
+ }
+
+ void CBaseCSGrenadeProjectile::Spawn()
+ {
+ m_flSpawnTime = gpGlobals->curtime;
+ BaseClass::Spawn();
+ }
+
+#else
+
+ void CBaseCSGrenadeProjectile::PostConstructor( const char *className )
+ {
+ BaseClass::PostConstructor( className );
+ TheBots->AddGrenade( this );
+ }
+
+ CBaseCSGrenadeProjectile::~CBaseCSGrenadeProjectile()
+ {
+ TheBots->RemoveGrenade( this );
+ }
+
+ void CBaseCSGrenadeProjectile::Spawn( void )
+ {
+ BaseClass::Spawn();
+
+ SetSolidFlags( FSOLID_NOT_STANDABLE );
+ SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM );
+ SetSolid( SOLID_BBOX ); // So it will collide with physics props!
+
+ // smaller, cube bounding box so we rest on the ground
+ SetSize( Vector ( -2, -2, -2 ), Vector ( 2, 2, 2 ) );
+ }
+
+ void CBaseCSGrenadeProjectile::DangerSoundThink( void )
+ {
+ if (!IsInWorld())
+ {
+ Remove( );
+ return;
+ }
+
+ if( gpGlobals->curtime > m_flDetonateTime )
+ {
+ Detonate();
+ return;
+ }
+
+ CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, GetAbsVelocity().Length( ), 0.2 );
+
+ SetNextThink( gpGlobals->curtime + 0.2 );
+
+ if (GetWaterLevel() != 0)
+ {
+ SetAbsVelocity( GetAbsVelocity() * 0.5 );
+ }
+ }
+
+ //Sets the time at which the grenade will explode
+ void CBaseCSGrenadeProjectile::SetDetonateTimerLength( float timer )
+ {
+ m_flDetonateTime = gpGlobals->curtime + timer;
+ }
+
+ void CBaseCSGrenadeProjectile::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity )
+ {
+ //Assume all surfaces have the same elasticity
+ float flSurfaceElasticity = 1.0;
+
+ //Don't bounce off of players with perfect elasticity
+ if( trace.m_pEnt && trace.m_pEnt->IsPlayer() )
+ {
+ flSurfaceElasticity = 0.3;
+ }
+
+ // if its breakable glass and we kill it, don't bounce.
+ // give some damage to the glass, and if it breaks, pass
+ // through it.
+ bool breakthrough = false;
+
+ if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable" ) )
+ {
+ breakthrough = true;
+ }
+
+ if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable_surf" ) )
+ {
+ breakthrough = true;
+ }
+
+ if (breakthrough)
+ {
+ CTakeDamageInfo info( this, this, 10, DMG_CLUB );
+ trace.m_pEnt->DispatchTraceAttack( info, GetAbsVelocity(), &trace );
+
+ ApplyMultiDamage();
+
+ if( trace.m_pEnt->m_iHealth <= 0 )
+ {
+ // slow our flight a little bit
+ Vector vel = GetAbsVelocity();
+
+ vel *= 0.4;
+
+ SetAbsVelocity( vel );
+ return;
+ }
+ }
+
+ float flTotalElasticity = GetElasticity() * flSurfaceElasticity;
+ flTotalElasticity = clamp( flTotalElasticity, 0.0f, 0.9f );
+
+ // NOTE: A backoff of 2.0f is a reflection
+ Vector vecAbsVelocity;
+ PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, 2.0f );
+ vecAbsVelocity *= flTotalElasticity;
+
+ // Get the total velocity (player + conveyors, etc.)
+ VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity );
+ float flSpeedSqr = DotProduct( vecVelocity, vecVelocity );
+
+ // Stop if on ground.
+ if ( trace.plane.normal.z > 0.7f ) // Floor
+ {
+ // Verify that we have an entity.
+ CBaseEntity *pEntity = trace.m_pEnt;
+ Assert( pEntity );
+
+ SetAbsVelocity( vecAbsVelocity );
+
+ if ( flSpeedSqr < ( 30 * 30 ) )
+ {
+ if ( pEntity->IsStandable() )
+ {
+ SetGroundEntity( pEntity );
+ }
+
+ // Reset velocities.
+ SetAbsVelocity( vec3_origin );
+ SetLocalAngularVelocity( vec3_angle );
+
+ //align to the ground so we're not standing on end
+ QAngle angle;
+ VectorAngles( trace.plane.normal, angle );
+
+ // rotate randomly in yaw
+ angle[1] = random->RandomFloat( 0, 360 );
+
+ // TODO: rotate around trace.plane.normal
+
+ SetAbsAngles( angle );
+ }
+ else
+ {
+ Vector vecDelta = GetBaseVelocity() - vecAbsVelocity;
+ Vector vecBaseDir = GetBaseVelocity();
+ VectorNormalize( vecBaseDir );
+ float flScale = vecDelta.Dot( vecBaseDir );
+
+ VectorScale( vecAbsVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, vecVelocity );
+ VectorMA( vecVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, GetBaseVelocity() * flScale, vecVelocity );
+ PhysicsPushEntity( vecVelocity, &trace );
+ }
+ }
+ else
+ {
+ // If we get *too* slow, we'll stick without ever coming to rest because
+ // we'll get pushed down by gravity faster than we can escape from the wall.
+ if ( flSpeedSqr < ( 30 * 30 ) )
+ {
+ // Reset velocities.
+ SetAbsVelocity( vec3_origin );
+ SetLocalAngularVelocity( vec3_angle );
+ }
+ else
+ {
+ SetAbsVelocity( vecAbsVelocity );
+ }
+ }
+
+ BounceSound();
+
+ // tell the bots a grenade has bounced
+ CCSPlayer *player = ToCSPlayer(GetThrower());
+ if ( player )
+ {
+ IGameEvent * event = gameeventmanager->CreateEvent( "grenade_bounce" );
+ 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 );
+ }
+ }
+ }
+
+ void CBaseCSGrenadeProjectile::SetupInitialTransmittedGrenadeVelocity( const Vector &velocity )
+ {
+ m_vInitialVelocity = velocity;
+ }
+
+ #define MAX_WATER_SURFACE_DISTANCE 512
+
+ void CBaseCSGrenadeProjectile::Splash()
+ {
+ Vector centerPoint = GetAbsOrigin();
+ Vector normal( 0, 0, 1 );
+
+ // Find our water surface by tracing up till we're out of the water
+ trace_t tr;
+ Vector vecTrace( 0, 0, MAX_WATER_SURFACE_DISTANCE );
+ UTIL_TraceLine( centerPoint, centerPoint + vecTrace, MASK_WATER, NULL, COLLISION_GROUP_NONE, &tr );
+
+ // If we didn't start in water, we're above it
+ if ( tr.startsolid == false )
+ {
+ // Look downward to find the surface
+ vecTrace.Init( 0, 0, -MAX_WATER_SURFACE_DISTANCE );
+ UTIL_TraceLine( centerPoint, centerPoint + vecTrace, MASK_WATER, NULL, COLLISION_GROUP_NONE, &tr );
+
+ // If we hit it, setup the explosion
+ if ( tr.fraction < 1.0f )
+ {
+ centerPoint = tr.endpos;
+ }
+ else
+ {
+ //NOTENOTE: We somehow got into a splash without being near water?
+ Assert( 0 );
+ }
+ }
+ else if ( tr.fractionleftsolid )
+ {
+ // Otherwise we came out of the water at this point
+ centerPoint = centerPoint + (vecTrace * tr.fractionleftsolid);
+ }
+ else
+ {
+ // Use default values, we're really deep
+ }
+
+ CEffectData data;
+ data.m_vOrigin = centerPoint;
+ data.m_vNormal = normal;
+ data.m_flScale = random->RandomFloat( 1.0f, 2.0f );
+
+ if ( GetWaterType() & CONTENTS_SLIME )
+ {
+ data.m_fFlags |= FX_WATER_IN_SLIME;
+ }
+
+ DispatchEffect( "gunshotsplash", data );
+ }
+
+#endif // !CLIENT_DLL