diff options
Diffstat (limited to 'game/shared/cstrike/basecsgrenade_projectile.cpp')
| -rw-r--r-- | game/shared/cstrike/basecsgrenade_projectile.cpp | 346 |
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 |