4883 lines
120 KiB
Plaintext
4883 lines
120 KiB
Plaintext
#include maps\_utility;
|
|
#include common_scripts\utility;
|
|
#include maps\_hud_util;
|
|
#include maps\_anim;
|
|
#include maps\_stealth_utility;
|
|
#include maps\_slowmo_breach;
|
|
#include maps\af_caves_code;
|
|
|
|
#using_animtree( "generic_human" );
|
|
|
|
// got two tangos down below, do it!
|
|
DO_IT_TIME = 4;
|
|
|
|
main()
|
|
{
|
|
set_console_status();
|
|
|
|
af_caves_firsthalf_init_flags();
|
|
|
|
default_start( ::start_default );
|
|
add_start( "road", ::start_road );
|
|
add_start( "rappel", ::start_rappel );
|
|
add_start( "barracks", ::start_barracks, "barracks (cave entrance)" );
|
|
add_start( "steamroom", ::start_steamroom );
|
|
add_start( "ledge", ::start_ledge );
|
|
add_start( "overlook", ::start_overlook );
|
|
add_start( "control", ::start_control_room );
|
|
add_start( "airstrip", ::start_airstrip );
|
|
|
|
level.primaryWeapon = "cheytac_silencer";
|
|
level.secondaryWeapon = "kriss_acog_silencer";
|
|
|
|
PrecacheModel( "com_flashlight_on" );
|
|
PrecacheModel( "weapon_parabolic_knife" );
|
|
PrecacheModel( "com_cellphone_on_anim" );
|
|
PrecacheItem( "scar_h_thermal_silencer" );
|
|
PrecacheItem( "usp_silencer" );
|
|
PrecacheItem( "rappel_knife" );
|
|
PrecacheItem( "rpg_straight" );
|
|
PrecacheItem( "hellfire_missile_af_caves" );
|
|
PrecacheRumble( "damage_heavy" );
|
|
PrecacheString( &"AF_CAVES_HINT_C4_SWITCH" );
|
|
|
|
level.mortarNoIncomingSound = true;
|
|
level.mortarNoQuake = true;
|
|
|
|
maps\af_caves_fx::main();
|
|
maps\af_caves_precache::main();
|
|
|
|
//JK - Fog and vision are now set in af_caves_fog.gsc
|
|
//VisionSetNaked( "af_caves_outdoors", 0 );
|
|
//setExpFog( 3764.17, 19391, 0.661137, 0.554261, 0.454014, 0.7, 0 );
|
|
|
|
level.goodFriendlyDistanceFromPlayerSquared = 250 * 250;
|
|
level.cosine[ "70" ] = cos( 70 );
|
|
level.cosine[ "45" ] = cos( 45 );
|
|
|
|
maps\af_caves_backhalf::main_af_caves_backhalf_preload();
|
|
maps\_attack_heli::preLoad();
|
|
maps\_breach::main();
|
|
maps\_hand_signals::initHandSignals();
|
|
|
|
maps\_c4::main();
|
|
|
|
maps\af_caves_anim::main();
|
|
maps\createart\af_caves_fog::main();
|
|
maps\_load::main();
|
|
|
|
array_thread( GetEntArray( "steamroom_c4", "targetname" ), maps\_load::ammo_pickup, "c4" );
|
|
|
|
maps\af_caves_backhalf::main_af_caves_backhalf_postload();
|
|
maps\_load::set_player_viewhand_model( "viewhands_player_us_army" );
|
|
|
|
maps\_drone_ai::init();
|
|
maps\_slowmo_breach::slowmo_breach_init();
|
|
maps\_nightvision::main();
|
|
|
|
maps\_stealth::main();
|
|
level.price_stealth_road_sightDistSqrd = 40 * 40;
|
|
level.price_weaponsfree_sightDistSqrd = 8000 * 8000;
|
|
|
|
maps\_patrol_anims::main();
|
|
|
|
animscripts\dog\dog_init::initDogAnimations();
|
|
maps\_idle::idle_main();
|
|
maps\_idle_phone::main();
|
|
maps\_idle_lean_smoke::main();
|
|
maps\_idle_coffee::main();
|
|
maps\_idle_sleep::main();
|
|
maps\_idle_sit_load_ak::main();
|
|
|
|
thread maps\_mortar::bunker_style_mortar();
|
|
level thread maps\af_caves_amb::main();
|
|
|
|
add_hint_string( "begin_descent", &"AF_CAVES_DESCEND", ::should_stop_descend_hint );
|
|
|
|
// Press^3 [{+actionslot 1}] ^7to use Night Vision Goggles.
|
|
add_hint_string( "nvg", &"SCRIPT_NIGHTVISION_USE", maps\_nightvision::ShouldBreakNVGHintPrint );
|
|
add_hint_string( "rappel_melee", &"SCRIPT_PLATFORM_OILRIG_HINT_STEALTH_KILL", ::should_not_do_melee_rappel_hint );
|
|
|
|
|
|
maps\_compass::setupMiniMap( "compass_map_afghan_caves" );
|
|
|
|
createthreatbiasgroup( "player" );
|
|
createthreatbiasgroup( "price" );
|
|
//createthreatbiasgroup( "dogs" );
|
|
//createthreatbiasgroup( "airstrip_tower_enemy" );
|
|
|
|
//setignoremegroup( "price", "airstrip_tower_enemy" );// airstrip_tower_enemy will ignore price
|
|
//setignoremegroup( "airstrip_tower_enemy", "price" );// price will ignore airstrip_tower_enemy
|
|
|
|
level.player setthreatbiasgroup( "player" );
|
|
|
|
//airstrip_tower_enemy = getentarray( "tower_gunners", "script_noteworthy" );
|
|
//array_thread( airstrip_tower_enemy, ::add_spawn_function, ::set_threatbiasgroup, "airstrip_tower_enemy" );
|
|
|
|
road_dogs = GetEntArray( "enemy_road_patrollers_dogs", "script_noteworthy" );
|
|
array_thread( road_dogs, ::add_spawn_function, ::road_dog_think );
|
|
|
|
road_patrollers = GetEntArray( "enemy_road_patrollers", "targetname" );
|
|
array_thread( road_patrollers, ::add_spawn_function, ::road_patroller_spawnfunc );
|
|
|
|
// spawn and setup Price
|
|
price_spawner = getent( "price_spawner", "targetname" );
|
|
price_spawner add_spawn_function( ::price_spawn );
|
|
price_spawner add_spawn_function( ::set_threatbiasgroup, "price" );
|
|
price_spawner spawn_ai();
|
|
|
|
// price won't stop in front of the player's gun until later
|
|
SetSavedDvar( "ai_friendlyFireBlockDuration", "0" );
|
|
|
|
// Misc
|
|
array_thread( getentarray( "clip_nosight", "targetname" ), ::clip_nosight_logic );
|
|
|
|
player_rope = getent( "player_rope", "targetname" );
|
|
player_rope hide();
|
|
|
|
price_new_rope = getent( "soldier_rope", "targetname" );
|
|
price_new_rope hide();
|
|
|
|
rappel_railing_glowing = getent( "rappel_hookup_glowing", "targetname" );
|
|
rappel_railing_glowing hide();
|
|
|
|
thread steamroom_gate_setup();
|
|
|
|
level.mortarNoIncomingSound = true;
|
|
level.mortarNoQuake = true;
|
|
|
|
thread rappel_setup();
|
|
thread barracks_setup();
|
|
thread steamroom_setup();
|
|
thread player_falling_kill_trigger();
|
|
thread player_falling_to_death();
|
|
thread setup_barrel_earthquake();
|
|
|
|
thread maps\af_caves_backhalf::AA_backhalf_init();
|
|
|
|
thread tv_cinematic_think();
|
|
|
|
steamroom_door_closed = getent( "steamroom_door_closed", "targetname" );
|
|
steamroom_door_closed hide_entity();
|
|
}
|
|
|
|
steamroom_gate_setup()
|
|
{
|
|
level.steamroom_gate_open = GetEnt( "steamroom_door_open", "targetname" );
|
|
level.steamroom_gate_closed = GetEnt( "steamroom_door_closed", "targetname" );
|
|
|
|
level.steamroom_gate_closed hide_entity();
|
|
}
|
|
|
|
af_caves_firsthalf_init_flags()
|
|
{
|
|
// global
|
|
flag_init( "scripted_dialogue" );
|
|
flag_init( "stealth_kill_dialogue_running" );
|
|
flag_init( "unsuppressed_weapon_warning_played" );
|
|
flag_init( "player_falling_kill_in_progress" );
|
|
|
|
// intro
|
|
flag_init( "intro_dialogue_start" );
|
|
flag_init( "intro_fade_in" );
|
|
flag_init( "intro_faded_in" );
|
|
flag_init( "player_intro_unlock" );
|
|
flag_init( "intro_player_moved" );
|
|
flag_init( "introscreen_feed_lines" );
|
|
flag_init( "introscreen_feed_lines_done" );
|
|
flag_init( "price_rise_up" );
|
|
flag_init( "price_abort_intro_stop" );
|
|
flag_init( "intro_player_past_starting_area" );
|
|
flag_init( "intro_price_sent_to_post_getup_node" );
|
|
flag_init( "intro_price_reached_post_getup_node" );
|
|
|
|
// road patrol
|
|
flag_init( "price_at_hillside" );
|
|
flag_init( "price_hillside_dialogue_done" );
|
|
flag_init( "road_enemy_wiretap_dialogue_done" );
|
|
flag_init( "road_group1_countdown_kill_aborted" );
|
|
flag_init( "group1_countdown_kill_done" );
|
|
flag_init( "road_group1_killed_without_stealthbreak" );
|
|
flag_init( "road_group2_alerted" );
|
|
flag_init( "road_group2_startmoving" );
|
|
flag_init( "road_group2_walked_away" );
|
|
flag_init( "road_group2_coming_back" );
|
|
flag_init( "road_group2_lastchance" );
|
|
flag_init( "road_player_broke_stealth" );
|
|
flag_init( "road_uav_inbound" );
|
|
flag_init( "player_shot_someone" );
|
|
flag_init( "price_done_moving_to_road" );
|
|
flag_init( "road_patrol_humans_cleared" );
|
|
flag_init( "road_patrol_cleared" );
|
|
|
|
// rappel
|
|
flag_init( "descending" );
|
|
flag_init( "rappel_threads" );
|
|
flag_init( "price_at_rappel" );
|
|
flag_init( "price_hooksup" );
|
|
flag_init( "player_hooking_up" );
|
|
flag_init( "player_hooked_up" );
|
|
flag_init( "player_failed_rappel" );
|
|
flag_init( "player_braked" );
|
|
flag_init( "guard_2_exposing_himself" );
|
|
flag_init( "player_killing_guard" );
|
|
flag_init( "player_rappeled" );
|
|
flag_init( "rappel_guards_react" );
|
|
flag_init( "rappel_end" );
|
|
flag_init( "end_of_rappel_scene" );
|
|
|
|
// barracks
|
|
flag_init( "barracks_price_ready_to_dodge_biggroup" );
|
|
flag_init( "barracks_biggroup_passingby" );
|
|
flag_init( "barracks_biggroup_gone" );
|
|
flag_init( "barracks_stairguys_countdown_dialogue_done" );
|
|
flag_init( "barracks_stairguys_spawned" );
|
|
flag_init( "barracks_stairguys_countdown_kill_done" );
|
|
flag_init( "barracks_stairguys_countdown_kill_aborted" );
|
|
flag_init( "barracks_stealth_broken" );
|
|
flag_init( "barracks_stealthbreak_survived" );
|
|
flag_init( "destroy_tv" );
|
|
flag_init( "barracks_follow_price" );
|
|
|
|
// steam room
|
|
flag_init( "steamroom_start" );
|
|
flag_init( "steamroom_knifekill_setup_done" );
|
|
flag_init( "steamroom_price_knifekill_sequencestart" );
|
|
flag_init( "steamroom_price_knifekill_abort" );
|
|
flag_init( "steamroom_price_knifekill_started" );
|
|
flag_init( "steamroom_price_knifekill_walkup_abort" );
|
|
flag_init( "steamroom_price_knifekill_committed" );
|
|
flag_init( "steamroom_price_knifekill_done" );
|
|
flag_init( "steamroom_halfway_point" );
|
|
flag_init( "steamroom_door_preblow" );
|
|
flag_init( "steamroom_door_blown" );
|
|
flag_init( "steamroom_ambush_started" );
|
|
flag_init( "steamroom_player_spotted" );
|
|
flag_init( "steamroom_patrollers_protect_door" );
|
|
flag_init( "steamroom_ambush_done" );
|
|
flag_init( "steamroom_going_dark" );
|
|
flag_init( "steamroom_lights_out" );
|
|
flag_init( "steamroom_ambush_finish_dialogue_ended" );
|
|
flag_init( "steamroom_done" );
|
|
}
|
|
|
|
// ****** Starts ****** //
|
|
start_default()
|
|
{
|
|
level.player stealth_default();
|
|
thread player_unsuppressed_weapon_warning();
|
|
|
|
thread intro_setup();
|
|
}
|
|
|
|
start_road()
|
|
{
|
|
level.player stealth_default();
|
|
thread player_unsuppressed_weapon_warning();
|
|
|
|
// warp player and price
|
|
playerstruct = GetStruct( "road_player", "targetname" );
|
|
pricestruct = GetStruct( "road_price", "targetname" );
|
|
level.player teleport_to_node( playerstruct );
|
|
level.price teleport_to_node( pricestruct );
|
|
|
|
// stuff that would have been done already
|
|
thread half_particles_setup();
|
|
thread intro_music();
|
|
|
|
flag_set( "price_goto_hillside" );
|
|
flag_set( "intro_price_reached_post_getup_node" );
|
|
|
|
thread objective_follow_price();
|
|
thread road_setup();
|
|
|
|
SoundSetTimeScaleFactor( "Music", 1 );
|
|
SoundSetTimeScaleFactor( "Menu", 1 );
|
|
SoundSetTimeScaleFactor( "Bulletimpact", 1 );
|
|
SoundSetTimeScaleFactor( "Voice", 1 );
|
|
SoundSetTimeScaleFactor( "effects2", 1 );
|
|
SoundSetTimeScaleFactor( "Mission", 1 );
|
|
SoundSetTimeScaleFactor( "Announcer", 1 );
|
|
SoundSetTimeScaleFactor( "local", 1 );
|
|
SoundSetTimeScaleFactor( "physics", 1 );
|
|
SoundSetTimeScaleFactor( "ambient", 1 );
|
|
SoundSetTimeScaleFactor( "auto", 1 );
|
|
}
|
|
|
|
start_rappel()
|
|
{
|
|
level.player stealth_default();
|
|
thread player_unsuppressed_weapon_warning();
|
|
|
|
thread objective_follow_price();
|
|
|
|
rappel_player = GetEnt( "rappel_player", "targetname" );
|
|
rappel_price = GetEnt( "rappel_price", "targetname" );
|
|
level.player teleport_to_node( rappel_player );
|
|
level.price teleport_to_node( rappel_price );
|
|
|
|
level.price AllowedStances( "stand", "crouch", "prone" );
|
|
level.price ForceUseWeapon( "scar_h_thermal_silencer", "primary" );
|
|
|
|
flag_set( "rappel_threads" );
|
|
thread intro_music();
|
|
|
|
wait( .5 );
|
|
thread autosave_by_name( "rappel" );
|
|
}
|
|
|
|
start_barracks()
|
|
{
|
|
thread rappel_price_setup_at_cave();
|
|
|
|
cave_entrance_player = getent( "cave_entrance_player", "targetname" );
|
|
cave_entrance_price = getent( "cave_entrance_price", "targetname" );
|
|
level.player teleport_to_node( cave_entrance_player );
|
|
level.price teleport_to_node( cave_entrance_price );
|
|
|
|
level.player SwitchToWeapon( level.secondaryWeapon );
|
|
|
|
level.price forceUseWeapon( "scar_h_thermal_silencer", "primary" );
|
|
level.price set_force_color( "r" );
|
|
level.price allowedstances( "crouch" );
|
|
|
|
level.player stealth_default();
|
|
thread player_unsuppressed_weapon_warning();
|
|
|
|
flag_set( "end_of_rappel_scene" );
|
|
flag_set( "player_killing_guard" );
|
|
|
|
thread stealth_music();
|
|
|
|
wait .5;
|
|
thread autosave_by_name( "cave_entrance" );
|
|
}
|
|
|
|
start_steamroom() //Starts at the bottom of the stairs just before the steamroom area.
|
|
{
|
|
flag_set( "barracks_follow_price" );
|
|
thread objective_follow_price_again();
|
|
|
|
activate_trigger_with_targetname( "control_room_visionset_indoors" );
|
|
|
|
steamroom_player = GetEnt( "steamroom_player", "targetname" );
|
|
level.player teleport_to_node( steamroom_player );
|
|
|
|
level.player stealth_default();
|
|
thread player_unsuppressed_weapon_warning();
|
|
|
|
level.player SwitchToWeapon( level.secondaryWeapon );
|
|
|
|
steamroom_price = GetEnt( "steamroom_price", "targetname" );
|
|
level.price teleport_to_node( steamroom_price );
|
|
|
|
level.price AllowedStances( "stand", "crouch", "prone" );
|
|
level.price forceUseWeapon( "scar_h_thermal_silencer", "primary" );
|
|
|
|
//level.price enable_ai_color();
|
|
//level.price set_force_color( "r" );
|
|
|
|
//thread turn_off_stealth();
|
|
|
|
flag_set( "steamroom_start" );
|
|
|
|
wait( 0.5 );
|
|
thread autosave_by_name( "steamroom" );
|
|
}
|
|
|
|
start_ledge()
|
|
{
|
|
level notify( "start_ledge" );
|
|
|
|
steamroom_door_setup();
|
|
thread steamroom_door_full_open();
|
|
|
|
level.player stealth_default();
|
|
thread turn_off_stealth();
|
|
|
|
flag_set( "steamroom_halfway_point" );
|
|
|
|
ledge_player = getent( "ledge_player", "targetname" );
|
|
level.player setorigin( ledge_player.origin );
|
|
level.player setplayerangles( ledge_player.angles );
|
|
thread maps\af_caves_backhalf::backhalf_loadout();
|
|
ledge_price = getent( "ledge_price", "targetname" );
|
|
level.price teleport( ledge_price.origin, ledge_price.angles );
|
|
|
|
level.price allowedstances( "stand", "crouch", "prone" );
|
|
level.price forceUseWeapon( "scar_h_thermal_silencer", "primary" );
|
|
|
|
wait( 0.1 ); // SRS hacky, let stealth set up on price so we can turn it off in the event thread
|
|
flag_set( "steamroom_done" ); // SRS triggered at the end of the steamroom scripting, normally
|
|
flag_set( "steamroom_ambush_finish_dialogue_ended" );
|
|
|
|
wait .5;
|
|
thread autosave_by_name( "ledge" );
|
|
}
|
|
|
|
|
|
start_overlook()
|
|
{
|
|
overlook_player = getent( "overlook_player", "targetname" );
|
|
level.player setorigin( overlook_player.origin );
|
|
level.player setplayerangles( overlook_player.angles );
|
|
thread maps\af_caves_backhalf::backhalf_loadout();
|
|
overlook_price = getent( "overlook_price", "targetname" );
|
|
level.price teleport( overlook_price.origin, overlook_price.angles );
|
|
|
|
level.price allowedstances( "stand", "crouch", "prone" );
|
|
level.price forceUseWeapon( "m4_grenadier", "primary" );
|
|
|
|
thread turn_off_stealth();
|
|
|
|
|
|
flag_set( "player_crossed_bridge" );
|
|
activate_trigger_with_targetname( "player_passed_bridge" );
|
|
|
|
wait .5;
|
|
thread autosave_by_name( "overlook" );
|
|
}
|
|
|
|
start_control_room()
|
|
{
|
|
|
|
control_room_player = getent( "control_room_player", "targetname" );
|
|
level.player setorigin( control_room_player.origin );
|
|
level.player setplayerangles( control_room_player.angles );
|
|
thread maps\af_caves_backhalf::backhalf_loadout();
|
|
control_room_price = getent( "control_room_price", "targetname" );
|
|
level.price teleport( control_room_price.origin, control_room_price.angles );
|
|
|
|
level.price allowedstances( "stand", "crouch", "prone" );
|
|
level.price forceUseWeapon( "m4_grenadier", "primary" );
|
|
level.price set_ignoreme( false );
|
|
|
|
// thread kill_sentry_minigun();
|
|
thread turn_off_stealth();
|
|
|
|
thread maps\af_caves_backhalf::AA_breach_init();
|
|
|
|
|
|
flag_set( "player_right_near_breach" );
|
|
flag_set( "player_right_near_breach" );
|
|
|
|
wait( 0.05 );
|
|
level.price enable_ai_color(); // SRS override stealth defaults
|
|
level.price AllowedStances( "stand", "crouch", "prone" );
|
|
}
|
|
|
|
start_airstrip()
|
|
{
|
|
airstrip_player = getent( "airstrip_player", "targetname" );
|
|
level.player setorigin( airstrip_player.origin );
|
|
level.player setplayerangles( airstrip_player.angles );
|
|
thread maps\af_caves_backhalf::backhalf_loadout();
|
|
airstrip_price = getnode( "node_price_escape_cover", "targetname" );
|
|
level.price teleport( airstrip_price.origin, airstrip_price.angles );
|
|
level.price setgoalnode( airstrip_price );
|
|
|
|
level.price allowedstances( "stand", "crouch", "prone" );
|
|
level.price forceUseWeapon( "m4_grenadier", "primary" );
|
|
level.price set_ignoreme( false );
|
|
|
|
thread turn_off_stealth();
|
|
|
|
flag_set( "location_change_control_room" );
|
|
|
|
flag_set( "obj_escape_complete" );
|
|
|
|
wait( 1 );
|
|
thread maps\af_caves_backhalf::AA_airstrip_init();
|
|
}
|
|
|
|
// ****** OBJECTIVES ****** //
|
|
|
|
// ****** 1st Objective, Follow Cpt. Price ****** //
|
|
objective_follow_price()
|
|
{
|
|
objective_number = 0;
|
|
obj_position = level.price.origin;
|
|
|
|
objective_add( objective_number, "active", &"AF_CAVES_FOLLOW_PRICE", obj_position );
|
|
objective_current( objective_number );
|
|
Objective_OnEntity( objective_number, level.price, (0, 0, 70) );
|
|
|
|
flag_wait( "price_hooksup" );
|
|
|
|
wait .5;
|
|
objective_state( objective_number, "done" );
|
|
|
|
thread objective_rappel();
|
|
}
|
|
|
|
// ****** 2nd Objective, Rappel ****** //
|
|
objective_rappel()
|
|
{
|
|
objective_number = 1;
|
|
|
|
objective_add( objective_number, "active", &"AF_CAVES_RAPPEL", ( 3006, 11756, -1834 ) );
|
|
objective_current( objective_number );
|
|
|
|
flag_wait( "player_hooking_up" );
|
|
|
|
wait 1;
|
|
objective_state( objective_number, "done" );
|
|
}
|
|
|
|
// ****** 3rd Objective, Follow Cpt. Price ****** //
|
|
objective_follow_price_again()
|
|
{
|
|
flag_wait( "barracks_follow_price" );
|
|
|
|
Objective_State( 0, "active" );
|
|
Objective_Current( 0 );
|
|
Objective_OnEntity( 0, level.price );
|
|
|
|
flag_wait( "steamroom_ambush_started" );
|
|
|
|
Objective_String( 0, &"AF_CAVES_SUPPORT_PRICE" );
|
|
Objective_SetPointerTextOverride( 0, &"AF_CAVES_OBJ_MARKER_SUPPORT" );
|
|
|
|
flag_wait( "steamroom_ambush_done" );
|
|
|
|
Objective_String( 0, &"AF_CAVES_FOLLOW_PRICE" );
|
|
Objective_SetPointerTextOverride( 0, "" );
|
|
|
|
flag_wait( "obj_ledge_traverse_given" );
|
|
|
|
Objective_State( 0, "done" );
|
|
|
|
/*
|
|
objective_number = 2;
|
|
obj_position = level.price.origin;
|
|
|
|
objective_add( objective_number, "active", &"AF_CAVES_FOLLOW_PRICE", obj_position );
|
|
objective_current( objective_number );
|
|
Objective_OnEntity( objective_number, level.price, (0, 0, 70) );
|
|
|
|
wait .5;
|
|
objective_state( objective_number, "done" );
|
|
*/
|
|
}
|
|
|
|
objective_regroup_on_price()
|
|
{
|
|
objective_number = 4;
|
|
obj_position = level.price.origin;
|
|
|
|
objective_add( objective_number, "active", &"AF_CAVES_REGROUP_WITH_PRICE", obj_position );
|
|
objective_current( objective_number );
|
|
Objective_OnEntity( objective_number, level.price, (0, 0, 70) );
|
|
|
|
flag_wait( "level_exit" );
|
|
|
|
objective_state( objective_number, "done" );
|
|
}
|
|
|
|
// -------------
|
|
// --- INTRO ---
|
|
// -------------
|
|
intro_setup()
|
|
{
|
|
thread half_particles_setup();
|
|
|
|
thread intro_player();
|
|
thread intro_catch_player_running_ahead();
|
|
thread intro_music();
|
|
thread intro_dialogue();
|
|
thread intro_price_rise_out_of_sand();
|
|
|
|
// level progression
|
|
thread road_setup();
|
|
}
|
|
|
|
intro_catch_player_running_ahead()
|
|
{
|
|
trigger_wait_targetname( "trig_intro_past_starting_area" );
|
|
flag_set( "intro_player_past_starting_area" );
|
|
}
|
|
|
|
intro_player()
|
|
{
|
|
playerstruct = GetStruct( "player_intro_spot", "targetname" );
|
|
level.player teleport_to_node( playerstruct );
|
|
level.player AllowCrouch( false );
|
|
level.player AllowStand( false );
|
|
level.player SetStance( "prone" );
|
|
level.player DisableWeapons();
|
|
|
|
wait( 0.2 ); // this is so the player drops to the ground before we freezecontrols
|
|
level.player FreezeControls( true ); // just during black screen
|
|
|
|
level.player.levelStartPos = level.player.origin;
|
|
|
|
flag_wait( "player_intro_unlock" );
|
|
level.player FreezeControls( false );
|
|
level.player AllowCrouch( true );
|
|
level.player AllowStand( true );
|
|
level.player EnableWeapons();
|
|
|
|
thread intro_player_catch_movement();
|
|
|
|
player_speed_percent( 90 );
|
|
}
|
|
|
|
intro_player_catch_movement()
|
|
{
|
|
// waittill after the player moves
|
|
distsqrd = 15 * 15;
|
|
while( DistanceSquared( level.player.origin, level.player.levelStartPos ) < distsqrd )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
flag_set( "intro_player_moved" );
|
|
}
|
|
|
|
intro_dialogue()
|
|
{
|
|
flag_wait( "intro_dialogue_start" );
|
|
|
|
// "I'll wait for you at the exfil point. Three hours."
|
|
radio_dialogue( "afcaves_nkl_waitforyou" );
|
|
|
|
// "Don't bother. This was a one-way flight, mate."
|
|
radio_dialogue( "afcaves_pri_dontbother" );
|
|
|
|
thread intro_sandstorm_and_fadein_flag();
|
|
|
|
// "Then good luck, my friend."
|
|
radio_dialogue( "afcaves_nkl_goodluck" );
|
|
|
|
flag_set( "price_rise_up" );
|
|
|
|
flag_wait( "intro_faded_in" );
|
|
|
|
thread intro_follow_objective();
|
|
flag_set( "introscreen_feed_lines" );
|
|
wait( 9.5 );
|
|
flag_set( "introscreen_feed_lines_done" );
|
|
|
|
if( !flag( "intro_player_moved" ) )
|
|
{
|
|
// "Move out."
|
|
radio_dialogue( "afcaves_pri_moveout" );
|
|
}
|
|
}
|
|
|
|
intro_follow_objective()
|
|
{
|
|
flag_wait( "player_intro_unlock" );
|
|
|
|
thread objective_follow_price();
|
|
}
|
|
|
|
intro_sandstorm_and_fadein_flag()
|
|
{
|
|
thread maps\af_caves_fx::introSandStorm();
|
|
wait( 0.25 ); // need to start the sandstorm before the blackscreen fades up
|
|
flag_set( "intro_fade_in" );
|
|
}
|
|
|
|
intro_price_rise_out_of_sand()
|
|
{
|
|
level.price PushPlayer( true );
|
|
|
|
anim_ent = GetNode( "price_get_up", "targetname" );
|
|
tarp = spawn_anim_model( "tarp", anim_ent.origin );
|
|
|
|
price_and_tarp[ 0 ] = level.price;
|
|
price_and_tarp[ 1 ] = tarp;
|
|
|
|
// he waits to get up
|
|
anim_ent anim_first_frame( price_and_tarp, "rise_up" );
|
|
|
|
flag_wait( "price_rise_up" );
|
|
|
|
delaythread( 4, ::flag_set, "player_intro_unlock" );
|
|
|
|
// now he gets up
|
|
anim_ent anim_single( price_and_tarp, "rise_up" );
|
|
|
|
level.price.moveplaybackrate = 1.2;
|
|
|
|
level.price AllowedStances( "stand", "crouch", "prone" );
|
|
level.price.goalradius = 128;
|
|
|
|
node = GetNode( "node_intro_price_postgetup", "targetname" );
|
|
level.price SetGoalNode( node );
|
|
if( !flag( "price_goto_hillside" ) )
|
|
{
|
|
level.price waittill( "goal" );
|
|
}
|
|
flag_set( "intro_price_reached_post_getup_node" );
|
|
}
|
|
|
|
|
|
// -------------------
|
|
// --- ROAD PATROL ---
|
|
// -------------------
|
|
road_setup()
|
|
{
|
|
level.price PushPlayer( true );
|
|
price_be_stealthy();
|
|
|
|
road_stealth_settings();
|
|
|
|
// deactivate trigger at bottom of hill so price doesn't prematurely move up to its corresponding color node when stealth is broken
|
|
colortrig = GetEnt( "trig_script_color_allies_r5", "targetname" );
|
|
colortrig trigger_off();
|
|
|
|
thread road_price_to_hillside();
|
|
|
|
thread road_ambient_action();
|
|
thread road_autosave();
|
|
|
|
//thread road_price_hillside_nag();
|
|
thread road_price_hillside_dialogue();
|
|
thread road_enemy_wiretap_dialogue();
|
|
|
|
thread road_humans_cleared_tracker();
|
|
thread road_stealthbreak_tracker();
|
|
thread road_playerslide_stealthbreak();
|
|
thread road_stealthbreak_price_dialogue();
|
|
|
|
thread road_price_stealthbreak_think();
|
|
|
|
thread road_group2_moveout();
|
|
|
|
thread road_group1_countdown_kill();
|
|
|
|
thread road_moveup_to_kill_group2();
|
|
|
|
// level progression
|
|
thread road_clear();
|
|
}
|
|
|
|
|
|
|
|
road_stealth_settings()
|
|
{
|
|
// whizby type stuff
|
|
ai_event = [];
|
|
ai_event[ "ai_eventDistBullet" ][ "hidden" ] = 256;
|
|
|
|
// distance within which two AIs can instantly tell each other about new enemies
|
|
ai_event[ "ai_eventDistNewEnemy" ][ "spotted" ] = 750;
|
|
ai_event[ "ai_eventDistNewEnemy" ][ "hidden" ] = 512;
|
|
|
|
thread stealth_ai_event_dist_custom( ai_event );
|
|
|
|
level.corpse_behavior_doesnt_require_player_sight = true;
|
|
}
|
|
|
|
road_ambient_action()
|
|
{
|
|
level thread convoy_loop( "intro_ambient_canyonroad_convoy_vehicle", "player_hooked_up", 12, 25 );
|
|
level thread convoy_loop( "intro_ambient_canyonroad_convoy_vehicle_lower", "player_hooked_up", 12, 25 );
|
|
|
|
flag_wait( "road_group2_startmoving" );
|
|
|
|
wait( 5.5 );
|
|
|
|
air_convoy_road = maps\_vehicle::spawn_vehicles_from_targetname_and_drive( "air_convoy_road" );
|
|
}
|
|
|
|
road_autosave()
|
|
{
|
|
flag_wait( "player_at_overlook" );
|
|
|
|
thread autosave_stealth();
|
|
}
|
|
|
|
road_patroller_spawnfunc()
|
|
{
|
|
corpse_array = [];
|
|
corpse_array[ "found" ] = ::road_patroller_event_override_func;
|
|
self stealth_corpse_behavior_custom( corpse_array );
|
|
|
|
awareness_array = [];
|
|
awareness_array[ "explode" ] = ::road_patroller_event_override_func;
|
|
awareness_array[ "heard_scream" ] = ::road_patroller_event_override_func;
|
|
awareness_array[ "doFlashBanged" ] = ::road_patroller_event_override_func;
|
|
|
|
foreach ( key, value in awareness_array )
|
|
{
|
|
self maps\_stealth_event_enemy::stealth_event_mod( key, value );
|
|
}
|
|
|
|
if( IsDefined( self.script_parameters ) && IsSubStr( self.script_parameters, "group2" ) )
|
|
{
|
|
self thread road_group2_member_alerted_tracker();
|
|
}
|
|
|
|
if( self is_dog() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
self.a.disableLongDeath = true;
|
|
|
|
arr[ "warning1" ] = maps\_stealth_threat_enemy::enemy_alert_level_warning2; // escalate to searching immediately
|
|
arr[ "attack" ] = ::small_goal_attack_behavior;
|
|
self stealth_threat_behavior_replace( arr );
|
|
}
|
|
|
|
road_group2_member_alerted_tracker()
|
|
{
|
|
level endon( "road_group2_alerted" );
|
|
|
|
self thread road_group2_member_catch_stealth_not_normal();
|
|
self waittill_any( "death", "group2_guy_alerted" );
|
|
|
|
flag_set( "road_group2_alerted" );
|
|
}
|
|
|
|
road_group2_member_catch_stealth_not_normal()
|
|
{
|
|
self endon( "death" );
|
|
|
|
while( self ent_flag( "_stealth_normal" ) )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
self notify( "group2_guy_alerted" );
|
|
}
|
|
|
|
road_patroller_event_override_func( type )
|
|
{
|
|
self.favoriteenemy = level.player;
|
|
wait( 1 );
|
|
}
|
|
|
|
/* fix for flashbanged guys sometimes doing the "radio back into base" animation - shut down by leads as NWF, keeping in case we need the fix later after all
|
|
road_patroller_event_override_func( type )
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.favoriteenemy = level.player;
|
|
wait( 1 );
|
|
|
|
// if he's flashed, we need to wait until after he's recovered so he has a chance to see the player
|
|
while( 1 )
|
|
{
|
|
if( self IsFlashed() )
|
|
{
|
|
wait( 0.25 );
|
|
}
|
|
|
|
wait( 0.5 );
|
|
|
|
if( !self IsFlashed() )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
small_goal_attack_behavior()
|
|
{
|
|
self.pathrandompercent = 200;
|
|
self thread disable_cqbwalk();
|
|
self thread maps\_stealth_shared_utilities::enemy_announce_spotted( self.origin );
|
|
|
|
self.goalradius = 1024;
|
|
minGoalRadius = 256;
|
|
timeInc = 2;
|
|
|
|
self endon( "death" );
|
|
|
|
self ent_flag_set( "_stealth_override_goalpos" );
|
|
|
|
while ( IsDefined( self.enemy ) && self ent_flag( "_stealth_enabled" ) )
|
|
{
|
|
gr = self.goalradius - 150;
|
|
if( gr < minGoalRadius )
|
|
{
|
|
gr = minGoalRadius;
|
|
}
|
|
self.goalradius = gr;
|
|
|
|
self SetGoalPos( self.enemy.origin );
|
|
|
|
wait( timeInc );
|
|
}
|
|
}
|
|
|
|
road_dog_think()
|
|
{
|
|
arr[ "attack" ] = ::road_dog_attack_func;
|
|
self stealth_threat_behavior_custom( arr );
|
|
|
|
self stealth_pre_spotted_function_custom( ::road_dog_prespotted_func );
|
|
}
|
|
|
|
road_dog_attack_func()
|
|
{
|
|
self endon( "death" );
|
|
|
|
self clear_run_anim();
|
|
|
|
// delay before attacking
|
|
wait( 5 );
|
|
self.goalradius = 6800;
|
|
self SetGoalEntity( level.player );
|
|
}
|
|
|
|
road_human_prespotted_func_easier()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "_stealth_spotted" );
|
|
|
|
wait( 4 ); // default is 2.25
|
|
}
|
|
|
|
road_human_prespotted_func_harder()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "_stealth_spotted" );
|
|
|
|
wait( 3 );
|
|
}
|
|
|
|
road_dog_prespotted_func()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "_stealth_spotted" );
|
|
|
|
// delay before telling other guys you noticed something
|
|
wait( 5 );
|
|
}
|
|
|
|
road_price_to_hillside()
|
|
{
|
|
flag_wait( "intro_price_reached_post_getup_node" );
|
|
flag_wait( "price_goto_hillside" );
|
|
|
|
thread intro_price_to_hillside_abort_notify( "player_moving_to_road" );
|
|
thread intro_price_to_hillside_abort_notify( "_stealth_spotted" );
|
|
thread intro_price_to_hillside_abort_notify( "player_shot_someone_in_group1" );
|
|
|
|
level.price AllowedStances( "crouch" );
|
|
|
|
node = getnode( "intro_price_hold_up_node", "targetname" );
|
|
node anim_reach_solo( level.price, "intro_stop" );
|
|
|
|
flag_set( "price_at_hillside" );
|
|
|
|
if ( flag( "price_abort_intro_stop" ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
node anim_single_solo( level.price, "intro_stop" );
|
|
|
|
level.price.og_goalradius = level.price.goalradius;
|
|
level.price.goalradius = 96;
|
|
level.price PushPlayer( true );
|
|
level.price SetGoalPos( level.price.origin );
|
|
}
|
|
|
|
intro_price_to_hillside_abort_notify( sNotifyString )
|
|
{
|
|
level endon( "price_abort_intro_stop" );
|
|
level waittill( sNotifyString );
|
|
flag_set( "price_abort_intro_stop" );
|
|
}
|
|
|
|
/*
|
|
road_price_hillside_nag()
|
|
{
|
|
level endon( "player_at_overlook" );
|
|
|
|
wait 30;
|
|
|
|
while ( !flag( "player_at_overlook" ) )
|
|
{
|
|
wait( randomintrange( 25, 35 ) );
|
|
if ( flag( "player_at_overlook" ) )
|
|
break;
|
|
|
|
//Price: "Soap, over here."
|
|
radio_dialogue( "pri_overhere" );
|
|
}
|
|
}
|
|
*/
|
|
|
|
road_price_hillside_dialogue()
|
|
{
|
|
level endon ( "player_moving_to_road" );
|
|
level endon( "_stealth_spotted" );
|
|
level endon( "player_shot_someone_in_group1" );
|
|
level endon( "road_patrol_group1" );
|
|
|
|
thread road_price_hillside_dialogue_stopper();
|
|
level endon( "hillside_dialogue_stop" );
|
|
|
|
flag_wait( "price_goto_hillside" );
|
|
//Price: "Soap, I'm picking up a thermal spike up ahead. The cave must be somewhere over the edge"
|
|
radio_dialogue( "pri_thermalspike" );
|
|
|
|
//flag_wait( "price_at_hillside" );
|
|
flag_wait( "player_at_overlook" );
|
|
|
|
// "Hold up."
|
|
radio_dialogue( "pri_holdup" );
|
|
|
|
// "Enemy patrol."
|
|
radio_dialogue( "pri_enemypatrol" );
|
|
|
|
// "Hold your fire."
|
|
radio_dialogue( "afcaves_pri_holdyourfire" );
|
|
|
|
// Looks like Makarov's intel was solid. This is it.
|
|
radio_dialogue( "afcaves_pri_intelwassolid" );
|
|
|
|
// half the guys start moving down the road
|
|
flag_set( "road_group2_startmoving" );
|
|
|
|
wait( 3.5 );
|
|
|
|
// "Good, they're splitting up. Let them separate."
|
|
radio_dialogue( "afcaves_pri_splittingup" );
|
|
|
|
wait( 1.5 );
|
|
|
|
// "This decryption code better be worth the price we paid..."
|
|
radio_dialogue( "afcaves_pri_decryptioncode" );
|
|
|
|
flag_set( "price_hillside_dialogue_done" );
|
|
}
|
|
|
|
road_price_hillside_dialogue_stopper()
|
|
{
|
|
level endon( "price_hillside_dialogue_done" );
|
|
|
|
while( stealth_is_everything_normal() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
level notify( "hillside_dialogue_stop" );
|
|
}
|
|
|
|
road_enemy_wiretap_dialogue()
|
|
{
|
|
level endon( "road_player_broke_stealth" );
|
|
|
|
flag_wait( "price_hillside_dialogue_done" );
|
|
|
|
wiretap_dialogue_wait();
|
|
// "...(go) ahead Alpha?"
|
|
radio_dialogue( "afcaves_schq_goahead" );
|
|
|
|
wiretap_dialogue_wait();
|
|
// "Riverbed all clear, over."
|
|
radio_dialogue( "afcaves_sc1_riverbedclear" );
|
|
|
|
wiretap_dialogue_wait();
|
|
// "Bravo?"
|
|
radio_dialogue( "afcaves_schq_bravo" );
|
|
|
|
//wiretap_dialogue_wait();
|
|
// "Catwalk all clear... visibility 100%, over."
|
|
//radio_dialogue( "afcaves_sc2_catwalkclear" );/
|
|
|
|
wiretap_dialogue_wait();
|
|
// "Sandstorm. Not much to see right now, over."
|
|
radio_dialogue( "afcaves_sc3_sandstorm" );
|
|
|
|
wiretap_dialogue_wait();
|
|
// "Zulu?"
|
|
radio_dialogue( "afcaves_schq_zulu" );
|
|
|
|
wiretap_dialogue_wait();
|
|
// "...uh, we're starting our patrol east along the canyon, north side access road, over."
|
|
radio_dialogue( "afcaves_sc1_startingpatrol" );
|
|
|
|
//wiretap_dialogue_wait();
|
|
// "Copy that, Disciple Four. Finish your sweep and get back inside. Zulu team report's a heavy sandstorm on the way. Oxide out."
|
|
//radio_dialogue( "afcaves_schq_finishsweep" );
|
|
|
|
flag_set( "road_enemy_wiretap_dialogue_done" );
|
|
}
|
|
|
|
wiretap_dialogue_wait()
|
|
{
|
|
while( 1 )
|
|
{
|
|
startTime = GetTime();
|
|
|
|
flag_waitopen( "scripted_dialogue" );
|
|
flag_waitopen( "stealth_kill_dialogue_running" );
|
|
flag_waitopen( "_stealth_spotted" );
|
|
flag_waitopen( "_stealth_event" );
|
|
|
|
if( GetTime() > startTime )
|
|
{
|
|
// let everything cool out for a moment
|
|
wait( 5 );
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
road_humans_cleared_tracker()
|
|
{
|
|
flag_wait( "player_at_overlook" );
|
|
|
|
group1 = get_ai_group_ai( "road_patrol_enemies_group1" );
|
|
group2 = get_ai_group_ai( "road_patrol_enemies_group2" );
|
|
|
|
allguys = array_combine( group1, group2 );
|
|
|
|
while( group_has_live_human( allguys ) )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
flag_set( "road_patrol_humans_cleared" );
|
|
}
|
|
|
|
road_stealthbreak_tracker()
|
|
{
|
|
level endon( "player_hooked_up" );
|
|
|
|
flag_wait( "_stealth_spotted" );
|
|
|
|
thread road_remove_hillside_clip();
|
|
thread road_remove_hillside_aiclip();
|
|
|
|
flag_set( "road_player_broke_stealth" );
|
|
}
|
|
|
|
road_remove_hillside_aiclip()
|
|
{
|
|
level endon( "player_hooked_up" );
|
|
|
|
flag_wait( "_stealth_spotted" );
|
|
clip = GetEnt( "sbmodel_hillside_brush_aiclip", "targetname" );
|
|
|
|
clip hide_entity();
|
|
}
|
|
|
|
road_playerslide_stealthbreak()
|
|
{
|
|
level endon( "road_player_broke_stealth" );
|
|
|
|
flag_wait( "player_slid_downhill" );
|
|
|
|
vol = GetEnt( "vol_player_slidedown_axis_stealthbreak", "targetname" );
|
|
|
|
axis = vol get_ai_touching_volume( "axis" );
|
|
axis = array_removedead( axis );
|
|
axis = array_removeundefined( axis );
|
|
axis = get_array_of_closest( level.player.origin, axis );
|
|
|
|
if( !axis.size )
|
|
{
|
|
return;
|
|
}
|
|
|
|
alerter = undefined;
|
|
foreach( guy in axis )
|
|
{
|
|
if( IsAlive( guy ) )
|
|
{
|
|
alerter = guy;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !IsDefined( alerter ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
alerter.favoriteenemy = level.player;
|
|
wait( 2 );
|
|
|
|
if( IsAlive( alerter ) )
|
|
{
|
|
alerter.favoriteenemy = undefined;
|
|
}
|
|
}
|
|
|
|
road_stealthbreak_price_dialogue()
|
|
{
|
|
level endon( "road_patrol_cleared" );
|
|
level endon( "road_patrol_humans_cleared" );
|
|
|
|
lines = [];
|
|
// "They're onto us - go loud."
|
|
lines[ 0 ] = "afcaves_pri_ontousgoloud";
|
|
// "We're compromised - go loud."
|
|
lines[ 1 ] = "afcaves_pri_compromisedgoloud";
|
|
|
|
while( !flag( "road_patrol_cleared" ) )
|
|
{
|
|
flag_wait( "_stealth_spotted" );
|
|
|
|
if( flag( "road_patrol_humans_cleared" ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
radio_dialogue( random( lines ) );
|
|
|
|
flag_waitopen( "_stealth_spotted" );
|
|
}
|
|
}
|
|
|
|
road_price_stealthbreak_think()
|
|
{
|
|
flag_wait( "price_at_hillside" );
|
|
flag_wait( "road_player_broke_stealth" );
|
|
|
|
battlechatter_off( "allies" ); // don't start chattering right now
|
|
|
|
wait( 0.5 );
|
|
|
|
level.price PushPlayer( false );
|
|
level.price.dontEverShoot = undefined;
|
|
level.price.maxsightdistsqrd = level.price_weaponsfree_sightDistSqrd;
|
|
level.price set_ignoreme( true );
|
|
|
|
thread road_price_stealthbreak_adjust_behavior();
|
|
level.price thread force_weapon_when_player_not_looking( "scar_h_thermal_silencer" );
|
|
|
|
if( IsDefined( level.price.og_goalradius ) )
|
|
{
|
|
while( level.price._animActive > 0 )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
level.price.goalradius = level.price.og_goalradius;
|
|
level.price.og_goalradius = undefined;
|
|
}
|
|
}
|
|
|
|
road_price_stealthbreak_adjust_behavior()
|
|
{
|
|
og_threatbias = level.price.threatbias;
|
|
level.price.threatbias = -350;
|
|
|
|
og_baseaccuracy = level.price.baseaccuracy;
|
|
level.price.baseaccuracy = 100;
|
|
|
|
while( !stealth_is_everything_normal() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
level.price.threatbias = og_threatbias;
|
|
level.price.baseaccuracy = og_baseaccuracy;
|
|
}
|
|
|
|
road_group2_moveout()
|
|
{
|
|
level endon( "_stealth_spotted" );
|
|
|
|
flag_wait( "road_group2_startmoving" );
|
|
|
|
group2 = get_ai_group_ai( "road_patrol_enemies_group2" );
|
|
array_thread( group2, ::road_group2_moveout_aithink, group2 );
|
|
}
|
|
|
|
force_180turn()
|
|
{
|
|
self anim_generic_run( self, "patrol_turn180" );
|
|
}
|
|
|
|
road_group2_moveout_aithink( group2 )
|
|
{
|
|
self endon( "death" );
|
|
self endon( "_stealth_spotted" );
|
|
|
|
level.road_group2_newgroup = 0;
|
|
self thread road_group2_monitor_distance();
|
|
level thread road_group2_walkaway_wait( group2 );
|
|
|
|
if( !self is_dog() )
|
|
{
|
|
// dog handler should go immediately
|
|
if( !IsDefined( self.script_pet ) )
|
|
{
|
|
wait( RandomFloatRange( 2, 3.5 ) );
|
|
self notify( "end_patrol" );
|
|
self force_180turn();
|
|
}
|
|
else
|
|
{
|
|
self notify( "end_patrol" );
|
|
wait( 0.05 );
|
|
}
|
|
self thread maps\_patrol::patrol( self.script_noteworthy );
|
|
|
|
// walk faster
|
|
thread road_group2_moveout_adjust_movespeed();
|
|
}
|
|
// dog #2 needs to start later so he doesn't run into his master when trying to heel during the 180 turn
|
|
else if( self.script_pet == 2 )
|
|
{
|
|
self.script_pet = -1;
|
|
handler = undefined;
|
|
foreach( guy in group2 )
|
|
{
|
|
if( !guy is_dog() && IsDefined( guy.script_pet ) && guy.script_pet == 2 )
|
|
{
|
|
handler = guy;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !IsDefined( handler ) )
|
|
{
|
|
// player killed handler - dog will bark
|
|
return;
|
|
}
|
|
|
|
handler endon( "death" );
|
|
|
|
waitNode = GetStruct( "relink_pet", "script_noteworthy" );
|
|
waitNode waittill( "trigger" );
|
|
|
|
self.script_pet = 2;
|
|
handler maps\_patrol::linkPet();
|
|
}
|
|
|
|
// wait to hit the trigger twice before registering that we're coming back
|
|
trig = GetEnt( "trig_road_group2_nearendpath", "targetname" );
|
|
numReqHits = 2;
|
|
numHits = 0;
|
|
while( numHits < numReqHits )
|
|
{
|
|
trig waittill( "trigger", other );
|
|
|
|
if( other == self )
|
|
{
|
|
numHits++;
|
|
|
|
while( self IsTouching( trig ) )
|
|
{
|
|
wait( 0.1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !flag( "road_group2_coming_back" ) )
|
|
{
|
|
flag_set( "road_group2_coming_back" );
|
|
}
|
|
|
|
self thread road_group2_ai_alert_when_find_bodies();
|
|
|
|
// getting close to where they can see the bodies
|
|
trigger_wait_targetname( "trig_road_group2_midpath" );
|
|
if( !flag( "road_group2_lastchance" ) )
|
|
{
|
|
flag_set( "road_group2_lastchance" );
|
|
}
|
|
}
|
|
|
|
road_group2_ai_alert_when_find_bodies()
|
|
{
|
|
self endon( "death" );
|
|
|
|
while( !self ent_flag( "_stealth_found_corpse" ) )
|
|
{
|
|
wait( 0.1 );
|
|
}
|
|
|
|
self.favoriteenemy = level.player;
|
|
wait( 2 );
|
|
self.favoriteenemy = undefined;
|
|
}
|
|
|
|
road_group2_moveout_adjust_movespeed()
|
|
{
|
|
self.moveplaybackrate = 1.25;
|
|
self waittill( "_stealth_spotted" );
|
|
self.moveplaybackrate = 1;
|
|
}
|
|
|
|
road_group2_monitor_distance()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "_stealth_spotted" );
|
|
|
|
dist = 500;
|
|
org = ( 2408, 13424, -1840 );
|
|
|
|
while( Distance2D( self.origin, org ) < dist )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
level.road_group2_newgroup++;
|
|
}
|
|
|
|
road_group2_walkaway_wait( group2 )
|
|
{
|
|
numGuys = group2.size;
|
|
|
|
while( group2.size > level.road_group2_newgroup )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
flag_set( "road_group2_walked_away" );
|
|
}
|
|
|
|
// handles coop shooting the first group of guys on the road patrol
|
|
road_group1_countdown_kill()
|
|
{
|
|
level thread road_group1_countdown_kill_spottedflag();
|
|
level thread road_group1_countdown_kill_alldead_flag();
|
|
level endon( "_stealth_spotted" );
|
|
|
|
flag_wait( "road_group2_walked_away" );
|
|
flag_wait( "road_enemy_wiretap_dialogue_done" );
|
|
|
|
while( !stealth_is_everything_normal() )
|
|
{
|
|
wait( 0.1 );
|
|
}
|
|
|
|
thread autosave_stealth();
|
|
|
|
level notify( "road_group1_countdown_kill_alldead_flag_stop" );
|
|
|
|
group1 = get_ai_group_ai( "road_patrol_enemies_group1" );
|
|
left = [];
|
|
right = [];
|
|
dog = undefined;
|
|
|
|
foreach( guy in group1 )
|
|
{
|
|
self.dontattackme = true;
|
|
|
|
if( guy is_dog() )
|
|
{
|
|
dog = guy;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
// player only gets extra time on normal and easy
|
|
if( level.gameskill < 2 )
|
|
{
|
|
guy stealth_pre_spotted_function_custom( ::road_human_prespotted_func_easier );
|
|
}
|
|
else
|
|
{
|
|
// increasing a bit for all difficulties since Price was having trouble reliably shooting both targets within the default prespotted time (2.25 seconds)
|
|
guy stealth_pre_spotted_function_custom( ::road_human_prespotted_func_harder );
|
|
}
|
|
}
|
|
|
|
if( IsDefined( guy.script_parameters ) )
|
|
{
|
|
if( guy.script_parameters == "leftside" )
|
|
{
|
|
left[ left.size ] = guy;
|
|
}
|
|
else if( guy.script_parameters == "rightside" )
|
|
{
|
|
right[ right.size ] = guy;
|
|
}
|
|
}
|
|
}
|
|
|
|
ASSERT( left.size == 2, right.size == 2, IsDefined( dog ) );
|
|
|
|
priceVictims = left;
|
|
playerVictims = right;
|
|
|
|
array_thread( group1, ::road_group1_countdown_kill_trackdamage, playerVictims );
|
|
level thread road_group1_countdown_kill_dialogue();
|
|
|
|
msg = level waittill_any_return( "player_shot_someone_in_group1", "countdown_kill_dialogue_done" );
|
|
|
|
playerTimedOut = false;
|
|
if( IsDefined( msg ) && msg == "countdown_kill_dialogue_done" )
|
|
{
|
|
playerTimedOut = true;
|
|
}
|
|
|
|
// trade target groups if the player shot the "wrong" guy
|
|
if( IsDefined( level.playerShotCorrectVictim ) && !level.playerShotCorrectVictim )
|
|
{
|
|
temp = priceVictims;
|
|
priceVictims = playerVictims;
|
|
playerVictims = temp;
|
|
}
|
|
|
|
price_be_lethal();
|
|
level.price ClearEnemy();
|
|
|
|
while( !all_dead( priceVictims ) )
|
|
{
|
|
foreach( guy in priceVictims )
|
|
{
|
|
if( !IsAlive( guy ) )
|
|
{
|
|
wait( 0.05 );
|
|
continue;
|
|
}
|
|
|
|
if( !IsAlive( level.price.enemy ) )
|
|
{
|
|
price_kill( guy );
|
|
guy waittill( "death" );
|
|
}
|
|
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
if( IsAlive( dog ) )
|
|
{
|
|
// give player a chance to get the dog
|
|
wait( 1.5 );
|
|
}
|
|
|
|
playerKilledDog = true;
|
|
if( IsAlive( dog ) )
|
|
{
|
|
price_kill( dog );
|
|
dog waittill( "death", attacker );
|
|
|
|
if( attacker == level.price )
|
|
{
|
|
playerKilledDog = false;
|
|
}
|
|
}
|
|
|
|
flag_wait( "road_patrol_group1" ); // deathflag
|
|
|
|
// wait so Price has non-superhuman reaction time
|
|
wait( 1 );
|
|
|
|
// congratulate the player if stealth wasn't broken
|
|
if( !flag( "road_player_broke_stealth" ) )
|
|
{
|
|
// player didn't shoot when Price said to
|
|
if( playerTimedOut )
|
|
{
|
|
// "We have to work together, Soap - stick to the plan next time."
|
|
radio_dialogue( "afcaves_pri_sticktoplan" );
|
|
}
|
|
// player kinda messed up and shot a different guy than Price said
|
|
else if( !level.playerShotCorrectVictim )
|
|
{
|
|
// "Close enough."
|
|
radio_dialogue( "afcaves_pri_closeenough" );
|
|
}
|
|
// player got his, plus the dog
|
|
else if( playerKilledDog )
|
|
{
|
|
// "Just like old times."
|
|
radio_dialogue( "afcaves_pri_justlikeoldtimes" );
|
|
}
|
|
// player just got his, price got the dog
|
|
else
|
|
{
|
|
// "Dog neutralized, I count five tangos down."
|
|
radio_dialogue( "afcaves_pri_dogneutralized" );
|
|
}
|
|
|
|
flag_set( "road_group1_killed_without_stealthbreak" );
|
|
}
|
|
|
|
flag_set( "group1_countdown_kill_done" );
|
|
}
|
|
|
|
road_group1_countdown_kill_spottedflag()
|
|
{
|
|
level endon( "group1_countdown_kill_done" );
|
|
level endon( "road_group1_countdown_kill_aborted" );
|
|
|
|
level waittill( "_stealth_spotted" );
|
|
|
|
flag_set( "road_group1_countdown_kill_aborted" );
|
|
}
|
|
|
|
road_group1_countdown_kill_alldead_flag()
|
|
{
|
|
level endon( "group1_countdown_kill_done" );
|
|
level endon( "road_group1_countdown_kill_alldead_flag_stop" );
|
|
level endon( "road_group1_countdown_kill_aborted" );
|
|
|
|
flag_wait( "road_patrol_group1" );
|
|
|
|
flag_set( "road_group1_countdown_kill_aborted" );
|
|
}
|
|
|
|
road_group1_countdown_kill_dialogue()
|
|
{
|
|
level endon( "_stealth_spotted" );
|
|
level endon( "road_group2_alerted" );
|
|
level endon( "player_shot_someone_in_group1" );
|
|
|
|
flag_set( "stealth_kill_dialogue_running" );
|
|
|
|
// "Focus on the group on the right, directly beneath us. Let's take them out first."
|
|
radio_dialogue( "afcaves_pri_grouponright" );
|
|
|
|
// "I'll take the two on the left."
|
|
radio_dialogue( "afcaves_pri_twoonleft" );
|
|
|
|
// "On my mark."
|
|
radio_dialogue( "afcaves_pri_onmymark" );
|
|
|
|
// "Three..."
|
|
radio_dialogue( "afcaves_pri_three" );
|
|
|
|
// "Two..."
|
|
radio_dialogue( "afcaves_pri_two" );
|
|
|
|
// "One..."
|
|
radio_dialogue( "afcaves_pri_one" );
|
|
|
|
// "Mark."
|
|
radio_dialogue( "afcaves_pri_mark" );
|
|
|
|
flag_clear( "stealth_kill_dialogue_running" );
|
|
|
|
wait( 1 ); // delay to let the player shoot before we chastize him for not shooting
|
|
level notify( "countdown_kill_dialogue_done" );
|
|
}
|
|
|
|
all_dead( arr )
|
|
{
|
|
foreach( guy in arr )
|
|
{
|
|
if( IsAlive( guy ) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
road_group1_countdown_kill_trackdamage( playerVictims )
|
|
{
|
|
level endon( "player_shot_someone_in_group1" );
|
|
|
|
self waittill( "damage", damage, attacker );
|
|
|
|
if( attacker == level.player )
|
|
{
|
|
level.playerShotCorrectVictim = false;
|
|
|
|
if( array_contains( playerVictims, self ) )
|
|
{
|
|
level.playerShotCorrectVictim = true;
|
|
}
|
|
|
|
level notify( "player_shot_someone_in_group1" );
|
|
}
|
|
}
|
|
|
|
road_price_group2_warnings()
|
|
{
|
|
level endon( "road_patrol_group2" );
|
|
level endon( "road_group2_alerted" );
|
|
|
|
flag_wait( "road_group2_lastchance" );
|
|
// "Soap, they're about to find the bodies! We need to take them out!"
|
|
radio_dialogue( "afcaves_pri_findthebodies" );
|
|
}
|
|
|
|
road_moveup_to_kill_group2()
|
|
{
|
|
// Price only moves up when the first group is dead
|
|
flag_wait( "road_patrol_group1" );
|
|
|
|
// if we didn't skip the countdown...
|
|
if( !flag( "road_group1_countdown_kill_aborted" ) )
|
|
{
|
|
// wait for it to finish, or for it to abort
|
|
if( !flag( "group1_countdown_kill_done" ) )
|
|
{
|
|
flag_wait_any( "group1_countdown_kill_done", "road_group1_countdown_kill_aborted" );
|
|
}
|
|
}
|
|
|
|
while( !stealth_is_everything_normal() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
// make sure everyone in group2 isn't dead already or that they weren't alerted
|
|
if( !flag( "road_patrol_group2" ) && !flag( "road_group2_alerted" ) )
|
|
{
|
|
thread road_price_group2_warnings();
|
|
|
|
wait( 0.5 ); // human reaction time
|
|
|
|
if( !flag( "road_patrol_group2" ) && !flag( "road_group2_alerted" ) )
|
|
{
|
|
// "All right, we've got to take out the other group before they come back. Move."
|
|
thread radio_dialogue( "afcaves_pri_beforecomeback" );
|
|
}
|
|
}
|
|
|
|
level.price thread force_weapon_when_player_not_looking( "scar_h_thermal_silencer" );
|
|
|
|
price_be_stealthy();
|
|
|
|
level.price set_ignoreme( true );
|
|
|
|
thread road_remove_hillside_clip();
|
|
|
|
// activate trigger now that price can move up
|
|
colortrig = GetEnt( "trig_script_color_allies_r5", "targetname" );
|
|
colortrig trigger_on();
|
|
colortrig notify( "trigger" );
|
|
|
|
anim_ent = getent( "price_slide_animent", "targetname" );
|
|
level.price.goalradius = 24;
|
|
anim_ent anim_reach_solo( level.price, "price_slide" );
|
|
|
|
//if( !flag( "road_group2_alerted" ) )
|
|
//{
|
|
anim_ent anim_single_solo( level.price, "price_slide" );
|
|
//}
|
|
|
|
if( !flag( "road_group2_alerted" ) )
|
|
{
|
|
level.price disable_ai_color();
|
|
level.price.goalradius = 256;
|
|
}
|
|
|
|
// first spot on road to move to
|
|
node1 = GetNode( "node_price_roadspot_1", "targetname" );
|
|
level.price SetGoalNode( node1 );
|
|
level.price waittill( "goal" );
|
|
|
|
if( !flag( "player_slid_downhill" ) && !flag( "road_patrol_group2" ) )
|
|
{
|
|
// nag player to come down the hill
|
|
thread road_moveup_to_kill_group2_nag_player();
|
|
}
|
|
|
|
// make sure player is down on the road
|
|
flag_wait( "player_slid_downhill" );
|
|
|
|
level.price AllowedStances( "stand", "crouch", "prone" );
|
|
|
|
if( !flag( "road_group2_alerted" ) )
|
|
{
|
|
// "Quickly, let's move up and take the others."
|
|
thread radio_dialogue( "afcaves_pri_taketheothers" );
|
|
}
|
|
|
|
level.price disable_ai_color();
|
|
level.price.goalradius = 64;
|
|
|
|
// next spot on road
|
|
node2 = GetNode( "node_price_roadspot_2", "targetname" );
|
|
level.price SetGoalNode( node2 );
|
|
level.price waittill( "goal" );
|
|
|
|
// price can be seen by enemies now
|
|
level.price set_ignoreme( false );
|
|
|
|
flag_set( "price_done_moving_to_road" );
|
|
|
|
if( !flag( "road_group2_alerted" ) )
|
|
{
|
|
thread road_group2_coop_kill();
|
|
}
|
|
}
|
|
|
|
road_moveup_to_kill_group2_nag_player()
|
|
{
|
|
level endon( "player_slid_downhill" );
|
|
level endon( "road_group2_coming_back" );
|
|
level endon( "road_group2_alerted" );
|
|
level endon( "road_patrol_group2" );
|
|
|
|
lines = [];
|
|
// Soap! Down here, let's go!
|
|
lines[ lines.size ] = "afcaves_pri_downhere";
|
|
// Move up! The other group's coming back!
|
|
lines[ lines.size ] = "afcaves_pri_groupsback";
|
|
|
|
while( !flag( "player_slid_downhill" ) )
|
|
{
|
|
foreach( line in lines )
|
|
{
|
|
wait( 10 );
|
|
|
|
if( !flag( "player_slid_downhill" ) )
|
|
{
|
|
radio_dialogue( line );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
road_remove_hillside_clip()
|
|
{
|
|
if( IsDefined( level.removed_hillside_clip ) )
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
level.removed_hillside_clip = true;
|
|
}
|
|
|
|
clip = GetEnt( "price_hillside_clip", "targetname" ); // so price doesn't fall down the cliff if the dogs attack him
|
|
clip ConnectPaths();
|
|
clip NotSolid();
|
|
}
|
|
|
|
road_group2_coop_kill()
|
|
{
|
|
level endon( "_stealth_spotted" );
|
|
|
|
group2 = get_ai_group_ai( "road_patrol_enemies_group2" );
|
|
|
|
// figure out who's actually there (should be everybody)
|
|
alive = [];
|
|
foreach( ai in group2 )
|
|
{
|
|
if( IsAlive( ai ) )
|
|
{
|
|
alive[ alive.size ] = ai;
|
|
}
|
|
}
|
|
ASSERT( alive.size == 3 );
|
|
|
|
// "I'm in position - take the shot."
|
|
thread radio_dialogue( "afcaves_pri_taketheshot" );
|
|
|
|
thread road_group2_price_shoot_with_player( group2 );
|
|
|
|
// wait for guys to turn around
|
|
msg = "";
|
|
if( !flag( "road_group2_coming_back" ) )
|
|
{
|
|
msg = level waittill_any_return( "player_shot_someone_in_group1", "road_group2_coming_back" );
|
|
}
|
|
|
|
if( msg == "road_group2_coming_back" || flag( "road_group2_coming_back" ) )
|
|
{
|
|
level notify( "price_shoot_abort" );
|
|
|
|
// send Price back up the road a bit
|
|
thread road_group2_price_reposition();
|
|
}
|
|
else
|
|
{
|
|
// otherwise we're done since the player engaged these guys
|
|
return;
|
|
}
|
|
|
|
msg = level waittill_any_return( "price_repositioned", "road_group2_alerted" );
|
|
|
|
if( msg == "price_repositioned" )
|
|
{
|
|
// "I'm in position, ready to shoot."
|
|
thread radio_dialogue( "afcaves_pri_readytoshoot" );
|
|
|
|
// wait to shoot again
|
|
thread road_group2_price_shoot_with_player( group2 );
|
|
}
|
|
else
|
|
{
|
|
// player engaged enemies or they were alerted somehow
|
|
return;
|
|
}
|
|
|
|
//flag_wait( "road_group2_lastchance" );
|
|
|
|
// "Soap, they're about to find the bodies! We need to take them out!"
|
|
//radio_dialogue( "afcaves_pri_findthebodies" );
|
|
}
|
|
|
|
road_group2_price_reposition()
|
|
{
|
|
// "Soap, they're coming back - I'm repositioning to get out of sight."
|
|
thread radio_dialogue( "afcaves_pri_repositioning" );
|
|
|
|
level.price.goalradius = 96;
|
|
|
|
node = GetNode( "node_price_roadspot_1", "targetname" );
|
|
level.price SetGoalNode( node );
|
|
level.price waittill( "goal" );
|
|
|
|
level notify( "price_repositioned" );
|
|
}
|
|
|
|
road_group2_price_shoot_with_player( group2 )
|
|
{
|
|
level endon( "price_shoot_abort" );
|
|
|
|
// sort humans into the first slot
|
|
arr = [];
|
|
foreach( guy in group2 )
|
|
{
|
|
if( IsAlive( guy ) && !guy is_dog() )
|
|
{
|
|
arr[ arr.size ] = guy;
|
|
}
|
|
}
|
|
|
|
foreach( guy in group2 )
|
|
{
|
|
if( IsAlive( guy ) && !array_contains( arr, guy ) )
|
|
{
|
|
arr[ arr.size ] = guy;
|
|
}
|
|
}
|
|
|
|
group2 = arr;
|
|
|
|
// wait for the player to shoot
|
|
array_thread( group2, ::road_group2_coop_kill_trackdamage );
|
|
level waittill( "player_shot_someone_in_group2", victim );
|
|
|
|
price_be_lethal();
|
|
level.price ClearEnemy();
|
|
|
|
// Price shoots with the player
|
|
while( !all_dead( group2 ) )
|
|
{
|
|
foreach( ai in group2 )
|
|
{
|
|
if( !IsAlive( ai ) )
|
|
{
|
|
wait( 0.05 );
|
|
continue;
|
|
}
|
|
|
|
if( !IsAlive( level.price.enemy ) )
|
|
{
|
|
price_kill( ai );
|
|
ai waittill( "death" );
|
|
}
|
|
|
|
wait( 0.5 );
|
|
}
|
|
}
|
|
}
|
|
|
|
road_group2_coop_kill_trackdamage()
|
|
{
|
|
level endon( "player_shot_someone_in_group2" );
|
|
|
|
self waittill( "damage", damage, attacker );
|
|
|
|
if( attacker == level.player )
|
|
{
|
|
level notify( "player_shot_someone_in_group2", self );
|
|
}
|
|
}
|
|
|
|
road_clear()
|
|
{
|
|
level endon( "road_uav_inbound" );
|
|
|
|
// deathflags
|
|
flag_wait( "road_patrol_group1" );
|
|
flag_wait( "road_patrol_group2" );
|
|
|
|
flag_set( "road_patrol_cleared" );
|
|
|
|
price_be_stealthy();
|
|
|
|
wait( 1.25 ); // human reaction time
|
|
|
|
if( !flag( "road_player_broke_stealth" ) || ( flag( "road_player_broke_stealth" ) && flag( "road_group1_killed_without_stealthbreak" ) ) )
|
|
{
|
|
// "We don't have much time before they find the bodies. Let's keep moving."
|
|
thread radio_dialogue( "afcaves_pri_muchtime" );
|
|
}
|
|
else
|
|
{
|
|
// don't chastize for group2 stealthbreak because that encounter is pretty easy if player breaks stealth
|
|
if( !flag( "road_group1_killed_without_stealthbreak" ) )
|
|
{
|
|
// "Soap, these aren't your average muppets. No more mistakes, let's go."
|
|
radio_dialogue( "afcaves_pri_nomistakes" );
|
|
}
|
|
}
|
|
|
|
flag_wait( "price_done_moving_to_road" );
|
|
|
|
//thread road_price_sees_thermalspike();
|
|
|
|
flag_set( "rappel_threads" );
|
|
}
|
|
|
|
road_price_sees_thermalspike()
|
|
{
|
|
flag_wait( "price_dialogue_thermalspike" ); // flag triggered by price or player which ever hits it first
|
|
|
|
//Price: "Soap, I'm picking up a thermal spike up ahead. The cave must be somewhere over the edge"
|
|
radio_dialogue( "pri_thermalspike" );
|
|
}
|
|
|
|
|
|
// ---------------------
|
|
// --- AUSSIE RAPPEL ---
|
|
// ---------------------
|
|
rappel_setup()
|
|
{
|
|
flag_wait( "rappel_threads" );
|
|
|
|
thread rappel_guard_weapons();
|
|
thread rappel_effects();
|
|
thread rappel_kill_enemy_hint();
|
|
thread rappel_price_hookup_nag();
|
|
thread rappel_prices_rappel_start();
|
|
thread rappel_show_objective_railing();
|
|
thread rappel_player_rappel_setup();
|
|
thread rappel_zodiacs();
|
|
thread rappel_dialogue();
|
|
thread rappel_ropes();
|
|
thread rappel_price_setup_at_cave();
|
|
thread stealth_music();
|
|
}
|
|
|
|
rappel_zodiacs()
|
|
{
|
|
flag_wait( "player_hooking_up" );
|
|
zodiacs = maps\_vehicle::spawn_vehicles_from_targetname_and_drive( "veh_rappel_zodiac" );
|
|
}
|
|
|
|
rappel_guard_weapons()//
|
|
{
|
|
guards_guns = getentarray( "guard_weapons", "targetname" );
|
|
foreach ( gun in guards_guns )
|
|
{
|
|
gun makeunusable();
|
|
gun hide();
|
|
}
|
|
|
|
flag_wait( "player_killing_guard" );
|
|
|
|
wait 1.75;
|
|
guards_guns = getentarray( "guard_weapons", "targetname" );
|
|
foreach ( gun in guards_guns )
|
|
{
|
|
gun show();
|
|
}
|
|
|
|
flag_wait( "end_of_rappel_scene" );
|
|
|
|
wait 1;
|
|
guards_guns = getentarray( "guard_weapons", "targetname" );
|
|
foreach ( gun in guards_guns )
|
|
{
|
|
gun makeusable();
|
|
}
|
|
}
|
|
|
|
rappel_player_rappel_setup()
|
|
{
|
|
flag_wait( "price_hooksup" );
|
|
|
|
wait( 0.5 );
|
|
|
|
rappel_trigger = getent( "player_rappel_trigger", "targetname" );
|
|
rappel_trigger sethintstring( &"AF_CAVES_RAPPEL_HINT" ); // Press and hold^3 &&1 ^7to rappel
|
|
|
|
for ( ;; )
|
|
{
|
|
rappel_trigger waittill( "trigger" );
|
|
if ( level.player isthrowinggrenade() )
|
|
continue;
|
|
if ( level.player isswitchingweapon() )
|
|
continue;
|
|
break;
|
|
}
|
|
rappel_trigger delete();
|
|
|
|
af_caves_rappel_behavior();
|
|
}
|
|
|
|
rappel_effects()
|
|
{
|
|
flag_wait( "rappel_end" );
|
|
|
|
// done in guard react now
|
|
//exploder( "rappel_disturbance" );
|
|
}
|
|
|
|
rappel_prices_rappel_start()
|
|
{
|
|
level.price allowedstances( "stand" );
|
|
level.price cqb_walk( "off" );
|
|
|
|
level.price.anim_ent = getent( "rappel_animent", "targetname" );
|
|
level thread rappel_price_rappel( level.price.anim_ent );
|
|
|
|
level.price.anim_ent anim_reach_solo( level.price, "pri_rappel_setup" );
|
|
level.price.anim_ent anim_single_solo( level.price, "pri_rappel_setup" );
|
|
|
|
if ( !flag( "player_hooking_up" ) )
|
|
level.price.anim_ent thread anim_loop_solo( level.price, "pri_rappel_idle" );
|
|
}
|
|
|
|
// a notetrack in the pri_rappel_setup animation calls this
|
|
price_rope_hookup( guy )
|
|
{
|
|
level.price_rope = spawn_anim_model( "rope_price", level.price.anim_ent.origin );
|
|
level.price.anim_ent thread anim_single_solo( level.price_rope, "rope_hookup" );
|
|
|
|
flag_set( "price_hooksup" );
|
|
}
|
|
|
|
rappel_price_rappel( anim_ent )
|
|
{
|
|
flag_wait( "player_hooking_up" );
|
|
|
|
thread rappel_price_kill( anim_ent );
|
|
level endon( "player_killing_guard" );
|
|
|
|
level.price set_ignoreme( true );
|
|
level.price set_ignoreme( true );
|
|
|
|
// price is hooked up, now switch to the other rope model.
|
|
level.price_rope Delete();
|
|
level.price_rope = spawn_anim_model( "rappel_rope_price", level.price.anim_ent.origin );
|
|
|
|
price_and_rope[ 0 ] = level.price;
|
|
price_and_rope[ 1 ] = level.price_rope;
|
|
|
|
anim_ent anim_stopanimscripted();
|
|
anim_ent anim_single( price_and_rope, "pri_rappel_jump" );
|
|
|
|
anim_ent thread anim_loop( price_and_rope, "pri_hanging_idle", "stop_hang_idle" );
|
|
}
|
|
|
|
rappel_price_kill( anim_ent )
|
|
{
|
|
flag_wait( "player_killing_guard" );
|
|
|
|
wait 1;
|
|
|
|
anim_ent notify( "stop_hang_idle" );
|
|
anim_ent anim_stopanimscripted();
|
|
level.price attach_model_if_not_attached( "weapon_parabolic_knife", "TAG_INHAND" );
|
|
anim_ent thread anim_single_solo( level.price, "pri_rappel_kill" );
|
|
}
|
|
|
|
rappel_kill_enemy_hint()
|
|
{
|
|
flag_wait( "rappel_end" );
|
|
level.player enableweapons();
|
|
|
|
cone = 8;
|
|
// lerp view back to 0 fov
|
|
level.player LerpViewAngleClamp( 0.5, 0.2, 0.2, cone, cone, cone, cone );//( 0.5, 0.2, 0.2, 0, 0, 0, 0 )
|
|
|
|
wait( DO_IT_TIME );
|
|
|
|
display_hint( "rappel_melee" );
|
|
}
|
|
|
|
rappel_guards_think()
|
|
{
|
|
self endon( "death" );
|
|
|
|
self.battlechatter = false;
|
|
self set_ignoreall( true );
|
|
self set_ignoreme( true );
|
|
}
|
|
|
|
rappel_guard2_patrol()// this is the guard below the price
|
|
{
|
|
level endon( "player_killing_guard" );
|
|
|
|
anim_ent = getent( "flick_animent", "targetname" );
|
|
self.animname = "guard_2";
|
|
|
|
wait 2.75;
|
|
anim_ent anim_single_solo( self, "flick" );
|
|
|
|
anim_ent thread anim_loop_solo( self, "guardB_idle", "stop_guardB_idle" );
|
|
}
|
|
|
|
rappel_guard2_death()// this is the guard below the price
|
|
{
|
|
anim_ent = getent( "rappel_animent", "targetname" );
|
|
self.animname = "guard_2";
|
|
|
|
flag_wait( "player_killing_guard" );
|
|
|
|
wait 1;
|
|
self thread gun_Remove();
|
|
anim_ent anim_single_solo( self, "guard_2_death" );
|
|
|
|
self.a.nodeath = true;
|
|
self.allowdeath = true;
|
|
self.diequietly = true;
|
|
self kill();
|
|
}
|
|
|
|
rappel_guard2_kill_player()// this is the guard below the price
|
|
{
|
|
level endon( "player_killing_guard" );
|
|
|
|
anim_ent = getent( "flick_animent", "targetname" );
|
|
self.animname = "guard_2";
|
|
|
|
flag_wait( "rappel_end" );
|
|
flag_wait( "rappel_guards_react" );
|
|
|
|
anim_ent notify( "stop_guardB_idle" );
|
|
anim_ent thread anim_single_solo( self, "guardB_react" );
|
|
}
|
|
|
|
rappel_guard1_kill_player()// this is the guard below the player
|
|
{
|
|
level endon( "player_killing_guard" );
|
|
|
|
anim_ent = getent( "players_rappel_guard", "targetname" );
|
|
self.animname = "guard_1";
|
|
|
|
anim_ent thread anim_loop_solo( self, "guardA_idle", "stop_guardA_idle" );
|
|
|
|
flag_wait( "rappel_end" );
|
|
wait( 7.2 );
|
|
exploder( "rappel_disturbance" );
|
|
wait( 0.5 );
|
|
flag_set( "rappel_guards_react" );
|
|
|
|
anim_ent notify( "stop_guardA_idle" );
|
|
anim_ent thread anim_single_solo( self, "guardA_react" );
|
|
|
|
wait 2;
|
|
thread hint_fade();
|
|
|
|
level.player EnableDeathShield( false );
|
|
level.player EnableHealthShield( false );
|
|
|
|
magicbullet( self.weapon, self gettagorigin( "tag_flash" ), level.player.origin + (0,0,64) );
|
|
wait .2;
|
|
magicbullet( self.weapon, self gettagorigin( "tag_flash" ), level.player.origin + (0,0,64) );
|
|
wait .2;
|
|
magicbullet( self.weapon, self gettagorigin( "tag_flash" ), level.player.origin + (0,0,64) );
|
|
wait .2;
|
|
magicbullet( self.weapon, self gettagorigin( "tag_flash" ), level.player.origin + (0,0,64) );
|
|
|
|
level.player kill();
|
|
|
|
flag_set( "player_failed_rappel" );
|
|
}
|
|
|
|
rappel_show_objective_railing()
|
|
{
|
|
flag_wait( "price_hooksup" );
|
|
|
|
wait( 0.5 );
|
|
rappel_railing = getent( "rappel_hookup", "targetname" );
|
|
rappel_railing hide();
|
|
|
|
rappel_railing_glowing = getent( "rappel_hookup_glowing", "targetname" );
|
|
rappel_railing_glowing show();
|
|
|
|
flag_wait( "player_hooking_up" );
|
|
|
|
rappel_railing = getent( "rappel_hookup", "targetname" );
|
|
rappel_railing show();
|
|
|
|
rappel_railing_glowing = getent( "rappel_hookup_glowing", "targetname" );
|
|
rappel_railing_glowing hide();
|
|
}
|
|
|
|
rappel_dialogue()
|
|
{
|
|
flag_wait( "pri_hook_up" );
|
|
|
|
flavorbursts_off( "axis" );
|
|
|
|
//Price: "Here we go - hook up here."
|
|
radio_dialogue( "pri_hookup" );
|
|
|
|
// "Disciple Four, Oxide. What's your status, over?"
|
|
thread radio_dialogue( "afcaves_schq_d4whatsyourstatus" );
|
|
|
|
flag_wait( "player_hooking_up" );
|
|
|
|
// "Disciple Four, Oxide, do you copy, over?"
|
|
thread radio_dialogue( "afcaves_schq_d4doyoucopy" );
|
|
|
|
wait 5.5;
|
|
thread autosave_by_name( "rappeling" );
|
|
|
|
//Price: "Go."
|
|
radio_dialogue_overlap( "pri_go" );
|
|
|
|
// "Hey, I'm not gettin' anything from Disciple Four at the north ridge road. Could be a bad transmitter."
|
|
thread radio_dialogue( "afcaves_schq_badtransmitter" );
|
|
|
|
level.price thread play_sound_on_entity( "scn_afcaves_rappel_start_npc" );
|
|
wait 5.3;
|
|
//Price: "Got two tangos down below."
|
|
radio_dialogue( "pri_2inthechest" );
|
|
|
|
flag_wait( "rappel_end" );
|
|
|
|
if( !flag( "player_killing_guard" ) )
|
|
{
|
|
endTime = GetTime() + milliseconds( DO_IT_TIME );
|
|
while( GetTime() < endTime && !flag( "player_killing_guard" ) )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
if( !flag( "player_killing_guard" ) )
|
|
{
|
|
//Price: "Do it."
|
|
radio_dialogue( "pri_doit" );
|
|
}
|
|
}
|
|
|
|
rappel_price_hookup_nag()
|
|
{
|
|
flag_wait( "price_hooksup" );
|
|
level endon( "player_hooking_up" );
|
|
|
|
while ( !flag( "player_hooking_up" ) )
|
|
{
|
|
wait( randomintrange( 24, 34 ) );
|
|
if ( flag( "player_hooking_up" ) )
|
|
break;
|
|
|
|
//* Price: "Soap, hook up."
|
|
radio_dialogue( "pri_soaphookup" );
|
|
|
|
wait( randomintrange( 20, 30 ) );
|
|
if ( flag( "player_hooking_up" ) )
|
|
break;
|
|
|
|
//* Price: "Soap, what's the problem? Hook up to the railing."
|
|
radio_dialogue( "pri_whatstheproblem" );
|
|
|
|
wait( randomintrange( 20, 30 ) );
|
|
if ( flag( "player_hooking_up" ) )
|
|
break;
|
|
|
|
//* Price: "Soap, hook up, let's go."
|
|
radio_dialogue( "pri_hookupletsgo" );
|
|
}
|
|
}
|
|
|
|
rappel_ropes()
|
|
{
|
|
flag_wait( "player_killing_guard" );
|
|
|
|
wait( 5 );
|
|
|
|
player_rope = getent( "player_rope", "targetname" );
|
|
player_rope show();
|
|
|
|
level.price_rope delete();
|
|
|
|
price_new_rope = getent( "soldier_rope", "targetname" );
|
|
price_new_rope show();
|
|
}
|
|
|
|
rappel_price_setup_at_cave()
|
|
{
|
|
flag_wait( "end_of_rappel_scene" );
|
|
|
|
level.default_goalradius = 2048;
|
|
level.price disable_surprise();
|
|
level.price allowedstances( "stand", "crouch", "prone" );
|
|
level.price set_ignoreall( true );
|
|
level.price set_ignoreme( true );
|
|
level.price.dontshootwhilemoving = undefined;
|
|
level.price.baseAccuracy = 25; // I want him to take out a some enemies, but not all of them.
|
|
}
|
|
|
|
|
|
// -------------------------
|
|
// --- CAVE 1 (BARRACKS) ---
|
|
// -------------------------
|
|
barracks_setup()
|
|
{
|
|
// SPAWNFUNCS
|
|
first_patroller = GetEnt( "backdoor_barracks_patroller_guy1", "targetname" );
|
|
first_patroller thread add_spawn_function( ::barracks_firstpatroller_spawnfunc );
|
|
first_patroller thread add_spawn_function( ::barracks_stealthsettings_spawnfunc );
|
|
|
|
biggroup = GetEntArray( "barracks_biggroup", "targetname" );
|
|
array_thread( biggroup, ::add_spawn_function, ::barracks_biggroup_spawnfunc );
|
|
array_thread( biggroup, ::add_spawn_function, ::barracks_stealthsettings_spawnfunc );
|
|
|
|
centerstanders = GetEntArray( "barracks_center_stander", "targetname" );
|
|
array_thread( centerstanders, ::add_spawn_function, ::restrict_fov_until_stealth_broken );
|
|
array_thread( centerstanders, ::add_spawn_function, ::barracks_stealthsettings_spawnfunc );
|
|
|
|
chessplayers = GetEntArray( "backdoor_barracks_chess_player", "targetname" );
|
|
array_thread( chessplayers, ::add_spawn_function, ::restrict_fov_until_stealth_broken );
|
|
array_thread( chessplayers, ::add_spawn_function, ::barracks_stealthsettings_spawnfunc );
|
|
|
|
pacingguy = GetEnt( "barracks_center_pacing_guy", "script_noteworthy" );
|
|
pacingguy thread add_spawn_function( ::barracks_stealthsettings_spawnfunc );
|
|
|
|
fridgeguy = GetEnt( "barracks_center_standing_fridge", "targetname" );
|
|
fridgeguy thread add_spawn_function( ::barracks_stealthsettings_spawnfunc );
|
|
|
|
nearleftguys = GetEntArray( "barracks_nearleft_guy", "targetname" );
|
|
array_thread( nearleftguys, ::add_spawn_function, ::barracks_nearleftguy_spawnfunc );
|
|
array_thread( nearleftguys, ::add_spawn_function, ::barracks_stealthsettings_spawnfunc );
|
|
|
|
stairguys = GetEntArray( "barracks_stairguys", "targetname" );
|
|
array_thread( stairguys, ::add_spawn_function, ::barracks_stairguys_spawnfunc );
|
|
//array_thread( stairguys, ::add_spawn_function, ::barracks_stealthsettings_spawnfunc );
|
|
// END SPAWNFUNCS
|
|
|
|
// wait for rappel to end before starting these threads
|
|
flag_wait( "end_of_rappel_scene" );
|
|
|
|
flavorbursts_on( "axis" );
|
|
|
|
level.corpse_behavior_doesnt_require_player_sight = undefined;
|
|
|
|
thread barracks_player_and_price_setup();
|
|
thread player_unsuppressed_weapon_warning();
|
|
thread objective_follow_price_again();
|
|
|
|
thread barracks_action();
|
|
thread barracks_stealthbreak_action();
|
|
thread barracks_stealthbreak_dialogue();
|
|
thread barracks_center_group();
|
|
thread barracks_chess_players();
|
|
thread barracks_fridge_guy();
|
|
thread barracks_enemy_cleanup_prethink();
|
|
|
|
thread barracks_backdoor_radio();
|
|
thread barracks_tv_light();
|
|
thread barracks_destroy_tv();
|
|
}
|
|
|
|
barracks_stealthsettings_spawnfunc()
|
|
{
|
|
corpse_array = [];
|
|
corpse_array[ "found" ] = ::barracks_enemy_event_override_func;
|
|
self stealth_corpse_behavior_custom( corpse_array );
|
|
|
|
self stealth_pre_spotted_function_custom( ::barracks_prespotted_func );
|
|
|
|
awareness_array = [];
|
|
awareness_array[ "explode" ] = ::barracks_enemy_event_override_func;
|
|
awareness_array[ "heard_scream" ] = ::barracks_enemy_event_override_func;
|
|
awareness_array[ "doFlashBanged" ] = ::barracks_enemy_event_override_func;
|
|
|
|
foreach ( key, value in awareness_array )
|
|
{
|
|
self maps\_stealth_event_enemy::stealth_event_mod( key, value );
|
|
}
|
|
|
|
self.a.disableLongDeath = true;
|
|
|
|
arr[ "warning1" ] = maps\_stealth_threat_enemy::enemy_alert_level_warning2; // escalate to searching immediately
|
|
arr[ "attack" ] = ::small_goal_attack_behavior;
|
|
self stealth_threat_behavior_replace( arr );
|
|
}
|
|
|
|
// guys wait less time before telling others about where the player is
|
|
barracks_prespotted_func()
|
|
{
|
|
wait( 0.5 );
|
|
}
|
|
|
|
barracks_enemy_event_override_func( type )
|
|
{
|
|
self.favoriteenemy = level.player;
|
|
wait( 3 );
|
|
self.favoriteenemy = undefined;
|
|
}
|
|
|
|
barracks_nearleftguy_spawnfunc()
|
|
{
|
|
// player is sprinting the level
|
|
if( !flag( "barracks_biggroup_gone" ) )
|
|
{
|
|
wait( 0.1 );
|
|
self notify( "end_patrol" );
|
|
self.baseaccuracy = 500;
|
|
self playerseek();
|
|
}
|
|
else
|
|
{
|
|
// need to detect the player shooting one of them to make it look like they're visible by the center group
|
|
self thread barracks_nearleftguy_alertondeath();
|
|
}
|
|
}
|
|
|
|
barracks_nearleftguy_alertondeath()
|
|
{
|
|
level endon( "_stealth_spotted" );
|
|
level endon( "steamroom_entrance" );
|
|
|
|
self waittill( "death" );
|
|
|
|
axis = GetAiArray( "axis" );
|
|
axis = get_array_of_closest( self.origin, axis );
|
|
|
|
notified = 0;
|
|
numToNotify = 3;
|
|
foreach( guy in axis )
|
|
{
|
|
if( IsAlive( guy ) && IsDefined( guy._stealth ) )
|
|
{
|
|
guy notify( "heard_scream", level.player.origin );
|
|
notified++;
|
|
|
|
if( notified >= numToNotify )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
barracks_player_and_price_setup()
|
|
{
|
|
player_speed_percent( 90 );
|
|
|
|
level.price cqb_walk( "on" );
|
|
level.price.moveplaybackrate = 1.2;
|
|
level.price PushPlayer( true );
|
|
level.price.pathrandompercent = 0;
|
|
|
|
level.price disable_ai_color();
|
|
}
|
|
|
|
barracks_firstpatroller_spawnfunc()
|
|
{
|
|
self.moveplaybackrate = 1.4;
|
|
self.dieQuietly = true;
|
|
|
|
level.barracks_firstpatroller = self;
|
|
|
|
// catch player trying to skirt around to the left of where this guy pauses
|
|
self thread barracks_firstpatroller_catch_player_sneaking_left();
|
|
}
|
|
|
|
barracks_biggroup_spawnfunc()
|
|
{
|
|
parameters = self.script_parameters;
|
|
|
|
if( RandomInt( 100 ) < 25 || ( IsDefined( parameters ) && IsSubStr( parameters, "flashlight" ) ) )
|
|
{
|
|
self thread give_flashlight();
|
|
}
|
|
|
|
if( IsDefined( parameters ) )
|
|
{
|
|
if( IsSubStr( parameters, "flashlight" ) && RandomInt( 100 ) < 25 )
|
|
{
|
|
self thread give_flashlight();
|
|
}
|
|
|
|
if( IsSubStr( parameters, "handsignal" ) )
|
|
{
|
|
self thread barracks_biggroup_leader_handsignal();
|
|
}
|
|
|
|
if( IsSubStr( parameters, "hallway_guard" ) )
|
|
{
|
|
self thread barracks_biggroup_guy_cqb_disable();
|
|
}
|
|
}
|
|
|
|
self.interval = 60;
|
|
self thread patroller_do_cqbwalk();
|
|
}
|
|
|
|
barracks_biggroup_guy_cqb_disable()
|
|
{
|
|
self endon( "death" );
|
|
self endon( "_stealth_spotted" );
|
|
|
|
self ent_flag_init( "patroller_stop_cqbwalking" );
|
|
self ent_flag_wait( "patroller_stop_cqbwalking" );
|
|
|
|
self notify( "end_scan_when_idle" );
|
|
|
|
self clear_generic_idle_anim();
|
|
self thread disable_cqbwalk();
|
|
self.moveplaybackrate = 1;
|
|
maps\_patrol::set_patrol_run_anim_array();
|
|
}
|
|
|
|
barracks_biggroup_leader_handsignal()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "_stealth_spotted" );
|
|
|
|
self waittill( "goal" );
|
|
self handsignal( "onme", true, "_stealth_spotted" );
|
|
}
|
|
|
|
barracks_biggroup_hallway_guard()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "_stealth_spotted" );
|
|
|
|
self waittill( "_patrol_reached_path_end" );
|
|
}
|
|
|
|
barracks_action()
|
|
{
|
|
level endon( "_stealth_spotted" );
|
|
|
|
thread barracks_rightside_warning();
|
|
|
|
//Price: "Let's go."
|
|
thread radio_dialogue( "pri_letsgo" );
|
|
flag_set( "barracks_follow_price" );
|
|
|
|
thread autosave_stealth();
|
|
|
|
thread price_goto_node( "node_backdoor_start_price" );
|
|
flag_wait( "player_entered_barracks_backdoor_hallway" );
|
|
|
|
thread price_goto_node( "node_backdoor_midpoint_price" );
|
|
flag_wait( "backdoor_hallway_midpoint" );
|
|
|
|
barracks_backdoor_stealth_settings();
|
|
SetSavedDvar( "aim_aimAssistRangeScale", "0" ); // no aim assist right here so we don't auto track the big group
|
|
|
|
thread barracks_price_biggroup_dodgeflag_set();
|
|
thread price_goto_node( "price_easynow_node" );
|
|
|
|
// first guy walking by
|
|
thread activate_trigger_with_targetname( "spawn_patroller_guy1" );
|
|
// "Tango up ahead. Do not engage."
|
|
thread radio_dialogue( "afcaves_pri_tangoupahead" );
|
|
|
|
// wait for the first patroller to get to his idle spot, or die, before spawning the other group
|
|
flag_wait_any( "backdoor_firstpatroller_idlespot_reached", "backdoor_firstpatroller_deathflag" );
|
|
|
|
if( !flag( "backdoor_firstpatroller_deathflag" ) )
|
|
{
|
|
flag_wait( "barracks_price_ready_to_dodge_biggroup" );
|
|
flag_wait( "backdoor_hallway_biggroup" );
|
|
}
|
|
|
|
if( flag( "backdoor_firstpatroller_deathflag" ) )
|
|
{
|
|
// human reaction time
|
|
wait( 1 );
|
|
}
|
|
|
|
// "Patrol coming our way - go left, quickly!"
|
|
thread radio_dialogue( "afcaves_pri_patrolcoming" );
|
|
|
|
thread price_goto_node( "node_barracks_price_biggroup_spotted" );
|
|
|
|
if( flag( "backdoor_firstpatroller_deathflag" ) )
|
|
{
|
|
// add spawnfunc to have them look for the player if he killed the first guard
|
|
biggroupSpawners = GetEntArray( "barracks_biggroup", "targetname" );
|
|
array_thread( biggroupSpawners, ::add_spawn_function, ::alert_heard_scream );
|
|
|
|
// "The guards know something's not right. Get out of sight and stay quiet."
|
|
thread radio_dialogue( "afcaves_pri_guardsknow" );
|
|
}
|
|
|
|
thread activate_trigger_with_targetname( "trig_barracks_biggroup_spawn" );
|
|
|
|
og_moveplaybackrate = level.price.moveplaybackrate;
|
|
level.price.moveplaybackrate = 1;
|
|
level.price cqb_walk( "off" );
|
|
level.price.neverEnableCQB = true;
|
|
//level.price AllowedStances( "crouch" );
|
|
|
|
level.price waittill_any_timeout( 7.5, "goal" ); // timeout in case Price gets hung up on something... this has never actually happened in my testing though
|
|
|
|
wait( 3.5 ); // let them start passing
|
|
|
|
flag_set( "barracks_biggroup_passingby" );
|
|
|
|
if( !flag( "backdoor_firstpatroller_deathflag" ) )
|
|
{
|
|
// "Let them pass."
|
|
radio_dialogue( "afcaves_pri_letthempass" );
|
|
thread barracks_biggroup_wiretap_dialogue();
|
|
}
|
|
|
|
// wait till all guys have passed
|
|
thread barracks_biggroup_waittill_gone();
|
|
flag_wait( "barracks_biggroup_gone" );
|
|
|
|
barracks_waittill_stealth_normal();
|
|
|
|
// take out the smoking guy if he's still around
|
|
firstPatrollerWasAround = false;
|
|
if( !flag( "backdoor_firstpatroller_deathflag" ) && !flag( "backdoor_firstpatroller_left_idle_area" ) )
|
|
{
|
|
firstPatrollerWasAround = true;
|
|
|
|
level.barracks_firstpatroller.health = 5;
|
|
|
|
// "Take out the guard having a smoke, or wait for him to move along."
|
|
thread radio_dialogue( "afcaves_pri_havingasmoke" );
|
|
}
|
|
|
|
msg = flag_wait_any_return( "backdoor_firstpatroller_deathflag", "backdoor_firstpatroller_left_idle_area" );
|
|
level notify( "barracks_firstpatroller_catch_player_abort" );
|
|
|
|
barracks_waittill_stealth_normal();
|
|
|
|
if( firstPatrollerWasAround && msg == "backdoor_firstpatroller_deathflag" )
|
|
{
|
|
// "Good night."
|
|
radio_dialogue_stop();
|
|
wait( 0.35 );
|
|
thread radio_dialogue( "pri_goodnight" );
|
|
wait( 1 ); // non superhuman reaction time before moving
|
|
}
|
|
|
|
thread autosave_stealth();
|
|
|
|
SetSavedDvar( "aim_aimAssistRangeScale", "1" );
|
|
|
|
//Price: "Let's go."
|
|
thread radio_dialogue( "pri_letsgo" );
|
|
|
|
thread barracks_nearleft_dialogue();
|
|
|
|
level.price.moveplaybackrate = 1;
|
|
level.price cqb_walk( "on" );
|
|
level.price.neverEnableCQB = false;
|
|
level.price AllowedStances( "prone", "crouch", "stand" );
|
|
|
|
// move up to the broken wall
|
|
if( !flag( "player_near_price_shuffle_start" ) && !flag( "player_near_price_at_broken_wall" ) )
|
|
{
|
|
thread price_goto_node( "price_smoker_node" );
|
|
flag_wait_any( "player_near_price_shuffle_start", "player_near_price_at_broken_wall" );
|
|
}
|
|
|
|
// move to the broken covercrouch wall right next to the center area
|
|
thread price_goto_node( "node_price_shuffle_start" );
|
|
level.price waittill( "goal" );
|
|
|
|
flag_wait( "player_near_price_shuffle_start" );
|
|
|
|
if( Distance( level.player.origin, level.price.origin ) <= 256 )
|
|
{
|
|
// "Easy now."
|
|
delaythread( 0.5, ::radio_dialogue, "afcaves_pri_easynow" );
|
|
}
|
|
|
|
// make sure the player hasn't run way ahead, otherwise the flag has already been set and
|
|
// won't kill the scripted shuffle in time
|
|
if( !flag( "barracks_player_near_stair_shooting_spot" ) )
|
|
{
|
|
// scripted shuffle! price shuffles down the wall to the left
|
|
node = GetNode( "node_price_barracks_near_center_2", "targetname" );
|
|
level.price.scripted_shuffleNode = node;
|
|
level.price AnimCustom( ::scripted_covercrouch_shuffle_left );
|
|
level.price waittill( "scripted_shuffle_done" );
|
|
}
|
|
|
|
// move to the left of the barracks area
|
|
thread barracks_nearleft_patrollers_watchsix();
|
|
|
|
thread price_goto_node( "price_going_left_node" );
|
|
|
|
flag_wait( "price_dialogue_stayleft" );
|
|
|
|
if( !flag( "nearleft_guys_turnaround" ) )
|
|
{
|
|
node = GetNode( "price_going_left_node", "targetname" );
|
|
price_wait_for_player( 240, node );
|
|
}
|
|
|
|
// move up near the end of the left path
|
|
thread price_goto_node( "node_barracks_price_countdown_kill" );
|
|
|
|
flag_wait( "barracks_player_near_stair_shooting_spot" );
|
|
|
|
thread autosave_stealth();
|
|
|
|
// guys come down the stairs for a coop kill
|
|
thread barracks_stair_guys_coop_kill();
|
|
flag_wait_any( "barracks_stairguys_countdown_kill_done", "barracks_stairguys_countdown_kill_aborted" );
|
|
|
|
barracks_waittill_stealth_normal();
|
|
|
|
level.price PushPlayer( true );
|
|
thread price_goto_node( "node_barracks_price_before_stairs" );
|
|
|
|
if( !flag( "barracks_player_past_price_near_steamroomdoor_spot" ) )
|
|
{
|
|
node = GetNode( "node_barracks_price_before_stairs", "targetname" );
|
|
price_wait_for_player( 240, node );
|
|
}
|
|
|
|
// level progression
|
|
flag_set( "steamroom_start" );
|
|
}
|
|
|
|
barracks_firstpatroller_catch_player_sneaking_left()
|
|
{
|
|
self endon( "death" );
|
|
level endon( "_stealth_spotted" );
|
|
level endon( "barracks_firstpatroller_catch_player_abort" );
|
|
|
|
// wait for flag trigger - player is trying to sneak around the left side
|
|
flag_wait( "player_near_price_shuffle_start" );
|
|
|
|
// alert if alive
|
|
if( IsAlive( self ) )
|
|
{
|
|
self.health = 150;
|
|
self.favoriteenemy = level.player;
|
|
}
|
|
}
|
|
|
|
alert_heard_scream()
|
|
{
|
|
wait( 0.1 ); // let stealth initialize
|
|
self notify( "heard_scream", level.player.origin );
|
|
}
|
|
|
|
barracks_waittill_stealth_normal()
|
|
{
|
|
if( !stealth_is_everything_normal() )
|
|
{
|
|
// "The guards know something's not right. Get out of sight and stay quiet."
|
|
thread radio_dialogue( "afcaves_pri_guardsknow" );
|
|
|
|
while( !stealth_is_everything_normal() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
}
|
|
|
|
barracks_nearleft_dialogue()
|
|
{
|
|
level endon( "steamroom_start" );
|
|
level endon( "_stealth_spotted" );
|
|
|
|
flag_wait( "price_dialogue_stayleft" );
|
|
|
|
// "Two tangos in this corridor - hold your fire and stay to the left."
|
|
radio_dialogue( "afcaves_pri_incorridor" );
|
|
|
|
thread barracks_wiretap_dialogue();
|
|
}
|
|
|
|
barracks_rightside_warning()
|
|
{
|
|
level endon( "steamroom_start" );
|
|
level endon( "_stealth_spotted" );
|
|
|
|
trig = GetEnt( "trig_script_color_alies_r18", "targetname" );
|
|
|
|
while( 1 )
|
|
{
|
|
while( !stealth_is_everything_normal() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
wait( 0.1 );
|
|
|
|
trig waittill( "trigger", other );
|
|
if( !IsPlayer( other ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( !stealth_is_everything_normal() )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// "Soap, that area's full of hostiles. We should keep to the left to avoid being spotted."
|
|
radio_dialogue( "afcaves_pri_avoidbeingspotted" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
barracks_backdoor_stealth_settings()
|
|
{
|
|
stealth_ai_event_dist_default();
|
|
|
|
ai_event = [];
|
|
ai_event[ "ai_eventDistDeath" ][ "hidden" ] = 256;
|
|
|
|
ai_event[ "ai_eventDistFootstepSprint" ][ "hidden" ] = 100;
|
|
|
|
ai_event[ "ai_eventDistFootstep" ] = [];
|
|
ai_event[ "ai_eventDistFootstep" ][ "spotted" ] = 300;
|
|
ai_event[ "ai_eventDistFootstep" ][ "hidden" ] = 100;
|
|
|
|
ai_event[ "ai_eventDistFootstepWalk" ] = [];
|
|
ai_event[ "ai_eventDistFootstepWalk" ][ "spotted" ] = 300;
|
|
ai_event[ "ai_eventDistFootstepWalk" ][ "hidden" ] = 100;
|
|
|
|
thread stealth_ai_event_dist_custom( ai_event );
|
|
|
|
hidden = [];
|
|
hidden[ "prone" ] = 300;
|
|
hidden[ "crouch" ] = 600;
|
|
hidden[ "stand" ] = 600;
|
|
stealth_detect_ranges_set( hidden );
|
|
|
|
corpseDists = [];
|
|
corpseDists[ "player_dist" ] = 725; // if the player is farther than this away from a corpse, and level.corpse_behavior_doesnt_require_player_sight isn't set, the AI won't see the corpse
|
|
corpseDists[ "sight_dist" ] = 400; // how far away AIs will spot a corpse
|
|
stealth_corpse_ranges_custom( corpseDists );
|
|
|
|
// reset from the road event where we needed this set
|
|
level.corpse_behavior_doesnt_require_player_sight = undefined;
|
|
}
|
|
|
|
barracks_price_biggroup_dodgeflag_set()
|
|
{
|
|
level waittill( "price_at_node" );
|
|
wait( 1 );
|
|
flag_set( "barracks_price_ready_to_dodge_biggroup" );
|
|
}
|
|
|
|
barracks_nearleft_patrollers_watchsix()
|
|
{
|
|
level endon( "steamroom_start" );
|
|
level endon( "barracks_player_near_stair_shooting_spot" );
|
|
|
|
// the first flag gets set when the patrollers hit a node on their patrol path,
|
|
// the second flag gets set whenever the player is touching a trigger
|
|
flag_wait_all( "barracks_nearleft_patroller_comingback", "barracks_player_farleft_back_area" );
|
|
|
|
// "Tangos on our six."
|
|
radio_dialogue( "afcaves_pri_tangosonsix" );
|
|
}
|
|
|
|
barracks_wiretap_dialogue()
|
|
{
|
|
flavorbursts_off( "axis" );
|
|
|
|
if( !flag( "nearleft_guys_turnaround" ) )
|
|
{
|
|
// "Disciple Five, Oxide. Gimme a sitrep over."
|
|
radio_dialogue( "afcaves_schq_sitrep" );
|
|
wait( 2 );
|
|
}
|
|
|
|
if( !flag( "nearleft_guys_turnaround" ) )
|
|
{
|
|
// "Disciple Five, Oxide. Gimme a sitrep over. [second time]"
|
|
radio_dialogue( "afcaves_schq_sitrepover" );
|
|
}
|
|
|
|
flag_wait( "barracks_stairguys_countdown_kill_done" );
|
|
|
|
flavorbursts_on( "axis" );
|
|
}
|
|
|
|
barracks_stair_guys_coop_kill()
|
|
{
|
|
if( Distance2D( level.player.origin, level.price.origin ) > 670 )
|
|
{
|
|
// we need to warp price up behind the player cause he's too far behind
|
|
level.price notify( "stop_going_to_node" );
|
|
level.price thread waittill_goal_stealthspotted_interrupt();
|
|
|
|
teleportOrg = ( 5184, 11394, -3735 );
|
|
teleportAng = ( 0, 20.7, 0 );
|
|
level.price ForceTeleport( teleportOrg, teleportAng );
|
|
|
|
thread price_goto_node( "node_barracks_price_countdown_kill" );
|
|
level.price thread move_fast_til_goal();
|
|
}
|
|
|
|
spawners = GetEntArray( "barracks_stairguys", "targetname" );
|
|
guys = spawn_ai_group( spawners, true );
|
|
ASSERT( guys.size == 2 );
|
|
|
|
flag_set( "barracks_stairguys_spawned" );
|
|
|
|
// figure out the guy the player is supposed to kill
|
|
playerVictim = undefined;
|
|
priceVictim = undefined;
|
|
foreach( guy in guys )
|
|
{
|
|
ASSERT( IsDefined( guy.script_parameters ) );
|
|
|
|
if( guy.script_parameters == "left" )
|
|
{
|
|
playerVictim = guy;
|
|
}
|
|
else
|
|
{
|
|
priceVictim = guy;
|
|
}
|
|
}
|
|
ASSERT( IsDefined( playerVictim ), IsDefined( priceVictim ) );
|
|
|
|
level endon( "_stealth_spotted" ); // end if we're not stealthy anymore
|
|
thread barracks_stairguys_countdown_kill_spottedflag();
|
|
|
|
level.playerShotCorrectVictim = undefined;
|
|
level.player.stealthkills = 0;
|
|
array_thread( guys, ::barracks_stairguys_countdown_kill_trackdamage, playerVictim );
|
|
thread barracks_stair_guys_coop_kill_countdown_dialogue();
|
|
|
|
msg = level waittill_any_return( "player_shot_someone_on_stairs", "barracks_stairguys_countdown_dialogue_done" );
|
|
|
|
playerTimedOut = false;
|
|
if( IsDefined( msg ) && msg == "barracks_stairguys_countdown_dialogue_done" )
|
|
{
|
|
playerTimedOut = true;
|
|
}
|
|
|
|
// trade target groups if the player shot the "wrong" guy
|
|
if( IsDefined( level.playerShotCorrectVictim ) && !level.playerShotCorrectVictim )
|
|
{
|
|
temp = priceVictim;
|
|
priceVictim = playerVictim;
|
|
playerVictim = temp;
|
|
}
|
|
|
|
level.price.ignoreall = false;
|
|
price_be_lethal();
|
|
level.price ClearEnemy();
|
|
|
|
if( IsAlive( priceVictim ) )
|
|
{
|
|
price_kill( priceVictim );
|
|
priceVictim waittill( "death" );
|
|
}
|
|
|
|
flag_wait( "barracks_stairguys_deathflag" );
|
|
|
|
// wait so Price has non-superhuman reaction time
|
|
wait( 1 );
|
|
|
|
sayMove = false;
|
|
// congratulate the player if stealth wasn't broken
|
|
if( !flag( "barracks_stairguys_countdown_kill_aborted" ) )
|
|
{
|
|
// player killed them both
|
|
if( level.player.stealthkills == 2 )
|
|
{
|
|
// "Impressive."
|
|
radio_dialogue( "afcaves_pri_impressive" );
|
|
}
|
|
// player kinda messed up and shot a different guy than Price said
|
|
else if( !level.playerShotCorrectVictim )
|
|
{
|
|
// "Close enough."
|
|
radio_dialogue( "afcaves_pri_closeenough" );
|
|
|
|
sayMove = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sayMove = true;
|
|
}
|
|
|
|
if( sayMove )
|
|
{
|
|
// "Move."
|
|
thread radio_dialogue( "afcaves_pri_move2" );
|
|
}
|
|
else
|
|
{
|
|
// "Clear. Go."
|
|
thread radio_dialogue( "afcaves_pri_cleargo" );
|
|
}
|
|
|
|
price_be_stealthy();
|
|
|
|
flag_set( "barracks_stairguys_countdown_kill_done" );
|
|
}
|
|
|
|
waittill_goal_stealthspotted_interrupt()
|
|
{
|
|
self endon( "goal" );
|
|
level waittill( "_stealth_spotted" );
|
|
self notify( "level_stealth_spotted" );
|
|
}
|
|
|
|
move_fast_til_goal()
|
|
{
|
|
og_moveplaybackrate = self.moveplaybackrate;
|
|
self.moveplaybackrate = 1.3;
|
|
self waittill_any( "goal", "level_stealth_spotted" );
|
|
self.moveplaybackrate = og_moveplaybackrate;
|
|
}
|
|
|
|
barracks_stairguys_countdown_kill_spottedflag()
|
|
{
|
|
level endon( "barracks_stairguys_countdown_kill_done" );
|
|
|
|
level waittill( "_stealth_spotted" );
|
|
|
|
flag_set( "barracks_stairguys_countdown_kill_aborted" );
|
|
}
|
|
|
|
barracks_stairguys_countdown_kill_trackdamage( playerVictim )
|
|
{
|
|
self waittill( "damage", damage, attacker );
|
|
|
|
if( attacker == level.player )
|
|
{
|
|
level.playerShotCorrectVictim = false;
|
|
|
|
if( self == playerVictim )
|
|
{
|
|
level.playerShotCorrectVictim = true;
|
|
}
|
|
|
|
level.player.stealthkills++;
|
|
|
|
level notify( "player_shot_someone_on_stairs" );
|
|
}
|
|
}
|
|
|
|
barracks_stair_guys_coop_kill_countdown_dialogue()
|
|
{
|
|
level endon( "_stealth_spotted" );
|
|
level endon( "player_shot_someone_on_stairs" );
|
|
level endon( "barracks_stairguys_countdown_aborted" );
|
|
|
|
// "Soap, we've got two tangos with taclights coming down the stairs under that red light, dead ahead. We've got to take 'em out before they find us."
|
|
radio_dialogue( "afcaves_pri_tangoswithtaclights" );
|
|
|
|
// "I'll take the one on the right. On my mark."
|
|
radio_dialogue( "afcaves_pri_takeoneright" );
|
|
|
|
// "Three..."
|
|
radio_dialogue( "afcaves_pri_three" );
|
|
|
|
// "Two..."
|
|
radio_dialogue( "afcaves_pri_two" );
|
|
|
|
// "One..."
|
|
radio_dialogue( "afcaves_pri_one" );
|
|
|
|
// "Mark."
|
|
radio_dialogue( "afcaves_pri_mark" );
|
|
|
|
wait( 0.5 ); // lets the player shoot before we set the flag
|
|
flag_set( "barracks_stairguys_countdown_dialogue_done" );
|
|
}
|
|
|
|
barracks_stairguys_spawnfunc()
|
|
{
|
|
self thread give_flashlight();
|
|
self.interval = 60;
|
|
self thread patroller_do_cqbwalk();
|
|
|
|
self.health = 5;
|
|
self.moveplaybackrate = 0.75;
|
|
|
|
self thread barracks_stairguy_see_price();
|
|
}
|
|
|
|
barracks_stairguy_see_price()
|
|
{
|
|
self endon( "death" );
|
|
|
|
trig = GetEnt( "trig_barracks_stairguy_seeprice", "targetname" );
|
|
|
|
while( !trig IsTouching( self ) )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
self.favoriteenemy = level.player;
|
|
}
|
|
|
|
barracks_biggroup_wiretap_dialogue()
|
|
{
|
|
level endon( "_stealth_spotted" );
|
|
|
|
flavorbursts_off( "axis" );
|
|
|
|
// "Butcher Seven, Oxide. We've lost contact with Disciple Four uh...probably just the sandstorm that's rollin' in or a bad transmitter. Send a team to check it out, over."
|
|
//radio_dialogue( "afcaves_schq_sendateam" );
|
|
|
|
// "Butcher Seven, Oxide. We've lost contact with Disciple Four."
|
|
radio_dialogue( "afcaves_schq_lostcontact2" );
|
|
|
|
// "Probably just the sandstorm that's rollin' in or a bad transmitter."
|
|
radio_dialogue( "afcaves_schq_badtransmitter2" );
|
|
|
|
// "Send a team to check it out, over."
|
|
radio_dialogue( "afcaves_schq_sendateam2" );
|
|
|
|
// "Roger that Oxide, I'll send Vinson and Lambert. Butcher Seven out."
|
|
radio_dialogue( "afcaves_sc2_sendvinson" );
|
|
|
|
flavorbursts_on( "axis" );
|
|
}
|
|
|
|
barracks_biggroup_waittill_gone()
|
|
{
|
|
areatrig = GetEnt( "trig_barracks_biggroup_pathstart_area", "targetname" );
|
|
|
|
// the guys spawn in staggered so we have to account for them not all being there at the start
|
|
aigroup = "barracks_biggroup";
|
|
guys = [];
|
|
while( !guys.size )
|
|
{
|
|
wait( 0.1 );
|
|
guys = get_ai_group_ai( aigroup );
|
|
}
|
|
|
|
while( guys.size )
|
|
{
|
|
guys = get_ai_group_ai( aigroup );
|
|
|
|
foundOne = false;
|
|
foreach( guy in guys )
|
|
{
|
|
if( guy IsTouching( areatrig ) )
|
|
{
|
|
foundOne = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !foundOne )
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
flag_set( "barracks_biggroup_gone" );
|
|
}
|
|
|
|
barracks_stealthbreak_action()
|
|
{
|
|
level endon( "steamroom_start" );
|
|
|
|
flag_wait( "_stealth_spotted" );
|
|
|
|
flag_set( "barracks_stealth_broken" );
|
|
|
|
// reset things that may have been set during stealth
|
|
SetSavedDvar( "aim_aimAssistRangeScale", "1" );
|
|
|
|
// clean up triggers we don't want anymore, and kill their spawners
|
|
delete_and_kill_targeted_spawners_by_targetname_safe( "trig_barracks_centergroup_walker_spawn" );
|
|
delete_and_kill_targeted_spawners_by_targetname_safe( "trig_barracks_nearleft_guys_spawn" );
|
|
delete_and_kill_targeted_spawners_by_targetname_safe( "spawn_patroller_guy1" );
|
|
|
|
level.price.ignoreall = false;
|
|
level.price.dontEverShoot = undefined;
|
|
level.price.maxsightdistsqrd = level.price_weaponsfree_sightDistSqrd;
|
|
level.price.baseaccuracy = 50;
|
|
|
|
wait( 2 ); // give player and price a chance to react
|
|
|
|
// spawn enemies to defend steamroom entrance (or delete the spawners, if we're too close)
|
|
thread barracks_stealthbreak_steamroom_defenders();
|
|
|
|
// alert everyone
|
|
axis = GetAiArray( "axis" );
|
|
closest = get_array_of_closest( level.player.origin, axis );
|
|
foreach( guy in axis )
|
|
{
|
|
if( IsAlive( guy ) && IsDefined( guy._stealth ) )
|
|
{
|
|
wait( 0.5 );
|
|
guy notify( "heard_scream", level.player.origin );
|
|
break;
|
|
}
|
|
}
|
|
|
|
thread barracks_stealthbreak_abandoned_price_watcher();
|
|
|
|
// enemies search out player after some time passes
|
|
thread barracks_stealthbreak_delayed_playerseek();
|
|
|
|
thread barracks_stealthbreak_enemies_cleanup();
|
|
|
|
// wait for guys to die off
|
|
flag_wait_all( "backdoor_firstpatroller_deathflag", "barracks_centergroup_deathflag", "barracks_nearleft_guys_deathflag" );
|
|
|
|
if( !flag( "player_at_stairs_before_steamroom" ) )
|
|
{
|
|
// price move up to near the steamroom stairs
|
|
thread price_goto_node( "node_barracks_stealthbreak_price_nearexit" );
|
|
}
|
|
|
|
// wait for door guards to die
|
|
flag_wait( "barracks_steamroom_defenders_deathflag" );
|
|
|
|
flag_set( "barracks_stealthbreak_survived" );
|
|
|
|
// "Keep moving."
|
|
radio_dialogue( "pri_keepmoving" );
|
|
|
|
spot = GetEnt( "steamroom_price", "targetname" );
|
|
level.price notify( "price_goto_node" );
|
|
level.price SetGoalPos( groundpos( spot.origin ) );
|
|
|
|
thread autosave_by_name( "barracks_stealthbreak_survived" );
|
|
|
|
// alternate level progression
|
|
flag_set( "steamroom_start" );
|
|
}
|
|
|
|
barracks_stealthbreak_steamroom_defenders()
|
|
{
|
|
spawners = GetEntArray( "barracks_steamroom_defenders", "targetname" );
|
|
if( !flag( "player_pre_steamroom_stairs" ) )
|
|
{
|
|
guys = spawn_ai_group( spawners );
|
|
}
|
|
else
|
|
{
|
|
array_call( spawners, ::Delete );
|
|
}
|
|
}
|
|
|
|
barracks_stealthbreak_abandoned_price_watcher()
|
|
{
|
|
level endon( "barracks_stealthbreak_survived" );
|
|
|
|
trig = GetEnt( "trig_player_on_backdoor_ledge", "targetname" );
|
|
|
|
warnTime = GetTime() + 5000;
|
|
failTime = GetTime() + 12000;
|
|
|
|
playerWarned = false;
|
|
|
|
while( 1 )
|
|
{
|
|
trig waittill( "trigger", other );
|
|
|
|
if( !IsPlayer( other ) )
|
|
{
|
|
wait( 0.05 );
|
|
continue;
|
|
}
|
|
|
|
// wait until warning time
|
|
while( level.player IsTouching( trig ) && !flag( "barracks_stealthbreak_survived" ) && GetTime() < warnTime )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
// check if we can still do the warning
|
|
if( !level.player IsTouching( trig ) || flag( "barracks_stealthbreak_survived" ) )
|
|
{
|
|
wait( 0.05 );
|
|
continue;
|
|
}
|
|
|
|
if( !playerWarned )
|
|
{
|
|
// warn player
|
|
// "Soap, where are you? Get back here!"
|
|
radio_dialogue( "afcaves_pri_getbackhere" );
|
|
playerWarned = true;
|
|
}
|
|
|
|
// wait until ending time
|
|
while( level.player IsTouching( trig ) && !flag( "barracks_stealthbreak_survived" ) && GetTime() < failTime )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
// check if we can still fail the player
|
|
if( !level.player IsTouching( trig ) || flag( "barracks_stealthbreak_survived" ) )
|
|
{
|
|
wait( 0.05 );
|
|
continue;
|
|
}
|
|
|
|
SetDvar( "ui_deadquote", "@AF_CAVES_DEADQUOTE_ABANDONED_PRICE" );
|
|
maps\_utility::missionFailedWrapper();
|
|
}
|
|
}
|
|
|
|
barracks_stealthbreak_delayed_playerseek()
|
|
{
|
|
level endon( "_stealth_normal" );
|
|
level endon( "steamroom_start" );
|
|
|
|
wait( 20 );
|
|
|
|
axis = GetAiArray( "axis" );
|
|
array_thread( axis, ::be_aggressive ); // don't use cover, use flashbangs a bit more
|
|
array_thread( axis, ::playerseek ); // go find the player
|
|
}
|
|
|
|
barracks_stealthbreak_enemies_cleanup()
|
|
{
|
|
numRemaining = 3;
|
|
|
|
axis = GetAiArray( "axis" );
|
|
|
|
while( axis.size > numRemaining && !flag( "player_at_stairs_before_steamroom" ) )
|
|
{
|
|
wait( 0.1 );
|
|
axis = GetAiArray( "axis" );
|
|
axis = array_removedead( axis );
|
|
axis = array_removeundefined( axis );
|
|
|
|
foundNum = 0;
|
|
foreach( guy in axis )
|
|
{
|
|
if( !IsAlive( guy ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( guy doingLongDeath() )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foundNum++;
|
|
}
|
|
|
|
if( foundNum <= numRemaining )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
axis = array_removedead( axis );
|
|
axis = array_removeundefined( axis );
|
|
array_thread( axis, ::make_easier_to_kill );
|
|
array_thread( axis, ::barracks_kill_when_player_not_looking );
|
|
}
|
|
|
|
barracks_kill_when_player_not_looking()
|
|
{
|
|
if( !IsAlive( self ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
self endon( "death" );
|
|
|
|
minDistSqrd = 256 * 256;
|
|
|
|
//while( within_fov( level.player.origin, level.player GetPlayerAngles(), self.origin, level.cosine[ "45" ] ) )
|
|
while ( players_looking_at( self.origin + ( 0, 0, 48 ), undefined, true ) || DistanceSquared( level.player.origin, self.origin ) <= minDistSqrd )
|
|
{
|
|
if( !flag( "steamroom_entrance" ) )
|
|
{
|
|
wait( RandomFloatRange( 0.5, 2 ) );
|
|
}
|
|
else
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
if( !flag( "steamroom_entrance" ) )
|
|
{
|
|
self.dieQuietly = true;
|
|
self Kill();
|
|
}
|
|
else
|
|
{
|
|
self Delete();
|
|
}
|
|
}
|
|
|
|
barracks_stealthbreak_dialogue()
|
|
{
|
|
level endon( "steamroom_start" );
|
|
level.player endon( "death" );
|
|
|
|
broken = [];
|
|
// "They're onto us - go loud."
|
|
broken[ 0 ] = "afcaves_pri_ontousgoloud";
|
|
// "We're compromised - go loud."
|
|
broken[ 1 ] = "afcaves_pri_compromisedgoloud";
|
|
|
|
recover = [];
|
|
// "We got lucky that time."
|
|
recover[ 0 ] = "afcaves_pri_gotlucky";
|
|
// "That was close."
|
|
recover[ 1 ] = "afcaves_pri_thatwasclose";
|
|
|
|
while( !flag( "steamroom_start" ) )
|
|
{
|
|
flag_wait( "_stealth_spotted" );
|
|
|
|
barracks_stealthbreak_enemy_dialogue();
|
|
|
|
if( flag( "_stealth_spotted" ) )
|
|
{
|
|
radio_dialogue( random( broken ) );
|
|
flag_waitopen( "_stealth_spotted" );
|
|
}
|
|
|
|
if( level.player.health > 0 )
|
|
{
|
|
radio_dialogue( random( recover ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
barracks_stealthbreak_enemy_dialogue()
|
|
{
|
|
lines = [];
|
|
// "I see him, he's over here!"
|
|
lines[ 0 ] = "afcaves_sc1_iseehim";
|
|
// "Intruder spotted!"
|
|
lines[ 1 ] = "afcaves_sc1_spotted";
|
|
// "Hostile at my location!"
|
|
lines[ 2 ] = "afcaves_sc1_hostilemyloc";
|
|
|
|
radio_dialogue_stop();
|
|
|
|
axis = GetAiArray( "axis" );
|
|
closest = get_array_of_closest( level.player.origin, axis );
|
|
foreach( guy in axis )
|
|
{
|
|
if( IsAlive( guy ) && IsDefined( guy._stealth ) )
|
|
{
|
|
guy thread radio_dialogue( random( lines ) );
|
|
wait( 0.05 ); // let the dialogue get into the queue before anything after this returns
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
barracks_center_group()
|
|
{
|
|
activate_trigger_with_targetname( "trig_backdoor_barracks_center_group_spawn" );
|
|
}
|
|
|
|
barracks_fridge_guy()
|
|
{
|
|
spawner = GetEnt( "barracks_center_standing_fridge", "targetname" );
|
|
guy = spawner spawn_ai();
|
|
guy.ignoreall = true;
|
|
|
|
guy endon( "death" );
|
|
|
|
node = GetStruct( spawner.target, "targetname" );
|
|
node stealth_ai_idle_and_react( guy, "fridge_idle", "fridge_react" );
|
|
|
|
if( IsAlive( guy ) )
|
|
{
|
|
guy.ignoreall = false;
|
|
}
|
|
}
|
|
|
|
barracks_chess_players()
|
|
{
|
|
guy1 = get_guy_with_script_noteworthy_from_spawner( "chess_guy_1" );
|
|
guy2 = get_guy_with_script_noteworthy_from_spawner( "chess_guy_2" );
|
|
|
|
guys = [];
|
|
guys[ guys.size ] = guy1;
|
|
guys[ guys.size ] = guy2;
|
|
|
|
guy1.animname = "chess_guy1";
|
|
guy2.animname = "chess_guy2";
|
|
guy1.deathanim = guy1 getanim( "chess_death_1" );
|
|
guy2.deathanim = guy2 getanim( "chess_death_2" );
|
|
|
|
array_thread( guys, ::barracks_chess_player_notify_when_broken, "chess_players_broken" );
|
|
array_thread( guys, ::set_allowdeath, true );
|
|
//array_thread( guys, ::set_ignoreall, true );
|
|
|
|
node = GetEnt( "chess_ent", "targetname" );
|
|
node2 = spawn( "script_origin", node.origin );
|
|
node2.angles = node.angles;
|
|
|
|
node thread stealth_ai_idle_and_react( guy1, "chess_idle_1", "chess_surprise_1" );
|
|
node2 thread stealth_ai_idle_and_react( guy2, "chess_idle_2", "chess_surprise_2" );
|
|
|
|
array_thread( guys, ::barracks_chess_players_alert );
|
|
}
|
|
|
|
barracks_chess_player_notify_when_broken( notifyStr )
|
|
{
|
|
self endon( "death" );
|
|
level endon( notifyStr );
|
|
|
|
self ent_flag_waitopen( "_stealth_normal" );
|
|
level notify( notifyStr );
|
|
}
|
|
|
|
barracks_chess_players_alert()
|
|
{
|
|
self stealth_enemy_waittill_alert();
|
|
self thread maps\_stealth_shared_utilities::enemy_announce_spotted_bring_group( level.player.origin );
|
|
self set_ignoreall( false );
|
|
self.deathanim = undefined;
|
|
}
|
|
|
|
barracks_backdoor_radio()
|
|
{
|
|
emitter = GetEnt( "radio_backdoor_emitter", "targetname" );
|
|
alias = "emt_afcaves_radio_music1";
|
|
|
|
emitter thread play_loop_sound_on_entity( alias );
|
|
|
|
trigger_wait_targetname( "trig_radio_damage_backdoor" );
|
|
|
|
emitter stop_loop_sound_on_entity( alias );
|
|
emitter Delete();
|
|
}
|
|
|
|
barracks_enemy_cleanup_prethink()
|
|
{
|
|
flag_wait( "steamroom_entrance" );
|
|
|
|
barracks_enemy_cleanup();
|
|
}
|
|
|
|
barracks_enemy_cleanup()
|
|
{
|
|
guys = [];
|
|
|
|
guys = get_ai_group_ai( "backdoor_firstpatroller" );
|
|
guys = array_combine( guys, get_ai_group_ai( "barracks_centergroup" ) );
|
|
guys = array_combine( guys, get_ai_group_ai( "barracks_biggroup" ) );
|
|
guys = array_combine( guys, get_ai_group_ai( "barracks_nearleft_guys" ) );
|
|
guys = array_combine( guys, get_ai_group_ai( "barracks_stairguys" ) );
|
|
|
|
if( !guys.size )
|
|
{
|
|
return;
|
|
}
|
|
|
|
thread AI_delete_when_out_of_sight( guys, 256 );
|
|
}
|
|
|
|
|
|
// -----------------
|
|
// --- STEAMROOM ---
|
|
// -----------------
|
|
steamroom_setup()
|
|
{
|
|
thread steamroom_before_player_gets_there_setup();
|
|
|
|
// wait for level progression
|
|
flag_wait( "steamroom_start" );
|
|
|
|
if( !flag( "barracks_stealth_broken" ) && !flag( "player_pre_steamroom_stairs" ) )
|
|
{
|
|
thread steamroom_knifekill_setup();
|
|
thread steamroom_price_knifekill();
|
|
}
|
|
|
|
thread steamroom_price_setup();
|
|
thread steamroom_action();
|
|
}
|
|
|
|
steamroom_before_player_gets_there_setup()
|
|
{
|
|
// wait for player to get close
|
|
flag_wait( "player_at_stairs_before_steamroom" );
|
|
exploder( "steamroom_steamclouds" );
|
|
thread steamroom_lighting_setup();
|
|
thread steamroom_door_setup();
|
|
thread steamroom_c4_hide();
|
|
}
|
|
|
|
steamroom_gate_swap()
|
|
{
|
|
yLimit = 9200;
|
|
distSqrd = 512;
|
|
|
|
while( 1 )
|
|
{
|
|
wait( 0.05 );
|
|
|
|
if( level.player.origin[ 1 ] > yLimit )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( level.price.origin[ 1 ] > yLimit )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
if( DistanceSquared( level.player.origin, level.steamroom_gate_closed.origin ) < distSqrd )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( within_fov( level.player.origin, level.player GetPlayerAngles(), level.steamroom_gate_closed.origin, level.cosine[ "45" ] ) )
|
|
{
|
|
continue;
|
|
}
|
|
*/
|
|
|
|
break;
|
|
}
|
|
|
|
level.steamroom_gate_open hide_entity();
|
|
level.steamroom_gate_closed PlaySound( "gate_iron_open" );
|
|
level.steamroom_gate_closed show_entity();
|
|
}
|
|
|
|
steamroom_c4_hide()
|
|
{
|
|
c4 = GetEnt( "smodel_steamroom_c4_plant", "targetname" );
|
|
c4 Hide();
|
|
}
|
|
|
|
steamroom_price_setup()
|
|
{
|
|
level.price disable_ai_color();
|
|
price_be_stealthy();
|
|
|
|
//flag_wait( "player_at_stairs_before_steamroom" );
|
|
flag_wait( "steamroom_door_blown" );
|
|
level.price cqb_walk( "off" );
|
|
level.price.neverEnableCQB = true;
|
|
|
|
level.price thread force_weapon_when_player_not_looking( "masada_eotech" );
|
|
}
|
|
|
|
steamroom_action()
|
|
{
|
|
thread steamroom_dialogue();
|
|
thread steamroom_price_movement();
|
|
thread steamroom_patrollers();
|
|
|
|
flag_wait( "steamroom_going_dark" );
|
|
|
|
thread steamroom_lights_go_out();
|
|
|
|
flag_wait( "steamroom_price_moveup_2" );
|
|
|
|
thread autosave_by_name( "barracks_doorbreach" );
|
|
steamroom_price_teleport(); // teleport him forward if he's still in the barracks
|
|
thread steamroom_blow_door();
|
|
|
|
//thread vision_set_fog_changes( "af_caves_indoors_steamroom_dark", 2.25 );
|
|
thread vision_set_fog_changes( "af_caves_indoors_steamroom", 2.25 );
|
|
delaythread( 2, ::steamroom_price_start_ambush );
|
|
|
|
// wait for ambush
|
|
flag_wait_any( "steamroom_ambush_started", "steamroom_player_spotted" );
|
|
|
|
if( !flag( "steamroom_ambush_started" ) )
|
|
{
|
|
flag_set( "steamroom_ambush_started" );
|
|
}
|
|
|
|
thread turn_off_stealth();
|
|
thread steamroom_price_combat_think();
|
|
thread steamroom_patrollers_protect_door();
|
|
thread steamroom_enemies_cleanup();
|
|
|
|
// wait for guys to die off
|
|
flag_wait_all( "steamroom_patrollers_deathflag", "steamroom_patrollers_group2_deathflag" );
|
|
|
|
if( !flag( "player_clear_steamroom" ) )
|
|
{
|
|
// price move up to near the door
|
|
thread price_goto_node( "node_steamroom_price_near_door" );
|
|
}
|
|
|
|
// wait for door guards to die
|
|
flag_wait( "steamroom_patrollers_doorguard_deathflag" );
|
|
|
|
thread steamroom_ambush_finish_dialogue();
|
|
|
|
flag_set( "steamroom_ambush_done" );
|
|
|
|
if( !flag( "player_clear_steamroom" ) )
|
|
{
|
|
price_goto_node_and_wait_for_player( "node_steamroom_price_exit_bodyup", 320 );
|
|
}
|
|
|
|
// level progression
|
|
flag_set( "steamroom_done" );
|
|
}
|
|
|
|
steamroom_patrollers_protect_door()
|
|
{
|
|
trigger_wait_targetname( "trig_steamroom_near_door" );
|
|
flag_set( "steamroom_patrollers_protect_door" );
|
|
}
|
|
|
|
steamroom_enemies_cleanup()
|
|
{
|
|
numRemaining = 3;
|
|
|
|
flag_wait( "steamroom_door_blown" );
|
|
wait( 1 );
|
|
|
|
axis = GetAiArray( "axis" );
|
|
|
|
while( axis.size > numRemaining && !flag( "steamroom_exit" ) )
|
|
{
|
|
wait( 0.1 );
|
|
axis = GetAiArray( "axis" );
|
|
axis = array_removedead( axis );
|
|
axis = array_removeundefined( axis );
|
|
|
|
foundNum = 0;
|
|
foreach( guy in axis )
|
|
{
|
|
if( !IsAlive( guy ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( guy doingLongDeath() )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
foundNum++;
|
|
}
|
|
|
|
if( foundNum <= numRemaining )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
axis = array_removedead( axis );
|
|
axis = array_removeundefined( axis );
|
|
array_thread( axis, ::make_easier_to_kill );
|
|
array_thread( axis, ::steamroom_kill_when_player_not_looking );
|
|
}
|
|
|
|
make_easier_to_kill()
|
|
{
|
|
if( !IsAlive( self ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
self.health = 1;
|
|
self.attackeraccuracy = 1;
|
|
}
|
|
|
|
steamroom_kill_when_player_not_looking()
|
|
{
|
|
if( !IsAlive( self ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
self endon( "death" );
|
|
|
|
minDistSqrd = 256 * 256;
|
|
|
|
//while( within_fov( level.player.origin, level.player GetPlayerAngles(), self.origin, level.cosine[ "45" ] ) )
|
|
while ( players_looking_at( self.origin + ( 0, 0, 48 ), undefined, true ) || DistanceSquared( level.player.origin, self.origin ) <= minDistSqrd )
|
|
{
|
|
if( !flag( "steamroom_exit" ) )
|
|
{
|
|
wait( RandomFloatRange( 0.5, 2 ) );
|
|
}
|
|
else
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
}
|
|
|
|
if( !flag( "steamroom_exit" ) )
|
|
{
|
|
self.dieQuietly = true;
|
|
self Kill();
|
|
}
|
|
else
|
|
{
|
|
self Delete();
|
|
}
|
|
}
|
|
|
|
steamroom_price_combat_think()
|
|
{
|
|
level.price.ignoreall = false;
|
|
level.price.dontEverShoot = undefined;
|
|
level.price.baseaccuracy = 2;
|
|
level.price.maxsightdistsqrd = level.price_weaponsfree_sightDistSqrd;
|
|
|
|
level.price.ignoresuppression = true;
|
|
level.price.ignoreme = true;
|
|
|
|
flag_wait_or_timeout( "steamroom_ambush_done", 5 );
|
|
|
|
level.price.ignoresuppression = false;
|
|
level.price.ignoreme = false;
|
|
|
|
if( !flag( "steamroom_ambush_done" ) )
|
|
{
|
|
level.price thread enable_ai_color();
|
|
}
|
|
|
|
flag_wait( "steamroom_ambush_done" );
|
|
|
|
level.price disable_ai_color();
|
|
|
|
colortrigs = GetEntArray( "trig_steamroom_allies_color", "script_noteworthy" );
|
|
array_call( colortrigs, ::Delete );
|
|
}
|
|
|
|
steamroom_price_cqb_at_stairs()
|
|
{
|
|
flag_wait( "price_at_steamroom_stairs" );
|
|
level.price cqb_walk( "on" );
|
|
}
|
|
|
|
steamroom_price_movement()
|
|
{
|
|
level endon( "steamroom_ambush_started" );
|
|
|
|
thread steamroom_price_cqb_at_stairs();
|
|
|
|
if( !flag( "barracks_stealth_broken" ) )
|
|
{
|
|
flag_set( "steamroom_price_knifekill_sequencestart" );
|
|
flag_wait( "steamroom_price_knifekill_done" );
|
|
}
|
|
|
|
thread price_goto_node( "node_steamroom_price_1" );
|
|
flag_wait( "steamroom_price_moveup_1" );
|
|
|
|
thread price_goto_node( "node_steamroom_price_2" );
|
|
flag_wait( "steamroom_price_moveup_2" );
|
|
|
|
thread price_goto_node( "node_steamroom_price_3" );
|
|
}
|
|
|
|
steamroom_price_teleport()
|
|
{
|
|
if( level.price.origin[ 1 ] < 9750 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
pos = groundpos( ( 4563, 9222, -3565 ) );
|
|
angles = ( 5207, 9566, -3499 );
|
|
|
|
level.price notify( "scripted_teleport" );
|
|
level.price ForceTeleport( pos, angles );
|
|
}
|
|
|
|
// --- KNIFE KILL SEQUENCE --
|
|
steamroom_knifekill_setup()
|
|
{
|
|
animref = GetEnt( "steamroom_price_stealthkill_animref", "targetname" );
|
|
|
|
spawner = GetEnt( animref.target, "targetname" );
|
|
guy = spawner spawn_ai( true );
|
|
ASSERT( IsDefined( guy ) );
|
|
|
|
guy.ignoreme = false;
|
|
guy.ignoreall = true;
|
|
guy.allowDeath = false;
|
|
guy.grenadeAmmo = 0;
|
|
|
|
guy AnimMode( "gravity" );
|
|
guy SetGoalPos( guy.origin );
|
|
|
|
level.knifekill_animref = animref;
|
|
level.knifekill_guard = guy;
|
|
|
|
flag_set( "steamroom_knifekill_setup_done" );
|
|
}
|
|
|
|
steamroom_price_knifekill()
|
|
{
|
|
flag_wait_all( "steamroom_knifekill_setup_done", "steamroom_price_knifekill_sequencestart" );
|
|
|
|
guard = level.knifekill_guard;
|
|
if( !IsAlive( guard ) )
|
|
{
|
|
flag_set( "steamroom_price_knifekill_done" );
|
|
return;
|
|
}
|
|
|
|
// "Top of the staircase - he's mine."
|
|
thread radio_dialogue( "afcaves_pri_topofstairs" );
|
|
|
|
guard.ignoreall = false;
|
|
guard.allowDeath = true;
|
|
guard.health = 5;
|
|
|
|
animref = level.knifekill_animref;
|
|
price = level.price;
|
|
|
|
priceAnime = "steamroom_knifekill_price";
|
|
guardAnime = "steamroom_knifekill_guard";
|
|
guardIdleAnime = "steamroom_knifekill_guard_idle";
|
|
guardReactAnime = "steamroom_knifekill_guard_reaction";
|
|
|
|
// guard interruptible idle
|
|
guard thread steamroom_price_knifekill_guard_handlephone( guardReactAnime );
|
|
guard AnimMode( "gravity" );
|
|
animref thread anim_generic_loop( guard, guardIdleAnime );
|
|
guard thread steamroom_price_knifekill_guard_idleinterrupt( animref, guardReactAnime );
|
|
level thread steamroom_price_knifekill_guard_fake_dropweapon( guard );
|
|
|
|
price_goto_node_and_wait_for_player( "node_steamroom_price_mid_stairs", 300 );
|
|
|
|
price.dontEverShoot = true;
|
|
price.ignoreall = true;
|
|
price setFlashbangImmunity( true );
|
|
price disable_surprise();
|
|
|
|
animref thread anim_generic_reach( price, priceAnime );
|
|
steamroom_price_knifekill_waitfor_price_reach();
|
|
|
|
if( IsAlive( guard ) && !flag( "steamroom_price_knifekill_abort" ) )
|
|
{
|
|
flag_set( "steamroom_price_knifekill_started" );
|
|
|
|
guard thread steamroom_price_knifekill_guard_handle_death_during_walkup( animref );
|
|
|
|
thread steamroom_price_knifekill_point_of_no_return( priceAnime, guard );
|
|
price thread steamroom_price_knifekill_handleknife( priceAnime );
|
|
|
|
price.anim_start_at_groundpos = true;
|
|
|
|
price thread steamroom_price_knifekill_foley();
|
|
|
|
price delaycall( 0.1, ::PushPlayer, true );
|
|
guard delaycall( 0.1, ::PushPlayer, true );
|
|
|
|
animref thread anim_generic( guard, guardAnime );
|
|
animref anim_generic_gravity( price, priceAnime );
|
|
|
|
price.anim_start_at_groundpos = undefined;
|
|
}
|
|
else
|
|
{
|
|
if( IsAlive( guard ) )
|
|
{
|
|
// price stop where you are until things calm down
|
|
price notify( "new_anim_reach" ); // cancel anim_reach movement
|
|
price SetGoalPos( price.origin );
|
|
price thread steamroom_price_knifekill_aborted_movement();
|
|
|
|
guard PushPlayer( false );
|
|
}
|
|
else
|
|
{
|
|
if( !flag( "steamroom_price_moveup_1" ) )
|
|
{
|
|
thread steamroom_price_knifekill_aborted_dialogue();
|
|
}
|
|
}
|
|
}
|
|
|
|
price.dontEverShoot = undefined;
|
|
price.ignoreall = false;
|
|
price setFlashbangImmunity( false );
|
|
price delaythread( 5, ::enable_surprise );
|
|
price PushPlayer( false );
|
|
|
|
if( flag( "steamroom_price_knifekill_abort" ) && IsAlive( guard ) )
|
|
{
|
|
price.favoriteenemy = guard;
|
|
guard waittill( "death" );
|
|
price.favoriteenemy = undefined;
|
|
}
|
|
|
|
flag_set( "steamroom_price_knifekill_done" );
|
|
}
|
|
|
|
steamroom_price_knifekill_foley()
|
|
{
|
|
ent = Spawn( "script_origin", level.price.origin );
|
|
ent LinkTo( level.price );
|
|
|
|
ent PlaySound( "scn_afcaves_knife_kill_behind" );
|
|
|
|
flag_wait_any( "steamroom_price_knifekill_abort", "steamroom_price_knifekill_walkup_abort", "steamroom_price_knifekill_done" );
|
|
|
|
ent StopSounds();
|
|
wait( 0.05 ); // or else the sound won't stop
|
|
ent Delete();
|
|
}
|
|
|
|
steamroom_price_knifekill_aborted_dialogue()
|
|
{
|
|
// "Never mind, then."
|
|
thread radio_dialogue( "afcaves_pri_nevermind" );
|
|
}
|
|
|
|
steamroom_price_knifekill_guard_handle_death_during_walkup( animref )
|
|
{
|
|
level endon( "steamroom_price_knifekill_committed" );
|
|
|
|
self waittill( "death" );
|
|
|
|
flag_set( "steamroom_price_knifekill_walkup_abort" );
|
|
level.price notify( "stop_animmode" );
|
|
level.price anim_stopanimscripted();
|
|
animref anim_stopanimscripted();
|
|
|
|
thread steamroom_price_knifekill_aborted_dialogue();
|
|
}
|
|
|
|
steamroom_price_knifekill_waitfor_price_reach()
|
|
{
|
|
level endon( "steamroom_price_knifekill_abort" );
|
|
level.price waittill( "anim_reach_complete" );
|
|
}
|
|
|
|
steamroom_price_knifekill_aborted_movement()
|
|
{
|
|
level endon( "steamroom_price_knifekill_done" );
|
|
level.price endon( "scripted_teleport" );
|
|
|
|
wait( 5 );
|
|
// move up to the doorway
|
|
level.price SetGoalPos( groundpos( ( 5207, 9566, -3499 ) ) );
|
|
}
|
|
|
|
steamroom_price_knifekill_guard_fake_dropweapon( guard )
|
|
{
|
|
level endon( "steamroom_price_knifekill_abort" );
|
|
|
|
weapon = guard.a.weaponPos[ "right" ];
|
|
|
|
flag_wait( "steamroom_price_knifekill_started" );
|
|
|
|
wait( 3 );
|
|
|
|
classname = "weapon_" + weapon;
|
|
Spawn( classname, groundpos( level.price GetTagOrigin( "tag_inhand" ) ) );
|
|
}
|
|
|
|
steamroom_price_knifekill_guard_handlephone( guardReactAnime )
|
|
{
|
|
phoneModel = "com_cellphone_on_anim";
|
|
linkTag = "tag_inhand";
|
|
|
|
self Attach( phoneModel, linkTag );
|
|
|
|
msg = flag_wait_any_return( "steamroom_price_knifekill_abort", "steamroom_price_knifekill_started" );
|
|
|
|
if( msg == "steamroom_price_knifekill_abort" )
|
|
{
|
|
animTime = GetAnimLength( getanim_generic( guardReactAnime ) );
|
|
waitTime = animTime * 0.04; // 4% of the way through
|
|
wait( waitTime );
|
|
}
|
|
else
|
|
{
|
|
self waittillmatch( "single anim", "end_reaction" );
|
|
}
|
|
|
|
self Detach( phoneModel, linkTag );
|
|
|
|
}
|
|
|
|
steamroom_price_knifekill_guard_idleinterrupt( animref, guardReactAnime )
|
|
{
|
|
self endon( "death" );
|
|
level endon( "steamroom_price_knifekill_started" );
|
|
|
|
self thread steamroom_price_knifekill_catch_player_movement_nearby();
|
|
self thread steamroom_price_knifekill_guard_catch_playerclose();
|
|
self thread steamroom_price_knifekill_guard_catch_gunshot();
|
|
self waittill_any( "playerclose", "bulletwhizby", "bullethit", "damage", "flashbang", "grenade danger", "explode" );
|
|
|
|
flag_set( "steamroom_price_knifekill_abort" );
|
|
animref anim_stopanimscripted();
|
|
|
|
self.health = 150;
|
|
self.ignoreall = false;
|
|
self.favoriteenemy = level.player;
|
|
self disable_surprise();
|
|
animref anim_generic_gravity( self, guardReactAnime );
|
|
|
|
wait( 2 );
|
|
|
|
self.favoriteenemy = undefined;
|
|
|
|
wait( 3 );
|
|
|
|
if( IsAlive( self ) )
|
|
{
|
|
vol = GetEnt( "goalvolume_steamroom_patrollers", "targetname" );
|
|
self SetGoalVolumeAuto( vol );
|
|
}
|
|
}
|
|
|
|
steamroom_price_knifekill_guard_catch_gunshot()
|
|
{
|
|
level endon( "steamroom_price_knifekill_abort" );
|
|
level endon( "steamroom_price_knifekill_started" );
|
|
|
|
self addAIEventListener( "gunshot" );
|
|
|
|
while( 1 )
|
|
{
|
|
self waittill( "ai_event", msg );
|
|
|
|
if( msg == "gunshot" )
|
|
{
|
|
self notify( "playerclose" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
steamroom_price_knifekill_guard_catch_playerclose()
|
|
{
|
|
level endon( "steamroom_price_knifekill_abort" );
|
|
level endon( "steamroom_price_knifekill_started" );
|
|
|
|
flag_wait( "steamroom_knifekill_guard_playerclose" );
|
|
|
|
self notify( "playerclose" );
|
|
}
|
|
|
|
steamroom_price_knifekill_catch_player_movement_nearby()
|
|
{
|
|
level endon( "steamroom_price_knifekill_abort" );
|
|
level endon( "steamroom_price_knifekill_started" );
|
|
|
|
flag_init( "player_jumping" );
|
|
thread player_jump_watcher();
|
|
thread player_jump_watcher_ender();
|
|
|
|
while( 1 )
|
|
{
|
|
wait( 0.05 );
|
|
|
|
if( !flag( "steamroom_stealthkill_player_in_awareness_zone" ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if( flag( "player_jumping" ) )
|
|
{
|
|
self notify( "playerclose" );
|
|
}
|
|
|
|
speed = get_player_speed();
|
|
|
|
if( speed > 200 ) // sprinting or doing weird stuff
|
|
{
|
|
self notify( "playerclose" );
|
|
}
|
|
}
|
|
}
|
|
|
|
player_jump_watcher()
|
|
{
|
|
level endon( "player_jump_watcher_stop" );
|
|
|
|
jumpflag = "player_jumping";
|
|
if( !flag_exist( jumpflag ) )
|
|
{
|
|
flag_init( jumpflag );
|
|
}
|
|
else
|
|
{
|
|
flag_clear( jumpflag );
|
|
}
|
|
|
|
NotifyOnCommand( "playerjump", "+gostand" );
|
|
NotifyOnCommand( "playerjump", "+moveup" );
|
|
|
|
while( 1 )
|
|
{
|
|
level.player waittill( "playerjump" );
|
|
wait( 0.1 ); // jumps don't happen immediately
|
|
|
|
if( !level.player IsOnGround() )
|
|
{
|
|
flag_set( jumpflag );
|
|
println( "jumping" );
|
|
}
|
|
|
|
while( !level.player IsOnGround() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
flag_clear( jumpflag );
|
|
println( "not jumping" );
|
|
}
|
|
}
|
|
|
|
player_jump_watcher_ender()
|
|
{
|
|
level waittill_any( "steamroom_price_knifekill_abort", "steamroom_price_knifekill_started" );
|
|
level notify( "player_jump_watcher_stop" );
|
|
}
|
|
|
|
get_player_speed()
|
|
{
|
|
vel = level.player GetVelocity();
|
|
// figure out the length of the vector to get the speed (distance from world center = length)
|
|
speed = Distance( ( vel[ 0 ], vel[ 1 ], 0 ), ( 0, 0, 0 ) ); // don't care about Z velocity
|
|
|
|
return speed;
|
|
}
|
|
|
|
steamroom_price_knifekill_point_of_no_return( priceAnime, guard )
|
|
{
|
|
animTime = GetAnimLength( getanim_generic( priceAnime ) );
|
|
committedWait = animTime * 0.31;
|
|
|
|
wait( committedWait );
|
|
|
|
flag_set( "steamroom_price_knifekill_committed" );
|
|
|
|
if( IsAlive( guard ) )
|
|
{
|
|
guard.allowDeath = true;
|
|
guard.a.nodeath = true;
|
|
guard set_battlechatter( false );
|
|
guard kill();
|
|
}
|
|
}
|
|
|
|
steamroom_price_knifekill_handleknife( priceAnime )
|
|
{
|
|
knifemodel = "weapon_parabolic_knife";
|
|
linktag = "tag_inhand";
|
|
|
|
animTime = GetAnimLength( getanim_generic( priceAnime ) );
|
|
stabWait = animTime * 0.48;
|
|
detachWait = animTime * 0.78;
|
|
|
|
startTime = GetTime();
|
|
|
|
self thread steamroom_price_knifekill_bloodfx( stabWait );
|
|
|
|
self waittillmatch( "custom_animmode", "knife pullout" );
|
|
self Attach( knifemodel, linktag );
|
|
|
|
waitTime = detachWait - seconds( GetTime() - startTime );
|
|
flag_wait_or_timeout( "steamroom_price_knifekill_walkup_abort", waitTime );
|
|
|
|
self Detach( knifemodel, linktag );
|
|
}
|
|
|
|
steamroom_price_knifekill_bloodfx( stabWaitTime )
|
|
{
|
|
level endon( "steamroom_price_knifekill_walkup_abort" );
|
|
|
|
bloodfx = getfx( "knife_stab" );
|
|
fxTag = "tag_knife_fx";
|
|
|
|
wait( stabWaitTime );
|
|
PlayFX( bloodfx, level.price GetTagOrigin( fxTag ) );
|
|
}
|
|
// --- END KNIFE KILL SEQUENCE --
|
|
|
|
steamroom_dialogue()
|
|
{
|
|
// "Disciple Six, we've lost all contact with Disciple Five. Check it out over."
|
|
radio_dialogue( "afcaves_schq_lostcontact" );
|
|
|
|
if( !flag( "steamroom_entrance" ) )
|
|
{
|
|
// "Roger that Oxide, we're on the catwalk, heading to the steam room. Standby."
|
|
radio_dialogue( "afcaves_sc3_oncatwalk" );
|
|
}
|
|
|
|
flag_wait( "steamroom_entrance" );
|
|
|
|
// "Oxide, Disciple Six at the steam room. No sign of Five, over."
|
|
//radio_dialogue( "afcaves_sc3_atsteamroom" );
|
|
|
|
// "Sounds like we're gonna meet 'em head on, Soap."
|
|
//radio_dialogue( "afcaves_pri_meetemheadon" );
|
|
|
|
if( !flag( "steamroom_price_moveup_1" ) )
|
|
{
|
|
// "Disciple Six, go dark, breach and clear."
|
|
radio_dialogue( "afcaves_schq_godark" );
|
|
|
|
// "Here we go - get ready."
|
|
thread radio_dialogue( "afcaves_pri_getready" );
|
|
}
|
|
|
|
flag_set( "steamroom_going_dark" );
|
|
|
|
if( !flag( "steamroom_price_moveup_2" ) )
|
|
{
|
|
// "Door charge planted. Ready to breach."
|
|
radio_dialogue( "afcaves_sc3_chargeplanted" );
|
|
}
|
|
}
|
|
|
|
steamroom_blow_door()
|
|
{
|
|
flag_set( "steamroom_door_preblow" );
|
|
|
|
// "Hit it."
|
|
radio_dialogue( "afcaves_scl_hitit" );
|
|
|
|
// "Breaching, breaching!"
|
|
thread radio_dialogue( "afcaves_sc3_breaching" );
|
|
wait( 0.8 );
|
|
|
|
exploder( 200 );
|
|
|
|
delaythread( 0.5, ::steamroom_gate_swap );
|
|
|
|
org = GetEnt( "smodel_steamroom_c4_plant", "targetname" );
|
|
|
|
thread play_sound_in_space( "af_caves_selfdestruct", org.origin );
|
|
Earthquake( .2, 1.75, level.player.origin, 350 );
|
|
level.player PlayRumbleOnEntity( "damage_heavy" );
|
|
SetBlur( 3, .1 );
|
|
|
|
spots = [];
|
|
spots[ 0 ] = org;
|
|
spots = array_combine( spots, GetEntArray( "steamroom_fake_c4_spot", "targetname" ) );
|
|
foreach( spot in spots )
|
|
{
|
|
PlayFX( level._effect[ "c4_explosion" ], spot.origin );
|
|
spot RadiusDamage( spot.origin, 256, 200, 50 );
|
|
}
|
|
|
|
flag_set( "steamroom_door_blown" );
|
|
|
|
wait( 1 );
|
|
SetBlur( 0, 3 );
|
|
}
|
|
|
|
steamroom_ambush_finish_dialogue()
|
|
{
|
|
if( !flag( "steamroom_exit" ) )
|
|
{
|
|
// "Move."
|
|
radio_dialogue( "afcaves_pri_move2" );
|
|
}
|
|
|
|
if( !flag( "steamroom_exit" ) )
|
|
{
|
|
// "Disciple Nine, your rear guard just flatlined!"
|
|
radio_dialogue( "afcaves_schq_flatlined" );
|
|
}
|
|
|
|
if( !flag( "steamroom_exit" ) )
|
|
{
|
|
// "Not possible. We just cleared that area. (snort) Nobody's that good Oxi-"
|
|
thread radio_dialogue( "afcaves_sc3_notpossible" );
|
|
|
|
wait( 2.75 ); // the next line needs to cut this one off a bit to sound right
|
|
|
|
// "It's Price."
|
|
radio_dialogue_overlap( "afcaves_shp_itsprice" );
|
|
}
|
|
|
|
// don't play if we're close to where we have to give the next objective
|
|
if( flag( "player_awayfrom_steamroom_exit" ) )
|
|
{
|
|
// "Backup priority items and burn the rest. Fire teams - just delay 'em until we're ready to pull out."
|
|
radio_dialogue( "afcaves_shp_burntherest" );
|
|
}
|
|
|
|
flag_set( "steamroom_ambush_finish_dialogue_ended" );
|
|
}
|
|
|
|
steamroom_price_start_ambush()
|
|
{
|
|
level endon( "steamroom_ambush_started" );
|
|
|
|
wait( 8 );
|
|
|
|
/*
|
|
vol = GetEnt( "goalvolume_steamroom_patrollers", "targetname" );
|
|
numGuysNeeded = 7;
|
|
|
|
guys = get_ai_group_ai( "steamroom_patrollers" );
|
|
while( guys.size && !all_dead( guys ) )
|
|
{
|
|
numFound = 0;
|
|
foreach( guy in guys )
|
|
{
|
|
if( vol IsTouching( guy ) )
|
|
{
|
|
numFound++;
|
|
}
|
|
}
|
|
|
|
if( numFound >= numGuysNeeded )
|
|
{
|
|
break;
|
|
}
|
|
|
|
wait( 0.1 );
|
|
|
|
guys = get_ai_group_ai( "steamroom_patrollers" );
|
|
}
|
|
*/
|
|
|
|
// "Go loud! Open fire!"
|
|
thread radio_dialogue( "afcaves_pri_goloud" );
|
|
|
|
flag_set( "steamroom_ambush_started" );
|
|
}
|
|
|
|
steamroom_patrollers()
|
|
{
|
|
flag_wait( "steamroom_door_preblow" );
|
|
|
|
spawnersExtra = GetEntArray( "steamroom_patroller_extraguy", "targetname" );
|
|
guysExtra = spawn_ai_group( spawnersExtra, true );
|
|
array_thread( guysExtra, ::steamroom_patroller_think );
|
|
|
|
flag_wait( "steamroom_door_blown" );
|
|
|
|
spawners = [];
|
|
guys = [];
|
|
spawners = GetEntArray( "steamroom_patroller", "targetname" );
|
|
guys = spawn_ai_group( spawners, true );
|
|
array_thread( guys, ::steamroom_patroller_think );
|
|
|
|
if( !flag( "steamroom_ambush_started" ) )
|
|
{
|
|
thread steamroom_patrollers_pre_ambush_dialogue();
|
|
}
|
|
|
|
spawners2 = GetEntArray( "steamroom_patroller_group2", "targetname" );
|
|
ASSERT( spawners2.size );
|
|
guys2 = spawn_ai_group( spawners2, true );
|
|
array_thread( guys2, ::steamroom_patroller_group2_wait );
|
|
|
|
spawners3 = GetEntArray( "steamroom_patroller_doorguard", "targetname" );
|
|
ASSERT( spawners3.size );
|
|
guys3 = spawn_ai_group( spawners3, true );
|
|
array_call( guys3, ::LaserForceOn );
|
|
array_thread( guys3, ::steamroom_patroller_baseaccuracy );
|
|
|
|
flag_wait_any( "steamroom_ambush_started", "steamroom_patrollers_deathflag" );
|
|
|
|
// spot the player if one of the patrollers dies
|
|
if( !flag( "steamroom_ambush_started" ) )
|
|
{
|
|
flag_set( "steamroom_player_spotted" );
|
|
}
|
|
|
|
thread steamroom_patrollers_post_ambush_dialogue();
|
|
}
|
|
|
|
steamroom_patroller_group2_wait()
|
|
{
|
|
self endon( "death" );
|
|
|
|
og_goalradius = self.goalradius;
|
|
self SetGoalPos( self.origin );
|
|
flag_wait_any( "steamroom_ambush_started", "steamroom_patrollers_deathflag" );
|
|
|
|
self.goalradius = og_goalradius;
|
|
vol = GetEnt( "goalvolume_steamroom_patrollers", "targetname" );
|
|
self SetGoalVolumeAuto( vol );
|
|
|
|
self thread steamroom_patroller_think();
|
|
}
|
|
|
|
steamroom_patrollers_pre_ambush_dialogue()
|
|
{
|
|
level endon( "steamroom_ambush_started" );
|
|
|
|
// "Move in."
|
|
radio_dialogue( "scl_movein" );
|
|
|
|
// "Foxtrot element, sweep left."
|
|
radio_dialogue( "afcaves_scl_foxtrotelement" );
|
|
|
|
// "Search pattern Echo Charlie. Go."
|
|
radio_dialogue( "afcaves_scl_patternecho" );
|
|
|
|
// "Door area clear."
|
|
radio_dialogue( "afcaves_sc3_areaclear" );
|
|
|
|
// "Check your corners."
|
|
radio_dialogue( "afcaves_scl_checkcorners" );
|
|
}
|
|
|
|
steamroom_patrollers_post_ambush_dialogue()
|
|
{
|
|
level endon( "steamroom_patrollers_group2_deathflag" );
|
|
|
|
// "They're here! Open fire!"
|
|
radio_dialogue( "afcaves_scl_theyrehere" );
|
|
|
|
wait( 5 );
|
|
|
|
// "Stay frosty, hunt them down!"
|
|
radio_dialogue( "afcaves_scl_huntthemdown" );
|
|
}
|
|
|
|
steamroom_patroller_think()
|
|
{
|
|
if( !flag( "steamroom_ambush_started" ) )
|
|
{
|
|
self thread steamroom_patroller_deathwait();
|
|
}
|
|
|
|
self thread steamroom_patroller_notify_on_player_spotted();
|
|
|
|
self endon( "death" );
|
|
|
|
self LaserForceOn();
|
|
|
|
self steamroom_patroller_baseaccuracy();
|
|
|
|
if( !flag( "steamroom_ambush_started" ) )
|
|
{
|
|
og_sightdist = self.maxsightdistsqrd;
|
|
self.maxsightdistsqrd = 500 * 500;
|
|
og_goalradius = self.goalradius;
|
|
self.goalradius = 64;
|
|
|
|
flag_wait( "steamroom_door_blown" );
|
|
|
|
self thread maps\_patrol::patrol( self.target );
|
|
wait( 0.1 );
|
|
self thread patroller_do_cqbwalk();
|
|
//self.script_idlereach = true;
|
|
//self thread maps\_idle::idle();
|
|
|
|
flag_wait( "steamroom_ambush_started" );
|
|
|
|
wait( 0.05 );
|
|
self notify( "end_patrol" );
|
|
self clear_generic_idle_anim();
|
|
self.goalradius = og_goalradius;
|
|
self.maxsightdistsqrd = og_sightdist;
|
|
}
|
|
|
|
//self be_aggressive();
|
|
|
|
flag_wait( "steamroom_patrollers_protect_door" );
|
|
self delaythread( 0.1, ::playerseek );
|
|
}
|
|
|
|
steamroom_patroller_baseaccuracy()
|
|
{
|
|
switch( level.gameskill )
|
|
{
|
|
case 0:
|
|
self.baseaccuracy = 0.9; // hard to see in here, frustrating for a noob
|
|
break;
|
|
case 1:
|
|
self.baseaccuracy = 1.1;
|
|
break;
|
|
case 2:
|
|
self.baseaccuracy = 1.25;
|
|
break;
|
|
case 3:
|
|
self.baseaccuracy = 1.5;
|
|
break;
|
|
}
|
|
}
|
|
|
|
steamroom_patroller_notify_on_player_spotted()
|
|
{
|
|
flagstr = "steamroom_player_spotted";
|
|
level endon( flagstr );
|
|
|
|
self endon( "death" );
|
|
|
|
self waittill( "enemy" );
|
|
|
|
if( !flag( flagstr ) )
|
|
{
|
|
flag_set( flagstr );
|
|
}
|
|
}
|
|
|
|
steamroom_patroller_deathwait()
|
|
{
|
|
level endon( "steamroom_ambush_started" );
|
|
self waittill( "death" );
|
|
|
|
flag_set( "steamroom_ambush_started" );
|
|
}
|
|
|
|
steamroom_lighting_setup()
|
|
{
|
|
//group 1
|
|
lights_out_grp1 = getentarray( "lights_off_grp1", "targetname" );
|
|
array_thread( lights_out_grp1, ::_setLightIntensity, 1.5 );
|
|
|
|
light_models_off_grp1 = getentarray( "security_lights_off_grp1", "targetname" );
|
|
array_call( light_models_off_grp1, ::hide );
|
|
|
|
light_models_on_grp1 = getentarray( "security_lights_on_grp1", "targetname" );
|
|
array_thread( light_models_on_grp1, ::steamroom_light_glow_fx );
|
|
|
|
//group 2
|
|
lights_out_grp2 = getentarray( "lights_off_grp2", "targetname" );
|
|
array_thread( lights_out_grp2, ::_setLightIntensity, 1.7);
|
|
|
|
light_models_off_grp2 = getentarray( "security_lights_off_grp2", "targetname" );
|
|
array_call( light_models_off_grp2, ::hide );
|
|
|
|
light_models_on_grp2 = getentarray( "security_lights_on_grp2", "targetname" );
|
|
array_thread( light_models_on_grp2, ::steamroom_light_glow_fx );
|
|
|
|
//group 3
|
|
lights_out_grp3 = getentarray( "lights_off_grp3", "targetname" );
|
|
array_thread( lights_out_grp3, ::_setLightIntensity, 1.7);
|
|
|
|
light_models_off_grp3 = getentarray( "security_lights_off_grp3", "targetname" );
|
|
array_call( light_models_off_grp3, ::hide );
|
|
|
|
light_models_on_grp3 = getentarray( "security_lights_on_grp3", "targetname" );
|
|
array_thread( light_models_on_grp3, ::steamroom_light_glow_fx );
|
|
|
|
//group 4
|
|
lights_out_grp4 = getentarray( "lights_off_grp4", "targetname" );
|
|
array_thread( lights_out_grp4, ::_setLightIntensity, 1.5);
|
|
|
|
light_models_off_grp4 = getentarray( "security_lights_off_grp4", "targetname" );
|
|
array_call( light_models_off_grp4, ::hide );
|
|
|
|
light_models_on_grp4 = getentarray( "security_lights_on_grp4", "targetname" );
|
|
array_thread( light_models_on_grp4, ::steamroom_light_glow_fx );
|
|
|
|
}
|
|
|
|
steamroom_light_glow_fx()
|
|
{
|
|
if ( self.model == "dt_light_on" || self.model == "com_utility_light_on" )
|
|
{
|
|
PlayFXOnTag( getfx( "light_glow_white_bulb" ), self, "tag_fx");
|
|
}
|
|
}
|
|
|
|
steamroom_door_setup()
|
|
{
|
|
door = GetEnt( "cavedoor", "targetname" );
|
|
door.lightOffModel = GetEnt( "sbmodel_steamroom_light_off", "targetname" );
|
|
door.lightOnModel = GetEnt( "sbmodel_steamroom_light_on", "targetname" );
|
|
door.lightOffModel Hide();
|
|
level.steamroom_door = door;
|
|
|
|
doorlight = GetEnt( "cave_door_light", "targetname" );
|
|
doorlight SetLightIntensity( 1.5 );
|
|
level.steamroom_doorlight = doorlight;
|
|
}
|
|
|
|
steamroom_door_lightswap()
|
|
{
|
|
level.steamroom_doorlight SetLightIntensity( 0 );
|
|
|
|
if( IsDefined( level.steamroom_door ) )
|
|
{
|
|
level.steamroom_door.lightOnModel Hide();
|
|
level.steamroom_door.lightOffModel Show();
|
|
}
|
|
|
|
wait( 0.25 );
|
|
level.player playsound( "scn_blackout_breaker_box" );
|
|
|
|
glowspots = GetStructArray( "cave_red_light_glowspot", "targetname" );
|
|
foreach( spot in glowspots )
|
|
{
|
|
PlayFX( getfx( "redlight_glow" ), spot.origin );
|
|
}
|
|
|
|
dlightspots = GetStructArray( "cave_red_light_dlight_spot", "targetname" );
|
|
foreach( dlight in dlightspots )
|
|
{
|
|
dlight.looper = PlayLoopedFX( getfx( "dlight_red" ), 50, dlight.origin, 2500 );
|
|
}
|
|
}
|
|
|
|
steamroom_lights_go_out()
|
|
{
|
|
thread steamroom_steam_fx_swap();
|
|
|
|
level.player playsound( "scn_blackout_breaker_box" );
|
|
|
|
thread vision_set_fog_changes( "af_caves_outdoors", 2.25 );
|
|
|
|
//group 1
|
|
lights_out_grp1 = getentarray( "lights_off_grp1", "targetname" );
|
|
array_thread( lights_out_grp1, ::_setLightIntensity, 0 );
|
|
|
|
light_models_on_grp1 = getentarray( "security_lights_on_grp1", "targetname" );
|
|
array_call( light_models_on_grp1, ::delete );
|
|
|
|
light_models_off_grp1 = getentarray( "security_lights_off_grp1", "targetname" );
|
|
array_call( light_models_off_grp1, ::show );
|
|
|
|
wait .75;
|
|
|
|
level.player playsound( "scn_blackout_breaker_box" );
|
|
|
|
//group 2
|
|
lights_out_grp2 = getentarray( "lights_off_grp2", "targetname" );
|
|
array_thread( lights_out_grp2, ::_setLightIntensity, 0 );
|
|
|
|
light_models_on_grp2 = getentarray( "security_lights_on_grp2", "targetname" );
|
|
array_call( light_models_on_grp2, ::delete );
|
|
|
|
light_models_off_grp2 = getentarray( "security_lights_off_grp2", "targetname" );
|
|
array_call( light_models_off_grp2, ::show );
|
|
|
|
wait .75;
|
|
level.player playsound( "scn_blackout_breaker_box" );
|
|
|
|
//group 3
|
|
lights_out_grp3 = getentarray( "lights_off_grp3", "targetname" );
|
|
array_thread( lights_out_grp3, ::_setLightIntensity, 0 );
|
|
|
|
light_models_on_grp3 = getentarray( "security_lights_on_grp3", "targetname" );
|
|
array_call( light_models_on_grp3, ::delete );
|
|
|
|
light_models_off_grp3 = getentarray( "security_lights_off_grp3", "targetname" );
|
|
array_call( light_models_off_grp3, ::show );
|
|
|
|
wait .75;
|
|
level.player playsound( "scn_blackout_breaker_box" );
|
|
|
|
//group 4
|
|
lights_out_grp4 = getentarray( "lights_off_grp4", "targetname" );
|
|
array_thread( lights_out_grp4, ::_setLightIntensity, 0 );
|
|
|
|
light_models_on_grp4 = getentarray( "security_lights_on_grp4", "targetname" );
|
|
array_call( light_models_on_grp4, ::delete );
|
|
|
|
light_models_off_grp4 = getentarray( "security_lights_off_grp4", "targetname" );
|
|
array_call( light_models_off_grp4, ::show );
|
|
|
|
thread steamroom_door_lightswap();
|
|
|
|
flag_set( "steamroom_lights_out" );
|
|
}
|
|
|
|
steamroom_steam_fx_swap()
|
|
{
|
|
wait( 2 );
|
|
pauseExploder( "steamroom_steamclouds" );
|
|
exploder( "steamroom_steamclouds_dark" );
|
|
|
|
level.og_pipe_fx = level._pipes._effect[ "steam" ];
|
|
level._pipes._effect[ "steam" ] = getfx( "pipe_steam_dark" );
|
|
}
|