mirror of
https://github.com/reaaLx/nx1-gsc-dump.git
synced 2025-04-22 17:15:48 +00:00
1370 lines
41 KiB
Plaintext
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;
|
|
}
|
|
|