Files
DoomRTX/neo/prey/Prey/game_fixedpod.cpp
2026-05-05 15:01:01 -07:00

210 lines
6.2 KiB
C++

// Game_FixedPod.cpp
//
// non-moving exploding pod
#include "precompiled.h"
#pragma hdrstop
#include "prey_local.h"
const idEventDef EV_ExplodedBy("<explodedby>", "e");
const idEventDef EV_SpawnShrapnel("<spawnDebris>");
CLASS_DECLARATION(idEntity, hhFixedPod)
EVENT( EV_Activate, hhFixedPod::Event_Trigger )
EVENT( EV_ExplodeDamage, hhFixedPod::Event_ExplodeDamage )
EVENT( EV_ExplodedBy, hhFixedPod::Event_ExplodedBy )
EVENT( EV_SpawnShrapnel, hhFixedPod::Event_SpawnDebris )
EVENT( EV_Broadcast_AssignFx, hhFixedPod::Event_AssignFx )
END_CLASS
hhFixedPod::hhFixedPod() {
fx = NULL;
}
//==========================================================================
//
// hhFixedPod::Spawn
//
//==========================================================================
void hhFixedPod::Spawn(void) {
fl.takedamage = true;
// setup the clipModel
GetPhysics()->SetContents( CONTENTS_SOLID );
// Spawn the energy beam
hhBeamSystem *beam = hhBeamSystem::SpawnBeam( GetOrigin(), spawnArgs.GetString("beam") );
if( beam ) {
beam->SetOrigin(GetPhysics()->GetOrigin() - GetPhysics()->GetAxis()[2]*28);
beam->SetAxis(GetPhysics()->GetAxis());
if (IsBound() || spawnArgs.GetBool("force_bind")) {
beam->Bind(this, false); // Only bind if we will be moving
}
beam->SetTargetLocation(beam->GetPhysics()->GetOrigin() + GetPhysics()->GetAxis()[2] * 56);
// Bound entities automatically removed upon destruction
}
hhFxInfo fxInfo;
if (IsBound() || spawnArgs.GetBool("force_bind")) {
fxInfo.SetEntity( this ); // Only bind if we will be moving
}
fxInfo.RemoveWhenDone( false );
fxInfo.NoRemoveWhenUnbound( true );
BroadcastFxInfo( spawnArgs.GetString("fx_energybeam"), GetOrigin(), GetAxis(), &fxInfo, &EV_Broadcast_AssignFx );
StartSound( "snd_idle", SND_CHANNEL_IDLE, 0, true, NULL );
}
//==========================================================================
//
// hhFixedPod::Event_AssignFxSmoke
//
//==========================================================================
void hhFixedPod::Event_AssignFx( hhEntityFx* fx ) {
this->fx = fx;
}
void hhFixedPod::Save(idSaveGame *savefile) const {
fx.Save(savefile);
}
void hhFixedPod::Restore( idRestoreGame *savefile ) {
fx.Restore(savefile);
}
//==========================================================================
//
// hhFixedPod::Killed
//
//==========================================================================
void hhFixedPod::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
fl.takedamage = false;
// Activate targets
ActivateTargets( attacker );
GetPhysics()->SetContents( 0 );
// Need to post an event because already in physics code now, can't nest a projectile spawn from within physics code
// currently, because rigid body physics ::Evaluate is not reentrant friendly (has a static timer)
PostEventMS( &EV_ExplodedBy, 0, attacker );
}
//==========================================================================
///
// hhFixedPod::Explode
//
//==========================================================================
void hhFixedPod::Explode( idEntity *attacker ) {
hhFxInfo fxInfo;
if (fx.IsValid()) {
fx->Hide();
fx->PostEventMS(&EV_Remove, 0);
}
// Spawn explosion
StopSound( SND_CHANNEL_IDLE, true );
StartSound( "snd_explode", SND_CHANNEL_ANY, 0, true, NULL );
fxInfo.SetNormal( idVec3(0.0f, 0.0f, 1.0f) );
fxInfo.RemoveWhenDone( true );
BroadcastFxInfoPrefixed( "fx_detonate", GetOrigin(), GetAxis(), &fxInfo );
Hide();
PostEventMS( &EV_SpawnShrapnel, 10 );
PostEventMS( &EV_ExplodeDamage, 250, attacker ); // NOTE: This even MUST occur before the remove event
PostEventMS( &EV_Remove, 500 ); // Remove after a small delay to allow sound commands to execute
}
//==========================================================================
//
// hhFixedPod::SpawnDebris
//
//==========================================================================
void hhFixedPod::SpawnDebris() {
idEntity* ent = NULL;
idVec3 launchDir;
int amount = 0;
idDebris* debris = NULL;
const idDict *dict = NULL;
int numShrapnel = spawnArgs.GetInt( "debris_count" );
if( !numShrapnel ) {
return;
}
for( const idKeyValue* kv = spawnArgs.MatchPrefix("def_debris", NULL); kv; kv = spawnArgs.MatchPrefix("def_debris", kv) ) {
if( !kv->GetValue().Length() ) {
continue;
}
dict = gameLocal.FindEntityDefDict( kv->GetValue().c_str(), false );
if( !dict ) {
continue;
}
amount = hhMath::hhMax( 1, gameLocal.random.RandomInt(numShrapnel) );
for ( int i = 0; i < amount; i++ ) {
launchDir = hhUtils::RandomVector();
launchDir.Normalize();
gameLocal.SpawnEntityDef( *dict, &ent );
if ( !ent || !ent->IsType( idDebris::Type ) ) {
gameLocal.Error( "'%s' is not an idDebris", kv->GetValue().c_str() );
}
debris = static_cast<idDebris *>(ent);
debris->Create( this, GetOrigin(), launchDir.ToMat3() );
debris->Launch();
}
}
}
//==========================================================================
//
// hhFixedPod::Event_ExplodeDamage
//
// Applies the radius damage slightly after the actual explosion, so that
// when one explodes it will cascade and explode other fixed pods.
//==========================================================================
void hhFixedPod::Event_ExplodeDamage( idEntity *attacker ) {
gameLocal.RadiusDamage( GetPhysics()->GetOrigin(), this, attacker, this, this, spawnArgs.GetString("def_explodedamage") );
}
//==========================================================================
//
// hhFixedPod::Event_ExplodedBy
//
//==========================================================================
void hhFixedPod::Event_ExplodedBy( idEntity *activator ) {
Explode(activator);
}
//==========================================================================
//
// hhFixedPod::Event_Trigger
//
//==========================================================================
void hhFixedPod::Event_Trigger( idEntity *activator ) {
Explode(activator);
}
//==========================================================================
//
// hhFixedPod::Event_SpawnDebris
//
//==========================================================================
void hhFixedPod::Event_SpawnDebris() {
SpawnDebris();
}