You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
8.4 KiB
312 lines
8.4 KiB
#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
|