nx1-gsc-dump/maps/nx_exfil.gsc

1370 lines
41 KiB
Plaintext

//****************************************************************************
// **
// Confidential - (C) Activision Publishing, Inc. 2010 **
// **
//****************************************************************************
// **
// Module: SKYSCRAPER EXFIL **
// **
// Created: 11/10/2011 - John Webb **
// **
//****************************************************************************
#include maps\_utility;
#include common_scripts\utility;
#include maps\_anim;
#include maps\_vehicle;
//*******************************************************************
// *
// *
//*******************************************************************
main()
{
// External Initialization
maps\nx_exfil_precache::main();
maps\nx_exfil_fx::main();
// Setup starts
default_start( ::intro_seq );
add_start( "intro", ::intro_seq, "Intro", ::intro );
add_start( "market", ::market_start, "Market", ::market );
add_start( "street", ::street_start, "Street", ::street );
add_start( "alley", ::alley_start, "Alley", ::alley );
add_start( "market_dev", ::market_start_dev, "Market Dev", ::market );
add_start( "street_dev", ::street_start_dev, "Street Dev", ::street );
maps\_riotshield::init_riotshield();
maps\_load::main();
maps\nx_exfil_amb::main();
maps\_drone_ai::init();
// Internal Initialization
mission_flag_inits();
mission_precache();
thread maps\nx_exfil_fx::create_string_light_glows();
maps\nx_exfil_anim::main();
//set timescale factors
SoundSetTimeScaleFactor( "Music", 0 );
// Mission threads
level thread maps\nx_exfil_audio::mission_music();
level thread mission_objective_logic();
// Spotlight heli
level._default_player_threatbias = level._player.threatbias;
thread wait_for_spotlight_heli_trigger();
// Animated flags
thread animated_flags_logic();
lastroomtrigger = GetEnt( "lastroomtrigger", "targetname" );
lastroomtrigger thread triggervolumetest();
thread audio_outro_chaos();
barricade_vo_warning = GetEnt( "barricade_vo_warning", "targetname" );
barricade_vo_warning thread maps\nx_exfil_audio::police_barricade_warning_vo();
init_spawn_funcs();
}
triggervolumetest()
{
self waittill( "trigger" );
helicopter_pass = spawn( "sound_emitter", ( 4968, -1616, 694 ) );
helicopter_pass PlaySound( "emt_exfil_chaos_helicopter" );
helicopter_pass moveto( ( 6000, 64, 694 ), 11.0, .5, .5 );
indoor_steps = spawn( "sound_emitter", ( 4621, -870, 467 ) );
indoor_steps PlaySound( "emt_exfil_chaos_indoor_steps" );
indoor_steps moveto( ( 4549, -442, 467 ), 3.0, .5, .5 );
wait 8;
helicopter_pass2 = spawn( "sound_emitter", ( 6000, 64, 694 ) );
helicopter_pass2 PlaySound( "emt_exfil_chaos_helicopter" );
helicopter_pass2 moveto( ( 4968, -1616, 694 ), 11.0, .5, .5 );
indoor_steps2 = spawn( "sound_emitter", ( 4549, -442, 467 ) );
indoor_steps2 PlaySound( "emt_exfil_chaos_indoor_steps" );
indoor_steps2 moveto( ( 4621, -870, 467 ), 3.0, .5, .5 );
}
audio_outro_chaos()
{
level.audio_outro_emitter = spawn( "sound_emitter", ( 4945, -576, 380 ) );
level.audio_outro_emitter PlayloopSound( "emt_exfil_chaos_01" );
}
// All mission specific PreCache calls
mission_precache()
{
precachestring( &"NX_EXFIL_OBJ_GET_TO_EXFIL" );
}
// All mission specific flag_init() calls
mission_flag_inits()
{
// Global inits here
flag_init( "market_enc_end" );
// Map specific inits here
maps\nx_exfil_audio::flag_inits();
maps\nx_exfil_anim::flag_inits();
maps\nx_exfil_intro::flag_inits();
maps\nx_exfil_market::flag_inits();
maps\nx_exfil_street::flag_inits();
}
//*******************************************************************
// OBJECTIVES *
// *
//*******************************************************************
mission_objective_logic()
{
// Wait for friendlies to spawn
waittillframeend;
switch ( level._start_point )
{
case "default":
case "intro":
case "market":
case "market_dev":
case "street":
case "street_dev":
case "alley":
objective_add( obj( "obj_get_to_exfil" ), "current", &"NX_EXFIL_OBJ_GET_TO_EXFIL" );
break;
default:
AssertMsg( "No objectives set for this start point" );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
init_spawn_funcs()
{
array_thread( GetEntArray( "alley_group1", "targetname" ), ::add_spawn_function, ::enable_cqbwalk );
array_thread( GetEntArray( "alley_group2", "targetname" ), ::add_spawn_function, ::enable_cqbwalk );
array_thread( GetEntArray( "arcade_dudes", "targetname" ), ::add_spawn_function, ::enable_cqbwalk );
array_thread( GetEntArray( "swatvan1", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::ignore_on_jumpedout );
array_thread( GetEntArray( "cops", "script_noteworthy" ), ::add_spawn_function, maps\nx_exfil_util::cop_init );
// SWAT teams with lasers
array_thread( GetEntArray( "swatvan1", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "swatvan1_backup", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "market_group1", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "market_group2", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "market_side", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "market_interior_group1", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "streets_reinforcements", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "street_dudes", "script_noteworthy" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "street_group1", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "swat_van_barricade_troops", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "barricade_troops_A", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
array_thread( GetEntArray( "barricade_setup_troops_A", "targetname" ), ::add_spawn_function, maps\nx_exfil_util::enemy_lasers );
}
intro_seq()
{
maps\nx_exfil_intro::start();
}
intro()
{
maps\nx_exfil_intro::main();
}
//*******************************************************************
// MARKET *
//*******************************************************************
market_start()
{
// First section of the mission
maps\nx_exfil_market::start();
// lets put our player and Baker into the correct places
player_start = GetEnt( "postintro_player", "targetname" );
level._player teleport_player( player_start );
ally_start = GetStruct( "postintro_ally1", "targetname" );
level.allies[ "ally1" ] forceTeleport( ally_start.origin, ally_start.angles );
}
market_start_dev()
{
battlechatter_off( "allies" );
battlechatter_off( "axis" );
market_start();
}
market()
{
//temp music_chk flag
//flag_set( "music_chk_market" );
maps\nx_exfil_market::main();
flag_wait( "market_enc_end" );
}
//*******************************************************************
// STREET *
//*******************************************************************
street_start()
{
// First section of the mission
maps\nx_exfil_street::start();
}
street_start_dev()
{
battlechatter_off( "allies" );
battlechatter_off( "axis" );
street_start();
}
street()
{
//temp music_chk flag
//flag_set( "music_chk_street" );
maps\nx_exfil_street::main();
}
//*******************************************************************
// ALLEY *
//*******************************************************************
alley_start()
{
// First section of the mission
maps\nx_exfil_alley::start();
}
alley()
{
maps\nx_exfil_alley::main();
}
//*******************************************************************
// *
// *
//*******************************************************************
wait_for_spotlight_heli_trigger()
{
// There are 2 paths the heli can start on
thread setup_spotlight_heli_intro_path();
thread setup_spotlight_heli_market_path();
}
//*******************************************************************
// *
// *
//*******************************************************************
setup_spotlight_heli_intro_path()
{
level endon( "start_spotlight_heli_market_path" );
flag_wait( "start_spotlight_heli_intro_path" );
thread setup_spotlight_heli( "heli_intro_path" );
}
//*******************************************************************
// *
// *
//*******************************************************************
setup_spotlight_heli_market_path()
{
level endon( "start_spotlight_heli_intro_path" );
flag_wait( "start_spotlight_heli_market_path" );
thread setup_spotlight_heli( "heli_market_path" );
}
//*******************************************************************
// *
// *
//*******************************************************************
setup_spotlight_heli( start_path_node_targetname, first_heli )
{
if ( !IsDefined( first_heli ) )
{
first_heli = true;
}
// Grab the heli
//spotlight_heli = spawn_vehicle_from_targetname_and_drive( "littlebird_spotlight" );
spotlight_heli = spawn_vehicle_from_targetname( "littlebird_spotlight" );
level._spotlight_heli = spotlight_heli;
node = GetStruct( start_path_node_targetname, "targetname" );
spotlight_heli thread vehicle_paths( node );
spotlight_heli thread maps\nx_exfil_audio::police_bullhorn_vo();
spotlight_heli thread heli_target_dialogue();
// Sanity check
if ( !IsDefined( spotlight_heli ) )
{
return;
}
spotlight_heli endon( "death" );
spotlight_heli maps\_vehicle::set_heli_move( "faster" );
// Set up some vars
spotlight_heli._state = "reveal";
spotlight_heli._section = "market";
spotlight_heli._spotTarget_last_known_pos = ( 0, 0, 0 );
spotlight_heli._default_speed = 18;
spotlight_heli._evade_health_threshold = 0.9;
spotlight_heli._num_evasions = 2;
spotlight_heli._reacquire_player_time = GetTime() + 9000;
spotlight_heli._focus_ally = false;
spotlight_heli._damage_fx = "none";
// Play progressive damage fx
//spotlight_heli thread spotlight_heli_damage_fx_process();
// Heli runs away when the player attacks
spotlight_heli thread spotlight_heli_evasive_think();
spotlight_heli thread spotlight_heli_on_death();
spotlight_heli thread spotlight_heli_trigger_death();
// Initiate pathing
//spotlight_heli thread maps\_attack_heli::heli_circling_think( "attack_heli_circle_node", 50, maps\_attack_heli::heli_circle_node_choice );
spotlight_heli gopath();
spotlight_heli Vehicle_SetSpeed( spotlight_heli._default_speed, 15, 15 );
// Set up spotlight
spotlight_heli.eTarget = level._player;
spotlight_heli maps\_attack_heli::heli_default_target_setup();
spotlight_heli thread maps\_attack_heli::heli_spotlight_on( "tag_barrel" , false, true );
spotlight_heli thread maps\_attack_heli::heli_spotlight_aim( ::spotlight_heli_think );
spotlight_heli thread spotlight_heli_check_vision_set();
// Slow down the rotation
spotlight_heli spotlight_heli_update_spotlight_speed( 0.33 );
if ( first_heli )
{
// Point in front of player
forward = AnglesToForward( level._player.angles );
forwardfar = vector_multiply( forward, 500 );
spot_vect = forwardfar + randomvector( 50 );
spotlight_heli.spotTarget = Spawn( "script_origin", ( level._player.origin + forwardfar ) );
spotlight_heli maps\_attack_heli::heli_spotlight_destroy_default_targets();
spotlight_heli maps\_attack_heli::heli_spotlight_create_default_targets( spotlight_heli.spotTarget );
// Path-swapping logic
spotlight_heli thread spotlight_heli_street_path_1_think();
//spotlight_heli thread spotlight_heli_street_path_2_think();
// Logic to focus on ally after market section
//spotlight_heli thread spotlight_heli_focus_ally_think();
// Heli logic for final encounter
spotlight_heli thread spotlight_heli_final_encounter_think();
}
return spotlight_heli;
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_update_spotlight_speed( speed_mult )
{
self SetTurretRotationSpeedMultiplier( speed_mult );
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_street_path_1_think()
{
self endon( "death" );
flag_wait( "heli_street_path_1_swap" );
self vehicle_pathdetach();
node = GetStruct( "heli_street_path_1", "targetname" );
self thread vehicle_paths( node );
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_street_path_2_think()
{
self endon( "death" );
flag_wait( "heli_street_path_2_swap" );
self vehicle_pathdetach();
node = GetStruct( "heli_street_path_2", "targetname" );
self thread vehicle_paths( node );
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_check_vision_set()
{
self endon( "death" );
vision_swap_time = 0.25;
while ( 1 )
{
if ( maps\_attack_heli::can_see_player( level._player ) )
{
pos = self GetTagOrigin( "TAG_FLASH" );
angles = self GetTagAngles( "TAG_FLASH" );
forward = AnglesToForward( angles );
eye_vect = ( level._player GetEye() ) - pos;
eye_vect = VectorNormalize( eye_vect );
angle = acos( VectorDot( forward, eye_vect ) );
if ( angle < 10 )
{
// In spotlight
vision_set = "nx_exfil_spotlight";
if ( self._section == "street" )
{
vision_set = "nx_exfil_spotlight_2";
}
VisionSetNaked( vision_set, vision_swap_time );
}
else
{
// Not in spotlight
VisionSetNaked( "nx_exfil", vision_swap_time );
}
}
else
{
// Not in spotlight
VisionSetNaked( "nx_exfil", vision_swap_time );
}
wait vision_swap_time;
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_final_encounter_think()
{
flag_wait( "heli_street_path_2_swap" );
// If previously killed, spawn another
if ( !IsDefined( self ) )
{
spotlight_heli = setup_spotlight_heli( "heli_focus_player_pos", false );
}
else
{
spotlight_heli = self;
}
spotlight_heli._section = "street";
spotlight_heli endon( "market_enc_end" );
spotlight_heli thread spotlight_heli_final_reveal();
spotlight_heli thread spotlight_heli_target_straight_down();
// Go hide, to give the player a breather
spotlight_heli vehicle_pathdetach();
node = GetStruct( "heli_hide_pos", "targetname" );
spotlight_heli SetVehGoalPos( node.origin, true );
spotlight_heli waittill( "near_goal" );
// Point toward player
spotlight_heli maps\nx_exfil_fx::turn_off_heli_spotlight_fx();
spotlight_heli SetLookAtEnt( level._player );
spotlight_heli SetTurretTargetEnt( level._player );
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_target_straight_down()
{
self endon( "market_enc_end" );
self endon( "near_goal" );
self endon( "death" );
self._state = "waiting";
self spotlight_heli_update_spotlight_speed( 0.33 );
self.spotTarget = Spawn( "script_origin", ( self.origin * ( 1, 1, 0 ) ) + ( 0, 0, 100 ) );
while ( 1 )
{
wait 0.05;
self.spotTarget.origin = ( self.origin * ( 1, 1, 0 ) ) + ( 0, 0, 100 );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_final_reveal()
{
self endon( "death" );
// Wait for trigger
flag_wait( "market_enc_end" );
self notify( "market_enc_end" );
// Point toward player
self spotlight_heli_update_spotlight_speed( 5.0 );
self SetLookAtEnt( level._player );
self SetTurretTargetEnt( level._player );
// Fly to middle of streen and turn on spotlight
node = GetStruct( "heli_focus_player_pos", "targetname" );
self SetVehGoalPos( node.origin, false );
self thread vehicle_paths( node );
self waittill( "near_goal" );
self Vehicle_SetSpeed( self._default_speed, 15, 15 );
self.spotTarget = level._player;
self maps\nx_exfil_fx::turn_on_heli_spotlight_fx();
//self._state = "waiting";
wait 5;
// Do a fly over the player
self Vehicle_SetSpeed( 25, 15, 15 );
node = GetStruct( "heli_flyover_pos", "targetname" );
self SetVehGoalPos( node.origin, true );
self waittill( "near_goal" );
// Resume position above street
self Vehicle_SetSpeed( 20, 15, 15 );
self spotlight_heli_set_focus_ally();
}
//*******************************************************************
// *
// *
//*******************************************************************
/*spotlight_heli_focus_ally_think()
{
//self endon( "death" );
//flag_wait( "market_enc_end" );
flag_wait( "heli_street_path_2_swap" );
if ( !IsDefined( self ) )
{
self = setup_spotlight_heli( "heli_focus_ally_pos", false );
}
self spotlight_heli_set_focus_ally();
self._section = "street";
}*/
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_set_focus_ally()
{
self endon( "death" );
self._focus_ally = true;
// Set up an array of things to look at
ally = level.allies[ "ally1" ];
heli_look_at[0] = ally;
heli_look_at[1] = level._player;
barricade_riot_spotlight = GetStruct( "barricade_riot_spotlight", "script_noteworthy" );
heli_look_at[2] = Spawn( "script_origin", barricade_riot_spotlight.origin );
heli_look_at[2].angles = barricade_riot_spotlight.angles;
heli_look_at[3] = get_living_ai( "turret_gunner", "script_noteworthy" );
self.spotTarget = ally;
self._state = "targeting";
// Speed up the rotation
self delayThread( 1.0, ::spotlight_heli_update_spotlight_speed, 5.0 );
spotlight_heli_set_threatbias( "none" );
self vehicle_pathdetach();
node = GetStruct( "heli_focus_ally_pos", "targetname" );
self SetVehGoalPos( node.origin, false );
self thread vehicle_paths( node );
self waittill( "near_goal" );
self Vehicle_SetSpeed( self._default_speed, 15, 15 );
while ( 1 )
{
if ( self.spotTarget != heli_look_at[2] )
{
wait( RandomFloatRange( 3.5, 5.5 ) );
}
else
{
wait( RandomFloatRange( 1.5, 3.0 ) );
}
// First, ensure the turret gunner is still there
if ( heli_look_at.size > 3 && !IsDefined( heli_look_at[3] ) )
{
heli_look_at = array_remove( heli_look_at, heli_look_at[3] );
}
// Choose a new target
self.spotTarget = heli_look_at[ RandomInt( heli_look_at.size ) ];
self SetLookAtEnt( self.spotTarget );
if ( maps\_attack_heli::can_see_player( self.spotTarget ) )
{
self._spotTarget_last_known_pos = self.spotTarget.origin;
}
else if ( self.spotTarget == level._player )
{
// Point in front of player
forward = AnglesToForward( self.spotTarget.angles );
forwardfar = vector_multiply( forward, 500 );
spot_vect = forwardfar + randomvector( 50 );
self._spotTarget_last_known_pos = ( self.spotTarget.origin + spot_vect );
}
// Slow down the spotlight
spotlight_heli_update_spotlight_speed( 0.33 );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
heli_target_dialogue()
{
self endon( "death" );
flag_wait( "heli_intro_dialogue_complete" );
wait 0.5;
current_target = undefined;
while ( 1 )
{
if ( isDefined( self.spottarget ) )
{
if ( !isDefined( current_target ) || current_target != self.spottarget )
{
current_target = self.spottarget;
if ( isDefined( current_target ) && isPlayer( current_target ) )
{
level.baker radio_dialogue( "exf_bak_helo_outofsight" ); // Spotlight's drawing heat! Get out of sight!
return; // Only do this dialogue once
}
}
}
wait 1.0;
}
}
//*******************************************************************
// *
// *
//*******************************************************************
/*spotlight_heli_damage_fx_process()
{
self endon( "death" );
self endon( "crashing" );
while ( 1 )
{
self waittill( "damage", damage, attacker );//, direction_vec, P, type );
curr_health = ( self.health - self.healthbuffer );
assert( self.script_startinghealth > 0 );
health_percent = ( curr_health / self.script_startinghealth );
// Damage FX Checks
if ( health_percent < 0.75 && health_percent > 0.5 && self._damage_fx == "none" )
{
self._damage_fx = "light";
maps\nx_exfil_fx::spotlight_heli_damage_fx( "light" );
}
else if ( health_percent < 0.5 && health_percent > 0.25 && self._damage_fx == "light" )
{
self._damage_fx = "med";
maps\nx_exfil_fx::spotlight_heli_damage_fx( "med" );
}
else if ( health_percent < 0.25 && health_percent > 0.0 && self._damage_fx == "med" )
{
self._damage_fx = "heavy";
maps\nx_exfil_fx::spotlight_heli_damage_fx( "heavy" );
return;
}
wait 0.05;
}
}*/
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_evasive_think()
{
self endon( "death" );
self endon( "crashing" );
while ( 1 )
{
// Wait until the player attacks
self waittill( "damage", damage, attacker );//, direction_vec, P, type );
if ( !IsDefined( attacker ) || !IsPlayer( attacker ) )
{
continue;
}
// Check evasion health threshold to see if the heli should run away
curr_health = ( self.health - self.healthbuffer );
assert( self.script_startinghealth > 0 );
health_percent = ( curr_health / self.script_startinghealth );
if ( health_percent < self._evade_health_threshold )
{
self._evade_health_threshold -= 0.1;
self._num_evasions -= 1;
// Damage FX Checks
if ( self._damage_fx == "none" )
{
self._damage_fx = "light";
maps\nx_exfil_fx::spotlight_heli_damage_fx( "light" );
}
else if ( self._damage_fx == "light" )
{
self._damage_fx = "med";
maps\nx_exfil_fx::spotlight_heli_damage_fx( "med" );
}
else if ( self._damage_fx == "med" )
{
self._damage_fx = "heavy";
maps\nx_exfil_fx::spotlight_heli_damage_fx( "heavy" );
}
}
else
{
continue;
}
// Fly off to the outside (right)
right = AnglesToRight( self.angles );
// Magic #'s, 600 insures it goes to a lower position than the flight path
new_pos = ( ( self.origin + ( right * 5000 ) ) * ( 1, 1, 0 ) ) + ( 0, 0, 600 );
// Ensure the heli can see the evasion location
while ( !BulletTracePassed( self.origin, new_pos, false, self ) )
{
// Can't see, so wait a bit
wait 0.25;
// Recalculate
right = AnglesToRight( self.angles );
new_pos = ( ( self.origin + ( right * 5000 ) ) * ( 1, 1, 0 ) ) + ( 0, 0, 600 );
}
self vehicle_pathdetach();
self Vehicle_SetSpeed( 85, 30, 30 );
self SetVehGoalPos( new_pos, true );
//self SetNearGoalNotifyDist( 300 );
wait RandomIntRange( 4, 8 );
self Vehicle_SetSpeed( self._default_speed, 15, 15 );
if ( self._focus_ally )
{
ally = level.allies[ "ally1" ];
node = GetStruct( "heli_focus_ally_pos", "targetname" );
self SetVehGoalPos( node.origin, false );
self thread vehicle_paths( node );
self waittill( "near_goal" );
self SetLookAtEnt( ally );
}
else
{
self vehicle_resumepath();
// Wait until it gets back on the path before starting the logic over again
self waittill( "near_goal" );
}
if ( self._num_evasions <= 0 )
{
return;
}
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_on_death()
{
self waittill( "death" );
spotlight_heli_set_threatbias( "none" );
VisionSetNaked( "nx_exfil", 0.25 );
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_trigger_death()
{
self endon( "death" );
flag_wait( "alley_begin" );
if ( IsDefined( level._spotlight_heli ) )
{
// Fly off and die
back = AnglesToForward( level._spotlight_heli.angles ) * -1;
// Magic #'s, 600 insures it goes to a lower position than the flight path
new_pos = ( ( level._spotlight_heli.origin + ( back * 10000 ) ) * ( 1, 1, 0 ) ) + ( 0, 0, 600 );
level._spotlight_heli vehicle_pathdetach();
level._spotlight_heli Vehicle_SetSpeed( 100, 40, 40 );
level._spotlight_heli SetVehGoalPos( new_pos, true );
level._spotlight_heli waittill( "near_goal" );
level._spotlight_heli Delete();
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_set_threatbias( target )
{
ally = level.allies[ "ally1" ];
// Force no threatbias during the last encounter (barricade)
if ( IsDefined( level._spotlight_heli ) && level._spotlight_heli._focus_ally == true )
{
target = "none";
}
switch ( target )
{
case "player":
// Set threatbias really high so enemies will target when they are in spotlight
level._player.threatbias = 1000;
level._player.attackeraccuracy = 1.3;
if ( IsDefined( ally ) )
{
ally.threatbias = 0;
}
break;
case "ally":
// Set threatbias really high so enemies will target when they are in spotlight
if ( IsDefined( ally ) )
{
ally.threatbias = 1000;
}
level._player.threatbias = 0;
level._player.attackeraccuracy = 0.7;
break;
case "none":
level._player.threatbias = level._default_player_threatbias;
level._player.attackeraccuracy = 1.0;
if ( IsDefined( ally ) )
{
ally.threatbias = 200;
}
break;
default:
assert( "need to pass in a target to spotlight_heli_set_threatbias" );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_default_targeting()
{
self endon( "death" );
iRand = RandomInt( level._spotlight_aim_ents.size );
self.targetdefault = level._spotlight_aim_ents[ iRand ];
self.spotTarget = self.targetdefault;
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_stop_circling()
{
self notify( "stop_circling" );
self notify( "stop_shooting" );
self.circling = false;
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_resume_circling()
{
self thread maps\_attack_heli::heli_circling_think( "attack_heli_circle_node", 50, maps\_attack_heli::heli_circle_node_choice );
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_think()
{
self endon( "death" );
while ( 1 )
{
wait( RandomFloatRange( 1, 3 ) );
switch ( self._state )
{
case "reveal":
self thread spotlight_heli_reveal_state();
break;
case "searching":
self thread spotlight_heli_searching_state();
break;
case "targeting":
self thread spotlight_heli_targeting_state();
break;
case "reacquire":
self thread spotlight_heli_reacquire_state();
break;
case "waiting":
// Do nothing
break;
default:
assert( "spotlight heli has invalid state" );
break;
}
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_reveal_state()
{
self endon( "death" );
if ( GetTime() > self._reacquire_player_time )
{
self maps\_attack_heli::heli_spotlight_destroy_default_targets();
self._state = "searching";
}
else
{
// Point in front of player
self maps\_attack_heli::heli_spotlight_destroy_default_targets();
forward = AnglesToForward( level._player.angles );
forwardfar = vector_multiply( forward, 500 );
spot_vect = forwardfar + randomvector( 50 );
self.spotTarget = Spawn( "script_origin", ( level._player.origin + forwardfar ) );
self maps\_attack_heli::heli_spotlight_create_default_targets( self.spotTarget );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_searching_state()
{
self endon( "death" );
ally = level.allies[ "ally1" ];
can_see_player = ( ( self._focus_ally == false ) && maps\_attack_heli::can_see_player( level._player ) );
can_see_ally = ( IsDefined( ally ) && maps\_attack_heli::can_see_player( ally ) );
target_player = false;
target_ally = false;
// Both in line of sight
if ( can_see_player && can_see_ally )
{
// Give player more chance to be targeted (66%)
iRand = RandomInt( 3 );
if ( iRand == 2 )
{
target_ally = true;
}
else
{
target_player = true;
}
}
else if ( can_see_player )
{
target_player = true;
}
else if ( can_see_ally )
{
target_ally = true;
}
else// otherwise just aim at one of the default targets
{
self spotlight_heli_default_targeting();
spotlight_heli_set_threatbias( "none" );
}
if ( target_player )
{
self.spotTarget = level._player;
self._state = "targeting";
// Speed up the rotation
self delayThread( 1.0, ::spotlight_heli_update_spotlight_speed, 5.0 );
spotlight_heli_set_threatbias( "player" );
}
else if ( target_ally )
{
self.spotTarget = ally;
self._state = "targeting";
// Speed up the rotation
self delayThread( 1.0, ::spotlight_heli_update_spotlight_speed, 5.0 );
spotlight_heli_set_threatbias( "ally" );
}
else
{
// Slow down the rotation
self spotlight_heli_update_spotlight_speed( 0.33 );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_targeting_state()
{
self endon( "death" );
ally = level.allies[ "ally1" ];
// Stay in this state as long as the heli can still see the target
if ( IsDefined( self.spotTarget ) && maps\_attack_heli::can_see_player( self.spotTarget ) )
{
self._spotTarget_last_known_pos = self.spotTarget.origin;
//self spotlight_heli_stop_circling();
// Chance to re-target player
if ( self._focus_ally == false )
{
if ( self.spotTarget != level._player )
{
iRand = RandomInt( 4 );
if ( iRand == 2 )
{
if ( maps\_attack_heli::can_see_player( level._player ) )
{
self.spotTarget = level._player;
self._spotTarget_last_known_pos = level._player.origin;
// Slow down the rotation, then delay speed it up
self spotlight_heli_update_spotlight_speed( 0.75 );
self delayThread( 0.75, ::spotlight_heli_update_spotlight_speed, 5.0 );
spotlight_heli_set_threatbias( "player" );
}
}
}
else if ( self.spotTarget != ally ) // Chence to re-target ally
{
iRand = RandomInt( 7 );
if ( iRand == 3 )
{
if ( maps\_attack_heli::can_see_player( ally ) )
{
self.spotTarget = ally;
self._spotTarget_last_known_pos = ally.origin;
// Slow down the rotation, then delay speed it up
self spotlight_heli_update_spotlight_speed( 0.75 );
self delayThread( 0.75, ::spotlight_heli_update_spotlight_speed, 5.0 );
spotlight_heli_set_threatbias( "ally" );
}
}
}
}
}
else
{
self.prevSpotTarget = self.spotTarget;
self.spotTarget = Spawn( "script_origin", self._spotTarget_last_known_pos );
self.spotTarget.angles = level._player.angles;
self._reacquire_player_time = GetTime() + 3000;
if ( self._focus_ally == false )
{
self._reacquire_ally_time = GetTime() + 10000;
}
else
{
self._reacquire_ally_time = GetTime() + 2500;
}
self maps\_attack_heli::heli_spotlight_destroy_default_targets();
self maps\_attack_heli::heli_spotlight_create_default_targets( self.spotTarget );
//self spotlight_heli_resume_circling();
spotlight_heli_set_threatbias( "none" );
self._state = "reacquire";
// Slow down the rotation
self spotlight_heli_update_spotlight_speed( 0.33 );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
spotlight_heli_reacquire_state()
{
self endon( "death" );
ally = level.allies[ "ally1" ];
// When heli loses sight of target, it will sweep the area of target's
// "last known position", and continue to do so until the target goes beyond
// a certain proximity.
if ( IsDefined( self.prevSpotTarget ) && IsDefined( self._spotTarget_last_known_pos ) && Distance( self.prevSpotTarget.origin, self._spotTarget_last_known_pos ) > 500 )
{
self maps\_attack_heli::heli_spotlight_destroy_default_targets();
self spotlight_heli_default_targeting();
self._state = "searching";
}
else if ( ( GetTime() > self._reacquire_player_time ) && maps\_attack_heli::can_see_player( level._player ) )
{
self maps\_attack_heli::heli_spotlight_destroy_default_targets();
self.spotTarget = level._player;
self._state = "targeting";
// Speed up the rotation
self delayThread( 1.0, ::spotlight_heli_update_spotlight_speed, 5.0 );
spotlight_heli_set_threatbias( "player" );
}
else if ( ( GetTime() > self._reacquire_ally_time ) && IsDefined( ally ) && maps\_attack_heli::can_see_player( ally ) )
{
self maps\_attack_heli::heli_spotlight_destroy_default_targets();
self.spotTarget = ally;
self._state = "targeting";
// Speed up the rotation
self delayThread( 1.0, ::spotlight_heli_update_spotlight_speed, 5.0 );
spotlight_heli_set_threatbias( "ally" );
}
}
//*******************************************************************
// *
// *
//*******************************************************************
#using_animtree( "animated_props" );
animated_flags_logic()
{
waittillframeend;
wind_radius = 550.0;
flags = [];
flags[0] = GetEnt( "swaying_flag01", "script_noteworthy" );
origin_swaying_flag01 = GetEnt( "origin_swaying_flag01", "script_noteworthy" );
flags[0].pos = origin_swaying_flag01.origin * ( 1, 1, 0 );
flags[0].slow_anim = %nx_pr_exfil_swinging_flag_slow_01;
flags[0].fast_anim = %nx_pr_exfil_swinging_flag_fast_01;
flags[0] SetAnim( flags[0].slow_anim, 1, 0, 1 );
flags[0] SetAnim( flags[0].fast_anim, 0, 0, 1 );
flags[1] = GetEnt( "swaying_flag02", "script_noteworthy" );
origin_swaying_flag02 = GetEnt( "origin_swaying_flag02", "script_noteworthy" );
flags[1].pos = origin_swaying_flag02.origin * ( 1, 1, 0 );
flags[1].slow_anim = %nx_pr_exfil_swinging_flag_slow_02;
flags[1].fast_anim = %nx_pr_exfil_swinging_flag_fast_02;
flags[1] SetAnim( flags[1].slow_anim, 1, 0, 1 );
flags[1] SetAnim( flags[1].fast_anim, 0, 0, 1 );
flags[2] = GetEnt( "swaying_flag03", "script_noteworthy" );
origin_swaying_flag03 = GetEnt( "origin_swaying_flag03", "script_noteworthy" );
flags[2].pos = origin_swaying_flag03.origin * ( 1, 1, 0 );
flags[2].slow_anim = %nx_pr_exfil_swinging_flag_slow_03;
flags[2].fast_anim = %nx_pr_exfil_swinging_flag_fast_03;
flags[2] SetAnim( flags[2].slow_anim, 1, 0, 1 );
flags[2] SetAnim( flags[2].fast_anim, 0, 0, 1 );
flags[3] = GetEnt( "swaying_flag04", "script_noteworthy" );
origin_swaying_flag04 = GetEnt( "origin_swaying_flag04", "script_noteworthy" );
flags[3].pos = origin_swaying_flag04.origin * ( 1, 1, 0 );
flags[3].slow_anim = %nx_pr_exfil_swinging_flag_slow_04;
flags[3].fast_anim = %nx_pr_exfil_swinging_flag_fast_04;
flags[3] SetAnim( flags[3].slow_anim, 1, 0, 1 );
flags[3] SetAnim( flags[3].fast_anim, 0, 0, 1 );
flags[4] = GetEnt( "swaying_flag06", "script_noteworthy" );
origin_swaying_flag06 = GetEnt( "origin_swaying_flag06", "script_noteworthy" );
flags[4].pos = origin_swaying_flag06.origin * ( 1, 1, 0 );
flags[4].slow_anim = %nx_pr_exfil_swinging_flag_slow_06;
flags[4].fast_anim = %nx_pr_exfil_swinging_flag_fast_06;
flags[4] SetAnim( flags[4].slow_anim, 1, 0, 1 );
flags[4] SetAnim( flags[4].fast_anim, 0, 0, 1 );
flag_wait( "heli_street_path_2_swap" );
while ( 1 )
{
if ( !IsDefined( level._spotlight_heli ) )
{
return;
}
wind_src_pos = level._spotlight_heli.origin * ( 1, 1, 0 );
foreach ( flag in flags )
{
dist = Length( wind_src_pos - flag.pos );
if ( dist < wind_radius )
{
flag notify( "aggressive" );
flag thread animated_flag_aggressive();
}
}
wait 0.05;
}
}
//*******************************************************************
// *
// *
//*******************************************************************
#using_animtree( "animated_props" );
animated_flag_aggressive()
{
self endon( "aggressive" );
self SetAnimKnob( self.fast_anim, 1, 0.25, 1 );
wait RandomFloatRange( 1.0, 1.2 );
ramp_down = RandomFloatRange( 1.6, 2.0 );
self SetAnimKnob( self.slow_anim, 1, ramp_down, 1 );
wait ramp_down;
}