boiii-scripts/shared/exploder_shared.csc
2023-04-13 17:30:38 +02:00

680 lines
21 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\callbacks_shared;
#using scripts\shared\fx_shared;
#using scripts\shared\sound_shared;
#using scripts\shared\system_shared;
#namespace exploder;
function autoexec __init__sytem__() { system::register("exploder",&__init__,undefined,undefined); }
function __init__()
{
if( SessionModeIsCampaignGame() )
{
callback::on_localclient_connect( &player_init );
}
}
function player_init( clientnum )
{
//println("*** Init exploders...");
script_exploders = [];
ents = struct::get_array( "script_brushmodel", "classname" );
//println("Client : s_bm " + ents.size);
smodels = struct::get_array( "script_model", "classname" );
//println("Client : sm " + smodels.size);
for( i = 0; i < smodels.size; i++ )
{
ents[ents.size] = smodels[i];
}
for( i = 0; i < ents.size; i++ )
{
if( isdefined( ents[i].script_prefab_exploder ) )
{
ents[i].script_exploder = ents[i].script_prefab_exploder;
}
}
potentialExploders = struct::get_array( "script_brushmodel", "classname" );
//println("Client : Potential exploders from script_brushmodel " + potentialExploders.size);
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 = struct::get_array( "script_model", "classname" );
//println("Client : Potential exploders from script_model " + potentialExploders.size);
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];
}
}
// Also support script_structs to work as exploders
for( i = 0; i < level.struct.size; i++ )
{
if( isdefined( level.struct[i].script_prefab_exploder ) )
{
level.struct[i].script_exploder = level.struct[i].script_prefab_exploder;
}
if( isdefined( level.struct[i].script_exploder ) )
{
script_exploders[script_exploders.size] = level.struct[i];
}
}
if( !isdefined( level.createFXent ) )
{
level.createFXent = [];
}
acceptableTargetnames = [];
acceptableTargetnames["exploderchunk visible"] = true;
acceptableTargetnames["exploderchunk"] = true;
acceptableTargetnames["exploder"] = true;
exploder_id = 1;
for( i = 0; i < script_exploders.size; i++ )
{
exploder = script_exploders[i];
ent = createExploder( exploder.script_fxid );
ent.v = [];
//if(!isdefined(exploder.origin))
//{
// println("************** NO EXPLODER ORIGIN." + i);
//}
ent.v["origin"] = exploder.origin;
ent.v["angles"] = exploder.angles;
ent.v["delay"] = exploder.script_delay;
ent.v["firefx"] = exploder.script_firefx;
ent.v["firefxdelay"] = exploder.script_firefxdelay;
ent.v["firefxsound"] = exploder.script_firefxsound;
ent.v["firefxtimeout"] = exploder.script_firefxtimeout;
ent.v["trailfx"] = exploder.script_trailfx;
ent.v["trailfxtag"] = exploder.script_trailfxtag;
ent.v["trailfxdelay"] = exploder.script_trailfxdelay;
ent.v["trailfxsound"] = exploder.script_trailfxsound;
ent.v["trailfxtimeout"] = exploder.script_firefxtimeout;
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["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;
// assert( isdefined( exploder.script_exploder ), "Exploder at origin " + exploder.origin + " has no script_exploder" );
if( !isdefined( ent.v["delay"] ) )
{
ent.v["delay"] = 0;
}
// MikeD( 4/14/2008 ): Attempt to use the fxid as the sound reference, this way Sound can add sounds to anything
// without the scripter needing to modify the map
if( isdefined( exploder.script_sound ) )
{
ent.v["soundalias"] = exploder.script_sound;
}
else if( ent.v["fxid"] != "No FX" )
{
if( isdefined( level.scr_sound ) && isdefined( level.scr_sound[ent.v["fxid"]] ) )
{
ent.v["soundalias"] = level.scr_sound[ent.v["fxid"]];
}
}
fixup_set = false;
if(isdefined(ent.v["target"]))
{
ent.needs_fixup = exploder_id;
exploder_id++;
fixup_set = true;
/* temp_ent = GetEnt(0, ent.v["target"], "targetname" );
* if( isdefined( temp_ent ) )
{
org = temp_ent.origin;
}
else */
{
temp_ent = struct::get( ent.v["target"], "targetname" );
if (isdefined(temp_ent) )
{
org = temp_ent.origin;
}
}
if(isdefined(org))
{
ent.v["angles"] = VectorToAngles( org - ent.v["origin"] );
}
//else
//{
//println("*** Client : Exploder " + exploder.script_fxid + " Failed to find target ");
//}
if(isdefined(ent.v["angles"]))
{
ent fx::set_forward_and_up_vectors();
}
//else
//{
//println("*** Client " + exploder.script_fxid + " has no angles.");
//}
}
// this basically determines if its a brush/model exploder or not
if( (isdefined(exploder.classname) && exploder.classname == "script_brushmodel") || isdefined( exploder.model ) )
{
//if(isdefined(exploder.model))
//{
//println("*** exploder " + exploder_id + " model " + exploder.model);
//}
ent.model = exploder;
//ent.model.disconnect_paths = exploder.script_disconnectpaths;
if(fixup_set == false)
{
ent.needs_fixup = exploder_id;
exploder_id++;
}
}
if( isdefined( exploder.targetname ) && isdefined( acceptableTargetnames[exploder.targetname] ) )
{
ent.v["exploder_type"] = exploder.targetname;
}
else
{
ent.v["exploder_type"] = "normal";
}
}
level.createFXexploders = [];
for(i = 0; i < level.createFXent.size;i ++ )
{
ent = level.createFXent[i];
if(ent.v["type"] != "exploder")
continue;
ent.v["exploder_id"] = exploder::getexploderid( ent );
if(!isdefined(level.createFXexploders[ent.v["exploder"]]))
{
level.createFXexploders[ent.v["exploder"]] = [];
}
level.createFXexploders[ent.v["exploder"]][level.createFXexploders[ent.v["exploder"]].size] = ent;
}
reportexploderids();
// println("*** Client : " + script_exploders.size + " exploders.");
}
function getExploderId( ent )
{
if(!isdefined(level._exploder_ids))
{
level._exploder_ids = [];
level._exploder_id = 1;
}
if(!isdefined(level._exploder_ids[ent.v["exploder"]]))
{
level._exploder_ids[ent.v["exploder"]] = level._exploder_id;
level._exploder_id ++;
}
return level._exploder_ids[ent.v["exploder"]];
}
function reportExploderIds()
{
if(!isdefined(level._exploder_ids))
return;
keys = GetArrayKeys( level._exploder_ids );
//println("Client Exploder dictionary : ");
//for( i = 0; i < keys.size; i++ )
//{
// println(keys[i] + " : " + level._exploder_ids[keys[i]]);
//}
}
//Note: specific client number only supported for radiant based exploders as ID based is now legacy
function exploder( exploder_id, n_localclientnumber )
{
if( IsInt( exploder_id ) )
{
activate_exploder( exploder_id );
}
else//This is a radiant exploder
{
activate_radiant_exploder( exploder_id, n_localclientnumber );
}
}
function activate_exploder( num )
{
num = int( num );
if(isdefined(level.createFXexploders) && isdefined(level.createFXexploders[num]))
{
for(i = 0; i < level.createFXexploders[num].size; i ++)
{
level.createFXexploders[num][i] activate_individual_exploder();
}
}
if(exploder_is_lightning_exploder(num))
{
if(isdefined(level.lightningNormalFunc) && isdefined(level.lightningFlashFunc))
{
thread fx::lightning(level.lightningNormalFunc, level.lightningFlashFunc);
}
}
}
function activate_individual_exploder()
{
if(!isdefined(self.v["angles"]))
{
self.v["angles"] = (0,0,0);
self fx::set_forward_and_up_vectors();
}
if( isdefined( self.v[ "firefx" ] ) )
self thread fire_effect();
if( isdefined( self.v[ "fxid" ] ) && self.v[ "fxid" ] != "No FX" )
self thread cannon_effect();
if( isdefined( self.v[ "earthquake" ] ) )
{
self thread exploder_earthquake();
}
}
//TODO T7 - update this if other functionality comes online for the new system
function activate_radiant_exploder( string, n_localclientnumber )
{
if( isdefined( n_localclientnumber ) )
{
PlayRadiantExploder( n_localclientnumber, string );
}
else
{
for ( localClientNum = 0; localClientNum < level.localPlayers.size; localClientNum++ )
{
PlayRadiantExploder( localClientNum, string );
}
}
}
//Note: specific client number only supported for radiant based exploders as ID based is now legacy
function stop_exploder( exploder_id, n_localclientnumber )
{
//println("*** Client : Delete exploder " + num);
if( IsString( exploder_id ) )
{
if( isdefined( n_localclientnumber ) )
{
StopRadiantExploder( n_localclientnumber, exploder_id );
}
else
{
for ( localClientNum = 0; localClientNum < level.localPlayers.size; localClientNum++ )
{
StopRadiantExploder( localClientNum, exploder_id );
}
}
return;
}
num = int( exploder_id );
if(isdefined(level.createFXexploders[exploder_id]))
{
for(i = 0; i < level.createFXexploders[exploder_id].size; i ++)
{
ent = level.createFXexploders[exploder_id][i];
if( isdefined(ent.loopFX) )
{
for(j = 0; j < ent.loopFX.size; j ++)
{
if( isdefined( ent.loopFX[j] ) )
{
StopFX( j, ent.loopFX[j] );
ent.loopFX[j] = undefined;
}
}
ent.loopFX = [];
}
}
}
}
function kill_exploder( exploder_id )
{
//println("*** Client : Delete exploder " + num);
if( IsString( exploder_id ) )
{
for ( localClientNum = 0; localClientNum < level.localPlayers.size; localClientNum++ )
{
KillRadiantExploder( localClientNum, exploder_id );
}
return;
}
assertmsg( "unhandled exploder type, only radiant exploders are handled: " + exploder_id );
}
function 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 )
waitrealtime( randomfloatrange( min_delay, max_delay ) );
}
function exploder_playSound()
{
if( !isdefined( self.v[ "soundalias" ] ) || self.v[ "soundalias" ] == "nil" )
return;
sound::play_in_space( 0, self.v[ "soundalias" ], self.v[ "origin" ] );
}
function exploder_earthquake()
{
self exploder_delay();
eq = level.earthquake[ self.v[ "earthquake" ] ];
if(isdefined(eq))
{
GetLocalPlayers()[0] earthquake( eq[ "magnitude" ], eq[ "duration" ], self.v[ "origin" ], eq[ "radius" ] );
}
}
function exploder_is_lightning_exploder(num)
{
if (isdefined(level.lightningExploder))
{
for(i = 0; i < level.lightningExploder.size; i ++)
{
if(level.lightningExploder[i] == num)
{
return true;
}
}
}
return false;
}
function stopLightLoopExploder( exploderIndex )
{
num = Int(exploderIndex);
if(isdefined(level.createFXexploders[num]))
{
for(i = 0; i < level.createFXexploders[num].size; i ++)
{
ent = level.createFXexploders[num][i];
if ( !isdefined( ent.looperFX ) )
{
ent.looperFX = [];
}
for( clientNum = 0; clientNum < level.max_local_clients; clientNum++ )
{
if( localClientActive( clientNum ) )
{
if ( isdefined( ent.looperFX[clientNum] ) )
{
for( looperFXCount = 0; looperFXCount < ent.looperFX[clientNum].size; looperFXCount++ )
{
deletefx( clientNum, ent.looperFX[clientNum][looperFXCount] );
}
}
}
ent.looperFX[clientNum] = [];
}
ent.looperFX = [];
}
}
}
function playLightLoopExploder( exploderIndex )
{
num = Int(exploderIndex);
if(isdefined(level.createFXexploders[num]))
{
for(i = 0; i < level.createFXexploders[num].size; i ++)
{
ent = level.createFXexploders[num][i];
if ( !isdefined( ent.looperFX ) )
{
ent.looperFX = [];
}
for( clientNum = 0; clientNum < level.max_local_clients; clientNum++ )
{
if( localClientActive( clientNum ) )
{
if ( !isdefined( ent.looperFX[clientNum] ) )
{
ent.looperFX[clientNum] = [];
}
ent.looperFX[clientNum][ent.looperFX[clientNum].size] = ent playExploderFX( clientNum );
}
}
}
}
}
function createExploder( fxid )
{
ent = fx::create_effect( "exploder", fxid );
ent.v[ "delay" ] = 0;
ent.v[ "exploder_type" ] = "normal";
return ent;
}
function cannon_effect()
{
if( isdefined( self.v[ "repeat" ] ) )
{
for( i = 0;i < self.v[ "repeat" ];i ++ )
{
players = getlocalplayers();
for(player = 0; player < players.size; player ++)
{
PlayFX( player, level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] );
}
self exploder_delay();
}
return;
}
self exploder_delay();
players = getlocalplayers();
if ( isdefined( self.loopFX ) )
{
for(i = 0; i < self.loopFX.size; i ++)
{
StopFX( i, self.loopFX[i] );
}
self.loopFX = [];
}
if(!isdefined(self.loopFX))
{
self.loopFX = [];
}
if(!isdefined(level._effect[self.v["fxid"]]))
{
assertmsg("*** Client : Effect " + self.v["fxid"] + " not precached in level_fx.csc.");
return;
}
for(i = 0; i < players.size; i ++)
{
if( isdefined( self.v["fxid"] ) )
{
self.loopFX[i] = PlayFX( i , level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ] );
}
}
self exploder_playSound();
}
function fire_effect()
{
forward = self.v[ "forward" ];
if( !isdefined( forward ) )
{
forward = anglestoforward( self.v["angles"] );
}
up = self.v[ "up" ];
if( !isdefined( up ) )
{
up = anglestoup( self.v["angles"] );
}
//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();
players = GetLocalPlayers();
for(i = 0; i < players.size; i ++)
{
if( isdefined( firefxSound ) )
{
level thread sound::loop_fx_sound( i, firefxSound, origin, ender );
}
playfx( i, level._effect[ firefx ], self.v[ "origin" ], forward, up, 0, self.v[ "primlightfrac" ], self.v[ "lightoriginoffs" ] );
}
}
// self is the exploder entity
function playExploderFX( clientNum )
{
/#
if ( !isdefined( self.v[ "origin" ] ) )
return;
if ( !isdefined( self.v[ "forward" ] ) )
return;
if ( !isdefined( self.v[ "up" ] ) )
return;
#/
return playfx( clientNum, level._effect[ self.v[ "fxid" ] ], self.v[ "origin" ], self.v[ "forward" ], self.v[ "up" ], 0, self.v[ "primlightfrac" ], self.v[ "lightoriginoffs" ] );
}
function stop_after_duration( name, duration )
{
wait( duration );
stop_exploder( name );
}
function exploder_duration( name, duration )
{
if ( !( isdefined( duration ) && duration ) )
{
return;
}
exploder( name );
level thread stop_after_duration( name, duration );
}