//**************************************************************************** // ** // Confidential - (C) Activision Publishing, Inc. 2011 ** // ** //**************************************************************************** // ** // Module: Nx_Hospital - Atrium / Construction area ** // ** // Created: 11/11/11 - Justin Rote ** // ** //**************************************************************************** #include maps\_utility; #include common_scripts\utility; #include maps\_anim; #include maps\_vehicle; //******************************************************************* // * // ATRIUM - Construction area * // * //******************************************************************* start() { maps\nx_hospital_util::actor_teleport( level.squad[ "ALLY_ALPHA" ], "atrium_start_alpha" ); maps\nx_hospital_util::actor_teleport( level.squad[ "ALLY_BRAVO" ], "atrium_start_bravo" ); level._player maps\_nx_utility::move_player_to_start_point( "atrium_start_player" ); } section_precache() { PreCacheRumble( "artillery_rumble" ); } section_flag_inits() { flag_init( "allies_move_down" ); flag_init( "atrium_clear" ); // -=TEMPORARY HACK FIX=- // JR - This is a hack and should not be here. // I had to do this because the previous section // was not threaded correctly and will block // untill it is fully completed. level.atrium_spawn_funcs_assigned = false; thread atrium_wave_logic(); } //******************************************************************* // * // * //******************************************************************* main() { // Allies go loud level.squad[ "ALLY_ALPHA" ].ignoreAll = false; level.squad[ "ALLY_BRAVO" ].ignoreAll = false; level.squad[ "ALLY_ALPHA" ].ignoreMe = false; level.squad[ "ALLY_BRAVO" ].ignoreMe = false; // Handle counting number of enemies killed thread atrium_wave_logic(); // Main logic thread for the encounter thread atrium_logic(); // Make it hard for the player to rush through the area thread atrium_exit_rush_logic(); // Makes the last few enemies more aggressive thread atrium_straggler_cleanup(); // Handle the exploding tank thread atrium_exploding_tank(); // If they reach the exit, move on to Hospital section flag_wait( "atrium_exit" ); // Cleanup remaining guys thread atrium_cleanup(); } //******************************************************************* // * // * //******************************************************************* // Main encounter thread atrium_logic() { // Move Baker up issue_color_orders( "b200", "allies" ); wait 1.75; // Move Keene up issue_color_orders( "g200", "allies" ); // Wait for X kills, and move up flag_wait( "player_at_perch" ); issue_color_orders( "b205", "allies" ); // Alters threatbias if the player stays up top for a long time delayThread( 20, ::atrium_handle_attacker_accuracy ); // Tell player to move down if they stay up top too long thread atrium_perch_warning(); wait 1.25; issue_color_orders( "g205", "allies" ); wait 4; // Baker: "Move up!" level.squad[ "ALLY_ALPHA" ] play_dialogue( "hos_bak_const_moveup", 0 ); wait 8; trigger = getent( "atrium_wave_2", "script_noteworthy" ); if ( isdefined( trigger ) ) { trigger notify( "trigger" ); } // Wait for X kills, and move up //wait_for_num_kills( 6 ); //remove_trigger( "trigger_construction_210" ); //issue_color_orders( "b220 g220", "allies" ); // Wait for X kills, and move up //wait_for_num_kills( 16 ); //remove_trigger( "trigger_construction_220" ); //issue_color_orders( "b230 g230", "allies" ); trigger = getent( "atrium_wave_3", "script_noteworthy" ); level notify( "atrium_wave_3_go" ); if ( isdefined( trigger ) ) { trigger notify( "trigger" ); } //****************************************************************** // Atrium Clear //****************************************************************** // Wait for atrium to be clear, and player hits exit flag flag_wait( "atrium_clear" ); // Cleanup AI trigs remove_trigger( "trigger_construction_allies" ); // Natural pause after last kill wait 2.82; // Move allies up thread move_allies_into_exit_corridor(); // Keene: "Clear!" level.squad[ "ALLY_BRAVO" ] play_dialogue( "hos_jenk_const_clear", 0 ); wait 1.1; // Baker: "We're clear!" level.squad[ "ALLY_ALPHA" ] play_dialogue( "hos_bak_const_wereclear", 0 ); wait 0.64; // Baker: "Let's go!" level.squad[ "ALLY_ALPHA" ] play_dialogue( "hos_bak_const_letsgo", 0 ); } // Moves allies up into the exit corridor section move_allies_into_exit_corridor() { trigger = GetEnt ("corridor_grenade_trigger", "targetname"); trigger endon ("trigger"); if( !flag( "atrium_exit" )) { // Moves allies up to outter door issue_color_orders( "b298 g298", "allies" ); // Wait for player to get close flag_wait( "player_at_atrium_exit" ); // Enable CQB maps\nx_hospital_util::squad_cqb( true ); // Keen moves up to K2 issue_color_orders( "g299", "allies" ); wait 2.5; // Baker moves up to b2 issue_color_orders( "b300", "allies" ); wait 1.5; // Baker: "It's too quiet" level.squad[ "ALLY_ALPHA" ] dialogue_queue( "hos_bak_corr_tooquiet" ); wait 2.5; // Keene moves up to k3 issue_color_orders( "g300", "allies" ); // Baker: "Take point" level.squad[ "ALLY_ALPHA" ] dialogue_queue( "hos_bak_corr_takepoint" ); } // Player rushed ahead, skip the VO and move allies up to 300 else { issue_color_orders( "b300 g300", "allies" ); } } // Init for the kill counter logic atrium_wave_logic() { if( !level.atrium_spawn_funcs_assigned ) { wave_counters = getentarray( "atrium_wave_counter", "script_noteworthy" ); array_thread( wave_counters, ::add_spawn_function, ::atrium_wave_counter ); level.wave_count = 0; level.atrium_spawn_funcs_assigned = true; } } // Keeps track of number of kills atrium_wave_counter() { self waittill( "death" ); level.wave_count++; } // If the player stays up top too long, they get called down atrium_perch_warning() { level endon( "atrium_clear" ); // Baker: "Get down here!" // Baker: "Get down here now!" // Baker: "Get out of there!" warning_vo_array = [ "hos_bak_const_getdown", "hos_bak_const_getdownhere", "hos_bak_const_getoutofhere" ]; wait 16; // Start rooftop warner while( flag( "flag_atrium_player_on_perch" )) { random_warner = Random( warning_vo_array ); level.squad[ "ALLY_ALPHA" ] play_dialogue( random_warner, 0 ); wait( RandomFloatRange( 18.0, 28.0 )); } } // Cleans up remaining enemies after you leave the area atrium_cleanup() { flag_wait( "atrium_cleanup" ); // Make sure no new guys spawn thread maps\_spawner::kill_spawnerNum( 210 ); thread maps\_spawner::kill_spawnerNum( 220 ); thread maps\_spawner::kill_spawnerNum( 240 ); // Kill off any remaining guys remaining_guys = get_ai_group_ai( "atrium_guys" ); foreach( guy in remaining_guys ) { guy thread maps\nx_hospital_util::delete_after_time( randomFloatRange( 1.5, 2.5 )); } } // Make it hard for the player to rush the exit door atrium_exit_rush_logic() { level endon( "atrium_wave_3_go" ); level endon( "atrium_clear" ); flag_wait( "flag_atrium_player_at_exit" ); // Spawn some very unhappy shotgunner guys blocking the exit array_spawn_targetname( "rush_stopper_guys" ); // Die!! level._player.attackerAccuracy = 1000; level._player.threatbias = 1000; thread reset_rush_penalty_after_time( 8 ); } // If the player somehow manages to live through this, fine, reset everything and let them continue. reset_rush_penalty_after_time( time ) { wait time; level._player.attackerAccuracy = 1; level._player.threatbias = 0; } // Increases enemy accuracy if the player hangs out up top // JR - I don't think I like this... atrium_handle_attacker_accuracy() { level endon( "atrium_clear" ); while( 1 ) { // ON flag_wait( "flag_atrium_player_on_perch" ); level._player.attackeraccuracy = 10.0; level._player.threatbias = 800; // OFF flag_waitopen( "flag_atrium_player_on_perch" ); level._player.attackeraccuracy = 1.0; level._player.threatbias = 0; } } //******************************************************************* // ATRIUM UTILS //******************************************************************* // Kills a trigger remove_trigger( name ) { triggers = GetEntArray( name, "targetname" ); foreach( trigger in triggers ) { if( isDefined( trigger )) { trigger delete(); } } } // Waits for a certain number of enemies to die wait_for_num_kills( num_kills ) { level endon( "atrium_clear" ); while( 1 ) { if( level.wave_count >= num_kills ) { return; } wait 1; } } // When encounter is almost over, kill all spawners and // make enemies more aggresive atrium_straggler_cleanup() { //****************************************************************** // Atrium Ending //****************************************************************** // Wait for X number of guys left waittill_aigroupcount( "atrium_guys", 3 ); // Make remaining guys more aggressive remaining_guys = get_ai_group_ai( "atrium_guys" ); foreach( guy in remaining_guys ) { guy.aggressivemode = true; guy thread ai_playerseek(); } // Make sure no new guys spawn thread maps\_spawner::kill_spawnerNum( 210 ); thread maps\_spawner::kill_spawnerNum( 220 ); thread maps\_spawner::kill_spawnerNum( 240 ); // Kill any guys stuck in the roof closet kill_volume = GetEnt( "atrium_roof_kill_volume", "targetname" ); kill_volume thread kill_ai_in_volume(); // Kill any guys in the stair case kill_volume = GetEnt( "atrium_stairs_kill_volume", "targetname" ); kill_volume thread kill_ai_in_volume(); // Kill any guys on the 2nd floor kill_volume = GetEnt( "atrium_2nd_story_kill_volume", "targetname" ); kill_volume thread kill_ai_in_volume(); } kill_ai_in_volume() { ai = GetAIArray(); foreach ( guy in ai ) { if ( guy IsTouching( self ) && !guy is_hero() && !player_can_see_ai( guy ) ) { guy Delete(); } } } // Make an actor seek out the player ai_playerseek() { self endon( "death" ); if ( isdefined( self.target ) ) self waittill( "goal" ); self ClearGoalVolume(); //iprintlnbold( "PLAYER SEEK" ); self setgoalentity( level._player ); self.goalradius = 256; self.favoriteenemy = level._player; } // Handle the explodable gas tank atrium_exploding_tank() { gas_tank = GetEnt( "atrium_tank", "script_noteworthy" ); gas_tank waittill( "exploded" ); // Trigger the exploders exploder( "exploder_atrium_tank" ); // Vibrate quakeobj = spawn( "script_origin", level._player.origin ); quakeobj PlayRumbleOnEntity( "artillery_rumble" ); // Kill the shootable_pipe object /* pipes = GetEntArray( "pipe_shootable", "targetname" ); foreach( pipe in pipes ) { if( isDefined( pipe ) && pipe.script_parameters == "atrium_pipe_shootable" ) { iprintlnbold( "Got pipe" ); pipe delete(); } } */ wait 0.5; // Trigger wall swap exploder( "exploder_atrium_wall" ); exploder( "exploder_atrium_exit" ); // Turn on a badplace where the explosion happened badplace = getent( "atrium_tank_badplace", "targetname" ); badplace_brush( "atrium_tank_badplace", 0, badplace, "axis" ); wait 0.3; exploder( "exploder_atrium_tank_dust_01" ); wait 0.4; exploder( "exploder_atrium_tank_dust_02" ); wait 0.5; exploder( "exploder_atrium_tank_dust_03" ); wait 0.4; exploder( "exploder_atrium_tank_dust_04" ); wait 0.6; exploder( "exploder_atrium_tank_dust_05" ); wait 0.5; exploder( "exploder_atrium_tank_dust_06" ); wait 0.5; exploder( "exploder_atrium_tank_dust_07" ); wait 2; exploder( "exploder_atrium_tank_wait" ); // Kill the roof spawners //thread maps\_spawner::kill_spawnerNum( 215 ); // Kill all enemies on the roof //kill_ai_in_volume = GetEnt( "atrium_roof_kill_volume", "targetname" ); //kill_ai_in_volume thread kill_ai_in_volume(); }