burc_2004

_zm_ai_ghost.gsc

Oct 22nd, 2015
292
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 78.37 KB | None | 0 0
  1. #include maps/mp/zombies/_zm_powerups;
  2. #include maps/mp/zombies/_zm_weap_time_bomb;
  3. #include maps/mp/zombies/_zm_laststand;
  4. #include maps/mp/zombies/_zm_score;
  5. #include maps/mp/zombies/_zm_stats;
  6. #include maps/mp/animscripts/zm_shared;
  7. #include maps/mp/zombies/_zm_weap_slowgun;
  8. #include maps/mp/zombies/_zm_spawner;
  9. #include maps/mp/zombies/_zm_ai_ghost;
  10. #include maps/mp/zombies/_zm_ai_ghost_ffotd;
  11. #include maps/mp/animscripts/zm_utility;
  12. #include maps/mp/zombies/_zm_utility;
  13. #include maps/mp/_utility;
  14. #include common_scripts/utility;
  15.  
  16. #using_animtree( "zm_buried_ghost" );
  17.  
  18. precache()
  19. {
  20. }
  21.  
  22. init_animtree()
  23. {
  24.     scriptmodelsuseanimtree( -1 );
  25. }
  26.  
  27. precache_fx()
  28. {
  29.     if ( !isDefined( level.ghost_effects ) )
  30.     {
  31.         level.ghost_effects = [];
  32.         level.ghost_effects[ 1 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_death" );
  33.         level.ghost_effects[ 2 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_drain" );
  34.         level.ghost_effects[ 3 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_spawn" );
  35.         level.ghost_effects[ 4 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_trail" );
  36.         level.ghost_effects[ 5 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_evaporation" );
  37.         level.ghost_impact_effects[ 1 ] = loadfx( "maps/zombie_buried/fx_buried_ghost_impact" );
  38.     }
  39. }
  40.  
  41. init()
  42. {
  43.     maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_init_start();
  44.     register_client_fields();
  45.     flag_init( "spawn_ghosts" );
  46.     if ( !init_ghost_spawners() )
  47.     {
  48.         return;
  49.     }
  50.     init_ghost_zone();
  51.     init_ghost_sounds();
  52.     init_ghost_script_move_path_data();
  53.     level.zombie_ai_limit_ghost = 4;
  54.     level.zombie_ai_limit_ghost_per_player = 1;
  55.     level.zombie_ghost_count = 0;
  56.     level.ghost_health = 100;
  57.     level.zombie_ghost_round_states = spawnstruct();
  58.     level.zombie_ghost_round_states.any_player_in_ghost_zone = 0;
  59.     level.zombie_ghost_round_states.active_zombie_locations = [];
  60.     level.is_ghost_round_started = ::is_ghost_round_started;
  61.     level.zombie_ghost_round_states.is_started = 0;
  62.     level.zombie_ghost_round_states.is_first_ghost_round_finished = 0;
  63.     level.zombie_ghost_round_states.current_ghost_round_number = 0;
  64.     level.zombie_ghost_round_states.next_ghost_round_number = 0;
  65.     level.zombie_ghost_round_states.presentation_stage_1_started = 0;
  66.     level.zombie_ghost_round_states.presentation_stage_2_started = 0;
  67.     level.zombie_ghost_round_states.presentation_stage_3_started = 0;
  68.     level.zombie_ghost_round_states.is_teleporting = 0;
  69.     level.zombie_ghost_round_states.round_count = 0;
  70.     level thread ghost_round_presentation_think();
  71.     if ( isDefined( level.ghost_round_think_override_func ) )
  72.     {
  73.         level thread [[ level.ghost_round_think_override_func ]]();
  74.     }
  75.     else
  76.     {
  77.         level thread ghost_round_think();
  78.     }
  79.     level thread player_in_ghost_zone_monitor();
  80.     if ( isDefined( level.ghost_zone_spawning_think_override_func ) )
  81.     {
  82.         level thread [[ level.ghost_zone_spawning_think_override_func ]]();
  83.     }
  84.     else
  85.     {
  86.         level thread ghost_zone_spawning_think();
  87.     }
  88.     level thread ghost_vox_think();
  89.     init_time_bomb_ghost_rounds();
  90. /#
  91.     level.force_no_ghost = 0;
  92.     level.ghost_devgui_toggle_no_ghost = ::devgui_toggle_no_ghost;
  93.     level.ghost_devgui_warp_to_mansion = ::devgui_warp_to_mansion;
  94. #/
  95.     maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_init_end();
  96. }
  97.  
  98. init_ghost_spawners()
  99. {
  100.     level.ghost_spawners = getentarray( "ghost_zombie_spawner", "script_noteworthy" );
  101.     if ( level.ghost_spawners.size == 0 )
  102.     {
  103.         return 0;
  104.     }
  105.     array_thread( level.ghost_spawners, ::add_spawn_function, ::prespawn );
  106.     _a131 = level.ghost_spawners;
  107.     _k131 = getFirstArrayKey( _a131 );
  108.     while ( isDefined( _k131 ) )
  109.     {
  110.         spawner = _a131[ _k131 ];
  111.         if ( spawner.targetname == "female_ghost" )
  112.         {
  113.             level.female_ghost_spawner = spawner;
  114.         }
  115.         _k131 = getNextArrayKey( _a131, _k131 );
  116.     }
  117.     return 1;
  118. }
  119.  
  120. init_ghost_script_move_path_data()
  121. {
  122.     level.ghost_script_move_sin = [];
  123.     degree = 0;
  124.     while ( degree < 360 )
  125.     {
  126.         level.ghost_script_move_sin[ level.ghost_script_move_sin.size ] = sin( degree );
  127.         degree += 15;
  128.     }
  129. }
  130.  
  131. init_ghost_sounds()
  132. {
  133.     level.ghost_vox = [];
  134.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_0";
  135.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_1";
  136.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_2";
  137.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_3";
  138.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_4";
  139.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_5";
  140.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_6";
  141.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_7";
  142.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_8";
  143.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_9";
  144.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_10";
  145.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_11";
  146.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_12";
  147.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_13";
  148.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_14";
  149.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_15";
  150.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_16";
  151.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_17";
  152.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_18";
  153.     level.ghost_vox[ level.ghost_vox.size ] = "vox_fg_ghost_haunt_19";
  154. }
  155.  
  156. init_ghost_zone()
  157. {
  158.     level.ghost_start_area = getent( "ghost_start_area", "targetname" );
  159.     level.ghost_zone_door_clips = getentarray( "ghost_zone_door_clip", "targetname" );
  160.     enable_ghost_zone_door_ai_clips();
  161.     level.ghost_zone_start_lower_locations = getstructarray( "ghost_zone_start_lower_location", "targetname" );
  162.     level.ghost_drop_down_locations = getstructarray( "ghost_start_zone_spawners", "targetname" );
  163.     level.ghost_front_standing_locations = getstructarray( "ghost_front_standing_location", "targetname" );
  164.     level.ghost_back_standing_locations = getstructarray( "ghost_back_standing_location", "targetname" );
  165.     level.ghost_front_flying_out_path_starts = getstructarray( "ghost_front_flying_out_path_start", "targetname" );
  166.     level.ghost_back_flying_out_path_starts = getstructarray( "ghost_back_flying_out_path_start", "targetname" );
  167.     level.ghost_gazebo_pit_volume = getent( "sloth_pack_volume", "targetname" );
  168.     level.ghost_gazebo_pit_perk_pos = getstruct( "ghost_gazebo_pit_perk_pos", "targetname" );
  169.     level.ghost_entry_room_to_mansion = "ghost_to_maze_zone_1";
  170.     level.ghost_entry_room_to_maze = "ghost_to_maze_zone_5";
  171.     level.ghost_rooms = [];
  172.     a_rooms = getentarray( "ghost_zone", "script_noteworthy" );
  173.     _a216 = a_rooms;
  174.     _k216 = getFirstArrayKey( _a216 );
  175.     while ( isDefined( _k216 ) )
  176.     {
  177.         room = _a216[ _k216 ];
  178.         str_targetname = room.targetname;
  179.         if ( !isDefined( level.ghost_rooms[ str_targetname ] ) )
  180.         {
  181.             level.ghost_rooms[ str_targetname ] = spawnstruct();
  182.             level.ghost_rooms[ str_targetname ].ghost_spawn_locations = [];
  183.             level.ghost_rooms[ str_targetname ].volumes = [];
  184.             level.ghost_rooms[ str_targetname ].name = str_targetname;
  185.             if ( issubstr( str_targetname, "from_maze" ) )
  186.             {
  187.                 level.ghost_rooms[ str_targetname ].from_maze = 1;
  188.                 break;
  189.             }
  190.             else
  191.             {
  192.                 if ( issubstr( str_targetname, "to_maze" ) )
  193.                 {
  194.                     level.ghost_rooms[ str_targetname ].to_maze = 1;
  195.                 }
  196.             }
  197.         }
  198. /#
  199.         assert( isDefined( room.target ), "ghost zone with targetname '" + str_targetname + "' is missing spawner target! This is used to pair zones with spawners." );
  200. #/
  201.         a_ghost_spawn_locations = getstructarray( room.target, "targetname" );
  202.         level.ghost_rooms[ str_targetname ].ghost_spawn_locations = arraycombine( a_ghost_spawn_locations, level.ghost_rooms[ str_targetname ].ghost_spawn_locations, 0, 0 );
  203.         level.ghost_rooms[ str_targetname ].volumes[ level.ghost_rooms[ str_targetname ].volumes.size ] = room;
  204.         if ( isDefined( room.script_string ) )
  205.         {
  206.             level.ghost_rooms[ str_targetname ].next_room_names = strtok( room.script_string, " " );
  207.         }
  208.         if ( isDefined( room.script_parameters ) )
  209.         {
  210.             level.ghost_rooms[ str_targetname ].previous_room_names = strtok( room.script_parameters, " " );
  211.         }
  212.         if ( isDefined( room.script_flag ) )
  213.         {
  214.             level.ghost_rooms[ str_targetname ].flag = room.script_flag;
  215.         }
  216.         _k216 = getNextArrayKey( _a216, _k216 );
  217.     }
  218. }
  219.  
  220. register_client_fields()
  221. {
  222.     registerclientfield( "actor", "ghost_impact_fx", 12000, 1, "int" );
  223.     registerclientfield( "actor", "ghost_fx", 12000, 3, "int" );
  224.     registerclientfield( "actor", "sndGhostAudio", 12000, 3, "int" );
  225.     registerclientfield( "scriptmover", "ghost_fx", 12000, 3, "int" );
  226.     registerclientfield( "scriptmover", "sndGhostAudio", 12000, 3, "int" );
  227.     registerclientfield( "world", "ghost_round_light_state", 12000, 1, "int" );
  228. }
  229.  
  230. is_player_fully_claimed( player )
  231. {
  232.     result = 0;
  233.     if ( isDefined( player.ghost_count ) && player.ghost_count >= level.zombie_ai_limit_ghost_per_player )
  234.     {
  235.         result = 1;
  236.     }
  237.     return result;
  238. }
  239.  
  240. ghost_zone_spawning_think()
  241. {
  242.     level endon( "intermission" );
  243.     if ( isDefined( level.intermission ) && level.intermission )
  244.     {
  245.         return;
  246.     }
  247.     if ( !isDefined( level.female_ghost_spawner ) )
  248.     {
  249. /#
  250.         assertmsg( "No female ghost spawner in the map.  Check to see if the zone is active and if it's pointing to spawners." );
  251. #/
  252.         return;
  253.     }
  254.     while ( 1 )
  255.     {
  256.         while ( level.zombie_ghost_count >= level.zombie_ai_limit_ghost )
  257.         {
  258.             wait 0,1;
  259.         }
  260.         valid_player_count = 0;
  261.         valid_players = [];
  262.         while ( valid_player_count < 1 )
  263.         {
  264.             players = getplayers();
  265.             valid_player_count = 0;
  266.             _a319 = players;
  267.             _k319 = getFirstArrayKey( _a319 );
  268.             while ( isDefined( _k319 ) )
  269.             {
  270.                 player = _a319[ _k319 ];
  271.                 if ( is_player_valid( player ) && !is_player_fully_claimed( player ) )
  272.                 {
  273.                     if ( isDefined( player.is_in_ghost_zone ) || player.is_in_ghost_zone && is_ghost_round_started() && isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone )
  274.                     {
  275.                         valid_player_count++;
  276.                         valid_players[ valid_players.size ] = player;
  277.                     }
  278.                 }
  279.                 _k319 = getNextArrayKey( _a319, _k319 );
  280.             }
  281.             wait 0,1;
  282.         }
  283.         valid_players = array_randomize( valid_players );
  284.         spawn_point = get_best_spawn_point( valid_players[ 0 ] );
  285.         while ( !isDefined( spawn_point ) )
  286.         {
  287.             wait 0,1;
  288.         }
  289. /#
  290.         while ( isDefined( level.force_no_ghost ) && level.force_no_ghost )
  291.         {
  292.             wait 0,1;
  293. #/
  294.         }
  295.         ghost_ai = undefined;
  296.         if ( isDefined( level.female_ghost_spawner ) )
  297.         {
  298.             ghost_ai = spawn_zombie( level.female_ghost_spawner, level.female_ghost_spawner.targetname, spawn_point );
  299.         }
  300.         else
  301.         {
  302. /#
  303.             assertmsg( "No female ghost spawner in the map." );
  304. #/
  305.             return;
  306.         }
  307.         if ( isDefined( ghost_ai ) )
  308.         {
  309.             ghost_ai setclientfield( "ghost_fx", 3 );
  310.             ghost_ai.spawn_point = spawn_point;
  311.             ghost_ai.is_ghost = 1;
  312.             ghost_ai.is_spawned_in_ghost_zone = 1;
  313.             ghost_ai.find_target = 1;
  314.             level.zombie_ghost_count++;
  315. /#
  316.             ghost_print( "ghost total " + level.zombie_ghost_count );
  317. #/
  318.         }
  319.         else
  320.         {
  321. /#
  322.             assertmsg( "Female ghost: failed spawn" );
  323. #/
  324.             return;
  325.         }
  326.         wait 0,1;
  327.     }
  328. }
  329.  
  330. is_player_in_ghost_room( player, room )
  331. {
  332.     _a392 = room.volumes;
  333.     _k392 = getFirstArrayKey( _a392 );
  334.     while ( isDefined( _k392 ) )
  335.     {
  336.         volume = _a392[ _k392 ];
  337.         if ( player istouching( volume ) )
  338.         {
  339.             return 1;
  340.         }
  341.         _k392 = getNextArrayKey( _a392, _k392 );
  342.     }
  343.     return 0;
  344. }
  345.  
  346. is_player_in_ghost_rooms( player, room_names )
  347. {
  348.     result = 0;
  349.     while ( isDefined( room_names ) )
  350.     {
  351.         _a408 = room_names;
  352.         _k408 = getFirstArrayKey( _a408 );
  353.         while ( isDefined( _k408 ) )
  354.         {
  355.             room_name = _a408[ _k408 ];
  356.             next_room = level.ghost_rooms[ room_name ];
  357.             if ( is_player_in_ghost_room( player, next_room ) )
  358.             {
  359.                 player.current_ghost_room_name = next_room.name;
  360.                 result = 1;
  361.                 break;
  362.             }
  363.             else
  364.             {
  365.                 _k408 = getNextArrayKey( _a408, _k408 );
  366.             }
  367.         }
  368.     }
  369.     return result;
  370. }
  371.  
  372. player_in_ghost_zone_monitor()
  373. {
  374.     level endon( "intermission" );
  375.     if ( level.intermission )
  376.     {
  377.         return;
  378.     }
  379.     while ( 1 )
  380.     {
  381.         while ( isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone )
  382.         {
  383.             players = getplayers();
  384.             _a437 = players;
  385.             _k437 = getFirstArrayKey( _a437 );
  386.             while ( isDefined( _k437 ) )
  387.             {
  388.                 player = _a437[ _k437 ];
  389.                 if ( is_player_valid( player ) && isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone )
  390.                 {
  391.                     if ( isDefined( player.current_ghost_room_name ) )
  392.                     {
  393.                         current_room = level.ghost_rooms[ player.current_ghost_room_name ];
  394. /#
  395.                         _a448 = current_room.ghost_spawn_locations;
  396.                         _k448 = getFirstArrayKey( _a448 );
  397.                         while ( isDefined( _k448 ) )
  398.                         {
  399.                             ghost_location = _a448[ _k448 ];
  400.                             draw_debug_star( ghost_location.origin, ( 1, 1, 1 ), 2 );
  401.                             _k448 = getNextArrayKey( _a448, _k448 );
  402.                         }
  403.                         _a452 = current_room.volumes;
  404.                         _k452 = getFirstArrayKey( _a452 );
  405.                         while ( isDefined( _k452 ) )
  406.                         {
  407.                             volume = _a452[ _k452 ];
  408.                             draw_debug_box( volume.origin, vectorScale( ( 1, 1, 1 ), 5 ), vectorScale( ( 1, 1, 1 ), 5 ), volume.angles[ 1 ], vectorScale( ( 1, 1, 1 ), 0,5 ), 2 );
  409.                             _k452 = getNextArrayKey( _a452, _k452 );
  410. #/
  411.                         }
  412.                         if ( is_player_in_ghost_room( player, current_room ) )
  413.                         {
  414.                             player.current_ghost_room_name = current_room.name;
  415.                             break;
  416.                         }
  417.                         else if ( is_player_in_ghost_rooms( player, current_room.next_room_names ) )
  418.                         {
  419.                             break;
  420.                         }
  421.                         else if ( is_player_in_ghost_rooms( player, current_room.previous_room_names ) )
  422.                         {
  423.                             break;
  424.                         }
  425.                         else }
  426.                     else player.current_ghost_room_name = level.ghost_entry_room_to_mansion;
  427.                 }
  428.                 _k437 = getNextArrayKey( _a437, _k437 );
  429.             }
  430.         }
  431.         wait 0,1;
  432.     }
  433. }
  434.  
  435. is_any_player_near_point( target, spawn_pos )
  436. {
  437.     players = getplayers();
  438.     _a493 = players;
  439.     _k493 = getFirstArrayKey( _a493 );
  440.     while ( isDefined( _k493 ) )
  441.     {
  442.         player = _a493[ _k493 ];
  443.         if ( target != player && is_player_valid( player ) )
  444.         {
  445.             dist_squared = distancesquared( player.origin, spawn_pos );
  446.             if ( dist_squared < ( 84 * 84 ) )
  447.             {
  448.                 return 1;
  449.             }
  450.         }
  451.         _k493 = getNextArrayKey( _a493, _k493 );
  452.     }
  453.     return 0;
  454. }
  455.  
  456. is_in_start_area()
  457. {
  458.     if ( isDefined( level.ghost_start_area ) && self istouching( level.ghost_start_area ) )
  459.     {
  460.         return 1;
  461.     }
  462.     return 0;
  463. }
  464.  
  465. get_best_spawn_point( player )
  466. {
  467.     spawn_point = undefined;
  468.     if ( isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone )
  469.     {
  470.         if ( isDefined( player.current_ghost_room_name ) )
  471.         {
  472.             min_distance_squared = 9600 * 9600;
  473.             selected_locations = [];
  474.             current_ghost_room_name = player.current_ghost_room_name;
  475.             _a530 = level.ghost_rooms[ current_ghost_room_name ].ghost_spawn_locations;
  476.             _k530 = getFirstArrayKey( _a530 );
  477.             while ( isDefined( _k530 ) )
  478.             {
  479.                 ghost_location = _a530[ _k530 ];
  480.                 player_eye_pos = player geteyeapprox();
  481.                 line_of_sight = sighttracepassed( player_eye_pos, ghost_location.origin, 0, self );
  482.                 if ( isDefined( line_of_sight ) && !line_of_sight )
  483.                 {
  484.                     if ( !self is_any_player_near_point( player, ghost_location.origin ) )
  485.                     {
  486.                         selected_locations[ selected_locations.size ] = ghost_location;
  487.                     }
  488.                 }
  489.                 _k530 = getNextArrayKey( _a530, _k530 );
  490.             }
  491.             if ( selected_locations.size > 0 )
  492.             {
  493.                 selected_location = selected_locations[ randomint( selected_locations.size ) ];
  494. /#
  495.                 draw_debug_line( player.origin, selected_location.origin, ( 1, 1, 1 ), 10, 0 );
  496. #/
  497.                 return selected_location;
  498.             }
  499.         }
  500.     }
  501.     else
  502.     {
  503.         if ( is_ghost_round_started() && isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone )
  504.         {
  505.             if ( isDefined( player.current_ghost_room_name ) && player.current_ghost_room_name == level.ghost_entry_room_to_maze )
  506.             {
  507.                 random_index = randomint( level.ghost_back_standing_locations.size );
  508.                 return level.ghost_back_standing_locations[ random_index ];
  509.             }
  510.             else
  511.             {
  512.                 if ( player is_in_start_area() )
  513.                 {
  514.                     random_index = randomint( level.ghost_zone_start_lower_locations.size );
  515.                     return level.ghost_zone_start_lower_locations[ random_index ];
  516.                 }
  517.                 else
  518.                 {
  519.                     random_index = randomint( level.ghost_front_standing_locations.size );
  520.                     return level.ghost_front_standing_locations[ random_index ];
  521.                 }
  522.             }
  523.         }
  524.     }
  525.     return undefined;
  526. }
  527.  
  528. check_players_in_ghost_zone()
  529. {
  530.     result = 0;
  531.     players = getplayers();
  532.     _a589 = players;
  533.     _k589 = getFirstArrayKey( _a589 );
  534.     while ( isDefined( _k589 ) )
  535.     {
  536.         player = _a589[ _k589 ];
  537.         if ( is_player_valid( player, 0, 1 ) && player_in_ghost_zone( player ) )
  538.         {
  539.             result = 1;
  540.         }
  541.         _k589 = getNextArrayKey( _a589, _k589 );
  542.     }
  543.     return result;
  544. }
  545.  
  546. player_in_ghost_zone( player )
  547. {
  548.     result = 0;
  549.     if ( isDefined( level.is_player_in_ghost_zone ) )
  550.     {
  551.         result = [[ level.is_player_in_ghost_zone ]]( player );
  552.     }
  553.     player.is_in_ghost_zone = result;
  554.     return result;
  555. }
  556.  
  557. ghost_vox_think()
  558. {
  559.     level endon( "end_game" );
  560.     level endon( "intermission" );
  561.     if ( isDefined( level.intermission ) && level.intermission )
  562.     {
  563.         return;
  564.     }
  565.     while ( 1 )
  566.     {
  567.         ghosts = get_current_ghosts();
  568.         while ( ghosts.size > 0 )
  569.         {
  570.             _a628 = ghosts;
  571.             _k628 = getFirstArrayKey( _a628 );
  572.             while ( isDefined( _k628 ) )
  573.             {
  574.                 ghost = _a628[ _k628 ];
  575.                 if ( isDefined( ghost.favoriteenemy ) && isDefined( ghost.favoriteenemy.ghost_talking ) && !ghost.favoriteenemy.ghost_talking )
  576.                 {
  577.                     ghost thread ghost_talk_to_target( ghost.favoriteenemy );
  578.                 }
  579.                 _k628 = getNextArrayKey( _a628, _k628 );
  580.             }
  581.         }
  582.         wait randomintrange( 2, 6 );
  583.     }
  584. }
  585.  
  586. ghost_talk_to_target( player )
  587. {
  588.     self endon( "death" );
  589.     level endon( "intermission" );
  590.     vox_index = randomint( level.ghost_vox.size );
  591.     vox_line = level.ghost_vox[ vox_index ];
  592.     self playsoundtoplayer( vox_line, player );
  593.     player.ghost_talking = 1;
  594.     wait 6;
  595.     player.ghost_talking = 0;
  596. }
  597.  
  598. prespawn()
  599. {
  600.     self endon( "death" );
  601.     level endon( "intermission" );
  602.     self maps/mp/zombies/_zm_ai_ghost_ffotd::prespawn_start();
  603.     self.startinglocation = self.origin;
  604.     self.animname = "ghost_zombie";
  605.     self.audio_type = "ghost";
  606.     self.has_legs = 1;
  607.     self.no_gib = 1;
  608.     self.ignore_enemy_count = 1;
  609.     self.ignore_equipment = 1;
  610.     self.ignore_claymore = 0;
  611.     self.force_killable_timer = 0;
  612.     self.noplayermeleeblood = 1;
  613.     self.paralyzer_hit_callback = ::paralyzer_callback;
  614.     self.paralyzer_slowtime = 0;
  615.     self.paralyzer_score_time_ms = getTime();
  616.     self.ignore_slowgun_anim_rates = undefined;
  617.     self.reset_anim = ::ghost_reset_anim;
  618.     self.custom_springpad_fling = ::ghost_springpad_fling;
  619.     self.bookcase_entering_callback = ::bookcase_entering_callback;
  620.     self.ignore_subwoofer = 1;
  621.     self.ignore_headchopper = 1;
  622.     self.ignore_spring_pad = 1;
  623.     recalc_zombie_array();
  624.     self setphysparams( 15, 0, 72 );
  625.     self.cant_melee = 1;
  626.     if ( isDefined( self.spawn_point ) )
  627.     {
  628.         spot = self.spawn_point;
  629.         if ( !isDefined( spot.angles ) )
  630.         {
  631.             spot.angles = ( 1, 1, 1 );
  632.         }
  633.         self forceteleport( spot.origin, spot.angles );
  634.     }
  635.     self set_zombie_run_cycle( "run" );
  636.     self setanimstatefromasd( "zm_move_run" );
  637.     self.actor_damage_func = ::ghost_damage_func;
  638.     self.deathfunction = ::ghost_death_func;
  639.     self.maxhealth = level.ghost_health;
  640.     self.health = level.ghost_health;
  641.     self.zombie_init_done = 1;
  642.     self notify( "zombie_init_done" );
  643.     self.allowpain = 0;
  644.     self.ignore_nuke = 1;
  645.     self animmode( "normal" );
  646.     self orientmode( "face enemy" );
  647.     self bloodimpact( "none" );
  648.     self disableaimassist();
  649.     self.forcemovementscriptstate = 0;
  650.     self maps/mp/zombies/_zm_spawner::zombie_setup_attack_properties();
  651.     if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone )
  652.     {
  653.         self.pathenemyfightdist = 0;
  654.     }
  655.     self maps/mp/zombies/_zm_spawner::zombie_complete_emerging_into_playable_area();
  656.     self setfreecameralockonallowed( 0 );
  657.     self.startinglocation = self.origin;
  658.     if ( isDefined( level.ghost_custom_think_logic ) )
  659.     {
  660.         self [[ level.ghost_custom_think_logic ]]();
  661.     }
  662.     self.bad_path_failsafe = ::maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_bad_path_failsafe;
  663.     self thread ghost_think();
  664.     self.attack_time = 0;
  665.     self.ignore_inert = 1;
  666.     self.subwoofer_burst_func = ::subwoofer_burst_func;
  667.     self.subwoofer_fling_func = ::subwoofer_fling_func;
  668.     self.subwoofer_knockdown_func = ::subwoofer_knockdown_func;
  669.     self maps/mp/zombies/_zm_ai_ghost_ffotd::prespawn_end();
  670. }
  671.  
  672. bookcase_entering_callback( bookcase_door )
  673. {
  674.     self endon( "death" );
  675.     while ( 1 )
  676.     {
  677.         if ( isDefined( bookcase_door._door_open ) && bookcase_door._door_open )
  678.         {
  679.             if ( isDefined( bookcase_door.door_moving ) && bookcase_door.door_moving )
  680.             {
  681.                 self.need_wait = 1;
  682.                 wait 2,1;
  683.                 self.need_wait = 0;
  684.             }
  685.             else
  686.             {
  687.                 self.need_wait = 0;
  688.             }
  689.             return;
  690.         }
  691.         else self.need_wait = 1;
  692.         wait 0,1;
  693.     }
  694. }
  695.  
  696. ghost_damage_func( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex )
  697. {
  698.     if ( sweapon == "equip_headchopper_zm" )
  699.     {
  700.         self.damageweapon_name = sweapon;
  701.         self check_zombie_damage_callbacks( smeansofdeath, shitloc, vpoint, eattacker, idamage );
  702.         self.damageweapon_name = undefined;
  703.     }
  704.     if ( idamage >= self.health )
  705.     {
  706.         self.killed_by = eattacker;
  707.         self thread prepare_to_die();
  708.     }
  709.     self thread set_impact_effect();
  710.     return idamage;
  711. }
  712.  
  713. set_impact_effect()
  714. {
  715.     self endon( "death" );
  716.     self setclientfield( "ghost_impact_fx", 1 );
  717.     wait_network_frame();
  718.     self setclientfield( "ghost_impact_fx", 0 );
  719. }
  720.  
  721. prepare_to_die()
  722. {
  723.     qrate = self getclientfield( "anim_rate" );
  724.     if ( qrate < 0,8 )
  725.     {
  726.         self.ignore_slowgun_anim_rates = 1;
  727.         self setclientfield( "anim_rate", 1 );
  728.         qrate = self getclientfield( "anim_rate" );
  729.         self setentityanimrate( qrate );
  730.         self.slowgun_anim_rate = qrate;
  731.         wait_network_frame();
  732.         self setclientfield( "anim_rate", 0,8 );
  733.         qrate = self getclientfield( "anim_rate" );
  734.         self setentityanimrate( qrate );
  735.         wait_network_frame();
  736.         ghost_reset_anim();
  737.     }
  738. }
  739.  
  740. ghost_reset_anim()
  741. {
  742.     if ( !isDefined( self ) )
  743.     {
  744.         return;
  745.     }
  746.     animstate = self getanimstatefromasd();
  747.     substate = self getanimsubstatefromasd();
  748.     if ( animstate == "zm_death" )
  749.     {
  750.         self setanimstatefromasd( "zm_death_no_restart", substate );
  751.     }
  752.     else
  753.     {
  754.         self maps/mp/zombies/_zm_weap_slowgun::reset_anim();
  755.     }
  756. }
  757.  
  758. wait_ghost_ghost( time )
  759. {
  760.     wait time;
  761.     if ( isDefined( self ) )
  762.     {
  763.         self ghost();
  764.     }
  765. }
  766.  
  767. ghost_death_func()
  768. {
  769.     if ( get_current_ghost_count() == 0 )
  770.     {
  771.         level.ghost_round_last_ghost_origin = self.origin;
  772.     }
  773.     self stoploopsound( 1 );
  774.     self playsound( "zmb_ai_ghost_death" );
  775.     self setclientfield( "ghost_impact_fx", 1 );
  776.     self setclientfield( "ghost_fx", 1 );
  777.     self thread prepare_to_die();
  778.     if ( isDefined( self.extra_custom_death_logic ) )
  779.     {
  780.         self thread [[ self.extra_custom_death_logic ]]();
  781.     }
  782.     qrate = self getclientfield( "anim_rate" );
  783.     self setanimstatefromasd( "zm_death" );
  784.     self thread wait_ghost_ghost( self getanimlengthfromasd( "zm_death", 0 ) );
  785.     maps/mp/animscripts/zm_shared::donotetracks( "death_anim" );
  786.     if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone )
  787.     {
  788.         level.zombie_ghost_count--;
  789.  
  790.         if ( isDefined( self.favoriteenemy ) )
  791.         {
  792.             if ( isDefined( self.favoriteenemy.ghost_count ) && self.favoriteenemy.ghost_count > 0 )
  793.             {
  794.                 self.favoriteenemy.ghost_count--;
  795.  
  796.             }
  797.         }
  798.     }
  799.     player = undefined;
  800.     if ( is_player_valid( self.attacker ) )
  801.     {
  802.         give_player_rewards( self.attacker );
  803.         player = self.attacker;
  804.     }
  805.     else
  806.     {
  807.         if ( isDefined( self.attacker ) && is_player_valid( self.attacker.owner ) )
  808.         {
  809.             give_player_rewards( self.attacker.owner );
  810.             player = self.attacker.owner;
  811.         }
  812.     }
  813.     if ( isDefined( player ) )
  814.     {
  815.         player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_ghost_killed", 0 );
  816.         player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_ghost_killed" );
  817.     }
  818.     self delete();
  819.     return 1;
  820. }
  821.  
  822. subwoofer_burst_func( weapon )
  823. {
  824.     self dodamage( self.health + 666, weapon.origin );
  825. }
  826.  
  827. subwoofer_fling_func( weapon, fling_vec )
  828. {
  829.     self dodamage( self.health + 666, weapon.origin );
  830. }
  831.  
  832. subwoofer_knockdown_func( weapon, gib )
  833. {
  834. }
  835.  
  836. ghost_think()
  837. {
  838.     self endon( "death" );
  839.     level endon( "intermission" );
  840.     if ( isDefined( level.ghost_round_presentation_ghost ) && level.ghost_round_presentation_ghost == self )
  841.     {
  842.         return;
  843.     }
  844.     if ( isDefined( level.ghost_custom_think_func_logic ) )
  845.     {
  846.         shouldwait = self [[ level.ghost_custom_think_func_logic ]]();
  847.         if ( shouldwait )
  848.         {
  849.             self waittill( "ghost_custom_think_done", find_flesh_struct_string );
  850.         }
  851.     }
  852.     self.ignore_slowgun_anim_rates = undefined;
  853.     self maps/mp/zombies/_zm_weap_slowgun::set_anim_rate( 1 );
  854.     self setclientfield( "slowgun_fx", 0 );
  855.     self setclientfield( "sndGhostAudio", 1 );
  856.     self init_thinking();
  857.     if ( isDefined( self.need_script_move ) && self.need_script_move )
  858.     {
  859.         self start_script_move();
  860.     }
  861.     else
  862.     {
  863.         if ( isDefined( self.is_spawned_in_ghost_zone ) && !self.is_spawned_in_ghost_zone && isDefined( self.respawned_by_time_bomb ) && !self.respawned_by_time_bomb )
  864.         {
  865.             self start_spawn();
  866.         }
  867.         else
  868.         {
  869.             self start_chase();
  870.         }
  871.     }
  872.     if ( isDefined( self.bad_path_failsafe ) )
  873.     {
  874.         self thread [[ self.bad_path_failsafe ]]();
  875.     }
  876.     while ( 1 )
  877.     {
  878.         switch( self.state )
  879.         {
  880.             case "script_move_update":
  881.                 self script_move_update();
  882.                 break;
  883.             case "chase_update":
  884.                 self chase_update();
  885.                 break;
  886.             case "drain_update":
  887.                 self drain_update();
  888.                 break;
  889.             case "runaway_update":
  890.                 self runaway_update();
  891.                 break;
  892.             case "evaporate_update":
  893.                 self evaporate_update();
  894.                 break;
  895.             case "wait_update":
  896.                 self wait_update();
  897.                 break;
  898.         }
  899.         wait 0,1;
  900.     }
  901. }
  902.  
  903. start_spawn()
  904. {
  905.     self animscripted( self.origin, self.angles, "zm_spawn" );
  906.     self maps/mp/animscripts/zm_shared::donotetracks( "spawn_anim" );
  907.     self start_chase();
  908. }
  909.  
  910. init_thinking()
  911. {
  912.     self thread find_flesh();
  913. }
  914.  
  915. find_flesh()
  916. {
  917.     self endon( "death" );
  918.     level endon( "intermission" );
  919.     self endon( "stop_find_flesh" );
  920.     if ( isDefined( level.intermission ) && level.intermission )
  921.     {
  922.         return;
  923.     }
  924.     self.nododgemove = 1;
  925.     self.ignore_player = [];
  926.     self zombie_history( "ghost find flesh -> start" );
  927.     self.goalradius = 32;
  928.     while ( 1 )
  929.     {
  930.         if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone )
  931.         {
  932.             if ( isDefined( self.find_target ) && self.find_target )
  933.             {
  934.                 self.favoriteenemy = get_closest_valid_player( self.origin );
  935.                 self.find_target = 0;
  936.             }
  937.         }
  938.         else
  939.         {
  940.             self.favoriteenemy = get_closest_valid_player( self.origin );
  941.         }
  942.         if ( isDefined( self.favoriteenemy ) )
  943.         {
  944.             self thread zombie_pathing();
  945.         }
  946.         else
  947.         {
  948.             if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone )
  949.             {
  950.                 self.find_target = 1;
  951.             }
  952.         }
  953.         self.zombie_path_timer = getTime() + ( randomfloatrange( 1, 3 ) * 1000 );
  954.         while ( getTime() < self.zombie_path_timer )
  955.         {
  956.             wait 0,1;
  957.         }
  958.         self notify( "path_timer_done" );
  959.         self zombie_history( "ghost find flesh -> path timer done" );
  960.         debug_print( "Zombie is re-acquiring enemy, ending breadcrumb search" );
  961.         self notify( "zombie_acquire_enemy" );
  962.     }
  963. }
  964.  
  965. get_closest_valid_player( origin )
  966. {
  967.     valid_player_found = 0;
  968.     players = get_players();
  969.     while ( !valid_player_found )
  970.     {
  971.         player = get_closest_player( origin, players );
  972.         if ( !isDefined( player ) )
  973.         {
  974.             return undefined;
  975.         }
  976.         if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone )
  977.         {
  978.             player_claimed_fully = is_player_fully_claimed( player );
  979.             if ( players.size == 1 && player_claimed_fully )
  980.             {
  981.                 return undefined;
  982.             }
  983.             while ( is_player_valid( player, 1 ) && !is_ghost_round_started() && isDefined( player.is_in_ghost_zone ) || !player.is_in_ghost_zone && player_claimed_fully )
  984.             {
  985.                 arrayremovevalue( players, player );
  986.             }
  987.             if ( isDefined( player.is_in_ghost_zone ) && !player.is_in_ghost_zone && !player is_in_start_area() )
  988.             {
  989.                 self.need_script_move = 1;
  990.             }
  991.             if ( !isDefined( player.ghost_count ) )
  992.             {
  993.                 player.ghost_count = 1;
  994.             }
  995.             else
  996.             {
  997.                 player.ghost_count += 1;
  998.             }
  999.         }
  1000.         else
  1001.         {
  1002.             while ( !is_player_valid( player, 1 ) )
  1003.             {
  1004.                 arrayremovevalue( players, player );
  1005.             }
  1006.         }
  1007.         return player;
  1008.     }
  1009. }
  1010.  
  1011. get_closest_player( origin, players )
  1012. {
  1013.     min_length_to_player = 9999999;
  1014.     player_to_return = undefined;
  1015.     i = 0;
  1016.     while ( i < players.size )
  1017.     {
  1018.         player = players[ i ];
  1019.         length_to_player = get_path_length_to_enemy( player );
  1020.         if ( length_to_player == 0 )
  1021.         {
  1022.             i++;
  1023.             continue;
  1024.         }
  1025.         else
  1026.         {
  1027.             if ( length_to_player < min_length_to_player )
  1028.             {
  1029.                 min_length_to_player = length_to_player;
  1030.                 player_to_return = player;
  1031.             }
  1032.         }
  1033.         i++;
  1034.     }
  1035.     if ( !isDefined( player_to_return ) )
  1036.     {
  1037.         player_to_return = getclosest( origin, players );
  1038.     }
  1039.     return player_to_return;
  1040. }
  1041.  
  1042. does_fall_into_pap_hole()
  1043. {
  1044.     if ( self istouching( level.ghost_gazebo_pit_volume ) )
  1045.     {
  1046.         self forceteleport( level.ghost_gazebo_pit_perk_pos.origin, ( 1, 1, 1 ) );
  1047.         wait 0,1;
  1048.         return 1;
  1049.     }
  1050.     return 0;
  1051. }
  1052.  
  1053. start_script_move()
  1054. {
  1055.     self.script_mover = spawn( "script_origin", self.origin );
  1056.     self.script_mover.angles = self.angles;
  1057.     self linkto( self.script_mover );
  1058.     self.state = "script_move_update";
  1059.     self setclientfield( "ghost_fx", 4 );
  1060.     player = self.favoriteenemy;
  1061.     if ( is_player_valid( player ) )
  1062.     {
  1063.         start_location = undefined;
  1064.         if ( isDefined( player.current_ghost_room_name ) && player.current_ghost_room_name == level.ghost_entry_room_to_maze )
  1065.         {
  1066.             start_location = level.ghost_back_flying_out_path_starts[ 0 ];
  1067.         }
  1068.         else
  1069.         {
  1070.             start_location = level.ghost_front_flying_out_path_starts[ 0 ];
  1071.         }
  1072.         self.script_move_target_node = self get_best_flying_target_node( player, start_location.origin );
  1073.     }
  1074.     self.script_move_sin_index = 0;
  1075. }
  1076.  
  1077. get_best_flying_target_node( player, start_loc )
  1078. {
  1079.     nearest_node = getnearestnode( player.origin );
  1080.     nodes = getnodesinradiussorted( player.origin, 540, 180, 60, "Path" );
  1081.     if ( !isDefined( nearest_node ) && nodes.size > 0 )
  1082.     {
  1083.         nearest_node = nodes[ 0 ];
  1084.     }
  1085.     selected_node = nearest_node;
  1086.     max_distance_squared = 0;
  1087.     start_pos = ( player.origin[ 0 ], player.origin[ 1 ], player.origin[ 2 ] + 60 );
  1088.     i = nodes.size - 1;
  1089.     while ( i >= 0 )
  1090.     {
  1091.         node = nodes[ i ];
  1092.         end_pos = ( node.origin[ 0 ], node.origin[ 1 ], node.origin[ 2 ] + 60 );
  1093.         line_of_sight = sighttracepassed( start_pos, end_pos, 0, player );
  1094.         if ( isDefined( line_of_sight ) && line_of_sight )
  1095.         {
  1096.             draw_debug_star( node.origin, ( 1, 1, 1 ), 100 );
  1097.             if ( is_within_view_2d( node.origin, player.origin, player.angles, 0,86 ) )
  1098.             {
  1099.                 selected_node = node;
  1100.                 break;
  1101.             }
  1102.             else
  1103.             {
  1104.                 selected_node = node;
  1105.             }
  1106.             i--;
  1107.  
  1108.         }
  1109.     }
  1110.     return selected_node;
  1111. }
  1112.  
  1113. script_move_update()
  1114. {
  1115.     if ( isDefined( self.is_traversing ) && self.is_traversing )
  1116.     {
  1117.         return;
  1118.     }
  1119.     player = self.favoriteenemy;
  1120.     if ( is_player_valid( player ) && isDefined( self.script_move_target_node ) )
  1121.     {
  1122.         desired_angles = vectorToAngle( vectornormalize( player.origin - self.origin ) );
  1123.         distance_squared = distancesquared( self.origin, self.script_move_target_node.origin );
  1124.         if ( distance_squared < 24 )
  1125.         {
  1126.             self.script_mover.angles = desired_angles;
  1127.             self remove_script_mover();
  1128.             wait_network_frame();
  1129.             self setclientfield( "ghost_fx", 3 );
  1130.             self setclientfield( "sndGhostAudio", 1 );
  1131.             wait_network_frame();
  1132.             self start_chase();
  1133.             return;
  1134.         }
  1135.         draw_debug_star( self.script_move_target_node.origin, ( 1, 1, 1 ), 1 );
  1136.         target_node_pos = self.script_move_target_node.origin + vectorScale( ( 1, 1, 1 ), 36 );
  1137.         distance_squared_to_target_node_pos = distancesquared( self.origin, target_node_pos );
  1138.         moved_distance_during_interval = 80;
  1139.         if ( distance_squared_to_target_node_pos <= ( moved_distance_during_interval * moved_distance_during_interval ) )
  1140.         {
  1141.             target_point = self.script_move_target_node.origin;
  1142.             self.script_mover moveto( target_point, 0,1, 0, 0,1 );
  1143.             self.script_mover waittill( "movedone" );
  1144.             self.script_mover.angles = desired_angles;
  1145.         }
  1146.         else
  1147.         {
  1148.             distance_squared_to_player = distancesquared( self.origin, player.origin );
  1149.             if ( distance_squared_to_player < 540 && isDefined( self.script_mover.search_target_node_again ) && !self.script_mover.search_target_node_again )
  1150.             {
  1151.                 self get_best_flying_target_node( player, self.script_move_target_node.origin );
  1152.                 self.script_mover.search_target_node_again = 1;
  1153.             }
  1154.             if ( self.script_move_sin_index >= level.ghost_script_move_sin.size )
  1155.             {
  1156.                 self.script_move_sin_index = 0;
  1157.             }
  1158.             move_dir = target_node_pos - self.origin;
  1159.             move_dir = vectornormalize( move_dir );
  1160.             target_point = self.origin + ( ( move_dir * 800 ) * 0,1 );
  1161.             x_offset = level.ghost_script_move_sin[ self.script_move_sin_index ] * 6;
  1162.             z_offset = level.ghost_script_move_sin[ self.script_move_sin_index ] * 12;
  1163.             target_point += ( x_offset, 0, z_offset );
  1164.             self.script_move_sin_index++;
  1165.             self.script_mover moveto( target_point, 0,1 );
  1166.             self.script_mover.angles = desired_angles;
  1167.             draw_debug_star( target_point, ( 1, 1, 1 ), 1 );
  1168.         }
  1169.     }
  1170.     else
  1171.     {
  1172.         self remove_script_mover();
  1173.         self start_evaporate( 1 );
  1174.     }
  1175. }
  1176.  
  1177. remove_script_mover()
  1178. {
  1179.     if ( isDefined( self.script_mover ) )
  1180.     {
  1181.         self dontinterpolate();
  1182.         self unlink();
  1183.         self.script_mover delete();
  1184.     }
  1185. }
  1186.  
  1187. start_chase()
  1188. {
  1189.     self set_zombie_run_cycle( "run" );
  1190.     self setanimstatefromasd( "zm_move_run" );
  1191.     self.state = "chase_update";
  1192.     self setclientfield( "ghost_fx", 4 );
  1193. }
  1194.  
  1195. chase_update()
  1196. {
  1197.     if ( isDefined( self.is_traversing ) && self.is_traversing )
  1198.     {
  1199.         return;
  1200.     }
  1201.     player = self.favoriteenemy;
  1202.     if ( is_player_valid( player ) )
  1203.     {
  1204.         if ( self should_runaway( player ) )
  1205.         {
  1206.             self start_runaway();
  1207.             return;
  1208.         }
  1209.         if ( self does_fall_into_pap_hole() )
  1210.         {
  1211.             self dodamage( self.health + 666, self.origin );
  1212.             return;
  1213.         }
  1214.         if ( self need_wait() )
  1215.         {
  1216.             self start_wait();
  1217.             return;
  1218.         }
  1219.         ghost_check_point = self.origin + ( 0, 0, 60 );
  1220.         player_eye_pos = player geteyeapprox();
  1221.         line_of_sight = sighttracepassed( ghost_check_point, player_eye_pos, 0, self );
  1222.         if ( isDefined( line_of_sight ) && line_of_sight && can_drain_points( self.origin, player.origin ) )
  1223.         {
  1224.             self start_drain();
  1225.             return;
  1226.         }
  1227.         distsquared = distancesquared( self.origin, player.origin );
  1228.         if ( distsquared > ( 300 * 300 ) )
  1229.         {
  1230.             if ( isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone && isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone && isDefined( player.current_ghost_room_name ) )
  1231.             {
  1232.                 current_room = level.ghost_rooms[ player.current_ghost_room_name ];
  1233.                 if ( isDefined( current_room.flag ) && current_room.flag != "no_cleanup" || self is_in_close_rooms( current_room ) && self is_in_room( current_room ) && !self is_following_room_path( player, current_room ) )
  1234.                 {
  1235.                     set_chase_status( "run" );
  1236.                 }
  1237.                 else
  1238.                 {
  1239.                     self start_evaporate( 1 );
  1240.                 }
  1241.             }
  1242.             else
  1243.             {
  1244.                 set_chase_status( "run" );
  1245.                 if ( distsquared > ( 9600 * 9600 ) )
  1246.                 {
  1247.                     teleport_location = level.ghost_front_flying_out_path_starts[ 0 ];
  1248.                     self forceteleport( teleport_location.origin, ( 1, 1, 1 ) );
  1249.                 }
  1250.             }
  1251.         }
  1252.         else if ( distsquared > ( 144 * 144 ) )
  1253.         {
  1254.             set_chase_status( "run" );
  1255.         }
  1256.         else
  1257.         {
  1258.             set_chase_status( "walk" );
  1259.         }
  1260.     }
  1261.     else
  1262.     {
  1263.         self set_zombie_run_cycle( "run" );
  1264.         if ( self getanimstatefromasd() != "zm_move_run" )
  1265.         {
  1266.             self setanimstatefromasd( "zm_move_run" );
  1267.         }
  1268.         self start_runaway();
  1269.     }
  1270. }
  1271.  
  1272. need_wait()
  1273. {
  1274.     if ( isDefined( self.need_wait ) )
  1275.     {
  1276.         return self.need_wait;
  1277.     }
  1278. }
  1279.  
  1280. start_wait()
  1281. {
  1282.     self setanimstatefromasd( "zm_idle" );
  1283.     self setclientfield( "ghost_fx", 4 );
  1284.     self.state = "wait_update";
  1285. }
  1286.  
  1287. wait_update()
  1288. {
  1289.     if ( isDefined( self.is_traversing ) && self.is_traversing )
  1290.     {
  1291.         return;
  1292.     }
  1293.     player = self.favoriteenemy;
  1294.     if ( is_player_valid( player ) )
  1295.     {
  1296.         ghost_check_point = self.origin + ( 0, 0, 60 );
  1297.         player_eye_pos = player geteyeapprox();
  1298.         line_of_sight = sighttracepassed( ghost_check_point, player_eye_pos, 0, self );
  1299.         if ( isDefined( line_of_sight ) && line_of_sight && can_drain_points( self.origin, player.origin ) )
  1300.         {
  1301.             self start_drain();
  1302.             return;
  1303.         }
  1304.         if ( !self need_wait() )
  1305.         {
  1306.             self start_chase();
  1307.         }
  1308.     }
  1309.     else
  1310.     {
  1311.         self set_zombie_run_cycle( "run" );
  1312.         if ( self getanimstatefromasd() != "zm_move_run" )
  1313.         {
  1314.             self setanimstatefromasd( "zm_move_run" );
  1315.         }
  1316.         self setclientfield( "ghost_fx", 4 );
  1317.         self start_runaway();
  1318.     }
  1319. }
  1320.  
  1321. start_evaporate( need_deletion )
  1322. {
  1323.     self setclientfield( "ghost_fx", 5 );
  1324.     wait 0,1;
  1325.     if ( isDefined( need_deletion ) && need_deletion )
  1326.     {
  1327.         level.zombie_ghost_count--;
  1328.  
  1329.         if ( isDefined( self.favoriteenemy ) )
  1330.         {
  1331.             if ( isDefined( self.favoriteenemy.ghost_count ) && self.favoriteenemy.ghost_count > 0 )
  1332.             {
  1333.                 self.favoriteenemy.ghost_count--;
  1334.  
  1335.             }
  1336.         }
  1337.         self delete();
  1338.     }
  1339.     else
  1340.     {
  1341.         self.state = "evaporate_update";
  1342.         self ghost();
  1343.         self notsolid();
  1344.     }
  1345. }
  1346.  
  1347. should_be_deleted_during_evaporate_update( player )
  1348. {
  1349.     if ( isDefined( self.is_spawned_in_ghost_zone ) && !self.is_spawned_in_ghost_zone )
  1350.     {
  1351.         return 0;
  1352.     }
  1353.     if ( !isDefined( player ) )
  1354.     {
  1355.         return 1;
  1356.     }
  1357.     if ( isDefined( player.sessionstate ) || player.sessionstate == "spectator" && player.sessionstate == "intermission" )
  1358.     {
  1359.         return 1;
  1360.     }
  1361.     return 0;
  1362. }
  1363.  
  1364. evaporate_update()
  1365. {
  1366.     player = self.favoriteenemy;
  1367.     if ( should_be_deleted_during_evaporate_update( player ) )
  1368.     {
  1369.         if ( level.zombie_ghost_count > 0 )
  1370.         {
  1371.             level.zombie_ghost_count--;
  1372.  
  1373.         }
  1374.         self delete();
  1375.     }
  1376.     else
  1377.     {
  1378.         if ( is_player_valid( player ) )
  1379.         {
  1380.             self solid();
  1381.             self show();
  1382.             self start_chase();
  1383.         }
  1384.     }
  1385. }
  1386.  
  1387. is_within_capsule( point, origin, angles, radius, range )
  1388. {
  1389.     forward_dir = vectornormalize( anglesToForward( angles ) );
  1390.     start = origin + ( forward_dir * radius );
  1391.     end = start + ( forward_dir * range );
  1392.     point_intersect = pointonsegmentnearesttopoint( start, end, point );
  1393.     distance_squared = distancesquared( point_intersect, point );
  1394.     if ( distance_squared <= ( radius * radius ) )
  1395.     {
  1396.         return 1;
  1397.     }
  1398.     return 0;
  1399. }
  1400.  
  1401. is_within_view_2d( point, origin, angles, fov_cos )
  1402. {
  1403.     dot = get_dot_production_2d( point, origin, angles );
  1404.     if ( dot > fov_cos )
  1405.     {
  1406.         return 1;
  1407.     }
  1408.     return 0;
  1409. }
  1410.  
  1411. get_dot_production_2d( point, origin, angles )
  1412. {
  1413.     forward_dir = anglesToForward( angles );
  1414.     forward_dir = ( forward_dir[ 0 ], forward_dir[ 1 ], 0 );
  1415.     forward_dir = vectornormalize( forward_dir );
  1416.     to_point_dir = point - origin;
  1417.     to_point_dir = ( to_point_dir[ 0 ], to_point_dir[ 1 ], 0 );
  1418.     to_point_dir = vectornormalize( to_point_dir );
  1419.     return vectordot( forward_dir, to_point_dir );
  1420. }
  1421.  
  1422. is_in_room( room )
  1423. {
  1424.     _a1702 = room.volumes;
  1425.     _k1702 = getFirstArrayKey( _a1702 );
  1426.     while ( isDefined( _k1702 ) )
  1427.     {
  1428.         volume = _a1702[ _k1702 ];
  1429.         if ( self istouching( volume ) )
  1430.         {
  1431.             return 1;
  1432.         }
  1433.         _k1702 = getNextArrayKey( _a1702, _k1702 );
  1434.     }
  1435.     return 0;
  1436. }
  1437.  
  1438. is_in_rooms( room_names )
  1439. {
  1440.     _a1715 = room_names;
  1441.     _k1715 = getFirstArrayKey( _a1715 );
  1442.     while ( isDefined( _k1715 ) )
  1443.     {
  1444.         room_name = _a1715[ _k1715 ];
  1445.         room = level.ghost_rooms[ room_name ];
  1446.         if ( self is_in_room( room ) )
  1447.         {
  1448.             return 1;
  1449.         }
  1450.         _k1715 = getNextArrayKey( _a1715, _k1715 );
  1451.     }
  1452.     return 0;
  1453. }
  1454.  
  1455. is_in_next_rooms( room )
  1456. {
  1457.     if ( self is_in_rooms( room.next_room_names ) )
  1458.     {
  1459.         return 1;
  1460.     }
  1461.     return 0;
  1462. }
  1463.  
  1464. is_in_close_rooms( room )
  1465. {
  1466.     _a1742 = room.next_room_names;
  1467.     _k1742 = getFirstArrayKey( _a1742 );
  1468.     while ( isDefined( _k1742 ) )
  1469.     {
  1470.         next_room_name = _a1742[ _k1742 ];
  1471.         next_room = level.ghost_rooms[ next_room_name ];
  1472.         if ( self is_in_rooms( next_room.next_room_names ) )
  1473.         {
  1474.             return 1;
  1475.         }
  1476.         _k1742 = getNextArrayKey( _a1742, _k1742 );
  1477.     }
  1478.     if ( self is_in_rooms( room.next_room_names ) )
  1479.     {
  1480.         return 1;
  1481.     }
  1482.     return 0;
  1483. }
  1484.  
  1485. is_following_room_path( player, room )
  1486. {
  1487.     if ( isDefined( room.volumes[ 0 ].script_angles ) )
  1488.     {
  1489.         dot = get_dot_production_2d( player.origin, self.origin, room.volumes[ 0 ].script_angles );
  1490.         if ( dot > 0 )
  1491.         {
  1492.             return 1;
  1493.         }
  1494.     }
  1495.     return 0;
  1496. }
  1497.  
  1498. can_drain_points( self_pos, target_pos )
  1499. {
  1500.     if ( isDefined( self.force_killable ) && self.force_killable )
  1501.     {
  1502.         return 0;
  1503.     }
  1504.     dist = distancesquared( self_pos, target_pos );
  1505.     if ( dist < ( 60 * 60 ) )
  1506.     {
  1507.         return 1;
  1508.     }
  1509.     return 0;
  1510. }
  1511.  
  1512. set_chase_status( move_speed )
  1513. {
  1514.     self setclientfield( "ghost_fx", 4 );
  1515.     if ( self.zombie_move_speed != move_speed )
  1516.     {
  1517.         self set_zombie_run_cycle( move_speed );
  1518.         self setanimstatefromasd( "zm_move_" + move_speed );
  1519.     }
  1520. }
  1521.  
  1522. start_drain()
  1523. {
  1524.     self setanimstatefromasd( "zm_drain" );
  1525.     self setclientfield( "ghost_fx", 2 );
  1526.     self.state = "drain_update";
  1527. }
  1528.  
  1529. drain_update()
  1530. {
  1531.     if ( isDefined( self.is_traversing ) && self.is_traversing )
  1532.     {
  1533.         return;
  1534.     }
  1535.     player = self.favoriteenemy;
  1536.     if ( is_player_valid( player ) )
  1537.     {
  1538.         if ( can_drain_points( self.origin, player.origin ) )
  1539.         {
  1540.             if ( self getanimstatefromasd() != "zm_drain" )
  1541.             {
  1542.                 self setanimstatefromasd( "zm_drain" );
  1543.             }
  1544.             self orientmode( "face enemy" );
  1545.             if ( isDefined( self.is_draining ) && !self.is_draining )
  1546.             {
  1547.                 self thread drain_player( player );
  1548.             }
  1549.         }
  1550.         else
  1551.         {
  1552.             self start_chase();
  1553.         }
  1554.     }
  1555.     else
  1556.     {
  1557.         self set_zombie_run_cycle( "run" );
  1558.         if ( self getanimstatefromasd() != "zm_move_run" )
  1559.         {
  1560.             self setanimstatefromasd( "zm_move_run" );
  1561.         }
  1562.         self setclientfield( "ghost_fx", 4 );
  1563.         self start_runaway();
  1564.     }
  1565. }
  1566.  
  1567. drain_player( player )
  1568. {
  1569.     self endon( "death" );
  1570.     self.is_draining = 1;
  1571.     player_drained = 0;
  1572.     points_to_drain = 2000;
  1573.     if ( player.score < points_to_drain )
  1574.     {
  1575.         if ( player.score > 0 )
  1576.         {
  1577.             points_to_drain = player.score;
  1578.         }
  1579.         else
  1580.         {
  1581.             points_to_drain = 0;
  1582.         }
  1583.     }
  1584.     if ( points_to_drain > 0 )
  1585.     {
  1586.         player maps/mp/zombies/_zm_score::minus_to_player_score( points_to_drain );
  1587.         player_drained = 1;
  1588.         player playsoundtoplayer( "zmb_ai_ghost_money_drain", player );
  1589.         level notify( "ghost_drained_player" );
  1590.     }
  1591.     else
  1592.     {
  1593.         if ( player.health > 0 && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() )
  1594.         {
  1595.             player dodamage( 25, self.origin, self );
  1596.             player_drained = 1;
  1597.             level notify( "ghost_damaged_player" );
  1598.         }
  1599.     }
  1600.     if ( player_drained )
  1601.     {
  1602.         give_player_rewards( player );
  1603.         player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_ghost_drained_player", 0 );
  1604.         player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_ghost_drained_player" );
  1605.         wait 2;
  1606.     }
  1607.     self.is_draining = 0;
  1608. }
  1609.  
  1610. should_runaway( player )
  1611. {
  1612.     result = 0;
  1613.     if ( !is_ghost_round_started() && isDefined( self.is_spawned_in_ghost_zone ) && self.is_spawned_in_ghost_zone && isDefined( player.is_in_ghost_zone ) && !player.is_in_ghost_zone )
  1614.     {
  1615.         path_lenth = self getpathlength();
  1616.         if ( path_lenth == 0 )
  1617.         {
  1618.             result = 1;
  1619.         }
  1620.     }
  1621.     return result;
  1622. }
  1623.  
  1624. start_runaway()
  1625. {
  1626.     wait 2;
  1627.     self.state = "runaway_update";
  1628.     self setgoalpos( self.startinglocation );
  1629.     self set_chase_status( "run" );
  1630. }
  1631.  
  1632. does_reach_runaway_goal()
  1633. {
  1634.     result = 0;
  1635.     dist_squared = distancesquared( self.origin, self.startinglocation );
  1636.     if ( dist_squared < ( 60 * 60 ) )
  1637.     {
  1638.         result = 1;
  1639.     }
  1640.     return result;
  1641. }
  1642.  
  1643. runaway_update()
  1644. {
  1645.     if ( isDefined( self.is_traversing ) && self.is_traversing )
  1646.     {
  1647.         return;
  1648.     }
  1649.     player = self.favoriteenemy;
  1650.     if ( is_player_valid( player ) || is_ghost_round_started() && isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone )
  1651.     {
  1652.         self.state = "chase_update";
  1653.         return;
  1654.     }
  1655.     if ( self does_fall_into_pap_hole() )
  1656.     {
  1657.         self dodamage( self.health + 666, self.origin );
  1658.         return;
  1659.     }
  1660.     if ( self does_reach_runaway_goal() )
  1661.     {
  1662.         should_delete = 1;
  1663.         if ( is_ghost_round_started() || isDefined( self.is_spawned_in_ghost_zone ) && !self.is_spawned_in_ghost_zone )
  1664.         {
  1665.             should_delete = 0;
  1666.         }
  1667.         self start_evaporate( should_delete );
  1668.     }
  1669.     else
  1670.     {
  1671.         self setgoalpos( self.startinglocation );
  1672. /#
  1673.         draw_debug_star( self.startinglocation, ( 1, 1, 1 ), 1 );
  1674.         draw_debug_line( self.origin, self.startinglocation, ( 1, 1, 1 ), 1, 0 );
  1675. #/
  1676.     }
  1677. }
  1678.  
  1679. paralyzer_callback( player, upgraded )
  1680. {
  1681.     if ( isDefined( self.ignore_slowgun_anim_rates ) && self.ignore_slowgun_anim_rates )
  1682.     {
  1683.         return;
  1684.     }
  1685.     if ( upgraded )
  1686.     {
  1687.         self setclientfield( "slowgun_fx", 5 );
  1688.     }
  1689.     else
  1690.     {
  1691.         self setclientfield( "slowgun_fx", 1 );
  1692.     }
  1693.     self maps/mp/zombies/_zm_weap_slowgun::zombie_slow_for_time( 0,3, 0 );
  1694. }
  1695.  
  1696. ghost_springpad_fling( weapon, attacker )
  1697. {
  1698.     self dodamage( self.health + 666, self.origin );
  1699.     weapon.springpad_kills++;
  1700. }
  1701.  
  1702. ghost_print( str )
  1703. {
  1704. /#
  1705.     if ( getDvarInt( #"151B6F17" ) )
  1706.     {
  1707.         iprintln( "ghost: " + str + "\n" );
  1708.         if ( isDefined( self ) )
  1709.         {
  1710.             if ( isDefined( self.debug_msg ) )
  1711.             {
  1712.                 self.debug_msg[ self.debug_msg.size ] = str;
  1713.                 return;
  1714.             }
  1715.             else
  1716.             {
  1717.                 self.debug_msg = [];
  1718.                 self.debug_msg[ self.debug_msg.size ] = str;
  1719. #/
  1720.             }
  1721.         }
  1722.     }
  1723. }
  1724.  
  1725. ghost_round_think()
  1726. {
  1727.     level endon( "intermission" );
  1728.     if ( isDefined( level.intermission ) && level.intermission )
  1729.     {
  1730.         return;
  1731.     }
  1732.     for ( ;; )
  1733.     {
  1734.         while ( 1 )
  1735.         {
  1736.             level.zombie_ghost_round_states.any_player_in_ghost_zone = check_players_in_ghost_zone();
  1737.             if ( can_start_ghost_round() )
  1738.             {
  1739.                 if ( ghost_round_start_conditions_met() )
  1740.                 {
  1741.                     start_ghost_round();
  1742.                     break;
  1743.                 }
  1744.                 else
  1745.                 {
  1746.                     wait 0,1;
  1747.                 }
  1748.             }
  1749.             while ( 1 )
  1750.             {
  1751.                 if ( can_end_ghost_round() )
  1752.                 {
  1753.                     wait 0,5;
  1754.                     end_ghost_round();
  1755.                     break;
  1756.                 }
  1757.                 else
  1758.                 {
  1759.                     level.zombie_ghost_round_states.any_player_in_ghost_zone = check_players_in_ghost_zone();
  1760.                     if ( isDefined( level.ghost_zone_teleport_logic ) )
  1761.                     {
  1762.                         [[ level.ghost_zone_teleport_logic ]]();
  1763.                     }
  1764.                     if ( isDefined( level.ghost_zone_fountain_teleport_logic ) )
  1765.                     {
  1766.                         [[ level.ghost_zone_fountain_teleport_logic ]]();
  1767.                     }
  1768.                     wait 0,1;
  1769.                 }
  1770.             }
  1771.         }
  1772.         else check_sending_away_zombie_followers();
  1773.         wait 0,1;
  1774.     }
  1775. }
  1776.  
  1777. ghost_round_start_conditions_met()
  1778. {
  1779.     if ( isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && level.zombie_ghost_round_states.any_player_in_ghost_zone )
  1780.     {
  1781.         b_conditions_met = !is_ghost_round_started();
  1782.     }
  1783.     if ( isDefined( level.force_ghost_round_start ) || level.force_ghost_round_start && is_ghost_round_started() )
  1784.     {
  1785.         b_conditions_met = 1;
  1786.     }
  1787.     return b_conditions_met;
  1788. }
  1789.  
  1790. can_start_ghost_round()
  1791. {
  1792. /#
  1793.     if ( isDefined( level.force_no_ghost ) && level.force_no_ghost )
  1794.     {
  1795.         return 0;
  1796. #/
  1797.     }
  1798.     result = 0;
  1799.     if ( isDefined( level.zombie_ghost_round_states ) )
  1800.     {
  1801.         if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) || !level.zombie_ghost_round_states.is_first_ghost_round_finished && level.round_number >= level.zombie_ghost_round_states.next_ghost_round_number )
  1802.         {
  1803.             result = 1;
  1804.         }
  1805.     }
  1806.     if ( isDefined( level.force_ghost_round_start ) && level.force_ghost_round_start )
  1807.     {
  1808.         result = 1;
  1809.     }
  1810.     return result;
  1811. }
  1812.  
  1813. set_ghost_round_number()
  1814. {
  1815.     if ( isDefined( level.zombie_ghost_round_states ) )
  1816.     {
  1817.         level.zombie_ghost_round_states.current_ghost_round_number = level.round_number;
  1818.         level.zombie_ghost_round_states.next_ghost_round_number = level.round_number + randomintrange( 4, 6 );
  1819.     }
  1820. }
  1821.  
  1822. is_ghost_round_started()
  1823. {
  1824.     if ( isDefined( level.zombie_ghost_round_states ) )
  1825.     {
  1826.         return level.zombie_ghost_round_states.is_started;
  1827.     }
  1828.     return 0;
  1829. }
  1830.  
  1831. start_ghost_round()
  1832. {
  1833.     level.zombie_ghost_round_states.is_started = 1;
  1834.     level.zombie_ghost_round_states.round_count++;
  1835.     flag_clear( "spawn_zombies" );
  1836.     flag_set( "spawn_ghosts" );
  1837.     disable_ghost_zone_door_ai_clips();
  1838.     clear_all_active_zombies();
  1839.     set_ghost_round_number();
  1840.     increase_ghost_health();
  1841.     ghost_round_presentation_reset();
  1842.     wait 0,5;
  1843.     level thread sndghostroundmus();
  1844.     level thread outside_ghost_zone_spawning_think();
  1845.     level thread player_moving_speed_scale_think();
  1846.     if ( !flag( "time_bomb_restore_active" ) )
  1847.     {
  1848.         level.force_ghost_round_start = undefined;
  1849.     }
  1850.     maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_round_start();
  1851. }
  1852.  
  1853. increase_ghost_health()
  1854. {
  1855.     if ( level.zombie_ghost_round_states.round_count == 1 )
  1856.     {
  1857.         new_health = level.ghost_health + 300;
  1858.         if ( level.round_number > 5 )
  1859.         {
  1860.             new_health = int( 1600 * ( level.round_number / 20 ) );
  1861.         }
  1862.         level.ghost_health = new_health;
  1863.     }
  1864.     else if ( level.zombie_ghost_round_states.round_count == 2 )
  1865.     {
  1866.         level.ghost_health += 500;
  1867.     }
  1868.     else if ( level.zombie_ghost_round_states.round_count == 3 )
  1869.     {
  1870.         level.ghost_health += 400;
  1871.     }
  1872.     else
  1873.     {
  1874.         if ( level.zombie_ghost_round_states.round_count == 4 )
  1875.         {
  1876.             level.ghost_health = 1600;
  1877.         }
  1878.     }
  1879.     if ( level.ghost_health > 1600 )
  1880.     {
  1881.         level.ghost_health = 1600;
  1882.     }
  1883. }
  1884.  
  1885. enable_ghost_zone_door_ai_clips()
  1886. {
  1887.     while ( isDefined( level.ghost_zone_door_clips ) && level.ghost_zone_door_clips.size > 0 )
  1888.     {
  1889.         _a2256 = level.ghost_zone_door_clips;
  1890.         _k2256 = getFirstArrayKey( _a2256 );
  1891.         while ( isDefined( _k2256 ) )
  1892.         {
  1893.             door_clip = _a2256[ _k2256 ];
  1894.             door_clip solid();
  1895.             door_clip disconnectpaths();
  1896.             _k2256 = getNextArrayKey( _a2256, _k2256 );
  1897.         }
  1898.     }
  1899. }
  1900.  
  1901. disable_ghost_zone_door_ai_clips()
  1902. {
  1903.     while ( isDefined( level.ghost_zone_door_clips ) && level.ghost_zone_door_clips.size > 0 )
  1904.     {
  1905.         _a2269 = level.ghost_zone_door_clips;
  1906.         _k2269 = getFirstArrayKey( _a2269 );
  1907.         while ( isDefined( _k2269 ) )
  1908.         {
  1909.             door_clip = _a2269[ _k2269 ];
  1910.             door_clip notsolid();
  1911.             door_clip connectpaths();
  1912.             _k2269 = getNextArrayKey( _a2269, _k2269 );
  1913.         }
  1914.     }
  1915. }
  1916.  
  1917. clear_all_active_zombies()
  1918. {
  1919.     zombies = get_round_enemy_array();
  1920.     while ( isDefined( zombies ) )
  1921.     {
  1922.         level.zombie_ghost_round_states.round_zombie_total = level.zombie_total + zombies.size;
  1923.         _a2288 = zombies;
  1924.         _k2288 = getFirstArrayKey( _a2288 );
  1925.         while ( isDefined( _k2288 ) )
  1926.         {
  1927.             zombie = _a2288[ _k2288 ];
  1928.             if ( isDefined( zombie.is_ghost ) && !zombie.is_ghost )
  1929.             {
  1930.                 spawn_point = spawnstruct();
  1931.                 spawn_point.origin = zombie.origin;
  1932.                 spawn_point.angles = zombie.angles;
  1933.                 if ( isDefined( zombie.completed_emerging_into_playable_area ) && !zombie.completed_emerging_into_playable_area )
  1934.                 {
  1935.                     if ( isDefined( zombie.spawn_point ) && isDefined( zombie.spawn_point.script_string ) )
  1936.                     {
  1937.                         no_barrier_target = zombie.spawn_point.script_string == "find_flesh";
  1938.                     }
  1939.                     if ( no_barrier_target )
  1940.                     {
  1941.                         if ( isDefined( zombie.spawn_point.script_noteworthy ) && zombie.spawn_point.script_noteworthy == "faller_location" )
  1942.                         {
  1943.                             ground_pos = groundpos_ignore_water_new( zombie.spawn_point.origin );
  1944.                             spawn_point.origin = ground_pos;
  1945.                         }
  1946.                     }
  1947.                     else
  1948.                     {
  1949.                         origin = zombie.origin;
  1950.                         desired_origin = zombie get_desired_origin();
  1951.                         if ( isDefined( desired_origin ) )
  1952.                         {
  1953.                             origin = desired_origin;
  1954.                         }
  1955.                         nodes = get_array_of_closest( origin, level.exterior_goals, undefined, 1 );
  1956.                         if ( nodes.size > 0 )
  1957.                         {
  1958.                             spawn_point.origin = nodes[ 0 ].neg_end.origin;
  1959.                             spawn_point.angles = nodes[ 0 ].neg_end.angles;
  1960.                         }
  1961.                     }
  1962.                 }
  1963.                 else
  1964.                 {
  1965.                     if ( isDefined( level.sloth ) && isDefined( level.sloth.crawler ) && zombie == level.sloth.crawler )
  1966.                     {
  1967.                         spawn_point.origin = level.sloth.origin;
  1968.                         spawn_point.angles = level.sloth.angles;
  1969.                     }
  1970.                 }
  1971.                 level.zombie_ghost_round_states.active_zombie_locations[ level.zombie_ghost_round_states.active_zombie_locations.size ] = spawn_point;
  1972.                 zombie.nodeathragdoll = 1;
  1973.                 zombie.turning_into_ghost = 1;
  1974.                 if ( isalive( zombie ) )
  1975.                 {
  1976.                     zombie dodamage( zombie.health + 666, zombie.origin );
  1977.                 }
  1978.             }
  1979.             _k2288 = getNextArrayKey( _a2288, _k2288 );
  1980.         }
  1981.     }
  1982. }
  1983.  
  1984. reset_ghost_round_states()
  1985. {
  1986.     if ( !isDefined( level.zombie_ghost_round_states.round_zombie_total ) )
  1987.     {
  1988.         level.zombie_ghost_round_states.round_zombie_total = 0;
  1989.     }
  1990.     level.zombie_ghost_round_states.is_started = 0;
  1991.     if ( should_restore_zombie_total() )
  1992.     {
  1993.         if ( level.zombie_ghost_round_states.round_zombie_total > 0 )
  1994.         {
  1995.             level.zombie_total = level.zombie_ghost_round_states.round_zombie_total;
  1996.         }
  1997.     }
  1998.     level.zombie_ghost_round_states.round_zombie_total = 0;
  1999.     level.zombie_ghost_round_states.active_zombie_locations = [];
  2000.     if ( is_false( level.zombie_ghost_round_states.is_first_ghost_round_finished ) )
  2001.     {
  2002.         level.zombie_ghost_round_states.is_first_ghost_round_finished = 1;
  2003.     }
  2004. }
  2005.  
  2006. should_restore_zombie_total()
  2007. {
  2008.     if ( flag( "time_bomb_restore_active" ) )
  2009.     {
  2010.         if ( flag( "time_bomb_restore_active" ) )
  2011.         {
  2012.             return maps/mp/zombies/_zm_weap_time_bomb::get_time_bomb_saved_round_type() == "ghost";
  2013.         }
  2014.     }
  2015. }
  2016.  
  2017. can_end_ghost_round()
  2018. {
  2019.     if ( isDefined( level.force_ghost_round_end ) && level.force_ghost_round_end )
  2020.     {
  2021.         return 1;
  2022.     }
  2023.     if ( isDefined( level.zombie_ghost_round_states.any_player_in_ghost_zone ) && !level.zombie_ghost_round_states.any_player_in_ghost_zone && get_current_ghost_count() <= 0 )
  2024.     {
  2025.         return 1;
  2026.     }
  2027.     return 0;
  2028. }
  2029.  
  2030. end_ghost_round()
  2031. {
  2032.     reset_ghost_round_states();
  2033.     if ( should_last_ghost_drop_powerup() )
  2034.     {
  2035.         trace = groundtrace( level.ghost_round_last_ghost_origin + vectorScale( ( 1, 1, 1 ), 10 ), level.ghost_round_last_ghost_origin + vectorScale( ( 1, 1, 1 ), 150 ), 0, undefined, 1 );
  2036.         power_up_origin = trace[ "position" ];
  2037.         powerup = level thread maps/mp/zombies/_zm_powerups::specific_powerup_drop( "free_perk", power_up_origin );
  2038.         if ( isDefined( powerup ) )
  2039.         {
  2040.             powerup.ghost_powerup = 1;
  2041.         }
  2042.         level.ghost_round_last_ghost_origin_last = level.ghost_round_last_ghost_origin;
  2043.         level.ghost_round_last_ghost_origin = undefined;
  2044.     }
  2045.     level setclientfield( "ghost_round_light_state", 0 );
  2046.     enable_ghost_zone_door_ai_clips();
  2047.     level notify( "ghost_round_end" );
  2048.     if ( isDefined( level.force_ghost_round_end ) && level.force_ghost_round_end )
  2049.     {
  2050.         level.force_ghost_round_end = undefined;
  2051.         return;
  2052.     }
  2053.     flag_set( "spawn_zombies" );
  2054.     flag_clear( "spawn_ghosts" );
  2055.     maps/mp/zombies/_zm_ai_ghost_ffotd::ghost_round_end();
  2056. }
  2057.  
  2058. should_last_ghost_drop_powerup()
  2059. {
  2060.     if ( flag( "time_bomb_restore_active" ) )
  2061.     {
  2062.         return 0;
  2063.     }
  2064.     if ( !isDefined( level.ghost_round_last_ghost_origin ) )
  2065.     {
  2066.         return 0;
  2067.     }
  2068.     return 1;
  2069. }
  2070.  
  2071. sndghostroundmus()
  2072. {
  2073.     level endon( "ghost_round_end" );
  2074.     ent = spawn( "script_origin", ( 1, 1, 1 ) );
  2075.     level.sndroundwait = 1;
  2076.     ent thread sndghostroundmus_end();
  2077.     ent endon( "sndGhostRoundEnd" );
  2078.     ent playsound( "mus_ghost_round_start" );
  2079.     wait 11;
  2080.     ent playloopsound( "mus_ghost_round_loop", 3 );
  2081. }
  2082.  
  2083. sndghostroundmus_end()
  2084. {
  2085.     level waittill( "ghost_round_end" );
  2086.     self notify( "sndGhostRoundEnd" );
  2087.     self stoploopsound( 1 );
  2088.     self playsoundwithnotify( "mus_ghost_round_over", "stingerDone" );
  2089.     self waittill( "stingerDone" );
  2090.     self delete();
  2091.     level.sndroundwait = 0;
  2092. }
  2093.  
  2094. sndghostroundready()
  2095. {
  2096.     level notify( "sndGhostRoundReady" );
  2097.     level endon( "sndGhostRoundReady" );
  2098.     mansion = ( 2830, 555, 436 );
  2099.     while ( 1 )
  2100.     {
  2101.         level waittill( "between_round_over" );
  2102.         if ( level.zombie_ghost_round_states.next_ghost_round_number == level.round_number )
  2103.         {
  2104.             playsoundatposition( "zmb_ghost_round_srt", mansion );
  2105.             ent = spawn( "script_origin", mansion );
  2106.             ent playloopsound( "zmb_ghost_round_lp", 3 );
  2107.             ent thread sndghostroundready_stoplp();
  2108.             break;
  2109.         }
  2110.         else
  2111.         {
  2112.         }
  2113.     }
  2114.     wait 15;
  2115.     level notify( "sndStopRoundReadyLp" );
  2116. }
  2117.  
  2118. sndghostroundready_stoplp()
  2119. {
  2120.     level waittill_either( "sndStopRoundReadyLp", "sndGhostRoundReady" );
  2121.     self stoploopsound( 3 );
  2122.     wait 3;
  2123.     self delete();
  2124. }
  2125.  
  2126. check_sending_away_zombie_followers()
  2127. {
  2128.     if ( flag_exists( "time_bomb_restore_active" ) && flag( "time_bomb_restore_active" ) )
  2129.     {
  2130.         return;
  2131.     }
  2132.     players = getplayers();
  2133.     valid_player_in_ghost_zone_count = 0;
  2134.     valid_player_count = 0;
  2135.     _a2522 = players;
  2136.     _k2522 = getFirstArrayKey( _a2522 );
  2137.     while ( isDefined( _k2522 ) )
  2138.     {
  2139.         player = _a2522[ _k2522 ];
  2140.         if ( is_player_valid( player ) )
  2141.         {
  2142.             valid_player_count++;
  2143.             if ( isDefined( player.is_in_ghost_zone ) && player.is_in_ghost_zone )
  2144.             {
  2145.                 valid_player_in_ghost_zone_count++;
  2146.                 break;
  2147.             }
  2148.             else
  2149.             {
  2150.                 player.zombie_followers_sent_away = 0;
  2151.             }
  2152.         }
  2153.         _k2522 = getNextArrayKey( _a2522, _k2522 );
  2154.     }
  2155.     if ( valid_player_count > 0 && valid_player_in_ghost_zone_count == valid_player_count )
  2156.     {
  2157.         if ( flag( "spawn_zombies" ) )
  2158.         {
  2159.             flag_clear( "spawn_zombies" );
  2160.         }
  2161.         zombies = get_round_enemy_array();
  2162.         _a2561 = zombies;
  2163.         _k2561 = getFirstArrayKey( _a2561 );
  2164.         while ( isDefined( _k2561 ) )
  2165.         {
  2166.             zombie = _a2561[ _k2561 ];
  2167.             if ( is_true( zombie.completed_emerging_into_playable_area ) && !is_true( zombie.zombie_path_bad ) )
  2168.             {
  2169.                 zombie notify( "bad_path" );
  2170.             }
  2171.             _k2561 = getNextArrayKey( _a2561, _k2561 );
  2172.         }
  2173.     }
  2174.     else if ( !flag( "spawn_zombies" ) )
  2175.     {
  2176.         flag_set( "spawn_zombies" );
  2177.     }
  2178. }
  2179.  
  2180. send_away_zombie_follower( player )
  2181. {
  2182.     self endon( "death" );
  2183.     dist_zombie = 0;
  2184.     dist_player = 0;
  2185.     dest = 0;
  2186.     awaydir = self.origin - player.origin;
  2187.     awaydir = ( awaydir[ 0 ], awaydir[ 1 ], 0 );
  2188.     awaydir = vectornormalize( awaydir );
  2189.     endpos = self.origin + vectorScale( awaydir, 600 );
  2190.     locs = array_randomize( level.enemy_dog_locations );
  2191.     i = 0;
  2192.     while ( i < locs.size )
  2193.     {
  2194.         dist_zombie = distancesquared( locs[ i ].origin, endpos );
  2195.         dist_player = distancesquared( locs[ i ].origin, player.origin );
  2196.         if ( dist_zombie < dist_player )
  2197.         {
  2198.             dest = i;
  2199.             break;
  2200.         }
  2201.         else
  2202.         {
  2203.             i++;
  2204.         }
  2205.     }
  2206.     self notify( "stop_find_flesh" );
  2207.     self notify( "zombie_acquire_enemy" );
  2208.     if ( isDefined( locs[ dest ] ) )
  2209.     {
  2210.         self setgoalpos( locs[ dest ].origin );
  2211.     }
  2212.     wait 5;
  2213.     self thread maps/mp/zombies/_zm_ai_basic::find_flesh();
  2214. }
  2215.  
  2216. outside_ghost_zone_spawning_think()
  2217. {
  2218.     level endon( "intermission" );
  2219.     if ( level.intermission )
  2220.     {
  2221.         return;
  2222.     }
  2223.     level endon( "ghost_round_end" );
  2224.     if ( !isDefined( level.female_ghost_spawner ) )
  2225.     {
  2226. /#
  2227.         assertmsg( "No female ghost spawner in the map." );
  2228. #/
  2229.         return;
  2230.     }
  2231.     while ( isDefined( level.zombie_ghost_round_states.active_zombie_locations ) )
  2232.     {
  2233.         i = 0;
  2234.         while ( i < level.zombie_ghost_round_states.active_zombie_locations.size )
  2235.         {
  2236.             if ( i >= 20 )
  2237.             {
  2238.                 return;
  2239.             }
  2240.             spawn_point = level.zombie_ghost_round_states.active_zombie_locations[ i ];
  2241.             ghost_ai = spawn_zombie( level.female_ghost_spawner, level.female_ghost_spawner.targetname, spawn_point );
  2242.             if ( isDefined( ghost_ai ) )
  2243.             {
  2244.                 ghost_ai setclientfield( "ghost_fx", 3 );
  2245.                 ghost_ai.spawn_point = spawn_point;
  2246.                 ghost_ai.is_ghost = 1;
  2247.             }
  2248.             else
  2249.             {
  2250. /#
  2251.                 assertmsg( "female ghost outside ghost zone: failed spawn" );
  2252. #/
  2253.                 return;
  2254.             }
  2255.             wait randomfloat( 0,3 );
  2256.             wait_network_frame();
  2257.             i++;
  2258.         }
  2259.     }
  2260. }
  2261.  
  2262. get_current_ghost_count()
  2263. {
  2264.     ghost_count = 0;
  2265.     ais = getaiarray( level.zombie_team );
  2266.     _a2673 = ais;
  2267.     _k2673 = getFirstArrayKey( _a2673 );
  2268.     while ( isDefined( _k2673 ) )
  2269.     {
  2270.         ai = _a2673[ _k2673 ];
  2271.         if ( isDefined( ai.is_ghost ) && ai.is_ghost )
  2272.         {
  2273.             ghost_count++;
  2274.         }
  2275.         _k2673 = getNextArrayKey( _a2673, _k2673 );
  2276.     }
  2277.     return ghost_count;
  2278. }
  2279.  
  2280. get_current_ghosts()
  2281. {
  2282.     ghosts = [];
  2283.     ais = getaiarray( level.zombie_team );
  2284.     _a2688 = ais;
  2285.     _k2688 = getFirstArrayKey( _a2688 );
  2286.     while ( isDefined( _k2688 ) )
  2287.     {
  2288.         ai = _a2688[ _k2688 ];
  2289.         if ( isDefined( ai.is_ghost ) && ai.is_ghost )
  2290.         {
  2291.             ghosts[ ghosts.size ] = ai;
  2292.         }
  2293.         _k2688 = getNextArrayKey( _a2688, _k2688 );
  2294.     }
  2295.     return ghosts;
  2296. }
  2297.  
  2298. set_player_moving_speed_scale( player, move_speed_scale )
  2299. {
  2300.     if ( isDefined( player ) )
  2301.     {
  2302.         player setmovespeedscale( move_speed_scale );
  2303.     }
  2304. }
  2305.  
  2306. player_moving_speed_scale_think()
  2307. {
  2308.     level endon( "intermission" );
  2309.     if ( isDefined( level.intermission ) && level.intermission )
  2310.     {
  2311.         return;
  2312.     }
  2313.     level endon( "ghost_round_end" );
  2314.     while ( 1 )
  2315.     {
  2316.         players = get_players();
  2317.         _a2723 = players;
  2318.         _k2723 = getFirstArrayKey( _a2723 );
  2319.         while ( isDefined( _k2723 ) )
  2320.         {
  2321.             player = _a2723[ _k2723 ];
  2322.             if ( !is_player_valid( player, undefined, 1 ) )
  2323.             {
  2324.             }
  2325.             else if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() )
  2326.             {
  2327.                 set_player_moving_speed_scale( player, 1 );
  2328.             }
  2329.             else
  2330.             {
  2331.                 if ( isDefined( player.ghost_next_drain_time_left ) )
  2332.                 {
  2333.                     player.ghost_next_drain_time_left -= 0,1;
  2334.                 }
  2335.                 player_slow_down = 0;
  2336.                 ais = getaiarray( level.zombie_team );
  2337.                 _a2743 = ais;
  2338.                 _k2743 = getFirstArrayKey( _a2743 );
  2339.                 while ( isDefined( _k2743 ) )
  2340.                 {
  2341.                     ai = _a2743[ _k2743 ];
  2342.                     if ( isDefined( ai.is_ghost ) && ai.is_ghost && can_drain_points( ai.origin, player.origin ) )
  2343.                     {
  2344.                         player_slow_down = 1;
  2345.                         set_player_moving_speed_scale( player, 0,5 );
  2346.                         if ( isDefined( player.ghost_next_drain_time_left ) && player.ghost_next_drain_time_left < 0 && isDefined( ai.favoriteenemy ) && player != ai.favoriteenemy )
  2347.                         {
  2348.                             give_player_rewards( player );
  2349.                             points_to_drain = 2000;
  2350.                             if ( player.score < points_to_drain )
  2351.                             {
  2352.                                 if ( player.score > 0 )
  2353.                                 {
  2354.                                     points_to_drain = player.score;
  2355.                                     break;
  2356.                                 }
  2357.                                 else
  2358.                                 {
  2359.                                     points_to_drain = 0;
  2360.                                 }
  2361.                             }
  2362.                             if ( points_to_drain > 0 )
  2363.                             {
  2364.                                 player maps/mp/zombies/_zm_score::minus_to_player_score( points_to_drain );
  2365.                                 player playsoundtoplayer( "zmb_ai_ghost_money_drain", player );
  2366.                             }
  2367.                             else
  2368.                             {
  2369.                                 if ( player.health > 0 && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() )
  2370.                                 {
  2371.                                     player dodamage( 25, ai.origin, ai );
  2372.                                 }
  2373.                             }
  2374.                             player.ghost_next_drain_time_left = 2;
  2375.                         }
  2376.                         break;
  2377.                     }
  2378.                     else
  2379.                     {
  2380.                         _k2743 = getNextArrayKey( _a2743, _k2743 );
  2381.                     }
  2382.                 }
  2383.                 if ( player_slow_down == 0 )
  2384.                 {
  2385.                     set_player_moving_speed_scale( player, 1 );
  2386.                 }
  2387.             }
  2388.             _k2723 = getNextArrayKey( _a2723, _k2723 );
  2389.         }
  2390.         wait 0,1;
  2391.     }
  2392. }
  2393.  
  2394. give_player_rewards( player )
  2395. {
  2396.     if ( player is_player_placeable_mine( "claymore_zm" ) )
  2397.     {
  2398.         claymore_count = player getweaponammostock( "claymore_zm" ) + 1;
  2399.         if ( claymore_count >= 2 )
  2400.         {
  2401.             claymore_count = 2;
  2402.             player notify( "zmb_disable_claymore_prompt" );
  2403.         }
  2404.         player setweaponammostock( "claymore_zm", claymore_count );
  2405.     }
  2406.     else
  2407.     {
  2408.         lethal_grenade_name = player get_player_lethal_grenade();
  2409.         if ( player hasweapon( lethal_grenade_name ) )
  2410.         {
  2411.             lethal_grenade_count = player getweaponammoclip( lethal_grenade_name ) + 1;
  2412.             if ( lethal_grenade_count > 4 )
  2413.             {
  2414.                 lethal_grenade_count = 4;
  2415.             }
  2416.             player setweaponammoclip( lethal_grenade_name, lethal_grenade_count );
  2417.         }
  2418.     }
  2419. }
  2420.  
  2421. set_player_current_ghost_zone( player, ghost_zone_name )
  2422. {
  2423.     if ( isDefined( player ) )
  2424.     {
  2425.         player.current_ghost_room_name = ghost_zone_name;
  2426.     }
  2427. }
  2428.  
  2429. can_start_ghost_round_presentation()
  2430. {
  2431. /#
  2432.     if ( isDefined( level.force_no_ghost ) && level.force_no_ghost )
  2433.     {
  2434.         return 0;
  2435. #/
  2436.     }
  2437.     if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) && level.zombie_ghost_round_states.is_first_ghost_round_finished )
  2438.     {
  2439.         if ( level.round_number < ( level.zombie_ghost_round_states.current_ghost_round_number + 4 ) )
  2440.         {
  2441.             return 0;
  2442.         }
  2443.     }
  2444.     if ( is_ghost_round_started() )
  2445.     {
  2446.         return 0;
  2447.     }
  2448.     if ( flag( "time_bomb_round_killed" ) && !flag( "time_bomb_enemies_restored" ) )
  2449.     {
  2450.         return 0;
  2451.     }
  2452.     return 1;
  2453. }
  2454.  
  2455. can_start_ghost_round_presentation_stage_1()
  2456. {
  2457.     if ( isDefined( level.zombie_ghost_round_states.presentation_stage_1_started ) && level.zombie_ghost_round_states.presentation_stage_1_started )
  2458.     {
  2459.         return 0;
  2460.     }
  2461.     return 1;
  2462. }
  2463.  
  2464. can_start_ghost_round_presentation_stage_2()
  2465. {
  2466.     if ( isDefined( level.zombie_ghost_round_states.presentation_stage_2_started ) && level.zombie_ghost_round_states.presentation_stage_2_started )
  2467.     {
  2468.         return 0;
  2469.     }
  2470.     if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) && level.zombie_ghost_round_states.is_first_ghost_round_finished )
  2471.     {
  2472.         if ( level.round_number < ( ( level.zombie_ghost_round_states.current_ghost_round_number + 4 ) + 1 ) )
  2473.         {
  2474.             return 0;
  2475.         }
  2476.     }
  2477.     return 1;
  2478. }
  2479.  
  2480. can_start_ghost_round_presentation_stage_3()
  2481. {
  2482.     if ( isDefined( level.zombie_ghost_round_states.presentation_stage_3_started ) && level.zombie_ghost_round_states.presentation_stage_3_started )
  2483.     {
  2484.         return 0;
  2485.     }
  2486.     if ( isDefined( level.zombie_ghost_round_states.is_first_ghost_round_finished ) && level.zombie_ghost_round_states.is_first_ghost_round_finished )
  2487.     {
  2488.         if ( level.round_number < ( ( level.zombie_ghost_round_states.current_ghost_round_number + 4 ) + 2 ) )
  2489.         {
  2490.             return 0;
  2491.         }
  2492.     }
  2493.     return 1;
  2494. }
  2495.  
  2496. get_next_spot_during_ghost_round_presentation()
  2497. {
  2498.     if ( isDefined( level.current_ghost_window_index ) )
  2499.     {
  2500.         standing_location_index = randomint( level.ghost_front_standing_locations.size );
  2501.         while ( standing_location_index == level.current_ghost_window_index )
  2502.         {
  2503.             standing_location_index = randomint( level.ghost_front_standing_locations.size );
  2504.         }
  2505.         level.current_ghost_window_index = standing_location_index;
  2506.     }
  2507.     else
  2508.     {
  2509.         level.current_ghost_window_index = 1;
  2510.     }
  2511.     return level.ghost_front_standing_locations[ level.current_ghost_window_index ];
  2512. }
  2513.  
  2514. spawn_ghost_round_presentation_ghost()
  2515. {
  2516.     spawn_point = get_next_spot_during_ghost_round_presentation();
  2517.     ghost = spawn( "script_model", spawn_point.origin );
  2518.     ghost.angles = spawn_point.angles;
  2519.     ghost setmodel( "c_zom_zombie_buried_ghost_woman_fb" );
  2520.     if ( isDefined( ghost ) )
  2521.     {
  2522.         ghost.spawn_point = spawn_point;
  2523.         ghost.for_ghost_round_presentation = 1;
  2524.         level.ghost_round_presentation_ghost = ghost;
  2525.     }
  2526.     else
  2527.     {
  2528. /#
  2529.         assertmsg( "ghost round presentation ghost: failed spawn" );
  2530. #/
  2531.         return;
  2532.     }
  2533.     wait 0,5;
  2534.     ghost useanimtree( -1 );
  2535.     ghost setanim( %ai_zombie_ghost_idle );
  2536.     ghost.script_mover = spawn( "script_origin", ghost.origin );
  2537.     ghost.script_mover.angles = ghost.angles;
  2538.     ghost linkto( ghost.script_mover );
  2539.     ghost setclientfield( "sndGhostAudio", 1 );
  2540. }
  2541.  
  2542. ghost_round_presentation_think()
  2543. {
  2544.     level endon( "intermission" );
  2545.     if ( isDefined( level.intermission ) && level.intermission )
  2546.     {
  2547.         return;
  2548.     }
  2549.     if ( !isDefined( level.sndmansionent ) )
  2550.     {
  2551.         level.sndmansionent = spawn( "script_origin", ( 2830, 555, 436 ) );
  2552.     }
  2553.     flag_wait( "start_zombie_round_logic" );
  2554.     while ( 1 )
  2555.     {
  2556.         if ( can_start_ghost_round_presentation() )
  2557.         {
  2558.             if ( can_start_ghost_round_presentation_stage_1() )
  2559.             {
  2560.                 level.zombie_ghost_round_states.presentation_stage_1_started = 1;
  2561.                 spawn_ghost_round_presentation_ghost();
  2562.                 if ( isDefined( level.ghost_round_presentation_ghost ) )
  2563.                 {
  2564.                     level.ghost_round_presentation_ghost thread ghost_switch_windows();
  2565.                 }
  2566.             }
  2567.             if ( can_start_ghost_round_presentation_stage_2() )
  2568.             {
  2569.                 level.zombie_ghost_round_states.presentation_stage_2_started = 1;
  2570.                 level.sndmansionent playloopsound( "zmb_ghost_round_lp_quiet", 3 );
  2571.                 level setclientfield( "ghost_round_light_state", 1 );
  2572.             }
  2573.             if ( can_start_ghost_round_presentation_stage_3() )
  2574.             {
  2575.                 level.zombie_ghost_round_states.presentation_stage_3_started = 1;
  2576.                 level.sndmansionent playloopsound( "zmb_ghost_round_lp_loud", 3 );
  2577.                 if ( isDefined( level.ghost_round_presentation_ghost ) )
  2578.                 {
  2579.                     level.ghost_round_presentation_ghost thread ghost_round_presentation_sound();
  2580.                 }
  2581.             }
  2582.         }
  2583.         wait 0,1;
  2584.     }
  2585. }
  2586.  
  2587. ghost_switch_windows()
  2588. {
  2589.     level endon( "intermission" );
  2590.     self endon( "death" );
  2591.     while ( 1 )
  2592.     {
  2593.         next_spot = get_next_spot_during_ghost_round_presentation();
  2594.         self setclientfield( "ghost_fx", 5 );
  2595.         self setclientfield( "sndGhostAudio", 0 );
  2596.         self ghost();
  2597.         self.script_mover moveto( next_spot.origin, 1 );
  2598.         self.script_mover waittill( "movedone" );
  2599.         self.script_mover.origin = next_spot.origin;
  2600.         self.script_mover.angles = next_spot.angles;
  2601.         self setclientfield( "ghost_fx", 3 );
  2602.         self setclientfield( "sndGhostAudio", 1 );
  2603.         self show();
  2604.         wait 6;
  2605.     }
  2606. }
  2607.  
  2608. ghost_round_presentation_sound()
  2609. {
  2610.     level endon( "intermission" );
  2611.     self endon( "death" );
  2612.     while ( 1 )
  2613.     {
  2614.         players = getplayers();
  2615.         _a3071 = players;
  2616.         _k3071 = getFirstArrayKey( _a3071 );
  2617.         while ( isDefined( _k3071 ) )
  2618.         {
  2619.             player = _a3071[ _k3071 ];
  2620.             if ( is_player_valid( player ) )
  2621.             {
  2622.                 vox_index = randomint( level.ghost_vox.size );
  2623.                 vox_line = level.ghost_vox[ vox_index ];
  2624.                 self playsoundtoplayer( vox_line, player );
  2625.             }
  2626.             _k3071 = getNextArrayKey( _a3071, _k3071 );
  2627.         }
  2628.         wait randomintrange( 2, 6 );
  2629.     }
  2630. }
  2631.  
  2632. ghost_round_presentation_reset()
  2633. {
  2634.     if ( isDefined( level.sndmansionent ) )
  2635.     {
  2636.         level.sndmansionent stoploopsound( 3 );
  2637.     }
  2638.     if ( isDefined( level.ghost_round_presentation_ghost ) )
  2639.     {
  2640.         level.ghost_round_presentation_ghost.skip_death_notetracks = 1;
  2641.         level.ghost_round_presentation_ghost.nodeathragdoll = 1;
  2642.         level.ghost_round_presentation_ghost setclientfield( "ghost_fx", 5 );
  2643.         wait_network_frame();
  2644.         level.ghost_round_presentation_ghost delete();
  2645.         level.ghost_round_presentation_ghost = undefined;
  2646.     }
  2647.     level.zombie_ghost_round_states.presentation_stage_1_started = 0;
  2648.     level.zombie_ghost_round_states.presentation_stage_2_started = 0;
  2649.     level.zombie_ghost_round_states.presentation_stage_3_started = 0;
  2650. }
  2651.  
  2652. behave_after_fountain_transport( player )
  2653. {
  2654.     wait 1;
  2655.     if ( isDefined( player ) )
  2656.     {
  2657.         set_player_current_ghost_zone( player, undefined );
  2658.         level.zombie_ghost_round_states.is_teleporting = 1;
  2659.         ais = getaiarray( level.zombie_team );
  2660.         ghost_teleport_point_index = 0;
  2661.         ais_need_teleported = [];
  2662.         _a3133 = ais;
  2663.         _k3133 = getFirstArrayKey( _a3133 );
  2664.         while ( isDefined( _k3133 ) )
  2665.         {
  2666.             ai = _a3133[ _k3133 ];
  2667.             if ( isDefined( ai.is_ghost ) && ai.is_ghost && isDefined( ai.favoriteenemy ) && ai.favoriteenemy == player )
  2668.             {
  2669.                 ais_need_teleported[ ais_need_teleported.size ] = ai;
  2670.             }
  2671.             _k3133 = getNextArrayKey( _a3133, _k3133 );
  2672.         }
  2673.         _a3141 = ais_need_teleported;
  2674.         _k3141 = getFirstArrayKey( _a3141 );
  2675.         while ( isDefined( _k3141 ) )
  2676.         {
  2677.             ai_need_teleported = _a3141[ _k3141 ];
  2678.             if ( ghost_teleport_point_index == level.ghost_zone_start_lower_locations.size )
  2679.             {
  2680.                 ghost_teleport_point_index = 0;
  2681.             }
  2682.             teleport_point_origin = level.ghost_zone_start_lower_locations[ ghost_teleport_point_index ].origin;
  2683.             teleport_point_angles = level.ghost_zone_start_lower_locations[ ghost_teleport_point_index ].angles;
  2684.             ai_need_teleported forceteleport( teleport_point_origin, teleport_point_angles );
  2685.             ghost_teleport_point_index++;
  2686.             wait_network_frame();
  2687.             _k3141 = getNextArrayKey( _a3141, _k3141 );
  2688.         }
  2689.         wait 1;
  2690.         level.zombie_ghost_round_states.is_teleporting = 0;
  2691.     }
  2692. }
  2693.  
  2694. init_time_bomb_ghost_rounds()
  2695. {
  2696.     register_time_bomb_enemy( "ghost", ::is_ghost_round, ::save_ghost_data, ::time_bomb_respawns_ghosts );
  2697.     level.ghost_custom_think_logic = ::time_bomb_ghost_respawn_think;
  2698.     maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_save( ::time_bomb_global_data_save_ghosts );
  2699.     maps/mp/zombies/_zm_weap_time_bomb::time_bomb_add_custom_func_global_restore( ::time_bomb_global_data_restore_ghosts );
  2700.     level._time_bomb.custom_funcs_get_enemies = ::time_bomb_custom_get_enemy_func;
  2701.     maps/mp/zombies/_zm_weap_time_bomb::register_time_bomb_enemy_save_filter( "zombie", ::is_ghost );
  2702. }
  2703.  
  2704. is_ghost()
  2705. {
  2706.     if ( isDefined( self.is_ghost )return !self.is_ghost;
  2707. }
  2708.  
  2709. is_ghost_round()
  2710. {
  2711.     return flag( "spawn_ghosts" );
  2712. }
  2713.  
  2714. save_ghost_data( s_data )
  2715. {
  2716.     s_data.origin = self.origin;
  2717.     s_data.angles = self.angles;
  2718.     s_data.is_ghost = self.is_ghost;
  2719.     s_data.spawn_point = self.spawn_point;
  2720.     if ( level.zombie_ghost_round_states.any_player_in_ghost_zone )
  2721.     {
  2722.         s_data.is_spawned_in_ghost_zone = self.is_spawned_in_ghost_zone;
  2723.     }
  2724.     else
  2725.     {
  2726.         s_data.is_spawned_in_ghost_zone = 0;
  2727.     }
  2728.     s_data.is_spawned_in_ghost_zone_actual = self.is_spawned_in_ghost_zone;
  2729.     s_data.find_target = self.find_target;
  2730.     s_data.favoriteenemy = self.favoriteenemy;
  2731.     s_data.ignore_timebomb_slowdown = self.ignore_timebomb_slowdown;
  2732. }
  2733.  
  2734. time_bomb_respawns_ghosts( save_struct )
  2735. {
  2736.     flag_clear( "spawn_ghosts" );
  2737.     ghost_round_presentation_reset();
  2738.     level.force_ghost_round_end = 1;
  2739.     level.force_ghost_round_start = 1;
  2740.     level waittill( "ghost_round_end" );
  2741.     level thread respawn_ghosts_outside_mansion( save_struct );
  2742.     level thread _respawn_ghost_failsafe();
  2743.     if ( !save_struct.custom_data.ghost_data.round_first_done )
  2744.     {
  2745.         level.zombie_ghost_round_states.is_first_ghost_round_finished = 0;
  2746.     }
  2747.     flag_wait( "time_bomb_enemies_restored" );
  2748.     level.force_ghost_round_end = undefined;
  2749.     level.force_ghost_round_start = undefined;
  2750.     level.zombie_ghost_round_states.is_started = save_struct.custom_data.ghost_data.round_started;
  2751. }
  2752.  
  2753. respawn_ghosts_outside_mansion( save_struct )
  2754. {
  2755.     a_spawns_outside_mansion = [];
  2756.     i = 0;
  2757.     while ( i < save_struct.enemies.size )
  2758.     {
  2759.         if ( isDefined( save_struct.enemies[ i ].is_spawned_in_ghost_zone ) && !save_struct.enemies[ i ].is_spawned_in_ghost_zone )
  2760.         {
  2761.             a_spawns_outside_mansion[ a_spawns_outside_mansion.size ] = save_struct.enemies[ i ];
  2762.         }
  2763.         i++;
  2764.     }
  2765.     level.zombie_ghost_round_states.active_zombie_locations = a_spawns_outside_mansion;
  2766.     save_struct.total_respawns = a_spawns_outside_mansion.size;
  2767. }
  2768.  
  2769. time_bomb_custom_get_enemy_func()
  2770. {
  2771.     a_enemies = [];
  2772.     a_valid_enemies = [];
  2773.     a_enemies = getaispeciesarray( level.zombie_team, "all" );
  2774.     i = 0;
  2775.     while ( i < a_enemies.size )
  2776.     {
  2777.         if ( isDefined( a_enemies[ i ].ignore_enemy_count ) && a_enemies[ i ].ignore_enemy_count && isDefined( a_enemies[ i ].is_ghost ) || !a_enemies[ i ].is_ghost && isDefined( level.ghost_round_presentation_ghost ) && level.ghost_round_presentation_ghost == a_enemies[ i ] )
  2778.         {
  2779.             i++;
  2780.             continue;
  2781.         }
  2782.         else
  2783.         {
  2784.             a_valid_enemies[ a_valid_enemies.size ] = a_enemies[ i ];
  2785.         }
  2786.         i++;
  2787.     }
  2788.     return a_valid_enemies;
  2789. }
  2790.  
  2791. time_bomb_global_data_save_ghosts()
  2792. {
  2793.     s_temp = spawnstruct();
  2794.     s_temp.ghost_count = level.zombie_ghost_count;
  2795.     s_temp.round_started = level.zombie_ghost_round_states.is_started;
  2796.     s_temp.round_first_done = level.zombie_ghost_round_states.is_first_ghost_round_finished;
  2797.     s_temp.round_next = level.zombie_ghost_round_states.next_ghost_round_number;
  2798.     s_temp.zombie_total = level.zombie_ghost_round_states.round_zombie_total;
  2799.     self.ghost_data = s_temp;
  2800. }
  2801.  
  2802. time_bomb_global_data_restore_ghosts()
  2803. {
  2804.     level.zombie_ghost_count = 0;
  2805.     level.zombie_ghost_round_states.is_started = self.ghost_data.round_started;
  2806.     level.zombie_ghost_round_states.is_first_ghost_round_finished = self.ghost_data.round_first_done;
  2807.     level.zombie_ghost_round_states.next_ghost_round_number = self.ghost_data.round_next;
  2808.     level.zombie_ghost_round_states.round_zombie_total = self.ghost_data.zombie_total;
  2809.     _a3311 = get_players();
  2810.     _k3311 = getFirstArrayKey( _a3311 );
  2811.     while ( isDefined( _k3311 ) )
  2812.     {
  2813.         player = _a3311[ _k3311 ];
  2814.         player.ghost_count = 0;
  2815.         _k3311 = getNextArrayKey( _a3311, _k3311 );
  2816.     }
  2817. }
  2818.  
  2819. time_bomb_ghost_respawn_think()
  2820. {
  2821.     if ( flag( "time_bomb_round_killed" ) && !flag( "time_bomb_enemies_restored" ) )
  2822.     {
  2823.         if ( isDefined( level.timebomb_override_struct ) )
  2824.         {
  2825.             save_struct = level.timebomb_override_struct;
  2826.         }
  2827.         else
  2828.         {
  2829.             save_struct = level.time_bomb_save_data;
  2830.         }
  2831.         if ( !isDefined( save_struct.respawn_counter ) )
  2832.         {
  2833.             save_struct.respawn_counter = 0;
  2834.         }
  2835.         n_index = save_struct.respawn_counter;
  2836.         save_struct.respawn_counter++;
  2837.         if ( save_struct.enemies.size > 0 && isDefined( save_struct.enemies ) && n_index < save_struct.enemies.size )
  2838.         {
  2839.             while ( isDefined( save_struct.enemies[ n_index ] ) && isDefined( save_struct.enemies[ n_index ].is_spawned_in_ghost_zone ) && save_struct.enemies[ n_index ].is_spawned_in_ghost_zone )
  2840.             {
  2841.                 save_struct.respawn_counter++;
  2842.                 n_index = save_struct.respawn_counter;
  2843.             }
  2844.             if ( isDefined( save_struct.enemies[ n_index ] ) )
  2845.             {
  2846.                 self _restore_ghost_data( save_struct, n_index );
  2847.             }
  2848.         }
  2849.         if ( save_struct.respawn_counter >= save_struct.enemies.size || save_struct.enemies.size == 0 )
  2850.         {
  2851.             flag_set( "time_bomb_enemies_restored" );
  2852.             level.zombie_ghost_round_states.active_zombie_locations = [];
  2853.         }
  2854.         flag_wait( "time_bomb_enemies_restored" );
  2855.         self thread restore_ghost_failsafe();
  2856.     }
  2857. }
  2858.  
  2859. restore_ghost_failsafe()
  2860. {
  2861.     self endon( "death" );
  2862.     wait randomfloatrange( 2, 3 );
  2863.     if ( !isDefined( self.state ) )
  2864.     {
  2865.         self.respawned_by_time_bomb = 1;
  2866.         self thread ghost_think();
  2867.     }
  2868.     else
  2869.     {
  2870.         if ( isDefined( level.ghost_round_presentation_ghost ) && level.ghost_round_presentation_ghost == self )
  2871.         {
  2872.             ghost_round_presentation_reset();
  2873.             wait_network_frame();
  2874.             self thread ghost_think();
  2875.         }
  2876.     }
  2877.     self.passed_failsafe = 1;
  2878. }
  2879.  
  2880. _restore_ghost_data( save_struct, n_index )
  2881. {
  2882.     s_data = save_struct.enemies[ n_index ];
  2883.     playfxontag( level._effect[ "time_bomb_respawns_enemy" ], self, "J_SpineLower" );
  2884.     self.origin = s_data.origin;
  2885.     self.angles = s_data.angles;
  2886.     self.is_ghost = s_data.is_ghost;
  2887.     self.spawn_point = s_data.spawn_point;
  2888.     self.is_spawned_in_ghost_zone = s_data.is_spawned_in_ghost_zone;
  2889.     self.find_target = s_data.find_target;
  2890.     if ( isDefined( s_data.favoriteenemy ) )
  2891.     {
  2892.         self.favoriteenemy = s_data.favoriteenemy;
  2893.     }
  2894.     self.ignore_timebomb_slowdown = 1;
  2895.     self setgoalpos( self.origin );
  2896. }
  2897.  
  2898. _respawn_ghost_failsafe()
  2899. {
  2900.     n_counter = 0;
  2901.     while ( !flag( "time_bomb_enemies_restored" ) && n_counter < 20 )
  2902.     {
  2903.         if ( get_current_actor_count() >= level.zombie_ai_limit || isDefined( level.time_bomb_save_data.total_respawns ) && level.time_bomb_save_data.total_respawns == 0 )
  2904.         {
  2905.             flag_set( "time_bomb_enemies_restored" );
  2906.         }
  2907.         n_counter++;
  2908.         wait 0,5;
  2909.     }
  2910.     flag_set( "time_bomb_enemies_restored" );
  2911. }
  2912.  
  2913. devgui_warp_to_mansion()
  2914. {
  2915. /#
  2916.     player = gethostplayer();
  2917.     player setorigin( ( 2324, 560, 148 ) );
  2918.     player setplayerangles( ( 1, 1, 1 ) );
  2919. #/
  2920. }
  2921.  
  2922. devgui_toggle_no_ghost()
  2923. {
  2924. /#
  2925.     level.force_no_ghost = !level.force_no_ghost;
  2926. #/
  2927. }
  2928.  
  2929. draw_debug_line( from, to, color, time, depth_test )
  2930. {
  2931. /#
  2932.     if ( isDefined( level.ghost_debug ) && level.ghost_debug )
  2933.     {
  2934.         if ( !isDefined( time ) )
  2935.         {
  2936.             time = 1000;
  2937.         }
  2938.         line( from, to, color, 1, depth_test, time );
  2939. #/
  2940.     }
  2941. }
  2942.  
  2943. draw_debug_star( origin, color, time )
  2944. {
  2945. /#
  2946.     if ( isDefined( level.ghost_debug ) && level.ghost_debug )
  2947.     {
  2948.         if ( !isDefined( time ) )
  2949.         {
  2950.             time = 1000;
  2951.         }
  2952.         if ( !isDefined( color ) )
  2953.         {
  2954.             color = ( 1, 1, 1 );
  2955.         }
  2956.         debugstar( origin, time, color );
  2957. #/
  2958.     }
  2959. }
  2960.  
  2961. draw_debug_box( origin, mins, maxs, yaw, color, time )
  2962. {
  2963. /#
  2964.     if ( isDefined( level.ghost_debug ) && level.ghost_debug )
  2965.     {
  2966.         if ( !isDefined( time ) )
  2967.         {
  2968.             time = 1000;
  2969.         }
  2970.         if ( !isDefined( color ) )
  2971.         {
  2972.             color = ( 1, 1, 1 );
  2973.         }
  2974.         box( origin, mins, maxs, yaw, color, 1, 0, 1 );
  2975. #/
  2976.     }
  2977. }
Advertisement
Add Comment
Please, Sign In to add comment