987 lines
24 KiB
Plaintext
987 lines
24 KiB
Plaintext
#include common_scripts\utility;
|
|
|
|
/*
|
|
|
|
Handles Old-School exploders. This is coupled with _createfx and _fx since a Radiant Created "exploder" can trigger a createfx created effect.
|
|
|
|
This Script is legacy, tried and true, It eats up entites when using script_brushmodel swapping and a lot of script_models and the damage triggers.
|
|
|
|
We should in a future game consider some entiity optimization in code. A way to Join models and brushes as one entity would be key.
|
|
|
|
*/
|
|
|
|
setup_individual_exploder( ent )
|
|
{
|
|
exploder_num = ent.script_exploder;
|
|
if ( !IsDefined( level.exploders[ exploder_num ] ) )
|
|
{
|
|
level.exploders[ exploder_num ] = [];
|
|
}
|
|
|
|
targetname = ent.targetname;
|
|
if ( !IsDefined( targetname ) )
|
|
targetname = "";
|
|
|
|
level.exploders[ exploder_num ][ level.exploders[ exploder_num ].size ] = ent;
|
|
if ( exploder_model_starts_hidden( ent ) )
|
|
{
|
|
ent Hide();
|
|
return;
|
|
}
|
|
|
|
if ( exploder_model_is_damaged_model( ent ) )
|
|
{
|
|
ent Hide();
|
|
ent NotSolid();
|
|
if ( IsDefined( ent.spawnflags ) && ( ent.spawnflags & 1 ) )
|
|
{
|
|
if ( IsDefined( ent.script_disconnectpaths ) )
|
|
{
|
|
ent ConnectPaths();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( exploder_model_is_chunk( ent ) )
|
|
{
|
|
ent Hide();
|
|
ent NotSolid();
|
|
if ( IsDefined( ent.spawnflags ) && ( ent.spawnflags & 1 ) )
|
|
ent ConnectPaths();
|
|
return;
|
|
}
|
|
}
|
|
|
|
setupExploders()
|
|
{
|
|
level.exploders = [];
|
|
|
|
// Hide exploder models.
|
|
ents = GetEntArray( "script_brushmodel", "classname" );
|
|
smodels = GetEntArray( "script_model", "classname" );
|
|
for ( i = 0; i < smodels.size; i++ )
|
|
ents[ ents.size ] = smodels[ i ];
|
|
|
|
foreach ( ent in ents )
|
|
{
|
|
if ( IsDefined( ent.script_prefab_exploder ) )
|
|
ent.script_exploder = ent.script_prefab_exploder;
|
|
|
|
if ( IsDefined( ent.masked_exploder ) )
|
|
continue;
|
|
|
|
if ( IsDefined( ent.script_exploder ) )
|
|
{
|
|
setup_individual_exploder( ent );
|
|
}
|
|
}
|
|
|
|
script_exploders = [];
|
|
|
|
potentialExploders = GetEntArray( "script_brushmodel", "classname" );
|
|
for ( i = 0; i < potentialExploders.size; i++ )
|
|
{
|
|
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
|
|
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
|
|
|
|
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
|
|
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
|
|
}
|
|
|
|
potentialExploders = GetEntArray( "script_model", "classname" );
|
|
for ( i = 0; i < potentialExploders.size; i++ )
|
|
{
|
|
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
|
|
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
|
|
|
|
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
|
|
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
|
|
}
|
|
|
|
potentialExploders = GetEntArray( "item_health", "classname" );
|
|
for ( i = 0; i < potentialExploders.size; i++ )
|
|
{
|
|
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
|
|
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
|
|
|
|
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
|
|
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
|
|
}
|
|
|
|
|
|
potentialExploders = level.struct;
|
|
for ( i = 0; i < potentialExploders.size; i++ )
|
|
{
|
|
if ( !IsDefined( potentialExploders[ i ] ) )
|
|
continue; // these must be getting deleted somewhere else?
|
|
if ( IsDefined( potentialExploders[ i ].script_prefab_exploder ) )
|
|
potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
|
|
|
|
if ( IsDefined( potentialExploders[ i ].script_exploder ) )
|
|
{
|
|
if ( !IsDefined( potentialExploders[ i ].angles ) )
|
|
potentialExploders[ i ].angles = ( 0, 0, 0 );
|
|
script_exploders[ script_exploders.size ] = potentialExploders[ i ];
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if ( !IsDefined( level.createFXent ) )
|
|
level.createFXent = [];
|
|
|
|
acceptableTargetnames = [];
|
|
acceptableTargetnames[ "exploderchunk visible" ] = true;
|
|
acceptableTargetnames[ "exploderchunk" ] = true;
|
|
acceptableTargetnames[ "exploder" ] = true;
|
|
|
|
thread setup_flag_exploders();
|
|
|
|
for ( i = 0; i < script_exploders.size; i++ )
|
|
{
|
|
exploder = script_exploders[ i ];
|
|
|
|
|
|
ent = createExploder( exploder.script_fxid );
|
|
ent.v = [];
|
|
ent.v[ "origin" ] = exploder.origin;
|
|
ent.v[ "angles" ] = exploder.angles;
|
|
ent.v[ "delay" ] = exploder.script_delay;
|
|
ent.v[ "delay_post" ] = exploder.script_delay_post;
|
|
ent.v[ "firefx" ] = exploder.script_firefx;
|
|
ent.v[ "firefxdelay" ] = exploder.script_firefxdelay;
|
|
ent.v[ "firefxsound" ] = exploder.script_firefxsound;
|
|
ent.v[ "earthquake" ] = exploder.script_earthquake;
|
|
ent.v[ "rumble" ] = exploder.script_rumble;
|
|
ent.v[ "damage" ] = exploder.script_damage;
|
|
ent.v[ "damage_radius" ] = exploder.script_radius;
|
|
ent.v[ "soundalias" ] = exploder.script_soundalias;
|
|
ent.v[ "repeat" ] = exploder.script_repeat;
|
|
ent.v[ "delay_min" ] = exploder.script_delay_min;
|
|
ent.v[ "delay_max" ] = exploder.script_delay_max;
|
|
ent.v[ "target" ] = exploder.target;
|
|
ent.v[ "ender" ] = exploder.script_ender;
|
|
ent.v[ "physics" ] = exploder.script_physics;
|
|
ent.v[ "type" ] = "exploder";
|
|
// ent.v[ "worldfx" ] = true;
|
|
if ( !IsDefined( exploder.script_fxid ) )
|
|
ent.v[ "fxid" ] = "No FX";
|
|
else
|
|
ent.v[ "fxid" ] = exploder.script_fxid;
|
|
ent.v [ "exploder" ] = exploder.script_exploder;
|
|
AssertEx( IsDefined( exploder.script_exploder ), "Exploder at origin " + exploder.origin + " has no script_exploder" );
|
|
if ( IsDefined( level.createFXexploders ) )
|
|
{ // if we're using the optimized lookup, add it in the proper place
|
|
ary = level.createFXexploders[ ent.v[ "exploder" ] ];
|
|
if ( !IsDefined( ary ) )
|
|
ary = [];
|
|
ary[ ary.size ] = ent;
|
|
level.createFXexploders[ ent.v[ "exploder" ] ] = ary;
|
|
}
|
|
|
|
if ( !IsDefined( ent.v[ "delay" ] ) )
|
|
ent.v[ "delay" ] = 0;
|
|
|
|
if ( IsDefined( exploder.target ) )
|
|
{
|
|
get_ent = GetEntArray( ent.v[ "target" ], "targetname" )[ 0 ];
|
|
if ( IsDefined( get_ent ) )
|
|
{
|
|
org = get_ent.origin;
|
|
ent.v[ "angles" ] = VectorToAngles( org - ent.v[ "origin" ] );
|
|
}
|
|
else
|
|
{
|
|
get_ent = get_target_ent( ent.v[ "target" ] );
|
|
if ( IsDefined( get_ent ) )
|
|
{
|
|
org = get_ent.origin;
|
|
ent.v[ "angles" ] = VectorToAngles( org - ent.v[ "origin" ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
// this basically determines if its a brush / model exploder or not
|
|
if ( !IsDefined( exploder.code_classname ) )
|
|
{
|
|
//I assume everything that doesn't have a code_classname is a struct that needs a script_modelname to make its way into the game
|
|
ent.model = exploder;
|
|
if ( IsDefined( ent.model.script_modelname ) )
|
|
{
|
|
PreCacheModel( ent.model.script_modelname );
|
|
}
|
|
}
|
|
else if ( exploder.code_classname == "script_brushmodel" || IsDefined( exploder.model ) )
|
|
{
|
|
ent.model = exploder;
|
|
ent.model.disconnect_paths = exploder.script_disconnectpaths;
|
|
}
|
|
|
|
if ( IsDefined( exploder.targetname ) && IsDefined( acceptableTargetnames[ exploder.targetname ] ) )
|
|
ent.v[ "exploder_type" ] = exploder.targetname;
|
|
else
|
|
ent.v[ "exploder_type" ] = "normal";
|
|
|
|
if ( IsDefined( exploder.masked_exploder ) )
|
|
{
|
|
ent.v[ "masked_exploder" ] = exploder.model;
|
|
ent.v[ "masked_exploder_spawnflags" ] = exploder.spawnflags;
|
|
ent.v[ "masked_exploder_script_disconnectpaths" ] = exploder.script_disconnectpaths;
|
|
exploder Delete();
|
|
}
|
|
ent common_scripts\_createfx::post_entity_creation_function();
|
|
}
|
|
}
|
|
|
|
setup_flag_exploders()
|
|
{
|
|
// createfx has to do 2 waittillframeends so we have to do 3 to make sure this comes after
|
|
// createfx is all done setting up. Who will raise the gambit to 4?
|
|
waittillframeend;
|
|
waittillframeend;
|
|
waittillframeend;
|
|
exploder_flags = [];
|
|
|
|
foreach ( ent in level.createFXent )
|
|
{
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
theFlag = ent.v[ "flag" ];
|
|
|
|
if ( !IsDefined( theFlag ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( theFlag == "nil" )
|
|
{
|
|
ent.v[ "flag" ] = undefined;
|
|
}
|
|
|
|
exploder_flags[ theFlag ] = true;
|
|
}
|
|
|
|
foreach ( msg, _ in exploder_flags )
|
|
{
|
|
thread exploder_flag_wait( msg );
|
|
}
|
|
}
|
|
|
|
exploder_flag_wait( msg )
|
|
{
|
|
if ( !flag_exist( msg ) )
|
|
flag_init( msg );
|
|
flag_wait( msg );
|
|
|
|
foreach ( ent in level.createFXent )
|
|
{
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
theFlag = ent.v[ "flag" ];
|
|
|
|
if ( !IsDefined( theFlag ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( theFlag != msg )
|
|
continue;
|
|
ent activate_individual_exploder();
|
|
}
|
|
}
|
|
|
|
exploder_model_is_damaged_model( ent )
|
|
{
|
|
return( IsDefined( ent.targetname ) ) && ( ent.targetname == "exploder" );
|
|
}
|
|
|
|
exploder_model_starts_hidden( ent )
|
|
{
|
|
return( ent.model == "fx" ) && ( ( !IsDefined( ent.targetname ) ) || ( ent.targetname != "exploderchunk" ) );
|
|
}
|
|
|
|
exploder_model_is_chunk( ent )
|
|
{
|
|
return( IsDefined( ent.targetname ) ) && ( ent.targetname == "exploderchunk" );
|
|
}
|
|
|
|
show_exploder_models_proc( num )
|
|
{
|
|
num += "";
|
|
|
|
//prof_begin( "hide_exploder" );
|
|
if ( IsDefined( level.createFXexploders ) )
|
|
{ // do optimized flavor if available
|
|
exploders = level.createFXexploders[ num ];
|
|
if ( IsDefined( exploders ) )
|
|
{
|
|
foreach ( ent in exploders )
|
|
{
|
|
//pre exploded geo. don't worry about deleted exploder geo..
|
|
if ( ! exploder_model_starts_hidden( ent.model )
|
|
&& ! exploder_model_is_damaged_model( ent.model )
|
|
&& !exploder_model_is_chunk( ent.model ) )
|
|
{
|
|
ent.model Show();
|
|
}
|
|
|
|
//exploded geo and should be shown
|
|
if ( IsDefined( ent.brush_shown ) )
|
|
ent.model Show();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < level.createFXent.size; i++ )
|
|
{
|
|
ent = level.createFXent[ i ];
|
|
if ( !IsDefined( ent ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
|
|
// make the exploder actually removed the array instead?
|
|
if ( !IsDefined( ent.v[ "exploder" ] ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "exploder" ] + "" != num )
|
|
continue;
|
|
|
|
if ( IsDefined( ent.model ) )
|
|
{
|
|
|
|
//pre exploded geo. don't worry about deleted exploder geo..
|
|
if ( ! exploder_model_starts_hidden( ent.model ) && ! exploder_model_is_damaged_model( ent.model ) && !exploder_model_is_chunk( ent.model ) )
|
|
{
|
|
ent.model Show();
|
|
}
|
|
|
|
//exploded geo and should be shown
|
|
if ( IsDefined( ent.brush_shown ) )
|
|
ent.model Show();
|
|
|
|
}
|
|
}
|
|
}
|
|
//prof_end( "hide_exploder" );
|
|
}
|
|
|
|
stop_exploder_proc( num )
|
|
{
|
|
num += "";
|
|
|
|
if ( IsDefined( level.createFXexploders ) )
|
|
{ // do optimized flavor if available
|
|
exploders = level.createFXexploders[ num ];
|
|
if ( IsDefined( exploders ) )
|
|
{
|
|
foreach ( ent in exploders )
|
|
{
|
|
if ( !IsDefined( ent.looper ) )
|
|
continue;
|
|
|
|
ent.looper Delete();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < level.createFXent.size; i++ )
|
|
{
|
|
ent = level.createFXent[ i ];
|
|
if ( !IsDefined( ent ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
|
|
// make the exploder actually removed the array instead?
|
|
if ( !IsDefined( ent.v[ "exploder" ] ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "exploder" ] + "" != num )
|
|
continue;
|
|
|
|
if ( !IsDefined( ent.looper ) )
|
|
continue;
|
|
|
|
ent.looper Delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
get_exploder_array_proc( msg )
|
|
{
|
|
msg += "";
|
|
array = [];
|
|
if ( IsDefined( level.createFXexploders ) )
|
|
{ // do optimized flavor if available
|
|
exploders = level.createFXexploders[ msg ];
|
|
if ( IsDefined( exploders ) )
|
|
{
|
|
array = exploders;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach ( ent in level.createFXent )
|
|
{
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
|
|
// make the exploder actually removed the array instead?
|
|
if ( !IsDefined( ent.v[ "exploder" ] ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "exploder" ] + "" != msg )
|
|
continue;
|
|
|
|
array[ array.size ] = ent;
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
hide_exploder_models_proc( num )
|
|
{
|
|
num += "";
|
|
|
|
//prof_begin( "hide_exploder" );
|
|
|
|
if ( IsDefined( level.createFXexploders ) )
|
|
{ // do optimized flavor if available
|
|
exploders = level.createFXexploders[ num ];
|
|
if ( IsDefined( exploders ) )
|
|
{
|
|
foreach ( ent in exploders )
|
|
{
|
|
if ( IsDefined( ent.model ) )
|
|
ent.model Hide();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < level.createFXent.size; i++ )
|
|
{
|
|
ent = level.createFXent[ i ];
|
|
if ( !IsDefined( ent ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
|
|
// make the exploder actually removed the array instead?
|
|
if ( !IsDefined( ent.v[ "exploder" ] ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "exploder" ] + "" != num )
|
|
continue;
|
|
|
|
|
|
if ( IsDefined( ent.model ) )
|
|
ent.model Hide();
|
|
|
|
}
|
|
}
|
|
//prof_end( "hide_exploder" );
|
|
}
|
|
|
|
delete_exploder_proc( num )
|
|
{
|
|
num += "";
|
|
|
|
//prof_begin( "delete_exploder" );
|
|
if ( IsDefined( level.createFXexploders ) )
|
|
{ // do optimized flavor if available
|
|
exploders = level.createFXexploders[ num ];
|
|
if ( IsDefined( exploders ) )
|
|
{
|
|
foreach ( ent in exploders )
|
|
{
|
|
if ( IsDefined( ent.model ) )
|
|
ent.model Delete();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0; i < level.createFXent.size; i++ )
|
|
{
|
|
ent = level.createFXent[ i ];
|
|
if ( !IsDefined( ent ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
|
|
// make the exploder actually removed the array instead?
|
|
if ( !IsDefined( ent.v[ "exploder" ] ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "exploder" ] + "" != num )
|
|
continue;
|
|
|
|
if ( IsDefined( ent.model ) )
|
|
ent.model Delete();
|
|
}
|
|
}
|
|
//ends trigger threads.
|
|
level notify( "killexplodertridgers" + num );
|
|
|
|
//prof_end( "delete_exploder" );
|
|
}
|
|
|
|
exploder_damage()
|
|
{
|
|
if ( IsDefined( self.v[ "delay" ] ) )
|
|
delay = self.v[ "delay" ];
|
|
else
|
|
delay = 0;
|
|
|
|
if ( IsDefined( self.v[ "damage_radius" ] ) )
|
|
radius = self.v[ "damage_radius" ];
|
|
else
|
|
radius = 128;
|
|
|
|
damage = self.v[ "damage" ];
|
|
origin = self.v[ "origin" ];
|
|
|
|
wait( delay );
|
|
|
|
if ( IsDefined( level.custom_radius_damage_for_exploders ) )
|
|
[[ level.custom_radius_damage_for_exploders ]]( origin, radius, damage );
|
|
else
|
|
// Range, max damage, min damage
|
|
RadiusDamage( origin, radius, damage, damage );
|
|
}
|
|
|
|
activate_individual_exploder_proc()
|
|
{
|
|
if ( IsDefined( self.v[ "firefx" ] ) )
|
|
self thread fire_effect();
|
|
|
|
if ( IsDefined( self.v[ "fxid" ] ) && self.v[ "fxid" ] != "No FX" )
|
|
self thread cannon_effect();
|
|
else
|
|
if ( IsDefined( self.v[ "soundalias" ] ) && self.v[ "soundalias" ] != "nil" )
|
|
self thread sound_effect();
|
|
|
|
if ( IsDefined( self.v[ "loopsound" ] ) && self.v[ "loopsound" ] != "nil" )
|
|
self thread effect_loopsound();
|
|
|
|
if ( IsDefined( self.v[ "damage" ] ) )
|
|
self thread exploder_damage();
|
|
|
|
if ( IsDefined( self.v[ "earthquake" ] ) )
|
|
self thread exploder_earthquake();
|
|
|
|
if ( IsDefined( self.v[ "rumble" ] ) )
|
|
self thread exploder_rumble();
|
|
|
|
if ( self.v[ "exploder_type" ] == "exploder" )
|
|
self thread brush_show();
|
|
else
|
|
if ( ( self.v[ "exploder_type" ] == "exploderchunk" ) || ( self.v[ "exploder_type" ] == "exploderchunk visible" ) )
|
|
self thread brush_throw();
|
|
else
|
|
self thread brush_delete();
|
|
}
|
|
|
|
brush_delete()
|
|
{
|
|
// if( ent.v[ "exploder_type" ] != "normal" && !isdefined( ent.v[ "fxid" ] ) && !isdefined( ent.v[ "soundalias" ] ) )
|
|
// if( !isdefined( ent.script_fxid ) )
|
|
|
|
num = self.v[ "exploder" ];
|
|
if ( IsDefined( self.v[ "delay" ] ) )
|
|
wait( self.v[ "delay" ] );
|
|
else
|
|
wait( 0.05 ); // so it disappears after the replacement appears
|
|
|
|
if ( !IsDefined( self.model ) )
|
|
return;
|
|
|
|
|
|
Assert( IsDefined( self.model ) );
|
|
|
|
if ( IsDefined( self.model.classname ) ) // script_struct support - Nate -- self is always a struct so it will never have a classname, using self.model instead -Carlos
|
|
if ( isSP() && ( self.model.spawnflags & 1 ) )
|
|
self.model call [[ level.connectPathsFunction ]]();
|
|
|
|
if ( level.createFX_enabled )
|
|
{
|
|
if ( IsDefined( self.exploded ) )
|
|
return;
|
|
|
|
self.exploded = true;
|
|
self.model Hide();
|
|
self.model NotSolid();
|
|
|
|
wait( 3 );
|
|
self.exploded = undefined;
|
|
self.model Show();
|
|
self.model Solid();
|
|
return;
|
|
}
|
|
|
|
if ( !IsDefined( self.v[ "fxid" ] ) || self.v[ "fxid" ] == "No FX" )
|
|
self.v[ "exploder" ] = undefined;
|
|
|
|
waittillframeend;// so it hides stuff after it shows the new stuff
|
|
|
|
// if ( IsDefined( self.classname ) ) // script_struct support nate --- self is always a struct so it will never have a classname, using self.model instead -Carlos
|
|
if ( IsDefined( self.model ) && IsDefined( self.model.classname ) )
|
|
{
|
|
self.model Delete();
|
|
}
|
|
}
|
|
|
|
brush_throw()
|
|
{
|
|
if ( IsDefined( self.v[ "delay" ] ) )
|
|
wait( self.v[ "delay" ] );
|
|
|
|
ent = undefined;
|
|
if ( IsDefined( self.v[ "target" ] ) )
|
|
ent = get_target_ent( self.v[ "target" ] );
|
|
|
|
if ( !IsDefined( ent ) )
|
|
{
|
|
self.model Delete();
|
|
return;
|
|
}
|
|
|
|
self.model Show();
|
|
|
|
if ( IsDefined( self.v[ "delay_post" ] ) )
|
|
wait( self.v[ "delay_post" ] );
|
|
|
|
startorg = self.v[ "origin" ];
|
|
startang = self.v[ "angles" ];
|
|
org = ent.origin;
|
|
|
|
temp_vec = ( org - self.v[ "origin" ] );
|
|
x = temp_vec[ 0 ];
|
|
y = temp_vec[ 1 ];
|
|
z = temp_vec[ 2 ];
|
|
|
|
physics = IsDefined( self.v[ "physics" ] );
|
|
if ( physics )
|
|
{
|
|
target = undefined;
|
|
if ( IsDefined( ent.target ) )
|
|
target = ent get_target_ent();
|
|
|
|
if ( !IsDefined( target ) )
|
|
{
|
|
contact_point = startorg; // no spin just push it.
|
|
throw_vec = ent.origin;
|
|
}
|
|
else
|
|
{
|
|
contact_point = ent.origin;
|
|
throw_vec = ( ( target.origin - ent.origin ) * self.v[ "physics" ] );
|
|
|
|
}
|
|
self.model PhysicsLaunchClient( contact_point, throw_vec );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
self.model RotateVelocity( ( x, y, z ), 12 );
|
|
self.model MoveGravity( ( x, y, z ), 12 );
|
|
}
|
|
|
|
if ( level.createFX_enabled )
|
|
{
|
|
if ( IsDefined( self.exploded ) )
|
|
return;
|
|
|
|
self.exploded = true;
|
|
wait( 3 );
|
|
self.exploded = undefined;
|
|
self.v[ "origin" ] = startorg;
|
|
self.v[ "angles" ] = startang;
|
|
self.model Hide();
|
|
return;
|
|
}
|
|
|
|
self.v[ "exploder" ] = undefined;
|
|
wait( 6 );
|
|
self.model Delete();
|
|
}
|
|
|
|
brush_show()
|
|
{
|
|
if ( IsDefined( self.v[ "delay" ] ) )
|
|
wait( self.v[ "delay" ] );
|
|
|
|
Assert( IsDefined( self.model ) );
|
|
|
|
if ( !IsDefined( self.model.script_modelname ) )
|
|
{
|
|
self.model Show();
|
|
self.model Solid();
|
|
}
|
|
else // script_structs don't pass in their .model value SO use script_modelname on them saves an entity.
|
|
{
|
|
model = self.model spawn_tag_origin();
|
|
if ( IsDefined( self.model.script_linkname ) )
|
|
model.script_linkname = self.model.script_linkname;
|
|
model SetModel( self.model.script_modelname );
|
|
model Show();
|
|
}
|
|
|
|
self.brush_shown = true; // used for hiding an exploder.
|
|
|
|
if ( isSP() && !IsDefined( self.model.script_modelname ) && ( self.model.spawnflags & 1 ) )
|
|
{
|
|
if ( !IsDefined( self.model.disconnect_paths ) )
|
|
self.model call [[ level.connectPathsFunction ]]();
|
|
else
|
|
self.model call [[ level.disconnectPathsFunction ]]();
|
|
}
|
|
|
|
if ( level.createFX_enabled )
|
|
{
|
|
if ( IsDefined( self.exploded ) )
|
|
return;
|
|
|
|
self.exploded = true;
|
|
wait( 3 );
|
|
self.exploded = undefined;
|
|
|
|
if ( !IsDefined( self.model.script_modelname ) )
|
|
{
|
|
self.model Hide();
|
|
self.model NotSolid();
|
|
}
|
|
}
|
|
}
|
|
|
|
exploder_rumble()
|
|
{
|
|
if ( !isSP() )
|
|
return;
|
|
|
|
self exploder_delay();
|
|
level.player PlayRumbleOnEntity( self.v[ "rumble" ] );
|
|
}
|
|
|
|
exploder_delay()
|
|
{
|
|
if ( !IsDefined( self.v[ "delay" ] ) )
|
|
self.v[ "delay" ] = 0;
|
|
|
|
min_delay = self.v[ "delay" ];
|
|
max_delay = self.v[ "delay" ] + 0.001; // cant randomfloatrange on the same #
|
|
if ( IsDefined( self.v[ "delay_min" ] ) )
|
|
min_delay = self.v[ "delay_min" ];
|
|
|
|
if ( IsDefined( self.v[ "delay_max" ] ) )
|
|
max_delay = self.v[ "delay_max" ];
|
|
|
|
if ( min_delay > 0 )
|
|
wait( RandomFloatRange( min_delay, max_delay ) );
|
|
}
|
|
|
|
effect_loopsound()
|
|
{
|
|
if ( IsDefined( self.loopsound_ent ) )
|
|
{
|
|
self.loopsound_ent Delete();
|
|
}
|
|
// save off this info in case we delete the effect
|
|
origin = self.v[ "origin" ];
|
|
alias = self.v[ "loopsound" ];
|
|
self exploder_delay();
|
|
|
|
self.loopsound_ent = play_loopsound_in_space( alias, origin );
|
|
}
|
|
|
|
sound_effect()
|
|
{
|
|
self effect_soundalias();
|
|
}
|
|
|
|
effect_soundalias()
|
|
{
|
|
// save off this info in case we delete the effect
|
|
origin = self.v[ "origin" ];
|
|
alias = self.v[ "soundalias" ];
|
|
self exploder_delay();
|
|
play_sound_in_space( alias, origin );
|
|
}
|
|
|
|
exploder_earthquake()
|
|
{
|
|
self exploder_delay();
|
|
do_earthquake( self.v[ "earthquake" ], self.v[ "origin" ] );
|
|
}
|
|
|
|
exploder_playSound()
|
|
{
|
|
if ( !IsDefined( self.v[ "soundalias" ] ) || self.v[ "soundalias" ] == "nil" )
|
|
return;
|
|
|
|
play_sound_in_space( self.v[ "soundalias" ], self.v[ "origin" ] );
|
|
}
|
|
|
|
fire_effect()
|
|
{
|
|
forward = self.v[ "forward" ];
|
|
up = self.v[ "up" ];
|
|
|
|
org = undefined;
|
|
|
|
firefxSound = self.v[ "firefxsound" ];
|
|
origin = self.v[ "origin" ];
|
|
firefx = self.v[ "firefx" ];
|
|
ender = self.v[ "ender" ];
|
|
if ( !IsDefined( ender ) )
|
|
ender = "createfx_effectStopper";
|
|
|
|
fireFxDelay = 0.5;
|
|
if ( IsDefined( self.v[ "firefxdelay" ] ) )
|
|
fireFxDelay = self.v[ "firefxdelay" ];
|
|
|
|
self exploder_delay();
|
|
|
|
if ( IsDefined( firefxSound ) )
|
|
loop_fx_sound( firefxSound, origin, 1, ender );
|
|
|
|
PlayFX( level._effect[ firefx ], self.v[ "origin" ], forward, up );
|
|
}
|
|
|
|
cannon_effect()
|
|
{
|
|
if ( IsDefined( self.v[ "repeat" ] ) )
|
|
{
|
|
thread exploder_playSound();
|
|
for ( i = 0; i < self.v[ "repeat" ]; i++ )
|
|
{
|
|
PlayFX( level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] );
|
|
self exploder_delay();
|
|
}
|
|
return;
|
|
}
|
|
self exploder_delay();
|
|
|
|
if ( IsDefined( self.looper ) )
|
|
self.looper Delete();
|
|
|
|
self.looper = SpawnFx( getfx( self.v[ "fxid" ] ), self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] );
|
|
TriggerFX( self.looper );
|
|
exploder_playSound();
|
|
}
|
|
|
|
activate_exploder( num, players, startTime )
|
|
{
|
|
num += "";
|
|
//prof_begin( "activate_exploder" );
|
|
|
|
//here's a hook so you can know when a certain number of an exploder is going off
|
|
level notify( "exploding_" + num );
|
|
|
|
found_server_exploder = false;
|
|
|
|
if ( IsDefined( level.createFXexploders ) && !level.createFX_enabled )
|
|
{ // do optimized form if available
|
|
exploders = level.createFXexploders[ num ];
|
|
if ( IsDefined( exploders ) )
|
|
{
|
|
foreach ( ent in exploders )
|
|
{
|
|
ent activate_individual_exploder();
|
|
found_server_exploder = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( i = 0;i < level.createFXent.size;i++ )
|
|
{
|
|
ent = level.createFXent[ i ];
|
|
if ( !IsDefined( ent ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "type" ] != "exploder" )
|
|
continue;
|
|
|
|
// make the exploder actually removed the array instead?
|
|
if ( !IsDefined( ent.v[ "exploder" ] ) )
|
|
continue;
|
|
|
|
if ( ent.v[ "exploder" ] + "" != num )
|
|
continue;
|
|
|
|
ent activate_individual_exploder();
|
|
found_server_exploder = true;
|
|
}
|
|
}
|
|
|
|
if ( !shouldRunServerSideEffects() && !found_server_exploder )
|
|
activate_clientside_exploder( num, players, startTime );
|
|
|
|
//prof_end( "activate_exploder" );
|
|
}
|
|
|
|
activate_clientside_exploder( exploderName, players, startTime )
|
|
{
|
|
if ( !is_valid_clientside_exploder_name( exploderName ) )
|
|
{
|
|
PrintLn( "^1ERROR: Exploder Index '" + exploderName + "' is not a valid exploder index >= 0" );
|
|
return;
|
|
}
|
|
|
|
exploder_num = Int( exploderName );
|
|
ActivateClientExploder( exploder_num, players, startTime );
|
|
}
|
|
|
|
is_valid_clientside_exploder_name( exploderName )
|
|
{
|
|
if ( !IsDefined( exploderName ) )
|
|
return false;
|
|
|
|
exploder_num = exploderName;
|
|
if ( IsString( exploderName ) )
|
|
{
|
|
exploder_num = Int( exploderName );
|
|
if ( exploder_num == 0 && exploderName != "0" )
|
|
return false;
|
|
}
|
|
|
|
return exploder_num >= 0;
|
|
}
|
|
|
|
shouldRunServerSideEffects()
|
|
{
|
|
if ( isSP() )
|
|
return true;
|
|
|
|
if ( !IsDefined( level.createFX_enabled ) )
|
|
level.createFX_enabled = ( GetDvar( "createfx" ) != "" );
|
|
|
|
if ( level.createFX_enabled )
|
|
return true;
|
|
else
|
|
return GetDvar( "clientSideEffects" ) != "1";
|
|
}
|
|
|
|
exploder_before_load( num, players, startTime )
|
|
{
|
|
// gotta wait twice because the createfx_init function waits once then inits all exploders. This guarentees
|
|
// that if an exploder is run on the first frame, it happens after the fx are init.
|
|
waittillframeend;
|
|
waittillframeend;
|
|
activate_exploder( num, players, startTime );
|
|
}
|
|
|
|
exploder_after_load( num, players, startTime )
|
|
{
|
|
activate_exploder( num, players, startTime );
|
|
} |