burc_2004

zm_alcatraz_sq.gsc

Oct 21st, 2015
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 68.39 KB | None | 0 0
  1. #include maps/mp/zombies/_zm_clone;
  2. #include maps/mp/zombies/_zm_laststand;
  3. #include maps/mp/zombies/_zm_ai_basic;
  4. #include maps/mp/animscripts/shared;
  5. #include maps/mp/zombies/_zm_ai_brutus;
  6. #include maps/mp/zombies/_zm_audio;
  7. #include maps/mp/zm_alcatraz_sq_nixie;
  8. #include maps/mp/zombies/_zm_unitrigger;
  9. #include maps/mp/zombies/_zm_equipment;
  10. #include maps/mp/zm_alcatraz_sq_vo;
  11. #include maps/mp/zm_prison_sq_final;
  12. #include maps/mp/gametypes_zm/_hud;
  13. #include maps/mp/gametypes_zm/_hud_util;
  14. #include maps/mp/zm_alcatraz_utility;
  15. #include maps/mp/zombies/_zm_sidequests;
  16. #include maps/mp/zombies/_zm_craftables;
  17. #include maps/mp/zombies/_zm_utility;
  18. #include maps/mp/zombies/_zm_afterlife;
  19. #include maps/_vehicle;
  20. #include maps/_utility;
  21. #include maps/mp/_utility;
  22. #include common_scripts/utility;
  23.  
  24. init()
  25. {
  26.     precachemodel( "accessories_gas_canister_1" );
  27.     precachemodel( "p6_zm_al_power_station_panels_03" );
  28.     precacheitem( "falling_hands_zm" );
  29.     precacheitem( "electrocuted_hands_zm" );
  30.     precachestring( &"ZM_PRISON_ELECTRIC_CHAIR_ACTIVATE" );
  31.     precachestring( &"ZM_PRISON_LAUNDRY_MACHINE_ACTIVATE" );
  32.     precachestring( &"ZM_PRISON_PLANE_BEGIN_TAKEOFF" );
  33.     precachestring( &"ZM_PRISON_PLANE_BOARD" );
  34.     precachestring( &"ZM_PRISON_KEY_DOOR_LOCKED" );
  35.     precacherumble( "damage_heavy" );
  36.     precacherumble( "explosion_generic" );
  37.     registerclientfield( "world", "fake_master_key", 9000, 2, "int" );
  38.     flag_init( "map_revealed" );
  39.     flag_init( "key_found" );
  40.     flag_init( "cloth_found" );
  41.     flag_init( "fueltanks_found" );
  42.     flag_init( "engine_found" );
  43.     flag_init( "steering_found" );
  44.     flag_init( "rigging_found" );
  45.     flag_init( "plane_ready" );
  46.     flag_init( "plane_built" );
  47.     flag_init( "plane_boarded" );
  48.     flag_init( "plane_departed" );
  49.     flag_init( "plane_approach_bridge" );
  50.     flag_init( "plane_zapped" );
  51.     flag_init( "plane_crashed" );
  52.     flag_init( "portal_open" );
  53.     flag_init( "spawn_fuel_tanks" );
  54.     flag_init( "plane_is_away" );
  55.     flag_init( "plane_trip_to_nml_successful" );
  56.     flag_init( "story_vo_playing" );
  57.     flag_init( "docks_inner_gate_unlocked" );
  58.     flag_init( "docks_inner_gate_open" );
  59.     flag_init( "docks_outer_gate_open" );
  60.     flag_init( "docks_gates_remain_open" );
  61.     flag_init( "nixie_puzzle_solved" );
  62.     flag_init( "nixie_countdown_started" );
  63.     flag_init( "nixie_countdown_expired" );
  64.     flag_init( "nixie_puzzle_completed" );
  65.     flag_init( "generator_challenge_completed" );
  66.     flag_init( "dryer_cycle_active" );
  67.     flag_init( "quest_completed_thrice" );
  68.     flag_init( "final_quest_ready" );
  69.     flag_init( "final_quest_audio_tour_started" );
  70.     flag_init( "final_quest_audio_tour_finished" );
  71.     flag_init( "final_quest_plane_built" );
  72.     flag_init( "final_quest_plane_boarded" );
  73.     flag_init( "final_quest_plane_departed" );
  74.     flag_init( "final_quest_plane_zapped" );
  75.     flag_init( "final_quest_plane_crashed" );
  76.     flag_init( "final_quest_final_battle_started" );
  77.     flag_init( "final_quest_good_wins" );
  78.     flag_init( "final_quest_evil_wins" );
  79.     flag_init( "nixie_ee_flashing" );
  80. }
  81.  
  82. start_alcatraz_sidequest()
  83. {
  84.     init();
  85.     onplayerconnect_callback( ::player_disconnect_watcher );
  86.     onplayerconnect_callback( ::player_death_watcher );
  87.     flag_wait( "start_zombie_round_logic" );
  88. /#
  89.     setup_devgui();
  90. #/
  91.     level.n_quest_iteration_count = 1;
  92.     level.n_plane_fuel_count = 5;
  93.     level.n_plane_pieces_found = 0;
  94.     level.final_flight_players = [];
  95.     level.final_flight_activated = 0;
  96.     level.characters_in_nml = [];
  97.     level.someone_has_visited_nml = 0;
  98.     level.custom_game_over_hud_elem = ::maps/mp/zm_prison_sq_final::custom_game_over_hud_elem;
  99.     prevent_theater_mode_spoilers();
  100.     setup_key_doors();
  101.     setup_puzzle_piece_glint();
  102.     setup_puzzles();
  103.     setup_quest_triggers();
  104.     if ( isDefined( level.gamedifficulty ) && level.gamedifficulty != 0 )
  105.     {
  106.         maps/mp/zm_prison_sq_final::final_flight_setup();
  107.     }
  108.     level thread warden_fence_hotjoin_handler();
  109.     if ( isDefined( level.host_migration_listener_custom_func ) )
  110.     {
  111.         level thread [[ level.host_migration_listener_custom_func ]]();
  112.     }
  113.     else
  114.     {
  115.         level thread host_migration_listener();
  116.     }
  117.     if ( isDefined( level.manage_electric_chairs_custom_func ) )
  118.     {
  119.         level thread [[ level.manage_electric_chairs_custom_func ]]();
  120.     }
  121.     else
  122.     {
  123.         level thread manage_electric_chairs();
  124.     }
  125.     if ( isDefined( level.plane_flight_thread_custom_func ) )
  126.     {
  127.         level thread [[ level.plane_flight_thread_custom_func ]]();
  128.     }
  129.     else
  130.     {
  131.         level thread plane_flight_thread();
  132.     }
  133.     if ( isDefined( level.track_quest_status_thread_custom_func ) )
  134.     {
  135.         level thread [[ level.track_quest_status_thread_custom_func ]]();
  136.     }
  137.     else
  138.     {
  139.         level thread track_quest_status_thread();
  140.     }
  141.     maps/mp/zm_alcatraz_sq_vo::opening_vo();
  142. }
  143.  
  144. host_migration_listener()
  145. {
  146.     level endon( "end_game" );
  147.     level notify( "afterlife_hostmigration" );
  148.     level endon( "afterlife_hostmigration" );
  149.     while ( 1 )
  150.     {
  151.         level waittill( "host_migration_end" );
  152.         m_plane_craftable = getent( "plane_craftable", "targetname" );
  153.         m_plane_about_to_crash = getent( "plane_about_to_crash", "targetname" );
  154.         veh_plane_flyable = getent( "plane_flyable", "targetname" );
  155.         a_players = getplayers();
  156.         if ( flag( "plane_boarded" ) && !flag( "plane_departed" ) )
  157.         {
  158.             _a215 = a_players;
  159.             _k215 = getFirstArrayKey( _a215 );
  160.             while ( isDefined( _k215 ) )
  161.             {
  162.                 player = _a215[ _k215 ];
  163.                 if ( isDefined( player ) && isDefined( player.character_name ) && isinarray( level.characters_in_nml, player.character_name ) )
  164.                 {
  165.                     player playerlinktodelta( m_plane_craftable, "tag_player_crouched_" + ( player.n_passenger_index + 1 ) );
  166.                 }
  167.                 _k215 = getNextArrayKey( _a215, _k215 );
  168.             }
  169.         }
  170.         else if ( flag( "plane_departed" ) && !flag( "plane_approach_bridge" ) )
  171.         {
  172.             _a225 = a_players;
  173.             _k225 = getFirstArrayKey( _a225 );
  174.             while ( isDefined( _k225 ) )
  175.             {
  176.                 player = _a225[ _k225 ];
  177.                 if ( isDefined( player ) && isDefined( player.character_name ) && isinarray( level.characters_in_nml, player.character_name ) )
  178.                 {
  179.                     player playerlinktodelta( veh_plane_flyable, "tag_player_crouched_" + ( player.n_passenger_index + 1 ) );
  180.                 }
  181.                 _k225 = getNextArrayKey( _a225, _k225 );
  182.             }
  183.         }
  184.         else if ( flag( "plane_approach_bridge" ) && !flag( "plane_zapped" ) )
  185.         {
  186.             _a235 = a_players;
  187.             _k235 = getFirstArrayKey( _a235 );
  188.             while ( isDefined( _k235 ) )
  189.             {
  190.                 player = _a235[ _k235 ];
  191.                 if ( isDefined( player ) && isDefined( player.character_name ) && isinarray( level.characters_in_nml, player.character_name ) )
  192.                 {
  193.                     player playerlinktoabsolute( veh_plane_flyable, "tag_player_crouched_" + ( player.n_passenger_index + 1 ) );
  194.                 }
  195.                 _k235 = getNextArrayKey( _a235, _k235 );
  196.             }
  197.         }
  198.         else while ( flag( "plane_zapped" ) && !flag( "plane_crashed" ) )
  199.         {
  200.             _a245 = a_players;
  201.             _k245 = getFirstArrayKey( _a245 );
  202.             while ( isDefined( _k245 ) )
  203.             {
  204.                 player = _a245[ _k245 ];
  205.                 if ( isDefined( player ) && isDefined( player.character_name ) && isinarray( level.characters_in_nml, player.character_name ) )
  206.                 {
  207.                     player playerlinktodelta( m_plane_about_to_crash, "tag_player_crouched_" + ( player.n_passenger_index + 1 ), 1, 0, 0, 0, 0, 1 );
  208.                 }
  209.                 _k245 = getNextArrayKey( _a245, _k245 );
  210.             }
  211.         }
  212.         setup_puzzle_piece_glint();
  213.         setclientfield( "fake_master_key", level.is_master_key_west + 1 );
  214.         if ( !flag( "key_found" ) )
  215.         {
  216.             if ( level.is_master_key_west )
  217.             {
  218.                 exploder( 101 );
  219.                 break;
  220.             }
  221.             else
  222.             {
  223.                 exploder( 100 );
  224.             }
  225.         }
  226.     }
  227. }
  228.  
  229. prevent_theater_mode_spoilers()
  230. {
  231.     flag_wait( "initial_blackscreen_passed" );
  232.     m_plane_flyable = getent( "plane_flyable", "targetname" );
  233.     m_plane_flyable setinvisibletoall();
  234.     m_plane_hideable_engine = getent( "plane_hideable_engine", "targetname" );
  235.     m_plane_hideable_engine ghost();
  236.     m_plane_hideable_clothes_pile = getent( "plane_hideable_clothes_pile", "targetname" );
  237.     m_plane_hideable_clothes_pile ghost();
  238.     a_str_partnames = [];
  239.     a_str_partnames[ 0 ] = "cloth";
  240.     a_str_partnames[ 1 ] = "steering";
  241.     i = 0;
  242.     while ( i < a_str_partnames.size )
  243.     {
  244.         m_plane_piece = get_craftable_piece_model( "plane", a_str_partnames[ i ] );
  245.         if ( isDefined( m_plane_piece ) )
  246.         {
  247.             m_plane_piece setinvisibletoall();
  248.         }
  249.         i++;
  250.     }
  251.     m_master_key = get_craftable_piece_model( "quest_key1", "p6_zm_al_key" );
  252.     if ( isDefined( m_master_key ) )
  253.     {
  254.         m_master_key setinvisibletoall();
  255.     }
  256. }
  257.  
  258. setup_puzzle_piece_glint()
  259. {
  260.     wait 1;
  261.     a_str_partnames = [];
  262.     a_str_partnames[ 0 ] = "cloth";
  263.     a_str_partnames[ 1 ] = "fueltanks";
  264.     a_str_partnames[ 2 ] = "engine";
  265.     a_str_partnames[ 3 ] = "steering";
  266.     a_str_partnames[ 4 ] = "rigging";
  267.     i = 0;
  268.     while ( i < a_str_partnames.size )
  269.     {
  270.         m_plane_piece = get_craftable_piece_model( "plane", a_str_partnames[ i ] );
  271.         if ( isDefined( m_plane_piece ) )
  272.         {
  273.             playfxontag( level._effect[ "quest_item_glow" ], m_plane_piece, "tag_origin" );
  274.         }
  275.         m_fuel_can = get_craftable_piece_model( "refuelable_plane", "fuel" + ( i + 1 ) );
  276.         if ( isDefined( m_fuel_can ) )
  277.         {
  278.             playfxontag( level._effect[ "quest_item_glow" ], m_fuel_can, "tag_origin" );
  279.         }
  280.         i++;
  281.     }
  282.     m_master_key = get_craftable_piece_model( "quest_key1", "p6_zm_al_key" );
  283.     if ( isDefined( m_master_key ) )
  284.     {
  285.         playfxontag( level._effect[ "key_glint" ], m_master_key, "tag_origin" );
  286.     }
  287.     m_fake_plane_steering = getent( "fake_veh_t6_dlc_zombie_part_control", "targetname" );
  288.     if ( isDefined( m_fake_plane_steering ) )
  289.     {
  290.         playfxontag( level._effect[ "quest_item_glow" ], m_fake_plane_steering, "tag_origin" );
  291.     }
  292. }
  293.  
  294. setup_devgui()
  295. {
  296.     setdvar( "add_afterlife", "off" );
  297.     setdvar( "build_plane", "off" );
  298.     setdvar( "get_master_key", "off" );
  299.     setdvar( "alcatraz_final_battle", "off" );
  300.     setdvar( "alcatraz_give_shield", "off" );
  301. /#
  302.     adddebugcommand( "devgui_cmd "Zombies/Alcatraz:1/Add Afterlife" "add_afterlife on"\n" );
  303.     adddebugcommand( "devgui_cmd "Zombies/Alcatraz:1/Get Master Key" "get_master_key on"\n" );
  304.     adddebugcommand( "devgui_cmd "Zombies/Alcatraz:1/Alcatraz Final Battle" "alcatraz_final_battle on"\n" );
  305.     adddebugcommand( "devgui_cmd "Zombies/Alcatraz:1/Build Plane:1" "build_plane on"\n" );
  306.     adddebugcommand( "devgui_cmd "Zombies/Alcatraz:1/Give Shield:1" "alcatraz_give_shield on"\n" );
  307. #/
  308.     level thread watch_devgui_alcatraz_final_battle();
  309.     level thread watch_devgui_afterlife();
  310.     level thread watch_devgui_plane();
  311.     level thread watch_devgui_get_key();
  312.     level thread watch_devgui_give_shield();
  313. }
  314.  
  315. watch_devgui_alcatraz_final_battle()
  316. {
  317.     while ( 1 )
  318.     {
  319.         if ( getDvar( "alcatraz_final_battle" ) == "on" )
  320.         {
  321.             players = getplayers();
  322.             _a379 = players;
  323.             _k379 = getFirstArrayKey( _a379 );
  324.             while ( isDefined( _k379 ) )
  325.             {
  326.                 player = _a379[ _k379 ];
  327. /#
  328.                 iprintlnbold( "LINK PLAYER TO PLANE, START COUNTDOWN IF NOT YET STARTED" );
  329. #/
  330.                 level.final_flight_activated = 1;
  331.                 player thread final_flight_player_thread();
  332.                 _k379 = getNextArrayKey( _a379, _k379 );
  333.             }
  334.             setdvar( "alcatraz_final_battle", "off" );
  335.         }
  336.         wait 0,1;
  337.     }
  338. }
  339.  
  340. watch_devgui_get_key()
  341. {
  342.     while ( 1 )
  343.     {
  344.         if ( getDvar( "get_master_key" ) == "on" )
  345.         {
  346.             a_players = [];
  347.             a_players = getplayers();
  348.             m_master_key = get_craftable_piece_model( "quest_key1", "p6_zm_al_key" );
  349.             if ( isDefined( m_master_key ) )
  350.             {
  351.                 m_master_key.origin = a_players[ 0 ].origin + vectorScale( ( 0, 0, 0 ), 60 );
  352.                 m_master_key setvisibletoall();
  353.             }
  354.             setdvar( "get_master_key", "off" );
  355.         }
  356.         wait 0,1;
  357.     }
  358. }
  359.  
  360. watch_devgui_afterlife()
  361. {
  362.     while ( 1 )
  363.     {
  364.         if ( getDvar( "add_afterlife" ) == "on" )
  365.         {
  366.             a_players = [];
  367.             a_players = getplayers();
  368.             i = 0;
  369.             while ( i < a_players.size )
  370.             {
  371.                 a_players[ i ] afterlife_add();
  372.                 i++;
  373.             }
  374.             setdvar( "add_afterlife", "off" );
  375.         }
  376.         wait 0,1;
  377.     }
  378. }
  379.  
  380. watch_devgui_give_shield()
  381. {
  382.     while ( 1 )
  383.     {
  384.         if ( getDvar( "alcatraz_give_shield" ) == "on" )
  385.         {
  386.             _a438 = getplayers();
  387.             _k438 = getFirstArrayKey( _a438 );
  388.             while ( isDefined( _k438 ) )
  389.             {
  390.                 player = _a438[ _k438 ];
  391.                 if ( is_equipment_included( "alcatraz_shield_zm" ) )
  392.                 {
  393.                     player maps/mp/zombies/_zm_equipment::equipment_buy( "alcatraz_shield_zm" );
  394.                 }
  395.                 _k438 = getNextArrayKey( _a438, _k438 );
  396.             }
  397.             setdvar( "alcatraz_give_shield", "off" );
  398.         }
  399.         wait 0,05;
  400.     }
  401. }
  402.  
  403. watch_devgui_plane()
  404. {
  405.     is_shortcut_plane_built = 0;
  406.     while ( !is_shortcut_plane_built )
  407.     {
  408.         if ( getDvar( "build_plane" ) == "on" )
  409.         {
  410. /#
  411.             iprintlnbold( "plane built!" );
  412. #/
  413.             is_shortcut_plane_built = 1;
  414.         }
  415.         wait 0,1;
  416.     }
  417.     i = 0;
  418.     while ( i < level.a_uts_craftables.size )
  419.     {
  420.         if ( level.a_uts_craftables[ i ].equipname == "plane" )
  421.         {
  422.             level.a_uts_craftables[ i ].crafted = 1;
  423.         }
  424.         i++;
  425.     }
  426.     level thread maps/mp/zm_alcatraz_sq_vo::escape_flight_vo();
  427.     plane_craftable = getent( "plane_craftable", "targetname" );
  428.     plane_craftable showpart( "tag_support_upper" );
  429.     plane_craftable showpart( "tag_wing_skins_up" );
  430.     plane_craftable showpart( "tag_engines_up" );
  431.     plane_craftable showpart( "tag_feul_tanks" );
  432.     plane_craftable showpart( "tag_control_mechanism" );
  433.     plane_craftable showpart( "tag_fuel_hose" );
  434.     t_plane_fly = getent( "plane_fly_trigger", "targetname" );
  435.     t_plane_fly trigger_on();
  436.     t_plane_fly.require_look_at = 0;
  437.     while ( isDefined( t_plane_fly ) )
  438.     {
  439.         t_plane_fly waittill( "trigger", e_triggerer );
  440.         if ( isplayer( e_triggerer ) )
  441.         {
  442. /#
  443.             iprintlnbold( e_triggerer );
  444. #/
  445.             while ( isDefined( level.custom_plane_validation ) )
  446.             {
  447.                 valid = t_plane_fly [[ level.custom_plane_validation ]]( e_triggerer );
  448.                 while ( !valid )
  449.                 {
  450.                     continue;
  451.                 }
  452.             }
  453.             if ( level.n_plane_fuel_count == 5 )
  454.             {
  455.                 if ( isDefined( level.plane_boarding_thread_custom_func ) )
  456.                 {
  457.                     e_triggerer thread [[ level.plane_boarding_thread_custom_func ]]();
  458.                     break;
  459.                 }
  460.                 else
  461.                 {
  462. /#
  463.                     iprintlnbold( "LINK PLAYER TO PLANE, START COUNTDOWN IF NOT YET STARTED" );
  464. #/
  465.                     e_triggerer thread plane_boarding_thread();
  466.                 }
  467.             }
  468.         }
  469.     }
  470. }
  471.  
  472. setup_key_doors()
  473. {
  474.     width = 0;
  475.     height = 0;
  476.     length = 0;
  477.     piece_number = 1;
  478.     while ( piece_number < 6 )
  479.     {
  480.         switch( piece_number )
  481.         {
  482.             case 1:
  483.                 width = 120;
  484.                 height = 112;
  485.                 length = 120;
  486.                 break;
  487.             case 2:
  488.                 width = 120;
  489.                 height = 112;
  490.                 length = 124;
  491.                 break;
  492.             case 3:
  493.                 width = 108;
  494.                 height = 112;
  495.                 length = 90;
  496.                 break;
  497.             case 4:
  498.                 width = 98;
  499.                 height = 112;
  500.                 length = 108;
  501.                 break;
  502.             case 5:
  503.                 width = 60;
  504.                 height = 112;
  505.                 length = 90;
  506.                 break;
  507.         }
  508.         create_key_door_unitrigger( piece_number, width, height, length );
  509.         piece_number++;
  510.     }
  511. }
  512.  
  513. create_key_door_unitrigger( piece_num, width, height, length )
  514. {
  515.     t_key_door = getstruct( "key_door_" + piece_num + "_trigger", "targetname" );
  516.     t_key_door.unitrigger_stub = spawnstruct();
  517.     t_key_door.unitrigger_stub.origin = t_key_door.origin;
  518.     t_key_door.unitrigger_stub.angles = t_key_door.angles;
  519.     t_key_door.unitrigger_stub.script_unitrigger_type = "unitrigger_box_use";
  520.     t_key_door.unitrigger_stub.hint_string = &"ZM_PRISON_KEY_DOOR_LOCKED";
  521.     t_key_door.unitrigger_stub.cursor_hint = "HINT_NOICON";
  522.     t_key_door.unitrigger_stub.script_width = width;
  523.     t_key_door.unitrigger_stub.script_height = height;
  524.     t_key_door.unitrigger_stub.script_length = length;
  525.     t_key_door.unitrigger_stub.n_door_index = piece_num;
  526.     t_key_door.unitrigger_stub.require_look_at = 0;
  527.     t_key_door.unitrigger_stub.prompt_and_visibility_func = ::key_door_trigger_visibility;
  528.     maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( t_key_door.unitrigger_stub, ::master_key_door_trigger_thread );
  529. }
  530.  
  531. key_door_trigger_visibility( player )
  532. {
  533.     if ( !player.afterlife && isDefined( self.stub.master_key_door_opened ) && !self.stub.master_key_door_opened )
  534.     {
  535.         if ( self.stub.n_door_index == 2 )
  536.         {
  537.             b_is_invis = !flag( "generator_challenge_completed" );
  538.         }
  539.     }
  540.     self setinvisibletoplayer( player, b_is_invis );
  541.     if ( flag( "key_found" ) )
  542.     {
  543.         self sethintstring( &"ZM_PRISON_KEY_DOOR" );
  544.     }
  545.     else
  546.     {
  547.         self sethintstring( self.stub.hint_string );
  548.     }
  549.     return !b_is_invis;
  550. }
  551.  
  552. master_key_door_trigger_thread()
  553. {
  554.     self endon( "death" );
  555.     self endon( "kill_trigger" );
  556.     n_door_index = self.stub.n_door_index;
  557.     b_door_open = 0;
  558.     while ( !b_door_open )
  559.     {
  560.         self waittill( "trigger", e_triggerer );
  561.         if ( e_triggerer is_holding_part( "quest_key1", "p6_zm_al_key" ) )
  562.         {
  563.             self.stub.master_key_door_opened = 1;
  564.             self.stub maps/mp/zombies/_zm_unitrigger::run_visibility_function_for_all_triggers();
  565.             level thread open_custom_door_master_key( n_door_index, e_triggerer );
  566.             self playsound( "evt_quest_door_open" );
  567.             b_door_open = 1;
  568.             continue;
  569.         }
  570.         else
  571.         {
  572.             e_triggerer thread do_player_general_vox( "quest", "sidequest_key", undefined, 100 );
  573. /#
  574.             iprintlnbold( "missing key!" );
  575. #/
  576.         }
  577.     }
  578.     level thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.stub );
  579. }
  580.  
  581. open_custom_door_master_key( n_door_index, e_triggerer )
  582. {
  583.     m_lock = getent( "masterkey_lock_" + n_door_index, "targetname" );
  584.     m_lock playsound( "zmb_quest_key_unlock" );
  585.     playfxontag( level._effect[ "fx_alcatraz_unlock_door" ], m_lock, "tag_origin" );
  586.     wait 0,5;
  587.     m_lock delete();
  588.     switch( n_door_index )
  589.     {
  590.         case 1:
  591.             shower_key_door = getent( "shower_key_door", "targetname" );
  592.             shower_key_door moveto( shower_key_door.origin + vectorScale( ( 0, 0, 0 ), 80 ), 0,25 );
  593.             shower_key_door connectpaths();
  594.             if ( isDefined( e_triggerer ) )
  595.             {
  596.                 e_triggerer door_rumble_on_open();
  597.             }
  598.             shower_key_door playsound( "zmb_chainlink_open" );
  599.             break;
  600.         case 2:
  601.             admin_powerhouse_puzzle_door_clip = getent( "admin_powerhouse_puzzle_door_clip", "targetname" );
  602.             admin_powerhouse_puzzle_door_clip delete();
  603.             admin_powerhouse_puzzle_door = getent( "admin_powerhouse_puzzle_door", "targetname" );
  604.             admin_powerhouse_puzzle_door rotateyaw( 90, 0,5 );
  605.             admin_powerhouse_puzzle_door playsound( "zmb_chainlink_open" );
  606.             break;
  607.         case 3:
  608.             m_nixie_door_left = getent( "nixie_door_left", "targetname" );
  609.             m_nixie_door_right = getent( "nixie_door_right", "targetname" );
  610.             m_nixie_door_left rotateyaw( -165, 0,5 );
  611.             m_nixie_door_right rotateyaw( 165, 0,5 );
  612.             m_nixie_tube_weaponclip = getent( "nixie_tube_weaponclip", "targetname" );
  613.             m_nixie_tube_weaponclip delete();
  614.             if ( isDefined( e_triggerer ) )
  615.             {
  616.                 e_triggerer door_rumble_on_open();
  617.             }
  618.             break;
  619.         case 4:
  620.             m_gate_01 = getent( "cable_puzzle_gate_01", "targetname" );
  621.             m_gate_01 moveto( m_gate_01.origin + ( -16, 80, 0 ), 0,5 );
  622.             m_gate_01 connectpaths();
  623.             gate_1_monsterclip = getent( "docks_gate_1_monsterclip", "targetname" );
  624.             gate_1_monsterclip.origin += vectorScale( ( 0, 0, 0 ), 256 );
  625.             gate_1_monsterclip disconnectpaths();
  626.             gate_1_monsterclip.origin -= vectorScale( ( 0, 0, 0 ), 256 );
  627.             if ( isDefined( e_triggerer ) )
  628.             {
  629.                 e_triggerer door_rumble_on_open();
  630.             }
  631.             m_gate_01 playsound( "zmb_chainlink_open" );
  632.             flag_set( "docks_inner_gate_unlocked" );
  633.             flag_set( "docks_inner_gate_open" );
  634.             break;
  635.         case 5:
  636.             m_infirmary_case_door_left = getent( "infirmary_case_door_left", "targetname" );
  637.             m_infirmary_case_door_right = getent( "infirmary_case_door_right", "targetname" );
  638.             m_infirmary_case_door_left rotateyaw( -165, 0,5 );
  639.             m_infirmary_case_door_right rotateyaw( 165, 0,5 );
  640.             m_fake_plane_steering = getent( "fake_veh_t6_dlc_zombie_part_control", "targetname" );
  641.             m_plane_steering = get_craftable_piece_model( "plane", "steering" );
  642.             m_plane_steering moveto( m_plane_steering.origin + vectorScale( ( 0, 0, 0 ), 512 ), 0,05 );
  643.             m_plane_steering setvisibletoall();
  644.             m_fake_plane_steering hide();
  645.             if ( isDefined( e_triggerer ) )
  646.             {
  647.                 e_triggerer door_rumble_on_open();
  648.             }
  649.             m_infirmary_case_door_right playsound( "zmb_cabinet_door" );
  650.             break;
  651.     }
  652. }
  653.  
  654. door_rumble_on_open()
  655. {
  656.     self endon( "disconnect" );
  657.     level endon( "end_game" );
  658.     self setclientfieldtoplayer( "rumble_door_open", 1 );
  659.     wait_network_frame();
  660.     self setclientfieldtoplayer( "rumble_door_open", 0 );
  661. }
  662.  
  663. setup_puzzles()
  664. {
  665.     level thread setup_master_key();
  666.     level thread setup_dryer_challenge();
  667.     level thread setup_generator_challenge();
  668.     level thread maps/mp/zm_alcatraz_sq_nixie::setup_nixie_tubes_puzzle();
  669.     level thread setup_gate_puzzle();
  670. }
  671.  
  672. setup_quest_triggers()
  673. {
  674.     t_plane_fuelable = getent( "plane_fuelable_trigger", "targetname" );
  675.     t_plane_fuelable trigger_off();
  676.     t_plane_fly = getent( "plane_fly_trigger", "targetname" );
  677.     t_plane_fly setcursorhint( "HINT_NOICON" );
  678.     t_plane_fly sethintstring( &"ZM_PRISON_PLANE_BOARD" );
  679.     t_plane_fly.require_look_at = 0;
  680.     t_plane_fly thread plane_fly_trigger_thread();
  681. }
  682.  
  683. setup_master_key()
  684. {
  685.     level.is_master_key_west = randomintrange( 0, 2 );
  686.     setclientfield( "fake_master_key", level.is_master_key_west + 1 );
  687.     if ( level.is_master_key_west )
  688.     {
  689.         level thread key_pulley( "west" );
  690.         exploder( 101 );
  691.         array_delete( getentarray( "wires_pulley_east", "script_noteworthy" ) );
  692.     }
  693.     else
  694.     {
  695.         level thread key_pulley( "east" );
  696.         exploder( 100 );
  697.         array_delete( getentarray( "wires_pulley_west", "script_noteworthy" ) );
  698.     }
  699. }
  700.  
  701. key_pulley( str_master_key_location )
  702. {
  703.     if ( level.is_master_key_west )
  704.     {
  705.         t_other_hurt_trigger = getent( "pulley_hurt_trigger_east", "targetname" );
  706.         t_other_panel = getent( "master_key_pulley_east", "targetname" );
  707.     }
  708.     else
  709.     {
  710.         t_other_hurt_trigger = getent( "pulley_hurt_trigger_west", "targetname" );
  711.         t_other_panel = getent( "master_key_pulley_west", "targetname" );
  712.     }
  713.     t_other_hurt_trigger delete();
  714.     t_other_panel setmodel( "p6_zm_al_power_station_panels_03" );
  715.     t_pulley_hurt_trigger = getent( "pulley_hurt_trigger_" + str_master_key_location, "targetname" );
  716.     t_pulley_hurt_trigger thread maps/mp/zm_alcatraz_sq_vo::sndhitelectrifiedpulley( str_master_key_location );
  717.     m_master_key_pulley = getent( "master_key_pulley_" + str_master_key_location, "targetname" );
  718.     m_master_key_pulley play_fx( "fx_alcatraz_panel_on_2", m_master_key_pulley.origin, m_master_key_pulley.angles, "power_down", 1, undefined, undefined );
  719.     m_master_key_pulley thread afterlife_interact_object_think();
  720.     level waittill( "master_key_pulley_" + str_master_key_location );
  721.     m_master_key_pulley playsound( "zmb_quest_generator_panel_spark" );
  722.     m_master_key_pulley notify( "power_down" );
  723.     m_master_key_pulley setmodel( "p6_zm_al_power_station_panels_03" );
  724.     playfxontag( level._effect[ "fx_alcatraz_panel_ol" ], m_master_key_pulley, "tag_origin" );
  725.     m_master_key_pulley play_fx( "fx_alcatraz_panel_off_2", m_master_key_pulley.origin, m_master_key_pulley.angles, "power_down", 1, undefined, undefined );
  726.     if ( level.is_master_key_west )
  727.     {
  728.         stop_exploder( 101 );
  729.         array_delete( getentarray( "wires_pulley_west", "script_noteworthy" ) );
  730.     }
  731.     else
  732.     {
  733.         stop_exploder( 100 );
  734.         array_delete( getentarray( "wires_pulley_east", "script_noteworthy" ) );
  735.     }
  736.     t_hurt_trigger = getent( "pulley_hurt_trigger_" + str_master_key_location, "targetname" );
  737.     t_hurt_trigger delete();
  738.     if ( str_master_key_location == "west" )
  739.     {
  740.         level setclientfield( "fxanim_pulley_down_start", 1 );
  741.     }
  742.     else
  743.     {
  744.         if ( str_master_key_location == "east" )
  745.         {
  746.             level setclientfield( "fxanim_pulley_down_start", 2 );
  747.         }
  748.     }
  749.     wait 3;
  750.     level setclientfield( "master_key_is_lowered", 1 );
  751.     m_master_key = get_craftable_piece_model( "quest_key1", "p6_zm_al_key" );
  752.     if ( isDefined( m_master_key ) )
  753.     {
  754.         e_master_key_target = getstruct( "master_key_" + str_master_key_location + "_origin", "targetname" );
  755.         m_master_key.origin = e_master_key_target.origin;
  756.         m_master_key setvisibletoall();
  757.     }
  758. }
  759.  
  760. setup_dryer_challenge()
  761. {
  762.     t_dryer = getent( "dryer_trigger", "targetname" );
  763.     t_dryer setcursorhint( "HINT_NOICON" );
  764.     t_dryer sethintstring( &"ZM_PRISON_LAUNDRY_MACHINE_ACTIVATE" );
  765.     t_dryer thread dryer_trigger_thread();
  766.     t_dryer thread dryer_zombies_thread();
  767.     t_dryer trigger_off();
  768.     level waittill( "laundry_power_switch_afterlife" );
  769.     level setclientfield( "dryer_stage", 1 );
  770. /#
  771.     iprintlnbold( "dryer can now be activated" );
  772. #/
  773.     t_dryer trigger_on();
  774.     t_dryer playsound( "evt_dryer_rdy_bell" );
  775.     wait 1;
  776.     players = getplayers();
  777.     _a900 = players;
  778.     _k900 = getFirstArrayKey( _a900 );
  779.     while ( isDefined( _k900 ) )
  780.     {
  781.         player = _a900[ _k900 ];
  782.         if ( !player.afterlife && distance( player.origin, t_dryer.origin ) < 1500 )
  783.         {
  784.             player thread do_player_general_vox( "general", "power_on", undefined, 100 );
  785.             return;
  786.         }
  787.         _k900 = getNextArrayKey( _a900, _k900 );
  788.     }
  789. }
  790.  
  791. dryer_trigger_thread()
  792. {
  793.     self endon( "death" );
  794.     n_dryer_cycle_duration = 30;
  795.     a_dryer_spawns = [];
  796.     sndent = spawn( "script_origin", ( 1613, 10599, 1203 ) );
  797.     self waittill( "trigger" );
  798.     self trigger_off();
  799.     level setclientfield( "dryer_stage", 2 );
  800.     dryer_playerclip = getent( "dryer_playerclip", "targetname" );
  801.     dryer_playerclip moveto( dryer_playerclip.origin + vectorScale( ( 0, 0, 0 ), 104 ), 0,05 );
  802.     level clientnotify( "sndFF" );
  803.     if ( isDefined( level.music_override ) && !level.music_override )
  804.     {
  805.         level notify( "sndStopBrutusLoop" );
  806.         level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "laundry_defend" );
  807.     }
  808.     exploder( 1000 );
  809.     sndent thread snddryercountdown( n_dryer_cycle_duration );
  810.     sndent playsound( "evt_dryer_start" );
  811.     sndent playloopsound( "evt_dryer_lp" );
  812.     level clientnotify( "fxanim_dryer_start" );
  813.     flag_set( "dryer_cycle_active" );
  814.     wait 1;
  815.     sndset = sndmusicvariable();
  816.     level clientnotify( "fxanim_dryer_idle_start" );
  817.     i = 3;
  818.     while ( i > 0 )
  819.     {
  820. /#
  821.         iprintlnbold( ( ( i / 3 ) * n_dryer_cycle_duration ) + " seconds left!" );
  822. #/
  823.         wait ( n_dryer_cycle_duration / 3 );
  824.         i--;
  825.  
  826.     }
  827.     level clientnotify( "fxanim_dryer_end_start" );
  828.     wait 2;
  829.     flag_clear( "dryer_cycle_active" );
  830.     dryer_playerclip = getent( "dryer_playerclip", "targetname" );
  831.     dryer_playerclip delete();
  832.     sndent stoploopsound();
  833.     sndent playsound( "evt_dryer_stop" );
  834.     if ( isDefined( sndset ) && sndset )
  835.     {
  836.         level.music_override = 0;
  837.     }
  838.     level clientnotify( "sndFF" );
  839.     level setclientfield( "dryer_stage", 3 );
  840.     stop_exploder( 900 );
  841.     stop_exploder( 1000 );
  842.     m_sheets = get_craftable_piece_model( "plane", "cloth" );
  843.     m_sheets.origin = ( 1586,16, 10598,3, 1192 );
  844.     m_sheets setvisibletoall();
  845.     m_sheets ghost();
  846.     self delete();
  847.     sndent thread delaysndenddelete();
  848. }
  849.  
  850. sndmusicvariable()
  851. {
  852.     if ( isDefined( level.music_override ) && !level.music_override )
  853.     {
  854.         level.music_override = 1;
  855.         return 1;
  856.     }
  857.     return 0;
  858. }
  859.  
  860. dryer_zombies_thread()
  861. {
  862.     n_zombie_count_min = 20;
  863.     e_shower_zone = getent( "cellblock_shower", "targetname" );
  864.     flag_wait( "dryer_cycle_active" );
  865.     if ( level.round_number > 4 || isDefined( level.is_forever_solo_game ) && level.is_forever_solo_game )
  866.     {
  867.         if ( level.zombie_total < n_zombie_count_min )
  868.         {
  869.             level.zombie_total = n_zombie_count_min;
  870.         }
  871.         while ( flag( "dryer_cycle_active" ) )
  872.         {
  873.             a_zombies_in_shower = [];
  874.             a_zombies_in_shower = get_zombies_touching_volume( "axis", "cellblock_shower", undefined );
  875.             if ( a_zombies_in_shower.size < n_zombie_count_min )
  876.             {
  877.                 e_zombie = get_farthest_available_zombie( e_shower_zone );
  878.                 if ( isDefined( e_zombie ) && !isinarray( a_zombies_in_shower, e_zombie ) )
  879.                 {
  880.                     e_zombie notify( "zapped" );
  881.                     e_zombie thread dryer_teleports_zombie();
  882.                 }
  883.             }
  884.             wait 1;
  885.         }
  886.     }
  887.     else maps/mp/zombies/_zm_ai_brutus::brutus_spawn_in_zone( "cellblock_shower" );
  888. }
  889.  
  890. get_farthest_available_zombie( e_landmark )
  891. {
  892.     if ( !isDefined( e_landmark ) )
  893.     {
  894.         return undefined;
  895.     }
  896.     while ( 1 )
  897.     {
  898.         a_zombies = getaiarray( level.zombie_team );
  899.         if ( isDefined( a_zombies ) )
  900.         {
  901.             zombies = get_array_of_closest( e_landmark.origin, a_zombies );
  902.             x = 0;
  903.             while ( x < zombies.size )
  904.             {
  905.                 zombie = zombies[ x ];
  906.                 if ( isDefined( zombie ) && isalive( zombie ) && isDefined( zombie.in_the_ground ) && !zombie.in_the_ground && isDefined( zombie.gibbed ) && !zombie.gibbed && isDefined( zombie.head_gibbed ) && !zombie.head_gibbed && isDefined( zombie.is_being_used_as_spawnpoint ) && !zombie.is_being_used_as_spawnpoint && zombie in_playable_area() )
  907.                 {
  908.                     zombie.is_being_used_as_spawnpoint = 1;
  909.                     return zombie;
  910.                 }
  911.                 x++;
  912.             }
  913.         }
  914.         else return undefined;
  915.         wait 0,05;
  916.     }
  917. }
  918.  
  919. get_zombies_touching_volume( team, volume_name, volume )
  920. {
  921.     if ( !isDefined( volume ) )
  922.     {
  923.         volume = getent( volume_name, "targetname" );
  924. /#
  925.         assert( isDefined( volume ), volume_name + " does not exist" );
  926. #/
  927.     }
  928.     guys = getaiarray( team );
  929.     guys_touching_volume = [];
  930.     i = 0;
  931.     while ( i < guys.size )
  932.     {
  933.         if ( guys[ i ] istouching( volume ) )
  934.         {
  935.             guys_touching_volume[ guys_touching_volume.size ] = guys[ i ];
  936.         }
  937.         i++;
  938.     }
  939.     return guys_touching_volume;
  940. }
  941.  
  942. dryer_teleports_zombie()
  943. {
  944.     self endon( "death" );
  945.     self endon( "zapped" );
  946.     if ( self.ai_state == "find_flesh" )
  947.     {
  948.         self.zapped = 1;
  949.         a_nodes = getstructarray( "dryer_zombie_teleports", "targetname" );
  950.         nd_target = random( a_nodes );
  951.         playfx( level._effect[ "afterlife_teleport" ], self.origin );
  952.         self hide();
  953.         linker = spawn( "script_origin", ( 0, 0, 0 ) );
  954.         linker thread linker_delete_watch( self );
  955.         linker.origin = self.origin;
  956.         linker.angles = self.angles;
  957.         self linkto( linker );
  958.         linker moveto( nd_target.origin, 0,05 );
  959.         linker waittill( "movedone" );
  960.         playfx( level._effect[ "afterlife_teleport" ], self.origin );
  961.         linker delete();
  962.         self show();
  963.         self.zapped = undefined;
  964.         self.ignoreall = 1;
  965.         self notify( "stop_find_flesh" );
  966.         self thread afterlife_zapped_fx();
  967.         self animscripted( self.origin, self.angles, "zm_afterlife_stun" );
  968.         self maps/mp/animscripts/shared::donotetracks( "stunned" );
  969.         self.ignoreall = 0;
  970.         self thread maps/mp/zombies/_zm_ai_basic::find_flesh();
  971.     }
  972. }
  973.  
  974. delaysndenddelete()
  975. {
  976.     wait 5;
  977.     self delete();
  978. }
  979.  
  980. snddryercountdown( num )
  981. {
  982.     ent = spawn( "script_origin", self.origin );
  983.     i = num;
  984.     while ( i > 0 )
  985.     {
  986.         if ( i <= 10 )
  987.         {
  988.             ent playsound( "zmb_quest_nixie_count_final" );
  989.         }
  990.         else
  991.         {
  992.             ent playsound( "zmb_quest_nixie_count" );
  993.         }
  994.         wait 1;
  995.         i--;
  996.  
  997.     }
  998.     ent delete();
  999. }
  1000.  
  1001. setup_generator_challenge()
  1002. {
  1003.     level.n_generator_panels_active = 0;
  1004.     generator_soundent = spawn( "script_origin", ( -467, 6388, 132 ) );
  1005.     i = 1;
  1006.     while ( i < 4 )
  1007.     {
  1008.         level thread generator_panel_trigger_thread( i, generator_soundent );
  1009.         i++;
  1010.     }
  1011.     level thread generator_challenge_main_thread();
  1012. }
  1013.  
  1014. generator_challenge_main_thread()
  1015. {
  1016.     exploder( 2000 );
  1017.     while ( !flag( "generator_challenge_completed" ) )
  1018.     {
  1019.         if ( level.n_generator_panels_active == 3 )
  1020.         {
  1021. /#
  1022.             iprintlnbold( "generator overloaded!" );
  1023. #/
  1024.             flag_set( "generator_challenge_completed" );
  1025.         }
  1026.         wait 0,1;
  1027.     }
  1028.     level clientnotify( "sndWard" );
  1029.     level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "piece_mid" );
  1030.     t_warden_fence_damage = getent( "warden_fence_damage", "targetname" );
  1031.     t_warden_fence_damage delete();
  1032.     level setclientfield( "warden_fence_down", 1 );
  1033.     array_delete( getentarray( "generator_wires", "script_noteworthy" ) );
  1034.     wait 3;
  1035.     stop_exploder( 2000 );
  1036.     wait 1;
  1037.     players = getplayers();
  1038.     player = players[ randomintrange( 0, players.size ) ];
  1039.     player do_player_general_vox( "general", "power_off", undefined, 100 );
  1040. }
  1041.  
  1042. generator_panel_trigger_thread( n_panel_index, generator_soundent )
  1043. {
  1044.     self endon( "death" );
  1045.     m_generator_panel = getent( "generator_panel_" + n_panel_index, "targetname" );
  1046.     m_generator_panel thread afterlife_interact_object_think();
  1047.     m_generator_panel play_fx( "fx_alcatraz_panel_on_2", m_generator_panel.origin, m_generator_panel.angles, "generator_panel_" + n_panel_index + "_afterlife", 1, undefined, undefined );
  1048.     level waittill( "generator_panel_" + n_panel_index + "_afterlife" );
  1049.     m_generator_panel notify( "generator_panel_" + n_panel_index + "_afterlife" );
  1050. /#
  1051.     iprintlnbold( "generator panel " + n_panel_index + " overloaded!" );
  1052. #/
  1053.     level.n_generator_panels_active += 1;
  1054.     m_generator_panel setmodel( "p6_zm_al_power_station_panels_03" );
  1055.     playfxontag( level._effect[ "fx_alcatraz_panel_ol" ], m_generator_panel, "tag_origin" );
  1056.     m_generator_panel play_fx( "fx_alcatraz_panel_off_2", m_generator_panel.origin, m_generator_panel.angles, undefined, 1, undefined, undefined );
  1057.     set_generator_vfx_amount( level.n_generator_panels_active, generator_soundent );
  1058.     playsoundatposition( "zmb_quest_generator_panel_spark", m_generator_panel.origin );
  1059. }
  1060.  
  1061. set_generator_vfx_amount( n_vfx_amount, generator_soundent )
  1062. {
  1063.     if ( n_vfx_amount == 1 )
  1064.     {
  1065.         generator_soundent playloopsound( "zmb_quest_generator_loop1" );
  1066.     }
  1067.     if ( n_vfx_amount == 2 )
  1068.     {
  1069.         generator_soundent stoploopsound();
  1070.         wait 0,05;
  1071.         generator_soundent playloopsound( "zmb_quest_generator_loop2" );
  1072.     }
  1073.     if ( n_vfx_amount == 3 )
  1074.     {
  1075.         exploder( 3100 );
  1076.         exploder( 3200 );
  1077.         exploder( 3300 );
  1078.         generator_soundent stoploopsound();
  1079.         wait 0,05;
  1080.         generator_soundent playloopsound( "zmb_quest_generator_loop3" );
  1081.     }
  1082. }
  1083.  
  1084. setup_gate_puzzle()
  1085. {
  1086.     self endon( "death" );
  1087.     is_gate_toggled = 0;
  1088.     is_inner_gate_toggleable = 0;
  1089.     m_gate_02 = getent( "cable_puzzle_gate_02", "targetname" );
  1090.     n_gate_move_duration = 0,5;
  1091.     m_docks_shockbox = getent( "docks_panel", "targetname" );
  1092.     array_set_visible_to_all( getentarray( "wires_docks_gate_toggle", "script_noteworthy" ), 0 );
  1093.     a_players = [];
  1094.     a_players = getplayers();
  1095.     if ( a_players.size > 1 )
  1096.     {
  1097.         is_inner_gate_toggleable = 1;
  1098.     }
  1099.     while ( 1 )
  1100.     {
  1101.         m_docks_shockbox thread afterlife_interact_object_think();
  1102.         level waittill( "cable_puzzle_gate_afterlife" );
  1103.         array_set_visible_to_all( getentarray( "wires_docks_gate_toggle", "script_noteworthy" ), 1 );
  1104.         if ( is_inner_gate_toggleable && flag( "docks_inner_gate_unlocked" ) )
  1105.         {
  1106.             level thread toggle_inner_gate( n_gate_move_duration );
  1107.         }
  1108.         if ( !flag( "docks_outer_gate_open" ) )
  1109.         {
  1110.             m_gate_02 moveto( m_gate_02.origin + ( -16, 80, 0 ), n_gate_move_duration );
  1111.             wait ( n_gate_move_duration + 0,25 );
  1112.             m_gate_02 connectpaths();
  1113.             gate_2_monsterclip = getent( "docks_gate_2_monsterclip", "targetname" );
  1114.             gate_2_monsterclip.origin += vectorScale( ( 0, 0, 0 ), 256 );
  1115.             gate_2_monsterclip disconnectpaths();
  1116.             gate_2_monsterclip.origin -= vectorScale( ( 0, 0, 0 ), 256 );
  1117.             m_gate_02 playsound( "zmb_chainlink_close" );
  1118.         }
  1119.         else
  1120.         {
  1121.             if ( !flag( "docks_gates_remain_open" ) )
  1122.             {
  1123.                 m_gate_02 moveto( m_gate_02.origin - ( -16, 80, 0 ), n_gate_move_duration );
  1124.                 wait ( n_gate_move_duration + 0,25 );
  1125.                 m_gate_02 disconnectpaths();
  1126.                 gate_2_monsterclip = getent( "docks_gate_2_monsterclip", "targetname" );
  1127.                 gate_2_monsterclip connectpaths();
  1128.                 m_gate_02 playsound( "zmb_chainlink_open" );
  1129.             }
  1130.         }
  1131.         flag_toggle( "docks_outer_gate_open" );
  1132. /#
  1133.         iprintlnbold( "gate toggled!" );
  1134. #/
  1135.         wait n_gate_move_duration;
  1136. /#
  1137.         iprintlnbold( "gate ready to be re-toggled" );
  1138. #/
  1139.         m_docks_shockbox notify( "afterlife_interact_reset" );
  1140.         array_set_visible_to_all( getentarray( "wires_docks_gate_toggle", "script_noteworthy" ), 0 );
  1141.     }
  1142. }
  1143.  
  1144. toggle_inner_gate( n_gate_move_duration )
  1145. {
  1146.     a_m_gate_01 = getentarray( "cable_puzzle_gate_01", "targetname" );
  1147.     if ( flag( "docks_inner_gate_open" ) && !flag( "docks_gates_remain_open" ) )
  1148.     {
  1149.         i = 0;
  1150.         while ( i < a_m_gate_01.size )
  1151.         {
  1152.             a_m_gate_01[ i ] moveto( a_m_gate_01[ i ].origin - ( -16, 80, 0 ), n_gate_move_duration );
  1153.             i++;
  1154.         }
  1155.         wait ( n_gate_move_duration + 0,25 );
  1156.         i = 0;
  1157.         while ( i < a_m_gate_01.size )
  1158.         {
  1159.             a_m_gate_01[ i ] disconnectpaths();
  1160.             i++;
  1161.         }
  1162.         gate_1_monsterclip = getent( "docks_gate_1_monsterclip", "targetname" );
  1163.         gate_1_monsterclip connectpaths();
  1164.         a_m_gate_01[ 0 ] playsound( "zmb_chainlink_close" );
  1165.     }
  1166.     else
  1167.     {
  1168.         i = 0;
  1169.         while ( i < a_m_gate_01.size )
  1170.         {
  1171.             a_m_gate_01[ i ] moveto( a_m_gate_01[ i ].origin + ( -16, 80, 0 ), n_gate_move_duration );
  1172.             i++;
  1173.         }
  1174.         wait ( n_gate_move_duration + 0,25 );
  1175.         i = 0;
  1176.         while ( i < a_m_gate_01.size )
  1177.         {
  1178.             a_m_gate_01[ i ] connectpaths();
  1179.             i++;
  1180.         }
  1181.         gate_1_monsterclip = getent( "docks_gate_1_monsterclip", "targetname" );
  1182.         gate_1_monsterclip.origin += vectorScale( ( 0, 0, 0 ), 256 );
  1183.         gate_1_monsterclip disconnectpaths();
  1184.         gate_1_monsterclip.origin -= vectorScale( ( 0, 0, 0 ), 256 );
  1185.         a_m_gate_01[ 0 ] playsound( "zmb_chainlink_open" );
  1186.     }
  1187.     flag_toggle( "docks_inner_gate_open" );
  1188. }
  1189.  
  1190. plane_fly_trigger_thread()
  1191. {
  1192.     self setcursorhint( "HINT_NOICON" );
  1193.     self sethintstring( &"ZM_PRISON_PLANE_BEGIN_TAKEOFF" );
  1194.     flag_wait( "initial_players_connected" );
  1195.     flag_wait( "brutus_setup_complete" );
  1196.     self trigger_off();
  1197.     wait 1;
  1198.     m_plane_craftable = getent( "plane_craftable", "targetname" );
  1199.     m_plane_craftable show();
  1200.     m_plane_craftable hidepart( "tag_support_upper" );
  1201.     m_plane_craftable hidepart( "tag_wing_skins_up" );
  1202.     m_plane_craftable hidepart( "tag_engines_up" );
  1203.     m_plane_craftable hidepart( "tag_feul_tanks" );
  1204.     m_plane_craftable hidepart( "tag_control_mechanism" );
  1205.     m_plane_craftable hidepart( "tag_engine_ground" );
  1206.     m_plane_craftable hidepart( "tag_clothes_ground" );
  1207.     m_plane_craftable hidepart( "tag_fuel_hose" );
  1208.     waittill_crafted( "plane" );
  1209.     maps/mp/zombies/_zm_ai_brutus::transfer_plane_trigger( "build", "fly" );
  1210.     self trigger_on();
  1211.     while ( isDefined( self ) )
  1212.     {
  1213.         self waittill( "trigger", e_triggerer );
  1214.         if ( isplayer( e_triggerer ) )
  1215.         {
  1216.             if ( level.n_plane_fuel_count == 5 )
  1217.             {
  1218.                 while ( isDefined( level.custom_plane_validation ) )
  1219.                 {
  1220.                     valid = self [[ level.custom_plane_validation ]]( e_triggerer );
  1221.                     while ( !valid )
  1222.                     {
  1223.                         continue;
  1224.                     }
  1225.                 }
  1226.                 self setinvisibletoplayer( e_triggerer );
  1227.                 if ( isDefined( level.plane_boarding_thread_custom_func ) )
  1228.                 {
  1229.                     e_triggerer thread [[ level.plane_boarding_thread_custom_func ]]();
  1230.                     break;
  1231.                 }
  1232.                 else
  1233.                 {
  1234.                     e_triggerer thread plane_boarding_thread();
  1235.                 }
  1236.             }
  1237.         }
  1238.     }
  1239. }
  1240.  
  1241. plane_boarding_thread()
  1242. {
  1243.     self endon( "death_or_disconnect" );
  1244.     flag_set( "plane_is_away" );
  1245.     self thread player_disconnect_watcher();
  1246.     self thread player_death_watcher();
  1247. /#
  1248.     iprintlnbold( "plane boarding thread started" );
  1249. #/
  1250.     flag_set( "plane_boarded" );
  1251.     self setclientfieldtoplayer( "effects_escape_flight", 1 );
  1252.     level.brutus_respawn_after_despawn = 0;
  1253.     a_nml_teleport_targets = [];
  1254.     i = 1;
  1255.     while ( i < 6 )
  1256.     {
  1257.         a_nml_teleport_targets[ i - 1 ] = getstruct( "nml_telepoint_" + i, "targetname" );
  1258.         i++;
  1259.     }
  1260.     level.characters_in_nml[ level.characters_in_nml.size ] = self.character_name;
  1261.     self.on_a_plane = 1;
  1262.     level.someone_has_visited_nml = 1;
  1263.     self.n_passenger_index = level.characters_in_nml.size;
  1264.     m_plane_craftable = getent( "plane_craftable", "targetname" );
  1265.     m_plane_about_to_crash = getent( "plane_about_to_crash", "targetname" );
  1266.     veh_plane_flyable = getent( "plane_flyable", "targetname" );
  1267.     t_plane_fly = getent( "plane_fly_trigger", "targetname" );
  1268.     t_plane_fly sethintstring( &"ZM_PRISON_PLANE_BOARD" );
  1269.     self enableinvulnerability();
  1270.     self playerlinktodelta( m_plane_craftable, "tag_player_crouched_" + ( self.n_passenger_index + 1 ) );
  1271.     self allowstand( 0 );
  1272.     flag_wait( "plane_departed" );
  1273.     level notify( "sndStopBrutusLoop" );
  1274.     self clientnotify( "sndPS" );
  1275.     self playsoundtoplayer( "zmb_plane_takeoff", self );
  1276.     level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "plane_takeoff", self );
  1277.     self playerlinktodelta( veh_plane_flyable, "tag_player_crouched_" + ( self.n_passenger_index + 1 ) );
  1278.     self setclientfieldtoplayer( "effects_escape_flight", 2 );
  1279.     flag_wait( "plane_approach_bridge" );
  1280.     self thread snddelayedimp();
  1281.     self setclientfieldtoplayer( "effects_escape_flight", 3 );
  1282.     self unlink();
  1283.     self playerlinktoabsolute( veh_plane_flyable, "tag_player_crouched_" + ( self.n_passenger_index + 1 ) );
  1284.     flag_wait( "plane_zapped" );
  1285.     flag_set( "activate_player_zone_bridge" );
  1286.     self playsoundtoplayer( "zmb_plane_fall", self );
  1287.     self setclientfieldtoplayer( "effects_escape_flight", 4 );
  1288.     self.dontspeak = 1;
  1289.     self setclientfieldtoplayer( "isspeaking", 1 );
  1290.     self playerlinktodelta( m_plane_about_to_crash, "tag_player_crouched_" + ( self.n_passenger_index + 1 ), 1, 0, 0, 0, 0, 1 );
  1291.     self forcegrenadethrow();
  1292.     str_current_weapon = self getcurrentweapon();
  1293.     self giveweapon( "falling_hands_zm" );
  1294.     self switchtoweaponimmediate( "falling_hands_zm" );
  1295.     self setweaponammoclip( "falling_hands_zm", 0 );
  1296.     players = getplayers();
  1297.     _a1548 = players;
  1298.     _k1548 = getFirstArrayKey( _a1548 );
  1299.     while ( isDefined( _k1548 ) )
  1300.     {
  1301.         player = _a1548[ _k1548 ];
  1302.         if ( player != self )
  1303.         {
  1304.             player setinvisibletoplayer( self );
  1305.         }
  1306.         _k1548 = getNextArrayKey( _a1548, _k1548 );
  1307.     }
  1308.     flag_wait( "plane_crashed" );
  1309.     self setclientfieldtoplayer( "effects_escape_flight", 5 );
  1310.     self takeweapon( "falling_hands_zm" );
  1311.     if ( isDefined( str_current_weapon ) && str_current_weapon != "none" )
  1312.     {
  1313.         self switchtoweaponimmediate( str_current_weapon );
  1314.     }
  1315.     self thread fadetoblackforxsec( 0, 2, 0, 0,5, "black" );
  1316.     self thread snddelayedmusic();
  1317.     self unlink();
  1318.     self allowstand( 1 );
  1319.     self setstance( "stand" );
  1320.     players = getplayers();
  1321.     _a1571 = players;
  1322.     _k1571 = getFirstArrayKey( _a1571 );
  1323.     while ( isDefined( _k1571 ) )
  1324.     {
  1325.         player = _a1571[ _k1571 ];
  1326.         if ( player != self )
  1327.         {
  1328.             player setvisibletoplayer( self );
  1329.         }
  1330.         _k1571 = getNextArrayKey( _a1571, _k1571 );
  1331.     }
  1332.     flag_clear( "spawn_zombies" );
  1333.     self setorigin( a_nml_teleport_targets[ self.n_passenger_index ].origin );
  1334.     e_poi = getstruct( "plane_crash_poi", "targetname" );
  1335.     vec_to_target = e_poi.origin - self.origin;
  1336.     vec_to_target = vectorToAngle( vec_to_target );
  1337.     vec_to_target = ( 0, vec_to_target[ 1 ], 0 );
  1338.     self setplayerangles( vec_to_target );
  1339.     n_shellshock_duration = 5;
  1340.     self shellshock( "explosion", n_shellshock_duration );
  1341.     self.dontspeak = 0;
  1342.     self setclientfieldtoplayer( "isspeaking", 0 );
  1343.     self notify( "player_at_bridge" );
  1344.     wait n_shellshock_duration;
  1345.     self disableinvulnerability();
  1346.     self.on_a_plane = 0;
  1347.     if ( level.characters_in_nml.size == 1 )
  1348.     {
  1349.         self vo_bridge_soliloquy();
  1350.     }
  1351.     else
  1352.     {
  1353.         if ( level.characters_in_nml.size == 4 )
  1354.         {
  1355.             vo_bridge_four_part_convo();
  1356.         }
  1357.     }
  1358.     wait 10;
  1359.     self playsoundtoplayer( "zmb_ggb_swarm_start", self );
  1360.     flag_set( "spawn_zombies" );
  1361.     level.brutus_respawn_after_despawn = 1;
  1362.     wait 5;
  1363.     character_name = level.characters_in_nml[ randomintrange( 0, level.characters_in_nml.size ) ];
  1364.     players = getplayers();
  1365.     _a1625 = players;
  1366.     _k1625 = getFirstArrayKey( _a1625 );
  1367.     while ( isDefined( _k1625 ) )
  1368.     {
  1369.         player = _a1625[ _k1625 ];
  1370.         if ( isDefined( player ) && player.character_name == character_name )
  1371.         {
  1372.             player thread do_player_general_vox( "quest", "zombie_arrive_gg", undefined, 100 );
  1373.         }
  1374.         _k1625 = getNextArrayKey( _a1625, _k1625 );
  1375.     }
  1376. }
  1377.  
  1378. snddelayedimp()
  1379. {
  1380.     self endon( "disconnect" );
  1381.     wait 6;
  1382.     self playsoundtoplayer( "zmb_plane_explode", self );
  1383. }
  1384.  
  1385. snddelayedmusic()
  1386. {
  1387.     self endon( "disconnect" );
  1388.     wait 1;
  1389.     level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "at_golden_gate", self );
  1390.     self clientnotify( "sndPE" );
  1391. }
  1392.  
  1393. track_quest_status_thread()
  1394. {
  1395.     while ( 1 )
  1396.     {
  1397.         while ( level.characters_in_nml.size == 0 )
  1398.         {
  1399.             wait 1;
  1400.         }
  1401.         while ( level.characters_in_nml.size > 0 )
  1402.         {
  1403.             wait 1;
  1404.         }
  1405.         if ( flag( "plane_trip_to_nml_successful" ) )
  1406.         {
  1407.             bestow_quest_rewards();
  1408.             flag_clear( "plane_trip_to_nml_successful" );
  1409.         }
  1410.         level notify( "bridge_empty" );
  1411.         level waittill( "start_of_round" );
  1412.         if ( level.n_quest_iteration_count == 2 )
  1413.         {
  1414.             vo_play_four_part_conversation( level.four_part_convos[ "alcatraz_return_alt" + randomintrange( 0, 2 ) ] );
  1415.         }
  1416.         prep_for_new_quest();
  1417.         waittill_crafted( "refuelable_plane" );
  1418.         maps/mp/zombies/_zm_ai_brutus::transfer_plane_trigger( "fuel", "fly" );
  1419.         t_plane_fly = getent( "plane_fly_trigger", "targetname" );
  1420.         t_plane_fly trigger_on();
  1421.     }
  1422. }
  1423.  
  1424. bestow_quest_rewards()
  1425. {
  1426.     level.n_quest_iteration_count += 1;
  1427.     if ( level.n_quest_iteration_count == 2 )
  1428.     {
  1429.         level notify( "unlock_all_perk_machines" );
  1430.         level notify( "intro_powerup_restored" );
  1431.     }
  1432.     else
  1433.     {
  1434.         if ( level.n_quest_iteration_count == 4 )
  1435.         {
  1436.             flag_set( "quest_completed_thrice" );
  1437.         }
  1438.     }
  1439. }
  1440.  
  1441. prep_for_new_quest()
  1442. {
  1443.     i = 1;
  1444.     while ( i < 4 )
  1445.     {
  1446.         str_trigger_targetname = "trigger_electric_chair_" + i;
  1447.         t_electric_chair = getent( str_trigger_targetname, "targetname" );
  1448.         t_electric_chair sethintstring( &"ZM_PRISON_ELECTRIC_CHAIR_ACTIVATE" );
  1449.         t_electric_chair trigger_on();
  1450.         i++;
  1451.     }
  1452.     flag_set( "spawn_fuel_tanks" );
  1453.     wait 0,05;
  1454.     flag_clear( "spawn_fuel_tanks" );
  1455.     i = 0;
  1456.     while ( i < level.a_uts_craftables.size )
  1457.     {
  1458.         if ( level.a_uts_craftables[ i ].equipname == "refuelable_plane" )
  1459.         {
  1460.             t_plane_fuelable = level.a_uts_craftables[ i ];
  1461.             level.zones[ "zone_roof" ].plane_triggers[ level.zones[ "zone_roof" ].plane_triggers.size ] = t_plane_fuelable;
  1462.             break;
  1463.         }
  1464.         else
  1465.         {
  1466.             i++;
  1467.         }
  1468.     }
  1469.     t_plane_fly = getent( "plane_fly_trigger", "targetname" );
  1470.     t_plane_fly trigger_off();
  1471.     players = get_players();
  1472.     t_plane_fly setvisibletoall();
  1473.     maps/mp/zombies/_zm_ai_brutus::transfer_plane_trigger( "fly", "fuel" );
  1474.     i = 1;
  1475.     while ( i < 5 )
  1476.     {
  1477.         m_electric_chair = getent( "electric_chair_" + i, "targetname" );
  1478.         m_electric_chair notify( "bridge_empty" );
  1479.         i++;
  1480.     }
  1481.     setup_puzzle_piece_glint();
  1482. /#
  1483.     iprintlnbold( "plane location reset" );
  1484. #/
  1485.     m_plane_craftable = getent( "plane_craftable", "targetname" );
  1486.     m_plane_craftable show();
  1487.     playfxontag( level._effect[ "fx_alcatraz_plane_apear" ], m_plane_craftable, "tag_origin" );
  1488.     veh_plane_flyable = getent( "plane_flyable", "targetname" );
  1489.     veh_plane_flyable attachpath( getvehiclenode( "zombie_plane_underground", "targetname" ) );
  1490.     vo_play_four_part_conversation( level.four_part_convos[ "alcatraz_return_quest_reset" ] );
  1491.     flag_clear( "plane_is_away" );
  1492. }
  1493.  
  1494. plane_flight_thread()
  1495. {
  1496.     while ( 1 )
  1497.     {
  1498.         m_plane_about_to_crash = getent( "plane_about_to_crash", "targetname" );
  1499.         m_plane_craftable = getent( "plane_craftable", "targetname" );
  1500.         t_plane_fly = getent( "plane_fly_trigger", "targetname" );
  1501.         veh_plane_flyable = getent( "plane_flyable", "targetname" );
  1502.         m_plane_about_to_crash ghost();
  1503.         flag_wait( "plane_boarded" );
  1504.         level clientnotify( "sndPB" );
  1505.         if ( isDefined( level.music_override ) && !level.music_override )
  1506.         {
  1507.             t_plane_fly playloopsound( "mus_event_plane_countdown_loop", 0,25 );
  1508.         }
  1509.         i = 10;
  1510.         while ( i > 0 )
  1511.         {
  1512. /#
  1513.             iprintlnbold( "TAKE-OFF IN " + i + "..." );
  1514. #/
  1515.             veh_plane_flyable playsound( "zmb_plane_countdown_tick" );
  1516.             wait 1;
  1517.             i--;
  1518.  
  1519.         }
  1520.         t_plane_fly stoploopsound( 2 );
  1521.         exploder( 10000 );
  1522.         veh_plane_flyable attachpath( getvehiclenode( "zombie_plane_flight_path", "targetname" ) );
  1523.         veh_plane_flyable startpath();
  1524.         flag_set( "plane_departed" );
  1525.         t_plane_fly trigger_off();
  1526.         m_plane_craftable ghost();
  1527.         veh_plane_flyable setvisibletoall();
  1528.         level setclientfield( "fog_stage", 1 );
  1529.         playfxontag( level._effect[ "fx_alcatraz_plane_trail" ], veh_plane_flyable, "tag_origin" );
  1530.         wait 2;
  1531.         playfxontag( level._effect[ "fx_alcatraz_plane_trail_fast" ], veh_plane_flyable, "tag_origin" );
  1532.         wait 3;
  1533.         exploder( 10001 );
  1534.         wait 4;
  1535.         playfxontag( level._effect[ "fx_alcatraz_flight_lightning" ], veh_plane_flyable, "tag_origin" );
  1536.         level setclientfield( "scripted_lightning_flash", 1 );
  1537.         wait 1;
  1538.         flag_set( "plane_approach_bridge" );
  1539.         stop_exploder( 10001 );
  1540.         level setclientfield( "fog_stage", 2 );
  1541.         veh_plane_flyable attachpath( getvehiclenode( "zombie_plane_bridge_approach", "targetname" ) );
  1542.         veh_plane_flyable startpath();
  1543.         wait 6;
  1544.         playfxontag( level._effect[ "fx_alcatraz_flight_lightning" ], veh_plane_flyable, "tag_origin" );
  1545.         level setclientfield( "scripted_lightning_flash", 1 );
  1546.         veh_plane_flyable waittill( "reached_end_node" );
  1547.         flag_set( "plane_zapped" );
  1548.         level setclientfield( "fog_stage", 3 );
  1549.         veh_plane_flyable setinvisibletoall();
  1550.         n_crash_duration = 2,25;
  1551.         nd_plane_about_to_crash_1 = getstruct( "plane_about_to_crash_point_1", "targetname" );
  1552.         m_plane_about_to_crash.origin = nd_plane_about_to_crash_1.origin;
  1553.         nd_plane_about_to_crash_2 = getstruct( "plane_about_to_crash_point_2", "targetname" );
  1554.         m_plane_about_to_crash moveto( nd_plane_about_to_crash_2.origin, n_crash_duration );
  1555.         m_plane_about_to_crash thread spin_while_falling();
  1556.         stop_exploder( 10000 );
  1557.         m_plane_about_to_crash waittill( "movedone" );
  1558.         flag_set( "plane_crashed" );
  1559.         wait 2;
  1560.         level setclientfield( "scripted_lightning_flash", 1 );
  1561.         m_plane_about_to_crash.origin += vectorScale( ( 0, 0, 0 ), 2048 );
  1562.         wait 4;
  1563.         veh_plane_flyable setvisibletoall();
  1564.         veh_plane_flyable play_fx( "fx_alcatraz_plane_fire_trail", veh_plane_flyable.origin, veh_plane_flyable.angles, "reached_end_node", 1, "tag_origin", undefined );
  1565.         veh_plane_flyable attachpath( getvehiclenode( "zombie_plane_bridge_flyby", "targetname" ) );
  1566.         veh_plane_flyable startpath();
  1567.         veh_plane_flyable thread sndpc();
  1568.         veh_plane_flyable waittill( "reached_end_node" );
  1569.         veh_plane_flyable setinvisibletoall();
  1570.         wait 20;
  1571.         if ( !level.final_flight_activated )
  1572.         {
  1573.             if ( isDefined( level.brutus_on_the_bridge_custom_func ) )
  1574.             {
  1575.                 level thread [[ level.brutus_on_the_bridge_custom_func ]]();
  1576.                 break;
  1577.             }
  1578.             else
  1579.             {
  1580.                 level thread brutus_on_the_bridge();
  1581.             }
  1582.         }
  1583.         flag_clear( "plane_built" );
  1584.         flag_clear( "plane_boarded" );
  1585.         flag_clear( "plane_departed" );
  1586.         flag_clear( "plane_approach_bridge" );
  1587.         flag_clear( "plane_zapped" );
  1588.         flag_clear( "plane_crashed" );
  1589.         level.n_plane_fuel_count = 0;
  1590.     }
  1591. }
  1592.  
  1593. sndpc()
  1594. {
  1595.     self playloopsound( "zmb_plane_fire", 4 );
  1596.     wait 6;
  1597.     self playsound( "zmb_plane_fire_whoosh" );
  1598.     wait 1;
  1599.     self stoploopsound( 3 );
  1600. }
  1601.  
  1602. brutus_on_the_bridge()
  1603. {
  1604.     level endon( "bridge_empty" );
  1605.     n_round_on_bridge = 1;
  1606.     n_desired_spawn_count = 0;
  1607.     n_spawn_cap = 4;
  1608.     level.n_bridge_brutuses_killed = 0;
  1609.     if ( isDefined( level.last_brutus_on_bridge_custom_func ) )
  1610.     {
  1611.         level thread [[ level.last_brutus_on_bridge_custom_func ]]();
  1612.     }
  1613.     else
  1614.     {
  1615.         level thread last_brutus_on_bridge();
  1616.     }
  1617.     if ( isDefined( level.brutus_despawn_manager_custom_func ) )
  1618.     {
  1619.         level thread [[ level.brutus_despawn_manager_custom_func ]]();
  1620.     }
  1621.     else
  1622.     {
  1623.         level thread brutus_despawn_manager();
  1624.     }
  1625.     while ( 1 )
  1626.     {
  1627.         level.brutus_last_spawn_round = 0;
  1628.         n_desired_spawn_count = int( min( n_round_on_bridge, n_spawn_cap ) );
  1629.         n_brutuses_on_bridge_count = get_bridge_brutus_count();
  1630.         n_spawns_needed = n_desired_spawn_count - n_brutuses_on_bridge_count;
  1631.         i = n_spawns_needed;
  1632.         while ( i > 0 )
  1633.         {
  1634.             ai = maps/mp/zombies/_zm_ai_brutus::brutus_spawn_in_zone( "zone_golden_gate_bridge", 1 );
  1635.             if ( isDefined( ai ) )
  1636.             {
  1637.                 ai.is_bridge_brutus = 1;
  1638.                 if ( level.n_bridge_brutuses_killed == 0 )
  1639.                 {
  1640.                     ai thread suppress_brutus_bridge_powerups();
  1641.                 }
  1642.             }
  1643.             wait randomfloatrange( 1, 4 );
  1644.             i--;
  1645.  
  1646.         }
  1647.         level waittill( "start_of_round" );
  1648.         n_round_on_bridge++;
  1649.     }
  1650. }
  1651.  
  1652. last_brutus_on_bridge()
  1653. {
  1654.     level endon( "bridge_empty" );
  1655.     e_gg_zone = getent( "zone_golden_gate_bridge", "targetname" );
  1656.     a_bridge_brutuses = [];
  1657.     while ( 1 )
  1658.     {
  1659.         a_bridge_brutuses = get_bridge_brutuses();
  1660.         if ( a_bridge_brutuses.size > 1 )
  1661.         {
  1662.             _a2012 = a_bridge_brutuses;
  1663.             _k2012 = getFirstArrayKey( _a2012 );
  1664.             while ( isDefined( _k2012 ) )
  1665.             {
  1666.                 brutus = _a2012[ _k2012 ];
  1667.                 if ( isDefined( brutus ) )
  1668.                 {
  1669.                     brutus.suppress_teargas_behavior = 1;
  1670.                 }
  1671.                 _k2012 = getNextArrayKey( _a2012, _k2012 );
  1672.             }
  1673.         }
  1674.         else if ( a_bridge_brutuses.size == 1 )
  1675.         {
  1676.             a_bridge_brutuses[ 0 ].suppress_teargas_behavior = 0;
  1677.         }
  1678.         wait 0,05;
  1679.     }
  1680. }
  1681.  
  1682. suppress_brutus_bridge_powerups()
  1683. {
  1684.     self endon( "brutus_teleporting" );
  1685.     level endon( "bridge_empty" );
  1686.     level endon( "first_bridge_brutus_killed" );
  1687.     self waittill( "death" );
  1688.     level.n_bridge_brutuses_killed++;
  1689.     if ( level.n_bridge_brutuses_killed >= 1 )
  1690.     {
  1691.         level.global_brutus_powerup_prevention = 1;
  1692.         level thread allow_brutus_powerup_spawning();
  1693.         level notify( "first_bridge_brutus_killed" );
  1694.     }
  1695. }
  1696.  
  1697. allow_brutus_powerup_spawning()
  1698. {
  1699.     level notify( "only_one_powerup_thread" );
  1700.     level endon( "only_one_powerup_thread" );
  1701.     level waittill( "bridge_empty" );
  1702.     level.global_brutus_powerup_prevention = 0;
  1703. }
  1704.  
  1705. get_bridge_brutuses()
  1706. {
  1707.     e_gg_zone = getent( "zone_golden_gate_bridge", "targetname" );
  1708.     a_bridge_brutuses = [];
  1709.     zombies = getaispeciesarray( "axis", "all" );
  1710.     i = 0;
  1711.     while ( i < zombies.size )
  1712.     {
  1713.         if ( isDefined( zombies[ i ].is_brutus ) && zombies[ i ].is_brutus )
  1714.         {
  1715.             brutus = zombies[ i ];
  1716.             if ( brutus istouching( e_gg_zone ) )
  1717.             {
  1718.                 brutus.is_bridge_brutus = 1;
  1719.                 a_bridge_brutuses[ a_bridge_brutuses.size ] = brutus;
  1720.             }
  1721.         }
  1722.         i++;
  1723.     }
  1724.     return a_bridge_brutuses;
  1725. }
  1726.  
  1727. brutus_despawn_manager()
  1728. {
  1729.     level notify( "brutus_despawn_manager" );
  1730.     level endon( "brutus_despawn_manager" );
  1731.     level endon( "bridge_empty" );
  1732.     e_gg_zone = getent( "zone_golden_gate_bridge", "targetname" );
  1733.     while ( 1 )
  1734.     {
  1735.         b_is_time_to_despawn = 0;
  1736.         while ( !b_is_time_to_despawn )
  1737.         {
  1738.             b_is_time_to_despawn = 1;
  1739.             players = getplayers();
  1740.             _a2098 = players;
  1741.             _k2098 = getFirstArrayKey( _a2098 );
  1742.             while ( isDefined( _k2098 ) )
  1743.             {
  1744.                 player = _a2098[ _k2098 ];
  1745.                 if ( isDefined( player ) && player istouching( e_gg_zone ) && !player.afterlife && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() )
  1746.                 {
  1747.                     b_is_time_to_despawn = 0;
  1748.                 }
  1749.                 _k2098 = getNextArrayKey( _a2098, _k2098 );
  1750.             }
  1751.             wait 0,1;
  1752.         }
  1753.         zombies = getaispeciesarray( "axis", "all" );
  1754.         i = 0;
  1755.         while ( i < zombies.size )
  1756.         {
  1757.             if ( isDefined( zombies[ i ].is_brutus ) && zombies[ i ].is_brutus && isDefined( zombies[ i ].is_bridge_brutus ) && zombies[ i ].is_bridge_brutus )
  1758.             {
  1759.                 level thread brutus_temp_despawn( zombies[ i ], "bridge_empty", "bring_bridge_brutuses_back" );
  1760.             }
  1761.             i++;
  1762.         }
  1763.         b_is_time_to_bring_back = 0;
  1764.         while ( !b_is_time_to_bring_back )
  1765.         {
  1766.             b_is_time_to_bring_back = 0;
  1767.             players = getplayers();
  1768.             _a2125 = players;
  1769.             _k2125 = getFirstArrayKey( _a2125 );
  1770.             while ( isDefined( _k2125 ) )
  1771.             {
  1772.                 player = _a2125[ _k2125 ];
  1773.                 if ( isDefined( player ) && player istouching( e_gg_zone ) && !player.afterlife && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() )
  1774.                 {
  1775.                     b_is_time_to_bring_back = 1;
  1776.                 }
  1777.                 _k2125 = getNextArrayKey( _a2125, _k2125 );
  1778.             }
  1779.             wait 0,1;
  1780.         }
  1781.         level notify( "bring_bridge_brutuses_back" );
  1782.     }
  1783. }
  1784.  
  1785. get_bridge_brutus_count()
  1786. {
  1787.     n_touching_count = 0;
  1788.     e_gg_zone = getent( "zone_golden_gate_bridge", "targetname" );
  1789.     zombies = getaispeciesarray( "axis", "all" );
  1790.     i = 0;
  1791.     while ( i < zombies.size )
  1792.     {
  1793.         if ( isDefined( zombies[ i ].is_brutus ) && zombies[ i ].is_brutus )
  1794.         {
  1795.             brutus = zombies[ i ];
  1796.             if ( brutus istouching( e_gg_zone ) )
  1797.             {
  1798.                 n_touching_count++;
  1799.             }
  1800.         }
  1801.         i++;
  1802.     }
  1803.     return n_touching_count;
  1804. }
  1805.  
  1806. clean_up_bridge_brutuses()
  1807. {
  1808.     zombies = getaispeciesarray( "axis", "all" );
  1809.     i = 0;
  1810.     while ( i < zombies.size )
  1811.     {
  1812.         if ( isDefined( zombies[ i ].is_brutus ) && zombies[ i ].is_brutus && isDefined( zombies[ i ].is_bridge_brutus ) && zombies[ i ].is_bridge_brutus )
  1813.         {
  1814.             brutus = zombies[ i ];
  1815.             brutus dodamage( 10000, brutus.origin );
  1816.         }
  1817.         i++;
  1818.     }
  1819. }
  1820.  
  1821. spin_while_falling()
  1822. {
  1823.     self endon( "movedone" );
  1824.     while ( 1 )
  1825.     {
  1826.         self.angles += vectorScale( ( 0, 0, 0 ), 4 );
  1827.         wait 0,05;
  1828.     }
  1829. }
  1830.  
  1831. manage_electric_chairs()
  1832. {
  1833.     level notify( "manage_electric_chairs" );
  1834.     level endon( "manage_electric_chairs" );
  1835.     n_chairs_wait = 60;
  1836.     while ( 1 )
  1837.     {
  1838.         flag_wait( "plane_approach_bridge" );
  1839.         i = 1;
  1840.         while ( i < 5 )
  1841.         {
  1842.             str_trigger_targetname = "trigger_electric_chair_" + i;
  1843.             t_electric_chair = getent( str_trigger_targetname, "targetname" );
  1844.             if ( isDefined( level.electric_chair_trigger_thread_custom_func ) )
  1845.             {
  1846.                 t_electric_chair thread [[ level.electric_chair_trigger_thread_custom_func ]]( i );
  1847.             }
  1848.             else
  1849.             {
  1850.                 t_electric_chair thread electric_chair_trigger_thread( i );
  1851.             }
  1852.             t_electric_chair setcursorhint( "HINT_NOICON" );
  1853.             t_electric_chair sethintstring( &"ZM_PRISON_ELECTRIC_CHAIR_ACTIVATE" );
  1854.             t_electric_chair usetriggerrequirelookat();
  1855.             i++;
  1856.         }
  1857.         if ( level.final_flight_activated )
  1858.         {
  1859.             level.revive_trigger_should_ignore_sight_checks = ::maps/mp/zm_prison_sq_final::revive_trigger_should_ignore_sight_checks;
  1860.             j = 0;
  1861.             while ( j < level.final_flight_players.size )
  1862.             {
  1863.                 m_electric_chair = getent( "electric_chair_" + ( j + 1 ), "targetname" );
  1864.                 corpse = level.final_flight_players[ j ].e_afterlife_corpse;
  1865.                 corpse linkto( m_electric_chair, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );
  1866.                 corpse maps/mp/zombies/_zm_clone::clone_animate( "chair" );
  1867.                 wait 1;
  1868.                 corpse.revivetrigger unlink();
  1869.                 corpse.revivetrigger.origin = m_electric_chair.origin + ( 64, 0, 32 );
  1870. /#
  1871.                 corpse.revivetrigger thread print3d_ent( "revivetrigger" );
  1872. #/
  1873.                 j++;
  1874.             }
  1875.             j = 1;
  1876.             while ( j < 5 )
  1877.             {
  1878.                 str_trigger_targetname = "trigger_electric_chair_" + j;
  1879.                 t_electric_chair = getent( str_trigger_targetname, "targetname" );
  1880.                 t_electric_chair trigger_off();
  1881.                 j++;
  1882.             }
  1883.             while ( flag( "plane_approach_bridge" ) )
  1884.             {
  1885.                 wait 1;
  1886.             }
  1887.         }
  1888.         else i = 1;
  1889.         while ( i < 5 )
  1890.         {
  1891.             m_electric_chair = getent( "electric_chair_" + i, "targetname" );
  1892.             m_electric_chair hide();
  1893.             str_trigger_targetname = "trigger_electric_chair_" + i;
  1894.             t_electric_chair = getent( str_trigger_targetname, "targetname" );
  1895.             t_electric_chair trigger_off();
  1896.             i++;
  1897.         }
  1898.         flag_wait( "plane_crashed" );
  1899.         wait n_chairs_wait;
  1900.         exploder( 666 );
  1901.         i = 1;
  1902.         while ( i < 5 )
  1903.         {
  1904.             m_electric_chair = getent( "electric_chair_" + i, "targetname" );
  1905.             m_electric_chair show();
  1906.             m_electric_chair thread snddelayedchairaudio( i );
  1907.             str_trigger_targetname = "trigger_electric_chair_" + i;
  1908.             t_electric_chair = getent( str_trigger_targetname, "targetname" );
  1909.             t_electric_chair trigger_on();
  1910.             i++;
  1911.         }
  1912.         wait 3;
  1913.         electric_chair_vo();
  1914.         wait 6;
  1915.     }
  1916. }
  1917.  
  1918. snddelayedchairaudio( i )
  1919. {
  1920.     wait ( i / 10 );
  1921.     self playsound( "zmb_quest_electricchair_spawn" );
  1922. }
  1923.  
  1924. electric_chair_trigger_thread( chair_number )
  1925. {
  1926.     level notify( "electric_chair_trigger_thread_" + chair_number );
  1927.     level endon( "electric_chair_trigger_thread_" + chair_number );
  1928.     m_electric_chair = getent( "electric_chair_" + chair_number, "targetname" );
  1929.     n_effects_wait_1 = 4;
  1930.     n_effects_wait_2 = 0,15;
  1931.     n_effects_wait_3 = 2;
  1932.     n_effects_wait_4 = 2;
  1933.     n_effects_duration = n_effects_wait_1 + n_effects_wait_2 + n_effects_wait_3 + n_effects_wait_4;
  1934.     while ( 1 )
  1935.     {
  1936.         self waittill( "trigger", e_triggerer );
  1937.         character_name = e_triggerer.character_name;
  1938.         if ( isplayer( e_triggerer ) && !e_triggerer.afterlife )
  1939.         {
  1940.             e_triggerer enableinvulnerability();
  1941.             self sethintstring( "" );
  1942.             self trigger_off();
  1943.             flag_set( "plane_trip_to_nml_successful" );
  1944.             if ( level.characters_in_nml.size == 1 )
  1945.             {
  1946.                 clean_up_bridge_brutuses();
  1947.             }
  1948.             v_origin = m_electric_chair gettagorigin( "seated" ) + ( 10, 0, -40 );
  1949.             v_seated_angles = m_electric_chair gettagangles( "seated" );
  1950.             m_linkpoint = spawn_model( "tag_origin", v_origin, v_seated_angles );
  1951.             if ( isDefined( level.electric_chair_player_thread_custom_func ) )
  1952.             {
  1953.                 e_triggerer thread [[ level.electric_chair_player_thread_custom_func ]]( m_linkpoint, chair_number, n_effects_duration );
  1954.             }
  1955.             else
  1956.             {
  1957.                 e_triggerer thread electric_chair_player_thread( m_linkpoint, chair_number, n_effects_duration );
  1958.             }
  1959.             chair_corpse = e_triggerer maps/mp/zombies/_zm_clone::spawn_player_clone( e_triggerer, e_triggerer.origin, undefined );
  1960.             chair_corpse linkto( m_electric_chair, "tag_origin", ( 0, 0, 0 ), ( 0, 0, 0 ) );
  1961.             chair_corpse.ignoreme = 1;
  1962.             chair_corpse show();
  1963.             chair_corpse detachall();
  1964.             chair_corpse setvisibletoall();
  1965.             chair_corpse setinvisibletoplayer( e_triggerer );
  1966.             chair_corpse maps/mp/zombies/_zm_clone::clone_animate( "chair" );
  1967.             if ( isDefined( e_triggerer ) )
  1968.             {
  1969.                 e_triggerer setclientfieldtoplayer( "rumble_electric_chair", 1 );
  1970.             }
  1971.             wait n_effects_wait_1;
  1972.             m_fx_1 = spawn_model( "tag_origin", ( -516,883, -3912,04, -7494,9 ), vectorScale( ( 0, 0, 0 ), 180 ) );
  1973.             m_fx_2 = spawn_model( "tag_origin", ( -517,024, -3252,66, -7496,2 ), ( 0, 0, 0 ) );
  1974.             level setclientfield( "scripted_lightning_flash", 1 );
  1975.             wait n_effects_wait_2;
  1976.             playfxontag( level._effect[ "fx_alcatraz_lightning_finale" ], m_fx_1, "tag_origin" );
  1977.             playfxontag( level._effect[ "fx_alcatraz_lightning_finale" ], m_fx_2, "tag_origin" );
  1978.             m_fx_3 = spawn_model( "tag_origin", ( -753,495, -3092,62, -8416,6 ), vectorScale( ( 0, 0, 0 ), 270 ) );
  1979.             playfxontag( level._effect[ "fx_alcatraz_lightning_wire" ], m_fx_3, "tag_origin" );
  1980.             wait n_effects_wait_3;
  1981.             m_electric_chair play_fx( "fx_alcatraz_elec_chair", m_electric_chair.origin, m_electric_chair.angles, "bridge_empty" );
  1982.             if ( isDefined( e_triggerer ) )
  1983.             {
  1984.                 e_triggerer setclientfieldtoplayer( "rumble_electric_chair", 2 );
  1985.             }
  1986.             wait n_effects_wait_4;
  1987.             playfxontag( level._effect[ "fx_alcatraz_afterlife_zmb_tport" ], m_electric_chair, "tag_origin" );
  1988.             if ( isDefined( e_triggerer ) )
  1989.             {
  1990.                 e_triggerer playsoundtoplayer( "zmb_afterlife_death", e_triggerer );
  1991.             }
  1992.             chair_corpse delete();
  1993.             if ( level.characters_in_nml.size == 1 )
  1994.             {
  1995.                 clean_up_bridge_brutuses();
  1996.             }
  1997.             if ( isinarray( level.characters_in_nml, character_name ) )
  1998.             {
  1999.                 arrayremovevalue( level.characters_in_nml, character_name );
  2000.             }
  2001.             m_fx_1 delete();
  2002.             m_fx_2 delete();
  2003.             self sethintstring( &"ZM_PRISON_ELECTRIC_CHAIR_ACTIVATE" );
  2004.             self trigger_on();
  2005.         }
  2006.     }
  2007. }
  2008.  
  2009. electric_chair_player_thread( m_linkpoint, chair_number, n_effects_duration )
  2010. {
  2011.     self endon( "death_or_disconnect" );
  2012.     e_home_telepoint = getstruct( "home_telepoint_" + chair_number, "targetname" );
  2013.     e_corpse_location = getstruct( "corpse_starting_point_" + chair_number, "targetname" );
  2014.     self disableweapons();
  2015.     self enableinvulnerability();
  2016.     self setstance( "stand" );
  2017.     self playerlinktodelta( m_linkpoint, "tag_origin", 1, 20, 20, 20, 20 );
  2018.     self setplayerangles( m_linkpoint.angles );
  2019.     self playsoundtoplayer( "zmb_electric_chair_2d", self );
  2020.     self do_player_general_vox( "quest", "chair_electrocution", undefined, 100 );
  2021.     self ghost();
  2022.     self.ignoreme = 1;
  2023.     self.dontspeak = 1;
  2024.     self setclientfieldtoplayer( "isspeaking", 1 );
  2025.     wait ( n_effects_duration - 2 );
  2026.     switch( self.character_name )
  2027.     {
  2028.         case "Arlington":
  2029.             self playsoundontag( "vox_plr_3_arlington_electrocution_0", "J_Head" );
  2030.             break;
  2031.         case "Sal":
  2032.             self playsoundontag( "vox_plr_1_sal_electrocution_0", "J_Head" );
  2033.             break;
  2034.         case "Billy":
  2035.             self playsoundontag( "vox_plr_2_billy_electrocution_0", "J_Head" );
  2036.             break;
  2037.         case "Finn":
  2038.             self playsoundontag( "vox_plr_0_finn_electrocution_0", "J_Head" );
  2039.             break;
  2040.     }
  2041.     wait 2;
  2042.     level.zones[ "zone_golden_gate_bridge" ].is_enabled = 1;
  2043.     level.zones[ "zone_golden_gate_bridge" ].is_spawning_allowed = 1;
  2044.     self.keep_perks = 1;
  2045.     self disableinvulnerability();
  2046.     self.afterlife = 1;
  2047.     self thread afterlife_laststand( 1 );
  2048.     self unlink();
  2049.     self setstance( "stand" );
  2050.     self waittill( "player_fake_corpse_created" );
  2051.     self thread track_player_completed_cycle();
  2052.     trace_start = e_corpse_location.origin + vectorScale( ( 0, 0, 0 ), 100 );
  2053.     trace_end = e_corpse_location.origin + vectorScale( ( 0, 0, 0 ), 100 );
  2054.     corpse_trace = bullettrace( trace_start, trace_end, 0, self.e_afterlife_corpse );
  2055.     self.e_afterlife_corpse.origin = corpse_trace[ "position" ];
  2056.     self setorigin( e_home_telepoint.origin );
  2057.     self enableweapons();
  2058.     self setclientfieldtoplayer( "rumble_electric_chair", 0 );
  2059.     if ( level.n_quest_iteration_count == 2 )
  2060.     {
  2061.         self waittill( "player_revived" );
  2062.         wait 1;
  2063.         self do_player_general_vox( "quest", "start_2", undefined, 100 );
  2064.     }
  2065. }
  2066.  
  2067. track_player_completed_cycle()
  2068. {
  2069.     self endon( "disconnect" );
  2070.     self.e_afterlife_corpse waittill( "death" );
  2071.     self notify( "player_completed_cycle" );
  2072.     level notify( "someone_completed_quest_cycle" );
  2073. }
  2074.  
  2075. reset_plane_hint_string( player )
  2076. {
  2077.     if ( isDefined( self.stub ) )
  2078.     {
  2079. /#
  2080.         println( "Error: This should have been handled by the craftables callback" );
  2081. #/
  2082.     }
  2083.     else
  2084.     {
  2085.         self.fly_trigger sethintstring( &"ZM_PRISON_PLANE_BEGIN_TAKEOFF" );
  2086.     }
  2087. }
  2088.  
  2089. play_fx( str_fx, v_origin, v_angles, time_to_delete_or_notify, b_link_to_self, str_tag, b_no_cull )
  2090. {
  2091.     if ( isDefined( time_to_delete_or_notify ) && !isstring( time_to_delete_or_notify ) && time_to_delete_or_notify == -1 && isDefined( b_link_to_self ) && b_link_to_self && isDefined( str_tag ) )
  2092.     {
  2093.         playfxontag( getfx( str_fx ), self, str_tag );
  2094.         return self;
  2095.     }
  2096.     else
  2097.     {
  2098.         m_fx = spawn_model( "tag_origin", v_origin, v_angles );
  2099.         if ( isDefined( b_link_to_self ) && b_link_to_self )
  2100.         {
  2101.             if ( isDefined( str_tag ) )
  2102.             {
  2103.                 m_fx linkto( self, str_tag, ( 0, 0, 0 ), ( 0, 0, 0 ) );
  2104.             }
  2105.             else
  2106.             {
  2107.                 m_fx linkto( self );
  2108.             }
  2109.         }
  2110.         if ( isDefined( b_no_cull ) && b_no_cull )
  2111.         {
  2112.             m_fx setforcenocull();
  2113.         }
  2114.         playfxontag( getfx( str_fx ), m_fx, "tag_origin" );
  2115.         m_fx thread _play_fx_delete( self, time_to_delete_or_notify );
  2116.         return m_fx;
  2117.     }
  2118. }
  2119.  
  2120. spawn_model( model_name, origin, angles, n_spawnflags )
  2121. {
  2122.     if ( !isDefined( n_spawnflags ) )
  2123.     {
  2124.         n_spawnflags = 0;
  2125.     }
  2126.     if ( !isDefined( origin ) )
  2127.     {
  2128.         origin = ( 0, 0, 0 );
  2129.     }
  2130.     model = spawn( "script_model", origin, n_spawnflags );
  2131.     model setmodel( model_name );
  2132.     if ( isDefined( angles ) )
  2133.     {
  2134.         model.angles = angles;
  2135.     }
  2136.     return model;
  2137. }
  2138.  
  2139. getfx( fx )
  2140. {
  2141. /#
  2142.     assert( isDefined( level._effect[ fx ] ), "Fx " + fx + " is not defined in level._effect." );
  2143. #/
  2144.     return level._effect[ fx ];
  2145. }
  2146.  
  2147. _play_fx_delete( ent, time_to_delete_or_notify )
  2148. {
  2149.     if ( !isDefined( time_to_delete_or_notify ) )
  2150.     {
  2151.         time_to_delete_or_notify = -1;
  2152.     }
  2153.     if ( isstring( time_to_delete_or_notify ) )
  2154.     {
  2155.         ent waittill_either( "death", time_to_delete_or_notify );
  2156.     }
  2157.     else if ( time_to_delete_or_notify > 0 )
  2158.     {
  2159.         ent waittill_notify_or_timeout( "death", time_to_delete_or_notify );
  2160.     }
  2161.     else
  2162.     {
  2163.         ent waittill( "death" );
  2164.     }
  2165.     if ( isDefined( self ) )
  2166.     {
  2167.         self delete();
  2168.     }
  2169. }
  2170.  
  2171. player_disconnect_watcher()
  2172. {
  2173.     if ( isDefined( level.player_disconnect_watcher_custom_func ) )
  2174.     {
  2175.         self thread [[ level.player_disconnect_watcher_custom_func ]]();
  2176.         return;
  2177.     }
  2178.     self notify( "disconnect_watcher" );
  2179.     self endon( "disconnect_watcher" );
  2180.     level endon( "bridge_empty" );
  2181. /#
  2182.     iprintlnbold( "player_disconnect_watcher" );
  2183. #/
  2184.     if ( !isDefined( self.character_name ) )
  2185.     {
  2186.         wait 0,1;
  2187.     }
  2188.     character_name = self.character_name;
  2189.     self waittill( "disconnect" );
  2190. /#
  2191.     iprintlnbold( character_name + " disconnected!" );
  2192. #/
  2193.     if ( isinarray( level.characters_in_nml, character_name ) )
  2194.     {
  2195.         arrayremovevalue( level.characters_in_nml, character_name );
  2196.         flag_set( "spawn_zombies" );
  2197.         level.brutus_respawn_after_despawn = 1;
  2198.     }
  2199. }
  2200.  
  2201. player_death_watcher()
  2202. {
  2203.     if ( isDefined( level.player_death_watcher_custom_func ) )
  2204.     {
  2205.         self thread [[ level.player_death_watcher_custom_func ]]();
  2206.         return;
  2207.     }
  2208.     self notify( "player_death_watcher" );
  2209.     self endon( "player_death_watcher" );
  2210.     level endon( "bridge_empty" );
  2211. /#
  2212.     iprintlnbold( "player_death_watcher" );
  2213. #/
  2214.     e_gg_zone = getent( "zone_golden_gate_bridge", "targetname" );
  2215.     nml_trip_is_over = 0;
  2216.     while ( !nml_trip_is_over )
  2217.     {
  2218.         level waittill( "start_of_round" );
  2219.         nml_trip_is_over = 1;
  2220.         players = getplayers();
  2221.         _a2671 = players;
  2222.         _k2671 = getFirstArrayKey( _a2671 );
  2223.         while ( isDefined( _k2671 ) )
  2224.         {
  2225.             player = _a2671[ _k2671 ];
  2226.             if ( player istouching( e_gg_zone ) || isDefined( player.on_a_plane ) && player.on_a_plane )
  2227.             {
  2228.                 nml_trip_is_over = 0;
  2229.                 if ( !isinarray( level.characters_in_nml, player.character_name ) )
  2230.                 {
  2231.                     level.characters_in_nml[ level.characters_in_nml.size ] = player.character_name;
  2232.                 }
  2233.             }
  2234.             _k2671 = getNextArrayKey( _a2671, _k2671 );
  2235.         }
  2236.     }
  2237.     while ( isDefined( level.characters_in_nml ) )
  2238.     {
  2239.         i = 0;
  2240.         while ( i < level.characters_in_nml.size )
  2241.         {
  2242.             character_name = level.characters_in_nml[ i ];
  2243.             if ( isinarray( level.characters_in_nml, character_name ) )
  2244.             {
  2245.                 arrayremovevalue( level.characters_in_nml, character_name );
  2246.             }
  2247.             i++;
  2248.         }
  2249.     }
  2250.     flag_set( "spawn_zombies" );
  2251.     level.brutus_respawn_after_despawn = 1;
  2252. }
  2253.  
  2254. array_set_visible_to_all( a_ents, is_visible )
  2255. {
  2256.     if ( is_visible )
  2257.     {
  2258.         _a2707 = a_ents;
  2259.         _k2707 = getFirstArrayKey( _a2707 );
  2260.         while ( isDefined( _k2707 ) )
  2261.         {
  2262.             ent = _a2707[ _k2707 ];
  2263.             ent setvisibletoall();
  2264.             _k2707 = getNextArrayKey( _a2707, _k2707 );
  2265.         }
  2266.     }
  2267.     else _a2714 = a_ents;
  2268.     _k2714 = getFirstArrayKey( _a2714 );
  2269.     while ( isDefined( _k2714 ) )
  2270.     {
  2271.         ent = _a2714[ _k2714 ];
  2272.         ent setinvisibletoall();
  2273.         _k2714 = getNextArrayKey( _a2714, _k2714 );
  2274.     }
  2275. }
  2276.  
  2277. warden_fence_hotjoin_handler()
  2278. {
  2279.     while ( 1 )
  2280.     {
  2281.         level waittill( "warden_fence_up" );
  2282.         stop_exploder( 2000 );
  2283.         exploder( 2000 );
  2284.         wait 0,05;
  2285.     }
  2286. }
Advertisement
Add Comment
Please, Sign In to add comment