mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user