iw6-scripts-dev/maps/mp/mp_dart_events.gsc
2024-12-11 11:28:08 +01:00

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();
}
}