Guest User

Untitled

a guest
Sep 28th, 2016
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 179.32 KB | None | 0 0
  1. #using scripts\codescripts\struct;
  2.  
  3. #using scripts\shared\aat_shared;
  4. #using scripts\shared\ai_puppeteer_shared;
  5. #using scripts\shared\archetype_shared\archetype_shared;
  6. #using scripts\shared\array_shared;
  7. #using scripts\shared\callbacks_shared;
  8. #using scripts\shared\clientfield_shared;
  9. #using scripts\shared\demo_shared;
  10. #using scripts\shared\flag_shared;
  11. #using scripts\shared\hud_util_shared;
  12. #using scripts\shared\laststand_shared;
  13. #using scripts\shared\lui_shared;
  14. #using scripts\shared\math_shared;
  15. #using scripts\shared\scoreevents_shared;
  16. #using scripts\shared\system_shared;
  17. #using scripts\shared\util_shared;
  18. #using scripts\shared\visionset_mgr_shared;
  19. #using scripts\zm\gametypes\_globallogic;
  20. #using scripts\zm\gametypes\_globallogic_vehicle;
  21.  
  22. #using scripts\zm\_bb;
  23.  
  24. #using scripts\shared\ai\systems\gib;
  25.  
  26. #insert scripts\shared\shared.gsh;
  27. #insert scripts\shared\version.gsh;
  28. #insert scripts\shared\ai\systems\gib.gsh;
  29. #insert scripts\shared\archetype_shared\archetype_shared.gsh;
  30.  
  31. #using scripts\zm\gametypes\_weapons;
  32. #using scripts\zm\gametypes\_zm_gametype;
  33. #using scripts\zm\gametypes\_globallogic_spawn;
  34. #using scripts\zm\gametypes\_globallogic_player;
  35.  
  36. #using scripts\zm\_util;
  37. #using scripts\zm\_zm_attackables;
  38. #using scripts\zm\_zm_audio;
  39. #using scripts\zm\_zm_bgb;
  40. #using scripts\zm\_zm_bgb_token;
  41. #using scripts\zm\_zm_blockers;
  42. #using scripts\zm\_zm_bot;
  43. #using scripts\zm\_zm_daily_challenges;
  44. #using scripts\zm\_zm_equipment;
  45. #using scripts\zm\_zm_ffotd;
  46. #using scripts\zm\_zm_game_module;
  47. #using scripts\zm\_zm_hero_weapon;
  48. #using scripts\zm\_zm_laststand;
  49. #using scripts\zm\_zm_melee_weapon;
  50. #using scripts\zm\_zm_perks;
  51. #using scripts\zm\_zm_pers_upgrades;
  52. #using scripts\zm\_zm_pers_upgrades_functions;
  53. #using scripts\zm\_zm_pers_upgrades_system;
  54. #using scripts\zm\_zm_placeable_mine;
  55. #using scripts\zm\_zm_player;
  56. #using scripts\zm\_zm_powerups;
  57. #using scripts\zm\_zm_score;
  58. #using scripts\zm\_zm_spawner;
  59. #using scripts\zm\_zm_stats;
  60. #using scripts\zm\_zm_timer;
  61. #using scripts\zm\_zm_unitrigger;
  62. #using scripts\zm\_zm_utility;
  63. #using scripts\zm\_zm_weapons;
  64. #using scripts\zm\_zm_zonemgr;
  65. #using scripts\shared\ai_shared;
  66.  
  67. // AATs
  68. #insert scripts\shared\aat_zm.gsh;
  69. #using scripts\zm\aats\_zm_aat_blast_furnace;
  70. #using scripts\zm\aats\_zm_aat_dead_wire;
  71. #using scripts\zm\aats\_zm_aat_fire_works;
  72. #using scripts\zm\aats\_zm_aat_thunder_wall;
  73. #using scripts\zm\aats\_zm_aat_turned;
  74.  
  75. #using scripts\zm\craftables\_zm_craftables;
  76.  
  77. #using scripts\shared\ai\zombie_death;
  78. #using scripts\shared\ai\zombie_utility;
  79.  
  80. #insert scripts\shared\ai\zombie.gsh;
  81. #insert scripts\zm\_zm_laststand.gsh;
  82. #insert scripts\zm\_zm_perks.gsh;
  83. #insert scripts\zm\_zm_utility.gsh;
  84.  
  85. #precache( "material", "hud_chalk_1" );
  86. #precache( "material", "hud_chalk_2" );
  87. #precache( "material", "hud_chalk_3" );
  88. #precache( "material", "hud_chalk_4" );
  89. #precache( "material", "hud_chalk_5" );
  90.  
  91. #precache( "material", "zom_icon_community_pot" );
  92. #precache( "material", "zom_icon_community_pot_strip" );
  93.  
  94. #precache( "material","zom_icon_player_life");
  95.  
  96. #precache( "string", "ZOMBIE_WEAPONCOSTAMMO" );
  97. #precache( "string", "ZOMBIE_ROUND" );
  98. #precache( "string", "SCRIPT_PLUS" );
  99. #precache( "string", "ZOMBIE_GAME_OVER" );
  100. #precache( "string", "ZOMBIE_SURVIVED_ROUND" );
  101. #precache( "string", "ZOMBIE_SURVIVED_ROUNDS" );
  102. #precache( "string", "ZOMBIE_SURVIVED_NOMANS" );
  103. #precache( "string", "ZOMBIE_EXTRA_LIFE" );
  104. #precache( "string", "ZOMBIE_UNDEFINED" );
  105. #precache( "triggerstring", "ZOMBIE_ELECTRIC_SWITCH" );
  106. #precache( "triggerstring", "ZOMBIE_NEED_POWER" );
  107. // Random Treasure Chest
  108. #precache( "string", "ZOMBIE_RANDOM_WEAPON_COST" );
  109. // Weapons
  110. #precache( "string", "ZOMBIE_WEAPON_COSTONLYFILL_500" );
  111. #precache( "triggerstring", "ZOMBIE_WEAPON_COSTONLYFILL_2000" );
  112. #precache( "triggerstring", "ZOMBIE_WEAPONAMMOONLY_250" );
  113. #precache( "triggerstring", "ZOMBIE_WEAPONCOSTAMMO_UPGRADE_500_250" );
  114. // Barrier Pieces
  115. #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_10" );
  116. #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_20" );
  117. #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_50" );
  118. #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_100" );
  119. // REWARD Barrier Pieces
  120. #precache( "string", "ZOMBIE_BUTTON_REWARD_BARRIER" );
  121. // Debris
  122. #precache( "string", "ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_COST" );
  123. // Doors
  124. #precache( "string", "ZOMBIE_BUTTON_BUY_OPEN_DOOR_COST" );
  125. #precache( "string", "ZOMBIE_BUTTON_BUY_CLOSE_DOOR" );
  126.  
  127. #precache( "triggerstring", "ZOMBIE_BUTTON_REWARD_BARRIER" );
  128.  
  129. #precache( "fx", "_t6/maps/zombie/fx_zombie_bar_break" );
  130. #precache( "fx", "_t6/maps/zombie/fx_zombie_bar_break_lite" );
  131. #precache( "fx", "_t6/maps/zombie/fx_fog_zombie_amb" );
  132. #precache( "fx", "zombie/fx_weapon_box_open_glow_zmb" );
  133. #precache( "fx", "zombie/fx_weapon_box_closed_glow_zmb" );
  134. #precache( "fx", "zombie/fx_glow_eye_orange" );
  135. #precache( "fx", "zombie/fx_bul_flesh_head_fatal_zmb" );
  136. #precache( "fx", "zombie/fx_bul_flesh_head_nochunks_zmb" );
  137. #precache( "fx", "zombie/fx_bul_flesh_neck_spurt_zmb" );
  138. #precache( "fx", "_t6/maps/zombie/fx_zombie_tesla_neck_spurt" );
  139. #precache( "fx", "zombie/fx_blood_torso_explo_zmb" );
  140. #precache( "fx", "zombie/fx_blood_torso_explo_lg_zmb" );
  141. #precache( "fx", "zombie/fx_spawn_dirt_hand_burst_zmb" );
  142. #precache( "fx", "zombie/fx_spawn_dirt_body_billowing_zmb" );
  143. #precache( "fx", "zombie/fx_spawn_dirt_body_dustfalling_zmb" );
  144. #precache( "fx", "zombie/fx_fire_torso_zmb" );
  145. #precache( "fx", "_t6/explosions/fx_default_explosion" );
  146. #precache( "fx", "_t6/maps/zombie/fx_zmb_tanzit_upgrade" );
  147.  
  148. #precache( "menu", "StartMenu_Main" );
  149. #precache( "menu", "InitialBlack" );
  150.  
  151. #precache( "eventstring", "force_scoreboard" );
  152. #precache( "eventstring", "game_timer_reset" );
  153. #precache( "eventstring", "open_ingame_menu" );
  154. #precache( "eventstring", "play_promo_anim" );
  155.  
  156. #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_0" );
  157. #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_1" );
  158. #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_2" );
  159. #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_3" );
  160.  
  161. #namespace zm;
  162.  
  163. function autoexec ignore_systems()
  164. {
  165. //shutdown unwanted systems - doing it in an autoexec is the only clean way to do it
  166. system::ignore("gadget_clone");
  167. system::ignore("gadget_armor");
  168. system::ignore("gadget_heat_wave");
  169. system::ignore("gadget_resurrect");
  170. system::ignore("gadget_shock_field");
  171. system::ignore("gadget_active_camo");
  172. system::ignore("gadget_mrpukey");
  173. system::ignore("gadget_misdirection");
  174. system::ignore("gadget_smokescreen");
  175. system::ignore("gadget_firefly_swarm");
  176. system::ignore("gadget_immolation");
  177. system::ignore("gadget_forced_malfunction");
  178. system::ignore("gadget_sensory_overload");
  179. system::ignore("gadget_rapid_strike");
  180. system::ignore("gadget_unstoppable_force");
  181. system::ignore("gadget_overdrive");
  182. system::ignore("gadget_concussive_wave");
  183. system::ignore("gadget_ravage_core");
  184. system::ignore("gadget_es_strike");
  185. system::ignore("gadget_cacophany");
  186. system::ignore("gadget_iff_override");
  187. system::ignore("gadget_security_breach");
  188. system::ignore("gadget_surge");
  189. system::ignore("gadget_exo_breakdown");
  190. system::ignore("gadget_servo_shortout");
  191. system::ignore("gadget_system_overload");
  192. system::ignore("gadget_cleanse");
  193. system::ignore("gadget_flashback");
  194. system::ignore("gadget_combat_efficiency");
  195. system::ignore("gadget_other");
  196. system::ignore("gadget_camo");
  197. system::ignore("gadget_vision_pulse");
  198. system::ignore("gadget_speed_burst");
  199. system::ignore("gadget_thief");
  200. system::ignore("replay_gun");
  201. system::ignore("spike_charge_siegebot");
  202. system::ignore("siegebot");
  203. system::ignore("amws");
  204.  
  205. }
  206.  
  207.  
  208.  
  209. REGISTER_SYSTEM( "zm", &__init__, undefined )
  210.  
  211. function __init__()
  212. {
  213. DEFAULT(level.zombie_vars,[]);
  214. }
  215.  
  216. function init()
  217. {
  218. //New movement disabled for Zombies
  219. SetDvar( "doublejump_enabled", 0 );
  220. SetDvar( "juke_enabled", 0 );
  221. SetDvar( "playerEnergy_enabled", 0 );
  222. SetDvar( "wallrun_enabled", 0 );
  223. SetDvar( "sprintLeap_enabled", 0 );
  224. SetDvar( "traverse_mode", 2 );
  225. SetDvar( "weaponrest_enabled", 0 );
  226.  
  227. //we dont care about CP movie skipping logic in ZM
  228. SetDvar( "ui_allowDisplayContinue", true );
  229.  
  230. if ( !IsDefined( level.killstreakWeapons ) )
  231. {
  232. level.killstreakWeapons = [];
  233. }
  234.  
  235. level.weaponNone = GetWeapon( "none" );
  236. level.weaponNull = GetWeapon( "weapon_null" );
  237. level.weaponBaseMelee = GetWeapon( "knife" );
  238. level.weaponBaseMeleeHeld = GetWeapon( "knife_held" );
  239. level.weaponBallisticKnife = GetWeapon( "knife_ballistic" );
  240. DEFAULT(level.weaponRiotshield,GetWeapon( "riotshield" ));
  241. level.weaponReviveTool = GetWeapon( "syrette" );
  242. level.weaponZMDeathThroe = GetWeapon( "death_throe" );
  243. level.weaponZMFists = GetWeapon( "zombie_fists" );
  244.  
  245. DEFAULT( level.giveCustomLoadout, &zm_weapons::give_start_weapons );
  246.  
  247. level.projectiles_should_ignore_world_pause = true;
  248.  
  249. level.player_out_of_playable_area_monitor = true;
  250. level.player_too_many_weapons_monitor = true;
  251. level.player_too_many_weapons_monitor_func = &player_too_many_weapons_monitor;
  252.  
  253. level.player_too_many_players_check = true;
  254. level.player_too_many_players_check_func = &player_too_many_players_check;
  255.  
  256. level._use_choke_weapon_hints = 1;
  257. level._use_choke_blockers = 1;
  258.  
  259. level.speed_change_round = 15;
  260.  
  261. level.passed_introscreen = false;
  262.  
  263. if(!isdefined(level.custom_ai_type))
  264. {
  265. level.custom_ai_type = [];
  266. }
  267.  
  268. level.custom_ai_spawn_check_funcs = [];
  269.  
  270. // put things you'd like to be able to turn off in here above this line
  271. level thread zm_ffotd::main_start();
  272.  
  273. level.zombiemode = true;
  274. level.reviveFeature = false;
  275. level.swimmingFeature = false;
  276. level.calc_closest_player_using_paths = false;
  277. level.zombie_melee_in_water = true;
  278. level.put_timed_out_zombies_back_in_queue = true;
  279. level.use_alternate_poi_positioning = true;
  280. level.zmb_laugh_alias = "zmb_laugh_child";
  281. level.sndAnnouncerIsRich = true;
  282.  
  283. level.scr_zm_ui_gametype = GetDvarString( "ui_gametype" );
  284. level.scr_zm_ui_gametype_group = "";//GetDvarString( "ui_zm_gamemodegroup" );
  285. level.scr_zm_map_start_location = "";//GetDvarString( "ui_zm_mapstartlocation" );
  286.  
  287. level.curr_gametype_affects_rank = false;
  288. gametype = toLower( GetDvarString( "g_gametype" ) );
  289. if ( "zclassic" == gametype || "zstandard" == gametype )
  290. {
  291. level.curr_gametype_affects_rank = true;
  292. }
  293.  
  294. level.grenade_multiattack_bookmark_count = 1;
  295. demo::initActorBookmarkParams( 3, 6000, 6000 );
  296.  
  297. // set up any gameplay modes
  298. /* level.GAME_MODULE_CLASSIC_INDEX = 0;
  299. zm_game_module::register_game_module(level.GAME_MODULE_CLASSIC_INDEX,"classic",undefined,undefined);
  300. zm_game_module::set_current_game_module(level.scr_zm_game_module); */
  301.  
  302. // Allowing custom round_spawn_failsafe function to be set here.
  303. if( !isdefined( level._zombies_round_spawn_failsafe ) )
  304. {
  305. level._zombies_round_spawn_failsafe = &zombie_utility::round_spawn_failsafe;
  306. }
  307.  
  308. level.func_get_zombie_spawn_delay = &get_zombie_spawn_delay;
  309. level.func_get_delay_between_rounds = &get_delay_between_rounds;
  310.  
  311. level.zombie_visionset = "zombie_neutral";
  312.  
  313. level.wait_and_revive = false;
  314.  
  315. if(GetDvarString("anim_intro") == "1")
  316. {
  317. level.zombie_anim_intro = 1;
  318. }
  319. else
  320. {
  321. level.zombie_anim_intro = 0;
  322. }
  323.  
  324. precache_models();
  325.  
  326. precache_zombie_leaderboards();
  327.  
  328. level._ZOMBIE_GIB_PIECE_INDEX_ALL = 0;
  329. level._ZOMBIE_GIB_PIECE_INDEX_RIGHT_ARM = 1;
  330. level._ZOMBIE_GIB_PIECE_INDEX_LEFT_ARM = 2;
  331. level._ZOMBIE_GIB_PIECE_INDEX_RIGHT_LEG = 3;
  332. level._ZOMBIE_GIB_PIECE_INDEX_LEFT_LEG = 4;
  333. level._ZOMBIE_GIB_PIECE_INDEX_HEAD = 5;
  334. level._ZOMBIE_GIB_PIECE_INDEX_GUTS = 6;
  335. level._ZOMBIE_GIB_PIECE_INDEX_HAT = 7;
  336.  
  337. //Limit zombie to 24 max, must have for network purposes
  338. if ( !isdefined( level.zombie_ai_limit ) )
  339. {
  340. level.zombie_ai_limit = 24;
  341. }
  342. if ( !isdefined( level.zombie_actor_limit ) )
  343. {
  344. level.zombie_actor_limit = 31;
  345. }
  346.  
  347. init_flags();
  348. init_dvars();
  349. init_strings();
  350. init_levelvars();
  351. init_sounds();
  352. init_shellshocks();
  353. init_client_field_callback_funcs();
  354.  
  355. zm_utility::register_offhand_weapons_for_level_defaults();
  356.  
  357. level thread drive_client_connected_notifies();
  358.  
  359. // load map defaults
  360.  
  361. //Systems
  362. zm_craftables::init();
  363. zm_perks::init();
  364. zm_powerups::init();
  365. zm_spawner::init();
  366. zm_weapons::init();
  367.  
  368. //Grab all static poi in the map
  369. level.zombie_poi_array = getEntArray( "zombie_poi", "script_noteworthy" );
  370.  
  371.  
  372. init_function_overrides();
  373.  
  374. // ww: init the pistols in the game so last stand has the importance order
  375. level thread last_stand_pistol_rank_init();
  376.  
  377. level thread post_all_players_connected();
  378.  
  379. zm_utility::init_utility();
  380.  
  381. util::registerClientSys( "lsm" );
  382.  
  383. // STATS_TODO: will check if the following is needed later
  384. initializeStatTracking();
  385.  
  386. if ( GetPlayers().size <= 1 )
  387. {
  388. incrementCounter( "global_solo_games", 1 );
  389. }
  390. else if( IS_TRUE(level.systemLink) )
  391. {
  392. incrementCounter( "global_systemlink_games", 1 );
  393. }
  394. else if ( GetDvarInt( "splitscreen_playerCount" ) == GetPlayers().size )
  395. {
  396. incrementCounter( "global_splitscreen_games", 1 );
  397. }
  398. else // coop game
  399. {
  400. incrementCounter( "global_coop_games", 1 );
  401. }
  402.  
  403. callback::on_connect( &zm_on_player_connect);
  404.  
  405. //self LUINotifyEvent( &"score_event", 3, label, score, rampageBonus );
  406.  
  407. // Initialize persistent upgrades
  408. //zm_pers_upgrades::pers_upgrade_init();
  409.  
  410. zm_utility::set_demo_intermission_point();
  411.  
  412. level thread zm_ffotd::main_end();
  413. level thread zm_utility::track_players_intersection_tracker();
  414. level thread onAllPlayersReady();
  415. level thread startUnitriggers();
  416.  
  417. callback::on_spawned( &zm_on_player_spawned );
  418. printHashIDs();
  419. }
  420.  
  421. function post_main()
  422. {
  423. level thread init_custom_ai_type();
  424. }
  425.  
  426. function cheat_enabled( val )
  427. {
  428. return false;
  429. }
  430.  
  431. function startUnitriggers()
  432. {
  433. level flag::wait_till_any( array( "start_zombie_round_logic", "start_encounters_match_logic" ) );
  434. level thread zm_unitrigger::main();
  435. }
  436.  
  437. function drive_client_connected_notifies()
  438. {
  439. while(1)
  440. {
  441. level waittill("connected", player);
  442. player demo::reset_actor_bookmark_kill_times();
  443. player callback::callback( #"on_player_connect" );
  444. }
  445. }
  446.  
  447. function fade_out_intro_screen_zm( hold_black_time, fade_out_time, destroyed_afterwards )
  448. {
  449. lui::screen_fade_out( 0, undefined );
  450.  
  451. if( IsDefined( hold_black_time ) )
  452. {
  453. wait hold_black_time;
  454. }
  455. else
  456. {
  457. wait 0.2;
  458. }
  459.  
  460. if( !IsDefined( fade_out_time ) )
  461. {
  462. fade_out_time = 1.5;
  463. }
  464.  
  465. array::thread_all(GetPlayers(), &initialBlackEnd);
  466. lui::screen_fade_in( fade_out_time, undefined );
  467.  
  468. level clientfield::set( "sndZMBFadeIn", 1 );
  469.  
  470. //level notify("fade_introblack");
  471.  
  472. wait 1.6;
  473.  
  474. level.passed_introscreen = true;
  475.  
  476. players = GetPlayers();
  477. for(i = 0; i < players.size; i++)
  478. {
  479. players[i] setClientUIVisibilityFlag( "hud_visible", 1 );
  480. players[i] setClientUIVisibilityFlag( "weapon_hud_visible", 1 );
  481.  
  482. if( !IS_TRUE( players[i].seen_promo_anim ) && SessionModeIsOnlineGame() )
  483. {
  484. players[i] LUINotifyEvent( &"play_promo_anim", 0 );
  485. players[i].seen_promo_anim = true;
  486. }
  487.  
  488. if(!IS_TRUE(level.host_ended_game))
  489. {
  490. if (isdefined(level.player_movement_suppressed))
  491. {
  492. players[i] FreezeControls(level.player_movement_suppressed);
  493. }
  494. else
  495. {
  496. if(!IS_TRUE(players[i].hostMigrationControlsFrozen))
  497. {
  498. players[i] FreezeControls(false);
  499. }
  500. }
  501. }
  502. }
  503. // level notify("fade_in_complete");
  504.  
  505. level flag::set("initial_blackscreen_passed");
  506. level clientfield::set("gameplay_started", 1);
  507. }
  508.  
  509. function onAllPlayersReady()
  510. {
  511.  
  512. timeOut = GetTime() + 5000; // 5 second time out.
  513.  
  514. while(IsLoadingCinematicPlaying() || (GetNumExpectedPlayers() == 0 && (GetTime() < timeOut)))
  515. {
  516. wait(0.1);
  517. }
  518.  
  519. player_count_actual = 0;
  520. while( (GetNumConnectedPlayers() < GetNumExpectedPlayers()) || (player_count_actual != GetNumExpectedPlayers()) )
  521. {
  522. players = GetPlayers();
  523. player_count_actual = 0;
  524. for( i = 0; i < players.size; i++ )
  525. {
  526. players[i] FreezeControls( true );
  527. if( players[i].sessionstate == "playing" )
  528. {
  529. player_count_actual++;
  530. }
  531. }
  532.  
  533. wait( 0.1 );
  534. }
  535.  
  536. SetInitialPlayersConnected();
  537.  
  538. level flag::set( "all_players_connected" );
  539. SetDvar( "all_players_are_connected", "1" );
  540.  
  541. //Check to see if we should spawn some bots to help
  542. if ( (1 == GetNumConnectedPlayers()) && (GetDvarInt( "scr_zm_enable_bots" )==1) )
  543. {
  544. level thread add_bots();
  545. level flag::set("initial_players_connected");
  546. }
  547. else
  548. {
  549. players = GetPlayers();
  550. if ( players.size == 1 )
  551. {
  552. level flag::set( "solo_game" );
  553. level.solo_lives_given = 0;
  554. foreach ( player in players )
  555. {
  556. player.lives = 0;
  557. }
  558. level zm::set_default_laststand_pistol( true );
  559. }
  560.  
  561. level flag::set("initial_players_connected");
  562.  
  563. array::thread_all(GetPlayers(), &initialBlack);
  564.  
  565. while ( !AreTexturesLoaded() )
  566. {
  567. WAIT_SERVER_FRAME;
  568. }
  569.  
  570. //level flag::set( "start_zombie_round_logic" );
  571. thread start_zombie_logic_in_x_sec( 3.0 );
  572. }
  573.  
  574. set_intermission_point();
  575.  
  576. n_black_screen = 5.0;
  577. level thread fade_out_intro_screen_zm( n_black_screen, 1.5, true );
  578. wait n_black_screen;
  579.  
  580. // Reset the start time
  581. level.n_gameplay_start_time = GetTime();
  582. foreach( player in level.players )
  583. {
  584. player LUINotifyEvent( &"game_timer_reset", 0 );
  585. }
  586. }
  587.  
  588. function initialBlack()
  589. {
  590. self CloseMenu( "InitialBlack" );
  591. self OpenMenu( "InitialBlack" );
  592. }
  593.  
  594. function initialBlackEnd()
  595. {
  596. self CloseMenu( "InitialBlack" );
  597. // self clientfield::set_to_player( "sndLevelStartSnapOff", 1 );
  598. }
  599.  
  600.  
  601.  
  602. function start_zombie_logic_in_x_sec( time_to_wait )
  603. {
  604. wait( time_to_wait );
  605. level flag::set( "start_zombie_round_logic" );
  606. }
  607.  
  608.  
  609. function getAllOtherPlayers()
  610. {
  611. aliveplayers = [];
  612.  
  613. // Make a list of fully connected, non-spectating, alive players
  614. for(i = 0; i < level.players.size; i++)
  615. {
  616. if ( !isdefined( level.players[i] ) )
  617. continue;
  618. player = level.players[i];
  619.  
  620. if ( player.sessionstate != "playing" || player == self )
  621. continue;
  622.  
  623. aliveplayers[aliveplayers.size] = player;
  624. }
  625. return aliveplayers;
  626. }
  627.  
  628. function getFreeSpawnpoint(spawnpoints, player)
  629. {
  630. // There are no valid spawnpoints in the map
  631. if(!isdefined(spawnpoints))
  632. {
  633. return undefined;
  634. }
  635.  
  636. // only should happen on initial spawn.
  637.  
  638. if(!isdefined(game["spawns_randomized"]))
  639. {
  640. game["spawns_randomized"] = true;
  641.  
  642. spawnpoints = array::randomize(spawnpoints);
  643.  
  644. random_chance = randomint(100);
  645. if(random_chance > 50)
  646. {
  647. zm_utility::set_game_var("side_selection", 1);
  648. }
  649. else
  650. {
  651. zm_utility::set_game_var("side_selection", 2);
  652. }
  653. }
  654.  
  655. side_selection = zm_utility::get_game_var("side_selection");
  656.  
  657. // used in vs. games where you switch sides on next round.
  658. if( zm_utility::get_game_var("switchedsides"))
  659. {
  660. if(side_selection == 2)
  661. {
  662. side_selection = 1;
  663. }
  664. else if(side_selection == 1)
  665. {
  666. side_selection = 2;
  667. }
  668. }
  669.  
  670. if(IsDefined(player) && IsDefined(player.team))
  671. {
  672. i = 0;
  673. while(IsDefined(spawnpoints) && i < spawnpoints.size)
  674. {
  675. If(side_selection == 1)
  676. {
  677. if(player.team != "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 1))
  678. {
  679. ArrayRemoveValue(spawnpoints, spawnpoints[i]);
  680. i=0;
  681. }
  682. else if(player.team == "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 2))
  683. {
  684. ArrayRemoveValue(spawnpoints, spawnpoints[i]);
  685. i=0;
  686. }
  687. else
  688. {
  689. i++;
  690. }
  691. }
  692. else
  693. {
  694. if(player.team == "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 1))
  695. {
  696. ArrayRemoveValue(spawnpoints, spawnpoints[i]);
  697. i=0;
  698. }
  699. else if(player.team != "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 2))
  700. {
  701. ArrayRemoveValue(spawnpoints, spawnpoints[i]);
  702. i=0;
  703. }
  704. else
  705. {
  706. i++;
  707. }
  708. }
  709. }
  710. }
  711.  
  712. if(!Isdefined(player.playernum))
  713. {
  714. if(player.team == "allies")
  715. {
  716. player.playernum = zm_utility::get_game_var("_team1_num");
  717. zm_utility::set_game_var("_team1_num", player.playernum + 1);
  718. }
  719. else
  720. {
  721. player.playernum = zm_utility::get_game_var("_team2_num");
  722. zm_utility::set_game_var("_team2_num", player.playernum + 1);
  723. }
  724. }
  725.  
  726. for( j = 0; j < spawnpoints.size; j++ )
  727. {
  728. if(!IsDefined(spawnpoints[j].en_num))
  729. {
  730. for( m = 0; m < spawnpoints.size; m++ )
  731. {
  732. spawnpoints[m].en_num = m;
  733. }
  734. }
  735.  
  736. if( spawnpoints[j].en_num == player.playernum)
  737. {
  738. return spawnpoints[j];
  739. }
  740. }
  741.  
  742. return spawnpoints[0];
  743. }
  744.  
  745.  
  746. function delete_in_createfx()
  747. {
  748. exterior_goals =struct::get_array( "exterior_goal", "targetname" );
  749. for( i = 0; i < exterior_goals.size; i++ )
  750. {
  751. if( !IsDefined( exterior_goals[i].target ) ) // If the exterior_goal entity has no targets defined then return
  752. {
  753. continue;
  754. }
  755. targets = GetEntArray( exterior_goals[i].target, "targetname" ); // Grab all the pieces that are targeted by the exterior_goal
  756.  
  757. for( j = 0; j < targets.size; j++ ) // count total targets of exterior_goal
  758. {
  759. targets[j] zm_utility::self_delete();
  760. }
  761. }
  762.  
  763. if(isdefined(level.level_createfx_callback_thread))
  764. {
  765. level thread [[level.level_createfx_callback_thread]]();
  766. }
  767. }
  768.  
  769.  
  770.  
  771. function add_bots()
  772. {
  773. //Wait for the host!
  774. host = util::GetHostPlayer();
  775. while ( !IsDefined( host ) )
  776. {
  777. WAIT_SERVER_FRAME;
  778. host = util::GetHostPlayer();
  779. }
  780.  
  781. wait( 4.0 );
  782.  
  783. //Then spawn bots
  784. zbot_spawn();
  785. SetDvar("bot_AllowMovement", "1");
  786. SetDvar("bot_PressAttackBtn", "1");
  787. SetDvar("bot_PressMeleeBtn", "1");
  788.  
  789. //Wait until bots are spawned
  790. while( GetPlayers().size<2 )
  791. {
  792. WAIT_SERVER_FRAME;
  793. }
  794.  
  795. //Unfreeze all players
  796. players = GetPlayers();
  797. for( i = 0; i < players.size; i++ )
  798. {
  799. players[i] FreezeControls( false );
  800. }
  801.  
  802. level.numberBotsAdded = 1;
  803. level flag::set( "start_zombie_round_logic" );
  804. }
  805.  
  806. function zbot_spawn()
  807. {
  808. player = util::GetHostPlayer();
  809.  
  810. //spawnPoints =struct::get_array( "initial_spawn_points", "targetname" );
  811. //spawnPoint = getFreeSpawnpoint( spawnPoints, player );
  812.  
  813. bot = AddTestClient();
  814. if ( !IsDefined( bot ) )
  815. {
  816. return;
  817. }
  818.  
  819.  
  820. spawnPoint = bot zm_gametype::onFindValidSpawnPoint();
  821.  
  822. bot.pers["isBot"] = true;
  823. bot.equipment_enabled = false;
  824. yaw = spawnPoint.angles[1];
  825.  
  826. return bot;
  827. }
  828.  
  829. function post_all_players_connected()
  830. {
  831. level thread end_game();
  832.  
  833. level flag::wait_till( "start_zombie_round_logic" );
  834. // Start the Zombie MODE!
  835. level thread round_end_monitor();
  836.  
  837. if(!level.zombie_anim_intro)
  838. {
  839. if(isDefined(level._round_start_func))
  840. {
  841. level thread [[level._round_start_func]]();
  842. }
  843. }
  844.  
  845. level thread players_playing();
  846.  
  847. DisableGrenadeSuicide();
  848. level.startInvulnerableTime = GetDvarInt( "player_deathInvulnerableTime" );
  849. }
  850.  
  851. function init_custom_ai_type()
  852. {
  853. //wait( 0.1 );
  854. // waittillframeend;
  855.  
  856. if( isDefined( level.custom_ai_type ) )
  857. {
  858. for( i = 0; i < level.custom_ai_type.size; i++ )
  859. {
  860. [[ level.custom_ai_type[i] ]]();
  861. }
  862. }
  863. }
  864.  
  865. function zombiemode_melee_miss()
  866. {
  867. if( isDefined( self.enemy.curr_pay_turret ) )
  868. {
  869. self.enemy doDamage( GetDvarInt( "ai_meleeDamage" ), self.origin, self, self, "none", "melee" );
  870. }
  871. }
  872.  
  873. /*------------------------------------
  874. function chrisp - adding vo to track players ammo
  875. ------------------------------------*/
  876. function player_track_ammo_count()
  877. {
  878. self notify( "stop_ammo_tracking" );
  879. self endon( "disconnect" );
  880. self endon( "stop_ammo_tracking" );
  881.  
  882. ammoLowCount = 0;
  883. ammoOutCount = 0;
  884.  
  885. while ( 1 )
  886. {
  887. wait( .5 );
  888. weapon = self getcurrentweapon();
  889.  
  890. if ( weapon == level.weaponNone || weapon.skiplowammovox )
  891. {
  892. continue;
  893. }
  894.  
  895. if( weapon.type == "grenade" )
  896. {
  897. continue;
  898. }
  899.  
  900. if ( self GetAmmoCount( weapon ) > 5 || self laststand::player_is_in_laststand() )
  901. {
  902. ammoOutCount = 0;
  903. ammoLowCount = 0;
  904. continue;
  905. }
  906.  
  907. if ( self GetAmmoCount( weapon ) > 0 )
  908. {
  909. if ( ammoLowCount < 1 )
  910. {
  911. self zm_audio::create_and_play_dialog( "general", "ammo_low" );
  912. ammoLowCount++;
  913. }
  914. }
  915. else
  916. {
  917. if ( ammoOutCount < 1 )
  918. {
  919. WAIT_SERVER_FRAME;
  920.  
  921. if( !self zm_equipment::has_player_equipment ( weapon ) )
  922. {
  923. continue;
  924. }
  925.  
  926. self zm_audio::create_and_play_dialog( "general", "ammo_out" );
  927. ammoOutCount++;
  928. }
  929. }
  930. wait( 20 );
  931. }
  932. }
  933.  
  934. /*------------------------------------
  935. function audio plays when more than 1 player connects
  936. ------------------------------------*/
  937. function spawn_vo()
  938. {
  939. //not sure if we need this
  940. wait(1);
  941.  
  942. players = GetPlayers();
  943.  
  944. //just pick a random player for now and play some vo
  945. if(players.size > 1)
  946. {
  947. player = array::random(players);
  948. index = zm_utility::get_player_index(player);
  949. player thread spawn_vo_player(index,players.size);
  950. }
  951.  
  952. }
  953.  
  954. function spawn_vo_player(index,num)
  955. {
  956. sound = "plr_" + index + "_vox_" + num +"play";
  957. self PlaySoundWithNotify(sound, "sound_done");
  958. self waittill("sound_done");
  959. }
  960.  
  961. function precache_models()
  962. {
  963. if ( isDefined( level.precacheCustomCharacters ) )
  964. {
  965. self [[ level.precacheCustomCharacters ]]();
  966. }
  967. }
  968.  
  969. function init_shellshocks()
  970. {
  971. level.player_killed_shellshock = "zombie_death";
  972. }
  973.  
  974. function init_strings()
  975. {
  976. zm_utility::add_zombie_hint( "undefined", &"ZOMBIE_UNDEFINED" );
  977.  
  978. // Random Treasure Chest
  979. zm_utility::add_zombie_hint( "default_treasure_chest", &"ZOMBIE_RANDOM_WEAPON_COST" );
  980.  
  981. // Barrier Pieces
  982. zm_utility::add_zombie_hint( "default_buy_barrier_piece_10", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_10" );
  983. zm_utility::add_zombie_hint( "default_buy_barrier_piece_20", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_20" );
  984. zm_utility::add_zombie_hint( "default_buy_barrier_piece_50", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_50" );
  985. zm_utility::add_zombie_hint( "default_buy_barrier_piece_100", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_100" );
  986.  
  987. // REWARD Barrier Pieces
  988. zm_utility::add_zombie_hint( "default_reward_barrier_piece", &"ZOMBIE_BUTTON_REWARD_BARRIER" );
  989.  
  990. // Areas
  991. zm_utility::add_zombie_hint( "default_buy_area", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_COST" );
  992. }
  993.  
  994. function init_sounds()
  995. {
  996. zm_utility::add_sound( "end_of_round", "mus_zmb_round_over" );
  997. zm_utility::add_sound( "end_of_game", "mus_zmb_game_over" ); //Had to remove this and add a music state switch so that we can add other musical elements.
  998. zm_utility::add_sound( "chalk_one_up", "mus_zmb_chalk" );
  999. zm_utility::add_sound( "purchase", "zmb_cha_ching" );
  1000. zm_utility::add_sound( "no_purchase", "zmb_no_cha_ching" );
  1001.  
  1002. // Zombification
  1003. // TODO need to vary these up
  1004. zm_utility::add_sound( "playerzombie_usebutton_sound", "zmb_zombie_vocals_attack" );
  1005. zm_utility::add_sound( "playerzombie_attackbutton_sound", "zmb_zombie_vocals_attack" );
  1006. zm_utility::add_sound( "playerzombie_adsbutton_sound", "zmb_zombie_vocals_attack" );
  1007.  
  1008. // Head gib
  1009. zm_utility::add_sound( "zombie_head_gib", "zmb_zombie_head_gib" );
  1010.  
  1011. // Blockers
  1012. zm_utility::add_sound( "rebuild_barrier_piece", "zmb_repair_boards" );
  1013. zm_utility::add_sound( "rebuild_barrier_metal_piece", "zmb_metal_repair" );
  1014. zm_utility::add_sound( "rebuild_barrier_hover", "zmb_boards_float" );
  1015. zm_utility::add_sound( "debris_hover_loop", "zmb_couch_loop" );
  1016. zm_utility::add_sound( "break_barrier_piece", "zmb_break_boards" );
  1017. zm_utility::add_sound( "grab_metal_bar", "zmb_bar_pull" );
  1018. zm_utility::add_sound( "break_metal_bar", "zmb_bar_break" );
  1019. zm_utility::add_sound( "drop_metal_bar", "zmb_bar_drop" );
  1020. zm_utility::add_sound("blocker_end_move", "zmb_board_slam");
  1021. zm_utility::add_sound( "barrier_rebuild_slam", "zmb_board_slam" );
  1022. zm_utility::add_sound( "bar_rebuild_slam", "zmb_bar_repair" );
  1023. zm_utility::add_sound( "zmb_rock_fix", "zmb_break_rock_barrier_fix" );
  1024. zm_utility::add_sound( "zmb_vent_fix", "evt_vent_slat_repair" );
  1025.  
  1026. // Doors
  1027. zm_utility::add_sound( "door_slide_open", "zmb_door_slide_open" );
  1028. zm_utility::add_sound( "door_rotate_open", "zmb_door_slide_open" );
  1029.  
  1030. // Debris
  1031. zm_utility::add_sound( "debris_move", "zmb_weap_wall" );
  1032.  
  1033. // Random Weapon Chest
  1034. zm_utility::add_sound( "open_chest", "zmb_lid_open" );
  1035. zm_utility::add_sound( "music_chest", "zmb_music_box" );
  1036. zm_utility::add_sound( "close_chest", "zmb_lid_close" );
  1037.  
  1038. // Weapons on walls
  1039. zm_utility::add_sound( "weapon_show", "zmb_weap_wall" );
  1040.  
  1041. zm_utility::add_sound( "break_stone", "evt_break_stone" );
  1042. }
  1043.  
  1044. function init_levelvars()
  1045. {
  1046. // Variables
  1047. // used to a check in last stand for players to become zombies
  1048. level.is_zombie_level = true;
  1049. level.default_laststandpistol = GetWeapon( "pistol_standard" );
  1050. level.default_solo_laststandpistol = GetWeapon( "pistol_standard_upgraded" );
  1051. level.laststandpistol = level.default_laststandpistol; // so we dont get the uber colt when we're knocked out
  1052. level.start_weapon = level.default_laststandpistol;
  1053. level.first_round = true;
  1054. level.start_round = GetGametypeSetting( "startRound" );
  1055. level.round_number = level.start_round;
  1056. level.enable_magic = GetGametypeSetting( "magic" );
  1057. level.headshots_only = GetGametypeSetting( "headshotsonly" );
  1058. level.player_starting_points = level.round_number * 500;
  1059. level.round_start_time = 0;
  1060. level.pro_tips_start_time = 0;
  1061. level.intermission = false;
  1062. level.dog_intermission = false;
  1063. level.zombie_total = 0; // Total number of zombies left to spawn
  1064. level.zombie_respawns = 0; // Total number of zombies that need to be respawned due to cleanup
  1065. level.total_zombies_killed = 0;
  1066. level.hudelem_count = 0;
  1067. level.zm_loc_types = [];
  1068. level.zm_loc_types[ "zombie_location" ] = []; // List of normal zombie spawners (other types will be added in the zone manager)
  1069.  
  1070. level.zm_variant_type_max = [];
  1071. level.zm_variant_type_max[ "walk" ] = [];
  1072. level.zm_variant_type_max[ "run" ] = [];
  1073. level.zm_variant_type_max[ "sprint" ] = [];
  1074. level.zm_variant_type_max[ "super_sprint" ] = [];
  1075. level.zm_variant_type_max[ "walk" ][ "down" ] = 14;
  1076. level.zm_variant_type_max[ "walk" ][ "up" ] = 16;
  1077. level.zm_variant_type_max[ "run" ][ "down" ] = 13;
  1078. level.zm_variant_type_max[ "run" ][ "up" ] = 12;
  1079. level.zm_variant_type_max[ "sprint" ][ "down" ] = 9;
  1080. level.zm_variant_type_max[ "sprint" ][ "up" ] = 8;
  1081. level.zm_variant_type_max[ "super_sprint" ][ "down" ] = 1;
  1082. level.zm_variant_type_max[ "super_sprint" ][ "up" ] = 1;
  1083.  
  1084. level.current_zombie_array = [];
  1085. level.current_zombie_count = 0;
  1086. level.zombie_total_subtract = 0;
  1087. level.destructible_callbacks = [];
  1088.  
  1089. foreach( team in level.teams )
  1090. {
  1091. DEFAULT( level.zombie_vars[ team ], [] );
  1092. }
  1093.  
  1094. difficulty = 1;
  1095. column = int(difficulty) + 1;
  1096.  
  1097. //#######################################################################
  1098. // zombie_utility::set_zombie_var( identifier, value, float, column );
  1099.  
  1100. // AI
  1101. zombie_utility::set_zombie_var( "zombie_health_increase", 100, false, column ); // cumulatively add this to the zombies' starting health each round (up to round 10)
  1102. zombie_utility::set_zombie_var( "zombie_health_increase_multiplier",0.1, true, column ); // after round 10 multiply the zombies' starting health by this amount
  1103. zombie_utility::set_zombie_var( "zombie_health_start", 150, false, column ); // starting health of a zombie at round 1
  1104. zombie_utility::set_zombie_var( "zombie_spawn_delay", 2.0, true, column ); // Time to wait between spawning zombies. This is modified based on the round number.
  1105. zombie_utility::set_zombie_var( "zombie_new_runner_interval", 10, false, column ); // Interval between changing walkers who are too far away into runners
  1106. zombie_utility::set_zombie_var( "zombie_move_speed_multiplier", 4, false, column ); // Multiply by the round number to give the base speed value. 0-40 = walk, 41-70 = run, 71+ = sprint
  1107. zombie_utility::set_zombie_var( "zombie_move_speed_multiplier_easy", 2, false, column ); // Multiply by the round number to give the base speed value. 0-40 = walk, 41-70 = run, 71+ = sprint
  1108.  
  1109. zombie_utility::set_zombie_var( "zombie_max_ai", 24, false, column ); // Base number of zombies per player (modified by round #)
  1110. zombie_utility::set_zombie_var( "zombie_ai_per_player", 6, false, column ); // additional zombie modifier for each player in the game
  1111. zombie_utility::set_zombie_var( "below_world_check", -1000 ); // Check height to see if a zombie has fallen through the world.
  1112.  
  1113. // Round
  1114. zombie_utility::set_zombie_var( "spectators_respawn", true ); // Respawn in the spectators in between rounds
  1115. zombie_utility::set_zombie_var( "zombie_use_failsafe", true ); // Will slowly kill zombies who are stuck
  1116. zombie_utility::set_zombie_var( "zombie_between_round_time", 10 ); // How long to pause after the round ends
  1117. zombie_utility::set_zombie_var( "zombie_intermission_time", 15 ); // Length of time to show the end of game stats
  1118. zombie_utility::set_zombie_var( "game_start_delay", 0, false, column ); // How much time to give people a break before starting spawning
  1119.  
  1120. // Life and death
  1121. zombie_utility::set_zombie_var( "player_base_health", 100 ); // Base health of a player
  1122.  
  1123. zombie_utility::set_zombie_var( "penalty_no_revive", 0.10, true, column ); // Percentage of money you lose if you let a teammate die
  1124. zombie_utility::set_zombie_var( "penalty_died", 0.0, true, column ); // Percentage of money lost if you die
  1125. zombie_utility::set_zombie_var( "penalty_downed", 0.05, true, column ); // Percentage of money lost if you go down // ww: told to remove downed point loss
  1126.  
  1127. zombie_utility::set_zombie_var( "zombie_score_kill_4player", 50 ); // Individual Points for a zombie kill in a 4 player game
  1128. zombie_utility::set_zombie_var( "zombie_score_kill_3player", 50 ); // Individual Points for a zombie kill in a 3 player game
  1129. zombie_utility::set_zombie_var( "zombie_score_kill_2player", 50 ); // Individual Points for a zombie kill in a 2 player game
  1130. zombie_utility::set_zombie_var( "zombie_score_kill_1player", 50 ); // Individual Points for a zombie kill in a 1 player game
  1131.  
  1132. zombie_utility::set_zombie_var( "zombie_score_damage_normal", 10 ); // points gained for a hit with a non-automatic weapon
  1133. zombie_utility::set_zombie_var( "zombie_score_damage_light", 10 ); // points gained for a hit with an automatic weapon
  1134.  
  1135. zombie_utility::set_zombie_var( "zombie_score_bonus_melee", 80 ); // Bonus points for a melee kill
  1136. zombie_utility::set_zombie_var( "zombie_score_bonus_head", 50 ); // Bonus points for a head shot kill
  1137. zombie_utility::set_zombie_var( "zombie_score_bonus_neck", 20 ); // Bonus points for a neck shot kill
  1138. zombie_utility::set_zombie_var( "zombie_score_bonus_torso", 10 ); // Bonus points for a torso shot kill
  1139. zombie_utility::set_zombie_var( "zombie_score_bonus_burn", 10 ); // Bonus points for a burn kill
  1140.  
  1141. zombie_utility::set_zombie_var( "zombie_flame_dmg_point_delay", 500 );
  1142.  
  1143. zombie_utility::set_zombie_var( "zombify_player", false ); // Default to not zombify the player till further support
  1144.  
  1145. if ( IsSplitScreen() )
  1146. {
  1147. zombie_utility::set_zombie_var( "zombie_timer_offset", 280 ); // hud offsets
  1148. }
  1149.  
  1150. level thread init_player_levelvars();
  1151.  
  1152. level.gamedifficulty = GetGametypeSetting( "zmDifficulty" );
  1153.  
  1154. if( level.gamedifficulty == 0 ) //easy
  1155. {
  1156. level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier_easy"];
  1157. }
  1158. else //normal
  1159. {
  1160. level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier"];
  1161. }
  1162.  
  1163. //Make sure we only have walker zombies in round 1
  1164. if ( level.round_number == 1 )
  1165. {
  1166. level.zombie_move_speed = 1;
  1167. }
  1168.  
  1169. level.speed_change_max = 0;
  1170. level.speed_change_num = 0;
  1171. }
  1172.  
  1173. function init_player_levelvars()
  1174. {
  1175. level flag::wait_till( "start_zombie_round_logic" );
  1176.  
  1177. difficulty = 1;
  1178. column = int(difficulty) + 1;
  1179.  
  1180. for(i = 0; i < 8; i ++)
  1181. {
  1182. points = 500;
  1183.  
  1184. if(i > 3)
  1185. {
  1186. points = 3000; // Dont change the behavior of grief.
  1187. }
  1188.  
  1189. points = zombie_utility::set_zombie_var( ("zombie_score_start_"+ (i+1) +"p"), points, false, column );
  1190. }
  1191. }
  1192.  
  1193. function init_dvars()
  1194. {
  1195. //t6.5todo: move these dvars out of script, dangerous to leave them here like this
  1196.  
  1197. if( GetDvarString( "zombie_debug" ) == "" )
  1198. {
  1199. SetDvar( "zombie_debug", "0" );
  1200. }
  1201.  
  1202. if( GetDvarString( "scr_zm_enable_bots" ) == "" )
  1203. {
  1204. SetDvar( "scr_zm_enable_bots", "0" );
  1205. }
  1206.  
  1207. if( GetDvarString( "zombie_cheat" ) == "" )
  1208. {
  1209. SetDvar( "zombie_cheat", "0" );
  1210. }
  1211.  
  1212. if ( GetDvarString("zombiemode_debug_zombie_count") == "" )
  1213. {
  1214. SetDvar("zombiemode_debug_zombie_count", "0");
  1215. }
  1216.  
  1217. SetDvar( "revive_trigger_radius", "75" );
  1218.  
  1219. SetDvar( "scr_deleteexplosivesonspawn", "0" );
  1220. }
  1221.  
  1222.  
  1223. function init_function_overrides()
  1224. {
  1225. level.callbackPlayerDamage = &Callback_PlayerDamage;
  1226. level.overridePlayerDamage = &player_damage_override; //_cheat;
  1227. level.callbackPlayerKilled = &player_killed_override;
  1228.  
  1229. level.playerlaststand_func = &player_laststand;
  1230. level.callbackPlayerLastStand = &Callback_PlayerLastStand;
  1231.  
  1232. level.prevent_player_damage = &player_prevent_damage;
  1233.  
  1234. level.callbackActorKilled = &actor_killed_override;
  1235. level.callbackActorDamage = &actor_damage_override_wrapper;
  1236.  
  1237. level.callbackVehicleDamage = &vehicle_damage_override;
  1238. level.callbackVehicleKilled = &globallogic_vehicle::Callback_VehicleKilled;
  1239. level.callbackVehicleRadiusDamage = &globallogic_vehicle::Callback_VehicleRadiusDamage;
  1240.  
  1241. level.custom_introscreen = &zombie_intro_screen;
  1242. level.custom_intermission = &player_intermission;
  1243.  
  1244. level.global_damage_func = &zm_spawner::zombie_damage;
  1245. level.global_damage_func_ads = &zm_spawner::zombie_damage_ads;
  1246.  
  1247. level.reset_clientdvars = &onPlayerConnect_clientDvars;
  1248.  
  1249. level.zombie_last_stand = &last_stand_pistol_swap;
  1250. level.zombie_last_stand_pistol_memory = &last_stand_save_pistol_ammo;
  1251. level.zombie_last_stand_ammo_return = &last_stand_restore_pistol_ammo;
  1252.  
  1253. level.player_becomes_zombie = &zombify_player;
  1254.  
  1255. level.validate_enemy_path_length = &zm_utility::default_validate_enemy_path_length;
  1256. }
  1257.  
  1258. function Callback_PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
  1259. {
  1260. self endon( "disconnect" );
  1261. //self Callback("on_player_last_stand");
  1262. zm_laststand::PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
  1263. }
  1264.  
  1265. function CodeCallback_DestructibleEvent( event, param1, param2, param3 )
  1266. {
  1267. if( event == "broken" )
  1268. {
  1269. notify_type = param1;
  1270. attacker = param2;
  1271. weapon = param3;
  1272.  
  1273. if ( IsDefined( level.destructible_callbacks[ notify_type ] ) )
  1274. {
  1275. self thread [[level.destructible_callbacks[ notify_type ]]]( notify_type, attacker );
  1276. }
  1277.  
  1278. self notify( event, notify_type, attacker );
  1279. }
  1280. else if( event == "breakafter" )
  1281. {
  1282. piece = param1;
  1283. time = param2;
  1284. damage = param3;
  1285. self thread breakAfter( time, damage, piece );
  1286. }
  1287. }
  1288.  
  1289. function breakAfter( time, damage, piece )
  1290. {
  1291. self notify( "breakafter" );
  1292. self endon( "breakafter" );
  1293.  
  1294. wait time;
  1295.  
  1296. // this does not work in mp. DoDamage does not take a piece for mp.
  1297. self dodamage( damage, self.origin, undefined, /*piece*/undefined );
  1298. }
  1299.  
  1300. function Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
  1301. {
  1302. startedInLastStand = 0;
  1303. if ( isPlayer(self) )
  1304. {
  1305. startedInLastStand = self laststand::player_is_in_laststand();
  1306. }
  1307.  
  1308. if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && (eAttacker.sessionteam == self.sessionteam) && !eAttacker HasPerk( "specialty_playeriszombie" ) && !IS_TRUE( self.is_zombie ) )
  1309. {
  1310. self process_friendly_fire_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
  1311. if ( self != eAttacker )
  1312. {
  1313. //one player shouldn't damage another player, grenades, airstrikes called in by another player
  1314.  
  1315.  
  1316. return;
  1317. }
  1318. else if ( sMeansOfDeath != "MOD_GRENADE_SPLASH"
  1319. && sMeansOfDeath != "MOD_GRENADE"
  1320. && sMeansOfDeath != "MOD_EXPLOSIVE"
  1321. && sMeansOfDeath != "MOD_PROJECTILE"
  1322. && sMeansOfDeath != "MOD_PROJECTILE_SPLASH"
  1323. && sMeansOfDeath != "MOD_BURNED"
  1324. && sMeansOfDeath != "MOD_SUICIDE" )
  1325. {
  1326. //player should be able to damage they're selves with grenades and stuff
  1327. //otherwise don't damage the player, so like airstrikes won't kill the player
  1328. return;
  1329. }
  1330. }
  1331.  
  1332. if( IsDefined( self.overridePlayerDamage ) )
  1333. {
  1334. iDamage = self [[self.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  1335. }
  1336. else if( IsDefined( level.overridePlayerDamage ) )
  1337. {
  1338. iDamage = self [[level.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  1339. }
  1340.  
  1341. Assert(IsDefined(iDamage), "You must return a value from a damage override function.");
  1342.  
  1343. // self Callback("on_player_damage");
  1344.  
  1345. if (IS_TRUE(self.magic_bullet_shield))
  1346. {
  1347. // save out and restore the maxHealth, because setting health below modifies it
  1348. maxHealth = self.maxHealth;
  1349.  
  1350. // increase health by damage, because it will be subtracted back out below in finishActorDamage
  1351. self.health += iDamage;
  1352.  
  1353. // restore the maxHealth to what it was
  1354. self.maxHealth = maxHealth;
  1355. }
  1356.  
  1357. // DtP: When player is diving to prone away from the grenade, the damage is reduced
  1358.  
  1359. // player is diving
  1360. if( isdefined( self.divetoprone ) && self.divetoprone == 1 )
  1361. {
  1362. // grenade splash damage
  1363. if( sMeansOfDeath == "MOD_GRENADE_SPLASH" )
  1364. {
  1365. // if the player is at least 32 units away
  1366. dist = Distance2d(vPoint, self.origin);
  1367. if( dist > 32 )
  1368. {
  1369. // if player is diving away
  1370. dot_product = vectordot( AnglesToForward( self.angles ), vDir );
  1371. if( dot_product > 0 )
  1372. {
  1373. // grenade is behind player
  1374. iDamage = int( iDamage * 0.5 ); // halves damage
  1375. }
  1376. }
  1377. }
  1378. }
  1379.  
  1380. // players can only hurt themselves, zombie players can hurt any other player and be hurt by human players
  1381. /* if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && !eAttacker HasPerk( "specialty_playeriszombie" ) && !IS_TRUE( self.is_zombie ) )
  1382. {
  1383. if ( self != eAttacker )
  1384. {
  1385. //one player shouldn't damage another player, grenades, airstrikes called in by another player
  1386. println("Exiting - players can't hurt each other.");
  1387. return;
  1388. }
  1389. else if ( sMeansOfDeath != "MOD_GRENADE_SPLASH"
  1390. && sMeansOfDeath != "MOD_GRENADE"
  1391. && sMeansOfDeath != "MOD_EXPLOSIVE"
  1392. && sMeansOfDeath != "MOD_PROJECTILE"
  1393. && sMeansOfDeath != "MOD_PROJECTILE_SPLASH"
  1394. && sMeansOfDeath != "MOD_BURNED"
  1395. && sMeansOfDeath != "MOD_SUICIDE" )
  1396. {
  1397. println("Exiting - damage type verbotten.");
  1398. //player should be able to damage they're selves with grenades and stuff
  1399. //otherwise don't damage the player, so like airstrikes won't kill the player
  1400. return;
  1401. }
  1402. }*/
  1403.  
  1404. if ( isdefined( level.prevent_player_damage ) )
  1405. {
  1406. if ( self [[ level.prevent_player_damage ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ) )
  1407. {
  1408. return;
  1409. }
  1410. }
  1411.  
  1412.  
  1413. iDFlags = iDFlags | level.iDFLAGS_NO_KNOCKBACK;
  1414.  
  1415. //damage should have been reduced to 0 if it really was a riotshield hit
  1416. if( iDamage > 0 && sHitLoc == "riotshield" )
  1417. {
  1418. sHitLoc = "torso_upper";
  1419. }
  1420.  
  1421. wasDowned = 0;
  1422. if ( isPlayer(self))
  1423. {
  1424. wasDowned = !startedInLastStand && self laststand::player_is_in_laststand();
  1425. }
  1426.  
  1427. self finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
  1428. }
  1429.  
  1430. function finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
  1431. {
  1432. self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
  1433.  
  1434. // the MP version of finishPlayerDamage does not take 11 parameters
  1435. // the 11 parameter version in SP does not take these parameters (10 is modelIndex and 11 is pOffsetTime)
  1436. //surface = "flesh";
  1437. //self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, surface );
  1438.  
  1439. }
  1440.  
  1441. function register_player_friendly_fire_callback( callback )
  1442. {
  1443. if (!isdefined(level.player_friendly_fire_callbacks))
  1444. level.player_friendly_fire_callbacks = [];
  1445. level.player_friendly_fire_callbacks[level.player_friendly_fire_callbacks.size] = callback;
  1446. }
  1447.  
  1448. function process_friendly_fire_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
  1449. {
  1450. if (isdefined(level.player_friendly_fire_callbacks))
  1451. {
  1452. foreach( callback in level.player_friendly_fire_callbacks )
  1453. {
  1454. self [[callback]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
  1455. }
  1456. }
  1457. }
  1458.  
  1459. function init_flags()
  1460. {
  1461. level flag::init( "solo_game" );
  1462. level flag::init( "start_zombie_round_logic" );
  1463. level flag::init( "start_encounters_match_logic" );
  1464. level flag::init( "spawn_point_override" );
  1465. level flag::init( "crawler_round" );
  1466. level flag::init( "spawn_zombies", true );
  1467. level flag::init( "special_round" );
  1468. level flag::init( "dog_round" );
  1469. level flag::init( "raps_round" );
  1470. level flag::init( "begin_spawning" );
  1471. level flag::init( "end_round_wait" );
  1472. level flag::init( "wait_and_revive" );
  1473. level flag::init( "instant_revive" );
  1474. level flag::init( "initial_blackscreen_passed" );
  1475. level flag::init( "initial_players_connected" );
  1476.  
  1477. level flag::init( "power_on" );
  1478. //DCS: this will init all zone controlling power switch flags.
  1479. power_trigs = GetEntArray( "use_elec_switch", "targetname" );
  1480. foreach(trig in power_trigs)
  1481. {
  1482. if(IsDefined(trig.script_int))
  1483. {
  1484. level flag::init("power_on" + trig.script_int);
  1485. }
  1486. }
  1487. }
  1488.  
  1489. function init_client_field_callback_funcs()
  1490. {
  1491. // Client fields for actors
  1492.  
  1493. clientfield::register("actor", "zombie_riser_fx", VERSION_SHIP, 1, "int");
  1494.  
  1495. if ( IS_TRUE( level.use_water_risers ) )
  1496. {
  1497. clientfield::register("actor", "zombie_riser_fx_water", VERSION_SHIP, 1, "int");
  1498. }
  1499.  
  1500. if ( IS_TRUE( level.use_foliage_risers ) )
  1501. {
  1502. clientfield::register("actor", "zombie_riser_fx_foliage", VERSION_SHIP, 1, "int");
  1503. }
  1504.  
  1505. if ( IS_TRUE( level.use_low_gravity_risers ) )
  1506. {
  1507. clientfield::register("actor", "zombie_riser_fx_lowg", VERSION_SHIP, 1, "int");
  1508. }
  1509.  
  1510. clientfield::register("actor", "zombie_has_eyes", VERSION_SHIP, 1, "int");
  1511. clientfield::register("actor", "zombie_ragdoll_explode", VERSION_SHIP, 1, "int");
  1512. clientfield::register("actor", "zombie_gut_explosion", VERSION_SHIP, 1, "int");
  1513. clientfield::register("actor", "sndZombieContext", VERSION_SHIP_OBSOLETE, 1, "int");
  1514. clientfield::register("actor", "zombie_keyline_render", VERSION_SHIP, 1, "int");
  1515.  
  1516. bits = 4;
  1517. trigs = GetEntArray( "use_elec_switch", "targetname" );
  1518. if ( IsDefined( trigs ) )
  1519. {
  1520. bits = GetMinBitCountForNum( trigs.size + 1 );
  1521. }
  1522. clientfield::register("world", "zombie_power_on", VERSION_SHIP, bits, "int");
  1523. clientfield::register("world", "zombie_power_off", VERSION_SHIP, bits, "int");
  1524.  
  1525. clientfield::register("world", "round_complete_time", VERSION_SHIP, 20, "int");
  1526. clientfield::register("world", "round_complete_num", VERSION_SHIP, 8, "int");
  1527. clientfield::register("world", "game_end_time", VERSION_SHIP, 20, "int");
  1528. clientfield::register("world", "quest_complete_time", VERSION_SHIP, 20, "int");
  1529. }
  1530.  
  1531. function init_fx()
  1532. {
  1533. level.createfx_callback_thread = &delete_in_createfx;
  1534.  
  1535. // level._effect["wood_chunk_destory"] = "_t6/impacts/fx_large_woodhit" ;
  1536. level._effect["fx_zombie_bar_break"] = "_t6/maps/zombie/fx_zombie_bar_break";
  1537. level._effect["fx_zombie_bar_break_lite"] = "_t6/maps/zombie/fx_zombie_bar_break_lite";
  1538.  
  1539. if ( !IS_TRUE( level.FX_exclude_edge_fog ) )
  1540. {
  1541. level._effect["edge_fog"] = "_t6/maps/zombie/fx_fog_zombie_amb";
  1542. }
  1543.  
  1544. level._effect["chest_light"] = "zombie/fx_weapon_box_open_glow_zmb";
  1545. level._effect["chest_light_closed"] = "zombie/fx_weapon_box_closed_glow_zmb";
  1546.  
  1547. if ( !IS_TRUE( level.FX_exclude_default_eye_glow ) )
  1548. {
  1549. level._effect["eye_glow"] = "zombie/fx_glow_eye_orange";
  1550. }
  1551.  
  1552. level._effect["headshot"] = "zombie/fx_bul_flesh_head_fatal_zmb";
  1553. level._effect["headshot_nochunks"] = "zombie/fx_bul_flesh_head_nochunks_zmb";
  1554. level._effect["bloodspurt"] = "zombie/fx_bul_flesh_neck_spurt_zmb";
  1555.  
  1556. if ( !IS_TRUE( level.FX_exclude_tesla_head_light ) )
  1557. {
  1558. level._effect["tesla_head_light"] = "_t6/maps/zombie/fx_zombie_tesla_neck_spurt";
  1559. }
  1560. level._effect["zombie_guts_explosion"] = "zombie/fx_blood_torso_explo_lg_zmb";
  1561.  
  1562.  
  1563. level._effect["rise_burst_water"] = "zombie/fx_spawn_dirt_hand_burst_zmb";
  1564. level._effect["rise_billow_water"] = "zombie/fx_spawn_dirt_body_billowing_zmb";
  1565. level._effect["rise_dust_water"] = "zombie/fx_spawn_dirt_body_dustfalling_zmb";
  1566.  
  1567. level._effect["rise_burst"] = "zombie/fx_spawn_dirt_hand_burst_zmb";
  1568. level._effect["rise_billow"] = "zombie/fx_spawn_dirt_body_billowing_zmb";
  1569. level._effect["rise_dust"] = "zombie/fx_spawn_dirt_body_dustfalling_zmb";
  1570.  
  1571. level._effect["fall_burst"] = "zombie/fx_spawn_dirt_hand_burst_zmb";
  1572. level._effect["fall_billow"] = "zombie/fx_spawn_dirt_body_billowing_zmb";
  1573. level._effect["fall_dust"] = "zombie/fx_spawn_dirt_body_dustfalling_zmb";
  1574.  
  1575. // Flamethrower
  1576. level._effect["character_fire_death_sm"] = "zombie/fx_fire_torso_zmb";
  1577. level._effect["character_fire_death_torso"] = "zombie/fx_fire_torso_zmb";
  1578.  
  1579. if ( !IS_TRUE( level.fx_exclude_default_explosion ) )
  1580. {
  1581. level._effect["def_explosion"] = "_t6/explosions/fx_default_explosion";
  1582. }
  1583. // level._effect["betty_explode"] = "_t6/weapon/bouncing_betty/fx_explosion_betty_generic";
  1584.  
  1585. // level._effect["default_weapon_glow"] = "_t6/maps/zombie/fx_zmb_tranzit_weapon_glow";
  1586.  
  1587. if ( !IS_TRUE( level.disable_fx_upgrade_aquired ) )
  1588. {
  1589. level._effect["upgrade_aquired"] = "_t6/maps/zombie/fx_zmb_tanzit_upgrade";
  1590. }
  1591. }
  1592.  
  1593. // Handles the intro screen
  1594. function zombie_intro_screen( string1, string2, string3, string4, string5 )
  1595. {
  1596. level flag::wait_till( "start_zombie_round_logic" );
  1597. }
  1598.  
  1599. function players_playing()
  1600. {
  1601. // initialize level.players_playing
  1602. players = GetPlayers();
  1603. level.players_playing = players.size;
  1604.  
  1605. wait( 20 );
  1606.  
  1607. players = GetPlayers();
  1608. level.players_playing = players.size;
  1609. }
  1610.  
  1611.  
  1612. //
  1613. // NETWORK SECTION ====================================================================== //
  1614. //
  1615.  
  1616. function onPlayerConnect_clientDvars()
  1617. {
  1618. self SetClientCompass( 0 );
  1619. self SetClientThirdPerson( 0 );
  1620. self resetFov();
  1621. self SetClientThirdPersonAngle( 0 );
  1622. self SetClientUIVisibilityFlag( "weapon_hud_visible", 1 );
  1623. self SetClientMiniScoreboardHide( 1 );
  1624. self SetClientHUDHardcore( 0 );
  1625. self SetClientPlayerPushAmount( 1 );
  1626.  
  1627. self SetDepthOfField( 0, 0, 512, 4000, 4, 0 );
  1628.  
  1629. self zm_laststand::player_getup_setup();
  1630. }
  1631.  
  1632.  
  1633.  
  1634. function checkForAllDead(excluded_player)
  1635. {
  1636. players = GetPlayers();
  1637. count = 0;
  1638. for( i = 0; i < players.size; i++ )
  1639. {
  1640. if(isDefined(excluded_player) && excluded_player == players[i])
  1641. {
  1642. continue;
  1643. }
  1644. if( !(players[i] laststand::player_is_in_laststand()) && !(players[i].sessionstate == "spectator") )
  1645. {
  1646. count++;
  1647. }
  1648. }
  1649.  
  1650. if( count==0 && !IS_TRUE( level.no_end_game_check ) )
  1651. {
  1652. level notify( "end_game" );
  1653. }
  1654. }
  1655.  
  1656.  
  1657. //
  1658. // Runs when the player spawns into the map
  1659. // self is the player.surprise!
  1660. //
  1661. function onPlayerSpawned()
  1662. {
  1663. self endon( "disconnect" );
  1664. self notify("stop_onPlayerSpawned");
  1665. self endon("stop_onPlayerSpawned");
  1666.  
  1667. for( ;; )
  1668. {
  1669. self waittill( "spawned_player" );
  1670.  
  1671. if(!IS_TRUE(level.host_ended_game))
  1672. {
  1673. self freezecontrols( false );
  1674. }
  1675. self.hits = 0;
  1676.  
  1677. self zm_utility::init_player_offhand_weapons();
  1678.  
  1679. lethal_grenade = self zm_utility::get_player_lethal_grenade();
  1680. if( !self HasWeapon( lethal_grenade ) )
  1681. {
  1682. self GiveWeapon( lethal_grenade );
  1683. self SetWeaponAmmoClip( lethal_grenade, 0 );
  1684. }
  1685.  
  1686. self RecordPlayerReviveZombies( self );
  1687.  
  1688. self SetActionSlot( 3, "altMode" );
  1689. self PlayerKnockback( false );
  1690.  
  1691. self SetClientThirdPerson( 0 );
  1692. self resetFov();
  1693. self SetClientThirdPersonAngle( 0 );
  1694.  
  1695. self SetDepthOfField( 0, 0, 512, 4000, 4, 0 );
  1696.  
  1697. self cameraactivate(false);
  1698.  
  1699. self.num_perks = 0;
  1700. self.on_lander_last_stand = undefined;
  1701. self setblur(0, 0.1);
  1702. self.zmbDialogQueue = [];
  1703. self.zmbDialogActive = false;
  1704. self.zmbDialogGroups = [];
  1705. self.zmbDialogGroup = "";
  1706.  
  1707. if ( IS_TRUE( level.player_out_of_playable_area_monitor ) )
  1708. {
  1709. self thread player_out_of_playable_area_monitor();
  1710. }
  1711.  
  1712. if ( IS_TRUE( level.player_too_many_weapons_monitor ) )
  1713. {
  1714. self thread [[level.player_too_many_weapons_monitor_func]]();
  1715. }
  1716.  
  1717. if ( IS_TRUE( level.player_too_many_players_check ) )
  1718. {
  1719. level thread [[level.player_too_many_players_check_func]]();
  1720. }
  1721.  
  1722. self.disabled_perks = [];
  1723.  
  1724. if( isdefined( self.player_initialized ) )
  1725. {
  1726. if( self.player_initialized == false )
  1727. {
  1728. self.player_initialized = true;
  1729.  
  1730. //t6.5todo self freezecontrols( true ); // first spawn only, intro_black_screen will pull them out of it
  1731.  
  1732. self giveweapon( self zm_utility::get_player_lethal_grenade() );
  1733. self setweaponammoclip( self zm_utility::get_player_lethal_grenade(), 0);
  1734. self SetClientUIVisibilityFlag( "weapon_hud_visible", 1 );
  1735. self SetClientMiniScoreboardHide( 0 );
  1736. // ww: set the is_drinking variable
  1737. self.is_drinking = 0;
  1738.  
  1739. self thread player_zombie_breadcrumb();
  1740.  
  1741. self thread player_monitor_travel_dist();
  1742. self thread player_monitor_time_played();
  1743.  
  1744. if(isDefined(level.custom_player_track_ammo_count))
  1745. {
  1746. self thread [[level.custom_player_track_ammo_count]]();
  1747. }
  1748. else
  1749. {
  1750. self thread player_track_ammo_count();
  1751. }
  1752.  
  1753. self thread zm_utility::shock_onpain();
  1754.  
  1755. self thread player_grenade_watcher();
  1756. self laststand::revive_hud_create();
  1757.  
  1758. if(isDefined(level.zm_gamemodule_spawn_func))
  1759. {
  1760. self thread [[level.zm_gamemodule_spawn_func]]();
  1761. }
  1762.  
  1763. self thread player_spawn_protection();
  1764. if(!isDefined(self.lives))
  1765. {
  1766. self.lives = 0;
  1767. }
  1768. }
  1769. }
  1770. }
  1771. }
  1772.  
  1773. function player_spawn_protection()
  1774. {
  1775. self endon("disconnect");
  1776. self zm_utility::increment_ignoreme();
  1777. x = 0;
  1778. while( x < 60 )
  1779. {
  1780. x++;
  1781. wait(.05);
  1782. }
  1783. self zm_utility::decrement_ignoreme();
  1784. }
  1785.  
  1786. function spawn_life_brush( origin, radius, height )
  1787. {
  1788. life_brush = spawn( "trigger_radius", origin, 0, radius, height );
  1789. life_brush.script_noteworthy = "life_brush";
  1790.  
  1791. return life_brush;
  1792. }
  1793.  
  1794.  
  1795. function in_life_brush()
  1796. {
  1797. life_brushes = getentarray( "life_brush", "script_noteworthy" );
  1798.  
  1799. if ( !IsDefined( life_brushes ) )
  1800. {
  1801. return false;
  1802. }
  1803.  
  1804. for ( i = 0; i < life_brushes.size; i++ )
  1805. {
  1806.  
  1807. if ( self IsTouching( life_brushes[i] ) )
  1808. {
  1809. return true;
  1810. }
  1811. }
  1812.  
  1813. return false;
  1814. }
  1815.  
  1816.  
  1817. function spawn_kill_brush( origin, radius, height )
  1818. {
  1819. kill_brush = spawn( "trigger_radius", origin, 0, radius, height );
  1820. kill_brush.script_noteworthy = "kill_brush";
  1821.  
  1822. return kill_brush;
  1823. }
  1824.  
  1825.  
  1826. function in_kill_brush()
  1827. {
  1828. kill_brushes = getentarray( "kill_brush", "script_noteworthy" );
  1829.  
  1830. self.kill_brush = undefined;
  1831.  
  1832. if ( !IsDefined( kill_brushes ) )
  1833. {
  1834. return false;
  1835. }
  1836.  
  1837. for ( i = 0; i < kill_brushes.size; i++ )
  1838. {
  1839.  
  1840. if ( self IsTouching( kill_brushes[i] ) )
  1841. {
  1842. self.kill_brush = kill_brushes[i];
  1843. return true;
  1844. }
  1845. }
  1846.  
  1847. return false;
  1848. }
  1849.  
  1850.  
  1851. function in_enabled_playable_area()
  1852. {
  1853. zm_zonemgr::wait_zone_flags_updating();
  1854.  
  1855. playable_area = getentarray( "player_volume", "script_noteworthy" );
  1856.  
  1857. if( !IsDefined( playable_area ) )
  1858. {
  1859. return false;
  1860. }
  1861.  
  1862. for ( i = 0; i < playable_area.size; i++ )
  1863. {
  1864. if ( zm_zonemgr::zone_is_enabled( playable_area[i].targetname ) && self IsTouching( playable_area[i] ) )
  1865. {
  1866. return true;
  1867. }
  1868. }
  1869.  
  1870. return false;
  1871. }
  1872.  
  1873.  
  1874. function get_player_out_of_playable_area_monitor_wait_time()
  1875. {
  1876. return 3;
  1877. }
  1878.  
  1879.  
  1880. function player_out_of_playable_area_monitor()
  1881. {
  1882. self notify( "stop_player_out_of_playable_area_monitor" );
  1883. self endon( "stop_player_out_of_playable_area_monitor" );
  1884. self endon( "disconnect" );
  1885. level endon( "end_game" );
  1886.  
  1887. while(!isDefined(self.characterindex))
  1888. {
  1889. wait(.05);
  1890. }
  1891. // load balancing
  1892. wait( (0.15 * self.characterindex) );
  1893.  
  1894. while ( true )
  1895. {
  1896. // skip over players in spectate, otherwise Sam keeps laughing every 3 seconds since their corpse is still invisibly in a kill area
  1897. if ( self.sessionstate == "spectator" )
  1898. {
  1899. wait( get_player_out_of_playable_area_monitor_wait_time() );
  1900. continue;
  1901. }
  1902.  
  1903. if(IS_TRUE(level.hostmigration_occured))
  1904. {
  1905. wait( get_player_out_of_playable_area_monitor_wait_time() );
  1906. continue;
  1907. }
  1908.  
  1909. if ( !self in_life_brush() && (self in_kill_brush() || !self in_enabled_playable_area() || ( isdefined(level.player_out_of_playable_area_override) && IS_TRUE( self [[level.player_out_of_playable_area_override]]() ) ) ) )
  1910. {
  1911. if ( !isdefined( level.player_out_of_playable_area_monitor_callback ) || self [[level.player_out_of_playable_area_monitor_callback]]() )
  1912. {
  1913. //track the cheaters
  1914. self zm_stats::increment_map_cheat_stat( "cheat_out_of_playable" );
  1915. self zm_stats::increment_client_stat( "cheat_out_of_playable",false );
  1916. self zm_stats::increment_client_stat( "cheat_total",false );
  1917.  
  1918. self playlocalsound( level.zmb_laugh_alias );
  1919.  
  1920. wait( 0.5 );
  1921.  
  1922. if ( GetPlayers().size == 1 && level flag::get( "solo_game" ) && IS_TRUE( self.waiting_to_revive ) )
  1923. {
  1924. level notify( "end_game" );
  1925. }
  1926. else
  1927. {
  1928. self DisableInvulnerability();
  1929. self.lives = 0;
  1930. self dodamage( self.health + 1000, self.origin );
  1931. self.bleedout_time = 0;
  1932. }
  1933. }
  1934. }
  1935.  
  1936. wait( get_player_out_of_playable_area_monitor_wait_time() );
  1937. }
  1938. }
  1939.  
  1940.  
  1941. function get_player_too_many_weapons_monitor_wait_time()
  1942. {
  1943. return 3;
  1944. }
  1945.  
  1946.  
  1947. function player_too_many_weapons_monitor_takeaway_simultaneous( primary_weapons_to_take )
  1948. {
  1949. self endon( "player_too_many_weapons_monitor_takeaway_sequence_done" );
  1950.  
  1951. self util::waittill_any( "player_downed", "replace_weapon_powerup" );
  1952.  
  1953. for ( i = 0; i < primary_weapons_to_take.size; i++ )
  1954. {
  1955. self TakeWeapon( primary_weapons_to_take[i] );
  1956. }
  1957.  
  1958. self zm_score::player_reduce_points( "take_all" );
  1959. self zm_utility::give_start_weapon( false );
  1960. if ( !self laststand::player_is_in_laststand() )
  1961. {
  1962. self zm_utility::decrement_is_drinking();
  1963. }
  1964. else if ( level flag::get( "solo_game" ) )
  1965. {
  1966. self.score_lost_when_downed = 0;
  1967. }
  1968.  
  1969. self notify( "player_too_many_weapons_monitor_takeaway_sequence_done" );
  1970. }
  1971.  
  1972.  
  1973. function player_too_many_weapons_monitor_takeaway_sequence( primary_weapons_to_take )
  1974. {
  1975. self thread player_too_many_weapons_monitor_takeaway_simultaneous( primary_weapons_to_take );
  1976.  
  1977. self endon( "player_downed" );
  1978. self endon( "replace_weapon_powerup" );
  1979.  
  1980. self zm_utility::increment_is_drinking();
  1981. score_decrement = zm_utility::round_up_to_ten( int( self.score / (primary_weapons_to_take.size + 1) ) );
  1982.  
  1983. for ( i = 0; i < primary_weapons_to_take.size; i++ )
  1984. {
  1985. self playlocalsound( level.zmb_laugh_alias );
  1986. self SwitchToWeapon( primary_weapons_to_take[i] );
  1987. self zm_score::player_reduce_points( "take_specified", score_decrement );
  1988. wait( 3 );
  1989.  
  1990. self TakeWeapon( primary_weapons_to_take[i] );
  1991. }
  1992.  
  1993. self playlocalsound( level.zmb_laugh_alias );
  1994. self zm_score::player_reduce_points( "take_all" );
  1995. wait( 1 );
  1996. self zm_utility::give_start_weapon( true );
  1997. self zm_utility::decrement_is_drinking();
  1998.  
  1999. self notify( "player_too_many_weapons_monitor_takeaway_sequence_done" );
  2000. }
  2001.  
  2002. function player_too_many_weapons_monitor()
  2003. {
  2004. self notify( "stop_player_too_many_weapons_monitor" );
  2005. self endon( "stop_player_too_many_weapons_monitor" );
  2006. self endon( "disconnect" );
  2007. level endon( "end_game" );
  2008.  
  2009. // load balancing
  2010. scalar = self.characterindex;
  2011.  
  2012. if ( !isdefined( scalar ) )
  2013. {
  2014. scalar = self GetEntityNumber();
  2015. }
  2016.  
  2017. wait( (0.15 * scalar) );
  2018.  
  2019. while ( true )
  2020. {
  2021. if ( self zm_utility::has_powerup_weapon() || self laststand::player_is_in_laststand() || self.sessionstate == "spectator" )
  2022. {
  2023. wait( get_player_too_many_weapons_monitor_wait_time() );
  2024. continue;
  2025. }
  2026.  
  2027. weapon_limit = zm_utility::get_player_weapon_limit( self );
  2028.  
  2029. primaryWeapons = self GetWeaponsListPrimaries();
  2030.  
  2031. if ( primaryWeapons.size > weapon_limit )
  2032. {
  2033. self zm_weapons::take_fallback_weapon();
  2034. primaryWeapons = self GetWeaponsListPrimaries();
  2035. }
  2036.  
  2037. primary_weapons_to_take = [];
  2038. for ( i = 0; i < primaryWeapons.size; i++ )
  2039. {
  2040. if ( zm_weapons::is_weapon_included( primaryWeapons[i] ) || zm_weapons::is_weapon_upgraded( primaryWeapons[i] ) )
  2041. {
  2042. primary_weapons_to_take[primary_weapons_to_take.size] = primaryWeapons[i];
  2043. }
  2044. }
  2045.  
  2046. if ( primary_weapons_to_take.size > weapon_limit )
  2047. {
  2048. if ( !isdefined( level.player_too_many_weapons_monitor_callback ) || self [[level.player_too_many_weapons_monitor_callback]]( primary_weapons_to_take ) )
  2049. {
  2050. //track the cheaters
  2051. self zm_stats::increment_map_cheat_stat( "cheat_too_many_weapons" );
  2052. self zm_stats::increment_client_stat( "cheat_too_many_weapons",false );
  2053. self zm_stats::increment_client_stat( "cheat_total",false );
  2054.  
  2055.  
  2056. self thread player_too_many_weapons_monitor_takeaway_sequence( primary_weapons_to_take );
  2057. self waittill( "player_too_many_weapons_monitor_takeaway_sequence_done" );
  2058. }
  2059. }
  2060.  
  2061. wait( get_player_too_many_weapons_monitor_wait_time() );
  2062. }
  2063. }
  2064.  
  2065.  
  2066. function player_monitor_travel_dist()
  2067. {
  2068. self endon("disconnect");
  2069. self notify("stop_player_monitor_travel_dist");
  2070. self endon("stop_player_monitor_travel_dist");
  2071.  
  2072. prevpos = self.origin;
  2073. while(1)
  2074. {
  2075. wait .1;
  2076.  
  2077. self.pers["distance_traveled"] += distance( self.origin, prevpos ) ;
  2078. prevpos = self.origin;
  2079. }
  2080. }
  2081.  
  2082. function player_monitor_time_played()
  2083. {
  2084. self endon( "disconnect" );
  2085. self notify("stop_player_monitor_time_played");
  2086. self endon("stop_player_monitor_time_played");
  2087.  
  2088. level flag::wait_till( "start_zombie_round_logic" );
  2089.  
  2090. for ( ;; )
  2091. {
  2092. wait ( 1.0 );
  2093. zm_stats::increment_client_stat( "time_played_total" );
  2094. }
  2095. }
  2096.  
  2097. function player_grenade_multiattack_bookmark_watcher( grenade )
  2098. {
  2099. self endon( "disconnect" );
  2100.  
  2101. waittillframeend;
  2102.  
  2103. if ( !IsDefined( grenade ) )
  2104. {
  2105. return;
  2106. }
  2107.  
  2108. inflictorEntNum = grenade getEntityNumber();
  2109. inflictorEntType = grenade getEntityType();
  2110. inflictorBirthTime = 0;
  2111. if ( isDefined( grenade.birthTime ) )
  2112. inflictorBirthTime = grenade.birthTime;
  2113.  
  2114. ret_val = grenade util::waittill_any_timeout( 15, "explode" );
  2115.  
  2116. if ( !IsDefined( self ) || (IsDefined( ret_val ) && "timeout" == ret_val) )
  2117. {
  2118. return;
  2119. }
  2120.  
  2121. self.grenade_multiattack_count = 0;
  2122. self.grenade_multiattack_ent = undefined;
  2123. self.grenade_multikill_count = 0; // Black Ops 3 - TU1 Fix; track multikill count in addition to multiattack, for the Five-for-One Challenge
  2124.  
  2125. waittillframeend;
  2126.  
  2127. if ( !IsDefined( self ) )
  2128. {
  2129. return;
  2130. }
  2131.  
  2132. count = level.grenade_multiattack_bookmark_count;
  2133. if ( IS_TRUE( grenade.grenade_multiattack_bookmark_count ) )
  2134. {
  2135. count = grenade.grenade_multiattack_bookmark_count;
  2136. }
  2137.  
  2138. bookmark_string = "zm_player_grenade_multiattack";
  2139. if ( IS_TRUE( grenade.use_grenade_special_long_bookmark ) )
  2140. {
  2141. bookmark_string = "zm_player_grenade_special_long";
  2142. }
  2143. else if ( IS_TRUE( grenade.use_grenade_special_bookmark ) )
  2144. {
  2145. bookmark_string = "zm_player_grenade_special";
  2146. }
  2147.  
  2148. if ( count <= self.grenade_multiattack_count && IsDefined( self.grenade_multiattack_ent ) )
  2149. {
  2150. addDemoBookmark( bookmark_string, gettime(), self GetEntityNumber(), 255, 0, inflictorEntNum, inflictorEntType, inflictorBirthTime, false, self.grenade_multiattack_ent GetEntityNumber() );
  2151. }
  2152.  
  2153. if ( 5 <= self.grenade_multikill_count ) // Black Ops 3 - TU1 Fix; track multikill count in addition to multiattack, for the Five-for-One Challenge
  2154. {
  2155. self zm_stats::increment_challenge_stat( "ZOMBIE_HUNTER_EXPLOSION_MULTIKILL" );
  2156. }
  2157.  
  2158. self.grenade_multiattack_count = 0;
  2159. self.grenade_multikill_count = 0; // Black Ops 3 - TU1 Fix; track multikill count in addition to multiattack, for the Five-for-One Challenge
  2160. }
  2161.  
  2162.  
  2163. function player_grenade_watcher()
  2164. {
  2165. self endon( "disconnect" );
  2166.  
  2167. self notify("stop_player_grenade_watcher");
  2168. self endon("stop_player_grenade_watcher");
  2169.  
  2170. self.grenade_multiattack_count = 0;
  2171. self.grenade_multikill_count = 0; //this was added to "player_grenade_multiattack_bookmark_watcher" for TU1, but not added here, which was causing a SRE.
  2172.  
  2173. while ( 1 )
  2174. {
  2175. self waittill( "grenade_fire", grenade, weapon );
  2176.  
  2177. if( isdefined( grenade ) && isalive( grenade ) )
  2178. {
  2179. grenade.team = self.team;
  2180. }
  2181.  
  2182. self thread player_grenade_multiattack_bookmark_watcher( grenade );
  2183.  
  2184. if ( isdefined( level.grenade_watcher ) )
  2185. {
  2186. self [[ level.grenade_watcher ]]( grenade, weapon );
  2187. }
  2188. }
  2189. }
  2190.  
  2191. function player_prevent_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime )
  2192. {
  2193. if( !isdefined( eInflictor ) || !isdefined( eAttacker ) )
  2194. {
  2195. return false;
  2196. }
  2197.  
  2198. if ( eInflictor == self || eAttacker == self )
  2199. {
  2200. return false;
  2201. }
  2202.  
  2203. if ( isdefined( eInflictor ) && isdefined( eInflictor.team ) )
  2204. {
  2205. if (!IS_TRUE(eInflictor.damage_own_team))
  2206. if ( eInflictor.team == self.team )
  2207. {
  2208. return true;
  2209. }
  2210. }
  2211.  
  2212. return false;
  2213. }
  2214.  
  2215. //
  2216. // Keep track of players going down and getting revived
  2217. function player_revive_monitor()
  2218. {
  2219. self endon( "disconnect" );
  2220. self notify("stop_player_revive_monitor");
  2221. self endon("stop_player_revive_monitor");
  2222.  
  2223. while (1)
  2224. {
  2225. self waittill( "player_revived", reviver );
  2226.  
  2227. self playsoundtoplayer( "zmb_character_revived", self );
  2228.  
  2229. if(IS_TRUE(level.isresetting_grief))
  2230. {
  2231. continue;
  2232. }
  2233.  
  2234. //self laststand_giveback_player_perks();
  2235.  
  2236. if ( IsDefined(reviver) )
  2237. {
  2238. if( reviver != self )
  2239. {
  2240. if( math::cointoss() )
  2241. self zm_audio::create_and_play_dialog( "general", "revive_up" );
  2242. else
  2243. reviver zm_audio::create_and_play_dialog( "general", "revive_support" );
  2244. }
  2245. else
  2246. {
  2247. self zm_audio::create_and_play_dialog( "general", "revive_up" );
  2248. }
  2249.  
  2250. //reviver maps\_zombiemode_rank::giveRankXp( "revive" );
  2251. //maps\_zombiemode_challenges::doMissionCallback( "zm_revive", reviver );
  2252.  
  2253. // Check to see how much money you lost from being down.
  2254. points = self.score_lost_when_downed;
  2255.  
  2256. reviver zm_score::player_add_points( "reviver", points );
  2257. self.score_lost_when_downed = 0;
  2258.  
  2259. if ( IsPlayer( reviver ) && reviver != self )
  2260. {
  2261. reviver zm_stats::increment_challenge_stat( "SURVIVALIST_REVIVE" );
  2262. }
  2263. }
  2264. }
  2265. }
  2266.  
  2267.  
  2268. // self = a player
  2269. // If the player has just 1 perk, they wil always get it back
  2270. // If the player has more than 1 perk, they will lose a single perk
  2271. function laststand_giveback_player_perks()
  2272. {
  2273. if ( IsDefined( self.laststand_perks ) )
  2274. {
  2275. // Calculate a lost perk index
  2276. lost_perk_index = int( -1 );
  2277. if( self.laststand_perks.size > 1 )
  2278. {
  2279. lost_perk_index = RandomInt( self.laststand_perks.size-1 );
  2280. }
  2281.  
  2282. // Give the player back their perks
  2283. for ( i=0; i<self.laststand_perks.size; i++ )
  2284. {
  2285. if ( self HasPerk( self.laststand_perks[i] ) )
  2286. {
  2287. continue;
  2288. }
  2289. if( i == lost_perk_index )
  2290. {
  2291. continue;
  2292. }
  2293.  
  2294. zm_perks::give_perk( self.laststand_perks[i] );
  2295. }
  2296. }
  2297. }
  2298.  
  2299. function remote_revive_watch()
  2300. {
  2301. self endon( "death" );
  2302. self endon( "player_revived" );
  2303.  
  2304. keep_checking = true;
  2305. while( keep_checking )
  2306. {
  2307. self waittill( "remote_revive", reviver );
  2308.  
  2309. //Check the remote reviver is on the same team
  2310. if( reviver.team == self.team )
  2311. keep_checking = false;
  2312. }
  2313.  
  2314. self zm_laststand::remote_revive( reviver );
  2315. }
  2316.  
  2317. function player_laststand( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
  2318. {
  2319. b_alt_visionset = false;
  2320.  
  2321. self AllowJump(false);
  2322.  
  2323. currWeapon = self GetCurrentWeapon();
  2324.  
  2325. self AddWeaponStat( currWeapon, "deathsDuringUse", 1 );
  2326.  
  2327. players = GetPlayers();
  2328. if ( players.size == 1 && level flag::get( "solo_game" ) )
  2329. {
  2330. if ( self.lives > 0 && self HasPerk(PERK_QUICK_REVIVE) )
  2331. {
  2332. self thread wait_and_revive();
  2333. }
  2334. }
  2335.  
  2336. self zm_utility::clear_is_drinking();
  2337.  
  2338. self thread remote_revive_watch();
  2339.  
  2340. self zm_score::player_downed_penalty();
  2341.  
  2342. // Turns out we need to do this after all, but we don't want to change _laststand.gsc postship, so I'm doing it here manually instead
  2343. self DisableOffhandWeapons();
  2344.  
  2345. self thread last_stand_grenade_save_and_return();
  2346.  
  2347. if( sMeansOfDeath != "MOD_SUICIDE" && sMeansOfDeath != "MOD_FALLING" )
  2348. {
  2349. if( !IS_TRUE(self.intermission) )
  2350. self zm_audio::create_and_play_dialog( "general", "revive_down" );
  2351. else
  2352. {
  2353. if(isDefined(level.custom_player_death_vo_func) && !self [[level.custom_player_death_vo_func]]() )
  2354. {
  2355. self zm_audio::create_and_play_dialog( "general", "exert_death" );
  2356. }
  2357. }
  2358. }
  2359.  
  2360. if( IsDefined( level._zombie_minigun_powerup_last_stand_func ) )
  2361. {
  2362. self thread [[level._zombie_minigun_powerup_last_stand_func]]();
  2363. }
  2364.  
  2365. if( IsDefined( level._zombie_tesla_powerup_last_stand_func ) )
  2366. {
  2367. self thread [[level._zombie_tesla_powerup_last_stand_func]]();
  2368. }
  2369.  
  2370. if ( self HasPerk( PERK_ELECTRIC_CHERRY ) )
  2371. {
  2372. b_alt_visionset = true;
  2373.  
  2374. if ( IsDefined( level.custom_laststand_func ) )
  2375. {
  2376. self thread [[ level.custom_laststand_func ]]();
  2377. }
  2378. }
  2379.  
  2380. if( IsDefined( self.intermission ) && self.intermission )
  2381. {
  2382. //maps\_zombiemode_challenges::doMissionCallback( "playerDied", self );
  2383.  
  2384. wait(.5);
  2385. self stopsounds();
  2386.  
  2387. level waittill( "forever" );
  2388. }
  2389.  
  2390. if ( !( b_alt_visionset ) )
  2391. {
  2392. visionset_mgr::activate( "visionset", ZM_LASTSTAND_VISIONSET, self, 1 );
  2393. }
  2394. }
  2395.  
  2396.  
  2397. function failsafe_revive_give_back_weapons(excluded_player)
  2398. {
  2399. for ( i = 0; i < 10; i++ )
  2400. {
  2401. WAIT_SERVER_FRAME;
  2402.  
  2403. players = GetPlayers();
  2404. foreach(player in players )
  2405. {
  2406. if (player == excluded_player|| !isdefined( player.reviveProgressBar ) || player zm_laststand::is_reviving_any() )
  2407. {
  2408. continue;
  2409. }
  2410.  
  2411. // he's not reviving anyone but he still has revive stuff up, clean it all up
  2412. // pass in "none" since we have no idea what the weapon they should be showing is
  2413. player zm_laststand::revive_give_back_weapons( level.weaponNone );
  2414.  
  2415. if ( isdefined( player.reviveProgressBar ) )
  2416. {
  2417. player.reviveProgressBar hud::destroyElem();
  2418. }
  2419.  
  2420. if ( isdefined( player.reviveTextHud ) )
  2421. {
  2422. player.reviveTextHud destroy();
  2423. }
  2424. }
  2425. }
  2426. }
  2427.  
  2428. function set_intermission_point()
  2429. {
  2430. points =struct::get_array( "intermission", "targetname" );
  2431.  
  2432. if( points.size < 1 )
  2433. {
  2434. return;
  2435. }
  2436. points = array::randomize( points );
  2437.  
  2438. point = points[0];
  2439.  
  2440. SetDemoIntermissionPoint( point.origin, point.angles );
  2441. }
  2442.  
  2443.  
  2444. function spawnSpectator()
  2445. {
  2446. self endon( "disconnect" );
  2447. self endon( "spawned_spectator" );
  2448. self notify( "spawned" );
  2449. self notify( "end_respawn" );
  2450.  
  2451. if( level.intermission )
  2452. {
  2453. return;
  2454. }
  2455.  
  2456. if( IsDefined( level.no_spectator ) && level.no_spectator )
  2457. {
  2458. wait( 3 );
  2459. ExitLevel();
  2460. }
  2461.  
  2462. // The check_for_level_end looks for this
  2463. self.is_zombie = true;
  2464.  
  2465. //failsafe against losing viewarms due to the thread returning them getting an endon from "zombified"
  2466. level thread failsafe_revive_give_back_weapons(self);
  2467.  
  2468. // Remove all reviving abilities
  2469. self notify ( "zombified" );
  2470.  
  2471. if( isdefined( self.revivetrigger ) )
  2472. {
  2473. self.revivetrigger delete();
  2474. self.revivetrigger = undefined;
  2475. }
  2476.  
  2477. self.zombification_time = GetTime(); //set time when player died
  2478.  
  2479. resetTimeout();
  2480.  
  2481. // Stop shellshock and rumble
  2482. self StopShellshock();
  2483. self StopRumble( "damage_heavy" );
  2484.  
  2485. self.sessionstate = "spectator";
  2486. self.spectatorclient = -1;
  2487.  
  2488. self.maxhealth = self.health;
  2489. self.shellshocked = false;
  2490. self.inWater = false;
  2491. self.friendlydamage = undefined;
  2492. self.hasSpawned = true;
  2493. self.spawnTime = GetTime();
  2494. self.afk = false;
  2495.  
  2496. self detachAll();
  2497.  
  2498. if( isdefined( level.custom_spectate_permissions ) )
  2499. {
  2500. self [[level.custom_spectate_permissions]]();
  2501. }
  2502. else
  2503. {
  2504. self setSpectatePermissions( true );
  2505. }
  2506. self thread spectator_thread();
  2507.  
  2508. self Spawn( self.origin, self.angles );
  2509. self notify( "spawned_spectator" );
  2510. }
  2511.  
  2512. function setSpectatePermissions( isOn )
  2513. {
  2514. self AllowSpectateTeam( "allies", isOn && self.team == "allies" );
  2515. self AllowSpectateTeam( "axis", isOn && self.team == "axis" );
  2516. self AllowSpectateTeam( "freelook", false );
  2517. self AllowSpectateTeam( "none", false );
  2518. }
  2519.  
  2520. function spectator_thread()
  2521. {
  2522. self endon( "disconnect" );
  2523. self endon( "spawned_player" );
  2524.  
  2525. /* we are not currently supporting the shared screen tech
  2526. if( self IsSplitScreen() )
  2527. {
  2528. last_alive = undefined;
  2529. players = GetPlayers();
  2530.  
  2531. for( i = 0; i < players.size; i++ )
  2532. {
  2533. if( !players[i].is_zombie )
  2534. {
  2535. last_alive = players[i];
  2536. }
  2537. }
  2538.  
  2539. share_screen( last_alive, true );
  2540.  
  2541. return;
  2542. }
  2543. */
  2544.  
  2545. // self thread spectator_toggle_3rd_person();
  2546. }
  2547.  
  2548. function spectator_toggle_3rd_person()
  2549. {
  2550. self endon( "disconnect" );
  2551. self endon( "spawned_player" );
  2552.  
  2553. third_person = true;
  2554. self set_third_person( true );
  2555. }
  2556.  
  2557.  
  2558. function set_third_person( value )
  2559. {
  2560. if( value )
  2561. {
  2562. self SetClientThirdPerson( 1 );
  2563. self SetClientThirdPersonAngle( 354 );
  2564.  
  2565. self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
  2566. }
  2567. else
  2568. {
  2569. self SetClientThirdPerson( 0 );
  2570. self SetClientThirdPersonAngle( 0 );
  2571.  
  2572. self setDepthOfField( 0, 0, 512, 4000, 4, 0 );
  2573. }
  2574. self resetFov();
  2575. }
  2576.  
  2577. function last_stand_revive()
  2578. {
  2579. level endon( "between_round_over" );
  2580.  
  2581. players = GetPlayers();
  2582.  
  2583.  
  2584. //If everyone is in last stand or spectate then revive all
  2585. laststand_count = 0;
  2586. foreach(player in players)
  2587. {
  2588. if( !zm_utility::is_player_valid( player ) )
  2589. {
  2590. laststand_count ++;
  2591. }
  2592. }
  2593.  
  2594. if( laststand_count == players.size )
  2595. {
  2596. for ( i = 0; i < players.size; i++ )
  2597. {
  2598. if ( players[i] laststand::player_is_in_laststand() && players[i].revivetrigger.beingRevived == 0 )
  2599. {
  2600. players[i] zm_laststand::auto_revive( players[i] );
  2601. }
  2602. }
  2603. }
  2604. }
  2605.  
  2606. // ww: arrange the last stand pistols so when it come time to choose which one they are inited
  2607. function last_stand_pistol_rank_init()
  2608. {
  2609. level.pistol_values = [];
  2610.  
  2611. // ww: in a solo game the ranking of the pistols is a bit different based on the upgraded 1911 swap
  2612. // any pistol ranked level.pistol_value_solo_replace_below or lower will be ignored and the player will be given the upgraded 1911
  2613. level.pistol_values[ level.pistol_values.size ] = level.default_laststandpistol;
  2614. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_burst" );
  2615. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_fullauto" );
  2616. level.pistol_value_solo_replace_below = level.pistol_values.size-1; // EO: anything scoring lower than this should be replaced
  2617. level.pistol_values[ level.pistol_values.size ] = level.default_solo_laststandpistol;
  2618. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_burst_upgraded" );
  2619. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_fullauto_upgraded" );
  2620. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "ray_gun" );
  2621. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark2" );
  2622. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "ray_gun_upgraded" );
  2623. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark2_upgraded" );
  2624. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark3" );
  2625. level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark3_upgraded" );
  2626. }
  2627.  
  2628. function last_stand_pistol_swap()
  2629. {
  2630. if ( self zm_utility::has_powerup_weapon() )
  2631. {
  2632. // this will force the laststand module to switch us to any primary weapon, since we will no longer have this after revive
  2633. self.lastActiveWeapon = level.weaponNone;
  2634. }
  2635.  
  2636. // PORTIZ: chance to override the player's last stand pistol, but only if the override is stronger than the current one
  2637. if ( isdefined( self.w_min_last_stand_pistol_override ) )
  2638. {
  2639. self last_stand_minimum_pistol_override();
  2640. }
  2641.  
  2642. if ( !self HasWeapon( self.laststandpistol ) )
  2643. {
  2644. self GiveWeapon( self.laststandpistol );
  2645. }
  2646. ammoclip = self.laststandpistol.clipSize;
  2647. doubleclip = ammoclip * 2;
  2648.  
  2649. if( IS_TRUE( self._special_solo_pistol_swap ) || (self.laststandpistol == level.default_solo_laststandpistol && !self.hadpistol) )
  2650. {
  2651. self._special_solo_pistol_swap = 0;
  2652. self.hadpistol = false;
  2653. self SetWeaponAmmoStock( self.laststandpistol, doubleclip );
  2654. }
  2655. else if( level flag::get("solo_game") && self.laststandpistol == level.default_solo_laststandpistol )
  2656. {
  2657. self SetWeaponAmmoStock( self.laststandpistol, doubleclip );
  2658. }
  2659. else if ( self.laststandpistol == level.default_laststandpistol )
  2660. {
  2661. self SetWeaponAmmoStock( self.laststandpistol, doubleclip );
  2662. }
  2663. else if ( !isdefined( self.stored_weapon_info[ self.laststandpistol ] ) )
  2664. {
  2665. self SetWeaponAmmoStock( self.laststandpistol, doubleclip ); // PORTIZ: in the case that we awarded a temporary last stand weapon, just set the stock and skip the ammo tracking
  2666. }
  2667. else if ( self.laststandpistol.name == "ray_gun" || self.laststandpistol.name == "ray_gun_upgraded" )
  2668. {
  2669. if ( self.stored_weapon_info[ self.laststandpistol ].total_amt >= ammoclip )
  2670. {
  2671. self SetWeaponAmmoClip( self.laststandpistol, ammoclip );
  2672. self.stored_weapon_info[ self.laststandpistol ].given_amt = ammoclip;
  2673. }
  2674. else
  2675. {
  2676. self SetWeaponAmmoClip( self.laststandpistol, self.stored_weapon_info[ self.laststandpistol ].total_amt );
  2677. self.stored_weapon_info[ self.laststandpistol ].given_amt = self.stored_weapon_info[ self.laststandpistol ].total_amt;
  2678. }
  2679. self SetWeaponAmmoStock( self.laststandpistol, 0 );
  2680. }
  2681. else
  2682. {
  2683. if ( self.stored_weapon_info[ self.laststandpistol ].stock_amt >= doubleclip )
  2684. {
  2685. self SetWeaponAmmoStock( self.laststandpistol, doubleclip );
  2686. self.stored_weapon_info[ self.laststandpistol ].given_amt = doubleclip + self.stored_weapon_info[ self.laststandpistol ].clip_amt + self.stored_weapon_info[ self.laststandpistol ].left_clip_amt;
  2687. }
  2688. else
  2689. {
  2690. self SetWeaponAmmoStock( self.laststandpistol, self.stored_weapon_info[ self.laststandpistol ].stock_amt );
  2691. self.stored_weapon_info[ self.laststandpistol ].given_amt = self.stored_weapon_info[ self.laststandpistol ].total_amt;
  2692. }
  2693. }
  2694.  
  2695. self SwitchToWeapon( self.laststandpistol );
  2696. }
  2697.  
  2698. // PORTIZ: this runs if self.w_min_last_stand_pistol_override is defined, and just before the player is given his last stand pistol.
  2699. function last_stand_minimum_pistol_override()
  2700. {
  2701. for( i = 0; i < level.pistol_values.size; i++ )
  2702. {
  2703. if( level.pistol_values[i] == self.w_min_last_stand_pistol_override )
  2704. {
  2705. n_min_last_stand_pistol_value = i; // find the value corresponding to our override weapon
  2706. break;
  2707. }
  2708. }
  2709.  
  2710. for( k = 0; k < level.pistol_values.size; k++ )
  2711. {
  2712. if( level.pistol_values[k] == self.laststandpistol )
  2713. {
  2714. n_default_last_stand_pistol_value = k; // find the value corresponding to our default last stand weapon
  2715. break;
  2716. }
  2717. }
  2718.  
  2719. if ( n_min_last_stand_pistol_value > n_default_last_stand_pistol_value )
  2720. {
  2721. self.hadpistol = false;
  2722. self.laststandpistol = self.w_min_last_stand_pistol_override;
  2723. }
  2724. }
  2725.  
  2726. // ww: make sure the player has the best pistol when they go in to last stand
  2727. function last_stand_best_pistol()
  2728. {
  2729. pistol_array = [];
  2730.  
  2731. current_weapons = self GetWeaponsListPrimaries();
  2732.  
  2733. for( i = 0; i < current_weapons.size; i++ )
  2734. {
  2735. // make sure the weapon is a pistol
  2736. wclass = current_weapons[i].weapClass;
  2737. if ( current_weapons[i].isBallisticKnife )
  2738. {
  2739. wclass = "knife";
  2740. }
  2741.  
  2742. if ( wclass == "pistol" || wclass == "pistolspread" || wclass == "pistol spread" )
  2743. {
  2744. if ( (current_weapons[i] != level.default_solo_laststandpistol && !level flag::get("solo_game") ) || (!level flag::get("solo_game") && current_weapons[i] != level.default_solo_laststandpistol ))
  2745. {
  2746. if( (current_weapons[i] != self.laststandpistol) || (self.laststandpistol != level.default_laststandpistol) )
  2747. {
  2748. if ( self GetAmmoCount( current_weapons[i] ) <= 0 )
  2749. {
  2750. continue;
  2751. }
  2752. }
  2753. }
  2754.  
  2755. pistol_array_index = pistol_array.size; // set up the spot in the array
  2756. pistol_array[ pistol_array_index ] = SpawnStruct(); // struct to store info on
  2757.  
  2758. pistol_array[ pistol_array_index ].weapon = current_weapons[i];
  2759. pistol_array[ pistol_array_index ].value = 0; // add a value in case a new weapon is introduced that hasn't been set up in level.pistol_values
  2760.  
  2761. // compare the current weapon to the level.pistol_values to see what the value is
  2762. for( j = 0; j < level.pistol_values.size; j++ )
  2763. {
  2764. if( level.pistol_values[j] == current_weapons[i].rootWeapon )
  2765. {
  2766. pistol_array[ pistol_array_index ].value = j;
  2767. break;
  2768. }
  2769. }
  2770. }
  2771. }
  2772.  
  2773. self.laststandpistol = last_stand_compare_pistols( pistol_array );
  2774. }
  2775.  
  2776. // ww: compares the array passed in for the highest valued pistol
  2777. function last_stand_compare_pistols( struct_array )
  2778. {
  2779. if( !IsArray( struct_array ) || struct_array.size <= 0 )
  2780. {
  2781. self.hadpistol = false;
  2782.  
  2783. //array will be empty if the pistol had no ammo...so lets see if the player had the pistol
  2784. if(isDefined(self.stored_weapon_info))
  2785. {
  2786. stored_weapon_info = GetArrayKeys( self.stored_weapon_info );
  2787. for( j = 0; j < stored_weapon_info.size; j++ )
  2788. {
  2789. if( stored_weapon_info[ j ].rootWeapon == level.laststandpistol)
  2790. {
  2791. self.hadpistol = true;
  2792. return stored_weapon_info[ j ];
  2793. }
  2794. }
  2795. }
  2796.  
  2797. return level.laststandpistol; // nothing in the array then give the level last stand pistol
  2798. }
  2799.  
  2800. highest_score_pistol = struct_array[0]; // first time through give the first one to the highest score
  2801.  
  2802. for( i = 1; i < struct_array.size; i++ )
  2803. {
  2804. if( struct_array[i].value > highest_score_pistol.value )
  2805. {
  2806. highest_score_pistol = struct_array[i];
  2807. }
  2808. }
  2809.  
  2810. if( level flag::get( "solo_game" ) )
  2811. {
  2812. self._special_solo_pistol_swap = 0; // ww: this way the weapon knows to pack texture when given
  2813. if( highest_score_pistol.value <= level.pistol_value_solo_replace_below )
  2814. {
  2815. self.hadpistol = false;
  2816. self._special_solo_pistol_swap = 1;
  2817.  
  2818. if ( IS_TRUE( level.force_solo_quick_revive ) && ( !self HasPerk( PERK_QUICK_REVIVE ) ) )
  2819. {
  2820. return highest_score_pistol.weapon; // ar: gun won't be replaced
  2821. }
  2822. else
  2823. {
  2824. return level.laststandpistol; // ww: if it scores too low the player gets the 1911 upgraded
  2825. }
  2826. }
  2827. else
  2828. {
  2829. return highest_score_pistol.weapon; // ww: gun is high in ranking and won't be replaced
  2830. }
  2831. }
  2832. else // ww: happens when not in solo
  2833. {
  2834. return highest_score_pistol.weapon;
  2835. }
  2836.  
  2837. }
  2838.  
  2839. // ww: override function for saving player pistol ammo count
  2840. function last_stand_save_pistol_ammo()
  2841. {
  2842. weapon_inventory = self GetWeaponsList( true );
  2843. self.stored_weapon_info = [];
  2844.  
  2845. for( i = 0; i < weapon_inventory.size; i++ )
  2846. {
  2847. weapon = weapon_inventory[i];
  2848.  
  2849. wclass = weapon.weapClass;
  2850. if ( weapon.isBallisticKnife )
  2851. {
  2852. wclass = "knife";
  2853. }
  2854.  
  2855. if ( wclass == "pistol" || wclass == "pistolspread" || wclass == "pistol spread" )
  2856. {
  2857. self.stored_weapon_info[ weapon ] = SpawnStruct();
  2858. self.stored_weapon_info[ weapon ].clip_amt = self GetWeaponAmmoClip( weapon );
  2859. self.stored_weapon_info[ weapon ].left_clip_amt = 0;
  2860. dual_wield_weapon = weapon.dualWieldWeapon;
  2861. if ( level.weaponNone != dual_wield_weapon )
  2862. {
  2863. self.stored_weapon_info[ weapon ].left_clip_amt = self GetWeaponAmmoClip( dual_wield_weapon );
  2864. }
  2865. self.stored_weapon_info[ weapon ].stock_amt = self GetWeaponAmmoStock( weapon );
  2866. self.stored_weapon_info[ weapon ].total_amt = self.stored_weapon_info[ weapon ].clip_amt + self.stored_weapon_info[ weapon ].left_clip_amt + self.stored_weapon_info[ weapon ].stock_amt;
  2867. self.stored_weapon_info[ weapon ].given_amt = 0;
  2868. }
  2869. }
  2870.  
  2871. self last_stand_best_pistol();
  2872. }
  2873.  
  2874. // ww: override to restore the player's pistol ammo after being picked up
  2875. function last_stand_restore_pistol_ammo()
  2876. {
  2877. self.weapon_taken_by_losing_specialty_additionalprimaryweapon = level.weaponNone;
  2878.  
  2879. if ( !IsDefined( self.stored_weapon_info ) )
  2880. {
  2881. return;
  2882. }
  2883.  
  2884. weapon_inventory = self GetWeaponsList( true );
  2885. weapon_to_restore = GetArrayKeys( self.stored_weapon_info );
  2886.  
  2887. for( i = 0; i < weapon_inventory.size; i++ )
  2888. {
  2889. weapon = weapon_inventory[i];
  2890.  
  2891. if ( weapon != self.laststandpistol )
  2892. {
  2893. continue;
  2894. }
  2895.  
  2896. // for this loop, weapon == self.laststandpistol
  2897. for( j = 0; j < weapon_to_restore.size; j++ )
  2898. {
  2899. if ( weapon == weapon_to_restore[j] )
  2900. {
  2901. dual_wield_weapon = weapon_to_restore[j].dualWieldWeapon;
  2902. if ( weapon != level.default_laststandpistol )
  2903. {
  2904. last_clip = self GetWeaponAmmoClip( weapon );
  2905. last_left_clip = 0;
  2906. if ( level.weaponNone != dual_wield_weapon )
  2907. {
  2908. last_left_clip = self GetWeaponAmmoClip( dual_wield_weapon );
  2909. }
  2910. last_stock = self GetWeaponAmmoStock( weapon );
  2911. last_total = last_clip + last_left_clip + last_stock;
  2912.  
  2913. used_amt = self.stored_weapon_info[ weapon ].given_amt - last_total;
  2914.  
  2915. if ( used_amt >= self.stored_weapon_info[ weapon ].stock_amt )
  2916. {
  2917. used_amt -= self.stored_weapon_info[ weapon ].stock_amt;
  2918. self.stored_weapon_info[ weapon ].stock_amt = 0;
  2919.  
  2920. self.stored_weapon_info[ weapon ].clip_amt -= used_amt;
  2921. if ( self.stored_weapon_info[ weapon ].clip_amt < 0 )
  2922. {
  2923. self.stored_weapon_info[ weapon ].clip_amt = 0;
  2924. }
  2925. }
  2926. else
  2927. {
  2928. new_stock_amt = self.stored_weapon_info[ weapon ].stock_amt - used_amt;
  2929. if ( new_stock_amt < self.stored_weapon_info[ weapon ].stock_amt )
  2930. {
  2931. self.stored_weapon_info[ weapon ].stock_amt = new_stock_amt;
  2932. }
  2933. }
  2934. }
  2935.  
  2936. self SetWeaponAmmoClip( weapon, self.stored_weapon_info[weapon].clip_amt );
  2937. if ( level.weaponNone != dual_wield_weapon )
  2938. {
  2939. self SetWeaponAmmoClip( dual_wield_weapon, self.stored_weapon_info[weapon].left_clip_amt );
  2940. }
  2941. self SetWeaponAmmoStock( weapon, self.stored_weapon_info[weapon].stock_amt );
  2942. break;
  2943. }
  2944. }
  2945. }
  2946. }
  2947.  
  2948. function last_stand_take_thrown_grenade()
  2949. {
  2950. self endon( "disconnect" );
  2951. self endon( "bled_out" );
  2952. self endon( "player_revived" );
  2953.  
  2954. self waittill ( "grenade_fire", grenade, weapon );
  2955.  
  2956. if ( isdefined(self.lsgsar_lethal) && weapon == self.lsgsar_lethal )
  2957. {
  2958. self.lsgsar_lethal_nade_amt--;
  2959. }
  2960.  
  2961. if ( isdefined(self.lsgsar_tactical) && weapon == self.lsgsar_tactical )
  2962. {
  2963. self.lsgsar_tactical_nade_amt--;
  2964. }
  2965. }
  2966.  
  2967. // ww: zeros out the player's grenades until they revive
  2968. function last_stand_grenade_save_and_return()
  2969. {
  2970. if(IS_TRUE(level.isresetting_grief)) //don't do this for Grief when resetting the round
  2971. {
  2972. return;
  2973. }
  2974. self endon( "disconnect" );
  2975. self endon ("bled_out");
  2976.  
  2977. self.lsgsar_lethal_nade_amt = 0;
  2978. self.lsgsar_has_lethal_nade = false;
  2979. self.lsgsar_tactical_nade_amt = 0;
  2980. self.lsgsar_has_tactical_nade = false;
  2981. self.lsgsar_lethal = undefined;
  2982. self.lsgsar_tactical = undefined;
  2983.  
  2984. if (self IsThrowingGrenade())
  2985. {
  2986. self thread last_stand_take_thrown_grenade();
  2987. }
  2988.  
  2989. weapon = self zm_utility::get_player_lethal_grenade();
  2990. if ( weapon != level.weaponNone )
  2991. {
  2992. self.lsgsar_has_lethal_nade = true;
  2993. self.lsgsar_lethal = weapon;
  2994. self.lsgsar_lethal_nade_amt = self GetWeaponAmmoClip( weapon );
  2995. self SetWeaponAmmoClip( weapon, 0 );
  2996. self TakeWeapon( weapon );
  2997. }
  2998.  
  2999. weapon = self zm_utility::get_player_tactical_grenade();
  3000. if ( weapon != level.weaponNone )
  3001. {
  3002. self.lsgsar_has_tactical_nade = true;
  3003. self.lsgsar_tactical = weapon;
  3004. self.lsgsar_tactical_nade_amt = self GetWeaponAmmoClip( weapon );
  3005. self SetWeaponAmmoClip( weapon, 0 );
  3006. self TakeWeapon( weapon );
  3007. }
  3008.  
  3009. self waittill( "player_revived" );
  3010.  
  3011. if ( self.lsgsar_has_lethal_nade )
  3012. {
  3013. self zm_utility::set_player_lethal_grenade( self.lsgsar_lethal );
  3014. self GiveWeapon( self.lsgsar_lethal );
  3015. self SetWeaponAmmoClip( self.lsgsar_lethal, self.lsgsar_lethal_nade_amt );
  3016. }
  3017.  
  3018. if ( self.lsgsar_has_tactical_nade )
  3019. {
  3020. self zm_utility::set_player_tactical_grenade( self.lsgsar_tactical );
  3021. self GiveWeapon( self.lsgsar_tactical );
  3022. self SetWeaponAmmoClip( self.lsgsar_tactical, self.lsgsar_tactical_nade_amt );
  3023. }
  3024.  
  3025. self.lsgsar_lethal_nade_amt = undefined;
  3026. self.lsgsar_has_lethal_nade = undefined;
  3027. self.lsgsar_tactical_nade_amt = undefined;
  3028. self.lsgsar_has_tactical_nade = undefined;
  3029. self.lsgsar_lethal = undefined;
  3030. self.lsgsar_tactical = undefined;
  3031.  
  3032. }
  3033.  
  3034. function spectators_respawn()
  3035. {
  3036. level endon( "between_round_over" );
  3037.  
  3038. if( !IsDefined( level.zombie_vars["spectators_respawn"] ) || !level.zombie_vars["spectators_respawn"] )
  3039. {
  3040. return;
  3041. }
  3042.  
  3043. while( 1 )
  3044. {
  3045. players = GetPlayers();
  3046. for( i = 0; i < players.size; i++ )
  3047. {
  3048. e_player = players[i];
  3049. e_player spectator_respawn_player();
  3050. }
  3051.  
  3052. wait( 1 );
  3053. }
  3054. }
  3055.  
  3056. function spectator_respawn_player()
  3057. {
  3058. if( self.sessionstate == "spectator" && IsDefined( self.spectator_respawn ))
  3059. {
  3060. if( !IsDefined( level.custom_spawnPlayer ) )
  3061. {
  3062. // Custom spawn call for when they respawn from spectator
  3063. level.custom_spawnPlayer = &spectator_respawn;
  3064. }
  3065.  
  3066. self [[level.spawnPlayer]]();
  3067. thread refresh_player_navcard_hud();
  3068. if (isDefined(level.script) && level.round_number > 6 && self.score < 1500)
  3069. {
  3070. self.old_score = self.score;
  3071. if(isDefined(level.spectator_respawn_custom_score))
  3072. {
  3073. self [[level.spectator_respawn_custom_score]]();
  3074. }
  3075. self.score = 1500;
  3076. }
  3077. }
  3078. }
  3079.  
  3080. function spectator_respawn()
  3081. {
  3082. assert( IsDefined( self.spectator_respawn ) );
  3083.  
  3084. origin = self.spectator_respawn.origin;
  3085. angles = self.spectator_respawn.angles;
  3086.  
  3087. self setSpectatePermissions( false );
  3088.  
  3089. new_origin = undefined;
  3090.  
  3091.  
  3092. if ( isdefined( level.check_valid_spawn_override ) )
  3093. {
  3094. new_origin = [[ level.check_valid_spawn_override ]]( self );
  3095. }
  3096.  
  3097. if ( !isdefined( new_origin ) )
  3098. {
  3099. new_origin = check_for_valid_spawn_near_team( self,true );
  3100. }
  3101.  
  3102.  
  3103. if( IsDefined( new_origin ) )
  3104. {
  3105. if(!isDefined(new_origin.angles))
  3106. {
  3107. angles = (0, 0, 0);
  3108. }
  3109. else
  3110. {
  3111. angles = new_origin.angles;
  3112. }
  3113. self Spawn( new_origin.origin, angles );
  3114. }
  3115. else
  3116. {
  3117. self Spawn( origin, angles );
  3118. }
  3119.  
  3120.  
  3121. if ( IsDefined( self zm_utility::get_player_placeable_mine() ) )
  3122. {
  3123. self TakeWeapon( self zm_utility::get_player_placeable_mine() );
  3124. self zm_utility::set_player_placeable_mine( level.weaponNone );
  3125. }
  3126.  
  3127. self zm_equipment::take();
  3128.  
  3129. self.is_burning = undefined;
  3130. self.abilities = [];
  3131.  
  3132. // The check_for_level_end looks for this
  3133. self.is_zombie = false;
  3134. zm_laststand::set_ignoreme( false );
  3135.  
  3136. self clientfield::set( "zmbLastStand", 0 );
  3137. self RevivePlayer();
  3138.  
  3139. self notify( "spawned_player" );
  3140. self callback::callback( #"on_player_spawned" );
  3141.  
  3142. if(IsDefined(level._zombiemode_post_respawn_callback))
  3143. {
  3144. self thread [[level._zombiemode_post_respawn_callback]]();
  3145. }
  3146.  
  3147. // Penalize the player when we respawn, since he 'died'
  3148. self zm_score::player_reduce_points( "died" );
  3149.  
  3150. self zm_melee_weapon::spectator_respawn_all();
  3151.  
  3152. self thread player_zombie_breadcrumb();
  3153.  
  3154. self thread zm_perks::return_retained_perks();
  3155.  
  3156. return true;
  3157. }
  3158.  
  3159.  
  3160. //*****************************************************************************
  3161. //*****************************************************************************
  3162.  
  3163. function check_for_valid_spawn_near_team( revivee, return_struct )
  3164. {
  3165. // if level override is detected, use it instead of normal respawn logic
  3166. if ( IsDefined( level.check_for_valid_spawn_near_team_callback ) )
  3167. {
  3168. spawn_location = [[ level.check_for_valid_spawn_near_team_callback ]](revivee, return_struct);
  3169. return spawn_location;
  3170. }
  3171. else // normal respawn logic below here
  3172. {
  3173. players = GetPlayers();
  3174. spawn_points = zm_gametype::get_player_spawns_for_gametype();
  3175.  
  3176. closest_group = undefined;
  3177. closest_distance = 100000000;
  3178. backup_group = undefined;
  3179. backup_distance = 100000000;
  3180.  
  3181. if( spawn_points.size == 0 )
  3182. return undefined;
  3183.  
  3184. a_enabled_zone_entities = zm_zonemgr::get_active_zones_entities();
  3185.  
  3186. // Look for the closest group that is within the specified ideal distances
  3187. // If we can't find one within a valid area, use the closest unlocked group.
  3188. for( i = 0; i < players.size; i++ )
  3189. {
  3190. if( zm_utility::is_player_valid( players[i],undefined,true ) && (players[i] != self) )
  3191. {
  3192. for( j = 0 ; j < spawn_points.size; j++ )
  3193. {
  3194. if( isdefined(spawn_points[j].script_int) )
  3195. ideal_distance = spawn_points[j].script_int;
  3196. else
  3197. ideal_distance = 1000;
  3198.  
  3199. // Safety check, check the spawn point is inside an enabled zone
  3200. // There have been cases where a spawn point has the wrong zone KVP on it compared to the zone it exists inside
  3201. if ( zm_utility::check_point_in_enabled_zone( spawn_points[j].origin, false, a_enabled_zone_entities ) == false )
  3202. {
  3203. continue;
  3204. }
  3205.  
  3206. if ( spawn_points[j].locked == false )
  3207. {
  3208. plyr_dist = DistanceSquared( players[i].origin, spawn_points[j].origin );
  3209. if( plyr_dist < ( ideal_distance * ideal_distance ) )
  3210. {
  3211. if ( plyr_dist < closest_distance )
  3212. {
  3213. closest_distance = plyr_dist;
  3214. closest_group = j;
  3215. }
  3216. }
  3217. else
  3218. {
  3219. if ( plyr_dist < backup_distance )
  3220. {
  3221. backup_group = j;
  3222. backup_distance = plyr_dist;
  3223. }
  3224. }
  3225. }
  3226. }
  3227. }
  3228.  
  3229. // If we don't have a closest_group, let's use the backup
  3230. if( !IsDefined( closest_group ) )
  3231. {
  3232. closest_group = backup_group;
  3233. }
  3234.  
  3235. if( IsDefined( closest_group ) )
  3236. {
  3237. spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct );
  3238. if( IsDefined(spawn_location) )
  3239. {
  3240. return( spawn_location );
  3241. }
  3242. }
  3243. }
  3244.  
  3245. return undefined;
  3246. }
  3247. }
  3248.  
  3249.  
  3250. //*****************************************************************************
  3251. //*****************************************************************************
  3252.  
  3253. function get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct )
  3254. {
  3255. spawn_array =struct::get_array( spawn_points[closest_group].target, "targetname" );
  3256. spawn_array = array::randomize(spawn_array);
  3257.  
  3258. for( k = 0; k < spawn_array.size; k++ )
  3259. {
  3260. if(IsDefined(spawn_array[k].plyr) && spawn_array[k].plyr == revivee GetEntityNumber())
  3261. {
  3262. if(positionWouldTelefrag(spawn_array[k].origin))
  3263. {
  3264. spawn_array[k].plyr = undefined;
  3265. break;
  3266. }
  3267. else if(IS_TRUE(return_struct))
  3268. {
  3269. return spawn_array[k];
  3270. }
  3271. else
  3272. {
  3273. return spawn_array[k].origin;
  3274. }
  3275. }
  3276. }
  3277.  
  3278. for( k = 0; k < spawn_array.size; k++ )
  3279. {
  3280. if(positionWouldTelefrag(spawn_array[k].origin))
  3281. {
  3282. continue;
  3283. }
  3284. if(!IsDefined(spawn_array[k].plyr) || spawn_array[k].plyr == revivee GetEntityNumber())
  3285. {
  3286. spawn_array[k].plyr = revivee GetEntityNumber();
  3287. if(IS_TRUE(return_struct))
  3288. {
  3289. return spawn_array[k];
  3290. }
  3291. else
  3292. {
  3293. return spawn_array[k].origin;
  3294. }
  3295. }
  3296. }
  3297.  
  3298. if(IS_TRUE(return_struct))
  3299. {
  3300. return spawn_array[0];
  3301. }
  3302.  
  3303. return spawn_array[0].origin;
  3304. }
  3305.  
  3306.  
  3307. //*****************************************************************************
  3308. //*****************************************************************************
  3309.  
  3310. function check_for_valid_spawn_near_position( revivee, v_position, return_struct )
  3311. {
  3312. spawn_points = zm_gametype::get_player_spawns_for_gametype();
  3313.  
  3314. if( spawn_points.size == 0 )
  3315. {
  3316. return( undefined );
  3317. }
  3318.  
  3319. closest_group = undefined;
  3320. closest_distance = 100000000;
  3321. backup_group = undefined;
  3322. backup_distance = 100000000;
  3323.  
  3324. for( i=0 ; i<spawn_points.size; i++ )
  3325. {
  3326. if( IsDefined(spawn_points[i].script_int) )
  3327. {
  3328. ideal_distance = spawn_points[i].script_int;
  3329. }
  3330. else
  3331. {
  3332. ideal_distance = 1000;
  3333. }
  3334.  
  3335. if ( spawn_points[i].locked == false )
  3336. {
  3337. dist = DistanceSquared( v_position, spawn_points[i].origin );
  3338. if( dist < ( ideal_distance * ideal_distance ) )
  3339. {
  3340. if ( dist < closest_distance )
  3341. {
  3342. closest_distance = dist;
  3343. closest_group = i;
  3344. }
  3345. }
  3346. else
  3347. {
  3348. if ( dist < backup_distance )
  3349. {
  3350. backup_group = i;
  3351. backup_distance = dist;
  3352. }
  3353. }
  3354. }
  3355. // If we don't have a closest_group, let's use the backup
  3356. if ( !IsDefined( closest_group ) )
  3357. {
  3358. closest_group = backup_group;
  3359. }
  3360. }
  3361.  
  3362. if( IsDefined( closest_group ) )
  3363. {
  3364. spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct );
  3365. if( IsDefined(spawn_location) )
  3366. {
  3367. return( spawn_location );
  3368. }
  3369. }
  3370.  
  3371. return undefined;
  3372. }
  3373.  
  3374.  
  3375.  
  3376. //*****************************************************************************
  3377. // Get a valid spawn point within the (min_distance, max_distance) ranges
  3378. //*****************************************************************************
  3379.  
  3380. function check_for_valid_spawn_within_range( revivee, v_position, return_struct, min_distance, max_distance )
  3381. {
  3382. spawn_points = zm_gametype::get_player_spawns_for_gametype();
  3383.  
  3384. if( spawn_points.size == 0 )
  3385. {
  3386. return( undefined );
  3387. }
  3388.  
  3389. closest_group = undefined;
  3390. closest_distance = 100000000;
  3391.  
  3392. for( i=0 ; i<spawn_points.size; i++ )
  3393. {
  3394. if ( spawn_points[i].locked == false )
  3395. {
  3396. dist = Distance( v_position, spawn_points[i].origin );
  3397. if( (dist >= min_distance) && (dist <= max_distance) )
  3398. {
  3399. if( dist < closest_distance )
  3400. {
  3401. closest_distance = dist;
  3402. closest_group = i;
  3403. }
  3404. }
  3405. }
  3406. }
  3407.  
  3408. if( IsDefined( closest_group ) )
  3409. {
  3410. spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct );
  3411. if( IsDefined(spawn_location) )
  3412. {
  3413. return( spawn_location );
  3414. }
  3415. }
  3416.  
  3417. return undefined;
  3418. }
  3419.  
  3420.  
  3421. //*****************************************************************************
  3422. //*****************************************************************************
  3423.  
  3424. function get_players_on_team(exclude)
  3425. {
  3426. teammates = [];
  3427.  
  3428. players = GetPlayers();
  3429. for(i=0;i<players.size;i++)
  3430. {
  3431. //check to see if other players on your team are alive and not waiting to be revived
  3432. if(players[i].spawn_side == self.spawn_side && !isDefined(players[i].revivetrigger) && players[i] != exclude )
  3433. {
  3434. teammates[teammates.size] = players[i];
  3435. }
  3436. }
  3437.  
  3438. return teammates;
  3439. }
  3440.  
  3441.  
  3442.  
  3443. function get_safe_breadcrumb_pos( player )
  3444. {
  3445. players = GetPlayers();
  3446. valid_players = [];
  3447.  
  3448. min_dist = 150 * 150;
  3449. for( i = 0; i < players.size; i++ )
  3450. {
  3451. if( !zm_utility::is_player_valid( players[i] ) )
  3452. {
  3453. continue;
  3454. }
  3455.  
  3456. valid_players[valid_players.size] = players[i];
  3457. }
  3458.  
  3459. for( i = 0; i < valid_players.size; i++ )
  3460. {
  3461. count = 0;
  3462. for( q = 1; q < player.zombie_breadcrumbs.size; q++ )
  3463. {
  3464. if( DistanceSquared( player.zombie_breadcrumbs[q], valid_players[i].origin ) < min_dist )
  3465. {
  3466. continue;
  3467. }
  3468.  
  3469. count++;
  3470. if( count == valid_players.size )
  3471. {
  3472. return player.zombie_breadcrumbs[q];
  3473. }
  3474. }
  3475. }
  3476.  
  3477. return undefined;
  3478. }
  3479.  
  3480. function round_spawning()
  3481. {
  3482. level endon( "intermission" );
  3483. level endon( "end_of_round" );
  3484. level endon( "restart_round" );
  3485.  
  3486. if( level.intermission )
  3487. {
  3488. return;
  3489. }
  3490.  
  3491. if ( cheat_enabled( 2 ) )
  3492. {
  3493. return;
  3494. }
  3495.  
  3496. if( level.zm_loc_types[ "zombie_location" ].size < 1 )
  3497. {
  3498. ASSERTMSG( "No active spawners in the map. Check to see if the zone is active and if it's pointing to spawners." );
  3499. return;
  3500. }
  3501.  
  3502. zombie_utility::ai_calculate_health( level.round_number );
  3503.  
  3504. count = 0;
  3505.  
  3506. //CODER MOD: TOMMY K
  3507. players = GetPlayers();
  3508. for( i = 0; i < players.size; i++ )
  3509. {
  3510. players[i].zombification_time = 0;
  3511. }
  3512.  
  3513. // Now set the total for the new round, except when it's already been set by the kill counter
  3514. if ( !( IsDefined( level.kill_counter_hud ) && level.zombie_total > 0 ) )
  3515. {
  3516. level.zombie_total = get_zombie_count_for_round( level.round_number, level.players.size );
  3517. level.zombie_respawns = 0; // reset number of zombies needing respawn
  3518. level notify( "zombie_total_set" );
  3519. }
  3520.  
  3521. if ( IsDefined( level.zombie_total_set_func ) )
  3522. {
  3523. level thread [[ level.zombie_total_set_func ]]();
  3524. }
  3525.  
  3526. if ( level.round_number < 10 || level.speed_change_max > 0 )
  3527. {
  3528. level thread zombie_utility::zombie_speed_up();
  3529. }
  3530.  
  3531. old_spawn = undefined;
  3532. while( 1 )
  3533. {
  3534. while( zombie_utility::get_current_zombie_count() >= level.zombie_ai_limit || level.zombie_total <= 0 )
  3535. {
  3536. wait( 0.1 );
  3537. }
  3538.  
  3539. while ( zombie_utility::get_current_actor_count() >= level.zombie_actor_limit )
  3540. {
  3541. zombie_utility::clear_all_corpses();
  3542. wait( 0.1 );
  3543. }
  3544.  
  3545. // if we're using something that can pause the world, wait until finished to continue spawning
  3546. if(flag::exists("world_is_paused"))
  3547. {
  3548. level flag::wait_till_clear("world_is_paused");
  3549. }
  3550.  
  3551. // added ability to pause zombie spawning
  3552. level flag::wait_till( "spawn_zombies" );
  3553.  
  3554. //Not great fix for this being zero - which it should NEVER be! (2 days to ship - PETER)
  3555. while( level.zm_loc_types[ "zombie_location" ].size <= 0 )
  3556. {
  3557. wait( 0.1 );
  3558. }
  3559.  
  3560. run_custom_ai_spawn_checks();
  3561.  
  3562. if ( IS_TRUE(level.hostMigrationTimer) )
  3563. {
  3564. util::wait_network_frame();
  3565. continue;
  3566. }
  3567.  
  3568. // Run custom round spawn logic - returns TRUE if we spawned something, FALSE if we need to spawn a zombie.
  3569. if ( isdefined( level.fn_custom_round_ai_spawn ) )
  3570. {
  3571. if ( [[ level.fn_custom_round_ai_spawn ]]() )
  3572. {
  3573. // we handled the spawn
  3574. util::wait_network_frame();
  3575. continue;
  3576. }
  3577. }
  3578.  
  3579. if( IsDefined( level.zombie_spawners ) )
  3580. {
  3581. // Check for custom zombie spawner selection
  3582. if ( isdefined( level.fn_custom_zombie_spawner_selection ) )
  3583. {
  3584. spawner = [[ level.fn_custom_zombie_spawner_selection ]]();
  3585. }
  3586.  
  3587. // Default zombie spawner selection
  3588. else
  3589. {
  3590. if( IS_TRUE( level.use_multiple_spawns ) )
  3591. {
  3592. if( isdefined( level.spawner_int ) && IS_TRUE( level.zombie_spawn[level.spawner_int].size ) )
  3593. {
  3594. spawner = array::random( level.zombie_spawn[level.spawner_int] );
  3595. }
  3596. else
  3597. {
  3598. spawner = array::random( level.zombie_spawners );
  3599. }
  3600. }
  3601. else
  3602. {
  3603. spawner = array::random( level.zombie_spawners );
  3604. }
  3605. }
  3606.  
  3607. ai = zombie_utility::spawn_zombie( spawner, spawner.targetname );
  3608. }
  3609.  
  3610. if( IsDefined( ai ) )
  3611. {
  3612. level.zombie_total--;
  3613. if ( level.zombie_respawns > 0 )
  3614. {
  3615. level.zombie_respawns--;
  3616. }
  3617.  
  3618. ai thread zombie_utility::round_spawn_failsafe();
  3619. count++;
  3620.  
  3621. if ( ai ai::has_behavior_attribute( "can_juke" ) )
  3622. {
  3623. ai ai::set_behavior_attribute("can_juke", false);
  3624. }
  3625.  
  3626. // Get zombies into the map quicker if they're respawning from cleanup
  3627. if ( level.zombie_respawns > 0 )//&& level.zombie_vars["zombie_spawn_delay"] > 1.0 )
  3628. {
  3629. wait 0.1;
  3630. }
  3631. else
  3632. {
  3633. wait( level.zombie_vars["zombie_spawn_delay"] );
  3634. }
  3635. }
  3636.  
  3637. util::wait_network_frame();
  3638. }
  3639. }
  3640.  
  3641. function get_zombie_count_for_round( n_round, n_player_count )
  3642. {
  3643. max = level.zombie_vars["zombie_max_ai"];
  3644.  
  3645. multiplier = n_round / 5;
  3646. if( multiplier < 1 )
  3647. {
  3648. multiplier = 1;
  3649. }
  3650.  
  3651. // After round 10, exponentially have more AI attack the player
  3652. if( n_round >= 10 )
  3653. {
  3654. multiplier *= n_round * 0.15;
  3655. }
  3656.  
  3657. if( n_player_count == 1 )
  3658. {
  3659. max += int( ( 0.5 * level.zombie_vars["zombie_ai_per_player"] ) * multiplier );
  3660. }
  3661. else
  3662. {
  3663. max += int( ( ( n_player_count - 1 ) * level.zombie_vars["zombie_ai_per_player"] ) * multiplier );
  3664. }
  3665.  
  3666. if( !isDefined( level.max_zombie_func ) )
  3667. {
  3668. level.max_zombie_func = &zombie_utility::default_max_zombie_func;
  3669. }
  3670.  
  3671. n_zombie_count = [[ level.max_zombie_func ]]( max, n_round );
  3672.  
  3673. return n_zombie_count;
  3674. }
  3675.  
  3676. // Add custom ai (quads, etc.) to zombie spawner arrays for spawning
  3677. function run_custom_ai_spawn_checks()
  3678. {
  3679. foreach ( str_id, s in level.custom_ai_spawn_check_funcs )
  3680. {
  3681. if ( [[ s.func_check ]]() )
  3682. {
  3683. a_spawners = [[ s.func_get_spawners ]]();
  3684. level.zombie_spawners = ArrayCombine( level.zombie_spawners, a_spawners, false, false );
  3685.  
  3686. if ( IS_TRUE( level.use_multiple_spawns ) )
  3687. {
  3688. foreach ( sp in a_spawners )
  3689. {
  3690. if ( IsDefined( sp.script_int ) )
  3691. {
  3692. if ( !IsDefined( level.zombie_spawn[ sp.script_int ] ) )
  3693. {
  3694. level.zombie_spawn[ sp.script_int ] = [];
  3695. }
  3696.  
  3697. if ( !IsInArray( level.zombie_spawn[ sp.script_int ], sp ) )
  3698. {
  3699. ARRAY_ADD( level.zombie_spawn[ sp.script_int ], sp );
  3700. }
  3701. }
  3702. }
  3703. }
  3704.  
  3705. if ( IsDefined( s.func_get_locations ) )
  3706. {
  3707. a_locations = [[ s.func_get_locations ]]();
  3708. level.zm_loc_types[ "zombie_location" ] = ArrayCombine( level.zm_loc_types[ "zombie_location" ], a_locations, false, false );
  3709. }
  3710. }
  3711. else
  3712. {
  3713. a_spawners = [[ s.func_get_spawners ]]();
  3714.  
  3715. foreach ( sp in a_spawners )
  3716. {
  3717. ArrayRemoveValue( level.zombie_spawners, sp );
  3718. }
  3719.  
  3720. if ( IS_TRUE( level.use_multiple_spawns ) )
  3721. {
  3722. foreach ( sp in a_spawners )
  3723. {
  3724. if ( IsDefined( sp.script_int ) && IsDefined( level.zombie_spawn[ sp.script_int ] ) )
  3725. {
  3726. ArrayRemoveValue( level.zombie_spawn[ sp.script_int ], sp );
  3727. }
  3728. }
  3729. }
  3730.  
  3731. if ( IsDefined( s.func_get_locations ) )
  3732. {
  3733. a_locations = [[ s.func_get_locations ]]();
  3734.  
  3735. foreach ( s_loc in a_locations )
  3736. {
  3737. ArrayRemoveValue( level.zm_loc_types[ "zombie_location" ], s_loc );
  3738. }
  3739. }
  3740. }
  3741. }
  3742. }
  3743.  
  3744. function register_custom_ai_spawn_check( str_id, func_check, func_get_spawners, func_get_locations )
  3745. {
  3746. if ( !IsDefined( level.custom_ai_spawn_check_funcs[str_id] ) )
  3747. {
  3748. level.custom_ai_spawn_check_funcs[ str_id ] = SpawnStruct();
  3749. }
  3750.  
  3751. level.custom_ai_spawn_check_funcs[ str_id ].func_check = func_check;
  3752. level.custom_ai_spawn_check_funcs[ str_id ].func_get_spawners = func_get_spawners;
  3753. level.custom_ai_spawn_check_funcs[ str_id ].func_get_locations = func_get_locations;
  3754. }
  3755.  
  3756. // TESTING: spawn one zombie at a time
  3757. function round_spawning_test()
  3758. {
  3759. while (true)
  3760. {
  3761. spawn_point = array::random( level.zm_loc_types[ "zombie_location" ] ); // grab a random spawner
  3762.  
  3763. spawner = array::random(level.zombie_spawners);
  3764. ai = zombie_utility::spawn_zombie( spawner,spawner.targetname,spawn_point);
  3765.  
  3766. ai waittill("death");
  3767.  
  3768. wait 5;
  3769. }
  3770. }
  3771.  
  3772.  
  3773. /////////////////////////////////////////////////////////
  3774.  
  3775. // round_text( text )
  3776. // {
  3777. // if( level.first_round )
  3778. // {
  3779. // intro = true;
  3780. // }
  3781. // else
  3782. // {
  3783. // intro = false;
  3784. // }
  3785. //
  3786. // hud = create_simple_hud();
  3787. // hud.horzAlign = "center";
  3788. // hud.vertAlign = "middle";
  3789. // hud.alignX = "center";
  3790. // hud.alignY = "middle";
  3791. // hud.y = -100;
  3792. // hud.foreground = 1;
  3793. // hud.fontscale = 16.0;
  3794. // hud.alpha = 0;
  3795. // hud.color = ( 1, 1, 1 );
  3796. //
  3797. // hud SetText( text );
  3798. // hud FadeOverTime( 1.5 );
  3799. // hud.alpha = 1;
  3800. // wait( 1.5 );
  3801. //
  3802. // if( intro )
  3803. // {
  3804. // wait( 1 );
  3805. // level notify( "intro_change_color" );
  3806. // }
  3807. //
  3808. // hud FadeOverTime( 3 );
  3809. // //hud.color = ( 0.8, 0, 0 );
  3810. // hud.color = ( 0.21, 0, 0 );
  3811. // wait( 3 );
  3812. //
  3813. // if( intro )
  3814. // {
  3815. // level waittill( "intro_hud_done" );
  3816. // }
  3817. //
  3818. // hud FadeOverTime( 1.5 );
  3819. // hud.alpha = 0;
  3820. // wait( 1.5 );
  3821. // hud destroy();
  3822. // }
  3823.  
  3824.  
  3825. // Allows the round to be paused. Displays a countdown timer.
  3826. //
  3827. function round_pause( delay )
  3828. {
  3829. if ( !IsDefined( delay ) )
  3830. {
  3831. delay = 30;
  3832. }
  3833.  
  3834. level.countdown_hud = zm_utility::create_counter_hud();
  3835. level.countdown_hud SetValue( delay );
  3836. level.countdown_hud.color = ( 1, 1, 1 );
  3837. level.countdown_hud.alpha = 1;
  3838. level.countdown_hud FadeOverTime( 2.0 );
  3839. wait( 2.0 );
  3840.  
  3841. level.countdown_hud.color = ( 0.21, 0, 0 );
  3842. level.countdown_hud FadeOverTime( 3.0 );
  3843. wait(3);
  3844.  
  3845. while (delay >= 1)
  3846. {
  3847. wait (1);
  3848. delay--;
  3849. level.countdown_hud SetValue( delay );
  3850. }
  3851.  
  3852. // Zero! Play end sound
  3853. players = GetPlayers();
  3854. for (i=0; i<players.size; i++ )
  3855. {
  3856. players[i] playlocalsound( "zmb_perks_packa_ready" );
  3857. }
  3858.  
  3859. level.countdown_hud FadeOverTime( 1.0 );
  3860. level.countdown_hud.color = (1,1,1);
  3861. level.countdown_hud.alpha = 0;
  3862. wait( 1.0 );
  3863.  
  3864. level.countdown_hud zm_utility::destroy_hud();
  3865. }
  3866.  
  3867.  
  3868. // Zombie spawning
  3869. //
  3870. function round_start()
  3871. {
  3872. if ( !isdefined( level.zombie_spawners) || level.zombie_spawners.size == 0 )
  3873. {
  3874. level flag::set( "begin_spawning" );
  3875. return;
  3876. }
  3877.  
  3878. if ( IsDefined(level.round_prestart_func) )
  3879. {
  3880. [[ level.round_prestart_func ]]();
  3881. }
  3882. else
  3883. {
  3884. n_delay = 2;
  3885.  
  3886. if ( IsDefined( level.zombie_round_start_delay ) )
  3887. {
  3888. n_delay = level.zombie_round_start_delay;
  3889. }
  3890.  
  3891. wait n_delay;
  3892. }
  3893.  
  3894. level.zombie_health = level.zombie_vars["zombie_health_start"];
  3895.  
  3896. if( GetDvarInt( "scr_writeconfigstrings" ) == 1 )
  3897. {
  3898. wait(5);
  3899. ExitLevel();
  3900. return;
  3901. }
  3902.  
  3903. if ( level.zombie_vars["game_start_delay"] > 0 )
  3904. {
  3905. round_pause( level.zombie_vars["game_start_delay"] );
  3906. }
  3907.  
  3908. level flag::set( "begin_spawning" );
  3909.  
  3910. if( !isDefined(level.round_spawn_func) )
  3911. {
  3912. level.round_spawn_func = &round_spawning;
  3913. }
  3914.  
  3915. if(!IsDefined(level.move_spawn_func))
  3916. {
  3917. level.move_spawn_func = &zm_utility::move_zombie_spawn_location;
  3918. }
  3919.  
  3920. if ( !isDefined(level.round_wait_func) )
  3921. {
  3922. level.round_wait_func = &round_wait;
  3923. }
  3924.  
  3925. if ( !IsDefined(level.round_think_func) )
  3926. {
  3927. level.round_think_func = &round_think;
  3928. }
  3929.  
  3930.  
  3931. level thread [[ level.round_think_func ]]();
  3932. }
  3933.  
  3934. //
  3935. // Lets the players know that you need power to open these
  3936. function play_door_dialog()
  3937. {
  3938. self endon ("warning_dialog");
  3939. timer = 0;
  3940.  
  3941. while(1)
  3942. {
  3943. WAIT_SERVER_FRAME;
  3944. players = GetPlayers();
  3945. for(i = 0; i < players.size; i++)
  3946. {
  3947. dist = distancesquared(players[i].origin, self.origin );
  3948. if(dist > 70*70)
  3949. {
  3950. timer =0;
  3951. continue;
  3952. }
  3953. while(dist < 70*70 && timer < 3)
  3954. {
  3955. wait(0.5);
  3956. timer++;
  3957. }
  3958. if(dist > 70*70 && timer >= 3)
  3959. {
  3960. self playsound("door_deny");
  3961.  
  3962. players[i] zm_audio::create_and_play_dialog( "general", "outofmoney" );
  3963. wait(3);
  3964. self notify ("warning_dialog");
  3965. //iprintlnbold("warning_given");
  3966. }
  3967. }
  3968. }
  3969. }
  3970.  
  3971. function wait_until_first_player()
  3972. {
  3973. players = GetPlayers();
  3974. if( !IsDefined( players[0] ) )
  3975. {
  3976. level waittill( "first_player_ready" );
  3977. }
  3978. }
  3979.  
  3980. //
  3981. // Set the current round number hud display
  3982. function round_one_up()
  3983. {
  3984. level endon("end_game");
  3985. if( isdefined(level.noRoundNumber) && level.noRoundNumber==true )
  3986. {
  3987. return;
  3988. }
  3989.  
  3990. if(!IsDefined(level.doground_nomusic))
  3991. {
  3992. level.doground_nomusic = 0;
  3993. }
  3994.  
  3995. if( level.first_round )
  3996. {
  3997. intro = true;
  3998. if( isdefined( level._custom_intro_vox ) )
  3999. {
  4000. level thread [[level._custom_intro_vox]]();
  4001. }
  4002. else
  4003. {
  4004. level thread play_level_start_vox_delayed();
  4005. };
  4006. }
  4007. else
  4008. {
  4009. intro = false;
  4010. }
  4011.  
  4012. //Round Number Specific Lines
  4013. if( level.round_number == 5 || level.round_number == 10 || level.round_number == 20 || level.round_number == 35 || level.round_number == 50 )
  4014. {
  4015. players = GetPlayers();
  4016. rand = RandomIntRange(0,players.size);
  4017. players[rand] thread zm_audio::create_and_play_dialog( "general", "round_" + level.round_number );
  4018. }
  4019.  
  4020. if( intro )
  4021. {
  4022. if(IS_TRUE(level.host_ended_game))
  4023. {
  4024. return;
  4025. }
  4026.  
  4027. wait( 6.25 );
  4028. level notify( "intro_hud_done" );
  4029. wait( 2 );
  4030.  
  4031. }
  4032. else
  4033. {
  4034. wait( 2.5 );
  4035. }
  4036.  
  4037. ReportMTU(level.round_number); // In network debug instrumented builds, causes network spike report to generate.
  4038. }
  4039.  
  4040.  
  4041. // Flash the round display at the end of the round
  4042. //
  4043. function round_over()
  4044. {
  4045. if( isdefined(level.noRoundNumber) && level.noRoundNumber==true )
  4046. {
  4047. return;
  4048. }
  4049.  
  4050. time = [[level.func_get_delay_between_rounds]]();
  4051.  
  4052. players = GetPlayers();
  4053. for ( player_index = 0; player_index < players.size; player_index++ )
  4054. {
  4055. if ( !IsDefined( players[player_index].pers["previous_distance_traveled"] ) )
  4056. {
  4057. players[player_index].pers["previous_distance_traveled"] = 0;
  4058. }
  4059. distanceThisRound = int( players[player_index].pers["distance_traveled"] - players[player_index].pers["previous_distance_traveled"] );
  4060. players[player_index].pers["previous_distance_traveled"] = players[player_index].pers["distance_traveled"];
  4061. players[player_index] IncrementPlayerStat("distance_traveled", distanceThisRound );
  4062. if ( players[player_index].pers["team"] != "spectator" )
  4063. {
  4064. players[player_index] recordRoundEndStats();
  4065. }
  4066. }
  4067. RecordZombieRoundEnd();
  4068. // waiting for the Pulse from lua
  4069. wait( time );
  4070. }
  4071.  
  4072. function get_delay_between_rounds()
  4073. {
  4074. return( level.zombie_vars["zombie_between_round_time"] );
  4075. }
  4076.  
  4077. function recordPlayerRoundWeapon(weapon, statname)
  4078. {
  4079. if (isDefined(weapon))
  4080. {
  4081. weaponIdx = GetBaseWeaponItemIndex(weapon);
  4082. if (isDefined(weaponIdx))
  4083. {
  4084. self incrementplayerstat(statname, weaponIdx);
  4085. }
  4086. }
  4087. }
  4088.  
  4089. function recordPrimaryWeaponsStats(base_stat_name, max_weapons)
  4090. {
  4091. current_weapons = self GetWeaponsListPrimaries();
  4092. for (index = 0; index < max_weapons && index < current_weapons.size; index++)
  4093. {
  4094. recordPlayerRoundWeapon(current_weapons[index], base_stat_name + index);
  4095. }
  4096. }
  4097.  
  4098. function recordRoundStartStats() //self == player
  4099. {
  4100. zoneName = self zm_utility::get_current_zone();
  4101. if( IsDefined(zoneName) )
  4102. {
  4103. self RecordZombieZone("startingZone", zoneName);
  4104. }
  4105.  
  4106. self incrementplayerstat("score", self.score);
  4107. primaryWeapon = self GetCurrentWeapon();
  4108.  
  4109. self recordPrimaryWeaponsStats("roundStartPrimaryWeapon", 3);
  4110. self RecordMapEvent(ZM_MAP_EVENT_ROUND_START, GetTime(), self.origin, level.round_number);
  4111. }
  4112.  
  4113. function recordRoundEndStats() //self == player
  4114. {
  4115. zoneName = self zm_utility::get_current_zone();
  4116. if( IsDefined(zoneName) )
  4117. {
  4118. self RecordZombieZone( "endingZone", zoneName );
  4119. }
  4120.  
  4121. self recordPrimaryWeaponsStats("roundEndPrimaryWeapon", 3);
  4122. self RecordMapEvent(ZM_MAP_EVENT_ROUND_END, GetTime(), self.origin, level.round_number);
  4123. }
  4124.  
  4125. function round_think( restart = false )
  4126. {
  4127. level endon("end_round_think");
  4128.  
  4129. if(!IS_TRUE(restart))
  4130. {
  4131. // Wait for blackscreen to end if in use
  4132. if ( IsDefined( level.initial_round_wait_func ))
  4133. [[level.initial_round_wait_func]]();
  4134.  
  4135. if(!IS_TRUE(level.host_ended_game))
  4136. {
  4137. //unfreeze the players controls now
  4138. players = GetPlayers();
  4139. foreach(player in players)
  4140. {
  4141. if(!IS_TRUE(player.hostMigrationControlsFrozen))
  4142. {
  4143. player FreezeControls(false);
  4144. }
  4145.  
  4146. // set the initial round_number
  4147. player zm_stats::set_global_stat( "rounds", level.round_number );
  4148. }
  4149. }
  4150. }
  4151.  
  4152. SetRoundsPlayed( level.round_number );
  4153.  
  4154. for( ;; )
  4155. {
  4156. //////////////////////////////////////////
  4157. //designed by prod DT#36173
  4158. maxreward = 50 * level.round_number;
  4159. if ( maxreward > 500 )
  4160. maxreward = 500;
  4161. level.zombie_vars["rebuild_barrier_cap_per_round"] = maxreward;
  4162. //////////////////////////////////////////
  4163.  
  4164. level.pro_tips_start_time = GetTime();
  4165. level.zombie_last_run_time = GetTime(); // Resets the last time a zombie ran
  4166.  
  4167. if ( IsDefined( level.zombie_round_change_custom ) )
  4168. {
  4169. [[ level.zombie_round_change_custom ]]();
  4170. }
  4171. else
  4172. {
  4173. if( !IS_TRUE( level.sndMusicSpecialRound ) )
  4174. {
  4175. if( IS_TRUE(level.sndGotoRoundOccurred))
  4176. level.sndGotoRoundOccurred = false;
  4177. else if( level.round_number == 1 )
  4178. level thread zm_audio::sndMusicSystem_PlayState( "round_start_first" );
  4179. else if( level.round_number <= 5 )
  4180. level thread zm_audio::sndMusicSystem_PlayState( "round_start" );
  4181. else
  4182. level thread zm_audio::sndMusicSystem_PlayState( "round_start_short" );
  4183. }
  4184. round_one_up();
  4185. // round_text( &"ZOMBIE_ROUND_BEGIN" );
  4186. }
  4187.  
  4188. zm_powerups::powerup_round_start();
  4189.  
  4190. players = GetPlayers();
  4191. array::thread_all( players, &zm_blockers::rebuild_barrier_reward_reset );
  4192.  
  4193. if(!IS_TRUE(level.headshots_only) && !restart ) //no grenades for headshot only mode, or when grief restarts the round after everyone dies
  4194. {
  4195. level thread award_grenades_for_survivors();
  4196. }
  4197.  
  4198. level.round_start_time = GetTime();
  4199.  
  4200. //Not great fix for this being zero - which it should NEVER be! (post ship - PETER)
  4201. while( level.zm_loc_types[ "zombie_location" ].size <= 0 )
  4202. {
  4203. wait( 0.1 );
  4204. }
  4205.  
  4206. level thread [[level.round_spawn_func]]();
  4207.  
  4208. level notify( "start_of_round" );
  4209. RecordZombieRoundStart();
  4210. players = GetPlayers();
  4211. for ( index = 0; index < players.size; index++ )
  4212. {
  4213. players[index] recordRoundStartStats();
  4214. }
  4215. if(isDefined(level.round_start_custom_func))
  4216. {
  4217. [[level.round_start_custom_func]]();
  4218. }
  4219.  
  4220. [[level.round_wait_func]]();
  4221.  
  4222. level.first_round = false;
  4223. level notify( "end_of_round" );
  4224. UploadStats();
  4225.  
  4226. if(isDefined(level.round_end_custom_logic))
  4227. {
  4228. [[level.round_end_custom_logic]]();
  4229. }
  4230.  
  4231. players = GetPlayers();
  4232.  
  4233. // PORTIZ 7/27/16: now that no_end_game_check is being used more regularly, I was tempted to remove/change this because it seems to arbitrarily add
  4234. // the revival of last stand players on top of whatever mechanic toggled the bool in the first place. however, it doesn't seem to do harm, and I'd rather avoid
  4235. // affecting these core systems if possible. for example, is there badness if a round transitions/starts and ALL players are in last stand? this can be revisited if
  4236. // any specific bugs/exploits arise from it...
  4237. if( IS_TRUE(level.no_end_game_check) )
  4238. {
  4239. level thread last_stand_revive();
  4240. level thread spectators_respawn();
  4241. }
  4242. else if ( 1 != players.size )
  4243. {
  4244. level thread spectators_respawn();
  4245. //level thread last_stand_revive();
  4246. }
  4247.  
  4248. players = GetPlayers();
  4249. array::thread_all( players, &zm_pers_upgrades_system::round_end );
  4250.  
  4251. if ( int(level.round_number / 5) * 5 == level.round_number )
  4252. {
  4253. level clientfield::set( "round_complete_time", int( ( level.time - level.n_gameplay_start_time + 500 ) / 1000 ) );
  4254. level clientfield::set( "round_complete_num", level.round_number );
  4255. }
  4256.  
  4257. //
  4258. // Increase the zombie move speed
  4259. //level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier"];
  4260.  
  4261. if( level.gamedifficulty == 0 ) //easy
  4262. {
  4263. level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier_easy"];
  4264. }
  4265. else //normal
  4266. {
  4267. level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier"];
  4268. }
  4269.  
  4270.  
  4271. level.round_number++;
  4272. if ( 255 < level.round_number )
  4273. {
  4274. level.round_number = 255;
  4275. }
  4276. SetRoundsPlayed( level.round_number );
  4277.  
  4278. // Here's the difficulty increase over time area
  4279. //level.zombie_vars["zombie_spawn_delay"] = get_zombie_spawn_delay( level.round_number );
  4280. level.zombie_vars["zombie_spawn_delay"] = [[level.func_get_zombie_spawn_delay]]( level.round_number );
  4281.  
  4282. // round_text( &"ZOMBIE_ROUND_END" );
  4283.  
  4284. matchUTCTime = GetUTC();
  4285.  
  4286. players = GetPlayers(); // delay in round_over allows a player that leaves during that time to remain in the players array - leading to round based SRES. Bad.
  4287. foreach(player in players)
  4288. {
  4289. player zm_stats::set_global_stat( "rounds", level.round_number );
  4290.  
  4291. // Reset the health if necessary
  4292. player zm_perks::perk_set_max_health_if_jugg( "health_reboot", true, true );
  4293.  
  4294. //XP event stuff
  4295. for ( i = 0; i < 4; i++ )
  4296. {
  4297. player.number_revives_per_round[i] = 0;
  4298. }
  4299.  
  4300. if ( IsAlive( player ) && player.sessionstate != "spectator" && !IS_TRUE( level.skip_alive_at_round_end_xp ) )
  4301. {
  4302. player zm_stats::increment_challenge_stat( "SURVIVALIST_SURVIVE_ROUNDS" );
  4303.  
  4304. score_number = level.round_number - 1;
  4305. if ( score_number < 1 )
  4306. {
  4307. score_number = 1;
  4308. }
  4309. else if ( score_number > 20 )
  4310. {
  4311. score_number = 20;
  4312. }
  4313. scoreevents::processScoreEvent( ("alive_at_round_end_" + score_number), player );
  4314. }
  4315. }
  4316.  
  4317. if( isdefined( level.check_quickrevive_hotjoin ) )
  4318. {
  4319. [[ level.check_quickrevive_hotjoin ]]();
  4320. }
  4321.  
  4322. level round_over();
  4323.  
  4324. level notify( "between_round_over" );
  4325.  
  4326. level.skip_alive_at_round_end_xp = false;
  4327.  
  4328. restart = false;
  4329. }
  4330. }
  4331.  
  4332.  
  4333. function award_grenades_for_survivors()
  4334. {
  4335. players = GetPlayers();
  4336.  
  4337. for (i = 0; i < players.size; i++)
  4338. {
  4339. if (!players[i].is_zombie && !IS_TRUE(players[i].altbody) && !players[i] laststand::player_is_in_laststand() )
  4340. {
  4341. lethal_grenade = players[i] zm_utility::get_player_lethal_grenade();
  4342. if( !players[i] HasWeapon( lethal_grenade ) )
  4343. {
  4344. players[i] GiveWeapon( lethal_grenade );
  4345. players[i] SetWeaponAmmoClip( lethal_grenade, 0 );
  4346. }
  4347.  
  4348. frac = players[i] GetFractionMaxAmmo( lethal_grenade );
  4349. if ( frac < .25 )
  4350. {
  4351. players[i] SetWeaponAmmoClip( lethal_grenade, 2 );
  4352. }
  4353. else if ( frac < .5 )
  4354. {
  4355. players[i] SetWeaponAmmoClip( lethal_grenade, 3 );
  4356. }
  4357. else
  4358. {
  4359. players[i] SetWeaponAmmoClip( lethal_grenade, 4 );
  4360. }
  4361. }
  4362. }
  4363. }
  4364.  
  4365.  
  4366. // Calculate the correct spawn delay for the round number
  4367. function get_zombie_spawn_delay( n_round )
  4368. {
  4369. if ( n_round > 60 ) // Don't let this loop too many times
  4370. {
  4371. n_round = 60;
  4372. }
  4373.  
  4374. // Decay rate
  4375. n_multiplier = 0.95;
  4376. // Base delay
  4377. switch( level.players.size )
  4378. {
  4379. case 1:
  4380. n_delay = 2.0; // 0.95 == 0.1 @ round 60
  4381. break;
  4382. case 2:
  4383. n_delay = 1.5; // 0.95 == 0.1 @ round 54
  4384. break;
  4385. case 3:
  4386. n_delay = 0.89; // 0.95 == 0.1 @ round 60
  4387. break;
  4388. case 4:
  4389. n_delay = 0.67; // 0.95 == 0.1 @ round 60
  4390. break;
  4391. }
  4392.  
  4393. for( i=1; i<n_round; i++ )
  4394. {
  4395. n_delay *= n_multiplier;
  4396.  
  4397. if ( n_delay <= 0.1 )
  4398. {
  4399. n_delay = 0.1;
  4400. break;
  4401. }
  4402. }
  4403.  
  4404. return n_delay;
  4405. }
  4406.  
  4407.  
  4408. // Waits for the time and the ai to die
  4409. function round_wait()
  4410. {
  4411. level endon("restart_round");
  4412. level endon( "kill_round" );
  4413.  
  4414. if ( cheat_enabled( 2 ) )
  4415. {
  4416. level waittill("forever");
  4417. }
  4418.  
  4419. wait( 1 );
  4420.  
  4421. while( 1 )
  4422. {
  4423. should_wait = ( zombie_utility::get_current_zombie_count() > 0 || level.zombie_total > 0 || level.intermission );
  4424. if( !should_wait )
  4425. {
  4426. level thread zm_audio::sndMusicSystem_PlayState( "round_end" );
  4427. return;
  4428. }
  4429.  
  4430. if( level flag::get( "end_round_wait" ) )
  4431. {
  4432. level thread zm_audio::sndMusicSystem_PlayState( "round_end" );
  4433. return;
  4434. }
  4435. wait( 1.0 );
  4436. }
  4437. }
  4438. //To make sure music plays when using debug to switch rounds
  4439. function sndMusicOnKillRound()
  4440. {
  4441. level endon( "end_of_round" );
  4442.  
  4443. level waittill( "kill_round" );
  4444. level thread zm_audio::sndMusicSystem_PlayState( "round_end" );
  4445. }
  4446.  
  4447.  
  4448.  
  4449. function zombify_player() // self = player
  4450. {
  4451. self zm_score::player_died_penalty();
  4452.  
  4453. self RecordPlayerDeathZombies();
  4454.  
  4455. if ( IsDefined( level.deathcard_spawn_func ) )
  4456. {
  4457. self [[level.deathcard_spawn_func]]();
  4458. }
  4459.  
  4460. if( isdefined( level.func_clone_plant_respawn ) && isdefined( self.s_clone_plant ) )
  4461. {
  4462. self [[level.func_clone_plant_respawn]]();
  4463. return;
  4464. }
  4465.  
  4466. if( !IsDefined( level.zombie_vars["zombify_player"] ) || !level.zombie_vars["zombify_player"] )
  4467. {
  4468. self thread spawnSpectator();
  4469. return;
  4470. }
  4471.  
  4472. self.ignoreme = true;
  4473. self.is_zombie = true;
  4474. self.zombification_time = GetTime();
  4475.  
  4476. self.team = level.zombie_team;
  4477. self notify( "zombified" );
  4478.  
  4479. if( IsDefined( self.revivetrigger ) )
  4480. {
  4481. self.revivetrigger Delete();
  4482. }
  4483. self.revivetrigger = undefined;
  4484.  
  4485. self setMoveSpeedScale( 0.3 );
  4486. self reviveplayer();
  4487.  
  4488. self TakeAllWeapons();
  4489. self DisableWeaponCycling();
  4490. self DisableOffhandWeapons();
  4491.  
  4492. self thread zombie_utility::zombie_eye_glow();
  4493.  
  4494. self thread playerzombie_player_damage();
  4495. self thread playerzombie_soundboard();
  4496. }
  4497.  
  4498. function playerzombie_player_damage()
  4499. {
  4500. self endon( "death" );
  4501. self endon( "disconnect" );
  4502.  
  4503. self thread playerzombie_infinite_health(); // manually keep regular health up
  4504. self.zombiehealth = level.zombie_health;
  4505.  
  4506. // enable PVP damage on this guy
  4507. // self EnablePvPDamage();
  4508.  
  4509. while( 1 )
  4510. {
  4511. self waittill( "damage", amount, attacker, directionVec, point, type );
  4512.  
  4513. if( !IsDefined( attacker ) || !IsPlayer( attacker ) )
  4514. {
  4515. WAIT_SERVER_FRAME;
  4516. continue;
  4517. }
  4518.  
  4519. self.zombiehealth -= amount;
  4520.  
  4521. if( self.zombiehealth <= 0 )
  4522. {
  4523. // "down" the zombie
  4524. self thread playerzombie_downed_state();
  4525. self waittill( "playerzombie_downed_state_done" );
  4526. self.zombiehealth = level.zombie_health;
  4527. }
  4528. }
  4529. }
  4530.  
  4531. function playerzombie_downed_state()
  4532. {
  4533. self endon( "death" );
  4534. self endon( "disconnect" );
  4535.  
  4536. downTime = 15;
  4537.  
  4538. startTime = GetTime();
  4539. endTime = startTime +( downTime * 1000 );
  4540.  
  4541. self thread playerzombie_downed_hud();
  4542.  
  4543. self.playerzombie_soundboard_disable = true;
  4544. self thread zombie_utility::zombie_eye_glow_stop();
  4545. self DisableWeapons();
  4546. self AllowStand( false );
  4547. self AllowCrouch( false );
  4548. self AllowProne( true );
  4549.  
  4550. while( GetTime() < endTime )
  4551. {
  4552. WAIT_SERVER_FRAME;
  4553. }
  4554.  
  4555. self.playerzombie_soundboard_disable = false;
  4556. self thread zombie_utility::zombie_eye_glow();
  4557. self EnableWeapons();
  4558. self AllowStand( true );
  4559. self AllowCrouch( false );
  4560. self AllowProne( false );
  4561.  
  4562. self notify( "playerzombie_downed_state_done" );
  4563. }
  4564.  
  4565. function playerzombie_downed_hud()
  4566. {
  4567. self endon( "death" );
  4568. self endon( "disconnect" );
  4569.  
  4570. text = NewClientHudElem( self );
  4571. text.alignX = "center";
  4572. text.alignY = "middle";
  4573. text.horzAlign = "user_center";
  4574. text.vertAlign = "user_bottom";
  4575. text.foreground = true;
  4576. text.font = "default";
  4577. text.fontScale = 1.8;
  4578. text.alpha = 0;
  4579. text.color = ( 1.0, 1.0, 1.0 );
  4580. text SetText( &"ZOMBIE_PLAYERZOMBIE_DOWNED" );
  4581.  
  4582. text.y = -113;
  4583. if( self IsSplitScreen() )
  4584. {
  4585. text.y = -137;
  4586. }
  4587.  
  4588. text FadeOverTime( 0.1 );
  4589. text.alpha = 1;
  4590.  
  4591. self waittill( "playerzombie_downed_state_done" );
  4592.  
  4593. text FadeOverTime( 0.1 );
  4594. text.alpha = 0;
  4595. }
  4596.  
  4597. function playerzombie_infinite_health()
  4598. {
  4599. self endon( "death" );
  4600. self endon( "disconnect" );
  4601.  
  4602. bighealth = 100000;
  4603.  
  4604. while( 1 )
  4605. {
  4606. if( self.health < bighealth )
  4607. {
  4608. self.health = bighealth;
  4609. }
  4610.  
  4611. wait( 0.1 );
  4612. }
  4613. }
  4614.  
  4615. function playerzombie_soundboard()
  4616. {
  4617. self endon( "death" );
  4618. self endon( "disconnect" );
  4619.  
  4620. self.playerzombie_soundboard_disable = false;
  4621.  
  4622. self.buttonpressed_use = false;
  4623. self.buttonpressed_attack = false;
  4624. self.buttonpressed_ads = false;
  4625.  
  4626. self.useSound_waitTime = 3 * 1000; // milliseconds
  4627. self.useSound_nextTime = GetTime();
  4628. useSound = "playerzombie_usebutton_sound";
  4629.  
  4630. self.attackSound_waitTime = 3 * 1000;
  4631. self.attackSound_nextTime = GetTime();
  4632. attackSound = "playerzombie_attackbutton_sound";
  4633.  
  4634. self.adsSound_waitTime = 3 * 1000;
  4635. self.adsSound_nextTime = GetTime();
  4636. adsSound = "playerzombie_adsbutton_sound";
  4637.  
  4638. self.inputSound_nextTime = GetTime(); // don't want to be able to do all sounds at once
  4639.  
  4640. while( 1 )
  4641. {
  4642. if( self.playerzombie_soundboard_disable )
  4643. {
  4644. WAIT_SERVER_FRAME;
  4645. continue;
  4646. }
  4647.  
  4648. if( self UseButtonPressed() )
  4649. {
  4650. if( self can_do_input( "use" ) )
  4651. {
  4652. self thread playerzombie_play_sound( useSound );
  4653. self thread playerzombie_waitfor_buttonrelease( "use" );
  4654. self.useSound_nextTime = GetTime() + self.useSound_waitTime;
  4655. }
  4656. }
  4657. else if( self AttackButtonPressed() )
  4658. {
  4659. if( self can_do_input( "attack" ) )
  4660. {
  4661. self thread playerzombie_play_sound( attackSound );
  4662. self thread playerzombie_waitfor_buttonrelease( "attack" );
  4663. self.attackSound_nextTime = GetTime() + self.attackSound_waitTime;
  4664. }
  4665. }
  4666. else if( self AdsButtonPressed() )
  4667. {
  4668. if( self can_do_input( "ads" ) )
  4669. {
  4670. self thread playerzombie_play_sound( adsSound );
  4671. self thread playerzombie_waitfor_buttonrelease( "ads" );
  4672. self.adsSound_nextTime = GetTime() + self.adsSound_waitTime;
  4673. }
  4674. }
  4675.  
  4676. WAIT_SERVER_FRAME;
  4677. }
  4678. }
  4679.  
  4680. function can_do_input( inputType )
  4681. {
  4682. if( GetTime() < self.inputSound_nextTime )
  4683. {
  4684. return false;
  4685. }
  4686.  
  4687. canDo = false;
  4688.  
  4689. switch( inputType )
  4690. {
  4691. case "use":
  4692. if( GetTime() >= self.useSound_nextTime && !self.buttonpressed_use )
  4693. {
  4694. canDo = true;
  4695. }
  4696. break;
  4697.  
  4698. case "attack":
  4699. if( GetTime() >= self.attackSound_nextTime && !self.buttonpressed_attack )
  4700. {
  4701. canDo = true;
  4702. }
  4703. break;
  4704.  
  4705. case "ads":
  4706. if( GetTime() >= self.useSound_nextTime && !self.buttonpressed_ads )
  4707. {
  4708. canDo = true;
  4709. }
  4710. break;
  4711.  
  4712. default:
  4713. ASSERTMSG( "can_do_input(): didn't recognize inputType of " + inputType );
  4714. break;
  4715. }
  4716.  
  4717. return canDo;
  4718. }
  4719.  
  4720. function playerzombie_play_sound( alias )
  4721. {
  4722. self zm_utility::play_sound_on_ent( alias );
  4723. }
  4724.  
  4725. function playerzombie_waitfor_buttonrelease( inputType )
  4726. {
  4727. if( inputType != "use" && inputType != "attack" && inputType != "ads" )
  4728. {
  4729. ASSERTMSG( "playerzombie_waitfor_buttonrelease(): inputType of " + inputType + " is not recognized." );
  4730. return;
  4731. }
  4732.  
  4733. notifyString = "waitfor_buttonrelease_" + inputType;
  4734. self notify( notifyString );
  4735. self endon( notifyString );
  4736.  
  4737. if( inputType == "use" )
  4738. {
  4739. self.buttonpressed_use = true;
  4740. while( self UseButtonPressed() )
  4741. {
  4742. WAIT_SERVER_FRAME;
  4743. }
  4744. self.buttonpressed_use = false;
  4745. }
  4746.  
  4747. else if( inputType == "attack" )
  4748. {
  4749. self.buttonpressed_attack = true;
  4750. while( self AttackButtonPressed() )
  4751. {
  4752. WAIT_SERVER_FRAME;
  4753. }
  4754. self.buttonpressed_attack = false;
  4755. }
  4756.  
  4757. else if( inputType == "ads" )
  4758. {
  4759. self.buttonpressed_ads = true;
  4760. while( self AdsButtonPressed() )
  4761. {
  4762. WAIT_SERVER_FRAME;
  4763. }
  4764. self.buttonpressed_ads = false;
  4765. }
  4766. }
  4767.  
  4768. function remove_ignore_attacker()
  4769. {
  4770. self notify( "new_ignore_attacker" );
  4771. self endon( "new_ignore_attacker" );
  4772. self endon( "disconnect" );
  4773.  
  4774. if( !isDefined( level.ignore_enemy_timer ) )
  4775. {
  4776. level.ignore_enemy_timer = 0.4;
  4777. }
  4778.  
  4779. wait( level.ignore_enemy_timer );
  4780.  
  4781. self.ignoreAttacker = undefined;
  4782. }
  4783.  
  4784. function player_damage_override_cheat( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime )
  4785. {
  4786. player_damage_override( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  4787. return 0;
  4788. }
  4789.  
  4790.  
  4791. //
  4792. // player_damage_override
  4793. // MUST return the value of the damage override
  4794. //
  4795. // MM (08/10/09) - Removed calls to PlayerDamageWrapper because it's always called in
  4796. // Callback_PlayerDamage now. We just need to return the damage.
  4797. //
  4798. function player_damage_override( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime )
  4799. {
  4800. iDamage = self check_player_damage_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  4801.  
  4802. if( self.scene_takedamage === false )
  4803. {
  4804. return 0;
  4805. }
  4806.  
  4807. if ( IS_TRUE( self.use_adjusted_grenade_damage ) )
  4808. {
  4809. self.use_adjusted_grenade_damage = undefined;
  4810. if( ( self.health > iDamage ) )
  4811. {
  4812. return iDamage;
  4813. }
  4814. }
  4815.  
  4816. if ( !iDamage )
  4817. {
  4818. return 0;
  4819. }
  4820.  
  4821. // WW (8/20/10) - Sledgehammer fix for Issue 43492. This should stop the player from taking any damage while in laststand
  4822. if( self laststand::player_is_in_laststand() )
  4823. {
  4824. return 0;
  4825. }
  4826.  
  4827. if ( isDefined( eInflictor ) )
  4828. {
  4829. if ( IS_TRUE( eInflictor.water_damage ) )
  4830. {
  4831. return 0;
  4832. }
  4833. }
  4834.  
  4835. if ( isDefined( eAttacker ) )
  4836. {
  4837. if( IS_EQUAL( eAttacker.owner, self ) )
  4838. {
  4839. return 0;
  4840. }
  4841.  
  4842. if( isDefined( self.ignoreAttacker ) && self.ignoreAttacker == eAttacker )
  4843. {
  4844. return 0;
  4845. }
  4846.  
  4847. // AR (5/30/12) - Stop Zombie players from damaging other Zombie players
  4848. if ( IS_TRUE( self.is_zombie ) && IS_TRUE( eAttacker.is_zombie ) )
  4849. {
  4850. return 0;
  4851. }
  4852.  
  4853. if( (isDefined( eAttacker.is_zombie ) && eAttacker.is_zombie) )
  4854. {
  4855. self.ignoreAttacker = eAttacker;
  4856. self thread remove_ignore_attacker();
  4857.  
  4858. if ( isdefined( eAttacker.custom_damage_func ) )
  4859. {
  4860. iDamage = eAttacker [[ eAttacker.custom_damage_func ]]( self );
  4861. }
  4862. }
  4863.  
  4864. eAttacker notify( "hit_player" );
  4865.  
  4866. if ( isdefined( eAttacker ) && isdefined( eAttacker.func_mod_damage_override ) )
  4867. {
  4868. sMeansOfDeath = eAttacker [[ eAttacker.func_mod_damage_override ]]( eInflictor, sMeansOfDeath, weapon );
  4869. }
  4870.  
  4871. if( sMeansOfDeath != "MOD_FALLING" )
  4872. {
  4873. self thread playSwipeSound( sMeansOfDeath, eattacker );
  4874. if( IS_TRUE(eattacker.is_zombie) || IsPlayer(eAttacker) )
  4875. self PlayRumbleOnEntity( "damage_heavy" );
  4876.  
  4877. if( IS_TRUE(eattacker.is_zombie) )
  4878. {
  4879. self zm_audio::create_and_play_dialog( "general", "attacked" );
  4880. }
  4881.  
  4882. canExert = true;
  4883.  
  4884. if ( IS_TRUE( level.pers_upgrade_flopper ) )
  4885. {
  4886. // If the player has persistent flopper power, then no exert on explosion
  4887. if ( IS_TRUE( self.pers_upgrades_awarded[ "flopper" ] ) )
  4888. {
  4889. canExert = ( sMeansOfDeath != "MOD_PROJECTILE_SPLASH" && sMeansOfDeath != "MOD_GRENADE" && sMeansOfDeath != "MOD_GRENADE_SPLASH" );
  4890. }
  4891. }
  4892.  
  4893. if ( IS_TRUE( canExert ) )
  4894. {
  4895. if(RandomIntRange(0,1) == 0 )
  4896. {
  4897. self thread zm_audio::playerExert( "hitmed" );
  4898. //self thread zm_audio::create_and_play_dialog( "general", "hitmed" );
  4899. }
  4900. else
  4901. {
  4902. self thread zm_audio::playerExert( "hitlrg" );
  4903. //self thread zm_audio::create_and_play_dialog( "general", "hitlrg" );
  4904. }
  4905. }
  4906. }
  4907. }
  4908.  
  4909. //Audio(RG:2/1/2016) adding underwater drowning exert.
  4910. if ( isDefined( sMeansOfDeath) && sMeansOfDeath == "MOD_DROWN")
  4911. {
  4912. self thread zm_audio::playerExert( "drowning", true );
  4913. self.voxDrowning = true;
  4914. }
  4915.  
  4916. if( isdefined( level.perk_damage_override ) )
  4917. {
  4918. foreach( func in level.perk_damage_override )
  4919. {
  4920. n_damage = self [[ func ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  4921. if( isdefined( n_damage ) )
  4922. {
  4923. iDamage = n_damage;
  4924. }
  4925. }
  4926. }
  4927. finalDamage = iDamage;
  4928.  
  4929.  
  4930. // claymores and freezegun shatters, like bouncing betties, harm no players
  4931. if ( zm_utility::is_placeable_mine( weapon ) )
  4932. {
  4933. return 0;
  4934. }
  4935.  
  4936. if ( isDefined( self.player_damage_override ) )
  4937. {
  4938. self thread [[ self.player_damage_override ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  4939. }
  4940.  
  4941. if ( sMeansOfDeath == "MOD_PROJECTILE" || sMeansOfDeath == "MOD_PROJECTILE_SPLASH" || sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" || sMeansOfDeath == "MOD_EXPLOSIVE" )
  4942. {
  4943. // player explosive splash damage (caps explosive damage), fixes raygun damage being fatal (or grenades) when damaging yourself
  4944. if ( !IS_TRUE( self.is_zombie ) )
  4945. {
  4946. // Don't do this for projectile damage coming from zombies
  4947. if ( !isdefined( eAttacker ) || ( !IS_TRUE( eAttacker.is_zombie ) && !IS_TRUE( eAttacker.b_override_explosive_damage_cap ) ) )
  4948. {
  4949. // Only do it for ray gun
  4950. if( isdefined(weapon.name) && ((weapon.name == "ray_gun") || ( weapon.name == "ray_gun_upgraded" )) )
  4951. {
  4952. // Clamp it, we don't want to increase the damage from player raygun splash damage or grenade splash damage
  4953. // Don't create more damage than we are trying to apply
  4954. if ( ( self.health > 25 ) && ( iDamage > 25 ) )
  4955. {
  4956. return 25;
  4957. }
  4958. }
  4959. else if ( ( self.health > 75 ) && ( iDamage > 75 ) )
  4960. {
  4961. return 75;
  4962. }
  4963. }
  4964. }
  4965. }
  4966.  
  4967. if( iDamage < self.health )
  4968. {
  4969. if ( IsDefined( eAttacker ) )
  4970. {
  4971. if( IsDefined( level.custom_kill_damaged_VO ) )
  4972. {
  4973. eAttacker thread [[ level.custom_kill_damaged_VO ]]( self );
  4974. }
  4975. else
  4976. {
  4977. eAttacker.sound_damage_player = self;
  4978. }
  4979.  
  4980. if( IS_TRUE( eAttacker.missingLegs ) )
  4981. {
  4982. self zm_audio::create_and_play_dialog( "general", "crawl_hit" );
  4983. }
  4984. }
  4985.  
  4986. // MM (08/10/09)
  4987. return finalDamage;
  4988. }
  4989.  
  4990. //player died
  4991. if( isdefined( eAttacker ) )
  4992. {
  4993. if(isDefined(eAttacker.animname) && eAttacker.animname == "zombie_dog")
  4994. {
  4995. self zm_stats::increment_client_stat( "killed_by_zdog" );
  4996. self zm_stats::increment_player_stat( "killed_by_zdog" );
  4997. }
  4998. else if(IS_TRUE(eAttacker.is_avogadro))
  4999. {
  5000. self zm_stats::increment_client_stat( "killed_by_avogadro", false );
  5001. self zm_stats::increment_player_stat( "killed_by_avogadro" );
  5002. }
  5003. }
  5004.  
  5005. self thread clear_path_timers();
  5006.  
  5007. if( level.intermission )
  5008. {
  5009. level waittill( "forever" );
  5010. }
  5011.  
  5012. // AR (3/7/12) - Keep track of which player killed player in Zombify modes like Cleansed / Turned
  5013. // Confirmed with Alex
  5014. if ( level.scr_zm_ui_gametype == "zcleansed" && iDamage > 0 )
  5015. {
  5016. if ( IsDefined( eAttacker ) && IsPlayer( eAttacker ) && eAttacker.team != self.team && ( ( !IS_TRUE( self.laststand ) && !self laststand::player_is_in_laststand() ) || !IsDefined( self.last_player_attacker ) ) )
  5017. {
  5018. // Restore Health To Zombie Player
  5019. //--------------------------------
  5020. if ( IsDefined( eAttacker.maxhealth ) && IS_TRUE( eAttacker.is_zombie ) )
  5021. {
  5022. eAttacker.health = eAttacker.maxhealth;
  5023. }
  5024.  
  5025. //self.last_player_attacker = eAttacker;
  5026.  
  5027. if ( IsDefined( level.player_kills_player ) )
  5028. {
  5029. self thread [[ level.player_kills_player]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  5030. }
  5031. }
  5032. }
  5033.  
  5034. if ( self.lives > 0 && self HasPerk( PERK_WHOSWHO ) )
  5035. {
  5036. self.lives--;
  5037. if ( IsDefined( level.whoswho_laststand_func ) )
  5038. {
  5039. self thread [[ level.whoswho_laststand_func]]();
  5040. return 0;
  5041. }
  5042. }
  5043.  
  5044. players = GetPlayers();
  5045. count = 0;
  5046. for( i = 0; i < players.size; i++ )
  5047. {
  5048. if( players[i] == self || players[i].is_zombie || players[i] laststand::player_is_in_laststand() || players[i].sessionstate == "spectator" )
  5049. {
  5050. count++;
  5051. }
  5052. }
  5053.  
  5054. if( count < players.size || (isDefined(level._game_module_game_end_check) && ![[level._game_module_game_end_check]]()) )
  5055. {
  5056. if ( IsDefined( self.lives ) && self.lives > 0 && IS_TRUE( level.force_solo_quick_revive ) && self HasPerk( PERK_QUICK_REVIVE ) )
  5057. {
  5058. self thread wait_and_revive();
  5059. }
  5060.  
  5061. // MM (08/10/09)
  5062. return finalDamage;
  5063. }
  5064.  
  5065. // PORTIZ 7/27/16: added level.no_end_game_check here, because if it's true by this point, this function will end up returning finalDamage anyway. additionally,
  5066. // no_end_game_check has been updated to support incrementing/decrementing, which makes it more robust than a single level.check_end_solo_game_override as more
  5067. // mechanics are introduced that require solo players to go into last stand instead of losing the game immediately
  5068. if ( players.size == 1 && level flag::get( "solo_game" ) )
  5069. {
  5070. if ( IS_TRUE( level.no_end_game_check ) || ( isdefined( level.check_end_solo_game_override ) && [[level.check_end_solo_game_override]]() ) )
  5071. {
  5072. return finalDamage;
  5073. }
  5074. else if ( self.lives == 0 || !self HasPerk( PERK_QUICK_REVIVE ) )
  5075. {
  5076. self.intermission = true;
  5077. }
  5078. }
  5079.  
  5080.  
  5081.  
  5082.  
  5083. // WW (01/05/11): When a two players enter a system link game and the client drops the host will be treated as if it was a solo game
  5084. // when it wasn't. This led to SREs about undefined and int being compared on death (self.lives was never defined on the host). While
  5085. // adding the check for the solo game flag we found that we would have to create a complex OR inside of the if check below. By breaking
  5086. // the conditions out in to their own variables we keep the complexity without making it look like a mess.
  5087. solo_death = ( players.size == 1 && level flag::get( "solo_game" ) && ( self.lives == 0 || !self HasPerk(PERK_QUICK_REVIVE) ) ); // there is only one player AND the flag is set AND self.lives equals 0
  5088. non_solo_death = ( ( count > 1 || ( players.size == 1 && !level flag::get( "solo_game" ) ) ) /*&& !level.is_zombie_level*/ ); // the player size is greater than one OR ( players.size equals 1 AND solo flag isn't set ) AND not a zombify game level
  5089. if ( (solo_death || non_solo_death) && !IS_TRUE(level.no_end_game_check ) ) // if only one player on their last life or any game that started with more than one player
  5090. {
  5091. level notify("stop_suicide_trigger");
  5092. self AllowProne( true ); //just in case
  5093. self thread zm_laststand::PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime );
  5094. if( !isdefined( vDir ) )
  5095. {
  5096. vDir = ( 1.0, 0.0, 0.0 );
  5097. }
  5098. self FakeDamageFrom(vDir);
  5099.  
  5100. level notify("last_player_died");
  5101. if ( isdefined(level.custom_player_fake_death) )
  5102. self thread [[level.custom_player_fake_death]](vDir, sMeansOfDeath);
  5103. else
  5104. self thread player_fake_death();
  5105. }
  5106.  
  5107. if( count == players.size && !IS_TRUE( level.no_end_game_check ) )
  5108. {
  5109. if ( players.size == 1 && level flag::get( "solo_game" ))
  5110. {
  5111. if ( self.lives == 0 || !self HasPerk(PERK_QUICK_REVIVE) ) // && !self laststand::player_is_in_laststand()
  5112. {
  5113. self.lives = 0;
  5114. level notify("pre_end_game");
  5115. util::wait_network_frame();
  5116. if(level flag::get("dog_round"))
  5117. {
  5118. increment_dog_round_stat( "lost" );
  5119.  
  5120. }
  5121. level notify( "end_game" );
  5122. }
  5123. else
  5124. {
  5125. return finalDamage;
  5126. }
  5127. }
  5128. else
  5129. {
  5130. level notify("pre_end_game");
  5131. util::wait_network_frame();
  5132. if(level flag::get("dog_round"))
  5133. {
  5134. increment_dog_round_stat( "lost" );
  5135.  
  5136. }
  5137. level notify( "end_game" );
  5138. }
  5139. return 0; // MM (09/16/09) Need to return something
  5140. }
  5141. else
  5142. {
  5143. // MM (08/10/09)
  5144.  
  5145. surface = "flesh";
  5146.  
  5147. return finalDamage;
  5148. }
  5149. }
  5150.  
  5151. function clear_path_timers()
  5152. {
  5153. zombies = GetAITeamArray( level.zombie_team );
  5154. foreach( zombie in zombies )
  5155. {
  5156. if ( isdefined( zombie.favoriteenemy ) && ( zombie.favoriteenemy == self ) )
  5157. {
  5158. zombie.zombie_path_timer = 0;
  5159. }
  5160. }
  5161. }
  5162.  
  5163.  
  5164. function check_player_damage_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime )
  5165. {
  5166. if ( !isdefined( level.player_damage_callbacks ) )
  5167. {
  5168. return iDamage;
  5169. }
  5170.  
  5171. for ( i = 0; i < level.player_damage_callbacks.size; i++ )
  5172. {
  5173. newDamage = self [[ level.player_damage_callbacks[i] ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
  5174. if ( -1 != newDamage )
  5175. {
  5176. return newDamage;
  5177. }
  5178. }
  5179.  
  5180. return iDamage;
  5181. }
  5182.  
  5183.  
  5184. function register_player_damage_callback( func )
  5185. {
  5186. if ( !isdefined( level.player_damage_callbacks ) )
  5187. {
  5188. level.player_damage_callbacks = [];
  5189. }
  5190.  
  5191. level.player_damage_callbacks[level.player_damage_callbacks.size] = func;
  5192. }
  5193.  
  5194.  
  5195. function wait_and_revive()
  5196. {
  5197.  
  5198. self endon( "remote_revive" );
  5199. level flag::set( "wait_and_revive" );
  5200. level.wait_and_revive = true;
  5201.  
  5202. if ( isdefined( self.waiting_to_revive ) && self.waiting_to_revive == true )
  5203. {
  5204. return;
  5205. }
  5206.  
  5207. self.waiting_to_revive = true;
  5208. self.lives--;
  5209.  
  5210. if ( isdefined( level.exit_level_func ) )
  5211. {
  5212. self thread [[ level.exit_level_func ]]();
  5213. }
  5214. else
  5215. {
  5216. if ( GetPlayers().size == 1 )
  5217. {
  5218. level.move_away_points = PositionQuery_Source_Navigation( GetPlayers()[0].origin, ZM_POSITION_QUERY_LAST_STAND_MOVE_DIST_MIN, ZM_POSITION_QUERY_LAST_STAND_MOVE_DIST_MAX, ZM_POSITION_QUERY_MOVE_DIST_MAX, ZM_POSITION_QUERY_RADIUS );
  5219. }
  5220. }
  5221.  
  5222. solo_revive_time = 10.0;
  5223.  
  5224. name = level.player_name_directive[self GetEntityNumber()];
  5225. self.revive_hud setText( &"ZOMBIE_REVIVING_SOLO", name );
  5226. self laststand::revive_hud_show_n_fade( solo_revive_time );
  5227.  
  5228. level flag::wait_till_timeout( solo_revive_time, "instant_revive" );
  5229.  
  5230. if ( level flag::get( "instant_revive" ) )
  5231. {
  5232. self laststand::revive_hud_show_n_fade( 1.0 );
  5233. }
  5234.  
  5235. level flag::clear( "wait_and_revive" );
  5236. level.wait_and_revive = false;
  5237.  
  5238. self zm_laststand::auto_revive( self );
  5239. self.waiting_to_revive = false;
  5240. }
  5241.  
  5242. function register_vehicle_damage_callback( func )
  5243. {
  5244. if( !IsDefined( level.vehicle_damage_callbacks ) )
  5245. {
  5246. level.vehicle_damage_callbacks = [];
  5247. }
  5248.  
  5249. level.vehicle_damage_callbacks[level.vehicle_damage_callbacks.size] = func;
  5250. }
  5251.  
  5252. function vehicle_damage_override( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal )
  5253. {
  5254. //apply damage modifiers on the vehicle
  5255. if( IsDefined( level.vehicle_damage_callbacks ) )
  5256. {
  5257. for( i = 0; i < level.vehicle_damage_callbacks.size; i++ )
  5258. {
  5259. iDamage = self [[ level.vehicle_damage_callbacks[i] ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
  5260. }
  5261. }
  5262.  
  5263. //TODO Sabarish: Move code from globallogic to here to be more consistent with other zombie damage functions
  5264. self globallogic_vehicle::Callback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal );
  5265. }
  5266.  
  5267. //
  5268. // MUST return the value of the damage override
  5269. //
  5270. function actor_damage_override( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType )
  5271. {
  5272. // skip conditions
  5273. if ( !isdefined( self ) || !isdefined( attacker ) )
  5274. return damage;
  5275.  
  5276. damage = self check_actor_damage_callbacks( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType );
  5277.  
  5278. self.knuckles_extinguish_flames = (weapon.name == "tazer_knuckles");
  5279.  
  5280. if ( isdefined( attacker.animname ) && attacker.animname == "quad_zombie" )
  5281. {
  5282. if ( isdefined( self.animname ) && self.animname == "quad_zombie" )
  5283. {
  5284. return 0;
  5285. }
  5286. }
  5287.  
  5288. if ( isdefined( self.killby_interdimensional_gun_hole ) )
  5289. {
  5290. return damage;
  5291. }
  5292. else if ( isdefined( self.interdimensional_gun_kill ) )
  5293. {
  5294. if ( isdefined( self.idgun_damage_cb ) )
  5295. {
  5296. self [[ self.idgun_damage_cb ]]( inflictor, attacker );
  5297. }
  5298. return 0;
  5299. }
  5300.  
  5301.  
  5302. if ( isdefined( weapon ) )
  5303. {
  5304. if( is_idgun_damage( weapon ) && ( !IsDefined( meansofdeath ) || meansofdeath != "MOD_EXPLOSIVE" ) )
  5305. {
  5306. if( !IS_EQUAL( self.archetype, ARCHETYPE_MARGWA ) && !IS_EQUAL( self.archetype, ARCHETYPE_MECHZ ))
  5307. {
  5308. self.damageOrigin = vpoint;
  5309. self.allowdeath = false;
  5310. self.magic_bullet_shield = true;
  5311. self.interdimensional_gun_kill = true;
  5312. self.interdimensional_gun_weapon = weapon;
  5313. self.interdimensional_gun_attacker = attacker;
  5314.  
  5315. if ( isdefined( inflictor ) )
  5316. {
  5317. self.interdimensional_gun_inflictor = inflictor;
  5318. }
  5319. else
  5320. {
  5321. self.interdimensional_gun_inflictor = attacker;
  5322. }
  5323. }
  5324.  
  5325. if ( isdefined( self.idgun_damage_cb ) )
  5326. {
  5327. self [[ self.idgun_damage_cb ]]( inflictor, attacker );
  5328. }
  5329.  
  5330. return 0;
  5331. }
  5332. }
  5333.  
  5334. if ( !isplayer( attacker ) && isdefined( self.non_attacker_func ) )
  5335. {
  5336. if(IS_TRUE(self.non_attack_func_takes_attacker))
  5337. {
  5338. return self [[ self.non_attacker_func ]]( damage, weapon, attacker );
  5339. }
  5340. else
  5341. {
  5342. return self [[ self.non_attacker_func ]]( damage, weapon );
  5343. }
  5344. }
  5345.  
  5346. if ( IsDefined( attacker ) && IsAI( attacker ) )
  5347. {
  5348. // AI do not do melee damage to teammates
  5349. if( self.team == attacker.team && meansofdeath == "MOD_MELEE" )
  5350. {
  5351. return 0;
  5352. }
  5353. }
  5354.  
  5355. if ( attacker.classname == "script_vehicle" && isDefined( attacker.owner ) )
  5356. {
  5357. attacker = attacker.owner;
  5358. }
  5359.  
  5360. if ( !isdefined( damage ) || !isdefined( meansofdeath ) )
  5361. {
  5362. return damage;
  5363. }
  5364.  
  5365. if ( meansofdeath == "" )
  5366. {
  5367. return damage;
  5368. }
  5369.  
  5370. // This is the AI system's override damage callback, it must come last!
  5371. if ( IsDefined( self.aiOverrideDamage ) )
  5372. {
  5373. for ( index = 0; index < self.aiOverrideDamage.size; index++ )
  5374. {
  5375. damageCallback = self.aiOverrideDamage[index];
  5376. damage = self [[damageCallback]]( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, undefined );
  5377. }
  5378. if ( damage < 1 )
  5379. return 0;
  5380.  
  5381. damage = int( damage + 0.5 );
  5382. }
  5383.  
  5384. old_damage = damage;
  5385. final_damage = damage;
  5386.  
  5387. if ( IsDefined( self.actor_damage_func ) )
  5388. {
  5389. final_damage = [[ self.actor_damage_func ]]( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex );
  5390. }
  5391.  
  5392. // debug
  5393. if ( IS_TRUE( self.in_water ) )
  5394. {
  5395. if ( int( final_damage ) >= self.health )
  5396. {
  5397. self.water_damage = true;
  5398. }
  5399. }
  5400.  
  5401. //modifier for the sword in ZOD colliding with zombies
  5402. if ( IsDefined( inflictor ) && IsDefined( inflictor.archetype ) && inflictor.archetype == ARCHETYPE_GLAIVE )
  5403. {
  5404. if( meansofdeath == "MOD_CRUSH" )
  5405. {
  5406. if ( ( IsDefined( inflictor.enemy ) && inflictor.enemy != self ) || IS_TRUE( inflictor._glaive_must_return_to_owner ) )
  5407. {
  5408. if ( IsDefined( self.archetype ) && self.archetype != ARCHETYPE_MARGWA )
  5409. {
  5410. final_damage += self.health;
  5411. if ( IsActor( self ) )
  5412. {
  5413. self zombie_utility::gib_random_parts();
  5414. }
  5415. }
  5416. }
  5417. else
  5418. {
  5419. return 0;
  5420. }
  5421. }
  5422. }
  5423.  
  5424. if ( isdefined( inflictor ) && isPlayer( attacker ) && attacker == inflictor )
  5425. {
  5426. if ( meansofdeath == "MOD_HEAD_SHOT" || meansofdeath == "MOD_PISTOL_BULLET" || meansofdeath == "MOD_RIFLE_BULLET" )
  5427. {
  5428. attacker.hits++;
  5429. }
  5430. }
  5431.  
  5432. if ( IS_TRUE( level.headshots_only ) && isDefined( attacker ) && isplayer( attacker ) )
  5433. {
  5434. if ( meansofdeath == "MOD_MELEE" && ( sHitLoc == "head" || sHitLoc == "helmet" ) )
  5435. {
  5436. return int( final_damage );
  5437. }
  5438. if ( zm_utility::is_explosive_damage( meansofdeath ) )
  5439. {
  5440. return int( final_damage );
  5441. }
  5442. else if ( !zm_utility::is_headshot( weapon, sHitLoc, meansofdeath ) )
  5443. {
  5444. return 0;
  5445. }
  5446. }
  5447.  
  5448. return int( final_damage );
  5449. }
  5450.  
  5451. function check_actor_damage_callbacks( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType )
  5452. {
  5453. if ( !isdefined( level.actor_damage_callbacks ) )
  5454. {
  5455. return damage;
  5456. }
  5457.  
  5458. for ( i = 0; i < level.actor_damage_callbacks.size; i++ )
  5459. {
  5460. newDamage = self [[ level.actor_damage_callbacks[i] ]]( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType );
  5461. if ( -1 != newDamage )
  5462. {
  5463. return newDamage;
  5464. }
  5465. }
  5466.  
  5467. return damage;
  5468. }
  5469.  
  5470.  
  5471. function register_actor_damage_callback( func )
  5472. {
  5473. if ( !isdefined( level.actor_damage_callbacks ) )
  5474. {
  5475. level.actor_damage_callbacks = [];
  5476. }
  5477.  
  5478. level.actor_damage_callbacks[level.actor_damage_callbacks.size] = func;
  5479. }
  5480.  
  5481.  
  5482.  
  5483. function actor_damage_override_wrapper( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, modelIndex, surfaceType, vSurfaceNormal )
  5484. {
  5485. damage_override = self actor_damage_override( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType );
  5486. willBeKilled = ( self.health - damage_override ) <= 0;
  5487. if( isdefined( level.zombie_damage_override_callbacks ) )
  5488. {
  5489. foreach( func_override in level.zombie_damage_override_callbacks )
  5490. {
  5491. self thread [[ func_override ]]( willBeKilled, inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType );
  5492. }
  5493. }
  5494. if ( !willBeKilled || !IS_TRUE( self.dont_die_on_me ) )
  5495. {
  5496. self finishActorDamage( inflictor, attacker, damage_override, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, surfaceType, vSurfaceNormal );
  5497. }
  5498. }
  5499.  
  5500. function register_zombie_damage_override_callback( func )
  5501. {
  5502. DEFAULT( level.zombie_damage_override_callbacks, [] );
  5503.  
  5504. ARRAY_ADD( level.zombie_damage_override_callbacks, func );
  5505. }
  5506.  
  5507. function actor_killed_override(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
  5508. {
  5509. if ( game["state"] == "postgame" )
  5510. {
  5511. return;
  5512. }
  5513.  
  5514. if( isai(attacker) && isDefined( attacker.script_owner ) )
  5515. {
  5516. // if the person who called the dogs in switched teams make sure they don't
  5517. // get penalized for the kill
  5518. if ( attacker.script_owner.team != self.team )
  5519. attacker = attacker.script_owner;
  5520. }
  5521.  
  5522. if( attacker.classname == "script_vehicle" && isDefined( attacker.owner ) )
  5523. {
  5524. attacker = attacker.owner;
  5525. }
  5526.  
  5527. if ( isdefined( attacker ) && isplayer( attacker ) )
  5528. {
  5529. multiplier = 1;
  5530. if( zm_utility::is_headshot( weapon, sHitLoc, sMeansOfDeath ) )
  5531. {
  5532. multiplier = 1.5;
  5533. }
  5534.  
  5535. type = undefined;
  5536.  
  5537. //MM (3/18/10) no animname check
  5538. if ( IsDefined(self.animname) )
  5539. {
  5540. switch( self.animname )
  5541. {
  5542. case "quad_zombie":
  5543. type = "quadkill";
  5544. break;
  5545. case "ape_zombie":
  5546. type = "apekill";
  5547. break;
  5548. case "zombie":
  5549. type = "zombiekill";
  5550. break;
  5551. case "zombie_dog":
  5552. type = "dogkill";
  5553. break;
  5554. }
  5555. }
  5556. }
  5557.  
  5558. if(IS_TRUE(self.is_ziplining))
  5559. {
  5560. self.deathanim = undefined;
  5561. }
  5562.  
  5563. if ( IsDefined( self.actor_killed_override ) )
  5564. {
  5565. self [[ self.actor_killed_override ]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime );
  5566. }
  5567.  
  5568. if ( IsDefined( self.deathFunction ) )
  5569. {
  5570. self [[ self.deathFunction ]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime );
  5571. }
  5572. }
  5573.  
  5574.  
  5575. function round_end_monitor()
  5576. {
  5577. while(1)
  5578. {
  5579. level waittill( "end_of_round" );
  5580.  
  5581. demo::bookmark( "zm_round_end", gettime(), undefined, undefined, 1 );
  5582. BBPostDemoStreamStatsForRound( level.round_number );
  5583.  
  5584. WAIT_SERVER_FRAME;
  5585. }
  5586. }
  5587.  
  5588.  
  5589. //*****************************************************************************
  5590. //*****************************************************************************
  5591.  
  5592. function end_game()
  5593. {
  5594. level waittill ( "end_game" );
  5595.  
  5596. check_end_game_intermission_delay();
  5597.  
  5598. setmatchflag( "game_ended", 1 );
  5599.  
  5600. level clientfield::set("gameplay_started", 0);
  5601. level clientfield::set("game_end_time", int( ( GetTime() - level.n_gameplay_start_time + 500 ) / 1000 ) );
  5602.  
  5603. util::clientnotify( "zesn" );
  5604.  
  5605. level thread zm_audio::sndMusicSystem_PlayState( "game_over" );
  5606.  
  5607. //AYERS: Turn off ANY last stand audio at the end of the game
  5608. players = GetPlayers();
  5609. for ( i = 0; i < players.size; i++ )
  5610. {
  5611. players[i] clientfield::set( "zmbLastStand", 0 );
  5612. }
  5613.  
  5614. for ( i = 0; i < players.size; i++ )
  5615. {
  5616. if ( players[i] laststand::player_is_in_laststand() )
  5617. {
  5618. players[i] RecordPlayerDeathZombies();
  5619. players[i] zm_stats::increment_player_stat( "deaths" );
  5620. players[i] zm_stats::increment_client_stat( "deaths" );
  5621. }
  5622.  
  5623. //clean up the revive text hud if it's active
  5624. if( isdefined( players[i].reviveTextHud ) )
  5625. {
  5626. players[i].reviveTextHud destroy();
  5627. }
  5628. }
  5629.  
  5630. StopAllRumbles();
  5631.  
  5632. level.intermission = true;
  5633. level.zombie_vars["zombie_powerup_insta_kill_time"] = 0;
  5634. level.zombie_vars["zombie_powerup_fire_sale_time"] = 0;
  5635. level.zombie_vars["zombie_powerup_double_points_time"] = 0;
  5636. wait 0.1;
  5637.  
  5638. game_over = [];
  5639. survived = [];
  5640.  
  5641. players = GetPlayers();
  5642.  
  5643. //disabled the ingame pause menu from opening after a game ends
  5644. setMatchFlag( "disableIngameMenu", 1 );
  5645. foreach( player in players )
  5646. {
  5647. player closeInGameMenu();
  5648. player CloseMenu( "StartMenu_Main" );
  5649. }
  5650.  
  5651.  
  5652. //AAR - set stat for each player (this will show the menu)
  5653. foreach( player in players )
  5654. {
  5655. player setDStat( "AfterActionReportStats", "lobbyPopup", "summary" );
  5656. }
  5657.  
  5658. if(!isDefined(level._supress_survived_screen))
  5659. {
  5660.  
  5661. for( i = 0; i < players.size; i++ )
  5662. {
  5663. game_over[i] = NewClientHudElem( players[i] );
  5664. survived[i] = NewClientHudElem( players[i] );
  5665. if ( IsDefined( level.custom_game_over_hud_elem ) )
  5666. {
  5667. [[ level.custom_game_over_hud_elem ]]( players[i], game_over[i], survived[i] );
  5668. }
  5669. else
  5670. {
  5671. game_over[i].alignX = "center";
  5672. game_over[i].alignY = "middle";
  5673. game_over[i].horzAlign = "center";
  5674. game_over[i].vertAlign = "middle";
  5675. game_over[i].y -= 130;
  5676. game_over[i].foreground = true;
  5677. game_over[i].fontScale = 3;
  5678. game_over[i].alpha = 0;
  5679. game_over[i].color = ( 1.0, 1.0, 1.0 );
  5680. game_over[i].hidewheninmenu = true;
  5681. game_over[i] SetText( &"ZOMBIE_GAME_OVER" );
  5682.  
  5683. game_over[i] FadeOverTime( 1 );
  5684. game_over[i].alpha = 1;
  5685. if ( players[i] isSplitScreen() )
  5686. {
  5687. game_over[i].fontScale = 2;
  5688. game_over[i].y += 40;
  5689. }
  5690.  
  5691. survived[i].alignX = "center";
  5692. survived[i].alignY = "middle";
  5693. survived[i].horzAlign = "center";
  5694. survived[i].vertAlign = "middle";
  5695. survived[i].y -= 100;
  5696. survived[i].foreground = true;
  5697. survived[i].fontScale = 2;
  5698. survived[i].alpha = 0;
  5699. survived[i].color = ( 1.0, 1.0, 1.0 );
  5700. survived[i].hidewheninmenu = true;
  5701. if ( players[i] isSplitScreen() )
  5702. {
  5703. survived[i].fontScale = 1.5;
  5704. survived[i].y += 40;
  5705. }
  5706. }
  5707.  
  5708.  
  5709. //OLD COUNT METHOD
  5710. if( level.round_number < 2 )
  5711. {
  5712. {
  5713. survived[i] SetText( &"ZOMBIE_SURVIVED_ROUND" );
  5714. }
  5715. }
  5716. else
  5717. {
  5718. survived[i] SetText( &"ZOMBIE_SURVIVED_ROUNDS", level.round_number );
  5719. }
  5720.  
  5721. survived[i] FadeOverTime( 1 );
  5722. survived[i].alpha = 1;
  5723. }
  5724. }
  5725.  
  5726.  
  5727. //check to see if we are in a game module that wants to do something with PvP damage
  5728. if(isDefined(level.custom_end_screen))
  5729. {
  5730. level [[level.custom_end_screen]]();
  5731. }
  5732.  
  5733. for (i = 0; i < players.size; i++)
  5734. {
  5735. players[i] SetClientUIVisibilityFlag( "weapon_hud_visible", 0 );
  5736. players[i] SetClientMiniScoreboardHide( true );
  5737. //players[i] setDStat( "AfterActionReportStats", "lobbyPopup", "summary" );
  5738.  
  5739. players[i] notify( "report_bgb_consumption" );
  5740. }
  5741.  
  5742. //LUINotifyEvent( &"force_scoreboard", 0 );
  5743.  
  5744. UploadStats();
  5745. zm_stats::update_players_stats_at_match_end( players );
  5746. zm_stats::update_global_counters_on_match_end();
  5747. upload_leaderboards();
  5748.  
  5749. recordGameResult( "draw" );
  5750. globallogic::recordZMEndGameComScoreEvent( "draw" );
  5751. globallogic_player::recordActivePlayersEndGameMatchRecordStats();
  5752.  
  5753. // Finalize Match Record
  5754. finalizeMatchRecord();
  5755.  
  5756. //zm_utility::play_sound_at_pos( "end_of_game", ( 0, 0, 0 ) );
  5757.  
  5758. players = GetPlayers();
  5759. foreach( player in players )
  5760. {
  5761. if( IsDefined( player.sessionstate ) && player.sessionstate == "spectator" )
  5762. {
  5763. player.sessionstate = "playing";
  5764. player thread end_game_player_was_spectator();
  5765. }
  5766. }
  5767. WAIT_SERVER_FRAME;
  5768.  
  5769. players = GetPlayers();
  5770.  
  5771. LUINotifyEvent( &"force_scoreboard", 1, 1 );
  5772.  
  5773. intermission();
  5774.  
  5775. wait( level.zombie_vars["zombie_intermission_time"] );
  5776.  
  5777. // hide the gameover message
  5778. if ( !isDefined( level._supress_survived_screen ) )
  5779. {
  5780. for ( i = 0; i < players.size; i++ )
  5781. {
  5782. survived[i] Destroy();
  5783. game_over[i] Destroy();
  5784. }
  5785. }
  5786. else
  5787. {
  5788. for ( i = 0; i < players.size; i++ )
  5789. {
  5790. if(isDefined(players[i].survived_hud ) )
  5791. players[i].survived_hud Destroy();
  5792. if (isDefined( players[i].game_over_hud ) )
  5793. players[i].game_over_hud Destroy();
  5794. }
  5795. }
  5796.  
  5797. level notify( "stop_intermission" );
  5798. array::thread_all( GetPlayers(), &player_exit_level );
  5799.  
  5800. wait( 1.5 );
  5801.  
  5802. players = GetPlayers();
  5803. for ( i = 0; i < players.size; i++ )
  5804. {
  5805. players[i] CameraActivate( false );
  5806. }
  5807.  
  5808. ExitLevel( false );
  5809.  
  5810. // Let's not exit the function
  5811. wait( 666 );
  5812. }
  5813.  
  5814. //*****************************************************************************
  5815. //*****************************************************************************
  5816.  
  5817. function end_game_player_was_spectator()
  5818. {
  5819. WAIT_SERVER_FRAME;
  5820.  
  5821. self Ghost();
  5822. self FreezeControls( true );
  5823. }
  5824.  
  5825. //*****************************************************************************
  5826. //*****************************************************************************
  5827.  
  5828. function disable_end_game_intermission( delay )
  5829. {
  5830. level.disable_intermission = true;
  5831. wait( delay );
  5832. level.disable_intermission = undefined;
  5833. }
  5834.  
  5835.  
  5836. //*****************************************************************************
  5837. //*****************************************************************************
  5838.  
  5839. function check_end_game_intermission_delay()
  5840. {
  5841. if( IsDefined(level.disable_intermission) )
  5842. {
  5843. while( 1 )
  5844. {
  5845. if( !IsDefined(level.disable_intermission) )
  5846. {
  5847. break;
  5848. }
  5849. wait( 0.01 );
  5850. }
  5851. }
  5852. }
  5853.  
  5854.  
  5855. //*****************************************************************************
  5856. // This will save the leaderboard data per round, for use in single player
  5857. //*****************************************************************************
  5858.  
  5859. function upload_leaderboards()
  5860. {
  5861. // place restrictions on whether leaderboards are uploaded to in the precache leaderboards function
  5862. players = GetPlayers();
  5863. for( i = 0; i < players.size; i++ )
  5864. {
  5865. players[i] uploadleaderboards();
  5866. }
  5867. }
  5868.  
  5869.  
  5870. function initializeStatTracking()
  5871. {
  5872. level.global_zombies_killed = 0;
  5873. level.zombies_timeout_spawn = 0;
  5874. level.zombies_timeout_playspace = 0;
  5875. level.zombies_timeout_undamaged = 0;
  5876. level.zombie_player_killed_count = 0;
  5877. level.zombie_trap_killed_count = 0;
  5878. level.zombie_pathing_failed = 0;
  5879. level.zombie_breadcrumb_failed = 0;
  5880.  
  5881. }
  5882.  
  5883. function uploadGlobalStatCounters()
  5884. {
  5885. incrementCounter( "global_zombies_killed", level.global_zombies_killed );
  5886. incrementCounter( "global_zombies_killed_by_players", level.zombie_player_killed_count );
  5887. incrementCounter( "global_zombies_killed_by_traps", level.zombie_trap_killed_count );
  5888. }
  5889.  
  5890. function player_fake_death()
  5891. {
  5892. level notify ("fake_death");
  5893. self notify ("fake_death");
  5894.  
  5895. self TakeAllWeapons();
  5896. self AllowStand( false );
  5897. self AllowCrouch( false );
  5898. self AllowProne( true );
  5899.  
  5900. self.ignoreme = true;
  5901. self EnableInvulnerability();
  5902.  
  5903. wait( 1 );
  5904. self FreezeControls( true );
  5905. }
  5906.  
  5907. function player_exit_level()
  5908. {
  5909. self AllowStand( true );
  5910. self AllowCrouch( false );
  5911. self AllowProne( false );
  5912.  
  5913. //self thread lui::screen_fade_out( 1 );
  5914. }
  5915.  
  5916.  
  5917. function player_killed_override(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
  5918. {
  5919. // BLANK
  5920. level waittill( "forever" );
  5921. }
  5922.  
  5923. function player_zombie_breadcrumb()
  5924. {
  5925. self notify("stop_player_zombie_breadcrumb");
  5926. self endon("stop_player_zombie_breadcrumb");
  5927. self endon( "disconnect" );
  5928. self endon( "spawned_spectator" );
  5929. level endon( "intermission" );
  5930.  
  5931. self.zombie_breadcrumbs = [];
  5932. self.zombie_breadcrumb_distance = 24 * 24; // min dist (squared) the player must move to drop a crumb
  5933. self.zombie_breadcrumb_area_num = 3; // the number of "rings" the area breadcrumbs use
  5934. self.zombie_breadcrumb_area_distance = 16; // the distance between each "ring" of the area breadcrumbs
  5935.  
  5936. self store_crumb( self.origin );
  5937. last_crumb = self.origin;
  5938.  
  5939. self thread zm_utility::debug_breadcrumbs();
  5940.  
  5941. while( 1 )
  5942. {
  5943. wait_time = 0.1;
  5944.  
  5945.  
  5946. if( self.ignoreme )
  5947. {
  5948. wait( wait_time );
  5949. continue;
  5950. }
  5951.  
  5952. //For cloaking ability
  5953. //if( self.ignoreme )
  5954. //{
  5955. // wait( wait_time );
  5956. // continue;
  5957. //}
  5958.  
  5959.  
  5960. store_crumb = true;
  5961. airborne = false;
  5962. crumb = self.origin;
  5963.  
  5964. //TODO TEMP SCRIPT for vehicle testing Delete/comment when done
  5965. if ( !self IsOnGround() && self isinvehicle() )
  5966. {
  5967. trace = bullettrace( self.origin + (0,0,10), self.origin, false, undefined );
  5968. crumb = trace["position"];
  5969. }
  5970.  
  5971. //TODO TEMP DISABLE for vehicle testing. Uncomment when reverting
  5972. // if ( !self IsOnGround() )
  5973. // {
  5974. // airborne = true;
  5975. // store_crumb = false;
  5976. // wait_time = 0.05;
  5977. // }
  5978. //
  5979. if( !airborne && DistanceSquared( crumb, last_crumb ) < self.zombie_breadcrumb_distance )
  5980. {
  5981. store_crumb = false;
  5982. }
  5983.  
  5984. if ( airborne && self IsOnGround() )
  5985. {
  5986. // player was airborne, store crumb now that he's on the ground
  5987. store_crumb = true;
  5988. airborne = false;
  5989. }
  5990.  
  5991. if( isDefined( level.custom_breadcrumb_store_func ) )
  5992. {
  5993. store_crumb = self [[ level.custom_breadcrumb_store_func ]]( store_crumb );
  5994. }
  5995.  
  5996. if( isDefined( level.custom_airborne_func ) )
  5997. {
  5998. airborne = self [[ level.custom_airborne_func ]]( airborne );
  5999. }
  6000.  
  6001. if( store_crumb )
  6002. {
  6003. zm_utility::debug_print( "Player is storing breadcrumb " + crumb );
  6004.  
  6005. if( IsDefined(self.node) )
  6006. {
  6007. zm_utility::debug_print( "has closest node " );
  6008. }
  6009.  
  6010. last_crumb = crumb;
  6011. self store_crumb( crumb );
  6012. }
  6013.  
  6014. wait( wait_time );
  6015. }
  6016. }
  6017.  
  6018.  
  6019. function store_crumb( origin )
  6020. {
  6021. offsets = [];
  6022. height_offset = 32;
  6023.  
  6024. index = 0;
  6025. for( j = 1; j <= self.zombie_breadcrumb_area_num; j++ )
  6026. {
  6027. offset = ( j * self.zombie_breadcrumb_area_distance );
  6028.  
  6029. offsets[0] = ( origin[0] - offset, origin[1], origin[2] );
  6030. offsets[1] = ( origin[0] + offset, origin[1], origin[2] );
  6031. offsets[2] = ( origin[0], origin[1] - offset, origin[2] );
  6032. offsets[3] = ( origin[0], origin[1] + offset, origin[2] );
  6033.  
  6034. offsets[4] = ( origin[0] - offset, origin[1], origin[2] + height_offset );
  6035. offsets[5] = ( origin[0] + offset, origin[1], origin[2] + height_offset );
  6036. offsets[6] = ( origin[0], origin[1] - offset, origin[2] + height_offset );
  6037. offsets[7] = ( origin[0], origin[1] + offset, origin[2] + height_offset );
  6038.  
  6039. for ( i = 0; i < offsets.size; i++ )
  6040. {
  6041. self.zombie_breadcrumbs[index] = offsets[i];
  6042. index++;
  6043. }
  6044. }
  6045. }
  6046.  
  6047.  
  6048. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6049. /////////////////////////////////////////////////LEADERBOARD CODE///////////////////////////////////////////////////////////
  6050. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6051. function to_mins( seconds )
  6052. {
  6053. hours = 0;
  6054. minutes = 0;
  6055.  
  6056. if( seconds > 59 )
  6057. {
  6058. minutes = int( seconds / 60 );
  6059.  
  6060. seconds = int( seconds * 1000 ) % ( 60 * 1000 );
  6061. seconds = seconds * 0.001;
  6062.  
  6063. if( minutes > 59 )
  6064. {
  6065. hours = int( minutes / 60 );
  6066. minutes = int( minutes * 1000 ) % ( 60 * 1000 );
  6067. minutes = minutes * 0.001;
  6068. }
  6069. }
  6070.  
  6071. if( hours < 10 )
  6072. {
  6073. hours = "0" + hours;
  6074. }
  6075.  
  6076. if( minutes < 10 )
  6077. {
  6078. minutes = "0" + minutes;
  6079. }
  6080.  
  6081. seconds = Int( seconds );
  6082. if( seconds < 10 )
  6083. {
  6084. seconds = "0" + seconds;
  6085. }
  6086.  
  6087. combined = "" + hours + ":" + minutes + ":" + seconds;
  6088.  
  6089. return combined;
  6090. }
  6091.  
  6092. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6093. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6094. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6095.  
  6096. //
  6097. // INTERMISSION =========================================================== //
  6098. //
  6099.  
  6100. function intermission()
  6101. {
  6102. level.intermission = true;
  6103. level notify( "intermission" );
  6104.  
  6105. players = GetPlayers();
  6106. for( i = 0; i < players.size; i++ )
  6107. {
  6108. players[i] SetClientThirdPerson( 0 );
  6109. players[i] resetFov();
  6110.  
  6111. players[i].health = 100; // This is needed so the player view doesn't get stuck
  6112. players[i] thread [[level.custom_intermission]]();
  6113.  
  6114. players[i] StopSounds();
  6115. }
  6116.  
  6117. wait( 5.25 );
  6118.  
  6119. players = GetPlayers();
  6120. for( i = 0; i < players.size; i++ )
  6121. {
  6122. players[i] clientfield::set( "zmbLastStand", 0 );
  6123. }
  6124.  
  6125. level thread zombie_game_over_death();
  6126. }
  6127.  
  6128. function zombie_game_over_death()
  6129. {
  6130. // Kill remaining zombies, in style!
  6131. zombies = GetAiTeamArray( level.zombie_team );
  6132. for( i = 0; i < zombies.size; i++ )
  6133. {
  6134. if( !IsAlive( zombies[i] ) )
  6135. {
  6136. continue;
  6137. }
  6138.  
  6139. zombies[i] SetGoal( zombies[i].origin );
  6140. }
  6141.  
  6142. for( i = 0; i < zombies.size; i++ )
  6143. {
  6144. if( !IsAlive( zombies[i] ) )
  6145. {
  6146. continue;
  6147. }
  6148.  
  6149. if ( IS_TRUE( zombies[i].ignore_game_over_death ) )
  6150. {
  6151. continue;
  6152. }
  6153.  
  6154. wait( 0.5 + RandomFloat( 2 ) );
  6155.  
  6156. if ( isdefined( zombies[i] ) )
  6157. {
  6158. if( !IsVehicle( zombies[i] ) )
  6159. {
  6160. zombies[i] zombie_utility::zombie_head_gib();
  6161. }
  6162.  
  6163. zombies[i] Kill();
  6164. }
  6165. }
  6166. }
  6167.  
  6168.  
  6169. #define INTERMISSION_STREAMER_HINT_PRIORITY 0.9
  6170.  
  6171. function screen_fade_in( n_time, v_color, str_menu_id )
  6172. {
  6173. lui::screen_fade( n_time, 0, 1, v_color, false, str_menu_id );
  6174. wait n_time;
  6175. }
  6176.  
  6177.  
  6178. function player_intermission()
  6179. {
  6180. self closeInGameMenu();
  6181. self CloseMenu( "StartMenu_Main" );
  6182.  
  6183. self notify("player_intermission");
  6184. self endon("player_intermission");
  6185. level endon( "stop_intermission" );
  6186. self endon("disconnect");
  6187. self endon("death");
  6188. self notify( "_zombie_game_over" ); // ww: notify so hud elements know when to leave
  6189.  
  6190. //Show total gained point for end scoreboard and lobby
  6191. self.score = self.score_total;
  6192.  
  6193. points =struct::get_array( "intermission", "targetname" );
  6194.  
  6195. if( !IsDefined( points ) || points.size == 0 )
  6196. {
  6197. points = getentarray( "info_intermission", "classname" );
  6198. if( points.size < 1 )
  6199. {
  6200. return;
  6201. }
  6202. }
  6203.  
  6204. if ( IS_TRUE( level.b_show_single_intermission ) )
  6205. {
  6206. a_s_temp_points = array::randomize( points );
  6207. points = [];
  6208. points[0] = array::random( a_s_temp_points );
  6209. }
  6210. else
  6211. {
  6212. points = array::randomize( points );
  6213. }
  6214.  
  6215. self zm_utility::create_streamer_hint( points[0].origin, points[0].angles, INTERMISSION_STREAMER_HINT_PRIORITY );
  6216.  
  6217. wait( 5 );
  6218.  
  6219. self lui::screen_fade_out( 1 );
  6220.  
  6221. // don't do this unti we're ready to "spawn" the players in the exit scenes
  6222. // the player camera will clip into the ground if this is done too early
  6223. self.sessionstate = "intermission";
  6224. self.spectatorclient = -1;
  6225. self.killcamentity = -1;
  6226. self.archivetime = 0;
  6227. self.psoffsettime = 0;
  6228. self.friendlydamage = undefined;
  6229. if ( isdefined( level.player_intemission_spawn_callback ) )
  6230. {
  6231. self thread [[ level.player_intemission_spawn_callback ]] ( points[0].origin, points[0].angles );
  6232. }
  6233.  
  6234. while( 1 )
  6235. {
  6236. for( i = 0; i < points.size; i++ )
  6237. {
  6238. point = points[i];
  6239. nextpoint = points[i+1];
  6240.  
  6241. self SetOrigin( point.origin );
  6242. self SetPlayerAngles( point.angles );
  6243. wait 0.15;
  6244.  
  6245. self notify("player_intermission_spawned");
  6246.  
  6247. if ( IsDefined(nextpoint) )
  6248. {
  6249. self zm_utility::create_streamer_hint( nextpoint.origin, nextpoint.angles, INTERMISSION_STREAMER_HINT_PRIORITY );
  6250. self screen_fade_in( 2 );
  6251.  
  6252. wait( 3 );
  6253.  
  6254. self lui::screen_fade_out( 2 );
  6255. }
  6256. else
  6257. {
  6258. self screen_fade_in( 2 );
  6259.  
  6260. if ( points.size == 1 )
  6261. {
  6262. return;
  6263. }
  6264. }
  6265. }
  6266. }
  6267. }
  6268.  
  6269. function fade_up_over_time(t)
  6270. {
  6271. self FadeOverTime( t );
  6272. self.alpha = 1;
  6273. }
  6274.  
  6275. function default_exit_level()
  6276. {
  6277. zombies = GetAiTeamArray( level.zombie_team );
  6278. for ( i = 0; i < zombies.size; i++ )
  6279. {
  6280. if ( IS_TRUE( zombies[i].ignore_solo_last_stand ) )
  6281. {
  6282. continue;
  6283. }
  6284.  
  6285. if ( isDefined( zombies[i].find_exit_point ) )
  6286. {
  6287. zombies[i] thread [[ zombies[i].find_exit_point ]]();
  6288. continue;
  6289. }
  6290.  
  6291. if ( zombies[i].ignoreme )
  6292. {
  6293. zombies[i] thread default_delayed_exit();
  6294. }
  6295. else
  6296. {
  6297. zombies[i] thread default_find_exit_point();
  6298. }
  6299. }
  6300. }
  6301.  
  6302. function default_delayed_exit()
  6303. {
  6304. self endon( "death" );
  6305.  
  6306. while ( 1 )
  6307. {
  6308. if ( !level flag::get( "wait_and_revive" ) )
  6309. {
  6310. return;
  6311. }
  6312.  
  6313. // broke through the barricade, find an exit point
  6314. if ( !self.ignoreme )
  6315. {
  6316. break;
  6317. }
  6318. wait( 0.1 );
  6319. }
  6320.  
  6321. self thread default_find_exit_point();
  6322. }
  6323.  
  6324. function default_find_exit_point()
  6325. {
  6326. self endon( "death" );
  6327.  
  6328. player = GetPlayers()[0];
  6329.  
  6330. dist_zombie = 0;
  6331. dist_player = 0;
  6332. dest = 0;
  6333.  
  6334. away = VectorNormalize( self.origin - player.origin );
  6335. endPos = self.origin + VectorScale( away, 600 );
  6336.  
  6337. if ( isdefined( level.zm_loc_types[ "wait_location" ] && level.zm_loc_types[ "wait_location" ].size > 0 ) )
  6338. {
  6339. locs = array::randomize( level.zm_loc_types[ "wait_location" ] );
  6340. }
  6341. //TODO Add wait_locations to Der Reise and we can remove this line
  6342. else // Legacy catch
  6343. {
  6344. locs = array::randomize( level.zm_loc_types[ "dog_location" ] );
  6345. }
  6346.  
  6347. for ( i = 0; i < locs.size; i++ )
  6348. {
  6349. dist_zombie = DistanceSquared( locs[i].origin, endPos );
  6350. dist_player = DistanceSquared( locs[i].origin, player.origin );
  6351.  
  6352. if ( dist_zombie < dist_player )
  6353. {
  6354. dest = i;
  6355. break;
  6356. }
  6357. }
  6358.  
  6359. self notify( "stop_find_flesh" );
  6360. self notify( "zombie_acquire_enemy" );
  6361.  
  6362. if( isdefined( locs[dest] ) )
  6363. {
  6364. self SetGoal( locs[dest].origin );
  6365. }
  6366.  
  6367. while ( 1 )
  6368. {
  6369. // in the event this function isn't run through a solo revive, use level override to dictate behavior; don't change existing behavior if this doesn't exist
  6370. b_passed_override = true;
  6371.  
  6372. // Returning 'false' from the level override will put zombies back into find_flesh
  6373. if ( IsDefined( level.default_find_exit_position_override ) )
  6374. {
  6375. b_passed_override = [[ level.default_find_exit_position_override ]]();
  6376. }
  6377.  
  6378. if ( !level flag::get( "wait_and_revive" ) && b_passed_override )
  6379. {
  6380. break;
  6381. }
  6382. wait( 0.1 );
  6383. }
  6384.  
  6385. }
  6386.  
  6387. function play_level_start_vox_delayed()
  6388. {
  6389. wait(3);
  6390. players = GetPlayers();
  6391. num = RandomIntRange( 0, players.size );
  6392. players[num] zm_audio::create_and_play_dialog( "general", "intro" );
  6393. }
  6394.  
  6395.  
  6396. function register_sidequest( id, sidequest_stat )
  6397. {
  6398. if ( !IsDefined( level.zombie_sidequest_stat ) )
  6399. {
  6400. level.zombie_sidequest_previously_completed = [];
  6401. level.zombie_sidequest_stat = [];
  6402. }
  6403.  
  6404. level.zombie_sidequest_stat[id] = sidequest_stat;
  6405.  
  6406. //level flag::wait_till( "all_players_spawned" );
  6407. level flag::wait_till( "start_zombie_round_logic" );
  6408.  
  6409. level.zombie_sidequest_previously_completed[id] = false;
  6410.  
  6411. // don't do stats stuff if it's not an online game
  6412. if ( level.systemLink || GetDvarInt( "splitscreen_playerCount" ) == GetPlayers().size )
  6413. {
  6414. return;
  6415. }
  6416.  
  6417. //don't do stats stuff if stats are disabled
  6418. if ( IS_TRUE( level.zm_disable_recording_stats ) )
  6419. {
  6420. return;
  6421. }
  6422.  
  6423. players = GetPlayers();
  6424. for ( i = 0; i < players.size; i++ )
  6425. {
  6426. if ( players[i] zm_stats::get_global_stat( level.zombie_sidequest_stat[id] ) )
  6427. {
  6428. level.zombie_sidequest_previously_completed[id] = true;
  6429. return;
  6430. }
  6431. }
  6432. }
  6433.  
  6434.  
  6435. function is_sidequest_previously_completed(id)
  6436. {
  6437. return IS_TRUE( level.zombie_sidequest_previously_completed[id] );
  6438. }
  6439.  
  6440.  
  6441. function set_sidequest_completed(id)
  6442. {
  6443. level notify( "zombie_sidequest_completed", id );
  6444. level.zombie_sidequest_previously_completed[id] = true;
  6445.  
  6446. // don't do stats stuff if it's not an online game
  6447. if ( level.systemLink )
  6448. {
  6449. return;
  6450. }
  6451. if ( GetDvarInt( "splitscreen_playerCount" ) == GetPlayers().size )
  6452. {
  6453. return;
  6454. }
  6455.  
  6456. //don't do stats stuff if stats are disabled
  6457. if ( IS_TRUE( level.zm_disable_recording_stats ) )
  6458. {
  6459. return;
  6460. }
  6461.  
  6462. players = GetPlayers();
  6463. for ( i = 0; i < players.size; i++ )
  6464. {
  6465. if ( isdefined( level.zombie_sidequest_stat[id] ) )
  6466. {
  6467. players[i] zm_stats::add_global_stat( level.zombie_sidequest_stat[id], 1 );
  6468. }
  6469. }
  6470. }
  6471.  
  6472. function playSwipeSound( mod, attacker )
  6473. {
  6474. if( IS_TRUE(attacker.is_zombie) || (isdefined( attacker.archetype ) && attacker.archetype == "margwa" ) )
  6475. {
  6476. self playsoundtoplayer( "evt_player_swiped", self );
  6477. return;
  6478. }
  6479. }
  6480.  
  6481. function precache_zombie_leaderboards()
  6482. {
  6483. // don't save leaderboards for systemlink or custom games
  6484. if( SessionModeIsSystemlink() )
  6485. {
  6486. return;
  6487. }
  6488.  
  6489. // GLOBAL LEADERBOARDS
  6490. globalLeaderboards = "LB_ZM_GB_BULLETS_FIRED_AT ";
  6491. globalLeaderboards += "LB_ZM_GB_BULLETS_HIT_AT ";
  6492. globalLeaderboards += "LB_ZM_GB_DISTANCE_TRAVELED_AT ";
  6493. globalLeaderboards += "LB_ZM_GB_DOORS_PURCHASED_AT ";
  6494. globalLeaderboards += "LB_ZM_GB_GRENADE_KILLS_AT ";
  6495. globalLeaderboards += "LB_ZM_GB_HEADSHOTS_AT ";
  6496. globalLeaderboards += "LB_ZM_GB_KILLS_AT ";
  6497. globalLeaderboards += "LB_ZM_GB_PERKS_DRANK_AT ";
  6498. globalLeaderboards += "LB_ZM_GB_REVIVES_AT ";
  6499.  
  6500. //Multirank
  6501. globalLeaderboards += "LB_ZM_GB_KILLSTATS_MR ";
  6502. globalLeaderboards += "LB_ZM_GB_GAMESTATS_MR ";
  6503.  
  6504. if ( !level.rankedMatch && (GetDvarInt( "zm_private_rankedmatch", 0 ) == 0) )
  6505. {
  6506. precacheLeaderboards( globalLeaderboards );
  6507. return;
  6508. }
  6509.  
  6510. // MAP LEADERBOARD
  6511. mapname = GetDvarString( "mapname" );
  6512. expectedPlayerNum = GetNumExpectedPlayers();
  6513.  
  6514. mapLeaderboard = "LB_ZM_MAP_"+ getsubstr( mapname, 3, mapname.size ) + "_" + expectedPlayerNum + "PLAYER";
  6515.  
  6516. precacheLeaderboards( globalLeaderboards + mapLeaderboard );
  6517. }
  6518.  
  6519. function zm_on_player_connect()
  6520. {
  6521. if( level.passed_introscreen)
  6522. {
  6523. self setClientUIVisibilityFlag( "hud_visible", 1 );
  6524. self setClientUIVisibilityFlag( "weapon_hud_visible", 1 );
  6525. }
  6526. thread refresh_player_navcard_hud();
  6527. self thread watchDisconnect();
  6528.  
  6529. self.hud_damagefeedback = newdamageindicatorhudelem(self);
  6530. self.hud_damagefeedback.horzAlign = "center";
  6531. self.hud_damagefeedback.vertAlign = "middle";
  6532. self.hud_damagefeedback.x = -12;
  6533. self.hud_damagefeedback.y = -12;
  6534. self.hud_damagefeedback.alpha = 0;
  6535. self.hud_damagefeedback.archived = true;
  6536. self.hud_damagefeedback setShader( "damage_feedback", 24, 48 );
  6537. self.hitSoundTracker = true;
  6538.  
  6539. if( IsDefined( level.n_gameplay_start_time ) ) //ensures that this is only called for players who are hotjoining
  6540. {
  6541. self LUINotifyEvent( &"game_timer_reset", 1, level.n_gameplay_start_time );
  6542. }
  6543. }
  6544.  
  6545. function zm_on_player_disconnect()
  6546. {
  6547. thread refresh_player_navcard_hud();
  6548. }
  6549.  
  6550. function watchDisconnect()
  6551. {
  6552. self notify("watchDisconnect");
  6553. self endon("watchDisconnect");
  6554. self waittill("disconnect");
  6555. zm_on_player_disconnect();
  6556. }
  6557.  
  6558.  
  6559.  
  6560. function increment_dog_round_stat(stat)
  6561. {
  6562. players = GetPlayers();
  6563. foreach(player in players)
  6564. {
  6565. player zm_stats::increment_client_stat( "zdog_rounds_" + stat );
  6566. }
  6567. }
  6568.  
  6569. function setup_player_navcard_hud()
  6570. {
  6571. level flag::wait_till( "start_zombie_round_logic" );
  6572. thread refresh_player_navcard_hud();
  6573. }
  6574.  
  6575.  
  6576. function refresh_player_navcard_hud()
  6577. {
  6578. if (!IsDefined(level.navcards))
  6579. return;
  6580. players = GetPlayers();
  6581. foreach( player in players )
  6582. {
  6583. navcard_bits = 0;
  6584. for(i = 0;i < level.navcards.size; i++)
  6585. {
  6586. hasit = player zm_stats::get_global_stat( level.navcards[i] );
  6587. if (isdefined(player.navcard_grabbed) && player.navcard_grabbed == level.navcards[i] )
  6588. hasit = 1;
  6589. if( hasit )
  6590. {
  6591. navcard_bits +=( 1 << i );
  6592. }
  6593. }
  6594. util::wait_network_frame();
  6595. player clientfield::set( "navcard_held", 0 );
  6596. if ( navcard_bits > 0 )
  6597. {
  6598. util::wait_network_frame();
  6599. player clientfield::set( "navcard_held", navcard_bits );
  6600. }
  6601. }
  6602.  
  6603. }
  6604.  
  6605. function set_default_laststand_pistol(solo_mode)
  6606. {
  6607.  
  6608. if (!solo_mode )
  6609. {
  6610. level.laststandpistol = level.default_laststandpistol;
  6611. }
  6612. else
  6613. {
  6614. level.laststandpistol = level.default_solo_laststandpistol;
  6615. }
  6616.  
  6617. }
  6618.  
  6619. //109171 Zombies - ZM_Global - Add check for player count at beginning of the game
  6620. //monitors during the match for exploits extra players being able to join the match
  6621. function player_too_many_players_check()
  6622. {
  6623. max_players = 4;
  6624. if ( level.scr_zm_ui_gametype == "zgrief" )
  6625. {
  6626. max_players = 8;
  6627. }
  6628.  
  6629. if ( GetPlayers().size > max_players )
  6630. {
  6631. zm_game_module::freeze_players(true);
  6632. level notify("end_game");
  6633. }
  6634.  
  6635. }
  6636.  
  6637. //vehicle response to idgun damage
  6638. function is_idgun_damage( weapon )
  6639. {
  6640. if( isdefined( level.idgun_weapons ) )
  6641. {
  6642. if ( IsInArray( level.idgun_weapons, weapon ) )
  6643. return true;
  6644. }
  6645. return false;
  6646. }
  6647.  
  6648. function zm_on_player_spawned()
  6649. {
  6650. thread update_zone_name();
  6651. thread update_is_player_valid();
  6652. }
  6653.  
  6654. function update_is_player_valid()
  6655. {
  6656. self endon( "death" );
  6657. self endon( "disconnnect" );
  6658.  
  6659. self.am_i_valid = true;
  6660. while ( isDefined( self ) )
  6661. {
  6662. self.am_i_valid = zm_utility::is_player_valid( self, true );
  6663. WAIT_SERVER_FRAME
  6664. }
  6665. }
  6666.  
  6667. function update_zone_name()
  6668. {
  6669. self endon( "death" );
  6670. self endon( "disconnnect" );
  6671.  
  6672. self.zone_name = zm_utility::get_current_zone();
  6673. if ( isDefined( self.zone_name ) )
  6674. {
  6675. self.previous_zone_name = self.zone_name;
  6676. }
  6677.  
  6678. while ( isDefined( self ) )
  6679. {
  6680. if( isDefined( self.zone_name ) )
  6681. {
  6682. self.previous_zone_name = self.zone_name;
  6683. }
  6684. self.zone_name = zm_utility::get_current_zone();
  6685.  
  6686. wait RandomFloatRange( 0.5, 1.0 );
  6687. }
  6688. }
Add Comment
Please, Sign In to add comment