1250 lines
30 KiB
Plaintext
1250 lines
30 KiB
Plaintext
#include common_scripts\utility;
|
|
#include maps\mp\_utility;
|
|
////////////////////////
|
|
// Gas Station
|
|
////////////////////////
|
|
|
|
#using_animtree( "animated_props" );
|
|
|
|
gas_station()
|
|
{
|
|
gas_station_precache();
|
|
|
|
flag_init( "gas_station_exploded" );
|
|
flag_init( "breach_connect_nodes" );
|
|
|
|
wait 0.05;
|
|
|
|
structs = getstructarray( "gas", "targetname" );
|
|
array_thread( structs, ::gas_station_init );
|
|
}
|
|
|
|
gas_station_init()
|
|
{
|
|
target_ents = GetEntArray( self.target, "targetname" );
|
|
target_structs = getstructarray( self.target, "targetname" );
|
|
target_ents = array_combine( target_ents, target_structs );
|
|
nodes = self getLinknameNodes();
|
|
targets = array_combine( target_ents, nodes );
|
|
|
|
self.clip_up = [];
|
|
self.clip_down = [];
|
|
self.launch_ents = [];
|
|
self.linked_ents = [];
|
|
|
|
if ( GetDvar( "r_reflectionProbeGenerate" ) == "1" )
|
|
return;
|
|
|
|
foreach ( target_ent in targets )
|
|
{
|
|
if ( !IsDefined( target_ent.script_noteworthy ) )
|
|
continue;
|
|
|
|
if ( !IsDefined( target_ent.script_parameters ) )
|
|
target_ent.script_parameters = "corner1_hit";
|
|
|
|
switch ( target_ent.script_noteworthy )
|
|
{
|
|
case "clip_up":
|
|
self.clip_up [ self.clip_up.size ] = target_ent;
|
|
self.linked_ents[ self.linked_ents.size ] = target_ent;
|
|
break;
|
|
case "clip_down_traverse":
|
|
target_ent.nodisconnect = true;
|
|
//Fallthrough
|
|
case "clip_down":
|
|
self.clip_down[ self.clip_down.size ] = target_ent;
|
|
target_ent SetAISightLineVisible( 0 );
|
|
target_ent ConnectPaths();
|
|
target_ent trigger_off();
|
|
break;
|
|
case "link_to_launch":
|
|
self thread gas_station_run_func_on_notify( target_ent.script_parameters, ::gas_station_launch_ent, target_ent );
|
|
self.launch_ents[ self.launch_ents.size ] = target_ent;
|
|
//Fallthrough
|
|
case "link_to":
|
|
self.linked_ents[ self.linked_ents.size ] = target_ent;
|
|
break;
|
|
case "fx":
|
|
self thread gas_station_run_func_on_notify( target_ent.script_parameters, ::gas_station_play_fx, target_ent );
|
|
break;
|
|
case "animated":
|
|
self.animated_model = target_ent;
|
|
break;
|
|
case "earthquake":
|
|
self thread gas_station_run_func_on_notify( target_ent.script_parameters, ::gas_station_earthquake, target_ent );
|
|
break;
|
|
case "sound":
|
|
self thread gas_station_run_func_on_notify( target_ent.script_parameters, ::gas_station_playSound, target_ent );
|
|
break;
|
|
case "connect_node":
|
|
target_ent DisconnectNode();
|
|
self thread gas_station_run_func_on_notify( target_ent.script_parameters, ::gas_station_connect_node, target_ent );
|
|
break;
|
|
case "disconnect_node":
|
|
self thread gas_station_run_func_on_notify( target_ent.script_parameters, ::gas_station_disconnect_node, target_ent );
|
|
break;
|
|
case "prone_kill_trigger":
|
|
self.prone_kill_trigger = target_ent;
|
|
target_ent trigger_off();
|
|
break;
|
|
case "killcam":
|
|
self.killCamEnt = Spawn( "script_model", target_ent.origin);
|
|
self.killCamEnt SetModel( "tag_origin" );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( IsDefined( self.animated_model ) )
|
|
{
|
|
foreach ( ent in self.linked_ents )
|
|
{
|
|
ent LinkTo( self.animated_model, "j_awning_main" );
|
|
}
|
|
}
|
|
|
|
self thread care_package_watch();
|
|
|
|
gas_pumps = GetScriptableArray( "gaspump", "targetname" );
|
|
|
|
level.last_player_to_damage_gas_pump = undefined;
|
|
level.player_who_caused_gas_station_explosion = undefined;
|
|
|
|
foreach ( pump in gas_pumps )
|
|
{
|
|
pump thread gas_pump_damage_monitor( self );
|
|
pump thread notify_explode( self, gas_pumps );
|
|
}
|
|
|
|
self waittill( "gas_station_explode", exploded_pump );
|
|
|
|
flag_set( "gas_station_exploded" );
|
|
foreach ( player in level.players )
|
|
{
|
|
player.present_for_gas_station_explosion = true;
|
|
}
|
|
|
|
foreach ( pump in gas_pumps )
|
|
{
|
|
if ( pump == exploded_pump )
|
|
continue;
|
|
if( IsDefined( level.player_who_caused_gas_station_explosion ) )
|
|
{
|
|
pump.attacker = level.player_who_caused_gas_station_explosion;
|
|
if( IsDefined( level.player_who_caused_gas_station_explosion.team ) )
|
|
{
|
|
pump.team = level.player_who_caused_gas_station_explosion.team;
|
|
}
|
|
}
|
|
if( IsDefined( pump.attacker ) )
|
|
{
|
|
pump SetScriptableDamageOwner( pump.attacker );
|
|
}
|
|
pump SetScriptablePartState( 0, "destroyed" );
|
|
}
|
|
|
|
//Play fx on pump that exploded
|
|
// PlayFX( level._effect[ "vfx_gas_station_explosion" ], exploded_pump.origin );
|
|
|
|
time = GetAnimLength( %mp_dart_gas_awning_fall );
|
|
|
|
self.gas_station_events = [];
|
|
// note time
|
|
self gas_station_add_event( "start" , 0.0 );
|
|
self gas_station_add_event( "beam_break" , 0.1 );
|
|
self gas_station_add_event( "corner1_hit", 1.9 );
|
|
self gas_station_add_event( "corner2_hit", 2.15 );
|
|
self gas_station_add_event( "sign_hit" , 2.5 );
|
|
self gas_station_add_event( "end" , time );
|
|
|
|
self thread gas_station_run_func_on_notify( "corner1_hit", ::gas_station_update_clip );
|
|
|
|
self thread gas_station_run_events();
|
|
|
|
if ( IsDefined( self.animated_model ) )
|
|
{
|
|
self.animated_model ScriptModelPlayAnimDeltaMotion( "mp_dart_gas_awning_fall" );
|
|
exploder( 22 );
|
|
|
|
sound_origins = GetEntArray( "gas_pump_fire_sound_origin", "targetname" );
|
|
foreach ( sound_origin in sound_origins )
|
|
{
|
|
sound_origin PlayLoopSound( "emt_dart_fire_small_ext_lp" );
|
|
}
|
|
}
|
|
}
|
|
|
|
gas_station_run_func_on_notify( note, func, param1 )
|
|
{
|
|
self waittill( note );
|
|
|
|
if ( IsDefined( param1 ) )
|
|
{
|
|
self thread [[ func ]]( param1 );
|
|
}
|
|
else
|
|
{
|
|
self thread [[ func ]]();
|
|
}
|
|
}
|
|
|
|
gas_station_update_clip()
|
|
{
|
|
killcam_struct = getstruct( "gas_station_killcam", "targetname" );
|
|
|
|
foreach ( clip in self.clip_up )
|
|
{
|
|
clip SetAISightLineVisible( 0 );
|
|
clip Delete();
|
|
}
|
|
|
|
foreach ( clip in self.clip_down )
|
|
{
|
|
clip SetAISightLineVisible( 1 );
|
|
|
|
clip.unresolved_collision_func = maps\mp\_movers::unresolved_collision_void;
|
|
|
|
clip trigger_on();
|
|
if ( !IsDefined( clip.nodisconnect ) || !clip.nodisconnect )
|
|
clip DisconnectPaths();
|
|
|
|
|
|
foreach ( character in level.characters )
|
|
{
|
|
if ( character IsTouching( clip ) && IsAlive( character ) )
|
|
{
|
|
if ( IsDefined( self.attacker ) && IsDefined( self.attacker.team ) && ( self.attacker.team == character.team ) )
|
|
{
|
|
character maps\mp\_movers::mover_suicide();
|
|
}
|
|
else
|
|
{
|
|
clip.killCamEnt = self.killCamEnt;
|
|
//HAVE to kill them, not just damage them
|
|
if( IsDefined( level.player_who_caused_gas_station_explosion ) )
|
|
{
|
|
character DoDamage( character.health + 10000, character.origin, level.player_who_caused_gas_station_explosion, clip, "MOD_EXPLOSIVE" );
|
|
}
|
|
else
|
|
{
|
|
character DoDamage( character.health + 10000, character.origin, self.attacker, clip, "MOD_EXPLOSIVE" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ( vanguard in level.remote_uav )
|
|
{
|
|
if ( vanguard IsTouching( clip ) )
|
|
{
|
|
vanguard notify( "death" );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( IsDefined( self.prone_kill_trigger ) )
|
|
{
|
|
self.prone_kill_trigger trigger_on();
|
|
foreach ( character in level.characters )
|
|
{
|
|
if ( character IsTouching( self.prone_kill_trigger ) && IsAlive( character ) )
|
|
{
|
|
if ( IsDefined( self.attacker ) && IsDefined( self.attacker.team ) && ( self.attacker.team == character.team ) )
|
|
{
|
|
character maps\mp\_movers::mover_suicide();
|
|
}
|
|
else
|
|
{
|
|
self.prone_kill_trigger.killCamEnt = self.killCamEnt;
|
|
if( IsDefined( level.player_who_caused_gas_station_explosion ) )
|
|
{
|
|
character DoDamage( character.health + 20, character.origin, level.player_who_caused_gas_station_explosion, self.prone_kill_trigger, "MOD_EXPLOSIVE" );
|
|
}
|
|
else
|
|
{
|
|
character DoDamage( character.health + 20, character.origin, self.attacker, self.prone_kill_trigger, "MOD_EXPLOSIVE" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
wait( 10 );
|
|
self.prone_kill_trigger Delete();
|
|
}
|
|
|
|
}
|
|
|
|
gas_station_launch_ent( ent )
|
|
{
|
|
angles = self.animated_model GetTagAngles( "j_awning_main" );
|
|
launch_dir = AnglesToUp( angles );
|
|
ent Unlink();
|
|
|
|
org_offset = ( RandomFloatRange( -1, 1 ), RandomFloatRange( -1, 1 ), 0 ); //give object rotation
|
|
ent PhysicsLaunchClient( ent.origin + org_offset, launch_dir * 15000 );
|
|
}
|
|
|
|
gas_station_play_fx( ent )
|
|
{
|
|
if ( !IsDefined( ent.script_fxid ) || !IsDefined( level._effect[ ent.script_fxid ] ) )
|
|
return;
|
|
|
|
PlayFX( level._effect[ ent.script_fxid ], ent.origin, AnglesToForward( ent.angles ) );
|
|
}
|
|
|
|
gas_station_earthquake( ent )
|
|
{
|
|
Earthquake( 0.3, .5, ent.origin, 800 );
|
|
}
|
|
|
|
gas_station_playSound( ent )
|
|
{
|
|
if ( !IsDefined( ent.script_sound ) )
|
|
return;
|
|
|
|
playSoundAtPos( ent.origin, ent.script_sound );
|
|
}
|
|
|
|
gas_station_connect_node( node )
|
|
{
|
|
node ConnectNode();
|
|
}
|
|
|
|
gas_station_disconnect_node( node )
|
|
{
|
|
node DisconnectNode();
|
|
}
|
|
|
|
gas_station_run_events()
|
|
{
|
|
start_time = GetTime();
|
|
while ( 1 )
|
|
{
|
|
foreach ( event in self.gas_station_events )
|
|
{
|
|
if ( event.done )
|
|
continue;
|
|
|
|
if ( ( GetTime() -start_time ) / 1000 >= event.time )
|
|
{
|
|
self notify( event.note );
|
|
event.done = true;
|
|
if ( event.note == "end" )
|
|
return;
|
|
}
|
|
}
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
gas_station_add_event( note, time )
|
|
{
|
|
if ( !IsDefined( self.gas_station_events ) )
|
|
self.gas_station_events = [];
|
|
s = SpawnStruct();
|
|
s.time = time;
|
|
s.note = note;
|
|
s.done = false;
|
|
|
|
self.gas_station_events[ self.gas_station_events.size ] = s;
|
|
}
|
|
|
|
//
|
|
gas_station_precache()
|
|
{
|
|
PrecacheMpAnim( "mp_dart_gas_awning_fall" );
|
|
}
|
|
|
|
gas_pump_damage_monitor( gas_station )
|
|
{
|
|
gas_station endon( "gas_station_explode" );
|
|
|
|
self.killCamEnt = gas_station.killCamEnt;
|
|
|
|
while( 1 )
|
|
{
|
|
self waittill( "damage", damage, attacker, direction_vec, point, meansOfDeath, modelName, tagName, partName, iDFlags, weapon );
|
|
|
|
if( IsPlayer( attacker ) || IsAgent( attacker ) )
|
|
{
|
|
if( IsAgent( attacker ) && IsDefined( attacker.owner ) )
|
|
{
|
|
attacker = attacker.owner;
|
|
}
|
|
|
|
level.last_player_to_damage_gas_pump = attacker;
|
|
self SetScriptableDamageOwner( attacker );
|
|
}
|
|
}
|
|
}
|
|
|
|
notify_explode( gas_station, gas_pumps )
|
|
{
|
|
self waittill( "death", attacker, mod, weapon );
|
|
|
|
if( !IsDefined( level.player_who_caused_gas_station_explosion ) )
|
|
{
|
|
if( IsPlayer( attacker ) || IsAgent( attacker ) )
|
|
{
|
|
if( IsAgent( attacker ) && IsDefined( attacker.owner ) )
|
|
{
|
|
attacker = attacker.owner;
|
|
}
|
|
|
|
level.player_who_caused_gas_station_explosion = attacker;
|
|
}
|
|
else if( IsDefined( level.last_player_to_damage_gas_pump ) )
|
|
{
|
|
level.player_who_caused_gas_station_explosion = level.last_player_to_damage_gas_pump;
|
|
}
|
|
self SetScriptableDamageOwner( level.player_who_caused_gas_station_explosion );
|
|
}
|
|
self.attacker = level.player_who_caused_gas_station_explosion;
|
|
gas_station.attacker = level.player_who_caused_gas_station_explosion;
|
|
if( IsDefined( level.player_who_caused_gas_station_explosion.team ) )
|
|
{
|
|
self.team = level.player_who_caused_gas_station_explosion.team;
|
|
gas_station.team = level.player_who_caused_gas_station_explosion.team;
|
|
}
|
|
|
|
gas_station notify( "gas_station_explode", self );
|
|
}
|
|
|
|
/////////////////////////////////////////////
|
|
// Broken Walls
|
|
////////////////////////////////////////////
|
|
broken_walls()
|
|
{
|
|
walls = getstructarray( "broken_wall", "targetname" );
|
|
array_thread( walls, ::broken_wall_init );
|
|
}
|
|
|
|
broken_wall_init( requires_explosive )
|
|
{
|
|
self.trigger_show = []; //May not be a trigger, just needs to be hidden like a trigger (origin +/- 10000)
|
|
self.delete_ents = [];
|
|
self.show_ents = [];
|
|
self.trigger_damage = [];
|
|
|
|
|
|
targets = GetEntArray( self.target, "targetname" );
|
|
|
|
foreach ( target in targets )
|
|
{
|
|
if ( !IsDefined( target.script_noteworthy ) )
|
|
{
|
|
target.script_noteworthy = target.classname;
|
|
}
|
|
|
|
switch( target.script_noteworthy )
|
|
{
|
|
case "delete":
|
|
self.delete_ents[ self.delete_ents.size ] = target;
|
|
break;
|
|
case "trigger_damage":
|
|
self.trigger_damage[ self.trigger_damage.size ] = target;
|
|
self thread broken_wall_damage_watch( target );
|
|
break;
|
|
case "show":
|
|
target Hide();
|
|
self.show_ents[ self.show_ents.size ] = target;
|
|
break;
|
|
case "trigger_show":
|
|
target trigger_off();
|
|
self.trigger_show[ self.trigger_show.size ] = target;
|
|
break;
|
|
case "trigger_use_touch":
|
|
target UseTriggerRequireLookAt();
|
|
target.script_noteworthy = "trigger_use"; // <- purely for consistency with the breach stuff
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
broken_wall_damage_watch( trigger, requires_explosive )
|
|
{
|
|
self endon( "break_wall" );
|
|
|
|
trigger waittill( "trigger" );
|
|
|
|
array_thread( self.show_ents, ::broken_wall_show );
|
|
array_call( self.trigger_damage, ::Delete );
|
|
// entities process
|
|
array_thread( self.delete_ents , ::broken_wall_delete );
|
|
array_thread( self.trigger_show, ::trigger_on );
|
|
|
|
self notify( "break_wall" );
|
|
}
|
|
|
|
broken_wall_delete()
|
|
{
|
|
if ( IsDefined( self.script_index ) )
|
|
{
|
|
exploder( self.script_index );
|
|
}
|
|
|
|
self SetAISightLineVisible( 0 );
|
|
self Delete();
|
|
}
|
|
|
|
broken_wall_show()
|
|
{
|
|
self SetAISightLineVisible( 1 );
|
|
self Show();
|
|
}
|
|
|
|
///////////////
|
|
// Breach
|
|
///////////////
|
|
breach()
|
|
{
|
|
if ( GetDvar( "r_reflectionProbeGenerate" ) == "1" )
|
|
return;
|
|
|
|
maps\mp\_breach::breach_precache();
|
|
dart_breach_precache();
|
|
dart_breach_anims_init();
|
|
waitframe();
|
|
|
|
breaches = getstructarray( "breach", "targetname" );
|
|
|
|
proxy = getstructarray( "breach_proxy", "targetname" );
|
|
foreach ( p in proxy )
|
|
{
|
|
if ( !IsDefined( p.target ) )
|
|
continue;
|
|
|
|
breach = getstruct( p.target, "targetname" );
|
|
if ( !IsDefined( breach ) )
|
|
continue;
|
|
|
|
// We need to make sure the breach already happened for this game mode
|
|
// Since we can't edit the map/prefabs, we will have to add this in through script
|
|
breach = setExtraBreachExceptions( breach );
|
|
|
|
breaches[ breaches.size ] = breach;
|
|
}
|
|
|
|
// entities process
|
|
array_thread( breaches , ::breach_init );
|
|
array_thread( breaches , maps\mp\_breach::breach_init );
|
|
|
|
}
|
|
|
|
setExtraBreachExceptions( breach )
|
|
{
|
|
if ( !IsDefined( breach.script_noteworthy ) )
|
|
return breach;
|
|
|
|
// Append an exception to the script_noteworthy that contains existing ones
|
|
// The exceptions in the script_noteworthy do not need to be in any specific order, so we can just add it to the end
|
|
if ( level.gametype == "siege" )
|
|
breach.script_noteworthy = breach.script_noteworthy + "," + "not_in_siege";
|
|
|
|
return breach;
|
|
}
|
|
|
|
dart_breach_precache()
|
|
{
|
|
PrecacheMpAnim( "mp_dart_container_breach_side1" );
|
|
PrecacheMpAnim( "mp_dart_container_breach_side2" );
|
|
PrecacheMpAnim( "mp_dart_container_breach_top" );
|
|
PrecacheMpAnim( "mp_dart_container_idle_side1" );
|
|
PrecacheMpAnim( "mp_dart_container_idle_side2" );
|
|
PrecacheMpAnim( "mp_dart_container_idle_top" );
|
|
}
|
|
|
|
dart_breach_anims_init()
|
|
{
|
|
level.breach_anims = [];
|
|
level.breach_anims[ "mp_dart_container_breach_side1" ] = "mp_dart_container_breach_side1";
|
|
level.breach_anims[ "mp_dart_container_breach_side1_idle" ] = "mp_dart_container_idle_side1";
|
|
level.breach_anims[ "mp_dart_container_breach_side2" ] = "mp_dart_container_breach_side2";
|
|
level.breach_anims[ "mp_dart_container_breach_side2_idle" ] = "mp_dart_container_idle_side2";
|
|
level.breach_anims[ "mp_dart_container_breach_top" ] = "mp_dart_container_breach_top";
|
|
level.breach_anims[ "mp_dart_container_breach_top_idle" ] = "mp_dart_container_idle_top";
|
|
}
|
|
|
|
breach_init()
|
|
{
|
|
self.animated_doors = [];
|
|
self.care_packages = [];
|
|
self.delete_ents = [];
|
|
self.doors = [];
|
|
self.notsolid_ents = [];
|
|
self.solid_ents = [];
|
|
|
|
target_ents = GetEntArray( self.target, "targetname" );
|
|
target_structs = getstructarray( self.target, "targetname" );
|
|
|
|
targets = array_combine( target_structs, target_ents );
|
|
|
|
foreach ( target in targets )
|
|
{
|
|
if ( IsDefined(target.classname) && target.classname == "trigger_use_touch" )
|
|
add_to_bot_use_targets( target, 1.5 );
|
|
|
|
if ( !IsDefined( target.script_noteworthy ) )
|
|
continue;
|
|
|
|
switch( target.script_noteworthy )
|
|
{
|
|
case "door":
|
|
self.doors[ self.doors.size ] = target;
|
|
self breach_door_init( target );
|
|
break;
|
|
case "triggers_with":
|
|
if ( IsDefined( target.target ) )
|
|
{
|
|
other_breach = getstruct( target.target, "targetname" );
|
|
if ( IsDefined( other_breach ) )
|
|
self thread breach_other_watch( other_breach );
|
|
}
|
|
break;
|
|
case "care_package":
|
|
self.care_packages[ self.care_packages.size ] = target;
|
|
break;
|
|
case "animated_door":
|
|
door = GetEnt( target.target, "targetname" );
|
|
self.animated_doors[ self.animated_doors.size ] = door;
|
|
self breach_animated_door_init( door );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
foreach ( door in self.doors )
|
|
{
|
|
self thread breach_close_door( door );
|
|
}
|
|
|
|
self thread breach_open_watch();
|
|
}
|
|
|
|
add_care_package( origin, angles, owner, owner_team, crateType, dropType )
|
|
{
|
|
if ( !IsDefined( dropType ) )
|
|
{
|
|
dropType = "airdrop_assault";
|
|
if ( IsDefined( crateType ) )
|
|
{
|
|
possible_dropTypes = [ "airdrop_assault", "airdrop_support" ];
|
|
foreach ( possible_dropType in possible_dropTypes )
|
|
{
|
|
if ( is_valid_crateType( possible_dropType, crateType ) )
|
|
{
|
|
dropType = possible_dropType;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !is_valid_dropType( dropType ) )
|
|
return;
|
|
|
|
if ( !IsDefined( crateType ) )
|
|
{
|
|
crateType = random( GetArrayKeys( level.crateTypes[ dropType ] ) );
|
|
}
|
|
|
|
if ( !is_valid_crateType( dropType, crateType ) )
|
|
return;
|
|
|
|
if ( !IsDefined( angles ) )
|
|
angles = ( 0, 0, 0 );
|
|
|
|
dropCrate = Spawn( "script_model", origin );
|
|
dropCrate SetModel( maps\mp\killstreaks\_airdrop::get_friendly_crate_model() );
|
|
dropCrate.angles = angles;
|
|
dropCrate.crateType = crateType;
|
|
dropCrate.owner = owner;
|
|
if ( IsDefined( owner_team ) )
|
|
{
|
|
dropCrate.team = owner_team;
|
|
}
|
|
else
|
|
{
|
|
dropCrate.team = owner.team;
|
|
}
|
|
dropCrate.targetname = "care_package";
|
|
dropCrate.droppingToGround = false;
|
|
dropCrate.id = "care_package";
|
|
|
|
dropCrate CloneBrushmodelToScriptmodel( level.airDropCrateCollision );
|
|
dropCrate thread entity_path_disconnect_thread( 1.0 );
|
|
dropCrate PhysicsLaunchServer( ( 0, 0, 0 ), ( 0, 0, 1 ) );
|
|
|
|
dropCrate thread [[ level.crateTypes[ dropType ][ crateType ].func ]]( dropType );
|
|
|
|
if ( IsBot( owner ) )
|
|
{
|
|
wait( 0.1 );
|
|
owner notify( "new_crate_to_take" );
|
|
}
|
|
}
|
|
|
|
is_valid_dropType( dropType )
|
|
{
|
|
if ( !IsDefined( dropType ) )
|
|
return false;
|
|
|
|
foreach ( key, value in level.crateTypes )
|
|
{
|
|
if ( key == dropType )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
is_valid_crateType( dropType, crateType )
|
|
{
|
|
if ( !is_valid_dropType( dropType ) )
|
|
return false;
|
|
|
|
if ( !IsDefined( crateType ) )
|
|
return false;
|
|
|
|
foreach ( key, value in level.crateTypes[ dropType ] )
|
|
{
|
|
if ( key == crateType )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
breach_animated_door_init( door )
|
|
{
|
|
breach_struct = self;
|
|
|
|
AssertEx( IsDefined( door.script_noteworthy ), "animated_door in breach without animation defined in door.script_noteworthy" );
|
|
if ( IsDefined( level.breach_anims[ door.script_noteworthy + "_idle" ] ) )
|
|
{
|
|
door ScriptModelPlayAnimDeltaMotion( level.breach_anims[ door.script_noteworthy + "_idle" ] );
|
|
}
|
|
|
|
door thread clear_attached_items( breach_struct );
|
|
}
|
|
|
|
clear_attached_items( breach_struct )
|
|
{
|
|
breach_struct waittill( "breach_activated" );
|
|
self maps\mp\_movers::notify_moving_platform_invalid();
|
|
}
|
|
|
|
breach_door_init( door )
|
|
{
|
|
target_ents = GetEntArray( door.target, "targetname" );
|
|
target_structs = getstructarray( door.target, "targetname" );
|
|
|
|
targets = array_combine( target_structs, target_ents );
|
|
|
|
door_parts = [];
|
|
pivot = undefined;
|
|
foreach ( target in targets )
|
|
{
|
|
if ( !IsDefined( target.script_noteworthy ) )
|
|
continue;
|
|
|
|
switch( target.script_noteworthy )
|
|
{
|
|
case "open":
|
|
door.open_pos = target;
|
|
break;
|
|
case "closed":
|
|
door.closed_pos = target;
|
|
break;
|
|
case "door_part":
|
|
door_parts[ door_parts.size ] = target;
|
|
break;
|
|
case "pivot":
|
|
pivot = target;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !IsDefined( door.open_pos ) || !IsDefined( door.closed_pos ) || !IsDefined( pivot ) || door_parts.size == 0 )
|
|
return false; //ERROR
|
|
|
|
door.closed_pos.move_angles = get_rotate_angle( door.open_pos.angles, door.closed_pos.angles, pivot.angles );
|
|
door.open_pos.move_angles = -1 * door.closed_pos.move_angles;
|
|
|
|
link_ent = Spawn( "script_model", pivot.origin );
|
|
link_ent SetModel( "tag_origin" );
|
|
link_ent.angles = pivot.angles;
|
|
|
|
foreach ( ent in door_parts )
|
|
{
|
|
ent LinkTo( link_ent );
|
|
}
|
|
|
|
door.link_ent = link_ent;
|
|
return true; //Great success
|
|
}
|
|
|
|
breach_other_watch( other )
|
|
{
|
|
other waittill( "breach_activated", player, no_fx, breaching_team );
|
|
self notify( "breach_activated", player, no_fx, breaching_team );
|
|
}
|
|
|
|
breach_open_watch()
|
|
{
|
|
self waittill( "breach_activated", player, no_fx, breaching_team );
|
|
|
|
target_ents = GetEntArray( self.target, "targetname" );
|
|
foreach ( target_ent in target_ents )
|
|
{
|
|
if ( IsDefined(target_ent.classname) && target_ent.classname == "trigger_use_touch" )
|
|
remove_from_bot_use_targets( target_ent );
|
|
}
|
|
|
|
if ( IsDefined( player ) && !isMLGMatch() )
|
|
{
|
|
foreach ( package in self.care_packages )
|
|
{
|
|
crateType = random( [ "uplink_support", "deployable_vest", "deployable_ammo", "ball_drone_radar", "aa_launcher", "jammer", "ims" ] );
|
|
add_care_package( package.origin, package.angles, player, breaching_team, crateType );
|
|
}
|
|
}
|
|
|
|
door_time = 0.2;
|
|
|
|
foreach ( door in self.doors )
|
|
{
|
|
self thread breach_open_door( door, door_time );
|
|
}
|
|
|
|
foreach ( animated_door in self.animated_doors )
|
|
{
|
|
animated_door ScriptModelPlayAnimDeltaMotion( level.breach_anims[ animated_door.script_noteworthy ] );
|
|
|
|
switch( animated_door.script_noteworthy )
|
|
{
|
|
case "mp_dart_container_breach_side1":
|
|
playSoundAtPos( animated_door.origin, "scn_dart_trailer_breach_side" );
|
|
break;
|
|
case "mp_dart_container_breach_side2":
|
|
playSoundAtPos( animated_door.origin, "scn_dart_trailer_breach_side" );
|
|
break;
|
|
case "mp_dart_container_breach_top":
|
|
playSoundAtPos( animated_door.origin, "scn_dart_trailer_breach_top" );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
wait door_time;
|
|
|
|
// entities process
|
|
array_call( self.notsolid_ents, ::NotSolid );
|
|
array_call( self.delete_ents , ::Delete );
|
|
|
|
array_call( self.solid_ents, ::Solid );
|
|
foreach ( ent in self.solid_ents )
|
|
{
|
|
ent Solid();
|
|
if ( IsDefined ( level.players ) )
|
|
{
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( player IsTouching( ent ) )
|
|
{
|
|
self thread breach_kill_player( player );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
flag_set( "breach_connect_nodes" );
|
|
}
|
|
|
|
breach_kill_player( player )
|
|
{
|
|
RadiusDamage( player.origin, 8, 1000, 1000, self.owner, "MOD_CRUSH" );
|
|
}
|
|
|
|
breach_open_door( door, time )
|
|
{
|
|
breach_move_door( door, door.open_pos, time );
|
|
}
|
|
|
|
breach_close_door( door, time )
|
|
{
|
|
breach_move_door( door, door.closed_pos, time );
|
|
}
|
|
|
|
breach_move_door( door, pos, time )
|
|
{
|
|
angles = pos.angles;
|
|
origin = pos.origin;
|
|
|
|
if ( IsDefined( time ) && time > 0 )
|
|
{
|
|
if ( IsDefined( angles ) && angles != door.link_ent.angles )
|
|
door.link_ent RotateBy( pos.move_angles, time, time );
|
|
if ( IsDefined( origin ) && origin != door.link_ent.origin )
|
|
door.link_ent MoveTo( origin, time );
|
|
}
|
|
else
|
|
{
|
|
if ( IsDefined( angles ) )
|
|
door.link_ent.angles = angles;
|
|
if ( IsDefined( origin ) )
|
|
door.link_ent.origin = origin;
|
|
}
|
|
}
|
|
|
|
////////////
|
|
// Util
|
|
///////////
|
|
is_explosive( cause )
|
|
{
|
|
if ( !IsDefined( cause ) )
|
|
return false;
|
|
|
|
cause = ToLower( cause );
|
|
switch( cause )
|
|
{
|
|
case "mod_grenade_splash":
|
|
case "mod_projectile_splash":
|
|
case "mod_explosive":
|
|
case "splash":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
normalize_angles_180( angles )
|
|
{
|
|
return ( AngleClamp180( angles[ 0 ] ), AngleClamp180( angles[ 1 ] ), AngleClamp180( angles[ 2 ] ) );
|
|
}
|
|
|
|
get_rotate_angle( start, end, through )
|
|
{
|
|
delta = end - start;
|
|
delta = normalize_angles_180( delta );
|
|
|
|
if ( IsDefined( through ) )
|
|
{
|
|
dir = through - start;
|
|
dir = normalize_angles_180( dir );
|
|
|
|
for ( i = 0;i < 3;i++ )
|
|
{
|
|
//check if dir and delta have the same sign
|
|
//if they dont the shortest path doesn't go through
|
|
if ( dir[ i ] * delta[ i ] < 0 )
|
|
{
|
|
change = 360;
|
|
if ( dir[ i ] < 0 )
|
|
change = -360;
|
|
delta = ( delta[ 0 ] +( change * ( i == 0 ) ), delta[ 1 ] +( change * ( i == 1 ) ), delta[ 2 ] +( change * ( i == 2 ) ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
return delta;
|
|
}
|
|
|
|
//////////////////////////
|
|
// Ceiling Rubble
|
|
/////////////////////////
|
|
|
|
|
|
|
|
|
|
ceiling_rubble()
|
|
{
|
|
level thread ceiling_rubble_onPlayerConnect();
|
|
wait 0.05;
|
|
|
|
if ( !IsDefined( level.fx_tag_origin ) )
|
|
level.fx_tag_origin = spawn_tag_origin();
|
|
|
|
rubbles = [];
|
|
//Validate structs
|
|
fxvolumes = GetEntArray( "fx_building_impact", "targetname" );
|
|
//foreach(volume in volumes)
|
|
//{
|
|
// if(IsDefined(rubble.script_index))
|
|
// {
|
|
// rubble.radius_squared = rubble.radius*rubble.radius;
|
|
// rubbles[rubbles.size] = rubble;
|
|
// }
|
|
//}
|
|
|
|
level thread do_rubble( fxvolumes );
|
|
}
|
|
|
|
wait_and_trigger_fx()
|
|
{
|
|
wait( RandomFloatRange( 0.0, 0.4 ) );
|
|
TriggerFX( self );
|
|
}
|
|
|
|
do_rubble( fxvolumes )
|
|
{
|
|
while ( 1 )
|
|
{
|
|
level waittill( "do_rubble", position );
|
|
//tag_origin = spawn_tag_origin();
|
|
foreach ( volume in fxvolumes )
|
|
{
|
|
if ( IsDefined( volume.script_index ) )
|
|
{
|
|
level.fx_tag_origin.origin = position;
|
|
if ( level.fx_tag_origin IsTouching( volume ) )
|
|
{
|
|
if ( IsDefined( volume.script_index ) )
|
|
{
|
|
if ( !IsDefined( volume.playing_effect ) )
|
|
volume.playing_effect = false;
|
|
if ( volume.playing_effect == false )
|
|
{
|
|
volume.playing_effect = true;
|
|
exploder(volume.script_index);
|
|
//
|
|
//foreach ( effect in level.scripted_exploders[ volume.script_index ] )
|
|
//{
|
|
// effect thread wait_and_trigger_fx();
|
|
//}
|
|
volume thread clear_volume_flag();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//tag_origin delete();
|
|
}
|
|
}
|
|
|
|
clear_volume_flag()
|
|
{
|
|
wait( 1.5 );
|
|
self.playing_effect = false;
|
|
}
|
|
|
|
ceiling_rubble_onPlayerConnect()
|
|
{
|
|
while ( 1 )
|
|
{
|
|
level waittill( "connected", player );
|
|
player thread ceiling_rubble_watchUsage( "missile_fire" );
|
|
player thread ceiling_rubble_watchUsage( "grenade_fire" );
|
|
}
|
|
}
|
|
|
|
ceiling_rubble_watchUsage( note )
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
while ( 1 )
|
|
{
|
|
self waittill( note, missile, weaponName );
|
|
|
|
if ( IsDefined( weaponName ) )
|
|
{
|
|
switch ( weaponName )
|
|
{
|
|
case "ac130_25mm_mp":
|
|
case "flash_grenade_mp":
|
|
case "concussion_grenade_mp":
|
|
case "smoke_grenade_mp":
|
|
case "smoke_grenadejugg_mp":
|
|
continue;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
missile thread ceiling_rubble_missile_explode_watch();
|
|
}
|
|
}
|
|
|
|
endOnDeath()
|
|
{
|
|
self waittill( "death" );
|
|
waittillframeend;
|
|
self notify ( "end_of_frame_death" );
|
|
}
|
|
|
|
ceiling_rubble_missile_explode_watch()
|
|
{
|
|
self thread endOnDeath();
|
|
self endon( "end_of_frame_death" );
|
|
self waittill( "explode", position );
|
|
level notify( "do_rubble", position );
|
|
}
|
|
|
|
search_bot()
|
|
{
|
|
while ( !IsDefined( level.players ) || level.players.size == 0 )
|
|
wait 0.05;
|
|
|
|
allnodes = GetAllNodes();
|
|
current_node = random( allnodes );
|
|
player = level.players[ 0 ];
|
|
|
|
search_bot = Spawn( "script_model", current_node.origin );
|
|
search_bot SetModel( "com_deploy_ballistic_vest_friend_world" );
|
|
|
|
while ( 1 )
|
|
{
|
|
path_nodes = GetNodesOnPath( current_node.origin, player.origin );
|
|
if ( !IsDefined( path_nodes ) || path_nodes.size == 0 )
|
|
{
|
|
wait 0.1;
|
|
continue;
|
|
}
|
|
|
|
goal_node = path_nodes[ 0 ];
|
|
if ( Distance( search_bot.origin, path_nodes[ 0 ].origin ) < 6 )
|
|
{
|
|
if ( path_nodes.size <= 1 )
|
|
{
|
|
wait 0.1;
|
|
continue;
|
|
}
|
|
goal_node = path_nodes[ 1 ];
|
|
}
|
|
dir = goal_node.origin - current_node.origin;
|
|
dir_angles = VectorToAngles( dir );
|
|
|
|
speed = 180;
|
|
dist = Length( dir );
|
|
time = dist / speed;
|
|
|
|
if ( time <= 0 )
|
|
{
|
|
wait 0.1;
|
|
continue;
|
|
}
|
|
|
|
search_bot RotateTo( dir_angles, min( 0.5, time ) );
|
|
search_bot MoveTo( goal_node.origin, time );
|
|
search_bot waittill( "movedone" );
|
|
current_node = goal_node;
|
|
}
|
|
|
|
}
|
|
|
|
player_connect_watch()
|
|
{
|
|
while ( 1 )
|
|
{
|
|
level waittill( "connected", player );
|
|
if ( flag( "gas_station_exploded" ) )
|
|
{
|
|
hide_gas_station_physics_pieces();
|
|
}
|
|
}
|
|
}
|
|
|
|
hide_gas_station_physics_pieces()
|
|
{
|
|
structs = getstructarray( "gas", "targetname" );
|
|
foreach ( struct in structs )
|
|
{
|
|
foreach ( ent in struct.launch_ents )
|
|
{
|
|
ent Hide();
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( IsDefined( player.present_for_gas_station_explosion ) && ( player.present_for_gas_station_explosion == true ) )
|
|
{
|
|
ent ShowToPlayer( player );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
care_package_watch()
|
|
{
|
|
self endon( "end" );
|
|
|
|
watch_volume = GetEnt( "care_package_volume", "targetname" );
|
|
|
|
flag_wait( "gas_station_exploded" );
|
|
|
|
care_packages = level.carePackages;
|
|
if ( IsDefined( care_packages ) )
|
|
{
|
|
foreach ( package in care_packages )
|
|
{
|
|
if( IsDefined(package.inUse) && package.inUse )
|
|
continue;
|
|
|
|
if ( ( IsDefined(package.droppingtoground) && !package.droppingtoground ) && ( IsDefined( package.friendlyModel) && package.friendlyModel IsTouching( watch_volume ) ) )
|
|
{
|
|
owner = package.owner;
|
|
dropType = package.dropType;
|
|
crateType = package.crateType;
|
|
origin = package.origin;
|
|
|
|
package maps\mp\killstreaks\_airdrop::deleteCrate();
|
|
|
|
newCrate = owner maps\mp\killstreaks\_airdrop::createAirDropCrate( owner, dropType, crateType, origin + ( 0, 0, 250 ) , origin + ( 0, 0, 250 ) );
|
|
newCrate.droppingtoground = true;
|
|
|
|
newCrate thread [[ level.crateTypes[ newCrate.dropType ][ newCrate.crateType ].func ]]( newCrate.dropType );
|
|
|
|
waitframe();
|
|
|
|
newCrate CloneBrushmodelToScriptmodel( level.airDropCrateCollision );
|
|
newCrate thread entity_path_disconnect_thread( 1.0 );
|
|
newCrate PhysicsLaunchServer( newCrate.origin, ( 0, -20000, 20000 ) );
|
|
|
|
if ( IsBot( newCrate.owner ) )
|
|
{
|
|
wait( 0.1 );
|
|
newCrate.owner notify( "new_crate_to_take" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
deleteOnOwnerDeath( owner )
|
|
{
|
|
wait ( 0.25 );
|
|
self LinkTo( owner, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );
|
|
|
|
owner waittill ( "death" );
|
|
|
|
self Delete();
|
|
}
|
|
|
|
container_pathnode_watch()
|
|
{
|
|
node_array = GetNodeArray( "disconnect_until_container_opens", "targetname" );
|
|
|
|
foreach( pathnode in node_array )
|
|
{
|
|
pathnode DisconnectNode();
|
|
}
|
|
|
|
flag_wait( "breach_connect_nodes" );
|
|
|
|
foreach( pathnode in node_array )
|
|
{
|
|
pathnode ConnectNode();
|
|
}
|
|
} |