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,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user