1619 lines
42 KiB
Text
1619 lines
42 KiB
Text
//
|
|
// file: ber3b_event_parliament.gsc
|
|
// description: reichstag parliament event script for berlin3b
|
|
// scripter: slayback
|
|
//
|
|
|
|
#include common_scripts\utility;
|
|
#include maps\_utility;
|
|
#include maps\_anim;
|
|
#include maps\ber3b;
|
|
#include maps\ber3b_anim;
|
|
#include maps\ber3_util;
|
|
#include maps\_music;
|
|
|
|
#using_animtree( "generic_human" );
|
|
|
|
// -- STARTS --
|
|
// start at the beginning of the parliament event
|
|
event_parliament_start()
|
|
{
|
|
objectives_skip( 1 );
|
|
|
|
warp_players_underworld();
|
|
warp_friendlies( "struct_parliament_start_friends", "targetname" );
|
|
warp_players( "struct_parliament_start", "targetname" );
|
|
set_color_chain( "trig_script_color_allies_b7" );
|
|
|
|
level thread event_parliament_setup();
|
|
}
|
|
|
|
event_parliament_doors_start()
|
|
{
|
|
objectives_skip( 1 );
|
|
|
|
warp_players_underworld();
|
|
warp_friendlies( "struct_parliament_doors_start_friends", "targetname" );
|
|
warp_players( "struct_parliament_doors_start", "targetname" );
|
|
set_color_chain( "trig_script_color_allies_b27" );
|
|
|
|
level thread event_parliament_setup();
|
|
}
|
|
// -- END STARTS --
|
|
|
|
event_parliament_setup( skipto )
|
|
{
|
|
if( !IsDefined( skipto ) )
|
|
{
|
|
skipto = false;
|
|
}
|
|
|
|
// CODER_MOD
|
|
// DSL - Migrated fake fire over to the client side, so need to notify client scripts of state change
|
|
// rather than simply sending a notify to the level on the server side.
|
|
if(level.clientscripts)
|
|
{
|
|
maps\_utility::setClientSysState("levelNotify", "intro_fakefire_end");
|
|
}
|
|
else
|
|
{
|
|
level notify( "intro_fakefire_end" );
|
|
}
|
|
|
|
thread parliament_aa_tracers();
|
|
|
|
thread event_parliament_action( skipto );
|
|
|
|
thread balcony_playerhints();
|
|
thread first_balcony_action();
|
|
|
|
thread bazooka_team_init();
|
|
thread falling_eagle_director();
|
|
thread falling_eagle();
|
|
|
|
thread cleanup_forcecolor_redshirts( "c", "trig_parliament_exit", "targetname" );
|
|
}
|
|
|
|
parliament_aa_tracers()
|
|
{
|
|
emitters = GetEntArray( "org_parliament_aa_emitter", "targetname" );
|
|
ASSERTEX( array_validate( emitters ), "Couldn't find parliament AA tracer emitters." );
|
|
|
|
array_thread( emitters, maps\ber3b_fx::ambient_aaa_fx, "parliament_doors_open" );
|
|
|
|
level waittill( "parliament_doors_open" );
|
|
level thread delete_group( emitters, 1 );
|
|
}
|
|
|
|
event_parliament_action( skipto )
|
|
{
|
|
if( !IsDefined( skipto ) )
|
|
{
|
|
skipto = false;
|
|
}
|
|
|
|
trigger_wait( "trig_parliament_playerNearDoor", "targetname" );
|
|
level thread parliament_doors_open();
|
|
|
|
level waittill( "parliament_doors_open" );
|
|
set_color_chain( "trig_script_color_allies_b17");
|
|
|
|
trigger_wait( "trig_parliament_exit", "targetname" );
|
|
|
|
// send control to roof script
|
|
maps\ber3b_event_roof::event_roof_setup();
|
|
}
|
|
|
|
balcony_playerhints()
|
|
{
|
|
flag_init( "player_start_balcony_path_hint" );
|
|
flag_init( "player_found_balcony_stairs" );
|
|
flag_init( "player_reached_balcony" );
|
|
thread player_start_path_hint();
|
|
thread player_heading_upstairs();
|
|
thread player_reached_balcony();
|
|
|
|
//TUEY SET MUSIC STATE to PARLIAMENT_ROOM
|
|
setmusicstate("PARLIAMENT_ROOM");
|
|
level thread maps\ber3b_amb::play_crowd_sound();
|
|
|
|
|
|
trigger_wait( "trig_parliament_entrance", "targetname" );
|
|
|
|
// sarge go to special node and wave for the player
|
|
sargeWaveNode = getnode_safe( "node_sarge_parliament_hint", "targetname" );
|
|
level.sarge thread sarge_balcony_playerhint_anim();
|
|
level.sarge SetGoalPos( sargeWaveNode.origin, sargeWaveNode.angles );
|
|
|
|
flag_wait( "player_start_balcony_path_hint" );
|
|
|
|
set_objective( 2 );
|
|
thread balcony_breadcrumbs( 2 );
|
|
|
|
// "Chyort! More MGs!"
|
|
level.sarge playsound_generic_facial( "Ber3B_IGD_033A_REZN" );
|
|
// "Be on your guard - they'll fight to hold every strong point they can!"
|
|
level.sarge playsound_generic_facial( "Ber3B_IGD_034A_REZN" );
|
|
// "Right flank - Get up on that balcony!"
|
|
level.sarge thread playsound_generic_facial( "Ber3B_IGD_035A_REZN" );
|
|
|
|
if( !flag( "player_reached_balcony" ) )
|
|
{
|
|
// lines to bug player to go upstairs
|
|
lines[0] = "Ber3B_IGD_104A_REZN"; // "Move upstairs!"
|
|
lines[1] = "Ber3B_IGD_035A_REZN"; // "Right flank - Get up on that balcony!
|
|
lines[2] = "Ber3B_IGD_025A_REZN"; // "Flank them!"
|
|
thread bug_player( lines, 15, 25, "player_reached_balcony" );
|
|
}
|
|
}
|
|
|
|
player_start_path_hint()
|
|
{
|
|
trig = getent_safe( "trig_parliament_path_hint", "targetname" );
|
|
trig waittill( "trigger" );
|
|
|
|
flag_set( "player_start_balcony_path_hint" );
|
|
|
|
wait( 1 );
|
|
trig Delete();
|
|
}
|
|
|
|
player_heading_upstairs()
|
|
{
|
|
// wait for player to start heading upstairs
|
|
trig = getent( "trig_player_heading_upstairs", "targetname" );
|
|
trig waittill( "trigger" );
|
|
|
|
flag_set( "player_found_balcony_stairs" );
|
|
|
|
wait( 1 );
|
|
trig Delete();
|
|
}
|
|
|
|
player_reached_balcony()
|
|
{
|
|
trigger_wait( "trig_parliament_rightbalcony_entrance", "targetname" );
|
|
flag_set( "player_reached_balcony" );
|
|
}
|
|
|
|
balcony_breadcrumbs( obj )
|
|
{
|
|
Objective_Position( obj, ( 1536, 17592, 934 ) );
|
|
Objective_Ring( obj );
|
|
trigger_wait( "trig_player_heading_upstairs", "targetname" );
|
|
Objective_Position( obj, ( 1792, 17830, 1194 ) );
|
|
Objective_Ring( obj );
|
|
trigger_wait( "trig_parliament_rightbalcony_entrance", "targetname" );
|
|
Objective_Position( obj, ( 2249, 18604, 1170 ) );
|
|
Objective_Ring( obj );
|
|
}
|
|
|
|
sarge_balcony_playerhint_anim()
|
|
{
|
|
// sarge go to special node
|
|
self clear_force_color();
|
|
self.og_goalradius = level.sarge.goalradius;
|
|
self.goalradius = 32;
|
|
self.ignoreall = true;
|
|
|
|
self waittill( "goal" );
|
|
// let him orient to the angles specified in SetGoalPos
|
|
self waittill_notify_or_timeout( "orientdone", 3 );
|
|
|
|
if( !flag( "player_found_balcony_stairs" ) )
|
|
{
|
|
loopEnder = "stop_balconywave";
|
|
|
|
self.animname = "sarge";
|
|
self thread anim_loop_solo( self, "balconywave", undefined, loopEnder );
|
|
|
|
flag_wait( "player_found_balcony_stairs" );
|
|
self notify( loopEnder );
|
|
}
|
|
|
|
// reset sarge
|
|
self.goalradius = level.sarge.og_goalradius;
|
|
self.ignoreall = false;
|
|
self set_force_color( "b" );
|
|
}
|
|
|
|
first_balcony_action()
|
|
{
|
|
flag_init( "sarge_balcony_moveup_dialogue_done" );
|
|
flag_init( "sarge_balcony_molotov_throwers_dialogue_done" );
|
|
|
|
thread downstairs_door_opener();
|
|
|
|
// wait for player to get upstairs
|
|
trigger_wait( "trig_parliament_rightbalcony_entrance", "targetname" );
|
|
|
|
// start checking for player kills
|
|
requiredKills = 12;
|
|
// --TEMP for testing
|
|
//timeout = 5;
|
|
timeout = 300;
|
|
thread balcony_playerkills( requiredKills, timeout );
|
|
|
|
// make players and squad invisible on balcony
|
|
thread balcony_threatbiases();
|
|
|
|
// wait for objective requirements to be satisfied
|
|
flag_wait( "first_balcony_russians_moveup" );
|
|
|
|
// move Russians on the floor up
|
|
thread sarge_balcony_moveup_dialogue();
|
|
set_color_chain( "trig_script_color_allies_c1" );
|
|
|
|
// Germans retreat
|
|
getent_safe( "trig_script_fallback_400", "targetname" ) notify( "trigger" );
|
|
|
|
// kill spawner groups 19 and 20
|
|
getent_safe( "trig_script_killspawner_19", "targetname" ) notify( "trigger" );
|
|
getent_safe( "trig_script_killspawner_20", "targetname" ) notify( "trigger" );
|
|
|
|
thread balcony_podium_enemies_dialogue();
|
|
wait( 0.5 );
|
|
|
|
// molotov throwers spawn
|
|
balcony_spawn_molotov_throwers();
|
|
balcony_spawn_flamethrowers();
|
|
wait( 3 ); // let them run into position
|
|
|
|
thread sarge_balcony_molotov_throwers_dialogue();
|
|
|
|
Objective_AdditionalCurrent( 10 );
|
|
|
|
// "filler" enemies so the scene doesn't die down
|
|
thread spawn_podium_filler_enemies();
|
|
wait( 2 );
|
|
|
|
// failsafe thread in case players hang out upstairs, to spawn podium enemies
|
|
thread balcony_failsafe_spawn_podium_enemies( 6 );
|
|
|
|
// wait for molotov guys to die
|
|
balcony_enemies = get_ai_group_ai( "parliament_balcony_enemies" );
|
|
if( array_validate( balcony_enemies ) )
|
|
{
|
|
timeout = 120;
|
|
waittill_group_dies( balcony_enemies, timeout, 0, false );
|
|
}
|
|
|
|
// "We must advance!"
|
|
level.sarge playsound_generic_facial( "RU_rez_order_attack_infantry_07" );
|
|
|
|
trig1 = getent_safe( "trig_parliament_defensive_line_entrance", "targetname" );
|
|
trig2 = getent_safe( "trig_parliament_back_entrance", "targetname" );
|
|
thread waittill_player_downstairs( trig1, trig2 );
|
|
|
|
set_objective( 3 );
|
|
objective_position( 3, (2830, 18996, 1078) );
|
|
|
|
// open doors
|
|
level notify( "balcony_doors_getready" );
|
|
flag_init( "balcony_doors_opened" );
|
|
|
|
//TUEY SET MUSIC STATE TO DOWNTHESTAIRS
|
|
setmusicstate("DOWN_THE_STAIRS");
|
|
|
|
animSpot = getstruct_safe( "struct_parliament_first_balcony_dooropen_spot", "targetname" );
|
|
waitNode = getnode_safe( "node_balcony_dooropener_wait", "targetname" );
|
|
|
|
opener = get_closest_from_group( animSpot.origin, level.friends );
|
|
ASSERTEX( is_active_ai( opener ), "Couldn't find an AI close to the balcony door." );
|
|
|
|
// set up opener
|
|
openerHadBulletShield = false;
|
|
if( IsDefined( opener.magic_bullet_shield ) && opener.magic_bullet_shield )
|
|
{
|
|
openerHadBulletShield = true;
|
|
}
|
|
else
|
|
{
|
|
opener thread magic_bullet_shield_safe();
|
|
}
|
|
opener.ignoreme = true;
|
|
opener.ignoreall = true;
|
|
opener.og_goalradius = opener.goalradius;
|
|
opener.goalradius = 24;
|
|
|
|
// send to wait node
|
|
opener clear_force_color();
|
|
opener SetGoalNode( waitNode );
|
|
|
|
// remove chain trig that players may not have hit, and manually send to chain near door
|
|
trig = GetEnt( "trig_script_color_allies_b10", "targetname" );
|
|
if( IsDefined( trig ) )
|
|
{
|
|
trig thread scr_delete();
|
|
}
|
|
set_color_chain( "trig_script_color_allies_b14" );
|
|
|
|
//set_objective( 3 );
|
|
//Objective_Position( 3, animSpot.origin );
|
|
|
|
// wait for players to get close to either set of doors
|
|
thread balcony_doors_wait( animSpot );
|
|
thread downstairs_doors_wait();
|
|
flag_wait( "first_balcony_doors_startopen" );
|
|
|
|
// save
|
|
thread autosave_by_name( "ber2_pment_balcony_cleared" );
|
|
|
|
opener set_animname_custom( "first_balcony_dooropener" );
|
|
animSpot anim_reach_solo( opener, "shoulder" );
|
|
thread balcony_doors_open( opener );
|
|
animSpot anim_single_solo( opener, "shoulder" );
|
|
|
|
flag_wait( "balcony_doors_opened" );
|
|
|
|
// reset opener
|
|
if( !openerHadBulletShield )
|
|
{
|
|
opener thread stop_magic_bullet_shield_safe();
|
|
}
|
|
|
|
opener SetGoalPos( ( 2123, 19023, 874 ) );
|
|
opener thread delayThread( 10, ::set_force_color, "b" );
|
|
opener thread delayThread( 5, ::scr_ignoreme, 0 );
|
|
opener thread delayThread( 5, ::scr_ignoreall, 0 );
|
|
opener thread delayThread( 5, ::scr_reset_goalradius );
|
|
|
|
// send friendlies downstairs
|
|
if( !flag( "parliament_backdoor_used" ) )
|
|
{
|
|
set_color_chain( "trig_script_color_allies_b11" );
|
|
}
|
|
|
|
// objective breadcrumbs
|
|
ogMarker = GetStruct( "struct_objective9_marker", "targetname" );
|
|
Objective_Position( 3, trig1.origin );
|
|
|
|
// lines to bug player to go downstairs
|
|
lines[0] = "RU_0_order_move_forward_05"; // "Quickly, advance!"
|
|
lines[1] = "RU_rez_order_move_follow_00"; // "Follow me, now!"
|
|
lines[2] = "RU_1_order_attack_infantry_05"; // "We have them on the run!"
|
|
thread bug_player( lines, 15, 25, "stop_bugging_player" );
|
|
|
|
flag_wait( "player_downstairs" );
|
|
|
|
level notify( "stop_bugging_player" );
|
|
Objective_Position( 3, ogMarker.origin );
|
|
|
|
wait( 0.1 );
|
|
trig1 Delete();
|
|
trig2 Delete();
|
|
}
|
|
|
|
sarge_balcony_moveup_dialogue()
|
|
{
|
|
// "Their defenses cannot hold!"
|
|
level.sarge playsound_generic_facial( "RU_1_order_action_boost_07" );
|
|
|
|
// "Now's our chance, attack!"
|
|
level.sarge playsound_generic_facial( "RU_0_order_attack_infantry_04" );
|
|
|
|
flag_set( "sarge_balcony_moveup_dialogue_done" );
|
|
}
|
|
|
|
sarge_balcony_molotov_throwers_dialogue()
|
|
{
|
|
flag_wait( "sarge_balcony_moveup_dialogue_done" );
|
|
|
|
// "More Nazis!"
|
|
level.sarge playsound_generic_facial( "RU_1_threat_infantry_multiple_03" );
|
|
|
|
// "There - on the balcony!"
|
|
level.sarge playsound_generic_facial( "RU_rez_landmark_near_balcony_01" );
|
|
|
|
// "Kill them all!"
|
|
level.sarge playsound_generic_facial( "RU_rez_threat_infantry_exposed_08" );
|
|
|
|
flag_set( "sarge_balcony_molotov_throwers_dialogue_done" );
|
|
}
|
|
|
|
balcony_podium_enemies_dialogue()
|
|
{
|
|
trigger_wait( "trig_spawn_podium_enemies", "script_noteworthy" );
|
|
|
|
flag_wait_all( "sarge_balcony_moveup_dialogue_done", "sarge_balcony_molotov_throwers_dialogue_done" );
|
|
|
|
// "German reinforcements!"
|
|
level.sarge playsound_generic_facial( "RU_rez_threat_infantry_multiple_02" );
|
|
|
|
// "All together, comrades!"
|
|
level.sarge playsound_generic_facial( "RU_0_order_action_suppress_04" );
|
|
}
|
|
|
|
waittill_player_downstairs( trig1, trig2 )
|
|
{
|
|
level endon( "player_downstairs" );
|
|
thread waittill_player_downstairs_2( trig2 );
|
|
|
|
trig1 waittill( "trigger" );
|
|
flag_set( "player_downstairs" );
|
|
}
|
|
|
|
waittill_player_downstairs_2( trig2 )
|
|
{
|
|
level endon( "player_downstairs" );
|
|
trig2 waittill( "trigger" );
|
|
|
|
level thread balcony_player_using_parliament_backentrance();
|
|
|
|
wait( 0.1 );
|
|
flag_set( "player_downstairs" );
|
|
}
|
|
|
|
// in case players use the back entrance, this hits triggers in the other staircase, etc.
|
|
balcony_player_using_parliament_backentrance()
|
|
{
|
|
flag_set( "parliament_backdoor_used" );
|
|
|
|
// friendly movement
|
|
trig = GetEnt( "trig_script_color_allies_b10", "targetname" );
|
|
if( IsDefined( trig ) )
|
|
{
|
|
trig thread scr_delete();
|
|
}
|
|
|
|
trig = GetEnt( "trig_script_color_allies_b12", "targetname" );
|
|
if( IsDefined( trig ) )
|
|
{
|
|
trig thread scr_delete();
|
|
}
|
|
|
|
set_color_chain( "trig_script_color_allies_b13" );
|
|
|
|
// new friendly respawn spot
|
|
getent_safe( "trig_friendly_respawn_first_balcony_exit", "script_noteworthy" ) notify( "trigger" );
|
|
|
|
// spawn podium enemies
|
|
getent_safe( "trig_spawn_podium_enemies", "script_noteworthy" ) notify( "trigger" );
|
|
|
|
getent_safe( "trig_parliament_defensive_line_entrance", "targetname" ) notify( "trigger" );
|
|
|
|
parliament_mg_adjust();
|
|
|
|
}
|
|
|
|
parliament_mg_adjust()
|
|
{
|
|
|
|
mg = getent( "auto788", "targetname" );
|
|
mg.yawconvergencetime = 2.25; // default is 1.5
|
|
mg.convergencetime = 2.25; // default is 1.5
|
|
mg.suppressionTime = 2.0; // default is 3
|
|
|
|
}
|
|
|
|
balcony_doors_wait( animSpot )
|
|
{
|
|
level endon( "first_balcony_doors_startopen" );
|
|
|
|
waittill_player_within_range( animSpot.origin, 245 );
|
|
flag_set( "first_balcony_doors_startopen" );
|
|
}
|
|
|
|
downstairs_doors_wait()
|
|
{
|
|
level endon( "first_balcony_doors_startopen" );
|
|
|
|
trig = getent_safe( "trig_parliament_downstairs_door_proxcheck", "targetname" );
|
|
trig waittill( "trigger" );
|
|
trig Delete();
|
|
|
|
flag_set( "first_balcony_doors_startopen" );
|
|
}
|
|
|
|
downstairs_door_opener()
|
|
{
|
|
animSpot = getstruct_safe( "struct_parliament_downstairs_dooropen_spot", "targetname" );
|
|
waitNode1 = getnode_safe( "node_parliament_doors_downstairs_wait1", "targetname" );
|
|
|
|
// wait for these guys to spawn, should only be needed at dev start spot
|
|
while( !array_validate( get_allies_by_color( "c" ) ) )
|
|
{
|
|
wait( 0.1 );
|
|
}
|
|
|
|
// reserve a redshirt for this
|
|
opener = undefined;
|
|
redshirts = get_allies_by_color( "c" );
|
|
for( i = 0; i < redshirts.size; i++ )
|
|
{
|
|
if( is_active_ai( redshirts[i] ) )
|
|
{
|
|
opener = redshirts[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERTEX( is_active_ai( opener ), "Couldn't find a guy to open the door downstairs!" );
|
|
|
|
opener thread magic_bullet_shield_safe();
|
|
opener.grenadeawareness = 0;
|
|
opener.ignoreme = true;
|
|
opener.og_goalradius = opener.goalradius;
|
|
opener.goalradius = 24;
|
|
opener.name = "Pvt. Lofski";
|
|
|
|
// take him off the chain
|
|
opener clear_force_color();
|
|
|
|
opener SetGoalNode( waitNode1 );
|
|
|
|
// --TEMP for testing
|
|
//opener waittill( "goal" );
|
|
level waittill( "balcony_doors_getready" );
|
|
|
|
opener set_animname_custom( "downstairs_dooropener" );
|
|
animSpot anim_reach_solo( opener, "shoulder" );
|
|
|
|
// --TEMP for testing
|
|
//waittill_player_within_range( opener.origin, 256 );
|
|
flag_wait( "first_balcony_doors_startopen" );
|
|
|
|
// open door
|
|
flag_init( "downstairs_doors_opened" );
|
|
|
|
thread downstairs_doors_open( opener );
|
|
animSpot anim_single_solo( opener, "shoulder" );
|
|
|
|
flag_wait( "downstairs_doors_opened" );
|
|
|
|
// reset opener
|
|
opener thread stop_magic_bullet_shield_safe();
|
|
opener.grenadeawareness = 1;
|
|
opener.ignoreme = false;
|
|
opener.ignoreall = false;
|
|
opener.goalradius = opener.og_goalradius;
|
|
|
|
// send through door and kill off
|
|
opener SetGoalPos( ( 1344, 18624, 880 ) );
|
|
wait( 5 );
|
|
opener bloody_death( true, 3 );
|
|
}
|
|
|
|
downstairs_doors_open( opener )
|
|
{
|
|
doorLeft = getent_safe( "parl_1st_floor_door_left", "targetname" );
|
|
doorRight = getent_safe( "parl_1st_floor_door_right", "targetname" );
|
|
|
|
rotateTime = 0.24;
|
|
accelTime = rotateTime * 0.1;
|
|
decelTime = rotateTime * 0.5;
|
|
|
|
opener waittillmatch( "single anim", "bash" );
|
|
|
|
doorLeft ConnectPaths();
|
|
doorRight ConnectPaths();
|
|
|
|
doorLeft RotateYaw( 85, rotateTime, accelTime, decelTime );
|
|
doorRight RotateYaw( -85, rotateTime, accelTime, decelTime );
|
|
wait( rotateTime );
|
|
|
|
flag_set( "downstairs_doors_opened" );
|
|
}
|
|
|
|
bug_player( lines, minBugInterval, maxBugInterval, ender )
|
|
{
|
|
level endon( ender );
|
|
|
|
theLine = undefined;
|
|
lastLine = undefined;
|
|
|
|
maxTries = 10;
|
|
|
|
while( 1 )
|
|
{
|
|
wait( RandomFloatRange( minBugInterval, maxBugInterval ) );
|
|
|
|
foundOne = false;
|
|
tries = 0;
|
|
|
|
while( !foundOne )
|
|
{
|
|
theLine = get_random( lines );
|
|
|
|
if( !IsDefined( lastLine ) )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if( tries < maxTries )
|
|
{
|
|
if( theLine != lastLine )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
// make sure we're not super unlucky
|
|
else
|
|
{
|
|
theLine = get_random( lines );
|
|
break;
|
|
}
|
|
}
|
|
|
|
tries++;
|
|
}
|
|
|
|
level.sarge playsound_generic_facial( theLine );
|
|
|
|
lastLine = theLine; // remember the latest line we played
|
|
}
|
|
}
|
|
|
|
balcony_playerkills( requiredKills, timeout )
|
|
{
|
|
level.balcony_playerkills = 0;
|
|
endTime = GetTime() + ( timeout * 1000 );
|
|
|
|
while( ( level.balcony_playerkills < requiredKills ) && ( GetTime() < endTime ) )
|
|
{
|
|
wait( 0.1 );
|
|
}
|
|
|
|
flag_set( "first_balcony_russians_moveup" );
|
|
}
|
|
|
|
balcony_threatbiases()
|
|
{
|
|
players = get_players();
|
|
for( i = 0; i < players.size; i++ )
|
|
{
|
|
players[i] SetThreatBiasGroup( "players" );
|
|
}
|
|
|
|
SetIgnoreMeGroup( "players", "parliament_floor_enemies" );
|
|
SetIgnoreMeGroup( "friends", "parliament_floor_enemies" );
|
|
}
|
|
|
|
balcony_spawn_molotov_throwers()
|
|
{
|
|
getent_safe( "trig_spawn_balcony_enemies", "targetname" ) notify( "trigger" );
|
|
thread kill_balcony_enemies();
|
|
}
|
|
|
|
kill_balcony_enemies()
|
|
{
|
|
trigger_wait( "trig_parliament_defensive_line_entrance", "targetname" );
|
|
|
|
wait( 5 );
|
|
|
|
ais = get_ai_group_ai( "parliament_balcony_enemies" );
|
|
|
|
for( i = 0; i < ais.size; i++ )
|
|
{
|
|
if( is_active_ai( ais[i] ) )
|
|
{
|
|
ais[i] DoDamage( ais[i].health + 1, ais[i].origin );
|
|
wait( RandomFloatRange( 3, 7 ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
parliament_molotovguy_spawnfunc()
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.ignoreme = true;
|
|
self.grenadeawareness = 0;
|
|
self.ignoresuppression = 1;
|
|
|
|
node = getnode_safe( self.target, "targetname" );
|
|
self SetGoalNode( node );
|
|
self waittill( "goal" );
|
|
|
|
self.allowdeath = true;
|
|
|
|
wait( RandomFloatRange( 0, 2 ) );
|
|
|
|
self.animname = "parliament_molotov_thrower";
|
|
anime = "molotov_throw_custom";
|
|
|
|
while( 1 )
|
|
{
|
|
forward = AnglesToForward( node.angles );
|
|
targetDist = RandomIntRange( 300, 700 );
|
|
target_pos = self.origin + vectorScale( forward, targetDist );
|
|
|
|
self maps\_grenade_toss::force_grenade_toss( target_pos, "molotov", undefined, anime );
|
|
|
|
wait( RandomFloatRange( 3, 6 ) );
|
|
}
|
|
}
|
|
|
|
// --- FLAMETHROWER GUYS ---
|
|
balcony_spawn_flamethrowers()
|
|
{
|
|
getent_safe( "trig_spawn_flamers", "targetname" ) notify( "trigger" );
|
|
|
|
thread balcony_kill_flamers();
|
|
}
|
|
|
|
balcony_kill_flamers()
|
|
{
|
|
trigger_wait( "trig_script_color_allies_b27", "targetname" );
|
|
flamers = get_ai_group_ai( "ai_parliament_flamer" );
|
|
array_thread( flamers, ::kill_flamer, 2, 4 );
|
|
}
|
|
|
|
kill_flamer( waitMin, waitMax )
|
|
{
|
|
self endon( "death" );
|
|
|
|
wait( RandomFloatRange( waitMin, waitMax ) );
|
|
|
|
players = get_players();
|
|
|
|
if( is_active_ai( self ) )
|
|
{
|
|
self DoDamage( self.health + 1, self.origin, players[0] );
|
|
}
|
|
}
|
|
|
|
// TFlames steez
|
|
flamer_setup()
|
|
{
|
|
self endon ("death");
|
|
// self disable_long_death(); // Uncomment if shooting in the looks like jokes.
|
|
self.ignoreme = true;
|
|
self.health = 10000;
|
|
//self thread wait_and_unignore(30);
|
|
//self thread wait_and_kill(60);
|
|
level thread flamer_blow( self );
|
|
}
|
|
|
|
flamer_blow( flamer )
|
|
{
|
|
total_dmg = 0;
|
|
|
|
while( 1 )
|
|
{
|
|
flamer waittill( "damage", amount, attacker, dir, point, mod );
|
|
if( IsPlayer( attacker ) )
|
|
{
|
|
if( flamer animscripts\utility::damageLocationIsAny( "torso_upper", "torso_lower", "head", "neck", "right_arm_upper", "right_arm_lower", "left_arm_upper", "left_arm_lower" ) )
|
|
{
|
|
break;
|
|
}
|
|
// If the flamethrower guy does not get damaged by the
|
|
// damagelocation above, calculate the total damage taken.
|
|
else
|
|
{
|
|
total_dmg += amount;
|
|
|
|
// Default AI health is 150
|
|
if( total_dmg > 150 )
|
|
{
|
|
// If killed by splash damage or an explosive type weapon, make the AI explode.
|
|
if( mod == "MOD_GRENADE_SPLASH" || mod == "MOD_EXPLOSIVE" || mod == "MOD_PROJECTILE" || mod == "MOD_PROJECTILE_SPLASH" )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Just kill the AI and do not explode since the AI was not killed by the damagelocation in the upper if statement.
|
|
flamer DoDamage( flamer.health * 10, flamer.origin );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
level thread flamer_blow_catch_splash_kills( flamer, attacker, 0.25 );
|
|
|
|
Earthquake( 0.2, 0.2, flamer.origin, 1500 );
|
|
PlayFX( level._effect["flameguy_explode"], flamer.origin + ( 0, 0, 50 ) );
|
|
flamer.health = 50;
|
|
attacker MagicGrenadeType( "stick_grenade", flamer.origin + ( -20, -25, 20 ), flamer.origin, 0.01 );
|
|
attacker MagicGrenadeType( "stick_grenade", flamer.origin + ( -25, -30, 10 ), flamer.origin, 0.01 );
|
|
spot = flamer.origin;
|
|
allies = GetAIArray( "allies" );
|
|
|
|
wait( 0.1 );
|
|
|
|
if( IsDefined( flamer ) && IsDefined( flamer.health ) && flamer.health > 0 )
|
|
{
|
|
flamer DoDamage( flamer.health * 10, flamer.origin );
|
|
flamer StartTanning();
|
|
}
|
|
|
|
wait( 0.1 );
|
|
|
|
attacker MagicGrenadeType( "molotov", spot + ( 0, 0, 5 ), spot + ( 0, 0, -1 ), 0.01 );
|
|
|
|
arcademode_assignpoints( "arcademode_score_kill", attacker );
|
|
}
|
|
|
|
// SRS 8/12/2008: catch splash damage off of flamethrower guys to give coop challenge XP
|
|
flamer_blow_catch_splash_kills( flamer, attacker, splashKillTimeWindow )
|
|
{
|
|
if( !IsDefined( level.flamerSplashKillsForChallenge ) )
|
|
{
|
|
level.flamerSplashKillsForChallenge = 2; // flamer + 2 = challenge complete
|
|
}
|
|
|
|
grenadeDist = 256;
|
|
|
|
if( !IsDefined( attacker.flamerSplashKills ) )
|
|
{
|
|
attacker.flamerSplashKills = [];
|
|
}
|
|
|
|
flamerIndex = attacker.flamerSplashKills.size;
|
|
attacker.flamerSplashKills[flamerIndex] = 0;
|
|
|
|
closeGuys = [];
|
|
|
|
ais = GetAIArray( "axis" );
|
|
for( i = 0; i < ais.size; i++ )
|
|
{
|
|
// SRS 9/1/2008: if close enough, and not the flamer...
|
|
if( ( Distance( ais[i].origin, flamer.origin ) <= grenadeDist ) && ( ais[i] != flamer ) )
|
|
{
|
|
// add to array
|
|
closeGuys[closeGuys.size] = ais[i];
|
|
}
|
|
}
|
|
|
|
// if there's not enough guys nearby to possibly complete the challenge, don't worry about it
|
|
if( closeGuys.size >= level.flamerSplashKillsForChallenge )
|
|
{
|
|
array_thread( closeGuys, ::flamer_blow_splash_kill_watcher, attacker, flamerIndex, splashKillTimeWindow );
|
|
}
|
|
}
|
|
|
|
flamer_blow_splash_kill_watcher( attacker, flamerIndex, splashKillTimeWindow )
|
|
{
|
|
endTime = GetTime() + ( splashKillTimeWindow * 1000 );
|
|
|
|
while( IsAlive( self ) && endTime > GetTime() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
// if dead, see if we credit the player for the splash kill
|
|
if( !IsAlive( self ) )
|
|
{
|
|
if( IsDefined( self.attacker ) && self.attacker == attacker )
|
|
{
|
|
if( IsDefined( self.damagemod ) && ( self.damagemod == "MOD_GRENADE" || self.damagemod == "MOD_GRENADE_SPLASH" || self.damagemod == "MOD_EXPLOSIVE" || self.damagemod == "MOD_BURNED" ) )
|
|
{
|
|
attacker.flamerSplashKills[flamerIndex]++;
|
|
|
|
// do coop points
|
|
if( attacker.flamerSplashKills[flamerIndex] >= level.flamerSplashKillsForChallenge )
|
|
{
|
|
if( !IsDefined( attacker.gaveFlamerPoints ) )
|
|
{
|
|
attacker.gaveFlamerPoints = true;
|
|
|
|
// give points
|
|
attacker maps\_challenges_coop::processChallenge( "ch_backdraft_1" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- END FLAMETHROWER GUYS ---
|
|
|
|
spawn_podium_filler_enemies()
|
|
{
|
|
getent_safe( "trig_spawn_podium_filler_enemies", "script_noteworthy" ) notify( "trigger" );
|
|
|
|
// stop when the rest of the podium enemies spawn
|
|
trigger_wait( "trig_spawn_podium_enemies", "script_noteworthy" );
|
|
getent_safe( "trig_killspawner_21", "targetname" ) notify( "trigger" );
|
|
}
|
|
|
|
balcony_failsafe_spawn_podium_enemies( axisLowerLimit )
|
|
{
|
|
trig = getent_safe( "trig_spawn_podium_enemies", "script_noteworthy" );
|
|
trig endon( "trigger" );
|
|
|
|
while( 1 )
|
|
{
|
|
axis = GetAIArray( "axis" );
|
|
|
|
if( !IsDefined( axis ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( axis.size < axisLowerLimit )
|
|
{
|
|
break;
|
|
}
|
|
|
|
wait( 1 );
|
|
}
|
|
|
|
trig notify( "trigger" );
|
|
}
|
|
|
|
balcony_doors_open( opener )
|
|
{
|
|
doorLeft = getent_safe( "sb_model_balcony_door_left", "targetname" );
|
|
doorRight = getent_safe( "sb_model_balcony_door_right", "targetname" );
|
|
|
|
rotateTime = 0.24;
|
|
accelTime = rotateTime * 0.1;
|
|
decelTime = rotateTime * 0.5;
|
|
|
|
opener waittillmatch( "single anim", "door_hit" );
|
|
|
|
doorLeft ConnectPaths();
|
|
doorRight ConnectPaths();
|
|
|
|
doorLeft RotateYaw( 110, rotateTime, accelTime, decelTime );
|
|
doorRight RotateYaw( -110, rotateTime, accelTime, decelTime );
|
|
wait( rotateTime );
|
|
|
|
flag_set( "balcony_doors_opened" );
|
|
}
|
|
|
|
parliament_enemy_spawnfunc()
|
|
{
|
|
if( IsDefined( self.script_string ) && self.script_string == "balcony_guy" )
|
|
{
|
|
self thread parliament_molotovguy_spawnfunc();
|
|
}
|
|
|
|
// special guys should always stand so they look/act smarter
|
|
if( IsSubStr( self.classname, "panzerschrek" ) || IsSubStr( self.classname, "flamethrower" ) )
|
|
{
|
|
self AllowedStances( "stand" );
|
|
}
|
|
|
|
self waittill( "death" );
|
|
|
|
if( IsDefined( self.attacker ) && IsPlayer( self.attacker ) )
|
|
{
|
|
if( !IsDefined( level.balcony_playerkills ) )
|
|
{
|
|
level.balcony_playerkills = 0;
|
|
}
|
|
|
|
level.balcony_playerkills++;
|
|
}
|
|
}
|
|
|
|
bazooka_team_init()
|
|
{
|
|
trig = getent_safe( "trig_parliament_bazookateam", "targetname" );
|
|
trig waittill( "trigger" );
|
|
|
|
thread bazooka_team( trig );
|
|
}
|
|
|
|
bazooka_team( trig )
|
|
{
|
|
spawner_primary = getent_safe( trig.target, "targetname" );
|
|
spawner_secondary = getent_safe( spawner_primary.target, "targetname" );
|
|
node_primary = getnode_safe( spawner_primary.target, "targetname" );
|
|
node_secondary = getnode_safe( spawner_secondary.target, "targetname" );
|
|
|
|
trig Delete();
|
|
|
|
guy_primary = spawn_guy( spawner_primary );
|
|
guy_secondary = spawn_guy( spawner_secondary );
|
|
|
|
guys[0] = guy_primary;
|
|
guys[1] = guy_secondary;
|
|
|
|
guys bazookateam_setup_ais();
|
|
guys bazookateam_runto_nodes( node_primary, node_secondary );
|
|
|
|
guy_primary.animname = "fireteam_bazooka_primary";
|
|
guy_secondary.animname = "fireteam_bazooka_secondary";
|
|
|
|
guy_primary SetCanDamage( false );
|
|
|
|
// collect aimSpots
|
|
aimSpots = GetEntArray( node_primary.target, "targetname" );
|
|
|
|
/*
|
|
for( i = 0; i < aimSpots.size; i++ )
|
|
{
|
|
thread draw_line_until_notify( guy_primary.origin, aimSpots[i].origin, 0, 255, 255, level, "bazookateam_done_firing" );
|
|
}
|
|
*/
|
|
|
|
explosionRadius = 215;
|
|
|
|
flag_set( "bazookateam_keep_firing" );
|
|
|
|
// MikeD yeaaa!
|
|
guy_primary.shoot_notify = "bazooka_shot";
|
|
|
|
for( i = 0; i < aimSpots.size; i++ )
|
|
{
|
|
// guys reload bazooka
|
|
guys bazookateam_reload();
|
|
|
|
guy_primary thread bazookateam_fire_dialogue();
|
|
wait( 1 );
|
|
|
|
aimSpot = aimSpots[RandomInt( aimSpots.size )];
|
|
guy_primary AllowedStances( "stand" );
|
|
wait( 0.8 );
|
|
guy_primary.ignoreall = false;
|
|
guy_primary SetEntityTarget( aimSpot );
|
|
|
|
// MikeD yeaaa!
|
|
guy_primary waittill( "bazooka_shot" );
|
|
|
|
level notify( "bazookateam_fire" );
|
|
|
|
wait( 0.05 );
|
|
guy_primary ClearEntityTarget();
|
|
|
|
guy_primary AllowedStances( "crouch" );
|
|
|
|
// if we're not stopping...
|
|
if( flag( "bazookateam_keep_firing" ) )
|
|
{
|
|
wait( RandomFloatRange( 3, 6 ) );
|
|
}
|
|
else
|
|
{
|
|
// give him some time after shooting
|
|
wait( 2 );
|
|
|
|
//guy_secondary say_dialogue( "fireteam_bazooka_secondary", "bazooka_done" );
|
|
|
|
// switch weapon
|
|
guy_primary gun_switchto( guy_primary.secondaryweapon, "right" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
guy_primary.shoot_notify = undefined;
|
|
|
|
// wait a few seconds
|
|
wait( 3 );
|
|
|
|
guys bazookateam_reset_ais();
|
|
|
|
array_thread( guys, ::bloody_death, true, 2 );
|
|
}
|
|
|
|
// self = a bazooka team AI
|
|
bazookateam_fire_dialogue()
|
|
{
|
|
dialogueString = undefined;
|
|
|
|
if( RandomInt( 100 ) < 50 )
|
|
{
|
|
dialogueString = "bazooka_firing_1";
|
|
}
|
|
else
|
|
{
|
|
dialogueString = "bazooka_firing_2";
|
|
}
|
|
|
|
self say_dialogue( "fireteam_bazooka_primary", "bazooka_firing_2" );
|
|
}
|
|
|
|
// TODO put in anims when we get them
|
|
// self = the bazookateam AI array
|
|
bazookateam_reload()
|
|
{
|
|
anime = "bazooka_reload";
|
|
|
|
level thread bazooka_reload_rocket_attach( self );
|
|
level thread anim_single( self, anime );
|
|
level waittill( anime );
|
|
}
|
|
|
|
bazooka_reload_rocket_attach( guys )
|
|
{
|
|
animname = "fireteam_bazooka_primary";
|
|
rocketModel = "weapon_ger_panzershreck_rocket";
|
|
attachTag = "tag_inhand";
|
|
attachNote = "attach clip left";
|
|
detachNote = "detach clip left";
|
|
|
|
guy = undefined;
|
|
|
|
for( i = 0; i < guys.size; i++ )
|
|
{
|
|
if( guys[i].animname == animname )
|
|
{
|
|
guy = guys[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERTEX( IsDefined( guy ), "Couldn't find the bazooka guy with animname " + animname );
|
|
|
|
guy endon( "death" );
|
|
|
|
guy waittillmatch( "single anim", attachNote );
|
|
guy Attach( rocketModel, attachTag );
|
|
guy thread bazooka_rocket_deathdetach( rocketModel, attachTag );
|
|
|
|
guy waittillmatch( "single anim", detachNote );
|
|
guy Detach( rocketModel, attachTag );
|
|
|
|
guy notify( "rocket_detached" );
|
|
}
|
|
|
|
bazooka_rocket_deathdetach( rocketModel, attachTag )
|
|
{
|
|
self endon( "rocket_detached" );
|
|
|
|
self waittill( "death" );
|
|
self Detach( rocketModel, attachTag );
|
|
}
|
|
|
|
// self = the bazooka team AI array
|
|
bazookateam_setup_ais()
|
|
{
|
|
self[0].bazookateam_role = "primary";
|
|
self[1].bazookateam_role = "secondary";
|
|
|
|
for( i = 0; i < self.size; i++ )
|
|
{
|
|
guy = self[i];
|
|
guy.og_goalradius = guy.goalradius;
|
|
guy.goalradius = 12;
|
|
guy.ignoreme = true;
|
|
guy.ignoreall = true;
|
|
guy.og_grenadeawareness = guy.grenadeawareness;
|
|
guy.grenadeawareness = 0;
|
|
guy PushPlayer( true );
|
|
guy thread magic_bullet_shield();
|
|
}
|
|
}
|
|
|
|
// self = the bazooka team AI array
|
|
bazookateam_reset_ais()
|
|
{
|
|
for( i = 0; i < self.size; i++ )
|
|
{
|
|
guy = self[i];
|
|
|
|
if( !is_active_ai( guy ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
guy.goalradius = guy.og_goalradius;
|
|
guy.ignoreme = false;
|
|
guy.ignoreall = false;
|
|
guy.grenadeawareness = guy.og_grenadeawareness;
|
|
guy PushPlayer( false );
|
|
|
|
guy notify( "stop magic bullet shield" );
|
|
guy SetCanDamage( true );
|
|
|
|
guy AllowedStances( "stand", "crouch", "prone" );
|
|
}
|
|
}
|
|
|
|
// self = an array of bazooka guys
|
|
bazookateam_runto_nodes( nodePrimary, nodeSecondary )
|
|
{
|
|
self[0] SetGoalNode( nodePrimary );
|
|
self[1] SetGoalNode( nodeSecondary );
|
|
|
|
array_thread( self, ::bazooka_guy_reached_node );
|
|
|
|
numReached = 0;
|
|
|
|
while( numReached < self.size )
|
|
{
|
|
level waittill( "bazooka_guy_reached_node" );
|
|
numReached++;
|
|
}
|
|
}
|
|
|
|
// self = an AI
|
|
bazooka_guy_reached_node()
|
|
{
|
|
self endon( "death" );
|
|
|
|
self waittill( "goal" );
|
|
level notify( "bazooka_guy_reached_node" );
|
|
self AllowedStances( "crouch" );
|
|
}
|
|
|
|
falling_eagle_director()
|
|
{
|
|
trigger_wait( "trig_parliament_rightbalcony_entrance", "targetname" );
|
|
wait( 1 );
|
|
|
|
level notify( "eagle_slip" );
|
|
|
|
flag_clear( "bazookateam_keep_firing" );
|
|
}
|
|
|
|
falling_eagle()
|
|
{
|
|
eagle = getent_safe( "smodel_parliament_eagle", "targetname" );
|
|
|
|
pieces["lamp_base_jnt"] = getent_safe( "smodel_parliament_spotlight", "targetname" );
|
|
pieces["bookcase01_jnt"] = getent_safe( "smodel_parliament_bookshelf_1", "targetname" );
|
|
pieces["bookcase02_jnt"] = getent_safe( "smodel_parliament_bookshelf_2", "targetname" );
|
|
pieces["bookcase03_jnt"] = getent_safe( "smodel_parliament_bookshelf_3", "targetname" );
|
|
pieces["bookcase04_jnt"] = getent_safe( "smodel_parliament_bookshelf_4", "targetname" );
|
|
pieces["bookcase05_jnt"] = getent_safe( "smodel_parliament_bookshelf_5", "targetname" );
|
|
pieces["bookcase06_jnt"] = getent_safe( "smodel_parliament_bookshelf_6", "targetname" );
|
|
pieces["bookcase07_jnt"] = getent_safe( "smodel_parliament_bookshelf_7", "targetname" );
|
|
pieces["bookcase08_jnt"] = getent_safe( "smodel_parliament_bookshelf_8", "targetname" );
|
|
pieces["bookcase09_jnt"] = getent_safe( "smodel_parliament_bookshelf_9", "targetname" );
|
|
pieces["bookcase10_jnt"] = getent_safe( "smodel_parliament_bookshelf_10", "targetname" );
|
|
|
|
keys = GetArrayKeys( pieces );
|
|
|
|
for( i = 0; i < pieces.size; i++ )
|
|
{
|
|
pieces[keys[i]] LinkTo( eagle, keys[i] );
|
|
}
|
|
|
|
rocketStart = ( 1144, 17688, 984 );
|
|
rocketTime = 1.5;
|
|
|
|
thread eagle_reaction_dialogue();
|
|
|
|
level waittill( "eagle_slip" );
|
|
|
|
MagicBullet( "panzerschrek", rocketStart, eagle.origin );
|
|
wait( rocketTime );
|
|
PlayFX( level._effect["eagle_support_break"], eagle.origin );
|
|
eagle thread parliament_eagle_anim( "parliament_eagle", "slip", "eagle_slip_anim" );
|
|
|
|
eagle_fall_wait();
|
|
|
|
killtrig = GetEnt( "trig_killspawner_22", "targetname" );
|
|
if( IsDefined( killtrig ) )
|
|
{
|
|
killtrig notify( "trigger" );
|
|
}
|
|
|
|
//kevin adding notify. This has to be here to make these go off.
|
|
level notify( "arty_strike" );
|
|
thread arty_strike_on_players( .35, 2, 500 );
|
|
|
|
if( !level.player_shot_eagle )
|
|
{
|
|
MagicBullet( "panzerschrek", rocketStart, eagle.origin );
|
|
wait( rocketTime );
|
|
}
|
|
|
|
fxSpot = getstruct_safe( "struct_parliament_eaglefall_fxspot", "targetname" );
|
|
PlayFX( level._effect["eagle_fall_impact"], fxSpot.origin );
|
|
|
|
PlayFX( level._effect["eagle_support_break"], eagle.origin );
|
|
eagle thread parliament_eagle_anim( "parliament_eagle", "fall", "eagle_fall_anim" );
|
|
|
|
// wait for the eagle to fall
|
|
wait( 0.6 );
|
|
|
|
podiumtrig = getent_safe( "trig_parliament_podium_area", "targetname" );
|
|
|
|
RadiusDamage( podiumtrig.origin, podiumtrig.radius, 5000, 5000 );
|
|
thread kill_axis_in_trigger( podiumtrig, 0 );
|
|
thread parliament_podiumdoor_clean_rogue_ai();
|
|
|
|
wait( 5 );
|
|
podiumtrig Delete();
|
|
}
|
|
|
|
eagle_reaction_dialogue()
|
|
{
|
|
level waittill( "eagle_slip" );
|
|
wait( 2 );
|
|
|
|
sarge_giveorder( "eagle_loosening" );
|
|
|
|
trigger_wait( "trig_parliament_defensive_line_entrance", "targetname" );
|
|
|
|
guy1 = get_randomfriend_notsarge();
|
|
guy1 say_dialogue( "eagle_redshirt2", "aim_for_eagle", true );
|
|
|
|
level thread eagle_bringdown_dialogue();
|
|
|
|
flag_wait( "eagle_fall" );
|
|
|
|
// "As this symbol of their decadence plummets, so too will their wretched Reich."
|
|
level.sarge playsound_generic_facial( "Ber3B_IGD_049A_REZN" );
|
|
}
|
|
|
|
eagle_bringdown_dialogue()
|
|
{
|
|
level endon( "eagle_fall" );
|
|
|
|
// "Concentrate fire!"
|
|
level.sarge playsound_generic_facial( "Ber1_IGD_022A_REZN" );
|
|
|
|
// "By the eagle!"
|
|
level.sarge playsound_generic_facial( "RU_rez_landmark_near_eagle_00" );
|
|
|
|
// "Dmitri - take it down!"
|
|
level.sarge playsound_generic_facial( "See1_IGD_049A_REZN" );
|
|
|
|
// "Use the panzerschreks!"
|
|
level.sarge playsound_generic_facial( "See1_IGD_300A_REZN" );
|
|
}
|
|
|
|
eagle_fall_wait()
|
|
{
|
|
level.player_shot_eagle = false;
|
|
|
|
// wait until players hit the floor of the parliament
|
|
trigger_wait( "trig_parliament_defensive_line_entrance", "targetname" );
|
|
|
|
thread eagle_fall_proxtrigger();
|
|
thread eagle_fall_dmgtrigger();
|
|
level waittill( "eagle_fall" );
|
|
}
|
|
|
|
eagle_fall_proxtrigger()
|
|
{
|
|
level endon( "eagle_fall" );
|
|
|
|
trigger_wait( "trig_parliament_approaching_podium", "targetname" );
|
|
flag_set( "eagle_fall" );
|
|
}
|
|
|
|
eagle_fall_dmgtrigger()
|
|
{
|
|
level endon( "eagle_fall" );
|
|
|
|
dmgtrig = getent_safe( "trig_damage_parliament_eagle", "targetname" );
|
|
dmgtrig waittill( "trigger" );
|
|
|
|
level.player_shot_eagle = true;
|
|
flag_set( "eagle_fall" );
|
|
|
|
dmgtrig Delete();
|
|
}
|
|
|
|
parliament_podiumdoor_clean_rogue_ai()
|
|
{
|
|
axis = GetAIArray( "axis" );
|
|
|
|
for( i = 0; i < axis.size; i++ )
|
|
{
|
|
guy = axis[i];
|
|
|
|
// if he's north of the door...
|
|
if( guy.origin[1] > 20360 )
|
|
{
|
|
// clean him up
|
|
guy bloody_death( true, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
parliament_doors_open()
|
|
{
|
|
//TUEY Set music state to PARLIAMENT_CLEARED
|
|
setmusicstate("PARLIAMENT_CLEARED");
|
|
|
|
doorLeft = GetEnt( "sbmodel_pment_door_left", "targetname" );
|
|
doorRight = GetEnt( "sbmodel_pment_door_right", "targetname" );
|
|
|
|
doorNodeLeft = getnode_safe( "node_parliament_door_left", "targetname" );
|
|
doorNodeRight = getnode_safe( "node_parliament_door_right", "targetname" );
|
|
|
|
// wait for players to get close to the door area
|
|
trigger_wait( "trig_parliament_playerNearDoor", "targetname" );
|
|
|
|
thread battlechatter_off( "allies" );
|
|
thread battlechatter_off( "axis" );
|
|
|
|
// get the animspot
|
|
animSpot = getent_safe( "org_parliamentdoors_animref", "targetname" );
|
|
|
|
thread parliament_doorrunners();
|
|
|
|
// set up the AIs to push the doors open
|
|
pushers[0] = get_closest_from_group( animSpot.origin, level.friends, level.sarge, "parliament_russian_backup_1" );
|
|
pushers[0] parliament_doorpusher_setup();
|
|
pushers[0].animname = "parliament_doorpusher_1";
|
|
|
|
pushers[1] = get_closest_from_group( animSpot.origin, level.friends, level.sarge, "parliament_russian_backup_2" );
|
|
pushers[1] parliament_doorpusher_setup();
|
|
pushers[1].animname = "parliament_doorpusher_2";
|
|
|
|
pushers[2] = level.sarge;
|
|
pushers[2] parliament_doorpusher_setup();
|
|
pushers[2].animname = "parliament_doorpusher_3";
|
|
|
|
thread parliament_doors_open_sarge_dialogue();
|
|
|
|
// spawn the germans who will push back
|
|
spawners = GetEntArray( "spawner_parliament_doorholder", "targetname" );
|
|
ASSERTEX( IsDefined( spawners ) && spawners.size == 3, "Couldn't find enough parliament door holder enemy spawners." );
|
|
|
|
germans = [];
|
|
|
|
for( i = 0; i < spawners.size; i++ )
|
|
{
|
|
enemy = spawn_guy( spawners[i] );
|
|
enemy parliament_doorpusher_setup();
|
|
enemy.nodeathragdoll = true;
|
|
enemy.animname = "parliament_doorholder_" + ( i + 1 );
|
|
enemy.deathanim = level.scr_anim[enemy.animname]["doorbreach"];
|
|
enemy thread magic_bullet_shield_safe();
|
|
enemy SetGoalPos( enemy.origin );
|
|
|
|
germans[i] = enemy;
|
|
}
|
|
|
|
ASSERTEX( IsDefined( germans ) && germans.size == 3, "Couldn't find enough parliament door holder enemies - one or more spawns must have failed." );
|
|
|
|
// reach the door holders to their spots
|
|
level.door_reachers = 0;
|
|
pushers[0] thread parliament_doors_reach_wait( doorNodeLeft );
|
|
pushers[1] thread parliament_doors_reach_wait( doorNodeRight );
|
|
pushers[2] thread parliament_doors_reach_wait();
|
|
animSpot thread anim_reach_solo( pushers[2], "doorpush" );
|
|
|
|
while( level.door_reachers < pushers.size )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
// start pushing the door open
|
|
doorLeft thread reichstag_dooranim( "parliament_door_left", "doorpush", "parliamentdoor_anim", false );
|
|
doorRight thread reichstag_dooranim( "parliament_door_right", "doorpush", "parliamentdoor_anim", false );
|
|
animSpot anim_single( pushers, "doorpush" );
|
|
|
|
level notify( "parliament_doors_opening" );
|
|
|
|
// now open the doors
|
|
doorLeft thread reichstag_dooranim( "parliament_door_left", "doorbreach", "parliamentdoor_anim", true );
|
|
doorRight thread reichstag_dooranim( "parliament_door_right", "doorbreach", "parliamentdoor_anim", true );
|
|
|
|
//Kevins audio notify
|
|
level notify ("door_music_stinger");
|
|
|
|
array_thread( germans, ::parliament_doors_kill_doorholder, animSpot );
|
|
animSpot anim_single( pushers, "doorbreach" );
|
|
|
|
pushers[0] AllowedStances( "stand", "crouch", "prone" );
|
|
pushers[1] AllowedStances( "stand", "crouch", "prone" );
|
|
|
|
// reset AIs to previous values and re-add to friends array
|
|
for( i = 0; i < pushers.size; i++ )
|
|
{
|
|
pushers[i] parliament_doorpusher_reset();
|
|
}
|
|
|
|
// "Go!... Everyone! Through the doors!"
|
|
level.sarge thread playsound_generic_facial( "Ber3B_IGD_042A_REZN" );
|
|
|
|
thread battlechatter_on( "allies" );
|
|
thread battlechatter_on( "axis" );
|
|
|
|
level notify( "parliament_doors_open" );
|
|
|
|
//TUEY Set Music State to THROUGH_THE_DOOR
|
|
setmusicstate("THROUGH_THE_DOOR");
|
|
}
|
|
|
|
parliament_doors_open_sarge_dialogue()
|
|
{
|
|
// "You two! Get those doors open."
|
|
level.sarge playsound_generic_facial( "Ber3B_IGD_036A_REZN" );
|
|
|
|
// "Get them open now!"
|
|
level.sarge playsound_generic_facial( "Ber3B_IGD_039A_REZN" );
|
|
}
|
|
|
|
// self = an AI
|
|
parliament_doors_reach_wait( reachNode )
|
|
{
|
|
if( IsDefined( reachNode ) )
|
|
{
|
|
self.goalradius = 24;
|
|
self SetGoalNode( reachNode );
|
|
self waittill( "goal" );
|
|
}
|
|
else
|
|
{
|
|
self waittill( "anim_reach_complete" );
|
|
}
|
|
|
|
level.door_reachers++;
|
|
}
|
|
|
|
// self = the AI we're setting up
|
|
parliament_doorpusher_setup()
|
|
{
|
|
if( level.friends array_contains_element( self ) )
|
|
{
|
|
self.removed_from_friends = true;
|
|
level.friends = array_remove( level.friends, self );
|
|
}
|
|
|
|
self clear_force_color();
|
|
|
|
self.og_animname = self.animname;
|
|
self.og_goalradius = self.goalradius;
|
|
self.ignoreall = true;
|
|
self.ignoreme = true;
|
|
self.pacifist = true;
|
|
self PushPlayer( true );
|
|
|
|
// make sure the the pusher cannot be killed
|
|
// No need to do it for heroes
|
|
if( self != level.sarge && self.health < 9999 )
|
|
{
|
|
self thread magic_bullet_shield();
|
|
}
|
|
}
|
|
|
|
// self = the AI
|
|
parliament_doorpusher_reset()
|
|
{
|
|
if( IsDefined( self.removed_from_friends ) && self.removed_from_friends )
|
|
{
|
|
level.friends = array_add( level.friends, self );
|
|
}
|
|
|
|
self set_force_color( "b" );
|
|
|
|
if( IsDefined( self.og_animname ) )
|
|
{
|
|
self.animname = self.og_animname;
|
|
}
|
|
|
|
self.ignoreall = false;
|
|
self.ignoreme = false;
|
|
self.pacifist = false;
|
|
self PushPlayer( false );
|
|
}
|
|
|
|
// self = a doorholder ai
|
|
parliament_doors_kill_doorholder( animSpot )
|
|
{
|
|
self thread stop_magic_bullet_shield_safe();
|
|
self maps\_anim::set_start_pos( "doorbreach", animSpot.origin, animSpot.angles, undefined );
|
|
self animscripts\shared::DropAllAIWeapons();
|
|
self DoDamage( self.health + 5, (0,0,0) );
|
|
}
|
|
|
|
parliament_doorrunners()
|
|
{
|
|
runners = get_spawners_and_spawn_group( "spawner_parliament_doorrunner", "targetname" );
|
|
|
|
array_thread( runners, ::door_runner_think );
|
|
}
|
|
|
|
door_runner_think()
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.goalradius = 24;
|
|
self.ignoreall = true;
|
|
self.ignoreme = true;
|
|
self.pacifist = true;
|
|
self thread magic_bullet_shield_safe();
|
|
|
|
self SetGoalPos( self.origin );
|
|
|
|
// lock him in place
|
|
org = Spawn( "script_origin", self.origin );
|
|
self LinkTo( org );
|
|
|
|
// HACK get a notetrack for this
|
|
level waittill( "parliament_doors_opening" );
|
|
wait( 8.75 );
|
|
|
|
self Unlink();
|
|
org Delete();
|
|
|
|
self SetGoalNode( getnode_safe( self.target, "targetname" ) );
|
|
self thread stop_magic_bullet_shield_safe();
|
|
self thread ignore_til_goal();
|
|
}
|