diff options
Diffstat (limited to 'game/server/tf2/mortar_round.cpp')
| -rw-r--r-- | game/server/tf2/mortar_round.cpp | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/game/server/tf2/mortar_round.cpp b/game/server/tf2/mortar_round.cpp new file mode 100644 index 0000000..38f72b9 --- /dev/null +++ b/game/server/tf2/mortar_round.cpp @@ -0,0 +1,257 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "mortar_round.h" +#include "engine/IEngineSound.h" +#include "tf_gamerules.h" +#include "tf_team.h" + + + +// Damage CVars +ConVar weapon_mortar_shell_damage( "weapon_mortar_shell_damage","0", FCVAR_NONE, "Mortar's standard shell maximum damage" ); +ConVar weapon_mortar_shell_radius( "weapon_mortar_shell_radius","0", FCVAR_NONE, "Mortar's standard shell splash radius" ); +ConVar weapon_mortar_starburst_damage( "weapon_mortar_starburst_damage","0", FCVAR_NONE, "Mortar's starburst maximum damage" ); +ConVar weapon_mortar_starburst_radius( "weapon_mortar_starburst_radius","0", FCVAR_NONE, "Mortar's starburst splash radius" ); +ConVar weapon_mortar_cluster_shells( "weapon_mortar_cluster_shells","0", FCVAR_NONE, "Number of shells a mortar cluster round bursts into" ); + +//===================================================================================================== +// MORTAR ROUND +//===================================================================================================== +BEGIN_DATADESC( CMortarRound ) + + // Function Pointers + DEFINE_FUNCTION( MissileTouch ), + DEFINE_FUNCTION( FallThink ), + +END_DATADESC() + +LINK_ENTITY_TO_CLASS( mortar_round, CMortarRound ); +PRECACHE_WEAPON_REGISTER(mortar_round); + +CMortarRound::CMortarRound() +{ + m_pSmokeTrail = NULL; + m_pLauncher = NULL; + m_iRoundType = MA_SHELL; + UseClientSideAnimation(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMortarRound::Precache( void ) +{ + PrecacheModel( "models/weapons/w_grenade.mdl" ); + + PrecacheScriptSound( "MortarRound.StopSound" ); + PrecacheScriptSound( "MortarRound.IncomingSound" ); + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMortarRound::Spawn( void ) +{ + Precache(); + + SetMoveType( MOVETYPE_FLYGRAVITY ); + SetSolid( SOLID_BBOX ); + SetModel( "models/weapons/w_grenade.mdl" ); + UTIL_SetSize( this, vec3_origin, vec3_origin ); + + SetTouch( MissileTouch ); + SetCollisionGroup( TFCOLLISION_GROUP_WEAPON ); + + // Trail smoke + m_pSmokeTrail = SmokeTrail::CreateSmokeTrail(); + if ( m_pSmokeTrail ) + { + m_pSmokeTrail->m_SpawnRate = 90; + m_pSmokeTrail->m_ParticleLifetime = 1.5; + m_pSmokeTrail->m_StartColor.Init(0.0, 0.0, 0.0); + m_pSmokeTrail->m_EndColor.Init( 0.5,0.5,0.5 ); + m_pSmokeTrail->m_StartSize = 10; + m_pSmokeTrail->m_EndSize = 50; + m_pSmokeTrail->m_SpawnRadius = 1; + m_pSmokeTrail->m_MinSpeed = 15; + m_pSmokeTrail->m_MaxSpeed = 25; + m_pSmokeTrail->SetLifetime(15); + m_pSmokeTrail->FollowEntity( this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMortarRound::MissileTouch( CBaseEntity *pOther ) +{ + CMortarRound *pRound = dynamic_cast< CMortarRound* >(pOther); + if ( pRound ) + return; + + // Stop emitting smoke/sound + m_pSmokeTrail->SetEmit(false); + EmitSound( "MortarRound.StopSound" ); + + // Create an explosion. + if ( m_iRoundType == MA_STARBURST ) + { + // Small explosion, blind people in the area + float flBlind = 0; + + // Shift it up a bit for the explosion + SetLocalOrigin( GetAbsOrigin() + Vector(0,0,32) ); + CPASFilter filter( GetAbsOrigin() ); + te->Explosion( filter, 0.0, &GetAbsOrigin(), g_sModelIndexFireball, 3.0, 15, TE_EXPLFLAG_NONE, 512, 100 ); + RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), weapon_mortar_starburst_damage.GetFloat(), DMG_BLAST ), GetAbsOrigin(), weapon_mortar_starburst_radius.GetFloat(), CLASS_NONE, NULL ); + + // Blind all players nearby + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBaseTFPlayer *pPlayer = ToBaseTFPlayer( UTIL_PlayerByIndex(i) ); + if ( pPlayer ) + { + Vector vecSrc = pPlayer->EyePosition(); + Vector vecToTarget = (vecSrc - GetAbsOrigin()); + float flLength = VectorNormalize( vecToTarget ); + // If the player's looking at the grenade, blind him a lot + if ( flLength < 2048 ) + { + Vector forward, right, up; + AngleVectors( pPlayer->pl.v_angle, &forward, &right, &up ); + float flDot = DotProduct( vecToTarget, forward ); + +// Msg( "Dot: %f\n", flDot ); + + // Make sure it's in front of the player + if ( flDot < 0.0f ) + { + flDot = fabs( DotProduct(vecToTarget, right ) ) + fabs( DotProduct(vecToTarget, up ) ); + + // Open LOS? + trace_t tr; + UTIL_TraceLine( vecSrc, GetAbsOrigin(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); + if ( ( tr.fraction == 1.0f ) || ( tr.m_pEnt == pPlayer ) ) + { + flBlind = flDot; + } + else + { + // Blocked blind is only half as effective + flBlind = flDot * 0.5; + } + } + else if ( flLength < 512 ) + { + // Otherwise, if the player's near the grenade blind him a little + flBlind = 0.2; + } + + + // Flash the screen red + color32 white = {255,255,255, 255}; + white.a = MIN( (flBlind * 255), 255 ); + UTIL_ScreenFade( pPlayer, white, 0.3, 5.0, 0 ); + } + } + } + + UTIL_Remove( this ); + } + else + { + // Large explosion + + // Shift it up a bit for the explosion + SetLocalOrigin( GetAbsOrigin() + Vector(0,0,64) ); + CPASFilter filter( GetAbsOrigin() ); + te->Explosion( filter, 0.0, &GetAbsOrigin(), g_sModelIndexFireball, 10.0, 15, TE_EXPLFLAG_NONE, 512, 300 ); + RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), weapon_mortar_shell_damage.GetFloat(), DMG_BLAST ), GetAbsOrigin(), weapon_mortar_shell_radius.GetFloat(), CLASS_NONE, NULL ); + UTIL_Remove( this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Play a fall sound when the mortar round begins to fall +//----------------------------------------------------------------------------- +void CMortarRound::FallThink( void ) +{ + if ( m_pLauncher ) + { + CRecipientFilter filter; + filter.AddAllPlayers(); + EmitSound( filter, entindex(), "MortarRound.IncomingSound" ); + + // Cluster bombs split up in the air + if ( m_iRoundType == MA_CLUSTER ) + { + Vector forward, right; + QAngle angles; + VectorAngles( GetAbsVelocity(), angles ); + SetLocalAngles( angles ); + AngleVectors( GetLocalAngles(), &forward, &right, NULL ); + for ( int i = 0; i < weapon_mortar_cluster_shells.GetInt(); i++ ) + { + Vector vecVelocity = GetAbsVelocity(); + vecVelocity += forward * random->RandomFloat( -200, 200 ); + vecVelocity += right * random->RandomFloat( -200, 200 ); + + CMortarRound *pRound = CMortarRound::Create( GetAbsOrigin(), vecVelocity, GetOwnerEntity() ? GetOwnerEntity()->edict() : NULL ); + pRound->SetLauncher( m_pLauncher ); + pRound->ChangeTeam( GetTeamNumber() ); + pRound->m_iRoundType = MA_SHELL; + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Keep a pointer to the Launcher +//----------------------------------------------------------------------------- +void CMortarRound::SetLauncher( CVehicleMortar *pLauncher ) +{ + m_pLauncher = pLauncher; +} + +//----------------------------------------------------------------------------- +// Purpose: Set the point at which we should start playing the fall sound +//----------------------------------------------------------------------------- +void CMortarRound::SetFallTime( float flFallTime ) +{ + SetThink( FallThink ); + SetNextThink( gpGlobals->curtime + flFallTime ); +} + +//----------------------------------------------------------------------------- +// Purpose: Set the round's type +//----------------------------------------------------------------------------- +void CMortarRound::SetRoundType( int iRoundType ) +{ + m_iRoundType = iRoundType; +} + +//----------------------------------------------------------------------------- +// Purpose: Create a missile +//----------------------------------------------------------------------------- +CMortarRound* CMortarRound::Create( const Vector &vecOrigin, const Vector &vecVelocity, edict_t *pentOwner = NULL ) +{ + CMortarRound *pGrenade = (CMortarRound*)CreateEntityByName("mortar_round"); + + UTIL_SetOrigin( pGrenade, vecOrigin ); + pGrenade->SetOwnerEntity( Instance( pentOwner ) ); + pGrenade->Spawn(); + pGrenade->SetAbsVelocity( vecVelocity ); + QAngle angles; + VectorAngles( vecVelocity, angles ); + pGrenade->SetLocalAngles( angles ); + + return pGrenade; +} + |