#using scripts\codescripts\struct; #using scripts\shared\aat_shared; #using scripts\shared\ai_puppeteer_shared; #using scripts\shared\archetype_shared\archetype_shared; #using scripts\shared\array_shared; #using scripts\shared\callbacks_shared; #using scripts\shared\clientfield_shared; #using scripts\shared\demo_shared; #using scripts\shared\flag_shared; #using scripts\shared\hud_util_shared; #using scripts\shared\laststand_shared; #using scripts\shared\lui_shared; #using scripts\shared\math_shared; #using scripts\shared\scoreevents_shared; #using scripts\shared\system_shared; #using scripts\shared\util_shared; #using scripts\shared\visionset_mgr_shared; #using scripts\zm\gametypes\_globallogic; #using scripts\zm\gametypes\_globallogic_vehicle; #using scripts\zm\_bb; #using scripts\shared\ai\systems\gib; #using scripts\zm\gametypes\_weapons; #using scripts\zm\gametypes\_zm_gametype; #using scripts\zm\gametypes\_globallogic_spawn; #using scripts\zm\gametypes\_globallogic_player; #using scripts\zm\_util; #using scripts\zm\_zm_attackables; #using scripts\zm\_zm_audio; #using scripts\zm\_zm_bgb; #using scripts\zm\_zm_bgb_token; #using scripts\zm\_zm_blockers; #using scripts\zm\_zm_bot; #using scripts\zm\_zm_daily_challenges; #using scripts\zm\_zm_equipment; #using scripts\zm\_zm_ffotd; #using scripts\zm\_zm_game_module; //#using scripts\zm\_zm_hero_weapon; #using scripts\zm\_zm_laststand; #using scripts\zm\_zm_melee_weapon; #using scripts\zm\_zm_perks; #using scripts\zm\_zm_pers_upgrades; #using scripts\zm\_zm_pers_upgrades_functions; #using scripts\zm\_zm_pers_upgrades_system; #using scripts\zm\_zm_placeable_mine; #using scripts\zm\_zm_player; #using scripts\zm\_zm_powerups; #using scripts\zm\_zm_score; #using scripts\zm\_zm_spawner; #using scripts\zm\_zm_stats; #using scripts\zm\_zm_timer; #using scripts\zm\_zm_unitrigger; #using scripts\zm\_zm_utility; #using scripts\zm\_zm_weapons; #using scripts\zm\_zm_zonemgr; #using scripts\shared\ai_shared; // AATs #using scripts\zm\aats\_zm_aat_blast_furnace; #using scripts\zm\aats\_zm_aat_dead_wire; #using scripts\zm\aats\_zm_aat_fire_works; #using scripts\zm\aats\_zm_aat_thunder_wall; #using scripts\zm\aats\_zm_aat_turned; // BGBs #using scripts\zm\bgbs\_zm_bgb_aftertaste; #using scripts\zm\bgbs\_zm_bgb_alchemical_antithesis; #using scripts\zm\bgbs\_zm_bgb_always_done_swiftly; #using scripts\zm\bgbs\_zm_bgb_anywhere_but_here; #using scripts\zm\bgbs\_zm_bgb_armamental_accomplishment; #using scripts\zm\bgbs\_zm_bgb_arms_grace; #using scripts\zm\bgbs\_zm_bgb_arsenal_accelerator; #using scripts\zm\bgbs\_zm_bgb_burned_out; #using scripts\zm\bgbs\_zm_bgb_cache_back; #using scripts\zm\bgbs\_zm_bgb_coagulant; #using scripts\zm\bgbs\_zm_bgb_danger_closest; #using scripts\zm\bgbs\_zm_bgb_dead_of_nuclear_winter; #using scripts\zm\bgbs\_zm_bgb_ephemeral_enhancement; #using scripts\zm\bgbs\_zm_bgb_firing_on_all_cylinders; #using scripts\zm\bgbs\_zm_bgb_im_feelin_lucky; #using scripts\zm\bgbs\_zm_bgb_immolation_liquidation; #using scripts\zm\bgbs\_zm_bgb_impatient; #using scripts\zm\bgbs\_zm_bgb_in_plain_sight; #using scripts\zm\bgbs\_zm_bgb_kill_joy; #using scripts\zm\bgbs\_zm_bgb_killing_time; #using scripts\zm\bgbs\_zm_bgb_licensed_contractor; #using scripts\zm\bgbs\_zm_bgb_lucky_crit; #using scripts\zm\bgbs\_zm_bgb_now_you_see_me; #using scripts\zm\bgbs\_zm_bgb_on_the_house; #using scripts\zm\bgbs\_zm_bgb_perkaholic; #using scripts\zm\bgbs\_zm_bgb_phoenix_up; #using scripts\zm\bgbs\_zm_bgb_pop_shocks; #using scripts\zm\bgbs\_zm_bgb_respin_cycle; #using scripts\zm\bgbs\_zm_bgb_stock_option; #using scripts\zm\bgbs\_zm_bgb_sword_flay; #using scripts\zm\bgbs\_zm_bgb_unquenchable; #using scripts\zm\bgbs\_zm_bgb_wall_power; #using scripts\zm\bgbs\_zm_bgb_whos_keeping_score; // DLC1 BGBS #using scripts\zm\bgbs\_zm_bgb_crawl_space; #using scripts\zm\bgbs\_zm_bgb_fatal_contraption; #using scripts\zm\bgbs\_zm_bgb_head_drama; #using scripts\zm\bgbs\_zm_bgb_undead_man_walking; // DLC2 BGBS #using scripts\zm\bgbs\_zm_bgb_fear_in_headlights; #using scripts\zm\bgbs\_zm_bgb_secret_shopper; #using scripts\zm\bgbs\_zm_bgb_temporal_gift; #using scripts\zm\bgbs\_zm_bgb_unbearable; // DLC3 BGBS #using scripts\zm\bgbs\_zm_bgb_crate_power; #using scripts\zm\bgbs\_zm_bgb_disorderly_combat; #using scripts\zm\bgbs\_zm_bgb_projectile_vomiting; #using scripts\zm\bgbs\_zm_bgb_shopping_free; #using scripts\zm\bgbs\_zm_bgb_slaughter_slide; // DLC4 BGBS #using scripts\zm\bgbs\_zm_bgb_bullet_boost; #using scripts\zm\bgbs\_zm_bgb_mind_blown; #using scripts\zm\bgbs\_zm_bgb_near_death_experience; #using scripts\zm\bgbs\_zm_bgb_newtonian_negation; #using scripts\zm\bgbs\_zm_bgb_profit_sharing; #using scripts\zm\bgbs\_zm_bgb_round_robbin; #using scripts\zm\bgbs\_zm_bgb_self_medication; // DLC5 BGBS #using scripts\zm\bgbs\_zm_bgb_board_games; #using scripts\zm\bgbs\_zm_bgb_board_to_death; #using scripts\zm\bgbs\_zm_bgb_extra_credit; #using scripts\zm\bgbs\_zm_bgb_eye_candy; #using scripts\zm\bgbs\_zm_bgb_flavor_hexed; #using scripts\zm\bgbs\_zm_bgb_idle_eyes; #using scripts\zm\bgbs\_zm_bgb_power_vacuum; #using scripts\zm\bgbs\_zm_bgb_reign_drops; #using scripts\zm\bgbs\_zm_bgb_soda_fountain; #using scripts\zm\bgbs\_zm_bgb_tone_death; // DLC5 BGB REQUIRED POWERUPS #using scripts\zm\_zm_powerup_bonus_points_player; #using scripts\zm\craftables\_zm_craftables; #using scripts\shared\ai\zombie_death; #using scripts\shared\ai\zombie_utility; #precache( "material", "hud_chalk_1" ); #precache( "material", "hud_chalk_2" ); #precache( "material", "hud_chalk_3" ); #precache( "material", "hud_chalk_4" ); #precache( "material", "hud_chalk_5" ); #precache( "material", "zom_icon_community_pot" ); #precache( "material", "zom_icon_community_pot_strip" ); #precache( "material","zom_icon_player_life"); #precache( "string", "ZOMBIE_WEAPONCOSTAMMO" ); #precache( "string", "ZOMBIE_ROUND" ); #precache( "string", "SCRIPT_PLUS" ); #precache( "string", "ZOMBIE_GAME_OVER" ); #precache( "string", "ZOMBIE_SURVIVED_ROUND" ); #precache( "string", "ZOMBIE_SURVIVED_ROUNDS" ); #precache( "string", "ZOMBIE_SURVIVED_NOMANS" ); #precache( "string", "ZOMBIE_EXTRA_LIFE" ); #precache( "string", "ZOMBIE_UNDEFINED" ); #precache( "triggerstring", "ZOMBIE_ELECTRIC_SWITCH" ); #precache( "triggerstring", "ZOMBIE_NEED_POWER" ); // Random Treasure Chest #precache( "string", "ZOMBIE_RANDOM_WEAPON_COST" ); // Weapons #precache( "string", "ZOMBIE_WEAPON_COSTONLYFILL_500" ); #precache( "triggerstring", "ZOMBIE_WEAPON_COSTONLYFILL_2000" ); #precache( "triggerstring", "ZOMBIE_WEAPONAMMOONLY_250" ); #precache( "triggerstring", "ZOMBIE_WEAPONCOSTAMMO_UPGRADE_500_250" ); // Barrier Pieces #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_10" ); #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_20" ); #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_50" ); #precache( "string", "ZOMBIE_BUTTON_BUY_BACK_BARRIER_100" ); // REWARD Barrier Pieces #precache( "string", "ZOMBIE_BUTTON_REWARD_BARRIER" ); // Debris #precache( "string", "ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_COST" ); // Doors #precache( "string", "ZOMBIE_BUTTON_BUY_OPEN_DOOR_COST" ); #precache( "string", "ZOMBIE_BUTTON_BUY_CLOSE_DOOR" ); #precache( "triggerstring", "ZOMBIE_BUTTON_REWARD_BARRIER" ); #precache( "fx", "_t6/maps/zombie/fx_zombie_bar_break" ); #precache( "fx", "_t6/maps/zombie/fx_zombie_bar_break_lite" ); #precache( "fx", "_t6/maps/zombie/fx_fog_zombie_amb" ); #precache( "fx", "zombie/fx_weapon_box_open_glow_zmb" ); #precache( "fx", "zombie/fx_weapon_box_closed_glow_zmb" ); #precache( "fx", "zombie/fx_glow_eye_orange" ); #precache( "fx", "zombie/fx_bul_flesh_head_fatal_zmb" ); #precache( "fx", "zombie/fx_bul_flesh_head_nochunks_zmb" ); #precache( "fx", "zombie/fx_bul_flesh_neck_spurt_zmb" ); #precache( "fx", "_t6/maps/zombie/fx_zombie_tesla_neck_spurt" ); #precache( "fx", "zombie/fx_blood_torso_explo_zmb" ); #precache( "fx", "zombie/fx_blood_torso_explo_lg_zmb" ); #precache( "fx", "zombie/fx_spawn_dirt_hand_burst_zmb" ); #precache( "fx", "zombie/fx_spawn_dirt_body_billowing_zmb" ); #precache( "fx", "zombie/fx_spawn_dirt_body_dustfalling_zmb" ); #precache( "fx", "zombie/fx_fire_torso_zmb" ); #precache( "fx", "_t6/explosions/fx_default_explosion" ); #precache( "fx", "_t6/maps/zombie/fx_zmb_tanzit_upgrade" ); #precache( "menu", "StartMenu_Main" ); #precache( "menu", "InitialBlack" ); #precache( "eventstring", "force_scoreboard" ); #precache( "eventstring", "open_ingame_menu" ); #precache( "eventstring", "play_promo_anim" ); #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_0" ); #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_1" ); #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_2" ); #precache( "string", "ZOMBIE_REVIVING_SOLO", "ZOMBIE_PLAYER_NAME_3" ); #namespace zm; function autoexec ignore_systems() { //shutdown unwanted systems - doing it in an autoexec is the only clean way to do it system::ignore("gadget_clone"); system::ignore("gadget_armor"); system::ignore("gadget_heat_wave"); system::ignore("gadget_resurrect"); system::ignore("gadget_shock_field"); system::ignore("gadget_active_camo"); system::ignore("gadget_mrpukey"); system::ignore("gadget_misdirection"); system::ignore("gadget_smokescreen"); system::ignore("gadget_firefly_swarm"); system::ignore("gadget_immolation"); system::ignore("gadget_forced_malfunction"); system::ignore("gadget_sensory_overload"); system::ignore("gadget_rapid_strike"); system::ignore("gadget_unstoppable_force"); system::ignore("gadget_overdrive"); system::ignore("gadget_concussive_wave"); system::ignore("gadget_ravage_core"); system::ignore("gadget_es_strike"); system::ignore("gadget_cacophany"); system::ignore("gadget_iff_override"); system::ignore("gadget_security_breach"); system::ignore("gadget_surge"); system::ignore("gadget_exo_breakdown"); system::ignore("gadget_servo_shortout"); system::ignore("gadget_system_overload"); system::ignore("gadget_cleanse"); system::ignore("gadget_flashback"); system::ignore("gadget_combat_efficiency"); system::ignore("gadget_other"); system::ignore("gadget_camo"); system::ignore("gadget_vision_pulse"); system::ignore("gadget_speed_burst"); system::ignore("gadget_thief"); system::ignore("replay_gun"); system::ignore("spike_charge_siegebot"); system::ignore("siegebot"); system::ignore("amws"); } function autoexec __init__sytem__() { system::register("zm",&__init__,undefined,undefined); } function __init__() { if(!isdefined(level.zombie_vars))level.zombie_vars=[]; } function init() { //New movement disabled for Zombies SetDvar( "doublejump_enabled", 0 ); SetDvar( "juke_enabled", 0 ); SetDvar( "playerEnergy_enabled", 0 ); SetDvar( "wallrun_enabled", 0 ); SetDvar( "sprintLeap_enabled", 0 ); SetDvar( "traverse_mode", 2 ); SetDvar( "weaponrest_enabled", 0 ); //we dont care about CP movie skipping logic in ZM SetDvar( "ui_allowDisplayContinue", true ); if ( !IsDefined( level.killstreakWeapons ) ) { level.killstreakWeapons = []; } level.weaponNone = GetWeapon( "none" ); level.weaponNull = GetWeapon( "weapon_null" ); level.weaponBaseMelee = GetWeapon( "knife" ); level.weaponBaseMeleeHeld = GetWeapon( "knife_held" ); level.weaponBallisticKnife = GetWeapon( "knife_ballistic" ); if(!isdefined(level.weaponRiotshield))level.weaponRiotshield=GetWeapon( "riotshield" ); level.weaponReviveTool = GetWeapon( "syrette" ); level.weaponZMDeathThroe = GetWeapon( "death_throe" ); level.weaponZMFists = GetWeapon( "zombie_fists" ); if(!isdefined(level.giveCustomLoadout))level.giveCustomLoadout=&zm_weapons::give_start_weapons; level.projectiles_should_ignore_world_pause = true; level.player_out_of_playable_area_monitor = true; level.player_too_many_weapons_monitor = true; level.player_too_many_weapons_monitor_func = &player_too_many_weapons_monitor; level.player_too_many_players_check = true; level.player_too_many_players_check_func = &player_too_many_players_check; level._use_choke_weapon_hints = 1; level._use_choke_blockers = 1; level.speed_change_round = 15; level.passed_introscreen = false; if(!isdefined(level.custom_ai_type)) { level.custom_ai_type = []; } level.custom_ai_spawn_check_funcs = []; // put things you'd like to be able to turn off in here above this line level thread zm_ffotd::main_start(); level.zombiemode = true; level.reviveFeature = false; level.swimmingFeature = false; level.calc_closest_player_using_paths = false; level.zombie_melee_in_water = true; level.put_timed_out_zombies_back_in_queue = true; level.use_alternate_poi_positioning = true; level.zmb_laugh_alias = "zmb_laugh_child"; level.sndAnnouncerIsRich = true; level.scr_zm_ui_gametype = GetDvarString( "ui_gametype" ); level.scr_zm_ui_gametype_group = "";//GetDvarString( "ui_zm_gamemodegroup" ); level.scr_zm_map_start_location = "";//GetDvarString( "ui_zm_mapstartlocation" ); level.curr_gametype_affects_rank = false; gametype = toLower( GetDvarString( "g_gametype" ) ); if ( "zclassic" == gametype || "zstandard" == gametype ) { level.curr_gametype_affects_rank = true; } level.grenade_multiattack_bookmark_count = 1; demo::initActorBookmarkParams( 3, 6000, 6000 ); // set up any gameplay modes /* level.GAME_MODULE_CLASSIC_INDEX = 0; zm_game_module::register_game_module(level.GAME_MODULE_CLASSIC_INDEX,"classic",undefined,undefined); zm_game_module::set_current_game_module(level.scr_zm_game_module); */ // Allowing custom round_spawn_failsafe function to be set here. if( !isdefined( level._zombies_round_spawn_failsafe ) ) { level._zombies_round_spawn_failsafe = &zombie_utility::round_spawn_failsafe; } level.func_get_zombie_spawn_delay = &get_zombie_spawn_delay; level.func_get_delay_between_rounds = &get_delay_between_rounds; level.zombie_visionset = "zombie_neutral"; level.wait_and_revive = false; if(GetDvarString("anim_intro") == "1") { level.zombie_anim_intro = 1; } else { level.zombie_anim_intro = 0; } precache_models(); precache_zombie_leaderboards(); level._ZOMBIE_GIB_PIECE_INDEX_ALL = 0; level._ZOMBIE_GIB_PIECE_INDEX_RIGHT_ARM = 1; level._ZOMBIE_GIB_PIECE_INDEX_LEFT_ARM = 2; level._ZOMBIE_GIB_PIECE_INDEX_RIGHT_LEG = 3; level._ZOMBIE_GIB_PIECE_INDEX_LEFT_LEG = 4; level._ZOMBIE_GIB_PIECE_INDEX_HEAD = 5; level._ZOMBIE_GIB_PIECE_INDEX_GUTS = 6; level._ZOMBIE_GIB_PIECE_INDEX_HAT = 7; //Limit zombie to 24 max, must have for network purposes if ( !isdefined( level.zombie_ai_limit ) ) { level.zombie_ai_limit = 24; } if ( !isdefined( level.zombie_actor_limit ) ) { level.zombie_actor_limit = 31; } init_flags(); init_dvars(); init_strings(); init_levelvars(); init_sounds(); init_shellshocks(); init_client_field_callback_funcs(); zm_utility::register_offhand_weapons_for_level_defaults(); level thread drive_client_connected_notifies(); // load map defaults //Systems zm_craftables::init(); zm_perks::init(); zm_powerups::init(); zm_spawner::init(); zm_weapons::init(); //Grab all static poi in the map level.zombie_poi_array = getEntArray( "zombie_poi", "script_noteworthy" ); init_function_overrides(); // ww: init the pistols in the game so last stand has the importance order level thread last_stand_pistol_rank_init(); level thread post_all_players_connected(); level start_zm_dash_counter_watchers(); zm_utility::init_utility(); util::registerClientSys( "lsm" ); // STATS_TODO: will check if the following is needed later initializeStatTracking(); if ( GetPlayers().size <= 1 ) { incrementCounter( "global_solo_games", 1 ); } else if( ( isdefined( level.systemLink ) && level.systemLink ) ) { incrementCounter( "global_systemlink_games", 1 ); } else if ( GetDvarInt( "splitscreen_playerCount" ) == GetPlayers().size ) { incrementCounter( "global_splitscreen_games", 1 ); } else // coop game { incrementCounter( "global_coop_games", 1 ); } callback::on_connect( &zm_on_player_connect); //self LUINotifyEvent( &"score_event", 3, label, score, rampageBonus ); // Initialize persistent upgrades //zm_pers_upgrades::pers_upgrade_init(); zm_utility::set_demo_intermission_point(); level thread zm_ffotd::main_end(); level thread zm_utility::track_players_intersection_tracker(); level thread onAllPlayersReady(); level thread startUnitriggers(); level thread confuse_third_party_trainers(); callback::on_spawned( &zm_on_player_spawned ); printHashIDs(); } function post_main() { level thread init_custom_ai_type(); } function cheat_enabled( val ) { if ( GetDvarInt( "zombie_cheat" ) >= val ) { /# return true; #/ if ( IsProfileBuild() ) { return true; } } return false; } function confuse_third_party_trainers() { level flag::wait_till_any( array( "start_zombie_round_logic", "start_encounters_match_logic" ) ); while(1) { temp_var = get_round_number(); level.round_number = undefined; temp_var2 = temp_var; switch( RandomInt(5) ) { case 0: temp_var3 = temp_var; case 1: temp_var4 = temp_var; case 2: temp_var5 = temp_var; case 3: temp_var6 = temp_var; case 4: temp_var7 = temp_var; } level.round_number = temp_var; temp_var = undefined; temp_var1 = undefined; temp_var2 = undefined; temp_var3 = undefined; temp_var4 = undefined; temp_var5 = undefined; temp_var6 = undefined; temp_var7 = undefined; {wait(.05);}; } } function set_round_number( new_round ) { if ( new_round > 255 ) new_round = 255; world.roundnumber = new_round ^ 115; } function get_round_number() { return world.roundnumber ^ 115; } function startUnitriggers() { level flag::wait_till_any( array( "start_zombie_round_logic", "start_encounters_match_logic" ) ); level thread zm_unitrigger::main(); } function drive_client_connected_notifies() { while(1) { level waittill("connected", player); player demo::reset_actor_bookmark_kill_times(); player callback::callback( #"on_player_connect" ); } } function fade_out_intro_screen_zm( hold_black_time, fade_out_time, destroyed_afterwards ) { lui::screen_fade_out( 0, undefined ); if( IsDefined( hold_black_time ) ) { wait hold_black_time; } else { wait 0.2; } if( !IsDefined( fade_out_time ) ) { fade_out_time = 1.5; } array::thread_all(GetPlayers(), &initialBlackEnd); level clientfield::set( "sndZMBFadeIn", 1 ); lui::screen_fade_in( fade_out_time, undefined ); //level notify("fade_introblack"); wait 1.6; level.passed_introscreen = true; players = GetPlayers(); for(i = 0; i < players.size; i++) { if( IsDefined( level.customHudReveal ) ) { players[i] thread [[level.customHudReveal]](); } else { players[i] ShowHudAndPlayPromo(); } if(!( isdefined( level.host_ended_game ) && level.host_ended_game )) { if (isdefined(level.player_movement_suppressed)) { players[i] FreezeControls(level.player_movement_suppressed); /# println(" Unfreeze controls 4"); #/ } else { if(!( isdefined( players[i].hostMigrationControlsFrozen ) && players[i].hostMigrationControlsFrozen )) { players[i] FreezeControls(false); /# println(" Unfreeze controls 5"); #/ } } } } // level notify("fade_in_complete"); level flag::set("initial_blackscreen_passed"); level clientfield::set("gameplay_started", 1); } function ShowHudAndPlayPromo() { self setClientUIVisibilityFlag( "hud_visible", 1 ); self setClientUIVisibilityFlag( "weapon_hud_visible", 1 ); if( !( isdefined( self.seen_promo_anim ) && self.seen_promo_anim ) && SessionModeIsOnlineGame() ) { self LUINotifyEvent( &"play_promo_anim", 0 ); self.seen_promo_anim = true; } } function onAllPlayersReady() { timeOut = GetTime() + 5000; // 5 second time out. while(IsLoadingCinematicPlaying() || (GetNumExpectedPlayers() == 0 && (GetTime() < timeOut))) { wait(0.1); } /# println( "ZM >> player_count_expected=" + GetNumExpectedPlayers()); #/ player_count_actual = 0; while( (GetNumConnectedPlayers() < GetNumExpectedPlayers()) || (player_count_actual != GetNumExpectedPlayers()) ) { players = GetPlayers(); player_count_actual = 0; for( i = 0; i < players.size; i++ ) { players[i] FreezeControls( true ); if( players[i].sessionstate == "playing" ) { player_count_actual++; } } /# println( "ZM >> Num Connected =" + GetNumConnectedPlayers() + " Expected : " + GetNumExpectedPlayers()); #/ wait( 0.1 ); } SetInitialPlayersConnected(); level flag::set( "all_players_connected" ); SetDvar( "all_players_are_connected", "1" ); /# println( "ZM >> We have all players - START ZOMBIE LOGIC" ); #/ //Check to see if we should spawn some bots to help if ( (1 == GetNumConnectedPlayers()) && (GetDvarInt( "scr_zm_enable_bots" )==1) ) { level thread add_bots(); level flag::set("initial_players_connected"); } else { players = GetPlayers(); if ( players.size == 1 ) { level flag::set( "solo_game" ); level.solo_lives_given = 0; foreach ( player in players ) { player.lives = 0; } level zm::set_default_laststand_pistol( true ); } level flag::set("initial_players_connected"); array::thread_all(GetPlayers(), &initialBlack); while ( !AreTexturesLoaded() ) { {wait(.05);}; } if ( isdefined(level.added_initial_streamer_blackscreen) ) { wait(level.added_initial_streamer_blackscreen); } //level flag::set( "start_zombie_round_logic" ); thread start_zombie_logic_in_x_sec( 3.0 ); } set_intermission_point(); n_black_screen = 5.0; level thread fade_out_intro_screen_zm( n_black_screen, 1.5, true ); wait n_black_screen; // Reset the start time level.n_gameplay_start_time = GetTime(); clientfield::set( "game_start_time", level.n_gameplay_start_time ); } function initialBlack() { self CloseMenu( "InitialBlack" ); self OpenMenu( "InitialBlack" ); } function initialBlackEnd() { self CloseMenu( "InitialBlack" ); // self clientfield::set_to_player( "sndLevelStartSnapOff", 1 ); } function start_zombie_logic_in_x_sec( time_to_wait ) { wait( time_to_wait ); level flag::set( "start_zombie_round_logic" ); } function getAllOtherPlayers() { aliveplayers = []; // Make a list of fully connected, non-spectating, alive players for(i = 0; i < level.players.size; i++) { if ( !isdefined( level.players[i] ) ) continue; player = level.players[i]; if ( player.sessionstate != "playing" || player == self ) continue; aliveplayers[aliveplayers.size] = player; } return aliveplayers; } function updatePlayerNum( player ) { if(!Isdefined(player.playernum)) { if(player.team == "allies") { player.playernum = zm_utility::get_game_var("_team1_num"); zm_utility::set_game_var("_team1_num", player.playernum + 1); } else { player.playernum = zm_utility::get_game_var("_team2_num"); zm_utility::set_game_var("_team2_num", player.playernum + 1); } } } function getFreeSpawnpoint(spawnpoints, player) { // There are no valid spawnpoints in the map if(!isdefined(spawnpoints)) { /# iprintlnbold( "ZM >> No free spawn points in map" ); #/ return undefined; } // only should happen on initial spawn. if(!isdefined(game["spawns_randomized"])) { game["spawns_randomized"] = true; spawnpoints = array::randomize(spawnpoints); random_chance = randomint(100); if(random_chance > 50) { zm_utility::set_game_var("side_selection", 1); } else { zm_utility::set_game_var("side_selection", 2); } } side_selection = zm_utility::get_game_var("side_selection"); // used in vs. games where you switch sides on next round. if( zm_utility::get_game_var("switchedsides")) { if(side_selection == 2) { side_selection = 1; } else if(side_selection == 1) { side_selection = 2; } } if(IsDefined(player) && IsDefined(player.team)) { i = 0; while(IsDefined(spawnpoints) && i < spawnpoints.size) { If(side_selection == 1) { if(player.team != "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 1)) { ArrayRemoveValue(spawnpoints, spawnpoints[i]); i=0; } else if(player.team == "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 2)) { ArrayRemoveValue(spawnpoints, spawnpoints[i]); i=0; } else { i++; } } else { if(player.team == "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 1)) { ArrayRemoveValue(spawnpoints, spawnpoints[i]); i=0; } else if(player.team != "allies" && (IsDefined(spawnpoints[i].script_int) && spawnpoints[i].script_int == 2)) { ArrayRemoveValue(spawnpoints, spawnpoints[i]); i=0; } else { i++; } } } } updatePlayerNum( player ); for( j = 0; j < spawnpoints.size; j++ ) { if(!IsDefined(spawnpoints[j].en_num)) { for( m = 0; m < spawnpoints.size; m++ ) { spawnpoints[m].en_num = m; } } if( spawnpoints[j].en_num == player.playernum) { return spawnpoints[j]; } } return spawnpoints[0]; } function delete_in_createfx() { exterior_goals =struct::get_array( "exterior_goal", "targetname" ); for( i = 0; i < exterior_goals.size; i++ ) { if( !IsDefined( exterior_goals[i].target ) ) // If the exterior_goal entity has no targets defined then return { continue; } targets = GetEntArray( exterior_goals[i].target, "targetname" ); // Grab all the pieces that are targeted by the exterior_goal for( j = 0; j < targets.size; j++ ) // count total targets of exterior_goal { targets[j] zm_utility::self_delete(); } } if(isdefined(level.level_createfx_callback_thread)) { level thread [[level.level_createfx_callback_thread]](); } } function add_bots() { //Wait for the host! host = util::GetHostPlayer(); while ( !IsDefined( host ) ) { {wait(.05);}; host = util::GetHostPlayer(); } wait( 4.0 ); //Then spawn bots zbot_spawn(); SetDvar("bot_AllowMovement", "1"); SetDvar("bot_PressAttackBtn", "1"); SetDvar("bot_PressMeleeBtn", "1"); //Wait until bots are spawned while( GetPlayers().size<2 ) { {wait(.05);}; } //Unfreeze all players players = GetPlayers(); for( i = 0; i < players.size; i++ ) { players[i] FreezeControls( false ); /# println(" Unfreeze controls 6"); #/ } level.numberBotsAdded = 1; level flag::set( "start_zombie_round_logic" ); } function zbot_spawn() { player = util::GetHostPlayer(); //spawnPoints =struct::get_array( "initial_spawn_points", "targetname" ); //spawnPoint = getFreeSpawnpoint( spawnPoints, player ); bot = AddTestClient(); if ( !IsDefined( bot ) ) { /# println( "Could not add test client" ); #/ return; } spawnPoint = bot zm_gametype::onFindValidSpawnPoint(); bot.pers["isBot"] = true; bot.equipment_enabled = false; yaw = spawnPoint.angles[1]; return bot; } function post_all_players_connected() { level thread end_game(); level flag::wait_till( "start_zombie_round_logic" ); zm_utility::increment_zm_dash_counter( "start_per_game", 1 ); zm_utility::increment_zm_dash_counter( "start_per_player", level.players.size ); zm_utility::upload_zm_dash_counters(); level.dash_counter_start_player_count = level.players.size; /# println( "sessions: mapname=", level.script, " gametype zom isserver 1 player_count=", GetPlayers().size ); #/ // Start the Zombie MODE! level thread round_end_monitor(); if(!level.zombie_anim_intro) { if(isDefined(level._round_start_func)) { level thread [[level._round_start_func]](); } } level thread players_playing(); DisableGrenadeSuicide(); level.startInvulnerableTime = GetDvarInt( "player_deathInvulnerableTime" ); } function start_zm_dash_counter_watchers() { level thread first_consumables_used_watcher(); level thread players_reached_rounds_counter_watcher(); } function first_consumables_used_watcher() { level flag::init( "first_consumables_used" ); level flag::wait_till( "first_consumables_used" ); zm_utility::increment_zm_dash_counter( "first_consumables_used", 1 ); zm_utility::upload_zm_dash_counters(); } function players_reached_rounds_counter_watcher() { while( true ) { level waittill( "start_of_round" ); if( !IsDefined( level.dash_counter_round_reached_5 ) && level.round_number >= 5 ) { level.dash_counter_round_reached_5 = true; zm_utility::increment_zm_dash_counter( "reached_5", 1 ); } if( !IsDefined( level.dash_counter_round_reached_10 ) && level.round_number >= 10 ) { level.dash_counter_round_reached_10 = true; zm_utility::increment_zm_dash_counter( "reached_10", 1 ); return; } } } function init_custom_ai_type() { //wait( 0.1 ); // waittillframeend; if( isDefined( level.custom_ai_type ) ) { for( i = 0; i < level.custom_ai_type.size; i++ ) { [[ level.custom_ai_type[i] ]](); } } } function zombiemode_melee_miss() { if( isDefined( self.enemy.curr_pay_turret ) ) { self.enemy doDamage( GetDvarInt( "ai_meleeDamage" ), self.origin, self, self, "none", "melee" ); } } /*------------------------------------ function chrisp - adding vo to track players ammo ------------------------------------*/ function player_track_ammo_count() { self notify( "stop_ammo_tracking" ); self endon( "disconnect" ); self endon( "stop_ammo_tracking" ); ammoLowCount = 0; ammoOutCount = 0; while ( 1 ) { wait( .5 ); weapon = self getcurrentweapon(); if ( weapon == level.weaponNone || weapon.skiplowammovox ) { continue; } if( weapon.type == "grenade" ) { continue; } if ( self GetAmmoCount( weapon ) > 5 || self laststand::player_is_in_laststand() ) { ammoOutCount = 0; ammoLowCount = 0; continue; } if ( self GetAmmoCount( weapon ) > 0 ) { if ( ammoLowCount < 1 ) { self zm_audio::create_and_play_dialog( "general", "ammo_low" ); ammoLowCount++; } } else { if ( ammoOutCount < 1 ) { wait ( .5 ); if( (self getcurrentweapon() ) !== weapon ) //This prevents "ammo out" vo from playing in the case that we swap a weapon from the box. { continue; } self zm_audio::create_and_play_dialog( "general", "ammo_out" ); ammoOutCount++; } } wait( 20 ); } } /*------------------------------------ function audio plays when more than 1 player connects ------------------------------------*/ function spawn_vo() { //not sure if we need this wait(1); players = GetPlayers(); //just pick a random player for now and play some vo if(players.size > 1) { player = array::random(players); index = zm_utility::get_player_index(player); player thread spawn_vo_player(index,players.size); } } function spawn_vo_player(index,num) { sound = "plr_" + index + "_vox_" + num +"play"; self PlaySoundWithNotify(sound, "sound_done"); self waittill("sound_done"); } function precache_models() { if ( isDefined( level.precacheCustomCharacters ) ) { self [[ level.precacheCustomCharacters ]](); } } function init_shellshocks() { level.player_killed_shellshock = "zombie_death"; } function init_strings() { zm_utility::add_zombie_hint( "undefined", &"ZOMBIE_UNDEFINED" ); // Random Treasure Chest zm_utility::add_zombie_hint( "default_treasure_chest", &"ZOMBIE_RANDOM_WEAPON_COST" ); // Barrier Pieces zm_utility::add_zombie_hint( "default_buy_barrier_piece_10", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_10" ); zm_utility::add_zombie_hint( "default_buy_barrier_piece_20", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_20" ); zm_utility::add_zombie_hint( "default_buy_barrier_piece_50", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_50" ); zm_utility::add_zombie_hint( "default_buy_barrier_piece_100", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_100" ); // REWARD Barrier Pieces zm_utility::add_zombie_hint( "default_reward_barrier_piece", &"ZOMBIE_BUTTON_REWARD_BARRIER" ); // Areas zm_utility::add_zombie_hint( "default_buy_area", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_COST" ); } function init_sounds() { zm_utility::add_sound( "end_of_round", "mus_zmb_round_over" ); 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. zm_utility::add_sound( "chalk_one_up", "mus_zmb_chalk" ); zm_utility::add_sound( "purchase", "zmb_cha_ching" ); zm_utility::add_sound( "no_purchase", "zmb_no_cha_ching" ); // Zombification // TODO need to vary these up zm_utility::add_sound( "playerzombie_usebutton_sound", "zmb_zombie_vocals_attack" ); zm_utility::add_sound( "playerzombie_attackbutton_sound", "zmb_zombie_vocals_attack" ); zm_utility::add_sound( "playerzombie_adsbutton_sound", "zmb_zombie_vocals_attack" ); // Head gib zm_utility::add_sound( "zombie_head_gib", "zmb_zombie_head_gib" ); // Blockers zm_utility::add_sound( "rebuild_barrier_piece", "zmb_repair_boards" ); zm_utility::add_sound( "rebuild_barrier_metal_piece", "zmb_metal_repair" ); zm_utility::add_sound( "rebuild_barrier_hover", "zmb_boards_float" ); zm_utility::add_sound( "debris_hover_loop", "zmb_couch_loop" ); zm_utility::add_sound( "break_barrier_piece", "zmb_break_boards" ); zm_utility::add_sound( "grab_metal_bar", "zmb_bar_pull" ); zm_utility::add_sound( "break_metal_bar", "zmb_bar_break" ); zm_utility::add_sound( "drop_metal_bar", "zmb_bar_drop" ); zm_utility::add_sound("blocker_end_move", "zmb_board_slam"); zm_utility::add_sound( "barrier_rebuild_slam", "zmb_board_slam" ); zm_utility::add_sound( "bar_rebuild_slam", "zmb_bar_repair" ); zm_utility::add_sound( "zmb_rock_fix", "zmb_break_rock_barrier_fix" ); zm_utility::add_sound( "zmb_vent_fix", "evt_vent_slat_repair" ); zm_utility::add_sound ("zmb_barrier_debris_move", "zmb_barrier_debris_move"); // Doors zm_utility::add_sound( "door_slide_open", "zmb_door_slide_open" ); zm_utility::add_sound( "door_rotate_open", "zmb_door_slide_open" ); // Debris zm_utility::add_sound( "debris_move", "zmb_weap_wall" ); // Random Weapon Chest zm_utility::add_sound( "open_chest", "zmb_lid_open" ); zm_utility::add_sound( "music_chest", "zmb_music_box" ); zm_utility::add_sound( "close_chest", "zmb_lid_close" ); // Weapons on walls zm_utility::add_sound( "weapon_show", "zmb_weap_wall" ); zm_utility::add_sound( "break_stone", "evt_break_stone" ); } function init_levelvars() { // Variables // used to a check in last stand for players to become zombies level.is_zombie_level = true; level.default_laststandpistol = GetWeapon( "pistol_standard" ); level.default_solo_laststandpistol = GetWeapon( "pistol_standard_upgraded" ); level.super_ee_weapon = GetWeapon( "pistol_burst" ); level.laststandpistol = level.default_laststandpistol; // so we dont get the uber colt when we're knocked out level.start_weapon = level.default_laststandpistol; level.first_round = true; level.start_round = GetGametypeSetting( "startRound" ); level.round_number = level.start_round; level.enable_magic = GetGametypeSetting( "magic" ); level.headshots_only = GetGametypeSetting( "headshotsonly" ); level.player_starting_points = level.round_number * 500; level.round_start_time = 0; level.pro_tips_start_time = 0; level.intermission = false; level.dog_intermission = false; level.zombie_total = 0; // Total number of zombies left to spawn level.zombie_respawns = 0; // Total number of zombies that need to be respawned due to cleanup level.total_zombies_killed = 0; level.hudelem_count = 0; level.zm_loc_types = []; level.zm_loc_types[ "zombie_location" ] = []; // List of normal zombie spawners (other types will be added in the zone manager) level.zm_variant_type_max = []; level.zm_variant_type_max[ "walk" ] = []; level.zm_variant_type_max[ "run" ] = []; level.zm_variant_type_max[ "sprint" ] = []; level.zm_variant_type_max[ "super_sprint" ] = []; level.zm_variant_type_max[ "walk" ][ "down" ] = 14; level.zm_variant_type_max[ "walk" ][ "up" ] = 16; level.zm_variant_type_max[ "run" ][ "down" ] = 13; level.zm_variant_type_max[ "run" ][ "up" ] = 12; level.zm_variant_type_max[ "sprint" ][ "down" ] = 9; level.zm_variant_type_max[ "sprint" ][ "up" ] = 8; level.zm_variant_type_max[ "super_sprint" ][ "down" ] = 1; level.zm_variant_type_max[ "super_sprint" ][ "up" ] = 1; level.zm_variant_type_max[ "burned" ][ "down" ] = 1; level.zm_variant_type_max[ "burned" ][ "up" ] = 1; level.zm_variant_type_max[ "jump_pad_super_sprint" ][ "down" ] = 1; level.zm_variant_type_max[ "jump_pad_super_sprint" ][ "up" ] = 1; level.current_zombie_array = []; level.current_zombie_count = 0; level.zombie_total_subtract = 0; level.destructible_callbacks = []; foreach( team in level.teams ) { if(!isdefined(level.zombie_vars[ team ]))level.zombie_vars[ team ]=[]; } difficulty = 1; column = int(difficulty) + 1; //####################################################################### // zombie_utility::set_zombie_var( identifier, value, float, column ); // AI 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) zombie_utility::set_zombie_var( "zombie_health_increase_multiplier",0.1, true, column ); // after round 10 multiply the zombies' starting health by this amount zombie_utility::set_zombie_var( "zombie_health_start", 150, false, column ); // starting health of a zombie at round 1 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. zombie_utility::set_zombie_var( "zombie_new_runner_interval", 10, false, column ); // Interval between changing walkers who are too far away into runners 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 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 zombie_utility::set_zombie_var( "zombie_max_ai", 24, false, column ); // Base number of zombies per player (modified by round #) zombie_utility::set_zombie_var( "zombie_ai_per_player", 6, false, column ); // additional zombie modifier for each player in the game zombie_utility::set_zombie_var( "below_world_check", -1000 ); // Check height to see if a zombie has fallen through the world. // Round zombie_utility::set_zombie_var( "spectators_respawn", true ); // Respawn in the spectators in between rounds zombie_utility::set_zombie_var( "zombie_use_failsafe", true ); // Will slowly kill zombies who are stuck zombie_utility::set_zombie_var( "zombie_between_round_time", 10 ); // How long to pause after the round ends zombie_utility::set_zombie_var( "zombie_intermission_time", 15 ); // Length of time to show the end of game stats zombie_utility::set_zombie_var( "game_start_delay", 0, false, column ); // How much time to give people a break before starting spawning // Life and death zombie_utility::set_zombie_var( "player_base_health", 100 ); // Base health of a player zombie_utility::set_zombie_var( "penalty_no_revive", 0.10, true, column ); // Percentage of money you lose if you let a teammate die zombie_utility::set_zombie_var( "penalty_died", 0.0, true, column ); // Percentage of money lost if you die 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 zombie_utility::set_zombie_var( "zombie_score_kill_4player", 50 ); // Individual Points for a zombie kill in a 4 player game zombie_utility::set_zombie_var( "zombie_score_kill_3player", 50 ); // Individual Points for a zombie kill in a 3 player game zombie_utility::set_zombie_var( "zombie_score_kill_2player", 50 ); // Individual Points for a zombie kill in a 2 player game zombie_utility::set_zombie_var( "zombie_score_kill_1player", 50 ); // Individual Points for a zombie kill in a 1 player game zombie_utility::set_zombie_var( "zombie_score_damage_normal", 10 ); // points gained for a hit with a non-automatic weapon zombie_utility::set_zombie_var( "zombie_score_damage_light", 10 ); // points gained for a hit with an automatic weapon zombie_utility::set_zombie_var( "zombie_score_bonus_melee", 80 ); // Bonus points for a melee kill zombie_utility::set_zombie_var( "zombie_score_bonus_head", 50 ); // Bonus points for a head shot kill zombie_utility::set_zombie_var( "zombie_score_bonus_neck", 20 ); // Bonus points for a neck shot kill zombie_utility::set_zombie_var( "zombie_score_bonus_torso", 10 ); // Bonus points for a torso shot kill zombie_utility::set_zombie_var( "zombie_score_bonus_burn", 10 ); // Bonus points for a burn kill zombie_utility::set_zombie_var( "zombie_flame_dmg_point_delay", 500 ); zombie_utility::set_zombie_var( "zombify_player", false ); // Default to not zombify the player till further support if ( IsSplitScreen() ) { zombie_utility::set_zombie_var( "zombie_timer_offset", 280 ); // hud offsets } level thread init_player_levelvars(); level.gamedifficulty = GetGametypeSetting( "zmDifficulty" ); if( level.gamedifficulty == 0 ) //easy { level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier_easy"]; } else //normal { level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier"]; } //Make sure we only have walker zombies in round 1 if ( level.round_number == 1 ) { level.zombie_move_speed = 1; } level.speed_change_max = 0; level.speed_change_num = 0; set_round_number( level.round_number ); } function init_player_levelvars() { level flag::wait_till( "start_zombie_round_logic" ); difficulty = 1; column = int(difficulty) + 1; for(i = 0; i < 8; i ++) { points = 500; if(i > 3) { points = 3000; // Dont change the behavior of grief. } points = zombie_utility::set_zombie_var( ("zombie_score_start_"+ (i+1) +"p"), points, false, column ); } } function init_dvars() { //t6.5todo: move these dvars out of script, dangerous to leave them here like this if( GetDvarString( "zombie_debug" ) == "" ) { SetDvar( "zombie_debug", "0" ); } if( GetDvarString( "scr_zm_enable_bots" ) == "" ) { SetDvar( "scr_zm_enable_bots", "0" ); } if( GetDvarString( "zombie_cheat" ) == "" ) { SetDvar( "zombie_cheat", "0" ); } if ( GetDvarString("zombiemode_debug_zombie_count") == "" ) { SetDvar("zombiemode_debug_zombie_count", "0"); } if ( level.script != "zombie_cod5_prototype" ) { SetDvar( "magic_chest_movable", "1" ); } SetDvar( "revive_trigger_radius", "75" ); SetDvar( "scr_deleteexplosivesonspawn", "0" ); } function init_function_overrides() { level.callbackPlayerDamage = &Callback_PlayerDamage; level.overridePlayerDamage = &player_damage_override; //_cheat; level.callbackPlayerKilled = &player_killed_override; level.playerlaststand_func = &player_laststand; level.callbackPlayerLastStand = &Callback_PlayerLastStand; level.prevent_player_damage = &player_prevent_damage; level.callbackActorKilled = &actor_killed_override; level.callbackActorDamage = &actor_damage_override_wrapper; level.callbackVehicleDamage = &vehicle_damage_override; level.callbackVehicleKilled = &globallogic_vehicle::Callback_VehicleKilled; level.callbackVehicleRadiusDamage = &globallogic_vehicle::Callback_VehicleRadiusDamage; level.custom_introscreen = &zombie_intro_screen; level.custom_intermission = &player_intermission; level.global_damage_func = &zm_spawner::zombie_damage; level.global_damage_func_ads = &zm_spawner::zombie_damage_ads; level.reset_clientdvars = &onPlayerConnect_clientDvars; level.zombie_last_stand = &last_stand_pistol_swap; level.zombie_last_stand_pistol_memory = &last_stand_save_pistol_ammo; level.zombie_last_stand_ammo_return = &last_stand_restore_pistol_ammo; level.player_becomes_zombie = &zombify_player; level.validate_enemy_path_length = &zm_utility::default_validate_enemy_path_length; } function Callback_PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ) { self endon( "disconnect" ); //self Callback("on_player_last_stand"); zm_laststand::PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ); } function CodeCallback_DestructibleEvent( event, param1, param2, param3 ) { if( event == "broken" ) { notify_type = param1; attacker = param2; weapon = param3; if ( IsDefined( level.destructible_callbacks[ notify_type ] ) ) { self thread [[level.destructible_callbacks[ notify_type ]]]( notify_type, attacker ); } self notify( event, notify_type, attacker ); } else if( event == "breakafter" ) { piece = param1; time = param2; damage = param3; self thread breakAfter( time, damage, piece ); } } function breakAfter( time, damage, piece ) { self notify( "breakafter" ); self endon( "breakafter" ); wait time; // this does not work in mp. DoDamage does not take a piece for mp. self dodamage( damage, self.origin, undefined, /*piece*/undefined ); } function Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal ) { startedInLastStand = 0; if ( isPlayer(self) ) { startedInLastStand = self laststand::player_is_in_laststand(); } /# println( "ZM Callback_PlayerDamage"+iDamage+"\n"); #/ if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && (eAttacker.sessionteam == self.sessionteam) && !eAttacker HasPerk( "specialty_playeriszombie" ) && !( isdefined( self.is_zombie ) && self.is_zombie ) ) { self process_friendly_fire_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex ); if ( self != eAttacker ) { //one player shouldn't damage another player, grenades, airstrikes called in by another player /# println("Exiting - players can't hurt each other."); #/ return; } else if ( sMeansOfDeath != "MOD_GRENADE_SPLASH" && sMeansOfDeath != "MOD_GRENADE" && sMeansOfDeath != "MOD_EXPLOSIVE" && sMeansOfDeath != "MOD_PROJECTILE" && sMeansOfDeath != "MOD_PROJECTILE_SPLASH" && sMeansOfDeath != "MOD_BURNED" && sMeansOfDeath != "MOD_SUICIDE" ) { /# println("Exiting - damage type verbotten."); #/ //player should be able to damage they're selves with grenades and stuff //otherwise don't damage the player, so like airstrikes won't kill the player return; } } // Notify the player of a zombie swipe if the persistent Insta Kill upgrade is active if( ( isdefined( level.pers_upgrade_insta_kill ) && level.pers_upgrade_insta_kill ) ) { self zm_pers_upgrades_functions::pers_insta_kill_melee_swipe( sMeansOfDeath, eAttacker ); } if( IsDefined( self.overridePlayerDamage ) ) { iDamage = self [[self.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); } else if( IsDefined( level.overridePlayerDamage ) ) { iDamage = self [[level.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); } Assert(IsDefined(iDamage), "You must return a value from a damage override function."); // self Callback("on_player_damage"); if (( isdefined( self.magic_bullet_shield ) && self.magic_bullet_shield )) { // save out and restore the maxHealth, because setting health below modifies it maxHealth = self.maxHealth; // increase health by damage, because it will be subtracted back out below in finishActorDamage self.health += iDamage; // restore the maxHealth to what it was self.maxHealth = maxHealth; } // DtP: When player is diving to prone away from the grenade, the damage is reduced // player is diving if( isdefined( self.divetoprone ) && self.divetoprone == 1 ) { // grenade splash damage if( sMeansOfDeath == "MOD_GRENADE_SPLASH" ) { // if the player is at least 32 units away dist = Distance2d(vPoint, self.origin); if( dist > 32 ) { // if player is diving away dot_product = vectordot( AnglesToForward( self.angles ), vDir ); if( dot_product > 0 ) { // grenade is behind player iDamage = int( iDamage * 0.5 ); // halves damage } } } } /# println("CB PD"); #/ // players can only hurt themselves, zombie players can hurt any other player and be hurt by human players /* if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && !eAttacker HasPerk( "specialty_playeriszombie" ) && !IS_TRUE( self.is_zombie ) ) { if ( self != eAttacker ) { //one player shouldn't damage another player, grenades, airstrikes called in by another player println("Exiting - players can't hurt each other."); return; } else if ( sMeansOfDeath != "MOD_GRENADE_SPLASH" && sMeansOfDeath != "MOD_GRENADE" && sMeansOfDeath != "MOD_EXPLOSIVE" && sMeansOfDeath != "MOD_PROJECTILE" && sMeansOfDeath != "MOD_PROJECTILE_SPLASH" && sMeansOfDeath != "MOD_BURNED" && sMeansOfDeath != "MOD_SUICIDE" ) { println("Exiting - damage type verbotten."); //player should be able to damage they're selves with grenades and stuff //otherwise don't damage the player, so like airstrikes won't kill the player return; } }*/ if ( isdefined( level.prevent_player_damage ) ) { if ( self [[ level.prevent_player_damage ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ) ) { return; } } iDFlags = iDFlags | level.iDFLAGS_NO_KNOCKBACK; //damage should have been reduced to 0 if it really was a riotshield hit if( iDamage > 0 && sHitLoc == "riotshield" ) { sHitLoc = "torso_upper"; } /# PrintLn("Finishplayerdamage wrapper."); #/ wasDowned = 0; if ( isPlayer(self)) { wasDowned = !startedInLastStand && self laststand::player_is_in_laststand(); } /# if(IsDefined(eAttacker)) { Record3DText( "D:" + iDamage + " H: " + self.health + " A: " + eAttacker GetEntityNumber(), self.origin, ( 1, 0, 0 ), "Script", self ); } else { Record3DText( "D:" + iDamage + " H: " + self.health + " A: undefined", self.origin, ( 1, 0, 0 ), "Script", self ); } #/ self finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal ); bb::logdamage(eattacker, self, weapon, idamage, smeansofdeath, shitloc, self.Health <= 0, wasDowned); } function finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal ) { self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal ); // the MP version of finishPlayerDamage does not take 11 parameters // the 11 parameter version in SP does not take these parameters (10 is modelIndex and 11 is pOffsetTime) //surface = "flesh"; //self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, surface ); } function register_player_friendly_fire_callback( callback ) { if (!isdefined(level.player_friendly_fire_callbacks)) level.player_friendly_fire_callbacks = []; level.player_friendly_fire_callbacks[level.player_friendly_fire_callbacks.size] = callback; } function process_friendly_fire_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex ) { if (isdefined(level.player_friendly_fire_callbacks)) { foreach( callback in level.player_friendly_fire_callbacks ) { self [[callback]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex ); } } } function init_flags() { level flag::init( "solo_game" ); level flag::init( "start_zombie_round_logic" ); level flag::init( "start_encounters_match_logic" ); level flag::init( "spawn_point_override" ); level flag::init( "crawler_round" ); level flag::init( "spawn_zombies", true ); level flag::init( "special_round" ); level flag::init( "dog_round" ); level flag::init( "raps_round" ); level flag::init( "begin_spawning" ); level flag::init( "end_round_wait" ); level flag::init( "wait_and_revive" ); level flag::init( "instant_revive" ); level flag::init( "initial_blackscreen_passed" ); level flag::init( "initial_players_connected" ); level flag::init( "power_on" ); //DCS: this will init all zone controlling power switch flags. power_trigs = GetEntArray( "use_elec_switch", "targetname" ); foreach(trig in power_trigs) { if(IsDefined(trig.script_int)) { level flag::init("power_on" + trig.script_int); } } } function init_client_field_callback_funcs() { // Client fields for actors clientfield::register("actor", "zombie_riser_fx", 1, 1, "int"); if ( ( isdefined( level.use_water_risers ) && level.use_water_risers ) ) { clientfield::register("actor", "zombie_riser_fx_water", 1, 1, "int"); } if ( ( isdefined( level.use_foliage_risers ) && level.use_foliage_risers ) ) { clientfield::register("actor", "zombie_riser_fx_foliage", 1, 1, "int"); } if ( ( isdefined( level.use_low_gravity_risers ) && level.use_low_gravity_risers ) ) { clientfield::register("actor", "zombie_riser_fx_lowg", 1, 1, "int"); } clientfield::register("actor", "zombie_has_eyes", 1, 1, "int"); clientfield::register("actor", "zombie_ragdoll_explode", 1, 1, "int"); clientfield::register("actor", "zombie_gut_explosion", 1, 1, "int"); clientfield::register("actor", "sndZombieContext", (0 - 1), 1, "int"); clientfield::register("actor", "zombie_keyline_render", 1, 1, "int"); bits = 4; trigs = GetEntArray( "use_elec_switch", "targetname" ); if ( IsDefined( trigs ) ) { bits = GetMinBitCountForNum( trigs.size + 1 ); } clientfield::register("world", "zombie_power_on", 1, bits, "int"); clientfield::register("world", "zombie_power_off", 1, bits, "int"); clientfield::register("world", "round_complete_time", 1, 20, "int"); clientfield::register("world", "round_complete_num", 1, 8, "int"); clientfield::register("world", "game_end_time", 1, 20, "int"); clientfield::register("world", "quest_complete_time", 1, 20, "int"); clientfield::register("world", "game_start_time", 15001, 20, "int" ); } function init_fx() { level.createfx_callback_thread = &delete_in_createfx; // level._effect["wood_chunk_destory"] = "_t6/impacts/fx_large_woodhit" ; level._effect["fx_zombie_bar_break"] = "_t6/maps/zombie/fx_zombie_bar_break"; level._effect["fx_zombie_bar_break_lite"] = "_t6/maps/zombie/fx_zombie_bar_break_lite"; if ( !( isdefined( level.FX_exclude_edge_fog ) && level.FX_exclude_edge_fog ) ) { level._effect["edge_fog"] = "_t6/maps/zombie/fx_fog_zombie_amb"; } level._effect["chest_light"] = "zombie/fx_weapon_box_open_glow_zmb"; level._effect["chest_light_closed"] = "zombie/fx_weapon_box_closed_glow_zmb"; if ( !( isdefined( level.FX_exclude_default_eye_glow ) && level.FX_exclude_default_eye_glow ) ) { level._effect["eye_glow"] = "zombie/fx_glow_eye_orange"; } level._effect["headshot"] = "zombie/fx_bul_flesh_head_fatal_zmb"; level._effect["headshot_nochunks"] = "zombie/fx_bul_flesh_head_nochunks_zmb"; level._effect["bloodspurt"] = "zombie/fx_bul_flesh_neck_spurt_zmb"; if ( !( isdefined( level.FX_exclude_tesla_head_light ) && level.FX_exclude_tesla_head_light ) ) { level._effect["tesla_head_light"] = "_t6/maps/zombie/fx_zombie_tesla_neck_spurt"; } level._effect["zombie_guts_explosion"] = "zombie/fx_blood_torso_explo_lg_zmb"; level._effect["rise_burst_water"] = "zombie/fx_spawn_dirt_hand_burst_zmb"; level._effect["rise_billow_water"] = "zombie/fx_spawn_dirt_body_billowing_zmb"; level._effect["rise_dust_water"] = "zombie/fx_spawn_dirt_body_dustfalling_zmb"; level._effect["rise_burst"] = "zombie/fx_spawn_dirt_hand_burst_zmb"; level._effect["rise_billow"] = "zombie/fx_spawn_dirt_body_billowing_zmb"; level._effect["rise_dust"] = "zombie/fx_spawn_dirt_body_dustfalling_zmb"; level._effect["fall_burst"] = "zombie/fx_spawn_dirt_hand_burst_zmb"; level._effect["fall_billow"] = "zombie/fx_spawn_dirt_body_billowing_zmb"; level._effect["fall_dust"] = "zombie/fx_spawn_dirt_body_dustfalling_zmb"; // Flamethrower level._effect["character_fire_death_sm"] = "zombie/fx_fire_torso_zmb"; level._effect["character_fire_death_torso"] = "zombie/fx_fire_torso_zmb"; if ( !( isdefined( level.fx_exclude_default_explosion ) && level.fx_exclude_default_explosion ) ) { level._effect["def_explosion"] = "_t6/explosions/fx_default_explosion"; } // level._effect["betty_explode"] = "_t6/weapon/bouncing_betty/fx_explosion_betty_generic"; // level._effect["default_weapon_glow"] = "_t6/maps/zombie/fx_zmb_tranzit_weapon_glow"; if ( !( isdefined( level.disable_fx_upgrade_aquired ) && level.disable_fx_upgrade_aquired ) ) { level._effect["upgrade_aquired"] = "_t6/maps/zombie/fx_zmb_tanzit_upgrade"; } } // Handles the intro screen function zombie_intro_screen( string1, string2, string3, string4, string5 ) { level flag::wait_till( "start_zombie_round_logic" ); } function players_playing() { // initialize level.players_playing players = GetPlayers(); level.players_playing = players.size; wait( 20 ); players = GetPlayers(); level.players_playing = players.size; } // // NETWORK SECTION ====================================================================== // // function onPlayerConnect_clientDvars() { self SetClientCompass( 0 ); self SetClientThirdPerson( 0 ); self resetFov(); self SetClientThirdPersonAngle( 0 ); self SetClientUIVisibilityFlag( "weapon_hud_visible", 1 ); self SetClientMiniScoreboardHide( 1 ); self SetClientHUDHardcore( 0 ); self SetClientPlayerPushAmount( 1 ); self SetDepthOfField( 0, 0, 512, 4000, 4, 0 ); self zm_laststand::player_getup_setup(); } function checkForAllDead(excluded_player) { players = GetPlayers(); count = 0; for( i = 0; i < players.size; i++ ) { if(isDefined(excluded_player) && excluded_player == players[i]) { continue; } if( !(players[i] laststand::player_is_in_laststand()) && !(players[i].sessionstate == "spectator") ) { count++; } } if( count==0 && !( isdefined( level.no_end_game_check ) && level.no_end_game_check ) ) { level notify( "end_game" ); } } // // Runs when the player spawns into the map // self is the player.surprise! // function onPlayerSpawned() { self endon( "disconnect" ); self notify("stop_onPlayerSpawned"); self endon("stop_onPlayerSpawned"); for( ;; ) { self waittill( "spawned_player" ); if(!( isdefined( level.host_ended_game ) && level.host_ended_game )) { self freezecontrols( false ); /# println(" Unfreeze controls 7"); #/ } self.hits = 0; self zm_utility::init_player_offhand_weapons(); lethal_grenade = self zm_utility::get_player_lethal_grenade(); if( !self HasWeapon( lethal_grenade ) ) { self GiveWeapon( lethal_grenade ); self SetWeaponAmmoClip( lethal_grenade, 0 ); } self RecordPlayerReviveZombies( self ); /# if ( GetDvarInt( "zombie_cheat" ) >= 1 && GetDvarInt( "zombie_cheat" ) <= 3 ) { self EnableInvulnerability(); } #/ self SetActionSlot( 3, "altMode" ); self PlayerKnockback( false ); self SetClientThirdPerson( 0 ); self resetFov(); self SetClientThirdPersonAngle( 0 ); self SetDepthOfField( 0, 0, 512, 4000, 4, 0 ); self cameraactivate(false); self.num_perks = 0; self.on_lander_last_stand = undefined; self setblur(0, 0.1); self.zmbDialogQueue = []; self.zmbDialogActive = false; self.zmbDialogGroups = []; self.zmbDialogGroup = ""; if ( ( isdefined( level.player_out_of_playable_area_monitor ) && level.player_out_of_playable_area_monitor ) ) { self thread player_out_of_playable_area_monitor(); } if ( ( isdefined( level.player_too_many_weapons_monitor ) && level.player_too_many_weapons_monitor ) ) { self thread [[level.player_too_many_weapons_monitor_func]](); } if ( ( isdefined( level.player_too_many_players_check ) && level.player_too_many_players_check ) ) { level thread [[level.player_too_many_players_check_func]](); } self.disabled_perks = []; if( isdefined( self.player_initialized ) ) { if( self.player_initialized == false ) { self.player_initialized = true; //t6.5todo self freezecontrols( true ); // first spawn only, intro_black_screen will pull them out of it self giveweapon( self zm_utility::get_player_lethal_grenade() ); self setweaponammoclip( self zm_utility::get_player_lethal_grenade(), 0); self SetClientUIVisibilityFlag( "weapon_hud_visible", 1 ); self SetClientMiniScoreboardHide( 0 ); // ww: set the is_drinking variable self.is_drinking = 0; self thread player_zombie_breadcrumb(); self thread player_monitor_travel_dist(); self thread player_monitor_time_played(); if(isDefined(level.custom_player_track_ammo_count)) { self thread [[level.custom_player_track_ammo_count]](); } else { self thread player_track_ammo_count(); } self thread zm_utility::shock_onpain(); self thread player_grenade_watcher(); self laststand::revive_hud_create(); if(isDefined(level.zm_gamemodule_spawn_func)) { self thread [[level.zm_gamemodule_spawn_func]](); } self thread player_spawn_protection(); if(!isDefined(self.lives)) { self.lives = 0; } } } } } function player_spawn_protection() { self endon("disconnect"); self zm_utility::increment_ignoreme(); x = 0; while( x < 60 ) { x++; wait(.05); } self zm_utility::decrement_ignoreme(); } function spawn_life_brush( origin, radius, height ) { life_brush = spawn( "trigger_radius", origin, 0, radius, height ); life_brush.script_noteworthy = "life_brush"; return life_brush; } function in_life_brush() { life_brushes = getentarray( "life_brush", "script_noteworthy" ); if ( !IsDefined( life_brushes ) ) { return false; } for ( i = 0; i < life_brushes.size; i++ ) { if ( self IsTouching( life_brushes[i] ) ) { return true; } } return false; } function spawn_kill_brush( origin, radius, height ) { kill_brush = spawn( "trigger_radius", origin, 0, radius, height ); kill_brush.script_noteworthy = "kill_brush"; return kill_brush; } function in_kill_brush() { kill_brushes = getentarray( "kill_brush", "script_noteworthy" ); self.kill_brush = undefined; if ( !IsDefined( kill_brushes ) ) { return false; } for ( i = 0; i < kill_brushes.size; i++ ) { if ( self IsTouching( kill_brushes[i] ) ) { self.kill_brush = kill_brushes[i]; return true; } } return false; } function in_enabled_playable_area() { zm_zonemgr::wait_zone_flags_updating(); playable_area = getentarray( "player_volume", "script_noteworthy" ); if( !IsDefined( playable_area ) ) { return false; } for ( i = 0; i < playable_area.size; i++ ) { if ( zm_zonemgr::zone_is_enabled( playable_area[i].targetname ) && self IsTouching( playable_area[i] ) ) { return true; } } return false; } function get_player_out_of_playable_area_monitor_wait_time() { /# if ( ( isdefined( level.check_kill_thread_every_frame ) && level.check_kill_thread_every_frame ) ) { return 0.05; } #/ return 3; } function player_out_of_playable_area_monitor() { self notify( "stop_player_out_of_playable_area_monitor" ); self endon( "stop_player_out_of_playable_area_monitor" ); self endon( "disconnect" ); level endon( "end_game" ); while(!isDefined(self.characterindex)) { wait(.05); } // load balancing wait( (0.15 * self.characterindex) ); while ( true ) { // skip over players in spectate, otherwise Sam keeps laughing every 3 seconds since their corpse is still invisibly in a kill area if ( self.sessionstate == "spectator" ) { wait( get_player_out_of_playable_area_monitor_wait_time() ); continue; } if(( isdefined( level.hostmigration_occured ) && level.hostmigration_occured )) { wait( get_player_out_of_playable_area_monitor_wait_time() ); continue; } if ( !self in_life_brush() && (self in_kill_brush() || !self in_enabled_playable_area() || ( isdefined(level.player_out_of_playable_area_override) && ( isdefined( self [[level.player_out_of_playable_area_override]]() ) && self [[level.player_out_of_playable_area_override]]() ) ) ) ) { if ( !isdefined( level.player_out_of_playable_area_monitor_callback ) || self [[level.player_out_of_playable_area_monitor_callback]]() ) { /# if ( ( isdefined( level.kill_thread_test_mode ) && level.kill_thread_test_mode ) ) { PrintTopRightln( "out of playable area: " + self.origin ); wait( get_player_out_of_playable_area_monitor_wait_time() ); continue; } if ( self isinmovemode( "ufo", "noclip" ) || ( isdefined( level.disable_kill_thread ) && level.disable_kill_thread ) || GetDvarInt( "zombie_cheat" ) > 0 ) { wait( get_player_out_of_playable_area_monitor_wait_time() ); continue; } #/ //track the cheaters self zm_stats::increment_map_cheat_stat( "cheat_out_of_playable" ); self zm_stats::increment_client_stat( "cheat_out_of_playable",false ); self zm_stats::increment_client_stat( "cheat_total",false ); self playlocalsound( level.zmb_laugh_alias ); wait( 0.5 ); if ( GetPlayers().size == 1 && level flag::get( "solo_game" ) && ( isdefined( self.waiting_to_revive ) && self.waiting_to_revive ) ) { level notify( "end_game" ); } else { self DisableInvulnerability(); self.lives = 0; self dodamage( self.health + 1000, self.origin ); self.bleedout_time = 0; } } } wait( get_player_out_of_playable_area_monitor_wait_time() ); } } function get_player_too_many_weapons_monitor_wait_time() { return 3; } function player_too_many_weapons_monitor_takeaway_simultaneous( primary_weapons_to_take ) { self endon( "player_too_many_weapons_monitor_takeaway_sequence_done" ); self util::waittill_any( "player_downed", "replace_weapon_powerup" ); for ( i = 0; i < primary_weapons_to_take.size; i++ ) { self TakeWeapon( primary_weapons_to_take[i] ); } self zm_score::player_reduce_points( "take_all" ); self zm_utility::give_start_weapon( false ); if ( !self laststand::player_is_in_laststand() ) { self zm_utility::decrement_is_drinking(); } else if ( level flag::get( "solo_game" ) ) { self.score_lost_when_downed = 0; } self notify( "player_too_many_weapons_monitor_takeaway_sequence_done" ); } function player_too_many_weapons_monitor_takeaway_sequence( primary_weapons_to_take ) { self thread player_too_many_weapons_monitor_takeaway_simultaneous( primary_weapons_to_take ); self endon( "player_downed" ); self endon( "replace_weapon_powerup" ); self zm_utility::increment_is_drinking(); score_decrement = zm_utility::round_up_to_ten( int( self.score / (primary_weapons_to_take.size + 1) ) ); for ( i = 0; i < primary_weapons_to_take.size; i++ ) { self playlocalsound( level.zmb_laugh_alias ); self SwitchToWeapon( primary_weapons_to_take[i] ); self zm_score::player_reduce_points( "take_specified", score_decrement ); wait( 3 ); self TakeWeapon( primary_weapons_to_take[i] ); } self playlocalsound( level.zmb_laugh_alias ); self zm_score::player_reduce_points( "take_all" ); wait( 1 ); self zm_utility::give_start_weapon( true ); self zm_utility::decrement_is_drinking(); self notify( "player_too_many_weapons_monitor_takeaway_sequence_done" ); } function player_too_many_weapons_monitor() { self notify( "stop_player_too_many_weapons_monitor" ); self endon( "stop_player_too_many_weapons_monitor" ); self endon( "disconnect" ); level endon( "end_game" ); // load balancing scalar = self.characterindex; if ( !isdefined( scalar ) ) { scalar = self GetEntityNumber(); } wait( (0.15 * scalar) ); while ( true ) { if ( self zm_utility::has_powerup_weapon() || self laststand::player_is_in_laststand() || self.sessionstate == "spectator" || isdefined( self.laststandpistol ) ) { wait( get_player_too_many_weapons_monitor_wait_time() ); continue; } /# if ( GetDvarInt( "zombie_cheat" ) > 0 ) { wait( get_player_too_many_weapons_monitor_wait_time() ); continue; } #/ weapon_limit = zm_utility::get_player_weapon_limit( self ); primaryWeapons = self GetWeaponsListPrimaries(); if ( primaryWeapons.size > weapon_limit ) { self zm_weapons::take_fallback_weapon(); primaryWeapons = self GetWeaponsListPrimaries(); } primary_weapons_to_take = []; for ( i = 0; i < primaryWeapons.size; i++ ) { if ( zm_weapons::is_weapon_included( primaryWeapons[i] ) || zm_weapons::is_weapon_upgraded( primaryWeapons[i] ) ) { primary_weapons_to_take[primary_weapons_to_take.size] = primaryWeapons[i]; } } if ( primary_weapons_to_take.size > weapon_limit ) { if ( !isdefined( level.player_too_many_weapons_monitor_callback ) || self [[level.player_too_many_weapons_monitor_callback]]( primary_weapons_to_take ) ) { //track the cheaters self zm_stats::increment_map_cheat_stat( "cheat_too_many_weapons" ); self zm_stats::increment_client_stat( "cheat_too_many_weapons",false ); self zm_stats::increment_client_stat( "cheat_total",false ); self thread player_too_many_weapons_monitor_takeaway_sequence( primary_weapons_to_take ); self waittill( "player_too_many_weapons_monitor_takeaway_sequence_done" ); } } wait( get_player_too_many_weapons_monitor_wait_time() ); } } function player_monitor_travel_dist() { self endon("disconnect"); self notify("stop_player_monitor_travel_dist"); self endon("stop_player_monitor_travel_dist"); prevpos = self.origin; while(1) { wait .1; self.pers["distance_traveled"] += distance( self.origin, prevpos ) ; prevpos = self.origin; } } function player_monitor_time_played() { self endon( "disconnect" ); self notify("stop_player_monitor_time_played"); self endon("stop_player_monitor_time_played"); level flag::wait_till( "start_zombie_round_logic" ); for ( ;; ) { wait ( 1.0 ); zm_stats::increment_client_stat( "time_played_total" ); } } function player_grenade_multiattack_bookmark_watcher( grenade ) { self endon( "disconnect" ); waittillframeend; if ( !IsDefined( grenade ) ) { return; } inflictorEntNum = grenade getEntityNumber(); inflictorEntType = grenade getEntityType(); inflictorBirthTime = 0; if ( isDefined( grenade.birthTime ) ) inflictorBirthTime = grenade.birthTime; ret_val = grenade util::waittill_any_ex( 15, "explode", "death", self, "disconnect" ); if ( !IsDefined( self ) || (IsDefined( ret_val ) && "timeout" == ret_val) ) { return; } self.grenade_multiattack_count = 0; self.grenade_multiattack_ent = undefined; self.grenade_multikill_count = 0; // Black Ops 3 - TU1 Fix; track multikill count in addition to multiattack, for the Five-for-One Challenge waittillframeend; if ( !IsDefined( self ) ) { return; } count = level.grenade_multiattack_bookmark_count; if ( ( isdefined( grenade.grenade_multiattack_bookmark_count ) && grenade.grenade_multiattack_bookmark_count ) ) { count = grenade.grenade_multiattack_bookmark_count; } bookmark_string = "zm_player_grenade_multiattack"; if ( ( isdefined( grenade.use_grenade_special_long_bookmark ) && grenade.use_grenade_special_long_bookmark ) ) { bookmark_string = "zm_player_grenade_special_long"; } else if ( ( isdefined( grenade.use_grenade_special_bookmark ) && grenade.use_grenade_special_bookmark ) ) { bookmark_string = "zm_player_grenade_special"; } if ( count <= self.grenade_multiattack_count && IsDefined( self.grenade_multiattack_ent ) ) { addDemoBookmark( bookmark_string, gettime(), self GetEntityNumber(), 255, 0, inflictorEntNum, inflictorEntType, inflictorBirthTime, false, self.grenade_multiattack_ent GetEntityNumber() ); } if ( 5 <= self.grenade_multikill_count ) // Black Ops 3 - TU1 Fix; track multikill count in addition to multiattack, for the Five-for-One Challenge { self zm_stats::increment_challenge_stat( "ZOMBIE_HUNTER_EXPLOSION_MULTIKILL" ); } self.grenade_multiattack_count = 0; self.grenade_multikill_count = 0; // Black Ops 3 - TU1 Fix; track multikill count in addition to multiattack, for the Five-for-One Challenge } function player_grenade_watcher() { self endon( "disconnect" ); self notify("stop_player_grenade_watcher"); self endon("stop_player_grenade_watcher"); self.grenade_multiattack_count = 0; 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. while ( 1 ) { self waittill( "grenade_fire", grenade, weapon ); if( isdefined( grenade ) && isalive( grenade ) ) { grenade.team = self.team; } self thread player_grenade_multiattack_bookmark_watcher( grenade ); if ( isdefined( level.grenade_watcher ) ) { self [[ level.grenade_watcher ]]( grenade, weapon ); } } } function player_prevent_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ) { if( !isdefined( eInflictor ) || !isdefined( eAttacker ) ) { return false; } if ( eInflictor == self || eAttacker == self ) { return false; } if ( isdefined( eInflictor ) && isdefined( eInflictor.team ) ) { if (!( isdefined( eInflictor.damage_own_team ) && eInflictor.damage_own_team )) if ( eInflictor.team == self.team ) { return true; } } return false; } // // Keep track of players going down and getting revived function player_revive_monitor() { self endon( "disconnect" ); self notify("stop_player_revive_monitor"); self endon("stop_player_revive_monitor"); while (1) { self waittill( "player_revived", reviver ); self playsoundtoplayer( "zmb_character_revived", self ); if(( isdefined( level.isresetting_grief ) && level.isresetting_grief )) { continue; } //self laststand_giveback_player_perks(); if ( IsDefined(reviver) ) { if( reviver != self ) { if( math::cointoss() ) self zm_audio::create_and_play_dialog( "general", "revive_up" ); else reviver zm_audio::create_and_play_dialog( "general", "revive_support" ); } else { self zm_audio::create_and_play_dialog( "general", "revive_up" ); } //reviver maps\_zombiemode_rank::giveRankXp( "revive" ); //maps\_zombiemode_challenges::doMissionCallback( "zm_revive", reviver ); // Check to see how much money you lost from being down. points = self.score_lost_when_downed; if ( !isdefined( points ) ) { points = 0; } /# println( "ZM >> LAST STAND - points = " + points); #/ reviver zm_score::player_add_points( "reviver", points ); self.score_lost_when_downed = 0; if ( IsPlayer( reviver ) && reviver != self ) { reviver zm_stats::increment_challenge_stat( "SURVIVALIST_REVIVE" ); } } } } // self = a player // If the player has just 1 perk, they wil always get it back // If the player has more than 1 perk, they will lose a single perk function laststand_giveback_player_perks() { if ( IsDefined( self.laststand_perks ) ) { // Calculate a lost perk index lost_perk_index = int( -1 ); if( self.laststand_perks.size > 1 ) { lost_perk_index = RandomInt( self.laststand_perks.size-1 ); } // Give the player back their perks for ( i=0; i> LAST STAND - player_laststand called" ); #/ b_alt_visionset = false; self AllowJump(false); currWeapon = self GetCurrentWeapon(); self AddWeaponStat( currWeapon, "deathsDuringUse", 1 ); // Grab the perks if we have the player persistent ability "perk lose" if( ( isdefined( self.pers_upgrades_awarded["perk_lose"] ) && self.pers_upgrades_awarded["perk_lose"] ) ) { self zm_pers_upgrades_functions::pers_upgrade_perk_lose_save(); } players = GetPlayers(); if ( players.size == 1 && level flag::get( "solo_game" ) ) { if ( self.lives > 0 && self HasPerk("specialty_quickrevive") ) { self thread wait_and_revive(); } } self zm_utility::clear_is_drinking(); self thread remote_revive_watch(); self zm_score::player_downed_penalty(); // 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 self DisableOffhandWeapons(); self thread last_stand_grenade_save_and_return(); if( sMeansOfDeath != "MOD_SUICIDE" && sMeansOfDeath != "MOD_FALLING" ) { if( !( isdefined( self.intermission ) && self.intermission ) ) self zm_audio::create_and_play_dialog( "general", "revive_down" ); else { if(isDefined(level.custom_player_death_vo_func) && !self [[level.custom_player_death_vo_func]]() ) { self zm_audio::create_and_play_dialog( "general", "exert_death" ); } } } if( IsDefined( level._zombie_minigun_powerup_last_stand_func ) ) { self thread [[level._zombie_minigun_powerup_last_stand_func]](); } if( IsDefined( level._zombie_tesla_powerup_last_stand_func ) ) { self thread [[level._zombie_tesla_powerup_last_stand_func]](); } if ( self HasPerk( "specialty_electriccherry" ) ) { b_alt_visionset = true; if ( IsDefined( level.custom_laststand_func ) ) { self thread [[ level.custom_laststand_func ]](); } } if( IsDefined( self.intermission ) && self.intermission ) { //maps\_zombiemode_challenges::doMissionCallback( "playerDied", self ); wait(.5); self stopsounds(); level waittill( "forever" ); } if ( !( b_alt_visionset ) ) { visionset_mgr::activate( "visionset", "zombie_last_stand", self, 1 ); } } function failsafe_revive_give_back_weapons(excluded_player) { for ( i = 0; i < 10; i++ ) { {wait(.05);}; players = GetPlayers(); foreach(player in players ) { if (player == excluded_player|| !isdefined( player.reviveProgressBar ) || player zm_laststand::is_reviving_any() ) { continue; } // he's not reviving anyone but he still has revive stuff up, clean it all up /# iprintlnbold( "FAILSAFE CLEANING UP REVIVE HUD AND GUN" ); #/ // pass in "none" since we have no idea what the weapon they should be showing is player zm_laststand::revive_give_back_weapons( level.weaponNone ); if ( isdefined( player.reviveProgressBar ) ) { player.reviveProgressBar hud::destroyElem(); } if ( isdefined( player.reviveTextHud ) ) { player.reviveTextHud destroy(); } } } } function set_intermission_point() { points =struct::get_array( "intermission", "targetname" ); if( points.size < 1 ) { return; } points = array::randomize( points ); point = points[0]; SetDemoIntermissionPoint( point.origin, point.angles ); } function spawnSpectator() { self endon( "disconnect" ); self endon( "spawned_spectator" ); self notify( "spawned" ); self notify( "end_respawn" ); if( level.intermission ) { return; } if( IsDefined( level.no_spectator ) && level.no_spectator ) { wait( 3 ); ExitLevel(); } // The check_for_level_end looks for this self.is_zombie = true; //failsafe against losing viewarms due to the thread returning them getting an endon from "zombified" level thread failsafe_revive_give_back_weapons(self); // Remove all reviving abilities self notify ( "zombified" ); if( isdefined( self.revivetrigger ) ) { self.revivetrigger delete(); self.revivetrigger = undefined; } self.zombification_time = GetTime(); //set time when player died resetTimeout(); // Stop shellshock and rumble self StopShellshock(); self StopRumble( "damage_heavy" ); self.sessionstate = "spectator"; self.spectatorclient = -1; self.maxhealth = self.health; self.shellshocked = false; self.inWater = false; self.friendlydamage = undefined; self.hasSpawned = true; self.spawnTime = GetTime(); self.afk = false; /# println( "*************************Zombie Spectator***" ); #/ self detachAll(); if( isdefined( level.custom_spectate_permissions ) ) { self [[level.custom_spectate_permissions]](); } else { self setSpectatePermissions( true ); } self thread spectator_thread(); self Spawn( self.origin, self.angles ); self notify( "spawned_spectator" ); } function setSpectatePermissions( isOn ) { self AllowSpectateTeam( "allies", isOn && self.team == "allies" ); self AllowSpectateTeam( "axis", isOn && self.team == "axis" ); self AllowSpectateTeam( "freelook", false ); self AllowSpectateTeam( "none", false ); } function spectator_thread() { self endon( "disconnect" ); self endon( "spawned_player" ); /* we are not currently supporting the shared screen tech if( self IsSplitScreen() ) { last_alive = undefined; players = GetPlayers(); for( i = 0; i < players.size; i++ ) { if( !players[i].is_zombie ) { last_alive = players[i]; } } share_screen( last_alive, true ); return; } */ // self thread spectator_toggle_3rd_person(); } function spectator_toggle_3rd_person() { self endon( "disconnect" ); self endon( "spawned_player" ); third_person = true; self set_third_person( true ); } function set_third_person( value ) { if( value ) { self SetClientThirdPerson( 1 ); self SetClientThirdPersonAngle( 354 ); self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 ); } else { self SetClientThirdPerson( 0 ); self SetClientThirdPersonAngle( 0 ); self setDepthOfField( 0, 0, 512, 4000, 4, 0 ); } self resetFov(); } function last_stand_revive() { level endon( "between_round_over" ); players = GetPlayers(); //If everyone is in last stand or spectate then revive all laststand_count = 0; foreach(player in players) { if( !zm_utility::is_player_valid( player ) ) { laststand_count ++; } } if( laststand_count == players.size ) { for ( i = 0; i < players.size; i++ ) { if ( players[i] laststand::player_is_in_laststand() && players[i].revivetrigger.beingRevived == 0 ) { players[i] zm_laststand::auto_revive( players[i] ); } } } } // ww: arrange the last stand pistols so when it come time to choose which one they are inited function last_stand_pistol_rank_init() { level.pistol_values = []; // ww: in a solo game the ranking of the pistols is a bit different based on the upgraded 1911 swap // any pistol ranked level.pistol_value_solo_replace_below or lower will be ignored and the player will be given the upgraded 1911 level.pistol_values[ level.pistol_values.size ] = level.default_laststandpistol; level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_burst" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_fullauto" ); level.pistol_value_solo_replace_below = level.pistol_values.size-1; // EO: anything scoring lower than this should be replaced level.pistol_values[ level.pistol_values.size ] = level.default_solo_laststandpistol; level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_burst_upgraded" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "pistol_fullauto_upgraded" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "ray_gun" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark2" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "ray_gun_upgraded" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark2_upgraded" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark3" ); level.pistol_values[ level.pistol_values.size ] = GetWeapon( "raygun_mark3_upgraded" ); } function last_stand_pistol_swap() { if ( self zm_utility::has_powerup_weapon() ) { // this will force the laststand module to switch us to any primary weapon, since we will no longer have this after revive self.lastActiveWeapon = level.weaponNone; } // PORTIZ: chance to override the player's last stand pistol, but only if the override is stronger than the current one if ( isdefined( self.w_min_last_stand_pistol_override ) ) { self last_stand_minimum_pistol_override(); } if ( !self HasWeapon( self.laststandpistol ) ) { self GiveWeapon( self.laststandpistol ); } ammoclip = self.laststandpistol.clipSize; doubleclip = ammoclip * 2; if( ( isdefined( self._special_solo_pistol_swap ) && self._special_solo_pistol_swap ) || (self.laststandpistol == level.default_solo_laststandpistol && !self.hadpistol) ) { self._special_solo_pistol_swap = 0; self.hadpistol = false; self SetWeaponAmmoStock( self.laststandpistol, doubleclip ); } else if( level flag::get("solo_game") && self.laststandpistol == level.default_solo_laststandpistol ) { self SetWeaponAmmoStock( self.laststandpistol, doubleclip ); } else if ( self.laststandpistol == level.default_laststandpistol ) { self SetWeaponAmmoStock( self.laststandpistol, doubleclip ); } else if ( !isdefined( self.stored_weapon_info ) || !isdefined( self.stored_weapon_info[ self.laststandpistol ] ) ) { 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 } else if ( self.laststandpistol.name == "ray_gun" || self.laststandpistol.name == "ray_gun_upgraded" ) { if ( self.stored_weapon_info[ self.laststandpistol ].total_amt >= ammoclip ) { self SetWeaponAmmoClip( self.laststandpistol, ammoclip ); self.stored_weapon_info[ self.laststandpistol ].given_amt = ammoclip; } else { self SetWeaponAmmoClip( self.laststandpistol, self.stored_weapon_info[ self.laststandpistol ].total_amt ); self.stored_weapon_info[ self.laststandpistol ].given_amt = self.stored_weapon_info[ self.laststandpistol ].total_amt; } self SetWeaponAmmoStock( self.laststandpistol, 0 ); } else { if ( self.stored_weapon_info[ self.laststandpistol ].stock_amt >= doubleclip ) { self SetWeaponAmmoStock( self.laststandpistol, doubleclip ); 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; } else { self SetWeaponAmmoStock( self.laststandpistol, self.stored_weapon_info[ self.laststandpistol ].stock_amt ); self.stored_weapon_info[ self.laststandpistol ].given_amt = self.stored_weapon_info[ self.laststandpistol ].total_amt; } } self SwitchToWeapon( self.laststandpistol ); } // PORTIZ: this runs if self.w_min_last_stand_pistol_override is defined, and just before the player is given his last stand pistol. function last_stand_minimum_pistol_override() { for( i = 0; i < level.pistol_values.size; i++ ) { if( level.pistol_values[i] == self.w_min_last_stand_pistol_override ) { n_min_last_stand_pistol_value = i; // find the value corresponding to our override weapon break; } } for( k = 0; k < level.pistol_values.size; k++ ) { if( level.pistol_values[k] == self.laststandpistol ) { n_default_last_stand_pistol_value = k; // find the value corresponding to our default last stand weapon break; } } if ( n_min_last_stand_pistol_value > n_default_last_stand_pistol_value ) { self.hadpistol = false; self.laststandpistol = self.w_min_last_stand_pistol_override; } } // ww: make sure the player has the best pistol when they go in to last stand function last_stand_best_pistol() { pistol_array = []; current_weapons = self GetWeaponsListPrimaries(); for( i = 0; i < current_weapons.size; i++ ) { // make sure the weapon is a pistol wclass = current_weapons[i].weapClass; if ( current_weapons[i].isBallisticKnife ) { wclass = "knife"; } if ( wclass == "pistol" || wclass == "pistolspread" || wclass == "pistol spread" ) { 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 )) { if( (current_weapons[i] != self.laststandpistol) || (self.laststandpistol != level.default_laststandpistol) ) { if ( self GetAmmoCount( current_weapons[i] ) <= 0 ) { continue; } } } pistol_array_index = pistol_array.size; // set up the spot in the array pistol_array[ pistol_array_index ] = SpawnStruct(); // struct to store info on pistol_array[ pistol_array_index ].weapon = current_weapons[i]; 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 // compare the current weapon to the level.pistol_values to see what the value is for( j = 0; j < level.pistol_values.size; j++ ) { if( level.pistol_values[j] == current_weapons[i].rootWeapon ) { pistol_array[ pistol_array_index ].value = j; break; } } } } self.laststandpistol = last_stand_compare_pistols( pistol_array ); } // ww: compares the array passed in for the highest valued pistol function last_stand_compare_pistols( struct_array ) { if( !IsArray( struct_array ) || struct_array.size <= 0 ) { self.hadpistol = false; //array will be empty if the pistol had no ammo...so lets see if the player had the pistol if(isDefined(self.stored_weapon_info)) { stored_weapon_info = GetArrayKeys( self.stored_weapon_info ); for( j = 0; j < stored_weapon_info.size; j++ ) { if( stored_weapon_info[ j ].rootWeapon == level.laststandpistol) { self.hadpistol = true; return stored_weapon_info[ j ]; } } } return level.laststandpistol; // nothing in the array then give the level last stand pistol } highest_score_pistol = struct_array[0]; // first time through give the first one to the highest score for( i = 1; i < struct_array.size; i++ ) { if( struct_array[i].value > highest_score_pistol.value ) { highest_score_pistol = struct_array[i]; } } if( level flag::get( "solo_game" ) ) { self._special_solo_pistol_swap = 0; // ww: this way the weapon knows to pack texture when given if( highest_score_pistol.value <= level.pistol_value_solo_replace_below ) { self.hadpistol = false; self._special_solo_pistol_swap = 1; if ( ( isdefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive ) && ( !self HasPerk( "specialty_quickrevive" ) ) ) { return highest_score_pistol.weapon; // ar: gun won't be replaced } else { return level.laststandpistol; // ww: if it scores too low the player gets the 1911 upgraded } } else { return highest_score_pistol.weapon; // ww: gun is high in ranking and won't be replaced } } else // ww: happens when not in solo { return highest_score_pistol.weapon; } } // ww: override function for saving player pistol ammo count function last_stand_save_pistol_ammo() { weapon_inventory = self GetWeaponsList( true ); self.stored_weapon_info = []; for( i = 0; i < weapon_inventory.size; i++ ) { weapon = weapon_inventory[i]; wclass = weapon.weapClass; if ( weapon.isBallisticKnife ) { wclass = "knife"; } if ( wclass == "pistol" || wclass == "pistolspread" || wclass == "pistol spread" ) { self.stored_weapon_info[ weapon ] = SpawnStruct(); self.stored_weapon_info[ weapon ].clip_amt = self GetWeaponAmmoClip( weapon ); self.stored_weapon_info[ weapon ].left_clip_amt = 0; dual_wield_weapon = weapon.dualWieldWeapon; if ( level.weaponNone != dual_wield_weapon ) { self.stored_weapon_info[ weapon ].left_clip_amt = self GetWeaponAmmoClip( dual_wield_weapon ); } self.stored_weapon_info[ weapon ].stock_amt = self GetWeaponAmmoStock( weapon ); 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; self.stored_weapon_info[ weapon ].given_amt = 0; } } self last_stand_best_pistol(); } // ww: override to restore the player's pistol ammo after being picked up function last_stand_restore_pistol_ammo() { self.weapon_taken_by_losing_specialty_additionalprimaryweapon = level.weaponNone; if ( !IsDefined( self.stored_weapon_info ) ) { return; } weapon_inventory = self GetWeaponsList( true ); weapon_to_restore = GetArrayKeys( self.stored_weapon_info ); for( i = 0; i < weapon_inventory.size; i++ ) { weapon = weapon_inventory[i]; if ( weapon != self.laststandpistol ) { continue; } // for this loop, weapon == self.laststandpistol for( j = 0; j < weapon_to_restore.size; j++ ) { if ( weapon == weapon_to_restore[j] ) { dual_wield_weapon = weapon_to_restore[j].dualWieldWeapon; if ( weapon != level.default_laststandpistol ) { last_clip = self GetWeaponAmmoClip( weapon ); last_left_clip = 0; if ( level.weaponNone != dual_wield_weapon ) { last_left_clip = self GetWeaponAmmoClip( dual_wield_weapon ); } last_stock = self GetWeaponAmmoStock( weapon ); last_total = last_clip + last_left_clip + last_stock; used_amt = self.stored_weapon_info[ weapon ].given_amt - last_total; if ( used_amt >= self.stored_weapon_info[ weapon ].stock_amt ) { used_amt -= self.stored_weapon_info[ weapon ].stock_amt; self.stored_weapon_info[ weapon ].stock_amt = 0; self.stored_weapon_info[ weapon ].clip_amt -= used_amt; if ( self.stored_weapon_info[ weapon ].clip_amt < 0 ) { self.stored_weapon_info[ weapon ].clip_amt = 0; } } else { new_stock_amt = self.stored_weapon_info[ weapon ].stock_amt - used_amt; if ( new_stock_amt < self.stored_weapon_info[ weapon ].stock_amt ) { self.stored_weapon_info[ weapon ].stock_amt = new_stock_amt; } } } self SetWeaponAmmoClip( weapon, self.stored_weapon_info[weapon].clip_amt ); if ( level.weaponNone != dual_wield_weapon ) { self SetWeaponAmmoClip( dual_wield_weapon, self.stored_weapon_info[weapon].left_clip_amt ); } self SetWeaponAmmoStock( weapon, self.stored_weapon_info[weapon].stock_amt ); break; } } } } function last_stand_take_thrown_grenade() { self endon( "disconnect" ); self endon( "bled_out" ); self endon( "player_revived" ); self waittill ( "grenade_fire", grenade, weapon ); if ( isdefined(self.lsgsar_lethal) && weapon == self.lsgsar_lethal ) { self.lsgsar_lethal_nade_amt--; } if ( isdefined(self.lsgsar_tactical) && weapon == self.lsgsar_tactical ) { self.lsgsar_tactical_nade_amt--; } } // ww: zeros out the player's grenades until they revive function last_stand_grenade_save_and_return() { if(( isdefined( level.isresetting_grief ) && level.isresetting_grief )) //don't do this for Grief when resetting the round { return; } self endon( "disconnect" ); self endon ("bled_out"); self.lsgsar_lethal_nade_amt = 0; self.lsgsar_has_lethal_nade = false; self.lsgsar_tactical_nade_amt = 0; self.lsgsar_has_tactical_nade = false; self.lsgsar_lethal = undefined; self.lsgsar_tactical = undefined; if (self IsThrowingGrenade()) { self thread last_stand_take_thrown_grenade(); } weapon = self zm_utility::get_player_lethal_grenade(); if ( weapon != level.weaponNone ) { self.lsgsar_has_lethal_nade = true; self.lsgsar_lethal = weapon; self.lsgsar_lethal_nade_amt = self GetWeaponAmmoClip( weapon ); self SetWeaponAmmoClip( weapon, 0 ); self TakeWeapon( weapon ); } weapon = self zm_utility::get_player_tactical_grenade(); if ( weapon != level.weaponNone ) { self.lsgsar_has_tactical_nade = true; self.lsgsar_tactical = weapon; self.lsgsar_tactical_nade_amt = self GetWeaponAmmoClip( weapon ); self SetWeaponAmmoClip( weapon, 0 ); self TakeWeapon( weapon ); } self waittill( "player_revived" ); if ( self.lsgsar_has_lethal_nade ) { self zm_utility::set_player_lethal_grenade( self.lsgsar_lethal ); self GiveWeapon( self.lsgsar_lethal ); self SetWeaponAmmoClip( self.lsgsar_lethal, self.lsgsar_lethal_nade_amt ); } if ( self.lsgsar_has_tactical_nade ) { self zm_utility::set_player_tactical_grenade( self.lsgsar_tactical ); self GiveWeapon( self.lsgsar_tactical ); self SetWeaponAmmoClip( self.lsgsar_tactical, self.lsgsar_tactical_nade_amt ); } self.lsgsar_lethal_nade_amt = undefined; self.lsgsar_has_lethal_nade = undefined; self.lsgsar_tactical_nade_amt = undefined; self.lsgsar_has_tactical_nade = undefined; self.lsgsar_lethal = undefined; self.lsgsar_tactical = undefined; } function spectators_respawn() { level endon( "between_round_over" ); if( !IsDefined( level.zombie_vars["spectators_respawn"] ) || !level.zombie_vars["spectators_respawn"] ) { return; } while( 1 ) { players = GetPlayers(); for( i = 0; i < players.size; i++ ) { e_player = players[i]; e_player spectator_respawn_player(); } wait( 1 ); } } function spectator_respawn_player() { if( self.sessionstate == "spectator" && IsDefined( self.spectator_respawn )) { if( !IsDefined( level.custom_spawnPlayer ) ) { // Custom spawn call for when they respawn from spectator level.custom_spawnPlayer = &spectator_respawn; } self [[level.spawnPlayer]](); thread refresh_player_navcard_hud(); if (isDefined(level.script) && level.round_number > 6 && self.score < 1500) { self.old_score = self.score; if(isDefined(level.spectator_respawn_custom_score)) { self [[level.spectator_respawn_custom_score]](); } self.score = 1500; } } } function spectator_respawn() { /# println( "*************************Respawn Spectator***" ); #/ assert( IsDefined( self.spectator_respawn ) ); origin = self.spectator_respawn.origin; angles = self.spectator_respawn.angles; self setSpectatePermissions( false ); new_origin = undefined; if ( isdefined( level.check_valid_spawn_override ) ) { new_origin = [[ level.check_valid_spawn_override ]]( self ); } if ( !isdefined( new_origin ) ) { new_origin = check_for_valid_spawn_near_team( self,true ); } if( IsDefined( new_origin ) ) { if(!isDefined(new_origin.angles)) { angles = (0, 0, 0); } else { angles = new_origin.angles; } self Spawn( new_origin.origin, angles ); } else { self Spawn( origin, angles ); } if ( IsDefined( self zm_utility::get_player_placeable_mine() ) ) { self TakeWeapon( self zm_utility::get_player_placeable_mine() ); self zm_utility::set_player_placeable_mine( level.weaponNone ); } self zm_equipment::take(); self.is_burning = undefined; self.abilities = []; // The check_for_level_end looks for this self.is_zombie = false; zm_laststand::set_ignoreme( false ); self clientfield::set( "zmbLastStand", 0 ); self RevivePlayer(); self notify( "spawned_player" ); self callback::callback( #"on_player_spawned" ); if(IsDefined(level._zombiemode_post_respawn_callback)) { self thread [[level._zombiemode_post_respawn_callback]](); } // Penalize the player when we respawn, since he 'died' self zm_score::player_reduce_points( "died" ); self zm_melee_weapon::spectator_respawn_all(); self thread player_zombie_breadcrumb(); self thread zm_perks::return_retained_perks(); return true; } //***************************************************************************** //***************************************************************************** function check_for_valid_spawn_near_team( revivee, return_struct ) { // if level override is detected, use it instead of normal respawn logic if ( IsDefined( level.check_for_valid_spawn_near_team_callback ) ) { spawn_location = [[ level.check_for_valid_spawn_near_team_callback ]](revivee, return_struct); return spawn_location; } else // normal respawn logic below here { players = GetPlayers(); spawn_points = zm_gametype::get_player_spawns_for_gametype(); closest_group = undefined; closest_distance = 100000000; backup_group = undefined; backup_distance = 100000000; if( spawn_points.size == 0 ) return undefined; a_enabled_zone_entities = zm_zonemgr::get_active_zones_entities(); // Look for the closest group that is within the specified ideal distances // If we can't find one within a valid area, use the closest unlocked group. for( i = 0; i < players.size; i++ ) { if( zm_utility::is_player_valid( players[i],undefined,true ) && (players[i] != self) ) { for( j = 0 ; j < spawn_points.size; j++ ) { if( isdefined(spawn_points[j].script_int) ) ideal_distance = spawn_points[j].script_int; else ideal_distance = 1000; // Safety check, check the spawn point is inside an enabled zone // There have been cases where a spawn point has the wrong zone KVP on it compared to the zone it exists inside if ( zm_utility::check_point_in_enabled_zone( spawn_points[j].origin, false, a_enabled_zone_entities ) == false ) { continue; } if ( spawn_points[j].locked == false ) { plyr_dist = DistanceSquared( players[i].origin, spawn_points[j].origin ); if( plyr_dist < ( ideal_distance * ideal_distance ) ) { if ( plyr_dist < closest_distance ) { closest_distance = plyr_dist; closest_group = j; } } else { if ( plyr_dist < backup_distance ) { backup_group = j; backup_distance = plyr_dist; } } } } } // If we don't have a closest_group, let's use the backup if( !IsDefined( closest_group ) ) { closest_group = backup_group; } if( IsDefined( closest_group ) ) { spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ); if( IsDefined(spawn_location) ) { return( spawn_location ); } } } return undefined; } } //***************************************************************************** //***************************************************************************** function get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ) { spawn_array =struct::get_array( spawn_points[closest_group].target, "targetname" ); spawn_array = array::randomize(spawn_array); for( k = 0; k < spawn_array.size; k++ ) { if(IsDefined(spawn_array[k].plyr) && spawn_array[k].plyr == revivee GetEntityNumber()) { if(positionWouldTelefrag(spawn_array[k].origin)) { spawn_array[k].plyr = undefined; break; } else if(( isdefined( return_struct ) && return_struct )) { return spawn_array[k]; } else { return spawn_array[k].origin; } } } for( k = 0; k < spawn_array.size; k++ ) { if(positionWouldTelefrag(spawn_array[k].origin)) { continue; } if(!IsDefined(spawn_array[k].plyr) || spawn_array[k].plyr == revivee GetEntityNumber()) { spawn_array[k].plyr = revivee GetEntityNumber(); if(( isdefined( return_struct ) && return_struct )) { return spawn_array[k]; } else { return spawn_array[k].origin; } } } if(( isdefined( return_struct ) && return_struct )) { return spawn_array[0]; } return spawn_array[0].origin; } //***************************************************************************** //***************************************************************************** function check_for_valid_spawn_near_position( revivee, v_position, return_struct ) { spawn_points = zm_gametype::get_player_spawns_for_gametype(); if( spawn_points.size == 0 ) { return( undefined ); } closest_group = undefined; closest_distance = 100000000; backup_group = undefined; backup_distance = 100000000; for( i=0 ; i= min_distance) && (dist <= max_distance) ) { if( dist < closest_distance ) { closest_distance = dist; closest_group = i; } } } } if( IsDefined( closest_group ) ) { spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ); if( IsDefined(spawn_location) ) { return( spawn_location ); } } return undefined; } //***************************************************************************** //***************************************************************************** function get_players_on_team(exclude) { teammates = []; players = GetPlayers(); for(i=0;i 0 ) ) { level.zombie_total = get_zombie_count_for_round( level.round_number, level.players.size ); level.zombie_respawns = 0; // reset number of zombies needing respawn level notify( "zombie_total_set" ); } if ( IsDefined( level.zombie_total_set_func ) ) { level thread [[ level.zombie_total_set_func ]](); } if ( level.round_number < 10 || level.speed_change_max > 0 ) { level thread zombie_utility::zombie_speed_up(); } old_spawn = undefined; while( 1 ) { while( zombie_utility::get_current_zombie_count() >= level.zombie_ai_limit || level.zombie_total <= 0 ) { wait( 0.1 ); } while ( zombie_utility::get_current_actor_count() >= level.zombie_actor_limit ) { zombie_utility::clear_all_corpses(); wait( 0.1 ); } // if we're using something that can pause the world, wait until finished to continue spawning if(flag::exists("world_is_paused")) { level flag::wait_till_clear("world_is_paused"); } // added ability to pause zombie spawning level flag::wait_till( "spawn_zombies" ); //Not great fix for this being zero - which it should NEVER be! (2 days to ship - PETER) while( level.zm_loc_types[ "zombie_location" ].size <= 0 ) { wait( 0.1 ); } run_custom_ai_spawn_checks(); if ( ( isdefined( level.hostMigrationTimer ) && level.hostMigrationTimer ) ) { util::wait_network_frame(); continue; } // Run custom round spawn logic - returns TRUE if we spawned something, FALSE if we need to spawn a zombie. if ( isdefined( level.fn_custom_round_ai_spawn ) ) { if ( [[ level.fn_custom_round_ai_spawn ]]() ) { // we handled the spawn util::wait_network_frame(); continue; } } if( IsDefined( level.zombie_spawners ) ) { // Check for custom zombie spawner selection if ( isdefined( level.fn_custom_zombie_spawner_selection ) ) { spawner = [[ level.fn_custom_zombie_spawner_selection ]](); } // Default zombie spawner selection else { if( ( isdefined( level.use_multiple_spawns ) && level.use_multiple_spawns ) ) { if( isdefined( level.spawner_int ) && ( isdefined( level.zombie_spawn[level.spawner_int].size ) && level.zombie_spawn[level.spawner_int].size ) ) { spawner = array::random( level.zombie_spawn[level.spawner_int] ); } else { spawner = array::random( level.zombie_spawners ); } } else { spawner = array::random( level.zombie_spawners ); } } ai = zombie_utility::spawn_zombie( spawner, spawner.targetname ); } if( IsDefined( ai ) ) { level.zombie_total--; if ( level.zombie_respawns > 0 ) { level.zombie_respawns--; } ai thread zombie_utility::round_spawn_failsafe(); count++; if ( ai ai::has_behavior_attribute( "can_juke" ) ) { ai ai::set_behavior_attribute("can_juke", false); } // Get zombies into the map quicker if they're respawning from cleanup if ( level.zombie_respawns > 0 )//&& level.zombie_vars["zombie_spawn_delay"] > 1.0 ) { wait 0.1; } else { wait( level.zombie_vars["zombie_spawn_delay"] ); } } util::wait_network_frame(); } } function get_zombie_count_for_round( n_round, n_player_count ) { max = level.zombie_vars["zombie_max_ai"]; multiplier = n_round / 5; if( multiplier < 1 ) { multiplier = 1; } // After round 10, exponentially have more AI attack the player if( n_round >= 10 ) { multiplier *= n_round * 0.15; } if( n_player_count == 1 ) { max += int( ( 0.5 * level.zombie_vars["zombie_ai_per_player"] ) * multiplier ); } else { max += int( ( ( n_player_count - 1 ) * level.zombie_vars["zombie_ai_per_player"] ) * multiplier ); } if( !isDefined( level.max_zombie_func ) ) { level.max_zombie_func = &zombie_utility::default_max_zombie_func; } n_zombie_count = [[ level.max_zombie_func ]]( max, n_round ); return n_zombie_count; } // Add custom ai (quads, etc.) to zombie spawner arrays for spawning function run_custom_ai_spawn_checks() { foreach ( str_id, s in level.custom_ai_spawn_check_funcs ) { if ( [[ s.func_check ]]() ) { a_spawners = [[ s.func_get_spawners ]](); level.zombie_spawners = ArrayCombine( level.zombie_spawners, a_spawners, false, false ); if ( ( isdefined( level.use_multiple_spawns ) && level.use_multiple_spawns ) ) { foreach ( sp in a_spawners ) { if ( IsDefined( sp.script_int ) ) { if ( !IsDefined( level.zombie_spawn[ sp.script_int ] ) ) { level.zombie_spawn[ sp.script_int ] = []; } if ( !IsInArray( level.zombie_spawn[ sp.script_int ], sp ) ) { if ( !isdefined( level.zombie_spawn[ sp.script_int ] ) ) level.zombie_spawn[ sp.script_int ] = []; else if ( !IsArray( level.zombie_spawn[ sp.script_int ] ) ) level.zombie_spawn[ sp.script_int ] = array( level.zombie_spawn[ sp.script_int ] ); level.zombie_spawn[ sp.script_int ][level.zombie_spawn[ sp.script_int ].size]=sp;; } } } } if ( IsDefined( s.func_get_locations ) ) { a_locations = [[ s.func_get_locations ]](); level.zm_loc_types[ "zombie_location" ] = ArrayCombine( level.zm_loc_types[ "zombie_location" ], a_locations, false, false ); } } else { a_spawners = [[ s.func_get_spawners ]](); foreach ( sp in a_spawners ) { ArrayRemoveValue( level.zombie_spawners, sp ); } if ( ( isdefined( level.use_multiple_spawns ) && level.use_multiple_spawns ) ) { foreach ( sp in a_spawners ) { if ( IsDefined( sp.script_int ) && IsDefined( level.zombie_spawn[ sp.script_int ] ) ) { ArrayRemoveValue( level.zombie_spawn[ sp.script_int ], sp ); } } } if ( IsDefined( s.func_get_locations ) ) { a_locations = [[ s.func_get_locations ]](); foreach ( s_loc in a_locations ) { ArrayRemoveValue( level.zm_loc_types[ "zombie_location" ], s_loc ); } } } } } function register_custom_ai_spawn_check( str_id, func_check, func_get_spawners, func_get_locations ) { if ( !IsDefined( level.custom_ai_spawn_check_funcs[str_id] ) ) { level.custom_ai_spawn_check_funcs[ str_id ] = SpawnStruct(); } level.custom_ai_spawn_check_funcs[ str_id ].func_check = func_check; level.custom_ai_spawn_check_funcs[ str_id ].func_get_spawners = func_get_spawners; level.custom_ai_spawn_check_funcs[ str_id ].func_get_locations = func_get_locations; } // TESTING: spawn one zombie at a time function round_spawning_test() { while (true) { spawn_point = array::random( level.zm_loc_types[ "zombie_location" ] ); // grab a random spawner spawner = array::random(level.zombie_spawners); ai = zombie_utility::spawn_zombie( spawner,spawner.targetname,spawn_point); ai waittill("death"); wait 5; } } ///////////////////////////////////////////////////////// // round_text( text ) // { // if( level.first_round ) // { // intro = true; // } // else // { // intro = false; // } // // hud = create_simple_hud(); // hud.horzAlign = "center"; // hud.vertAlign = "middle"; // hud.alignX = "center"; // hud.alignY = "middle"; // hud.y = -100; // hud.foreground = 1; // hud.fontscale = 16.0; // hud.alpha = 0; // hud.color = ( 1, 1, 1 ); // // hud SetText( text ); // hud FadeOverTime( 1.5 ); // hud.alpha = 1; // wait( 1.5 ); // // if( intro ) // { // wait( 1 ); // level notify( "intro_change_color" ); // } // // hud FadeOverTime( 3 ); // //hud.color = ( 0.8, 0, 0 ); // hud.color = ( 0.21, 0, 0 ); // wait( 3 ); // // if( intro ) // { // level waittill( "intro_hud_done" ); // } // // hud FadeOverTime( 1.5 ); // hud.alpha = 0; // wait( 1.5 ); // hud destroy(); // } // Allows the round to be paused. Displays a countdown timer. // function round_pause( delay ) { if ( !IsDefined( delay ) ) { delay = 30; } level.countdown_hud = zm_utility::create_counter_hud(); level.countdown_hud SetValue( delay ); level.countdown_hud.color = ( 1, 1, 1 ); level.countdown_hud.alpha = 1; level.countdown_hud FadeOverTime( 2.0 ); wait( 2.0 ); level.countdown_hud.color = ( 0.21, 0, 0 ); level.countdown_hud FadeOverTime( 3.0 ); wait(3); while (delay >= 1) { wait (1); delay--; level.countdown_hud SetValue( delay ); } // Zero! Play end sound players = GetPlayers(); for (i=0; i> round_start start" ); #/ if ( IsDefined(level.round_prestart_func) ) { [[ level.round_prestart_func ]](); } else { n_delay = 2; if ( IsDefined( level.zombie_round_start_delay ) ) { n_delay = level.zombie_round_start_delay; } wait n_delay; } level.zombie_health = level.zombie_vars["zombie_health_start"]; if( GetDvarInt( "scr_writeconfigstrings" ) == 1 ) { wait(5); ExitLevel(); return; } if ( level.zombie_vars["game_start_delay"] > 0 ) { round_pause( level.zombie_vars["game_start_delay"] ); } level flag::set( "begin_spawning" ); if( !isDefined(level.round_spawn_func) ) { level.round_spawn_func = &round_spawning; } if(!IsDefined(level.move_spawn_func)) { level.move_spawn_func = &zm_utility::move_zombie_spawn_location; } /# if (GetDvarInt( "zombie_rise_test") ) { level.round_spawn_func = &round_spawning_test; // FOR TESTING, one zombie at a time, no round advancement } #/ if ( !isDefined(level.round_wait_func) ) { level.round_wait_func = &round_wait; } if ( !IsDefined(level.round_think_func) ) { level.round_think_func = &round_think; } level thread [[ level.round_think_func ]](); } // // Lets the players know that you need power to open these function play_door_dialog() { self endon ("warning_dialog"); timer = 0; while(1) { {wait(.05);}; players = GetPlayers(); for(i = 0; i < players.size; i++) { dist = distancesquared(players[i].origin, self.origin ); if(dist > 70*70) { timer =0; continue; } while(dist < 70*70 && timer < 3) { wait(0.5); timer++; } if(dist > 70*70 && timer >= 3) { self playsound("door_deny"); players[i] zm_audio::create_and_play_dialog( "general", "outofmoney" ); wait(3); self notify ("warning_dialog"); //iprintlnbold("warning_given"); } } } } function wait_until_first_player() { players = GetPlayers(); if( !IsDefined( players[0] ) ) { level waittill( "first_player_ready" ); } } // // Set the current round number hud display function round_one_up() { level endon("end_game"); if( isdefined(level.noRoundNumber) && level.noRoundNumber==true ) { return; } if(!IsDefined(level.doground_nomusic)) { level.doground_nomusic = 0; } if( level.first_round ) { intro = true; if( isdefined( level._custom_intro_vox ) ) { level thread [[level._custom_intro_vox]](); } else { level thread play_level_start_vox_delayed(); }; } else { intro = false; } //Round Number Specific Lines if( level.round_number == 5 || level.round_number == 10 || level.round_number == 20 || level.round_number == 35 || level.round_number == 50 ) { players = GetPlayers(); rand = RandomIntRange(0,players.size); players[rand] thread zm_audio::create_and_play_dialog( "general", "round_" + level.round_number ); } if( intro ) { if(( isdefined( level.host_ended_game ) && level.host_ended_game )) { return; } wait( 6.25 ); level notify( "intro_hud_done" ); wait( 2 ); } else { wait( 2.5 ); } ReportMTU(level.round_number); // In network debug instrumented builds, causes network spike report to generate. } // Flash the round display at the end of the round // function round_over() { if( isdefined(level.noRoundNumber) && level.noRoundNumber==true ) { return; } time = [[level.func_get_delay_between_rounds]](); players = GetPlayers(); for ( player_index = 0; player_index < players.size; player_index++ ) { if ( !IsDefined( players[player_index].pers["previous_distance_traveled"] ) ) { players[player_index].pers["previous_distance_traveled"] = 0; } distanceThisRound = int( players[player_index].pers["distance_traveled"] - players[player_index].pers["previous_distance_traveled"] ); players[player_index].pers["previous_distance_traveled"] = players[player_index].pers["distance_traveled"]; players[player_index] IncrementPlayerStat("distance_traveled", distanceThisRound ); if ( players[player_index].pers["team"] != "spectator" ) { players[player_index] recordRoundEndStats(); } } RecordZombieRoundEnd(); // waiting for the Pulse from lua wait( time ); } function get_delay_between_rounds() { return( level.zombie_vars["zombie_between_round_time"] ); } function recordPlayerRoundWeapon(weapon, statname) { if (isDefined(weapon)) { weaponIdx = GetBaseWeaponItemIndex(weapon); if (isDefined(weaponIdx)) { self incrementplayerstat(statname, weaponIdx); } } } function recordPrimaryWeaponsStats(base_stat_name, max_weapons) { current_weapons = self GetWeaponsListPrimaries(); for (index = 0; index < max_weapons && index < current_weapons.size; index++) { recordPlayerRoundWeapon(current_weapons[index], base_stat_name + index); } } function recordRoundStartStats() //self == player { zoneName = self zm_utility::get_current_zone(); if( IsDefined(zoneName) ) { self RecordZombieZone("startingZone", zoneName); } self incrementplayerstat("score", self.score); primaryWeapon = self GetCurrentWeapon(); self recordPrimaryWeaponsStats("roundStartPrimaryWeapon", 3); self RecordMapEvent(8, GetTime(), self.origin, level.round_number); } function recordRoundEndStats() //self == player { zoneName = self zm_utility::get_current_zone(); if( IsDefined(zoneName) ) { self RecordZombieZone( "endingZone", zoneName ); } self recordPrimaryWeaponsStats("roundEndPrimaryWeapon", 3); self RecordMapEvent(9, GetTime(), self.origin, level.round_number); } function round_think( restart = false ) { /# PrintLn( "ZM >> round_think start" ); #/ level endon("end_round_think"); if(!( isdefined( restart ) && restart )) { // Wait for blackscreen to end if in use if ( IsDefined( level.initial_round_wait_func )) [[level.initial_round_wait_func]](); if(!( isdefined( level.host_ended_game ) && level.host_ended_game )) { //unfreeze the players controls now players = GetPlayers(); foreach(player in players) { if(!( isdefined( player.hostMigrationControlsFrozen ) && player.hostMigrationControlsFrozen )) { player FreezeControls(false); /# println(" Unfreeze controls 8"); #/ } // set the initial round_number player zm_stats::set_global_stat( "rounds", level.round_number ); } } } SetRoundsPlayed( level.round_number ); for( ;; ) { ////////////////////////////////////////// //designed by prod DT#36173 maxreward = 50 * level.round_number; if ( maxreward > 500 ) maxreward = 500; level.zombie_vars["rebuild_barrier_cap_per_round"] = maxreward; ////////////////////////////////////////// level.pro_tips_start_time = GetTime(); level.zombie_last_run_time = GetTime(); // Resets the last time a zombie ran if ( IsDefined( level.zombie_round_change_custom ) ) { [[ level.zombie_round_change_custom ]](); } else { if( !( isdefined( level.sndMusicSpecialRound ) && level.sndMusicSpecialRound ) ) { if( ( isdefined( level.sndGotoRoundOccurred ) && level.sndGotoRoundOccurred )) level.sndGotoRoundOccurred = false; else if( level.round_number == 1 ) level thread zm_audio::sndMusicSystem_PlayState( "round_start_first" ); else if( level.round_number <= 5 ) level thread zm_audio::sndMusicSystem_PlayState( "round_start" ); else level thread zm_audio::sndMusicSystem_PlayState( "round_start_short" ); } round_one_up(); // round_text( &"ZOMBIE_ROUND_BEGIN" ); } zm_powerups::powerup_round_start(); players = GetPlayers(); array::thread_all( players, &zm_blockers::rebuild_barrier_reward_reset ); if(!( isdefined( level.headshots_only ) && level.headshots_only ) && !restart ) //no grenades for headshot only mode, or when grief restarts the round after everyone dies { level thread award_grenades_for_survivors(); } /# PrintLn( "ZM >> round_think, round="+level.round_number+", player_count=" + players.size ); #/ level.round_start_time = GetTime(); //Not great fix for this being zero - which it should NEVER be! (post ship - PETER) while( level.zm_loc_types[ "zombie_location" ].size <= 0 ) { wait( 0.1 ); } /# //Reset spawn counter for zones zkeys = GetArrayKeys( level.zones ); for ( i = 0; i < zkeys.size; i++ ) { zoneName = zkeys[i]; level.zones[zoneName].round_spawn_count = 0; } #/ level thread [[level.round_spawn_func]](); level notify( "start_of_round" ); RecordZombieRoundStart(); bb::logRoundEvent("start_of_round"); players = GetPlayers(); for ( index = 0; index < players.size; index++ ) { players[index] recordRoundStartStats(); } if(isDefined(level.round_start_custom_func)) { [[level.round_start_custom_func]](); } [[level.round_wait_func]](); level.first_round = false; level notify( "end_of_round" ); bb::logRoundEvent("end_of_round"); UploadStats(); if(isDefined(level.round_end_custom_logic)) { [[level.round_end_custom_logic]](); } players = GetPlayers(); // 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 // 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 // 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 // any specific bugs/exploits arise from it... if( ( isdefined( level.no_end_game_check ) && level.no_end_game_check ) ) { level thread last_stand_revive(); level thread spectators_respawn(); } else if ( 1 != players.size ) { level thread spectators_respawn(); //level thread last_stand_revive(); } players = GetPlayers(); array::thread_all( players, &zm_pers_upgrades_system::round_end ); if ( int(level.round_number / 5) * 5 == level.round_number ) { level clientfield::set( "round_complete_time", int( ( level.time - level.n_gameplay_start_time + 500 ) / 1000 ) ); level clientfield::set( "round_complete_num", level.round_number ); } // // Increase the zombie move speed //level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier"]; if( level.gamedifficulty == 0 ) //easy { level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier_easy"]; } else //normal { level.zombie_move_speed = level.round_number * level.zombie_vars["zombie_move_speed_multiplier"]; } set_round_number( 1 + get_round_number() ); SetRoundsPlayed( get_round_number() ); // Here's the difficulty increase over time area //level.zombie_vars["zombie_spawn_delay"] = get_zombie_spawn_delay( level.round_number ); level.zombie_vars["zombie_spawn_delay"] = [[level.func_get_zombie_spawn_delay]]( get_round_number() ); // round_text( &"ZOMBIE_ROUND_END" ); matchUTCTime = GetUTC(); 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. foreach(player in players) { if ( level.curr_gametype_affects_rank && get_round_number() > (3 + level.start_round) ) { player zm_stats::add_client_stat( "weighted_rounds_played",get_round_number() ); } player zm_stats::set_global_stat( "rounds", get_round_number() ); // update the game played time player zm_stats::update_playing_utc_time( matchUTCTime ); // Reset the health if necessary player zm_perks::perk_set_max_health_if_jugg( "health_reboot", true, true ); //XP event stuff for ( i = 0; i < 4; i++ ) { player.number_revives_per_round[i] = 0; } if ( IsAlive( player ) && player.sessionstate != "spectator" && !( isdefined( level.skip_alive_at_round_end_xp ) && level.skip_alive_at_round_end_xp ) ) { player zm_stats::increment_challenge_stat( "SURVIVALIST_SURVIVE_ROUNDS" ); score_number = get_round_number() - 1; if ( score_number < 1 ) { score_number = 1; } else if ( score_number > 20 ) { score_number = 20; } scoreevents::processScoreEvent( ("alive_at_round_end_" + score_number), player ); } } if( isdefined( level.check_quickrevive_hotjoin ) ) { [[ level.check_quickrevive_hotjoin ]](); } level.round_number = get_round_number(); level round_over(); level notify( "between_round_over" ); level.skip_alive_at_round_end_xp = false; restart = false; } } function award_grenades_for_survivors() { players = GetPlayers(); for (i = 0; i < players.size; i++) { if (!players[i].is_zombie && !( isdefined( players[i].altbody ) && players[i].altbody ) && !players[i] laststand::player_is_in_laststand() ) { lethal_grenade = players[i] zm_utility::get_player_lethal_grenade(); if( !players[i] HasWeapon( lethal_grenade ) ) { players[i] GiveWeapon( lethal_grenade ); players[i] SetWeaponAmmoClip( lethal_grenade, 0 ); } frac = players[i] GetFractionMaxAmmo( lethal_grenade ); if ( frac < .25 ) { players[i] SetWeaponAmmoClip( lethal_grenade, 2 ); } else if ( frac < .5 ) { players[i] SetWeaponAmmoClip( lethal_grenade, 3 ); } else { players[i] SetWeaponAmmoClip( lethal_grenade, 4 ); } } } } // Calculate the correct spawn delay for the round number function get_zombie_spawn_delay( n_round ) { if ( n_round > 60 ) // Don't let this loop too many times { n_round = 60; } // Decay rate n_multiplier = 0.95; // Base delay switch( level.players.size ) { case 1: n_delay = 2.0; // 0.95 == 0.1 @ round 60 break; case 2: n_delay = 1.5; // 0.95 == 0.1 @ round 54 break; case 3: n_delay = 0.89; // 0.95 == 0.1 @ round 60 break; case 4: n_delay = 0.67; // 0.95 == 0.1 @ round 60 break; } for( i=1; i 0 || level.zombie_total > 0 || level.intermission ); if( !should_wait ) { level thread zm_audio::sndMusicSystem_PlayState( "round_end" ); return; } if( level flag::get( "end_round_wait" ) ) { level thread zm_audio::sndMusicSystem_PlayState( "round_end" ); return; } wait( 1.0 ); } } //To make sure music plays when using debug to switch rounds function sndMusicOnKillRound() { level endon( "end_of_round" ); level waittill( "kill_round" ); level thread zm_audio::sndMusicSystem_PlayState( "round_end" ); } function zombify_player() // self = player { self zm_score::player_died_penalty(); self RecordPlayerDeathZombies(); if ( IsDefined( level.deathcard_spawn_func ) ) { self [[level.deathcard_spawn_func]](); } if( isdefined( level.func_clone_plant_respawn ) && isdefined( self.s_clone_plant ) ) { self [[level.func_clone_plant_respawn]](); return; } if( !IsDefined( level.zombie_vars["zombify_player"] ) || !level.zombie_vars["zombify_player"] ) { self thread spawnSpectator(); return; } self.ignoreme = true; self.is_zombie = true; self.zombification_time = GetTime(); self.team = level.zombie_team; self notify( "zombified" ); if( IsDefined( self.revivetrigger ) ) { self.revivetrigger Delete(); } self.revivetrigger = undefined; self setMoveSpeedScale( 0.3 ); self reviveplayer(); self TakeAllWeapons(); self DisableWeaponCycling(); self DisableOffhandWeapons(); self thread zombie_utility::zombie_eye_glow(); self thread playerzombie_player_damage(); self thread playerzombie_soundboard(); } function playerzombie_player_damage() { self endon( "death" ); self endon( "disconnect" ); self thread playerzombie_infinite_health(); // manually keep regular health up self.zombiehealth = level.zombie_health; // enable PVP damage on this guy // self EnablePvPDamage(); while( 1 ) { self waittill( "damage", amount, attacker, directionVec, point, type ); if( !IsDefined( attacker ) || !IsPlayer( attacker ) ) { {wait(.05);}; continue; } self.zombiehealth -= amount; if( self.zombiehealth <= 0 ) { // "down" the zombie self thread playerzombie_downed_state(); self waittill( "playerzombie_downed_state_done" ); self.zombiehealth = level.zombie_health; } } } function playerzombie_downed_state() { self endon( "death" ); self endon( "disconnect" ); downTime = 15; startTime = GetTime(); endTime = startTime +( downTime * 1000 ); self thread playerzombie_downed_hud(); self.playerzombie_soundboard_disable = true; self thread zombie_utility::zombie_eye_glow_stop(); self DisableWeapons(); self AllowStand( false ); self AllowCrouch( false ); self AllowProne( true ); while( GetTime() < endTime ) { {wait(.05);}; } self.playerzombie_soundboard_disable = false; self thread zombie_utility::zombie_eye_glow(); self EnableWeapons(); self AllowStand( true ); self AllowCrouch( false ); self AllowProne( false ); self notify( "playerzombie_downed_state_done" ); } function playerzombie_downed_hud() { self endon( "death" ); self endon( "disconnect" ); text = NewClientHudElem( self ); text.alignX = "center"; text.alignY = "middle"; text.horzAlign = "user_center"; text.vertAlign = "user_bottom"; text.foreground = true; text.font = "default"; text.fontScale = 1.8; text.alpha = 0; text.color = ( 1.0, 1.0, 1.0 ); text SetText( &"ZOMBIE_PLAYERZOMBIE_DOWNED" ); text.y = -113; if( self IsSplitScreen() ) { text.y = -137; } text FadeOverTime( 0.1 ); text.alpha = 1; self waittill( "playerzombie_downed_state_done" ); text FadeOverTime( 0.1 ); text.alpha = 0; } function playerzombie_infinite_health() { self endon( "death" ); self endon( "disconnect" ); bighealth = 100000; while( 1 ) { if( self.health < bighealth ) { self.health = bighealth; } wait( 0.1 ); } } function playerzombie_soundboard() { self endon( "death" ); self endon( "disconnect" ); self.playerzombie_soundboard_disable = false; self.buttonpressed_use = false; self.buttonpressed_attack = false; self.buttonpressed_ads = false; self.useSound_waitTime = 3 * 1000; // milliseconds self.useSound_nextTime = GetTime(); useSound = "playerzombie_usebutton_sound"; self.attackSound_waitTime = 3 * 1000; self.attackSound_nextTime = GetTime(); attackSound = "playerzombie_attackbutton_sound"; self.adsSound_waitTime = 3 * 1000; self.adsSound_nextTime = GetTime(); adsSound = "playerzombie_adsbutton_sound"; self.inputSound_nextTime = GetTime(); // don't want to be able to do all sounds at once while( 1 ) { if( self.playerzombie_soundboard_disable ) { {wait(.05);}; continue; } if( self UseButtonPressed() ) { if( self can_do_input( "use" ) ) { self thread playerzombie_play_sound( useSound ); self thread playerzombie_waitfor_buttonrelease( "use" ); self.useSound_nextTime = GetTime() + self.useSound_waitTime; } } else if( self AttackButtonPressed() ) { if( self can_do_input( "attack" ) ) { self thread playerzombie_play_sound( attackSound ); self thread playerzombie_waitfor_buttonrelease( "attack" ); self.attackSound_nextTime = GetTime() + self.attackSound_waitTime; } } else if( self AdsButtonPressed() ) { if( self can_do_input( "ads" ) ) { self thread playerzombie_play_sound( adsSound ); self thread playerzombie_waitfor_buttonrelease( "ads" ); self.adsSound_nextTime = GetTime() + self.adsSound_waitTime; } } {wait(.05);}; } } function can_do_input( inputType ) { if( GetTime() < self.inputSound_nextTime ) { return false; } canDo = false; switch( inputType ) { case "use": if( GetTime() >= self.useSound_nextTime && !self.buttonpressed_use ) { canDo = true; } break; case "attack": if( GetTime() >= self.attackSound_nextTime && !self.buttonpressed_attack ) { canDo = true; } break; case "ads": if( GetTime() >= self.useSound_nextTime && !self.buttonpressed_ads ) { canDo = true; } break; default: ASSERTMSG( "can_do_input(): didn't recognize inputType of " + inputType ); break; } return canDo; } function playerzombie_play_sound( alias ) { self zm_utility::play_sound_on_ent( alias ); } function playerzombie_waitfor_buttonrelease( inputType ) { if( inputType != "use" && inputType != "attack" && inputType != "ads" ) { ASSERTMSG( "playerzombie_waitfor_buttonrelease(): inputType of " + inputType + " is not recognized." ); return; } notifyString = "waitfor_buttonrelease_" + inputType; self notify( notifyString ); self endon( notifyString ); if( inputType == "use" ) { self.buttonpressed_use = true; while( self UseButtonPressed() ) { {wait(.05);}; } self.buttonpressed_use = false; } else if( inputType == "attack" ) { self.buttonpressed_attack = true; while( self AttackButtonPressed() ) { {wait(.05);}; } self.buttonpressed_attack = false; } else if( inputType == "ads" ) { self.buttonpressed_ads = true; while( self AdsButtonPressed() ) { {wait(.05);}; } self.buttonpressed_ads = false; } } function remove_ignore_attacker() { self notify( "new_ignore_attacker" ); self endon( "new_ignore_attacker" ); self endon( "disconnect" ); if( !isDefined( level.ignore_enemy_timer ) ) { level.ignore_enemy_timer = 0.4; } wait( level.ignore_enemy_timer ); self.ignoreAttacker = undefined; } function player_damage_override_cheat( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ) { player_damage_override( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); return 0; } // // player_damage_override // MUST return the value of the damage override // // MM (08/10/09) - Removed calls to PlayerDamageWrapper because it's always called in // Callback_PlayerDamage now. We just need to return the damage. // function player_damage_override( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ) { iDamage = self check_player_damage_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); if( self.scene_takedamage === false ) { return 0; } if ( IsDefined( eAttacker ) && ( isdefined( eAttacker.b_aat_fire_works_weapon ) && eAttacker.b_aat_fire_works_weapon ) ) { return 0; } if ( ( isdefined( self.use_adjusted_grenade_damage ) && self.use_adjusted_grenade_damage ) ) { self.use_adjusted_grenade_damage = undefined; if( ( self.health > iDamage ) ) { return iDamage; } } if ( !iDamage ) { return 0; } // WW (8/20/10) - Sledgehammer fix for Issue 43492. This should stop the player from taking any damage while in laststand if( self laststand::player_is_in_laststand() ) { return 0; } if ( isDefined( eInflictor ) ) { if ( ( isdefined( eInflictor.water_damage ) && eInflictor.water_damage ) ) { return 0; } } if ( isDefined( eAttacker ) ) { if( ( eAttacker.owner === self ) ) { return 0; } if( isDefined( self.ignoreAttacker ) && self.ignoreAttacker == eAttacker ) { return 0; } // AR (5/30/12) - Stop Zombie players from damaging other Zombie players if ( ( isdefined( self.is_zombie ) && self.is_zombie ) && ( isdefined( eAttacker.is_zombie ) && eAttacker.is_zombie ) ) { return 0; } if( (isDefined( eAttacker.is_zombie ) && eAttacker.is_zombie) ) { self.ignoreAttacker = eAttacker; self thread remove_ignore_attacker(); if ( isdefined( eAttacker.custom_damage_func ) ) { iDamage = eAttacker [[ eAttacker.custom_damage_func ]]( self ); } } eAttacker notify( "hit_player" ); if ( isdefined( eAttacker ) && isdefined( eAttacker.func_mod_damage_override ) ) { sMeansOfDeath = eAttacker [[ eAttacker.func_mod_damage_override ]]( eInflictor, sMeansOfDeath, weapon ); } if( sMeansOfDeath != "MOD_FALLING" ) { self thread playSwipeSound( sMeansOfDeath, eattacker ); if( ( isdefined( eattacker.is_zombie ) && eattacker.is_zombie ) || IsPlayer(eAttacker) ) self PlayRumbleOnEntity( "damage_heavy" ); if( ( isdefined( eattacker.is_zombie ) && eattacker.is_zombie ) ) { self zm_audio::create_and_play_dialog( "general", "attacked" ); } canExert = true; if ( ( isdefined( level.pers_upgrade_flopper ) && level.pers_upgrade_flopper ) ) { // If the player has persistent flopper power, then no exert on explosion if ( ( isdefined( self.pers_upgrades_awarded[ "flopper" ] ) && self.pers_upgrades_awarded[ "flopper" ] ) ) { canExert = ( sMeansOfDeath != "MOD_PROJECTILE_SPLASH" && sMeansOfDeath != "MOD_GRENADE" && sMeansOfDeath != "MOD_GRENADE_SPLASH" ); } } if ( ( isdefined( canExert ) && canExert ) ) { if(RandomIntRange(0,1) == 0 ) { self thread zm_audio::playerExert( "hitmed" ); //self thread zm_audio::create_and_play_dialog( "general", "hitmed" ); } else { self thread zm_audio::playerExert( "hitlrg" ); //self thread zm_audio::create_and_play_dialog( "general", "hitlrg" ); } } } } //Audio(RG:2/1/2016) adding underwater drowning exert. if ( isDefined( sMeansOfDeath) && sMeansOfDeath == "MOD_DROWN") { self thread zm_audio::playerExert( "drowning", true ); self.voxDrowning = true; } if( isdefined( level.perk_damage_override ) ) { foreach( func in level.perk_damage_override ) { n_damage = self [[ func ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); if( isdefined( n_damage ) ) { iDamage = n_damage; } } } finalDamage = iDamage; // claymores and freezegun shatters, like bouncing betties, harm no players if ( zm_utility::is_placeable_mine( weapon ) ) { return 0; } if ( isDefined( self.player_damage_override ) ) { self thread [[ self.player_damage_override ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); } // exploding quads should not kill player if ( IsDefined( eInflictor ) && IsDefined( eInflictor.archetype ) && eInflictor.archetype == "zombie_quad" ) { if ( sMeansOfDeath == "MOD_EXPLOSIVE" ) { if ( self.health > 75 ) { return 75; } } } // Players can't die from cooked grenade if trhey have the bgb Danger Closet if ( sMeansOfDeath == "MOD_SUICIDE" && self bgb::is_enabled( "zm_bgb_danger_closest" ) ) { return 0; } if ( sMeansOfDeath == "MOD_PROJECTILE" || sMeansOfDeath == "MOD_PROJECTILE_SPLASH" || sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" || sMeansOfDeath == "MOD_EXPLOSIVE" ) { if( self bgb::is_enabled( "zm_bgb_danger_closest" ) ) { return 0; } // player explosive splash damage (caps explosive damage), fixes raygun damage being fatal (or grenades) when damaging yourself if ( !( isdefined( self.is_zombie ) && self.is_zombie ) ) { // Don't do this for projectile damage coming from zombies if ( !isdefined( eAttacker ) || ( !( isdefined( eAttacker.is_zombie ) && eAttacker.is_zombie ) && !( isdefined( eAttacker.b_override_explosive_damage_cap ) && eAttacker.b_override_explosive_damage_cap ) ) ) { // Only do it for ray gun if( isdefined(weapon.name) && ((weapon.name == "ray_gun") || ( weapon.name == "ray_gun_upgraded" )) ) { // Clamp it, we don't want to increase the damage from player raygun splash damage or grenade splash damage // Don't create more damage than we are trying to apply if ( ( self.health > 25 ) && ( iDamage > 25 ) ) { return 25; } } else if ( ( self.health > 75 ) && ( iDamage > 75 ) ) { return 75; } } } } if( iDamage < self.health ) { if ( IsDefined( eAttacker ) ) { if( IsDefined( level.custom_kill_damaged_VO ) ) { eAttacker thread [[ level.custom_kill_damaged_VO ]]( self ); } else { eAttacker.sound_damage_player = self; } if( ( isdefined( eAttacker.missingLegs ) && eAttacker.missingLegs ) ) { self zm_audio::create_and_play_dialog( "general", "crawl_hit" ); } } // MM (08/10/09) return finalDamage; } //player died if( isdefined( eAttacker ) ) { if(isDefined(eAttacker.animname) && eAttacker.animname == "zombie_dog") { self zm_stats::increment_client_stat( "killed_by_zdog" ); self zm_stats::increment_player_stat( "killed_by_zdog" ); } else if(( isdefined( eAttacker.is_avogadro ) && eAttacker.is_avogadro )) { self zm_stats::increment_client_stat( "killed_by_avogadro", false ); self zm_stats::increment_player_stat( "killed_by_avogadro" ); } } self thread clear_path_timers(); if( level.intermission ) { level waittill( "forever" ); } // AR (3/7/12) - Keep track of which player killed player in Zombify modes like Cleansed / Turned // Confirmed with Alex if ( level.scr_zm_ui_gametype == "zcleansed" && iDamage > 0 ) { if ( IsDefined( eAttacker ) && IsPlayer( eAttacker ) && eAttacker.team != self.team && ( ( !( isdefined( self.laststand ) && self.laststand ) && !self laststand::player_is_in_laststand() ) || !IsDefined( self.last_player_attacker ) ) ) { // Restore Health To Zombie Player //-------------------------------- if ( IsDefined( eAttacker.maxhealth ) && ( isdefined( eAttacker.is_zombie ) && eAttacker.is_zombie ) ) { eAttacker.health = eAttacker.maxhealth; } //self.last_player_attacker = eAttacker; if ( IsDefined( level.player_kills_player ) ) { self thread [[ level.player_kills_player]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); } } } if ( self.lives > 0 && self HasPerk( "specialty_whoswho" ) ) { self.lives--; if ( IsDefined( level.whoswho_laststand_func ) ) { self thread [[ level.whoswho_laststand_func]](); return 0; } } players = GetPlayers(); count = 0; for( i = 0; i < players.size; i++ ) { if( players[i] == self || players[i].is_zombie || players[i] laststand::player_is_in_laststand() || players[i].sessionstate == "spectator" ) { count++; } } if( count < players.size || (isDefined(level._game_module_game_end_check) && ![[level._game_module_game_end_check]]()) ) { if ( IsDefined( self.lives ) && self.lives > 0 && ( isdefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive ) && self HasPerk( "specialty_quickrevive" ) ) { self thread wait_and_revive(); } // MM (08/10/09) return finalDamage; } // 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, // 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 // mechanics are introduced that require solo players to go into last stand instead of losing the game immediately if ( players.size == 1 && level flag::get( "solo_game" ) ) { if ( ( isdefined( level.no_end_game_check ) && level.no_end_game_check ) || ( isdefined( level.check_end_solo_game_override ) && [[level.check_end_solo_game_override]]() ) ) { return finalDamage; } else if ( self.lives == 0 || !self HasPerk( "specialty_quickrevive" ) ) { self.intermission = true; } } // 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 // 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 // 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 // the conditions out in to their own variables we keep the complexity without making it look like a mess. solo_death = ( players.size == 1 && level flag::get( "solo_game" ) && ( self.lives == 0 || !self HasPerk("specialty_quickrevive") ) ); // there is only one player AND the flag is set AND self.lives equals 0 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 if ( (solo_death || non_solo_death) && !( isdefined( level.no_end_game_check ) && level.no_end_game_check ) ) // if only one player on their last life or any game that started with more than one player { level notify("stop_suicide_trigger"); self AllowProne( true ); //just in case self thread zm_laststand::PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime ); if( !isdefined( vDir ) ) { vDir = ( 1.0, 0.0, 0.0 ); } self FakeDamageFrom(vDir); level notify("last_player_died"); if ( isdefined(level.custom_player_fake_death) ) self thread [[level.custom_player_fake_death]](vDir, sMeansOfDeath); else self thread player_fake_death(); } if( count == players.size && !( isdefined( level.no_end_game_check ) && level.no_end_game_check ) ) { if ( players.size == 1 && level flag::get( "solo_game" )) { if ( self.lives == 0 || !self HasPerk("specialty_quickrevive") ) // && !self laststand::player_is_in_laststand() { self.lives = 0; level notify("pre_end_game"); util::wait_network_frame(); if(level flag::get("dog_round")) { increment_dog_round_stat( "lost" ); } level notify( "end_game" ); } else { return finalDamage; } } else { level notify("pre_end_game"); util::wait_network_frame(); if(level flag::get("dog_round")) { increment_dog_round_stat( "lost" ); } level notify( "end_game" ); } return 0; // MM (09/16/09) Need to return something } else { // MM (08/10/09) surface = "flesh"; return finalDamage; } } function clear_path_timers() { zombies = GetAITeamArray( level.zombie_team ); foreach( zombie in zombies ) { if ( isdefined( zombie.favoriteenemy ) && ( zombie.favoriteenemy == self ) ) { zombie.zombie_path_timer = 0; } } } function check_player_damage_callbacks( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ) { if ( !isdefined( level.player_damage_callbacks ) ) { return iDamage; } for ( i = 0; i < level.player_damage_callbacks.size; i++ ) { newDamage = self [[ level.player_damage_callbacks[i] ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime ); if ( -1 != newDamage ) { return newDamage; } } return iDamage; } function register_player_damage_callback( func ) { if ( !isdefined( level.player_damage_callbacks ) ) { level.player_damage_callbacks = []; } level.player_damage_callbacks[level.player_damage_callbacks.size] = func; } function wait_and_revive() { self endon( "remote_revive" ); level flag::set( "wait_and_revive" ); level.wait_and_revive = true; if ( isdefined( self.waiting_to_revive ) && self.waiting_to_revive == true ) { return; } // Grab the perks if we have the player persistent ability "perk lose" if( ( isdefined( self.pers_upgrades_awarded["perk_lose"] ) && self.pers_upgrades_awarded["perk_lose"] ) ) { self zm_pers_upgrades_functions::pers_upgrade_perk_lose_save(); } self.waiting_to_revive = true; self.lives--; if ( isdefined( level.exit_level_func ) ) { self thread [[ level.exit_level_func ]](); } else { if ( GetPlayers().size == 1 ) { player = GetPlayers()[0]; level.move_away_points = PositionQuery_Source_Navigation( player.origin, 12*40, 12*80, 120, 20 ); if ( !isdefined( level.move_away_points ) ) { level.move_away_points = PositionQuery_Source_Navigation( player.last_valid_position, 12*40, 12*80, 120, 20 ); } } } solo_revive_time = 10.0; name = level.player_name_directive[self GetEntityNumber()]; self.revive_hud setText( &"ZOMBIE_REVIVING_SOLO", name ); self laststand::revive_hud_show_n_fade( solo_revive_time ); level flag::wait_till_timeout( solo_revive_time, "instant_revive" ); if ( level flag::get( "instant_revive" ) ) { self laststand::revive_hud_show_n_fade( 1.0 ); } level flag::clear( "wait_and_revive" ); level.wait_and_revive = false; self zm_laststand::auto_revive( self ); self.waiting_to_revive = false; // Give player his perks back if he has the "perk_lose" persistent ability if( ( isdefined( self.pers_upgrades_awarded["perk_lose"] ) && self.pers_upgrades_awarded["perk_lose"] ) ) { self thread zm_pers_upgrades_functions::pers_upgrade_perk_lose_restore(); } } function register_vehicle_damage_callback( func ) { if( !IsDefined( level.vehicle_damage_callbacks ) ) { level.vehicle_damage_callbacks = []; } level.vehicle_damage_callbacks[level.vehicle_damage_callbacks.size] = func; } function vehicle_damage_override( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal ) { //apply damage modifiers on the vehicle if( IsDefined( level.vehicle_damage_callbacks ) ) { for( i = 0; i < level.vehicle_damage_callbacks.size; i++ ) { iDamage = self [[ level.vehicle_damage_callbacks[i] ]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal ); } } //TODO Sabarish: Move code from globallogic to here to be more consistent with other zombie damage functions self globallogic_vehicle::Callback_VehicleDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, damageFromUnderneath, modelIndex, partName, vSurfaceNormal ); } // // MUST return the value of the damage override // function actor_damage_override( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType ) { // skip conditions if ( !isdefined( self ) || !isdefined( attacker ) ) return damage; damage = bgb::actor_damage_override( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType ); damage = self check_actor_damage_callbacks( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType ); self.knuckles_extinguish_flames = (weapon.name == "tazer_knuckles"); if ( isdefined( attacker.animname ) && attacker.animname == "quad_zombie" ) { if ( isdefined( self.animname ) && self.animname == "quad_zombie" ) { return 0; } } if ( isdefined( self.killby_interdimensional_gun_hole ) ) { return damage; } else if ( isdefined( self.interdimensional_gun_kill ) ) { if ( isdefined( self.idgun_damage_cb ) ) { self [[ self.idgun_damage_cb ]]( inflictor, attacker ); return 0; } } if ( isdefined( weapon ) ) { if( is_idgun_damage( weapon ) && ( !IsDefined( meansofdeath ) || meansofdeath != "MOD_EXPLOSIVE" ) ) { if( !( self.archetype === "margwa" ) && !( self.archetype === "mechz" )) { self.damageOrigin = vpoint; self.allowdeath = false; self.magic_bullet_shield = true; self.interdimensional_gun_kill = true; self.interdimensional_gun_weapon = weapon; self.interdimensional_gun_attacker = attacker; if ( isdefined( inflictor ) ) { self.interdimensional_gun_inflictor = inflictor; } else { self.interdimensional_gun_inflictor = attacker; } } if ( isdefined( self.idgun_damage_cb ) ) { self [[ self.idgun_damage_cb ]]( inflictor, attacker ); } return 0; } } attacker thread zm_audio::sndPlayerHitAlert( self, meansofdeath, inflictor, weapon ); if ( !isplayer( attacker ) && isdefined( self.non_attacker_func ) ) { if(( isdefined( self.non_attack_func_takes_attacker ) && self.non_attack_func_takes_attacker )) { return self [[ self.non_attacker_func ]]( damage, weapon, attacker ); } else { return self [[ self.non_attacker_func ]]( damage, weapon ); } } if ( IsDefined( attacker ) && IsAI( attacker ) ) { // AI do not do melee damage to teammates if( self.team == attacker.team && meansofdeath == "MOD_MELEE" ) { return 0; } } if ( attacker.classname == "script_vehicle" && isDefined( attacker.owner ) ) { attacker = attacker.owner; } if ( !isdefined( damage ) || !isdefined( meansofdeath ) ) { return damage; } if ( meansofdeath == "" ) { return damage; } // This is the AI system's override damage callback, it must come last! if ( IsDefined( self.aiOverrideDamage ) ) { for ( index = 0; index < self.aiOverrideDamage.size; index++ ) { damageCallback = self.aiOverrideDamage[index]; damage = self [[damageCallback]]( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, undefined ); } if ( damage < 1 ) return 0; damage = int( damage + 0.5 ); } old_damage = damage; final_damage = damage; if ( IsDefined( self.actor_damage_func ) ) { final_damage = [[ self.actor_damage_func ]]( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex ); } // debug /# if ( GetDvarInt( "scr_perkdebug") ) println( "Perk/> Damage Factor: " + final_damage/old_damage + " - Pre Damage: " + old_damage + " - Post Damage: " + final_damage ); #/ if ( ( isdefined( self.in_water ) && self.in_water ) ) { if ( int( final_damage ) >= self.health ) { self.water_damage = true; } } //modifier for the sword in ZOD colliding with zombies if ( IsDefined( inflictor ) && IsDefined( inflictor.archetype ) && inflictor.archetype == "glaive" ) { if( meansofdeath == "MOD_CRUSH" ) { if ( ( IsDefined( inflictor.enemy ) && inflictor.enemy != self ) || ( isdefined( inflictor._glaive_must_return_to_owner ) && inflictor._glaive_must_return_to_owner ) ) { if ( IsDefined( self.archetype ) && self.archetype != "margwa" ) { final_damage += self.health; if ( IsActor( self ) ) { self zombie_utility::gib_random_parts(); } } } else { return 0; } } } if ( isdefined( inflictor ) && isPlayer( attacker ) && attacker == inflictor ) { if ( meansofdeath == "MOD_HEAD_SHOT" || meansofdeath == "MOD_PISTOL_BULLET" || meansofdeath == "MOD_RIFLE_BULLET" ) { attacker.hits++; } } if ( ( isdefined( level.headshots_only ) && level.headshots_only ) && isDefined( attacker ) && isplayer( attacker ) ) { if ( meansofdeath == "MOD_MELEE" && ( sHitLoc == "head" || sHitLoc == "helmet" ) ) { return int( final_damage ); } if ( zm_utility::is_explosive_damage( meansofdeath ) ) { return int( final_damage ); } else if ( !zm_utility::is_headshot( weapon, sHitLoc, meansofdeath ) ) { return 0; } } return int( final_damage ); } function check_actor_damage_callbacks( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType ) { if ( !isdefined( level.actor_damage_callbacks ) ) { return damage; } for ( i = 0; i < level.actor_damage_callbacks.size; i++ ) { newDamage = self [[ level.actor_damage_callbacks[i] ]]( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType ); if ( -1 != newDamage ) { return newDamage; } } return damage; } function register_actor_damage_callback( func ) { if ( !isdefined( level.actor_damage_callbacks ) ) { level.actor_damage_callbacks = []; } level.actor_damage_callbacks[level.actor_damage_callbacks.size] = func; } function actor_damage_override_wrapper( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, modelIndex, surfaceType, vSurfaceNormal ) { damage_override = self actor_damage_override( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType ); willBeKilled = ( self.health - damage_override ) <= 0; if( isdefined( level.zombie_damage_override_callbacks ) ) { foreach( func_override in level.zombie_damage_override_callbacks ) { self thread [[ func_override ]]( willBeKilled, inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, psOffsetTime, boneIndex, surfaceType ); } } bb::logdamage( attacker, self, weapon, damage_override, meansofdeath, shitloc, willBeKilled, willBeKilled ); if ( !willBeKilled || !( isdefined( self.dont_die_on_me ) && self.dont_die_on_me ) ) { self finishActorDamage( inflictor, attacker, damage_override, flags, meansofdeath, weapon, vpoint, vdir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, surfaceType, vSurfaceNormal ); } } function register_zombie_damage_override_callback( func ) { if(!isdefined(level.zombie_damage_override_callbacks))level.zombie_damage_override_callbacks=[]; if ( !isdefined( level.zombie_damage_override_callbacks ) ) level.zombie_damage_override_callbacks = []; else if ( !IsArray( level.zombie_damage_override_callbacks ) ) level.zombie_damage_override_callbacks = array( level.zombie_damage_override_callbacks ); level.zombie_damage_override_callbacks[level.zombie_damage_override_callbacks.size]=func;; } function actor_killed_override(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime) { if ( game["state"] == "postgame" ) { return; } if( isai(attacker) && isDefined( attacker.script_owner ) ) { // if the person who called the dogs in switched teams make sure they don't // get penalized for the kill if ( attacker.script_owner.team != self.team ) attacker = attacker.script_owner; } if( attacker.classname == "script_vehicle" && isDefined( attacker.owner ) ) { attacker = attacker.owner; } if ( isdefined( attacker ) && isplayer( attacker ) ) { multiplier = 1; if( zm_utility::is_headshot( weapon, sHitLoc, sMeansOfDeath ) ) { multiplier = 1.5; } type = undefined; //MM (3/18/10) no animname check if ( IsDefined(self.animname) ) { switch( self.animname ) { case "quad_zombie": type = "quadkill"; break; case "ape_zombie": type = "apekill"; break; case "zombie": type = "zombiekill"; break; case "zombie_dog": type = "dogkill"; break; } } } if(( isdefined( self.is_ziplining ) && self.is_ziplining )) { self.deathanim = undefined; } if ( IsDefined( self.actor_killed_override ) ) { self [[ self.actor_killed_override ]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime ); } if ( IsDefined( self.deathFunction ) ) { self [[ self.deathFunction ]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime ); } } function round_end_monitor() { while(1) { level waittill( "end_of_round" ); demo::bookmark( "zm_round_end", gettime(), undefined, undefined, 1 ); BBPostDemoStreamStatsForRound( level.round_number ); zm_utility::upload_zm_dash_counters(); {wait(.05);}; } } //***************************************************************************** //***************************************************************************** function updateEndOfMatchCounters() { zm_utility::increment_zm_dash_counter( "end_per_game", 1 ); zm_utility::increment_zm_dash_counter( "end_per_player", level.players.size ); if( !( isdefined( level.dash_counter_round_reached_5 ) && level.dash_counter_round_reached_5 ) ) { zm_utility::increment_zm_dash_counter( "end_less_5", 1 ); } else { if( !( isdefined( level.dash_counter_round_reached_10 ) && level.dash_counter_round_reached_10 ) ) { zm_utility::increment_zm_dash_counter( "end_reached_5_less_10", 1 ); } else { zm_utility::increment_zm_dash_counter( "end_reached_10", 1 ); } } if( !zm_utility::is_solo_ranked_game() ) { if( level.dash_counter_start_player_count != level.players.size ) { zm_utility::increment_zm_dash_counter( "end_player_count_diff", 1 ); } } } function end_game() { level waittill ( "end_game" ); check_end_game_intermission_delay(); /# println( "end_game TRIGGERED " ); #/ setmatchflag( "game_ended", 1 ); level clientfield::set("gameplay_started", 0); level clientfield::set("game_end_time", int( ( GetTime() - level.n_gameplay_start_time + 500 ) / 1000 ) ); util::clientnotify( "zesn" ); level thread zm_audio::sndMusicSystem_PlayState( "game_over" ); //AYERS: Turn off ANY last stand audio at the end of the game players = GetPlayers(); for ( i = 0; i < players.size; i++ ) { players[i] clientfield::set( "zmbLastStand", 0 ); } for ( i = 0; i < players.size; i++ ) { if ( players[i] laststand::player_is_in_laststand() ) { players[i] RecordPlayerDeathZombies(); players[i] zm_stats::increment_player_stat( "deaths" ); players[i] zm_stats::increment_client_stat( "deaths" ); players[i] zm_pers_upgrades_functions::pers_upgrade_jugg_player_death_stat(); } //clean up the revive text hud if it's active if( isdefined( players[i].reviveTextHud ) ) { players[i].reviveTextHud destroy(); } } StopAllRumbles(); level.intermission = true; level.zombie_vars["zombie_powerup_insta_kill_time"] = 0; level.zombie_vars["zombie_powerup_fire_sale_time"] = 0; level.zombie_vars["zombie_powerup_double_points_time"] = 0; wait 0.1; game_over = []; survived = []; players = GetPlayers(); //disabled the ingame pause menu from opening after a game ends setMatchFlag( "disableIngameMenu", 1 ); foreach( player in players ) { player closeInGameMenu(); player CloseMenu( "StartMenu_Main" ); } //AAR - set stat for each player (this will show the menu) foreach( player in players ) { player setDStat( "AfterActionReportStats", "lobbyPopup", "summary" ); } if(!isDefined(level._supress_survived_screen)) { for( i = 0; i < players.size; i++ ) { game_over[i] = NewClientHudElem( players[i] ); survived[i] = NewClientHudElem( players[i] ); if ( IsDefined( level.custom_game_over_hud_elem ) ) { [[ level.custom_game_over_hud_elem ]]( players[i], game_over[i], survived[i] ); } else { game_over[i].alignX = "center"; game_over[i].alignY = "middle"; game_over[i].horzAlign = "center"; game_over[i].vertAlign = "middle"; game_over[i].y -= 130; game_over[i].foreground = true; game_over[i].fontScale = 3; game_over[i].alpha = 0; game_over[i].color = ( 1.0, 1.0, 1.0 ); game_over[i].hidewheninmenu = true; game_over[i] SetText( &"ZOMBIE_GAME_OVER" ); game_over[i] FadeOverTime( 1 ); game_over[i].alpha = 1; if ( players[i] isSplitScreen() ) { game_over[i].fontScale = 2; game_over[i].y += 40; } survived[i].alignX = "center"; survived[i].alignY = "middle"; survived[i].horzAlign = "center"; survived[i].vertAlign = "middle"; survived[i].y -= 100; survived[i].foreground = true; survived[i].fontScale = 2; survived[i].alpha = 0; survived[i].color = ( 1.0, 1.0, 1.0 ); survived[i].hidewheninmenu = true; if ( players[i] isSplitScreen() ) { survived[i].fontScale = 1.5; survived[i].y += 40; } } //OLD COUNT METHOD if( level.round_number < 2 ) { if( level.script == "zm_moon" ) { if( !isdefined(level.left_nomans_land) ) { nomanslandtime = level.nml_best_time; player_survival_time = int( nomanslandtime/1000 ); player_survival_time_in_mins = zm::to_mins( player_survival_time ); survived[i] SetText( &"ZOMBIE_SURVIVED_NOMANS", player_survival_time_in_mins ); } else if( level.left_nomans_land == 2 ) { survived[i] SetText( &"ZOMBIE_SURVIVED_ROUND" ); } } else { survived[i] SetText( &"ZOMBIE_SURVIVED_ROUND" ); } } else { survived[i] SetText( &"ZOMBIE_SURVIVED_ROUNDS", level.round_number ); } survived[i] FadeOverTime( 1 ); survived[i].alpha = 1; } } //check to see if we are in a game module that wants to do something with PvP damage if(isDefined(level.custom_end_screen)) { level [[level.custom_end_screen]](); } for (i = 0; i < players.size; i++) { players[i] SetClientUIVisibilityFlag( "weapon_hud_visible", 0 ); players[i] SetClientMiniScoreboardHide( true ); //players[i] setDStat( "AfterActionReportStats", "lobbyPopup", "summary" ); players[i] notify( "report_bgb_consumption" ); players[i] zm_utility::zm_dash_stats_game_end(); } //LUINotifyEvent( &"force_scoreboard", 0 ); UploadStats(); zm_stats::update_players_stats_at_match_end( players ); zm_stats::update_global_counters_on_match_end(); bb::logroundevent("end_game"); upload_leaderboards(); recordGameResult( "draw" ); globallogic::recordZMEndGameComScoreEvent( "draw" ); globallogic_player::recordActivePlayersEndGameMatchRecordStats(); updateEndOfMatchCounters(); //update dash and promo counters if( SessionModeIsOnlineGame() ) { level thread zm_utility::upload_zm_dash_counters_end_game(); } // Finalize Match Record finalizeMatchRecord(); //zm_utility::play_sound_at_pos( "end_of_game", ( 0, 0, 0 ) ); players = GetPlayers(); foreach( player in players ) { if( IsDefined( player.sessionstate ) && player.sessionstate == "spectator" ) { player.sessionstate = "playing"; player thread end_game_player_was_spectator(); } } {wait(.05);}; /# if ( !( isdefined( level.host_ended_game ) && level.host_ended_game ) && GetDvarInt( "scr_restart_on_wipe" ) > 1 ) { LUINotifyEvent( &"force_scoreboard", 0 ); map_restart( true ); wait( 666 ); } #/ players = GetPlayers(); LUINotifyEvent( &"force_scoreboard", 1, 1 ); intermission(); wait( level.zombie_vars["zombie_intermission_time"] ); // hide the gameover message if ( !isDefined( level._supress_survived_screen ) ) { for ( i = 0; i < players.size; i++ ) { survived[i] Destroy(); game_over[i] Destroy(); } } else { for ( i = 0; i < players.size; i++ ) { if(isDefined(players[i].survived_hud ) ) players[i].survived_hud Destroy(); if (isDefined( players[i].game_over_hud ) ) players[i].game_over_hud Destroy(); } } level notify( "stop_intermission" ); array::thread_all( GetPlayers(), &player_exit_level ); wait( 1.5 ); players = GetPlayers(); for ( i = 0; i < players.size; i++ ) { players[i] CameraActivate( false ); } /# if ( !( isdefined( level.host_ended_game ) && level.host_ended_game ) && GetDvarInt( "scr_restart_on_wipe" ) ) { LUINotifyEvent( &"force_scoreboard", 1, 0 ); map_restart( true ); wait( 666 ); } #/ ExitLevel( false ); // Let's not exit the function wait( 666 ); } //***************************************************************************** //***************************************************************************** function end_game_player_was_spectator() { {wait(.05);}; self Ghost(); self FreezeControls( true ); } //***************************************************************************** //***************************************************************************** function disable_end_game_intermission( delay ) { level.disable_intermission = true; wait( delay ); level.disable_intermission = undefined; } //***************************************************************************** //***************************************************************************** function check_end_game_intermission_delay() { if( IsDefined(level.disable_intermission) ) { while( 1 ) { if( !IsDefined(level.disable_intermission) ) { break; } wait( 0.01 ); } } } //***************************************************************************** // This will save the leaderboard data per round, for use in single player //***************************************************************************** function upload_leaderboards() { // place restrictions on whether leaderboards are uploaded to in the precache leaderboards function players = GetPlayers(); for( i = 0; i < players.size; i++ ) { players[i] uploadleaderboards(); } } function initializeStatTracking() { level.global_zombies_killed = 0; level.zombies_timeout_spawn = 0; level.zombies_timeout_playspace = 0; level.zombies_timeout_undamaged = 0; level.zombie_player_killed_count = 0; level.zombie_trap_killed_count = 0; level.zombie_pathing_failed = 0; level.zombie_breadcrumb_failed = 0; } function uploadGlobalStatCounters() { incrementCounter( "global_zombies_killed", level.global_zombies_killed ); incrementCounter( "global_zombies_killed_by_players", level.zombie_player_killed_count ); incrementCounter( "global_zombies_killed_by_traps", level.zombie_trap_killed_count ); } function player_fake_death() { level notify ("fake_death"); self notify ("fake_death"); self TakeAllWeapons(); self AllowStand( false ); self AllowCrouch( false ); self AllowProne( true ); self.ignoreme = true; self EnableInvulnerability(); wait( 1 ); self FreezeControls( true ); } function player_exit_level() { self AllowStand( true ); self AllowCrouch( false ); self AllowProne( false ); //self thread lui::screen_fade_out( 1 ); } function player_killed_override(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration) { // BLANK level waittill( "forever" ); } function player_zombie_breadcrumb() { self notify("stop_player_zombie_breadcrumb"); self endon("stop_player_zombie_breadcrumb"); self endon( "disconnect" ); self endon( "spawned_spectator" ); level endon( "intermission" ); self.zombie_breadcrumbs = []; self.zombie_breadcrumb_distance = 24 * 24; // min dist (squared) the player must move to drop a crumb self.zombie_breadcrumb_area_num = 3; // the number of "rings" the area breadcrumbs use self.zombie_breadcrumb_area_distance = 16; // the distance between each "ring" of the area breadcrumbs self store_crumb( self.origin ); last_crumb = self.origin; self thread zm_utility::debug_breadcrumbs(); while( 1 ) { wait_time = 0.1; if( self.ignoreme ) { wait( wait_time ); continue; } //For cloaking ability //if( self.ignoreme ) //{ // wait( wait_time ); // continue; //} store_crumb = true; airborne = false; crumb = self.origin; //TODO TEMP SCRIPT for vehicle testing Delete/comment when done if ( !self IsOnGround() && self isinvehicle() ) { trace = bullettrace( self.origin + (0,0,10), self.origin, false, undefined ); crumb = trace["position"]; } //TODO TEMP DISABLE for vehicle testing. Uncomment when reverting // if ( !self IsOnGround() ) // { // airborne = true; // store_crumb = false; // wait_time = 0.05; // } // if( !airborne && DistanceSquared( crumb, last_crumb ) < self.zombie_breadcrumb_distance ) { store_crumb = false; } if ( airborne && self IsOnGround() ) { // player was airborne, store crumb now that he's on the ground store_crumb = true; airborne = false; } if( isDefined( level.custom_breadcrumb_store_func ) ) { store_crumb = self [[ level.custom_breadcrumb_store_func ]]( store_crumb ); } if( isDefined( level.custom_airborne_func ) ) { airborne = self [[ level.custom_airborne_func ]]( airborne ); } if( store_crumb ) { zm_utility::debug_print( "Player is storing breadcrumb " + crumb ); if( IsDefined(self.node) ) { zm_utility::debug_print( "has closest node " ); } last_crumb = crumb; self store_crumb( crumb ); } wait( wait_time ); } } function store_crumb( origin ) { offsets = []; height_offset = 32; index = 0; for( j = 1; j <= self.zombie_breadcrumb_area_num; j++ ) { offset = ( j * self.zombie_breadcrumb_area_distance ); offsets[0] = ( origin[0] - offset, origin[1], origin[2] ); offsets[1] = ( origin[0] + offset, origin[1], origin[2] ); offsets[2] = ( origin[0], origin[1] - offset, origin[2] ); offsets[3] = ( origin[0], origin[1] + offset, origin[2] ); offsets[4] = ( origin[0] - offset, origin[1], origin[2] + height_offset ); offsets[5] = ( origin[0] + offset, origin[1], origin[2] + height_offset ); offsets[6] = ( origin[0], origin[1] - offset, origin[2] + height_offset ); offsets[7] = ( origin[0], origin[1] + offset, origin[2] + height_offset ); for ( i = 0; i < offsets.size; i++ ) { self.zombie_breadcrumbs[index] = offsets[i]; index++; } } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////LEADERBOARD CODE/////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function to_mins( seconds ) { hours = 0; minutes = 0; if( seconds > 59 ) { minutes = int( seconds / 60 ); seconds = int( seconds * 1000 ) % ( 60 * 1000 ); seconds = seconds * 0.001; if( minutes > 59 ) { hours = int( minutes / 60 ); minutes = int( minutes * 1000 ) % ( 60 * 1000 ); minutes = minutes * 0.001; } } if( hours < 10 ) { hours = "0" + hours; } if( minutes < 10 ) { minutes = "0" + minutes; } seconds = Int( seconds ); if( seconds < 10 ) { seconds = "0" + seconds; } combined = "" + hours + ":" + minutes + ":" + seconds; return combined; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // INTERMISSION =========================================================== // // function intermission() { level.intermission = true; level notify( "intermission" ); players = GetPlayers(); for( i = 0; i < players.size; i++ ) { players[i] SetClientThirdPerson( 0 ); players[i] resetFov(); players[i].health = 100; // This is needed so the player view doesn't get stuck players[i] thread [[level.custom_intermission]](); players[i] StopSounds(); } wait( 5.25 ); players = GetPlayers(); for( i = 0; i < players.size; i++ ) { players[i] clientfield::set( "zmbLastStand", 0 ); } level thread zombie_game_over_death(); } function zombie_game_over_death() { // Kill remaining zombies, in style! zombies = GetAiTeamArray( level.zombie_team ); for( i = 0; i < zombies.size; i++ ) { if( !IsAlive( zombies[i] ) ) { continue; } zombies[i] SetGoal( zombies[i].origin ); } for( i = 0; i < zombies.size; i++ ) { if( !IsAlive( zombies[i] ) ) { continue; } if ( ( isdefined( zombies[i].ignore_game_over_death ) && zombies[i].ignore_game_over_death ) ) { continue; } wait( 0.5 + RandomFloat( 2 ) ); if ( isdefined( zombies[i] ) ) { if( !IsVehicle( zombies[i] ) ) { zombies[i] zombie_utility::zombie_head_gib(); } zombies[i] Kill(); } } } function screen_fade_in( n_time, v_color, str_menu_id ) { lui::screen_fade( n_time, 0, 1, v_color, false, str_menu_id ); wait n_time; } function player_intermission() { self closeInGameMenu(); self CloseMenu( "StartMenu_Main" ); self notify("player_intermission"); self endon("player_intermission"); level endon( "stop_intermission" ); self endon("disconnect"); self endon("death"); self notify( "_zombie_game_over" ); // ww: notify so hud elements know when to leave //Show total gained point for end scoreboard and lobby self.score = self.score_total; points =struct::get_array( "intermission", "targetname" ); if( !IsDefined( points ) || points.size == 0 ) { points = getentarray( "info_intermission", "classname" ); if( points.size < 1 ) { /# println( "NO info_intermission POINTS IN MAP" ); #/ return; } } if ( ( isdefined( level.b_show_single_intermission ) && level.b_show_single_intermission ) ) { a_s_temp_points = array::randomize( points ); points = []; points[0] = array::random( a_s_temp_points ); } else { points = array::randomize( points ); } self zm_utility::create_streamer_hint( points[0].origin, points[0].angles, 0.9 ); wait( 5 ); self lui::screen_fade_out( 1 ); // don't do this unti we're ready to "spawn" the players in the exit scenes // the player camera will clip into the ground if this is done too early self.sessionstate = "intermission"; self.spectatorclient = -1; self.killcamentity = -1; self.archivetime = 0; self.psoffsettime = 0; self.friendlydamage = undefined; if ( isdefined( level.player_intemission_spawn_callback ) ) { self thread [[ level.player_intemission_spawn_callback ]] ( points[0].origin, points[0].angles ); } while( 1 ) { for( i = 0; i < points.size; i++ ) { point = points[i]; nextpoint = points[i+1]; self SetOrigin( point.origin ); self SetPlayerAngles( point.angles ); wait 0.15; self notify("player_intermission_spawned"); if ( IsDefined(nextpoint) ) { self zm_utility::create_streamer_hint( nextpoint.origin, nextpoint.angles, 0.9 ); self screen_fade_in( 2 ); wait( 3 ); self lui::screen_fade_out( 2 ); } else { self screen_fade_in( 2 ); if ( points.size == 1 ) { return; } } } } } function fade_up_over_time(t) { self FadeOverTime( t ); self.alpha = 1; } function default_exit_level() { zombies = GetAiTeamArray( level.zombie_team ); for ( i = 0; i < zombies.size; i++ ) { if ( ( isdefined( zombies[i].ignore_solo_last_stand ) && zombies[i].ignore_solo_last_stand ) ) { continue; } if ( isDefined( zombies[i].find_exit_point ) ) { zombies[i] thread [[ zombies[i].find_exit_point ]](); continue; } if ( zombies[i].ignoreme ) { zombies[i] thread default_delayed_exit(); } else { zombies[i] thread default_find_exit_point(); } } } function default_delayed_exit() { self endon( "death" ); while ( 1 ) { if ( !level flag::get( "wait_and_revive" ) ) { return; } // broke through the barricade, find an exit point if ( !self.ignoreme ) { break; } wait( 0.1 ); } self thread default_find_exit_point(); } function default_find_exit_point() { self endon( "death" ); player = GetPlayers()[0]; dist_zombie = 0; dist_player = 0; dest = 0; away = VectorNormalize( self.origin - player.origin ); endPos = self.origin + VectorScale( away, 600 ); if ( isdefined( level.zm_loc_types[ "wait_location" ] ) && level.zm_loc_types[ "wait_location" ].size > 0 ) { locs = array::randomize( level.zm_loc_types[ "wait_location" ] ); } //TODO Add wait_locations to Der Reise and we can remove this line else // Legacy catch { locs = array::randomize( level.zm_loc_types[ "dog_location" ] ); } for ( i = 0; i < locs.size; i++ ) { dist_zombie = DistanceSquared( locs[i].origin, endPos ); dist_player = DistanceSquared( locs[i].origin, player.origin ); if ( dist_zombie < dist_player ) { dest = i; break; } } self notify( "stop_find_flesh" ); self notify( "zombie_acquire_enemy" ); if( isdefined( locs[dest] ) ) { self SetGoal( locs[dest].origin ); } while ( 1 ) { // 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 b_passed_override = true; // Returning 'false' from the level override will put zombies back into find_flesh if ( IsDefined( level.default_find_exit_position_override ) ) { b_passed_override = [[ level.default_find_exit_position_override ]](); } if ( !level flag::get( "wait_and_revive" ) && b_passed_override ) { break; } wait( 0.1 ); } } function play_level_start_vox_delayed() { wait(3); players = GetPlayers(); num = RandomIntRange( 0, players.size ); players[num] zm_audio::create_and_play_dialog( "general", "intro" ); } function register_sidequest( id, sidequest_stat ) { if ( !IsDefined( level.zombie_sidequest_stat ) ) { level.zombie_sidequest_previously_completed = []; level.zombie_sidequest_stat = []; } level.zombie_sidequest_stat[id] = sidequest_stat; //level flag::wait_till( "all_players_spawned" ); level flag::wait_till( "start_zombie_round_logic" ); level.zombie_sidequest_previously_completed[id] = false; // don't do stats stuff if it's not an online game if ( !level.onlineGame ) { return; } //don't do stats stuff if stats are disabled if ( ( isdefined( level.zm_disable_recording_stats ) && level.zm_disable_recording_stats ) ) { return; } players = GetPlayers(); for ( i = 0; i < players.size; i++ ) { if ( players[i] zm_stats::get_global_stat( level.zombie_sidequest_stat[id] ) ) { level.zombie_sidequest_previously_completed[id] = true; return; } } } function is_sidequest_previously_completed(id) { return ( isdefined( level.zombie_sidequest_previously_completed[id] ) && level.zombie_sidequest_previously_completed[id] ); } function set_sidequest_completed(id) { level notify( "zombie_sidequest_completed", id ); level.zombie_sidequest_previously_completed[id] = true; // don't do stats stuff if it's not an online game if ( !level.onlineGame ) { return; } //don't do stats stuff if stats are disabled if ( ( isdefined( level.zm_disable_recording_stats ) && level.zm_disable_recording_stats ) ) { return; } players = GetPlayers(); for ( i = 0; i < players.size; i++ ) { if ( isdefined( level.zombie_sidequest_stat[id] ) ) { players[i] zm_stats::add_global_stat( level.zombie_sidequest_stat[id], 1 ); } } } function playSwipeSound( mod, attacker ) { if( ( isdefined( attacker.is_zombie ) && attacker.is_zombie ) || (isdefined( attacker.archetype ) && attacker.archetype == "margwa" ) ) { self playsoundtoplayer( "evt_player_swiped", self ); return; } } function precache_zombie_leaderboards() { // don't save leaderboards for systemlink or custom games if( SessionModeIsSystemlink() ) { return; } // GLOBAL LEADERBOARDS globalLeaderboards = "LB_ZM_GB_BULLETS_FIRED_AT "; globalLeaderboards += "LB_ZM_GB_BULLETS_HIT_AT "; globalLeaderboards += "LB_ZM_GB_DISTANCE_TRAVELED_AT "; globalLeaderboards += "LB_ZM_GB_DOORS_PURCHASED_AT "; globalLeaderboards += "LB_ZM_GB_GRENADE_KILLS_AT "; globalLeaderboards += "LB_ZM_GB_HEADSHOTS_AT "; globalLeaderboards += "LB_ZM_GB_KILLS_AT "; globalLeaderboards += "LB_ZM_GB_PERKS_DRANK_AT "; globalLeaderboards += "LB_ZM_GB_REVIVES_AT "; //Multirank globalLeaderboards += "LB_ZM_GB_KILLSTATS_MR "; globalLeaderboards += "LB_ZM_GB_GAMESTATS_MR "; if ( !level.rankedMatch && (GetDvarInt( "zm_private_rankedmatch", 0 ) == 0) ) { precacheLeaderboards( globalLeaderboards ); return; } // MAP LEADERBOARD mapname = GetDvarString( "mapname" ); expectedPlayerNum = GetNumExpectedPlayers(); mapLeaderboard = "LB_ZM_MAP_"+ getsubstr( mapname, 3, mapname.size ) + "_" + expectedPlayerNum + "PLAYER"; precacheLeaderboards( globalLeaderboards + mapLeaderboard ); } function zm_on_player_connect() { if( level.passed_introscreen) { self setClientUIVisibilityFlag( "hud_visible", 1 ); self setClientUIVisibilityFlag( "weapon_hud_visible", 1 ); zm_utility::increment_zm_dash_counter( "hotjoined", 1 ); zm_utility::upload_zm_dash_counters(); } self flag::init( "used_consumable" ); self thread zm_utility::zm_dash_stats_game_start(); self thread zm_utility::zm_dash_stats_wait_for_consumable_use(); thread refresh_player_navcard_hud(); self thread watchDisconnect(); self.hud_damagefeedback = newdamageindicatorhudelem(self); self.hud_damagefeedback.horzAlign = "center"; self.hud_damagefeedback.vertAlign = "middle"; self.hud_damagefeedback.x = -12; self.hud_damagefeedback.y = -12; self.hud_damagefeedback.alpha = 0; self.hud_damagefeedback.archived = true; self.hud_damagefeedback setShader( "damage_feedback", 24, 48 ); self.hitSoundTracker = true; } function zm_on_player_disconnect() { thread refresh_player_navcard_hud(); zm_utility::increment_zm_dash_counter( "left_midgame", 1 ); zm_utility::upload_zm_dash_counters(); } function watchDisconnect() { self notify("watchDisconnect"); self endon("watchDisconnect"); self waittill("disconnect"); zm_on_player_disconnect(); } function increment_dog_round_stat(stat) { players = GetPlayers(); foreach(player in players) { player zm_stats::increment_client_stat( "zdog_rounds_" + stat ); } } function setup_player_navcard_hud() { level flag::wait_till( "start_zombie_round_logic" ); thread refresh_player_navcard_hud(); } function refresh_player_navcard_hud() { if (!IsDefined(level.navcards)) return; players = GetPlayers(); foreach( player in players ) { navcard_bits = 0; for(i = 0;i < level.navcards.size; i++) { hasit = player zm_stats::get_global_stat( level.navcards[i] ); if (isdefined(player.navcard_grabbed) && player.navcard_grabbed == level.navcards[i] ) hasit = 1; if( hasit ) { navcard_bits +=( 1 << i ); } } util::wait_network_frame(); player clientfield::set( "navcard_held", 0 ); if ( navcard_bits > 0 ) { util::wait_network_frame(); player clientfield::set( "navcard_held", navcard_bits ); } } } function set_default_laststand_pistol(solo_mode) { if (!solo_mode ) { level.laststandpistol = level.default_laststandpistol; } else { level.laststandpistol = level.default_solo_laststandpistol; } } //109171 Zombies - ZM_Global - Add check for player count at beginning of the game //monitors during the match for exploits extra players being able to join the match function player_too_many_players_check() { max_players = 4; if ( level.scr_zm_ui_gametype == "zgrief" || level.scr_zm_ui_gametype == "zmeat" ) { max_players = 8; } if ( GetPlayers().size > max_players ) { zm_game_module::freeze_players(true); level notify("end_game"); } } //vehicle response to idgun damage function is_idgun_damage( weapon ) { if( isdefined( level.idgun_weapons ) ) { if ( IsInArray( level.idgun_weapons, weapon ) ) return true; } return false; } function zm_on_player_spawned() { thread update_zone_name(); thread update_is_player_valid(); } function update_is_player_valid() { self endon( "death" ); self endon( "disconnnect" ); self.am_i_valid = true; while ( isDefined( self ) ) { self.am_i_valid = zm_utility::is_player_valid( self, true ); {wait(.05);} } } function update_zone_name() { self endon( "death" ); self endon( "disconnnect" ); self.zone_name = zm_utility::get_current_zone(); if ( isDefined( self.zone_name ) ) { self.previous_zone_name = self.zone_name; } while ( isDefined( self ) ) { if( isDefined( self.zone_name ) ) { self.previous_zone_name = self.zone_name; } self.zone_name = zm_utility::get_current_zone(); wait RandomFloatRange( 0.5, 1.0 ); } } /# function printHashIDs() { outputString = "\n------------------- BEGIN HASH ID DUMP -----------------------------\n"; //Print Craftables outputString += "** CRAFTABLES **\n"; foreach( s_craftable in level.zombie_include_craftables ) { outputString += "+" + s_craftable.name + "," + s_craftable.hash_id + "\n"; if (!isDefined(s_craftable.a_piecestubs)) { continue; } foreach( s_piece in s_craftable.a_piecestubs ) { outputString += s_piece.pieceName + "," + s_piece.hash_id + "\n"; } } //Print Powerups outputString += "** POWERUPS **\n"; foreach ( powerup in level.zombie_powerups) { outputString += powerup.powerup_name + "," + powerup.hash_id + "\n"; } //Print AATs outputString += "** AAT **\n"; if( ( isdefined( level.aat_in_use ) && level.aat_in_use ) ) { foreach (aat in level.aat) { if (!isDefined(aat) || !isDefined(aat.name) || aat.name == "none") { continue; } outputString += aat.name + "," + aat.hash_id + "\n"; } } //Print AATs outputString += "** PERKS **\n"; foreach (perk in level._custom_perks) { if (!isDefined(perk) || !isDefined(perk.alias)) { continue; } outputString += perk.alias + "," + perk.hash_id + "\n"; } outputString += "------------------- END HASH ID DUMP -----------------------------\n"; PrintLn(outputString); } #/