mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-01-05 17:13:36 +08:00
312 lines
8.7 KiB
C++
312 lines
8.7 KiB
C++
#include "cbase.h"
|
|
#include "engine/IEngineSound.h"
|
|
#include "asw_shareddefs.h"
|
|
#include "basegrenade_shared.h"
|
|
#include "Sprite.h"
|
|
#include "asw_mortarbug_shell_shared.h"
|
|
#ifdef CLIENT_DLL
|
|
#include "c_asw_marine.h"
|
|
#include "particles_simple.h"
|
|
#include "idebugoverlaypanel.h"
|
|
#include "engine/IVDebugOverlay.h"
|
|
#include "baseparticleentity.h"
|
|
#define CASW_Marine C_ASW_Marine
|
|
#else
|
|
#include "asw_marine.h"
|
|
#include "iasw_spawnable_npc.h"
|
|
#include "IEffects.h"
|
|
#include "te_effect_dispatch.h"
|
|
#include "world.h"
|
|
#include "asw_util_shared.h"
|
|
#include "particle_parse.h"
|
|
#include "asw_boomer_blob.h"
|
|
#endif
|
|
#include "asw_gamerules.h"
|
|
#include "util_shared.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
#define SHELL_MODEL "models/swarm/MortarBugProjectile/MortarBugProjectile.mdl"
|
|
#define SHELL_AURA "mortar_shell_aura"
|
|
#define SHELL_WARN_DELAY 1.5f
|
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( ASW_Mortarbug_Shell, DT_ASW_Mortarbug_Shell );
|
|
|
|
BEGIN_NETWORK_TABLE( CASW_Mortarbug_Shell, DT_ASW_Mortarbug_Shell )
|
|
END_NETWORK_TABLE()
|
|
|
|
#ifdef GAME_DLL
|
|
|
|
LINK_ENTITY_TO_CLASS( asw_mortarbug_shell, CASW_Mortarbug_Shell );
|
|
PRECACHE_REGISTER( asw_mortarbug_shell );
|
|
|
|
BEGIN_DATADESC( CASW_Mortarbug_Shell )
|
|
DEFINE_FUNCTION( VShellTouch ),
|
|
DEFINE_THINKFUNC( ShellFlyThink ),
|
|
DEFINE_THINKFUNC( ShellThink ),
|
|
DEFINE_THINKFUNC( Detonate ),
|
|
END_DATADESC()
|
|
|
|
extern int g_sModelIndexFireball;
|
|
|
|
ConVar asw_mortarbug_shell_gravity("asw_mortarbug_shell_gravity", "0.8f", FCVAR_CHEAT, "Gravity of mortarbug shell");
|
|
ConVar asw_mortarbug_shell_fuse("asw_mortarbug_shell_fuse", "3.0f", FCVAR_CHEAT, "Time before mortarbug shell explodes");
|
|
|
|
CASW_Mortarbug_Shell::CASW_Mortarbug_Shell()
|
|
{
|
|
m_bDoScreenShake = false;
|
|
|
|
g_aExplosiveProjectiles.AddToTail( this );
|
|
}
|
|
|
|
CASW_Mortarbug_Shell::~CASW_Mortarbug_Shell()
|
|
{
|
|
g_aExplosiveProjectiles.FindAndRemove( this );
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::Precache( void )
|
|
{
|
|
BaseClass::Precache( );
|
|
|
|
PrecacheModel( SHELL_MODEL );
|
|
PrecacheParticleSystem( SHELL_AURA );
|
|
|
|
PrecacheScriptSound( "ASW_Boomer_Grenade.Explode" );
|
|
PrecacheScriptSound( "ASW_Boomer_Projectile.Spawned" );
|
|
PrecacheScriptSound( "ASW_Boomer_Projectile.ImpactHard" );
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::Spawn( void )
|
|
{
|
|
Precache( );
|
|
|
|
SetModel( SHELL_MODEL );
|
|
SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE );
|
|
SetSequence( LookupSequence( "MortarBugProjectile_Closed" ) );
|
|
|
|
// TODO:
|
|
m_flDamage = 50;
|
|
m_DmgRadius = 220.0f;
|
|
|
|
//Ignite(3.0, false, 0, false);
|
|
|
|
m_takedamage = DAMAGE_NO;
|
|
|
|
m_bModelOpening = false;
|
|
|
|
EmitSound( "ASW_Boomer_Projectile.Spawned" );
|
|
|
|
SetSize( -Vector(4,4,4), Vector(4,4,4) );
|
|
SetSolid( SOLID_BBOX );
|
|
SetGravity( asw_mortarbug_shell_gravity.GetFloat() );
|
|
|
|
SetCollisionGroup( COLLISION_GROUP_DEBRIS ); // TODO: change this to a custom collision group?
|
|
SetTouch( &CASW_Mortarbug_Shell::VShellTouch );
|
|
|
|
// TODO: Have a sound for the shell?
|
|
//EmitSound( "ASWGrenade.Alarm" ); // 3 second warning sound
|
|
|
|
m_vecLastPosition = vec3_origin;
|
|
SetThink( &CASW_Mortarbug_Shell::ShellFlyThink );
|
|
SetNextThink( gpGlobals->curtime + 0.05f );
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::ShellFlyThink()
|
|
{
|
|
// face the direction we're moving
|
|
Vector vecForward = GetAbsVelocity();
|
|
VectorNormalize(vecForward);
|
|
QAngle angles;
|
|
VectorAngles( vecForward, angles );
|
|
angles[PITCH] -= 90; // TODO: rotate pitch properly?
|
|
SetAbsAngles( angles );
|
|
|
|
SetNextThink( gpGlobals->curtime + 0.05f );
|
|
|
|
|
|
// check for not moving
|
|
float flDist = ( GetAbsOrigin() - m_vecLastPosition ).Length();
|
|
if ( flDist < 5.0f )
|
|
{
|
|
SetFuseLength( asw_mortarbug_shell_fuse.GetFloat() + RandomFloat( -0.3f, 0.3f ) );
|
|
}
|
|
m_vecLastPosition = GetAbsOrigin();
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::ShellThink( )
|
|
{
|
|
if ( !m_bModelOpening && gpGlobals->curtime >= (m_fDetonateTime - SHELL_WARN_DELAY) )
|
|
{
|
|
// we are one second from detonating, commit to detonating and start the opening sequence
|
|
// regardless of anyone nearby
|
|
m_bModelOpening = true;
|
|
ResetSequence( LookupSequence( "MortarBugProjectile_Opening" ) );
|
|
|
|
CEffectData data;
|
|
data.m_vOrigin = GetAbsOrigin();
|
|
CPASFilter filter( data.m_vOrigin );
|
|
filter.SetIgnorePredictionCull(true);
|
|
DispatchParticleEffect( "mortar_grenade_open", PATTACH_ABSORIGIN_FOLLOW, this, -1, false, -1, &filter );
|
|
}
|
|
|
|
// if we exceeded the detonation time, just detonate
|
|
if ( gpGlobals->curtime >= m_fDetonateTime )
|
|
{
|
|
Detonate();
|
|
return;
|
|
}
|
|
|
|
// if the model is opening, do the animation advance
|
|
if ( m_bModelOpening )
|
|
{
|
|
StudioFrameAdvance();
|
|
SetNextThink( gpGlobals->curtime );
|
|
return;
|
|
}
|
|
|
|
if ( m_fDetonateTime <= gpGlobals->curtime + 0.1f )
|
|
{
|
|
SetThink( &CASW_Mortarbug_Shell::Detonate );
|
|
SetNextThink( m_fDetonateTime );
|
|
}
|
|
else
|
|
{
|
|
SetThink( &CASW_Mortarbug_Shell::ShellThink );
|
|
SetNextThink( gpGlobals->curtime + 0.1f );
|
|
}
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::VShellTouch( CBaseEntity *pOther )
|
|
{
|
|
if (!pOther || pOther == GetOwnerEntity())
|
|
return;
|
|
|
|
if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) )
|
|
return;
|
|
|
|
// make sure we don't die on things we shouldn't
|
|
if (!ASWGameRules() || !ASWGameRules()->ShouldCollide(GetCollisionGroup(), pOther->GetCollisionGroup()))
|
|
return;
|
|
|
|
// trace to latch onto the thing we collided with
|
|
Vector vecForward = GetAbsVelocity();
|
|
VectorNormalize(vecForward);
|
|
trace_t tr;
|
|
UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60 * vecForward, MASK_SOLID,
|
|
this, GetCollisionGroup(), &tr);
|
|
|
|
if ( !tr.DidHit() )
|
|
return;
|
|
|
|
QAngle angles;
|
|
VectorAngles( tr.plane.normal, angles );
|
|
angles[PITCH] += 90; // TODO: rotate pitch properly?
|
|
SetAbsAngles( angles );
|
|
SetAbsVelocity( vec3_origin );
|
|
UTIL_SetOrigin( this, tr.endpos );
|
|
//SetParent( tr.m_pEnt );
|
|
|
|
EmitSound( "ASW_Boomer_Projectile.ImpactHard" );
|
|
|
|
SetTouch( NULL );
|
|
|
|
SetFuseLength( asw_mortarbug_shell_fuse.GetFloat() + RandomFloat( -0.3f, 0.3f ) );
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::SetFuseLength(float fSeconds)
|
|
{
|
|
m_fDetonateTime = gpGlobals->curtime + fSeconds;
|
|
|
|
SetThink( &CASW_Mortarbug_Shell::ShellThink );
|
|
SetNextThink( gpGlobals->curtime );
|
|
|
|
//SetSequence( LookupSequence( "MortarBugProjectile_Opening" ) );
|
|
//SetThink( &CASW_Mortarbug_Shell::Detonate );
|
|
//SetNextThink( gpGlobals->curtime + fSeconds );
|
|
}
|
|
|
|
CASW_Mortarbug_Shell* CASW_Mortarbug_Shell::CreateShell( const Vector &vecOrigin, const Vector &vecForward, CBaseEntity *pOwner )
|
|
{
|
|
CASW_Mortarbug_Shell *pShell = (CASW_Mortarbug_Shell *)CreateEntityByName( "asw_mortarbug_shell" );
|
|
QAngle angles;
|
|
VectorAngles( vecForward, angles );
|
|
pShell->SetAbsAngles( angles );
|
|
UTIL_SetOrigin( pShell, vecOrigin );
|
|
pShell->Spawn();
|
|
pShell->SetOwnerEntity( pOwner );
|
|
UTIL_SetOrigin( pShell, vecOrigin );
|
|
|
|
return pShell;
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::Detonate()
|
|
{
|
|
m_takedamage = DAMAGE_NO;
|
|
|
|
// explosion effects
|
|
DispatchParticleEffect( "boomer_drop_explosion", GetAbsOrigin(), Vector( m_DmgRadius, 0.0f, 0.0f ), QAngle( 0.0f, 0.0f, 0.0f ) );
|
|
EmitSound( "ASW_Boomer_Grenade.Explode" );
|
|
|
|
Vector vecForward = GetAbsVelocity();
|
|
VectorNormalize(vecForward);
|
|
trace_t tr;
|
|
UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SHOT,
|
|
this, COLLISION_GROUP_NONE, &tr);
|
|
|
|
if ((tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0))
|
|
{
|
|
// non-world needs smaller decals
|
|
if( tr.m_pEnt && !tr.m_pEnt->IsNPC() )
|
|
{
|
|
UTIL_DecalTrace( &tr, "SmallScorch" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UTIL_DecalTrace( &tr, "Scorch" );
|
|
}
|
|
|
|
ScreenShake_t shake;
|
|
shake.direction = Vector( 0, 0, 1 );
|
|
shake.amplitude = 40.0f;
|
|
shake.duration = 0.3f;
|
|
shake.frequency = 1.0f;
|
|
shake.command = SHAKE_START;
|
|
UTIL_ASW_ScreenPunch( GetAbsOrigin(), 350.0f, shake );
|
|
|
|
RadiusDamage ( CTakeDamageInfo( this, GetOwnerEntity(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL );
|
|
|
|
UTIL_Remove( this );
|
|
}
|
|
|
|
#endif // GAME_DLL
|
|
|
|
|
|
|
|
#ifdef CLIENT_DLL
|
|
|
|
CASW_Mortarbug_Shell::CASW_Mortarbug_Shell()
|
|
{
|
|
|
|
}
|
|
|
|
void CASW_Mortarbug_Shell::PostDataUpdate( DataUpdateType_t updateType )
|
|
{
|
|
BaseClass::PostDataUpdate(updateType);
|
|
// If this entity was new, then latch in various values no matter what.
|
|
if ( updateType == DATA_UPDATE_CREATED )
|
|
{
|
|
CNewParticleEffect *pBurningEffect = ParticleProp()->Create( SHELL_AURA, PATTACH_ABSORIGIN_FOLLOW );
|
|
if (pBurningEffect)
|
|
{
|
|
ParticleProp()->AddControlPoint( pBurningEffect, 1, this, PATTACH_ABSORIGIN_FOLLOW );
|
|
pBurningEffect->SetControlPoint( 0, GetAbsOrigin() );
|
|
pBurningEffect->SetControlPoint( 1, GetAbsOrigin() );
|
|
pBurningEffect->SetControlPointEntity( 0, this );
|
|
pBurningEffect->SetControlPointEntity( 1, this );
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // CLIENT_DLL
|