From 3b8633823613a69ee382d6a3e30c728fd98e3f50 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Fri, 24 Apr 2020 10:21:48 -0700 Subject: [PATCH] see description Added several new scripts to the no known errors category, but also moved some scripts to improper debug methods category. Added new scripts that need debugging which includes the remainder of the zombies class of scripts in patch_zm. Updated the debugging script and readme with more exact instructions to its usage. Will work on many of the remaining zombies scripts and eventually move to gametypes_zm scripts. --- debugging mod/_zm_bot.gsc | 105 +- debugging mod/readme.md | 47 + debugging_guide.md | 1 + .../maps/mp/gametypes_zm/_zm_gametype.gsc | 146 +- patch_zm/maps/mp/zombies/_load.gsc | 114 +- patch_zm/maps/mp/zombies/_zm_blockers.gsc | 2513 +++++++ patch_zm/maps/mp/zombies/_zm_buildables.gsc | 3195 +++++++++ patch_zm/maps/mp/zombies/_zm_devgui.gsc | 2344 +++++++ .../maps/mp/zombies/_zm_equip_turbine.gsc | 789 +++ patch_zm/maps/mp/zombies/_zm_game_module.gsc | 491 ++ patch_zm/maps/mp/zombies/_zm_jump_pad.gsc | 557 ++ patch_zm/maps/mp/zombies/_zm_laststand.gsc | 1459 ++++ .../maps/mp/zombies/_zm_magicbox_lock.gsc | 98 + patch_zm/maps/mp/zombies/_zm_mgturret.gsc | 339 + patch_zm/maps/mp/zombies/_zm_perks.gsc | 196 +- patch_zm/maps/mp/zombies/_zm_playerhealth.gsc | 583 ++ patch_zm/maps/mp/zombies/_zm_power.gsc | 741 +++ patch_zm/maps/mp/zombies/_zm_powerups.gsc | 676 +- patch_zm/maps/mp/zombies/_zm_score.gsc | 46 +- patch_zm/maps/mp/zombies/_zm_sidequests.gsc | 1130 ++++ patch_zm/maps/mp/zombies/_zm_stats.gsc | 1079 +++ patch_zm/maps/mp/zombies/_zm_tombstone.gsc | 200 +- patch_zm/maps/mp/zombies/_zm_traps.gsc | 948 +++ patch_zm/maps/mp/zombies/_zm_turned.gsc | 447 ++ patch_zm/maps/mp/zombies/_zm_unitrigger.gsc | 800 +++ patch_zm/maps/mp/zombies/_zm_utility.gsc | 5861 +++++++++++++++++ .../mp/zombies/_zm_weap_cymbal_monkey.gsc | 577 ++ patch_zm/readme.md | 59 +- 28 files changed, 24709 insertions(+), 832 deletions(-) create mode 100644 patch_zm/maps/mp/zombies/_zm_blockers.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_buildables.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_devgui.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_equip_turbine.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_game_module.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_jump_pad.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_laststand.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_magicbox_lock.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_mgturret.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_playerhealth.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_power.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_sidequests.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_stats.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_traps.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_turned.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_unitrigger.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_utility.gsc create mode 100644 patch_zm/maps/mp/zombies/_zm_weap_cymbal_monkey.gsc diff --git a/debugging mod/_zm_bot.gsc b/debugging mod/_zm_bot.gsc index 28d9d1a..8409a72 100644 --- a/debugging mod/_zm_bot.gsc +++ b/debugging mod/_zm_bot.gsc @@ -1,3 +1,6 @@ +#include maps/mp/_utility; +#include maps/common_scripts/utility; + init() { debug_tracker(); @@ -8,13 +11,109 @@ debug_tracker() numberOfScriptsBeingLogged = 0; if ( !isDefined( level.debugLogging ) ) { - level.debugLogging = 1; + level.debugLogging = getDvarIntDefault( "debugModDebugLoggingActive", 1 ); + } + if ( isDefined( level.customZgrief_loaded ) && level.customZgrief_loaded ) + { + level.debugLoggingZgrief = getDvarIntDefault( "debugModDebugLoggingZgrief", 1 ); + numberOfScriptsBeingLogged++; + } + if ( isDefined( level.custom_zm_loaded ) && level.custom_zm_loaded ) + { + level.debugLogging_zm = getDvarIntDefault( "debugModDebugLogging_zm", 1 ); + numberOfScriptsBeingLogged++; } if ( isDefined( level.custom_zm_ai_dogs_loaded ) && level.custom_zm_ai_dogs_loaded ) { - level.debugLogging_zm_ai_dogs = 1; + level.debugLogging_zm_ai_dogs = getDvarIntDefault( "debugModDebugLogging_zm_ai_dogs", 1 ); numberOfScriptsBeingLogged++; } - level.player_starting_points = 1000000; + if ( isDefined( level.custom_zm_audio_loaded ) && level.custom_zm_audio_loaded ) + { + level.debugLogging_zm_audio = getDvarIntDefault( "debugModDebugLogging_zm_audio", 1 ); + numberOfScriptsBeingLogged++; + } + if ( isDefined( level.custom_zm_magicbox_loaded ) && level.custom_zm_magicbox_loaded ) + { + level.debugLogging_zm_magicbox = getDvarIntDefault( "debugModDebugLogging_zm_magicbox", 1 ); + numberOfScriptsBeingLogged++; + } + if ( isDefined( level.custom_zm_perks_loaded ) && level.custom_zm_perks_loaded ) + { + level.debugLogging_zm_perks = getDvarIntDefault( "debugModDebugLogging_zm_perks", 1 ); + numberOfScriptsBeingLogged++; + } + if ( isDefined( level.custom_zm_perk_electric_cherry_loaded ) && level.custom_zm_perk_electric_cherry_loaded ) + { + level.debugLogging_zm_perk_electric_cherry = getDvarIntDefault( "debugModDebugLogging_zm_perk_electric_cherry", 1 ); + numberOfScriptsBeingLogged++; + } + if ( isDefined( level.custom_zm_powerups_loaded ) && level.custom_zm_powerups_loaded ) + { + level.debugLogging_zm_powerups = getDvarIntDefault( "debugModDebugLogging_zm_powerups", 1 ); + numberOfScriptsBeingLogged++; + } + if ( isDefined( level.custom_zm_spawner_loaded ) && level.custom_zm_spawner_loaded ) + { + level.debugLogging_zm_spawner = getDvarIntDefault( "debugModDebugLogging_zm_spawner", 1 ); + numberOfScriptsBeingLogged++; + } + if ( isDefined( level.custom_zm_weapons_loaded ) && level.custom_zm_weapons_loaded ) + { + level.debugLogging_zm_weapons = getDvarIntDefault( "debugModDebugLogging_zm_weapons", 1 ); + numberOfScriptsBeingLogged++; + } + level.player_starting_points = getDvarIntDefault( "debugModStartingPoints", 500 ); + if ( getDvarIntDefault( "debugModTestBotsEnabled", 0 ) == 1 ) + { + level thread add_bots(); + } + level.errorDisplayLevel = getDvarIntDefault( "debugModErrorDisplay", 0 ); //Use this to choose what is written to the log + //Error levels: + //0 - Display all types of log messages + //1 - Display only errors + //2 - Display only warnings + //3 - Display only info } +add_bots() +{ + //Wait for the host! + players = get_players(); + while ( players.size < 1 ) + { + players = get_players(); + wait 1; + } + //Then spawn bots + botsToSpawn = getDvarIntDefault( "debugModBotsToSpawn", 1 ) + for ( currentBots = 0; currentBots < botsToSpawn; currentBots++ ) + { + zbot_spawn(); + wait 1; + } + SetDvar("bot_AllowMovement", "1"); + SetDvar("bot_PressAttackBtn", "1"); + SetDvar("bot_PressMeleeBtn", "1"); +} + +zbot_spawn() +{ + bot = AddTestClient(); + if ( !IsDefined( bot ) ) + { + return; + } + + bot.pers["isBot"] = true; + bot.equipment_enabled = false; + return bot; +} + + + + + + + + diff --git a/debugging mod/readme.md b/debugging mod/readme.md index 456f24f..448c3d7 100644 --- a/debugging mod/readme.md +++ b/debugging mod/readme.md @@ -6,7 +6,17 @@ What is does it override the typical _zm_bot.gsc logic, and replaces it with glo **Currently only the following scripts are supported**: ``` +zgrief.gsc _zm_ai_dogs.gsc +_zm_audio.gsc +_zm_magicbox.gsc +_perks.gsc +_zm_perk_electric_cherry.gsc +_zm_powerups.gsc +_zm_spawner.gsc +_zm_weapons.gsc + + ``` ## How it Works @@ -14,3 +24,40 @@ _zm_ai_dogs.gsc Compile _zm_bot.gsc as _zm_bot.gsc and place it in maps/mp/zombies. It automatically has the debug variables set to 1 so it will be active. It works by writing to the log useful events that may need monitoring in order to determine broken aspects of the script. To disable it simply remove the mod or modify the vars in the mod. + +## How to Make Use of The Mod + +If you want to debug scripts on your own copy and paste this template into the code you would like to monitor: +``` +if ( ( level.errorDisplayLevel == 0 || level.errorDisplayLevel == 1 ) && level.debugLogging_zm_audio ) +{ + logline1 = "ERROR_TYPE: GSC_FILE_NAME.gsc FUNCTION_THIS_IS_CALLED_IN yourtext" + "\n"; + logprint( logline1 ); +} +``` +By using this exact template to debug your code you can run multiple loglines that will print to your server log in data/logs. +Key: +ERROR_TYPE = INFO or ERROR or WARNING use these to indicate whether a log message is just information or is an unexpected error or something isn't right. +GSC_FILE_NAME = this is the actual .gsc you are currently debugging this can be useful if you are debugging mutliple scripts at once so it easier to sift thru the log. +FUNCTION_THIS_IS_CALLED_IN = use this to indicate what function this log message is inside of to again make it easier to tell what messages are coming from what. +If you would like to debug a script that isn't already supported use this template and place it in the very top of the init() in whatever script you would like to debug: +``` +//begin debug code +level.custom_GSC_FILE_NAME_loaded = 1; +maps/mp/zombies/_zm_bot::init(); +if ( !isDefined( level.debugLogging_GSC_FILE_NAME ) ) +{ + level.debugLogging_GSC_FILE_NAME = 0; +} +//end debug code +``` +and then put this in the _zm_bot.gsc debug_tracker() included with this guide: +``` +if ( isDefined( level.custom_GSC_FILE_NAME_loaded ) && level.custom_GSC_FILE_NAME_loaded ) +{ + level.debugLogging_GSC_FILE_NAME = getDvarIntDefault( "debugModDebugLogging_GSC_FILE_NAME", 1 ); + numberOfScriptsBeingLogged++; +} +``` +In both of these replace GSC_FILE_NAME with the name of the .gsc you are debugging. + diff --git a/debugging_guide.md b/debugging_guide.md index 5c42760..5d9199b 100644 --- a/debugging_guide.md +++ b/debugging_guide.md @@ -47,3 +47,4 @@ This can also happen when a client connects so controls are frozen. This can also happen with a blackscreen that doesn't pass. + diff --git a/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc b/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc index ce237f9..ce765e0 100644 --- a/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc +++ b/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc @@ -20,15 +20,12 @@ #include maps/mp/gametypes_zm/_hud_util; #include maps/mp/_utility; -main() +main() //checked matches cerberus output { - //the bare minimum for a zombies game maps/mp/gametypes_zm/_globallogic::init(); maps/mp/gametypes_zm/_callbacksetup::setupcallbacks(); globallogic_setupdefault_zombiecallbacks(); menu_init(); - - //controls several gamemode specific variables non essential registerroundlimit( 1, 1 ); registertimelimit( 0, 0 ); registerscorelimit( 0, 0 ); @@ -38,9 +35,6 @@ main() maps/mp/gametypes_zm/_weapons::registerthrowngrenadeduddvar( level.gametype, 0, 0, 1440 ); maps/mp/gametypes_zm/_weapons::registerkillstreakdelay( level.gametype, 0, 0, 1440 ); maps/mp/gametypes_zm/_globallogic::registerfriendlyfiredelay( level.gametype, 15, 0, 1440 ); - - - //determines many aspects of the game non essential level.takelivesondeath = 1; level.teambased = 1; level.disableprematchmessages = 1; @@ -60,14 +54,11 @@ main() level.dontshowendreason = 1; level.forceallallies = 0; level.allow_teamchange = 0; - - //non essential dvars setdvar( "scr_disable_team_selection", 1 ); makedvarserverinfo( "scr_disable_team_selection", 1 ); setmatchflag( "hud_zombie", 1 ); setdvar( "scr_disable_weapondrop", 1 ); setdvar( "scr_xpscale", 0 ); - level.onstartgametype = ::onstartgametype; level.onspawnplayer = ::blank; level.onspawnplayerunified = ::onspawnplayerunified; @@ -77,12 +68,8 @@ main() set_game_var( "ZM_scoreLimit", 1 ); set_game_var( "_team1_num", 0 ); set_game_var( "_team2_num", 0 ); - - //all working non essential map_name = level.script; mode = getDvar( "ui_gametype" ); - - //condition was incorrect if ( !isDefined( mode ) && isDefined( level.default_game_mode ) || mode == "" && isDefined( level.default_game_mode ) ) { mode = level.default_game_mode; @@ -97,8 +84,6 @@ main() set_gamemode_var_once( "location", location ); set_gamemode_var_once( "randomize_mode", getDvarInt( "zm_rand_mode" ) ); set_gamemode_var_once( "randomize_location", getDvarInt( "zm_rand_loc" ) ); - - //non essential vars set_gamemode_var_once( "team_1_score", 0 ); set_gamemode_var_once( "team_2_score", 0 ); set_gamemode_var_once( "current_round", 0 ); @@ -114,8 +99,6 @@ main() set_gamemode_var( "match_end_notify", undefined ); set_gamemode_var( "match_end_func", undefined ); setscoreboardcolumns( "score", "kills", "downs", "revives", "headshots" ); - - //causes no crashes probably fine onplayerconnect_callback( ::onplayerconnect_check_for_hotjoin ); } @@ -248,54 +231,57 @@ globallogic_setupdefault_zombiecallbacks() //checked matches cerberus output setup_standard_objects( location ) //checked partially used cerberus output { structs = getstructarray( "game_mode_object" ); - foreach ( struct in structs ) + i = 0; + while ( i < structs.size ) { - if ( isdefined( struct.script_noteworthy ) && struct.script_noteworthy != location ) + if ( isdefined( structs[ i ].script_noteworthy ) && structs[ i ].script_noteworthy != location ) { - //continue; + i++; + continue; } - if ( isdefined( struct.script_string ) ) + if ( isdefined( structs[ i ].script_string ) ) { keep = 0; - tokens = strtok( struct.script_string, " " ); - _a300 = tokens; - _k300 = getFirstArrayKey( _a300 ); - while ( isDefined( _k300 ) ) + tokens = strtok( structs[ i ].script_string, " " ); + i = 0; + while ( i < tokens.size ) { - token = _a300[ _k300 ]; - if(token == level.scr_zm_ui_gametype && token != "zstandard") + if ( tokens[ i ] == level.scr_zm_ui_gametype && tokens[ i ] != "zstandard" ) + { + keep = 1; + i++; + continue; + } + if ( tokens[ i ] == "zstandard" ) { keep = 1; } - if(token == "zstandard") - { - keep = 1; - } - _k300 = getNextArrayKey( _a300, _k300 ); } if ( !keep ) { - //break; + i++; + continue; } } - barricade = spawn("script_model", struct.origin); - barricade.angles = struct.angles; - barricade setmodel(struct.script_parameters); + barricade = spawn( "script_model", structs[ i ].origin ); + barricade.angles = structs[ i ].angles; + barricade setmodel( structs[ i ].script_parameters ); } objects = getentarray(); - foreach ( object in objects ) + i = 0; + while ( i < objects.size ) { - if ( !object is_survival_object() ) + if ( !objects[ i ] is_survival_object() ) { + i++; + continue; } - else + if ( isdefined( objects[ i ].spawnflags ) && objects[ i ].spawnflags == 1 && objects[ i ].classname != "trigger_multiple" ) { - if ( isdefined(object.spawnflags) && object.spawnflags == 1 && object.classname != "trigger_multiple" ) - { - object connectpaths(); - } - object delete(); + objects[ i ] connectpaths(); } + objects[ i ] delete(); + i++; } if ( isdefined( level._classic_setup_func ) ) { @@ -310,11 +296,11 @@ is_survival_object() //checked changed to cerberus output { return 0; } - tokens = strtok(self.script_parameters, " "); + tokens = strtok( self.script_parameters, " " ); remove = 0; - foreach(token in tokens) + foreach ( token in tokens ) { - if(token == "survival_remove") + if ( token == "survival_remove" ) { remove = 1; } @@ -351,9 +337,9 @@ game_module_player_damage_callback( einflictor, eattacker, idamage, idflags, sme return; } } - else if(!isdefined(self.riotshieldentity)) + else if ( !isdefined( self.riotshieldentity ) ) { - if(!self maps/mp/zombies/_zm::player_shield_facing_attacker(vdir, -0.2) && isdefined(self.player_shield_apply_damage)) + if ( !self maps/mp/zombies/_zm::player_shield_facing_attacker( vdir, -0.2 ) && isdefined( self.player_shield_apply_damage ) ) { return; } @@ -651,15 +637,15 @@ create_hud_scoreboard( duration, fade ) //checked matches cerberus output respawn_spectators_and_freeze_players() //checked changed to match cerberus output { players = get_players(); - foreach(player in players) + foreach ( player in players ) { - if(player.sessionstate == "spectator") + if ( player.sessionstate == "spectator" ) { - if(isdefined(player.spectate_hud)) + if ( isdefined( player.spectate_hud ) ) { player.spectate_hud destroy(); } - player [[level.spawnplayer]](); + player [[ level.spawnplayer ]](); } player freeze_player_controls(1); } @@ -774,11 +760,11 @@ revive_laststand_players() //checked changed to match cerberus output return; } players = get_players(); - foreach(player in players) + foreach ( player in players ) { - if(player maps/mp/zombies/_zm_laststand::player_is_in_laststand()) + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) { - player thread maps/mp/zombies/_zm_laststand::auto_revive(player); + player thread maps/mp/zombies/_zm_laststand::auto_revive( player ); } } } @@ -917,10 +903,10 @@ unlink_meat_traversal_nodes() //checked changed to match cerberus output meat_farm_nodes = getnodearray( "meat_farm_barrier_traversals", "targetname" ); nodes = arraycombine( meat_town_nodes, meat_tunnel_nodes, 1, 0 ); traversal_nodes = arraycombine( nodes, meat_farm_nodes, 1, 0 ); - foreach(node in traversal_nodes) + foreach ( node in traversal_nodes ) { - end_node = getnode(node.target, "targetname"); - unlink_nodes(node, end_node); + end_node = getnode( node.target, "targetname" ); + unlink_nodes( node, end_node ); } } @@ -1443,35 +1429,7 @@ onspawnplayer( predictedspawn ) //fixed checked changed partially to match cerbe match_string = level.scr_zm_ui_gametype + "_" + location; spawnpoints = []; - structs = getstructarray("initial_spawn", "script_noteworthy"); - /* - if ( isDefined( structs ) ) - { - _a1757 = structs; - _k1757 = getFirstArrayKey( _a1757 ); - while ( isDefined( _k1757 ) ) - { - struct = _a1757[ _k1757 ]; - if ( isDefined( struct.script_string ) ) - { - tokens = strtok( struct.script_string, " " ); - _a1763 = tokens; - _k1763 = getFirstArrayKey( _a1763 ); - while ( isDefined( _k1763 ) ) - { - token = _a1763[ _k1763 ]; - if ( token == match_string ) - { - spawnpoints[ spawnpoints.size ] = struct; - - } - _k1763 = getNextArrayKey( _a1763, _k1763 ); - } - } - _k1757 = getNextArrayKey( _a1757, _k1757 ); - } - } - */ + structs = getstructarray( "initial_spawn", "script_noteworthy" ); if ( isdefined( structs ) ) { i = 0; @@ -1860,12 +1818,12 @@ custom_spawn_init_func() //checked matches cerberus output kill_all_zombies() //changed to match cerberus output { ai = getaiarray( level.zombie_team ); - foreach(zombie in ai) + foreach ( zombie in ai ) { - if(isdefined(zombie)) + if ( isdefined( zombie ) ) { - zombie dodamage(zombie.maxhealth * 2, zombie.origin, zombie, zombie, "none", "MOD_SUICIDE"); - wait(0.05); + zombie dodamage( zombie.maxhealth * 2, zombie.origin, zombie, zombie, "none", "MOD_SUICIDE" ); + wait 0.05; } } } @@ -2042,3 +2000,5 @@ blank() + + diff --git a/patch_zm/maps/mp/zombies/_load.gsc b/patch_zm/maps/mp/zombies/_load.gsc index cd154dd..62844f7 100644 --- a/patch_zm/maps/mp/zombies/_load.gsc +++ b/patch_zm/maps/mp/zombies/_load.gsc @@ -9,7 +9,7 @@ #include maps/mp/_utility; #include common_scripts/utility; -main( bscriptgened, bcsvgened, bsgenabled ) +main( bscriptgened, bcsvgened, bsgenabled ) //checked partially changed to match cerberus output { if ( !isDefined( level.script_gen_dump_reasons ) ) { @@ -35,7 +35,10 @@ main( bscriptgened, bcsvgened, bsgenabled ) level.bscriptgened = bscriptgened; level._loadstarted = 1; struct_class_init(); - level.clientscripts = getDvar( "cg_usingClientScripts" ) != ""; + if ( getDvar( "cg_usingClientScripts" ) != "" ) //changed at own discretion + { + level.clientscripts = getDvar( "cg_usingClientScripts" ); + } level._client_exploders = []; level._client_exploder_ids = []; if ( !isDefined( level.flag ) ) @@ -62,13 +65,11 @@ main( bscriptgened, bcsvgened, bsgenabled ) { script_gen_dump_addline( "maps\\mp\\createfx\\" + level.script + "_fx::main();", level.script + "_fx" ); } - while ( isDefined( level.script_gen_dump_preload ) ) + if ( isDefined( level.script_gen_dump_preload ) ) { - i = 0; - while ( i < level.script_gen_dump_preload.size ) + for ( i = 0; i < level.script_gen_dump_preload.size; i++ ) { script_gen_dump_addline( level.script_gen_dump_preload[ i ].string, level.script_gen_dump_preload[ i ].signature ); - i++; } } if ( getDvar( "scr_RequiredMapAspectratio" ) == "" ) @@ -93,7 +94,10 @@ main( bscriptgened, bcsvgened, bsgenabled ) level.physicstracemaskwater = 4; level.physicstracemaskclip = 8; level.physicstracecontentsvehicleclip = 16; - level.createfx_enabled = getDvar( "createfx" ) != ""; + if ( getDvar( "createfx" ) != "" ) //changed at own discretion + { + level.createfx_enabled = getDvar( "createfx" ); + } level thread start_intro_screen_zm(); thread maps/mp/_interactive_objects::init(); maps/mp/_audio::init(); @@ -130,8 +134,7 @@ main( bscriptgened, bcsvgened, bsgenabled ) } thread maps/mp/_global_fx::main(); maps/mp/_demo::init(); - p = 0; - while ( p < 6 ) + for ( p = 0; p < 6; p++ ) { switch( p ) { @@ -160,8 +163,7 @@ main( bscriptgened, bcsvgened, bsgenabled ) break; } triggers = getentarray( triggertype, "classname" ); - i = 0; - while ( i < triggers.size ) + for ( i = 0; i < triggers.size; i++ ) { if ( isDefined( triggers[ i ].script_prefab_exploder ) ) { @@ -171,13 +173,11 @@ main( bscriptgened, bcsvgened, bsgenabled ) { level thread maps/mp/zombies/_load::exploder_load( triggers[ i ] ); } - i++; } - p++; } } -level_notify_listener() +level_notify_listener() //checked matches cerberus output { while ( 1 ) { @@ -191,7 +191,7 @@ level_notify_listener() } } -client_notify_listener() +client_notify_listener() //checked matches cerberus output { while ( 1 ) { @@ -205,7 +205,7 @@ client_notify_listener() } } -footsteps() +footsteps() //checked matches cerberus output { if ( is_true( level.fx_exclude_footsteps ) ) { @@ -230,10 +230,9 @@ footsteps() maps/mp/animscripts/utility::setfootstepeffect( "wood", loadfx( "bio/player/fx_footstep_dust" ) ); } -parse_structs() +parse_structs() //checked matches cerberus output { - i = 0; - while ( i < level.struct.size ) + for ( i = 0; i < level.struct.size; i++ ) { if ( isDefined( level.struct[ i ].targetname ) ) { @@ -253,11 +252,10 @@ parse_structs() level._effect[ "spotlight_beam" ] = loadfx( "env/light/fx_ray_spotlight_md" ); } } - i++; } } -exploder_load( trigger ) +exploder_load( trigger ) //checked matches cerberus output { level endon( "killexplodertridgers" + trigger.script_exploder ); trigger waittill( "trigger" ); @@ -278,15 +276,13 @@ exploder_load( trigger ) level notify( "killexplodertridgers" + trigger.script_exploder ); } -setupexploders() +setupexploders() //checked partially changed to match cerberus output { ents = getentarray( "script_brushmodel", "classname" ); smodels = getentarray( "script_model", "classname" ); - i = 0; - while ( i < smodels.size ) + for ( i = 0; i < smodels.size; i++ ) { ents[ ents.size ] = smodels[ i ]; - i++; } i = 0; while ( i < ents.size ) @@ -303,31 +299,24 @@ setupexploders() i++; continue; } - else + if ( isDefined( ents[ i ].targetname ) && ents[ i ].targetname == "exploder" ) { - if ( isDefined( ents[ i ].targetname ) && ents[ i ].targetname == "exploder" ) - { - ents[ i ] hide(); - ents[ i ] notsolid(); - i++; - continue; - } - else - { - if ( isDefined( ents[ i ].targetname ) && ents[ i ].targetname == "exploderchunk" ) - { - ents[ i ] hide(); - ents[ i ] notsolid(); - } - } + ents[ i ] hide(); + ents[ i ] notsolid(); + i++; + continue; + } + if ( isDefined( ents[ i ].targetname ) && ents[ i ].targetname == "exploderchunk" ) + { + ents[ i ] hide(); + ents[ i ] notsolid(); } } i++; } script_exploders = []; potentialexploders = getentarray( "script_brushmodel", "classname" ); - i = 0; - while ( i < potentialexploders.size ) + for ( i = 0; i < potentialexploders.size; i++ ) { if ( isDefined( potentialexploders[ i ].script_prefab_exploder ) ) { @@ -337,11 +326,9 @@ setupexploders() { script_exploders[ script_exploders.size ] = potentialexploders[ i ]; } - i++; } potentialexploders = getentarray( "script_model", "classname" ); - i = 0; - while ( i < potentialexploders.size ) + for ( i = 0; i < potentialexploders.size; i++ ) { if ( isDefined( potentialexploders[ i ].script_prefab_exploder ) ) { @@ -351,11 +338,9 @@ setupexploders() { script_exploders[ script_exploders.size ] = potentialexploders[ i ]; } - i++; } potentialexploders = getentarray( "item_health", "classname" ); - i = 0; - while ( i < potentialexploders.size ) + for ( i = 0; i < potentialexploders.size; i++ ) { if ( isDefined( potentialexploders[ i ].script_prefab_exploder ) ) { @@ -365,7 +350,6 @@ setupexploders() { script_exploders[ script_exploders.size ] = potentialexploders[ i ]; } - i++; } if ( !isDefined( level.createfxent ) ) { @@ -375,8 +359,7 @@ setupexploders() acceptabletargetnames[ "exploderchunk visible" ] = 1; acceptabletargetnames[ "exploderchunk" ] = 1; acceptabletargetnames[ "exploder" ] = 1; - i = 0; - while ( i < script_exploders.size ) + for ( i = 0; i < script_exploders.size; i++ ) { exploder = script_exploders[ i ]; ent = createexploder( exploder.script_fxid ); @@ -435,7 +418,6 @@ setupexploders() ent.v[ "exploder_type" ] = "normal"; } ent maps/mp/_createfx::post_entity_creation_function(); - i++; } level.createfxexploders = []; i = 0; @@ -447,35 +429,30 @@ setupexploders() i++; continue; } - else + ent.v[ "exploder_id" ] = getexploderid( ent ); + if ( !isDefined( level.createfxexploders[ ent.v[ "exploder" ] ] ) ) { - ent.v[ "exploder_id" ] = getexploderid( ent ); - if ( !isDefined( level.createfxexploders[ ent.v[ "exploder" ] ] ) ) - { - level.createfxexploders[ ent.v[ "exploder" ] ] = []; - } - level.createfxexploders[ ent.v[ "exploder" ] ][ level.createfxexploders[ ent.v[ "exploder" ] ].size ] = ent; + level.createfxexploders[ ent.v[ "exploder" ] ] = []; } + level.createfxexploders[ ent.v[ "exploder" ] ][ level.createfxexploders[ ent.v[ "exploder" ] ].size ] = ent; i++; } } -setup_traversals() +setup_traversals() //checked changed to match cerberus output { potential_traverse_nodes = getallnodes(); - i = 0; - while ( i < potential_traverse_nodes.size ) + for ( i = 0; i < potential_traverse_nodes.size; i++ ) { node = potential_traverse_nodes[ i ]; if ( node.type == "Begin" ) { node maps/mp/animscripts/traverse/shared::init_traverse(); } - i++; } } -calculate_map_center() +calculate_map_center() //checked matches cerberus output { if ( !isDefined( level.mapcenter ) ) { @@ -491,7 +468,7 @@ calculate_map_center() } } -start_intro_screen_zm() +start_intro_screen_zm() //checked changed to match cerberus output { if ( level.createfx_enabled ) { @@ -512,12 +489,11 @@ start_intro_screen_zm() } level.introscreen.alpha = 1; players = get_players(); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { players[ i ] freezecontrols( 1 ); - i++; } wait 1; } + diff --git a/patch_zm/maps/mp/zombies/_zm_blockers.gsc b/patch_zm/maps/mp/zombies/_zm_blockers.gsc new file mode 100644 index 0000000..4385372 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_blockers.gsc @@ -0,0 +1,2513 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/zombies/_zm_net; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + init_blockers(); + if ( isDefined( level.quantum_bomb_register_result_func ) ) + { + [[ level.quantum_bomb_register_result_func ]]( "open_nearest_door", ::quantum_bomb_open_nearest_door_result, 35, ::quantum_bomb_open_nearest_door_validation ); + } +} + +init_blockers() +{ + level.exterior_goals = getstructarray( "exterior_goal", "targetname" ); + array_thread( level.exterior_goals, ::blocker_init ); + zombie_doors = getentarray( "zombie_door", "targetname" ); + if ( isDefined( zombie_doors ) ) + { + flag_init( "door_can_close" ); + array_thread( zombie_doors, ::door_init ); + } + zombie_debris = getentarray( "zombie_debris", "targetname" ); + array_thread( zombie_debris, ::debris_init ); + flag_blockers = getentarray( "flag_blocker", "targetname" ); + array_thread( flag_blockers, ::flag_blocker ); +} + +door_init() +{ + self.type = undefined; + self.purchaser = undefined; + self._door_open = 0; + targets = getentarray( self.target, "targetname" ); + while ( isDefined( self.script_flag ) && !isDefined( level.flag[ self.script_flag ] ) ) + { + while ( isDefined( self.script_flag ) ) + { + tokens = strtok( self.script_flag, "," ); + i = 0; + while ( i < tokens.size ) + { + flag_init( self.script_flag ); + i++; + } + } + } + if ( !isDefined( self.script_noteworthy ) ) + { + self.script_noteworthy = "default"; + } + self.doors = []; + i = 0; + while ( i < targets.size ) + { + targets[ i ] door_classify( self ); + if ( !isDefined( targets[ i ].og_origin ) ) + { + targets[ i ].og_origin = targets[ i ].origin; + targets[ i ].og_angles = targets[ i ].angles; + } + i++; + } + cost = 1000; + if ( isDefined( self.zombie_cost ) ) + { + cost = self.zombie_cost; + } + self setcursorhint( "HINT_NOICON" ); + self thread door_think(); + if ( isDefined( self.script_noteworthy ) ) + { + if ( self.script_noteworthy == "electric_door" || self.script_noteworthy == "electric_buyable_door" ) + { + if ( getDvar( "ui_gametype" ) == "zgrief" ) + { + self setinvisibletoall(); + return; + } + self sethintstring( &"ZOMBIE_NEED_POWER" ); + if ( isDefined( level.door_dialog_function ) ) + { + self thread [[ level.door_dialog_function ]](); + } + return; + } + else + { + if ( self.script_noteworthy == "local_electric_door" ) + { + if ( getDvar( "ui_gametype" ) == "zgrief" ) + { + self setinvisibletoall(); + return; + } + self sethintstring( &"ZOMBIE_NEED_LOCAL_POWER" ); + if ( isDefined( level.door_dialog_function ) ) + { + self thread [[ level.door_dialog_function ]](); + } + return; + } + else + { + if ( self.script_noteworthy == "kill_counter_door" ) + { + self sethintstring( &"ZOMBIE_DOOR_ACTIVATE_COUNTER", cost ); + return; + } + } + } + } + self set_hint_string( self, "default_buy_door", cost ); +} + +door_classify( parent_trig ) +{ + if ( isDefined( self.script_noteworthy ) && self.script_noteworthy == "clip" ) + { + parent_trig.clip = self; + parent_trig.script_string = "clip"; + break; +} +else +{ + if ( !isDefined( self.script_string ) ) + { + if ( isDefined( self.script_angles ) ) + { + self.script_string = "rotate"; + } + else + { + if ( isDefined( self.script_vector ) ) + { + self.script_string = "move"; + } + } + break; +} +else if ( !isDefined( self.script_string ) ) +{ + self.script_string = ""; +} +switch( self.script_string ) +{ + case "anim": +/# + assert( isDefined( self.script_animname ), "Blocker_init: You must specify a script_animname for " + self.targetname ); +#/ +/# + assert( isDefined( level.scr_anim[ self.script_animname ] ), "Blocker_init: You must define a level.scr_anim for script_anim -> " + self.script_animname ); +#/ +/# + assert( isDefined( level.blocker_anim_func ), "Blocker_init: You must define a level.blocker_anim_func" ); +#/ + break; + case "counter_1s": + parent_trig.counter_1s = self; + return; + case "counter_10s": + parent_trig.counter_10s = self; + return; + case "counter_100s": + parent_trig.counter_100s = self; + return; + case "explosives": + if ( !isDefined( parent_trig.explosives ) ) + { + parent_trig.explosives = []; + } + parent_trig.explosives[ parent_trig.explosives.size ] = self; + return; + } + } + if ( self.classname == "script_brushmodel" ) + { + self disconnectpaths(); + } + parent_trig.doors[ parent_trig.doors.size ] = self; + } +} + +door_buy() +{ + self waittill( "trigger", who, force ); + if ( isDefined( level.custom_door_buy_check ) ) + { + if ( !( who [[ level.custom_door_buy_check ]]( self ) ) ) + { + return 0; + } + } + if ( getDvarInt( "zombie_unlock_all" ) > 0 || isDefined( force ) && force ) + { + return 1; + } + if ( !who usebuttonpressed() ) + { + return 0; + } + if ( who in_revive_trigger() ) + { + return 0; + } + if ( is_player_valid( who ) ) + { + players = get_players(); + cost = self.zombie_cost; + if ( who maps/mp/zombies/_zm_pers_upgrades_functions::is_pers_double_points_active() ) + { + cost = who maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_double_points_cost( cost ); + } + if ( self._door_open == 1 ) + { + self.purchaser = undefined; + } + else if ( who.score >= cost ) + { + who maps/mp/zombies/_zm_score::minus_to_player_score( cost, 1 ); + maps/mp/_demo::bookmark( "zm_player_door", getTime(), who ); + who maps/mp/zombies/_zm_stats::increment_client_stat( "doors_purchased" ); + who maps/mp/zombies/_zm_stats::increment_player_stat( "doors_purchased" ); + self.purchaser = who; + } + else + { + play_sound_at_pos( "no_purchase", self.doors[ 0 ].origin ); + if ( isDefined( level.custom_generic_deny_vo_func ) ) + { + who thread [[ level.custom_generic_deny_vo_func ]]( 1 ); + } + else + { + who maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "door_deny" ); + } + return 0; + } + } + if ( isDefined( level._door_open_rumble_func ) ) + { + who thread [[ level._door_open_rumble_func ]](); + } + return 1; +} + +door_delay() +{ + while ( isDefined( self.explosives ) ) + { + i = 0; + while ( i < self.explosives.size ) + { + self.explosives[ i ] show(); + i++; + } + } + if ( !isDefined( self.script_int ) ) + { + self.script_int = 5; + } + all_trigs = getentarray( self.target, "target" ); + i = 0; + while ( i < all_trigs.size ) + { + all_trigs[ i ] trigger_off(); + i++; + } + wait self.script_int; + i = 0; + while ( i < self.script_int ) + { +/# + iprintln( self.script_int - i ); +#/ + wait 1; + i++; + } + while ( isDefined( self.explosives ) ) + { + i = 0; + while ( i < self.explosives.size ) + { + playfx( level._effect[ "def_explosion" ], self.explosives[ i ].origin, anglesToForward( self.explosives[ i ].angles ) ); + self.explosives[ i ] hide(); + i++; + } + } +} + +door_activate( time, open, quick, use_blocker_clip_for_pathing ) +{ + if ( !isDefined( open ) ) + { + open = 1; + } + if ( !isDefined( time ) ) + { + time = 1; + if ( isDefined( self.script_transition_time ) ) + { + time = self.script_transition_time; + } + } + if ( isDefined( self.door_moving ) ) + { + if ( isDefined( self.script_noteworthy ) || self.script_noteworthy == "clip" && isDefined( self.script_string ) && self.script_string == "clip" ) + { + if ( !is_true( use_blocker_clip_for_pathing ) ) + { + if ( !open ) + { + return; + } + } + } + else + { + return; + } + } + self.door_moving = 1; + if ( open || isDefined( quick ) && !quick ) + { + self notsolid(); + } + if ( self.classname == "script_brushmodel" ) + { + if ( open ) + { + self connectpaths(); + } + } + if ( isDefined( self.script_noteworthy ) || self.script_noteworthy == "clip" && isDefined( self.script_string ) && self.script_string == "clip" ) + { + if ( !open ) + { + self delay_thread( time, ::self_disconnectpaths ); + wait 0,1; + self solid(); + } + return; + } + if ( isDefined( self.script_sound ) ) + { + if ( open ) + { + playsoundatposition( self.script_sound, self.origin ); + } + else + { + playsoundatposition( self.script_sound + "_close", self.origin ); + } + } + else + { + play_sound_at_pos( "door_slide_open", self.origin ); + } + scale = 1; + if ( !open ) + { + scale = -1; + } + switch( self.script_string ) + { + case "rotate": + if ( isDefined( self.script_angles ) ) + { + rot_angle = self.script_angles; + if ( !open ) + { + rot_angle = self.og_angles; + } + self rotateto( rot_angle, time, 0, 0 ); + self thread door_solid_thread(); + if ( !open ) + { + self thread disconnect_paths_when_done(); + } + } + wait randomfloat( 0,15 ); + break; + case "move": + case "slide_apart": + if ( isDefined( self.script_vector ) ) + { + vector = vectorScale( self.script_vector, scale ); + if ( time >= 0,5 ) + { + self moveto( self.origin + vector, time, time * 0,25, time * 0,25 ); + } + else + { + self moveto( self.origin + vector, time ); + } + self thread door_solid_thread(); + if ( !open ) + { + self thread disconnect_paths_when_done(); + } + } + wait randomfloat( 0,15 ); + break; + case "anim": + self [[ level.blocker_anim_func ]]( self.script_animname ); + self thread door_solid_thread_anim(); + wait randomfloat( 0,15 ); + break; + case "physics": + self thread physics_launch_door( self ); + wait 0,1; + break; + } + if ( isDefined( self.script_firefx ) ) + { + playfx( level._effect[ self.script_firefx ], self.origin ); + } +} + +kill_trapped_zombies( trigger ) +{ + zombies = getaiarray( level.zombie_team ); + if ( !isDefined( zombies ) ) + { + return; + } + i = 0; + while ( i < zombies.size ) + { + if ( !isDefined( zombies[ i ] ) ) + { + i++; + continue; + } + else if ( zombies[ i ] istouching( trigger ) ) + { + zombies[ i ].marked_for_recycle = 1; + zombies[ i ] dodamage( zombies[ i ].health + 666, trigger.origin, self ); + wait randomfloat( 0,15 ); + i++; + continue; + } + else + { + if ( isDefined( level.custom_trapped_zombies ) ) + { + zombies[ i ] thread [[ level.custom_trapped_zombies ]](); + wait randomfloat( 0,15 ); + } + } + i++; + } +} + +any_player_touching( trigger ) +{ + _a556 = get_players(); + _k556 = getFirstArrayKey( _a556 ); + while ( isDefined( _k556 ) ) + { + player = _a556[ _k556 ]; + if ( player istouching( trigger ) ) + { + return 1; + } + wait 0,01; + _k556 = getNextArrayKey( _a556, _k556 ); + } + return 0; +} + +any_player_touching_any( trigger, more_triggers ) +{ + _a567 = get_players(); + _k567 = getFirstArrayKey( _a567 ); + while ( isDefined( _k567 ) ) + { + player = _a567[ _k567 ]; + while ( is_player_valid( player, 0, 1 ) ) + { + if ( isDefined( trigger ) && player istouching( trigger ) ) + { + return 1; + } + while ( isDefined( more_triggers ) && more_triggers.size > 0 ) + { + _a574 = more_triggers; + _k574 = getFirstArrayKey( _a574 ); + while ( isDefined( _k574 ) ) + { + trig = _a574[ _k574 ]; + if ( isDefined( trig ) && player istouching( trig ) ) + { + return 1; + } + _k574 = getNextArrayKey( _a574, _k574 ); + } + } + } + _k567 = getNextArrayKey( _a567, _k567 ); + } + return 0; +} + +any_zombie_touching_any( trigger, more_triggers ) +{ + zombies = getaiarray( level.zombie_team ); + _a586 = zombies; + _k586 = getFirstArrayKey( _a586 ); + while ( isDefined( _k586 ) ) + { + zombie = _a586[ _k586 ]; + if ( isDefined( trigger ) && zombie istouching( trigger ) ) + { + return 1; + } + while ( isDefined( more_triggers ) && more_triggers.size > 0 ) + { + _a591 = more_triggers; + _k591 = getFirstArrayKey( _a591 ); + while ( isDefined( _k591 ) ) + { + trig = _a591[ _k591 ]; + if ( isDefined( trig ) && zombie istouching( trig ) ) + { + return 1; + } + _k591 = getNextArrayKey( _a591, _k591 ); + } + } + _k586 = getNextArrayKey( _a586, _k586 ); + } + return 0; +} + +wait_trigger_clear( trigger, more_triggers, end_on ) +{ + self endon( end_on ); + while ( any_player_touching_any( trigger, more_triggers ) || any_zombie_touching_any( trigger, more_triggers ) ) + { + wait 1; + } +/# + println( "ZM BLOCKER local door trigger clear\n" ); +#/ + self notify( "trigger_clear" ); +} + +waittill_door_trigger_clear_local_power_off( trigger, all_trigs ) +{ + self endon( "trigger_clear" ); + while ( 1 ) + { + if ( isDefined( self.local_power_on ) && self.local_power_on ) + { + self waittill( "local_power_off" ); + } +/# + println( "ZM BLOCKER local door power off\n" ); +#/ + self wait_trigger_clear( trigger, all_trigs, "local_power_on" ); + } +} + +waittill_door_trigger_clear_global_power_off( trigger, all_trigs ) +{ + self endon( "trigger_clear" ); + while ( 1 ) + { + if ( isDefined( self.power_on ) && self.power_on ) + { + self waittill( "power_off" ); + } +/# + println( "ZM BLOCKER global door power off\n" ); +#/ + self wait_trigger_clear( trigger, all_trigs, "power_on" ); + } +} + +waittill_door_can_close() +{ + trigger = undefined; + if ( isDefined( self.door_hold_trigger ) ) + { + trigger = getent( self.door_hold_trigger, "targetname" ); + } + all_trigs = getentarray( self.target, "target" ); + switch( self.script_noteworthy ) + { + case "local_electric_door": + if ( isDefined( trigger ) || isDefined( all_trigs ) ) + { + self waittill_door_trigger_clear_local_power_off( trigger, all_trigs ); + self thread kill_trapped_zombies( trigger ); + } + else + { + if ( isDefined( self.local_power_on ) && self.local_power_on ) + { + self waittill( "local_power_off" ); + } + } + return; + case "electric_door": + if ( isDefined( trigger ) || isDefined( all_trigs ) ) + { + self waittill_door_trigger_clear_global_power_off( trigger, all_trigs ); + if ( isDefined( trigger ) ) + { + self thread kill_trapped_zombies( trigger ); + } + } + else + { + if ( isDefined( self.power_on ) && self.power_on ) + { + self waittill( "power_off" ); + } + } + return; + } + } +} + +door_think() +{ + self endon( "kill_door_think" ); + cost = 1000; + if ( isDefined( self.zombie_cost ) ) + { + cost = self.zombie_cost; + } + self sethintlowpriority( 1 ); + for ( ;; ) + { + while ( 1 ) + { + switch( self.script_noteworthy ) + { + case "local_electric_door": + if ( isDefined( self.local_power_on ) && !self.local_power_on ) + { + self waittill( "local_power_on" ); + } + if ( isDefined( self._door_open ) && !self._door_open ) + { +/# + println( "ZM BLOCKER local door opened\n" ); +#/ + self door_opened( cost, 1 ); + if ( !isDefined( self.power_cost ) ) + { + self.power_cost = 0; + } + self.power_cost += 200; + } + self sethintstring( "" ); + if ( isDefined( level.local_doors_stay_open ) && level.local_doors_stay_open ) + { + return; + } + wait 3; + self waittill_door_can_close(); + self door_block(); + if ( isDefined( self._door_open ) && self._door_open ) + { +/# + println( "ZM BLOCKER local door closed\n" ); +#/ + self door_opened( cost, 1 ); + } + self sethintstring( &"ZOMBIE_NEED_LOCAL_POWER" ); + wait 3; + } + case "electric_door": + if ( isDefined( self.power_on ) && !self.power_on ) + { + self waittill( "power_on" ); + } + if ( isDefined( self._door_open ) && !self._door_open ) + { +/# + println( "ZM BLOCKER global door opened\n" ); +#/ + self door_opened( cost, 1 ); + if ( !isDefined( self.power_cost ) ) + { + self.power_cost = 0; + } + self.power_cost += 200; + } + self sethintstring( "" ); + if ( isDefined( level.local_doors_stay_open ) && level.local_doors_stay_open ) + { + return; + } + wait 3; + self waittill_door_can_close(); + self door_block(); + if ( isDefined( self._door_open ) && self._door_open ) + { +/# + println( "ZM BLOCKER global door closed\n" ); +#/ + self door_opened( cost, 1 ); + } + self sethintstring( &"ZOMBIE_NEED_POWER" ); + wait 3; + } + case "electric_buyable_door": + flag_wait( "power_on" ); + self set_hint_string( self, "default_buy_door", cost ); + while ( !self door_buy() ) + { + continue; + } + case "delay_door": + while ( !self door_buy() ) + { + continue; + } + self door_delay(); + break; + default: + if ( isDefined( level._default_door_custom_logic ) ) + { + self [[ level._default_door_custom_logic ]](); + break; + } + else while ( !self door_buy() ) + { + continue; + } + } + self door_opened( cost ); + if ( !flag( "door_can_close" ) ) + { + return; + } + else } + } + } +} + +self_and_flag_wait( msg ) +{ + self endon( msg ); + if ( isDefined( self.power_door_ignore_flag_wait ) && self.power_door_ignore_flag_wait ) + { + level waittill( "forever" ); + } + else + { + flag_wait( msg ); + } +} + +door_block() +{ + while ( isDefined( self.doors ) ) + { + i = 0; + while ( i < self.doors.size ) + { + if ( isDefined( self.doors[ i ].script_noteworthy ) || self.doors[ i ].script_noteworthy == "clip" && isDefined( self.doors[ i ].script_string ) && self.doors[ i ].script_string == "clip" ) + { + self.doors[ i ] solid(); + } + i++; + } + } +} + +door_opened( cost, quick_close ) +{ + if ( isDefined( self.door_is_moving ) && self.door_is_moving ) + { + return; + } + self.has_been_opened = 1; + all_trigs = getentarray( self.target, "target" ); + self.door_is_moving = 1; + _a848 = all_trigs; + _k848 = getFirstArrayKey( _a848 ); + while ( isDefined( _k848 ) ) + { + trig = _a848[ _k848 ]; + trig.door_is_moving = 1; + trig trigger_off(); + trig.has_been_opened = 1; + if ( !isDefined( trig._door_open ) || trig._door_open == 0 ) + { + trig._door_open = 1; + trig notify( "door_opened" ); + level thread maps/mp/zombies/_zm_audio::sndmusicstingerevent( "door_open" ); + } + else + { + trig._door_open = 0; + } + if ( isDefined( trig.script_flag ) && trig._door_open == 1 ) + { + tokens = strtok( trig.script_flag, "," ); + i = 0; + while ( i < tokens.size ) + { + flag_set( tokens[ i ] ); + i++; + } + } + else while ( isDefined( trig.script_flag ) && trig._door_open == 0 ) + { + tokens = strtok( trig.script_flag, "," ); + i = 0; + while ( i < tokens.size ) + { + flag_clear( tokens[ i ] ); + i++; + } + } + if ( isDefined( quick_close ) && quick_close ) + { + trig set_hint_string( trig, "" ); + } + else + { + if ( trig._door_open == 1 && flag( "door_can_close" ) ) + { + trig set_hint_string( trig, "default_buy_door_close" ); + break; + } + else + { + if ( trig._door_open == 0 ) + { + trig set_hint_string( trig, "default_buy_door", cost ); + } + } + } + _k848 = getNextArrayKey( _a848, _k848 ); + } + level notify( "door_opened" ); + if ( isDefined( self.doors ) ) + { + is_script_model_door = 0; + have_moving_clip_for_door = 0; + use_blocker_clip_for_pathing = 0; + _a905 = self.doors; + _k905 = getFirstArrayKey( _a905 ); + while ( isDefined( _k905 ) ) + { + door = _a905[ _k905 ]; + if ( is_true( door.ignore_use_blocker_clip_for_pathing_check ) ) + { + } + else if ( door.classname == "script_model" ) + { + is_script_model_door = 1; + } + else + { + if ( door.classname == "script_brushmodel" && isDefined( door.script_noteworthy ) && door.script_noteworthy != "clip" || !isDefined( door.script_string ) && door.script_string != "clip" ) + { + have_moving_clip_for_door = 1; + } + } + _k905 = getNextArrayKey( _a905, _k905 ); + } + if ( is_script_model_door ) + { + use_blocker_clip_for_pathing = !have_moving_clip_for_door; + } + i = 0; + while ( i < self.doors.size ) + { + self.doors[ i ] thread door_activate( self.doors[ i ].script_transition_time, self._door_open, quick_close, use_blocker_clip_for_pathing ); + i++; + } + if ( self.doors.size ) + { + play_sound_at_pos( "purchase", self.doors[ 0 ].origin ); + } + } + level.active_zone_names = maps/mp/zombies/_zm_zonemgr::get_active_zone_names(); + wait 1; + self.door_is_moving = 0; + _a948 = all_trigs; + _k948 = getFirstArrayKey( _a948 ); + while ( isDefined( _k948 ) ) + { + trig = _a948[ _k948 ]; + trig.door_is_moving = 0; + _k948 = getNextArrayKey( _a948, _k948 ); + } + if ( isDefined( quick_close ) && quick_close ) + { + i = 0; + while ( i < all_trigs.size ) + { + all_trigs[ i ] trigger_on(); + i++; + } + return; + } + while ( flag( "door_can_close" ) ) + { + wait 2; + i = 0; + while ( i < all_trigs.size ) + { + all_trigs[ i ] trigger_on(); + i++; + } + } +} + +physics_launch_door( door_trig ) +{ + vec = vectorScale( vectornormalize( self.script_vector ), 10 ); + self rotateroll( 5, 0,05 ); + wait 0,05; + self moveto( self.origin + vec, 0,1 ); + self waittill( "movedone" ); + self physicslaunch( self.origin, self.script_vector * 300 ); + wait 60; + self delete(); +} + +door_solid_thread() +{ + self waittill_either( "rotatedone", "movedone" ); + self.door_moving = undefined; + while ( 1 ) + { + players = get_players(); + player_touching = 0; + i = 0; + while ( i < players.size ) + { + if ( players[ i ] istouching( self ) ) + { + player_touching = 1; + break; + } + else + { + i++; + } + } + if ( !player_touching ) + { + self solid(); + return; + } + wait 1; + } +} + +door_solid_thread_anim() +{ + self waittillmatch( "door_anim" ); + return "end"; + self.door_moving = undefined; + while ( 1 ) + { + players = get_players(); + player_touching = 0; + i = 0; + while ( i < players.size ) + { + if ( players[ i ] istouching( self ) ) + { + player_touching = 1; + break; + } + else + { + i++; + } + } + if ( !player_touching ) + { + self solid(); + return; + } + wait 1; + } +} + +disconnect_paths_when_done() +{ + self waittill_either( "rotatedone", "movedone" ); + self disconnectpaths(); +} + +self_disconnectpaths() +{ + self disconnectpaths(); +} + +debris_init() +{ + cost = 1000; + if ( isDefined( self.zombie_cost ) ) + { + cost = self.zombie_cost; + } + self set_hint_string( self, "default_buy_debris", cost ); + self setcursorhint( "HINT_NOICON" ); + if ( isDefined( self.script_flag ) && !isDefined( level.flag[ self.script_flag ] ) ) + { + flag_init( self.script_flag ); + } + self thread debris_think(); +} + +debris_think() +{ + if ( isDefined( level.custom_debris_function ) ) + { + self [[ level.custom_debris_function ]](); + } + for ( ;; ) + { + while ( 1 ) + { + self waittill( "trigger", who, force ); + if ( getDvarInt( "zombie_unlock_all" ) > 0 || isDefined( force ) && force ) + { + } + else + { + while ( !who usebuttonpressed() ) + { + continue; + } + while ( who in_revive_trigger() ) + { + continue; + } + } + if ( is_player_valid( who ) ) + { + players = get_players(); + if ( getDvarInt( "zombie_unlock_all" ) > 0 ) + { + break; + } + else if ( who.score >= self.zombie_cost ) + { + who maps/mp/zombies/_zm_score::minus_to_player_score( self.zombie_cost ); + maps/mp/_demo::bookmark( "zm_player_door", getTime(), who ); + who maps/mp/zombies/_zm_stats::increment_client_stat( "doors_purchased" ); + who maps/mp/zombies/_zm_stats::increment_player_stat( "doors_purchased" ); + break; + } + else + { + play_sound_at_pos( "no_purchase", self.origin ); + who maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "door_deny" ); + } + } + bbprint( "zombie_uses", "playername %s playerscore %d round %d cost %d name %s x %f y %f z %f type %s", who.name, who.score, level.round_number, self.zombie_cost, self.script_flag, self.origin, "door" ); + junk = getentarray( self.target, "targetname" ); + while ( isDefined( self.script_flag ) ) + { + tokens = strtok( self.script_flag, "," ); + i = 0; + while ( i < tokens.size ) + { + flag_set( tokens[ i ] ); + i++; + } + } + play_sound_at_pos( "purchase", self.origin ); + level notify( "junk purchased" ); + move_ent = undefined; + clip = undefined; + i = 0; + while ( i < junk.size ) + { + junk[ i ] connectpaths(); + if ( isDefined( junk[ i ].script_noteworthy ) ) + { + if ( junk[ i ].script_noteworthy == "clip" ) + { + clip = junk[ i ]; + i++; + continue; + } + } + else struct = undefined; + if ( isDefined( junk[ i ].script_linkto ) ) + { + struct = getstruct( junk[ i ].script_linkto, "script_linkname" ); + if ( isDefined( struct ) ) + { + move_ent = junk[ i ]; + junk[ i ] thread debris_move( struct ); + } + else + { + junk[ i ] delete(); + } + i++; + continue; + } + else + { + junk[ i ] delete(); + } + i++; + } + all_trigs = getentarray( self.target, "target" ); + i = 0; + while ( i < all_trigs.size ) + { + all_trigs[ i ] delete(); + i++; + } + if ( isDefined( clip ) ) + { + if ( isDefined( move_ent ) ) + { + move_ent waittill( "movedone" ); + } + clip delete(); + } + return; + } + else + { + } + } +} + +debris_move( struct ) +{ + self script_delay(); + self notsolid(); + self play_sound_on_ent( "debris_move" ); + playsoundatposition( "zmb_lightning_l", self.origin ); + if ( isDefined( self.script_firefx ) ) + { + playfx( level._effect[ self.script_firefx ], self.origin ); + } + while ( isDefined( self.script_noteworthy ) ) + { + while ( self.script_noteworthy == "jiggle" ) + { + num = randomintrange( 3, 5 ); + og_angles = self.angles; + i = 0; + while ( i < num ) + { + angles = og_angles + ( -5 + randomfloat( 10 ), -5 + randomfloat( 10 ), -5 + randomfloat( 10 ) ); + time = randomfloatrange( 0,1, 0,4 ); + self rotateto( angles, time ); + wait ( time - 0,05 ); + i++; + } + } + } + time = 0,5; + if ( isDefined( self.script_transition_time ) ) + { + time = self.script_transition_time; + } + self moveto( struct.origin, time, time * 0,5 ); + self rotateto( struct.angles, time * 0,75 ); + self waittill( "movedone" ); + if ( isDefined( self.script_fxid ) ) + { + playfx( level._effect[ self.script_fxid ], self.origin ); + playsoundatposition( "zmb_zombie_spawn", self.origin ); + } + self delete(); +} + +blocker_disconnect_paths( start_node, end_node, two_way ) +{ +} + +blocker_connect_paths( start_node, end_node, two_way ) +{ +} + +blocker_init() +{ + if ( !isDefined( self.target ) ) + { + return; + } + targets = getentarray( self.target, "targetname" ); + self.barrier_chunks = []; + j = 0; + while ( j < targets.size ) + { + if ( targets[ j ] iszbarrier() ) + { + if ( isDefined( level.zbarrier_override ) ) + { + self thread [[ level.zbarrier_override ]]( targets[ j ] ); + j++; + continue; + } + else self.zbarrier = targets[ j ]; + if ( isDefined( level.zbarrier_script_string_sets_collision ) && level.zbarrier_script_string_sets_collision ) + { + if ( isDefined( self.zbarrier.script_string ) ) + { + } + else + { + } + m_collision = "p6_anim_zm_barricade_board_collision"; + } + else + { + m_collision = "p6_anim_zm_barricade_board_collision"; + } + precachemodel( m_collision ); + self.zbarrier setzbarriercolmodel( m_collision ); + self.zbarrier.chunk_health = []; + i = 0; + while ( i < self.zbarrier getnumzbarrierpieces() ) + { + self.zbarrier.chunk_health[ i ] = 0; + i++; + } + } + else if ( isDefined( targets[ j ].script_string ) && targets[ j ].script_string == "rock" ) + { + targets[ j ].material = "rock"; + } + if ( isDefined( targets[ j ].script_parameters ) ) + { + if ( targets[ j ].script_parameters == "grate" ) + { + if ( isDefined( targets[ j ].script_noteworthy ) ) + { + if ( targets[ j ].script_noteworthy != "2" && targets[ j ].script_noteworthy != "3" && targets[ j ].script_noteworthy != "4" || targets[ j ].script_noteworthy == "5" && targets[ j ].script_noteworthy == "6" ) + { + targets[ j ] hide(); +/# + iprintlnbold( " Hide " ); +#/ + } + } + break; + } + else if ( targets[ j ].script_parameters == "repair_board" ) + { + targets[ j ].unbroken_section = getent( targets[ j ].target, "targetname" ); + if ( isDefined( targets[ j ].unbroken_section ) ) + { + targets[ j ].unbroken_section linkto( targets[ j ] ); + targets[ j ] hide(); + targets[ j ] notsolid(); + targets[ j ].unbroken = 1; + if ( isDefined( targets[ j ].unbroken_section.script_noteworthy ) && targets[ j ].unbroken_section.script_noteworthy == "glass" ) + { + targets[ j ].material = "glass"; + targets[ j ] thread destructible_glass_barricade( targets[ j ].unbroken_section, self ); + break; + } + else + { + if ( isDefined( targets[ j ].unbroken_section.script_noteworthy ) && targets[ j ].unbroken_section.script_noteworthy == "metal" ) + { + targets[ j ].material = "metal"; + } + } + } + break; + } + else + { + if ( targets[ j ].script_parameters == "barricade_vents" ) + { + targets[ j ].material = "metal_vent"; + } + } + } + if ( isDefined( targets[ j ].targetname ) ) + { + if ( targets[ j ].targetname == "auto2" ) + { + } + } + targets[ j ] update_states( "repaired" ); + targets[ j ].destroyed = 0; + targets[ j ] show(); + targets[ j ].claimed = 0; + targets[ j ].anim_grate_index = 0; + targets[ j ].og_origin = targets[ j ].origin; + targets[ j ].og_angles = targets[ j ].angles; + self.barrier_chunks[ self.barrier_chunks.size ] = targets[ j ]; + j++; + } + target_nodes = getnodearray( self.target, "targetname" ); + j = 0; + while ( j < target_nodes.size ) + { + if ( target_nodes[ j ].type == "Begin" ) + { + self.neg_start = target_nodes[ j ]; + if ( isDefined( self.neg_start.target ) ) + { + self.neg_end = getnode( self.neg_start.target, "targetname" ); + } + blocker_disconnect_paths( self.neg_start, self.neg_end ); + } + j++; + } + if ( isDefined( self.zbarrier ) ) + { + if ( isDefined( self.barrier_chunks ) ) + { + i = 0; + while ( i < self.barrier_chunks.size ) + { + self.barrier_chunks[ i ] delete(); + i++; + } + self.barrier_chunks = []; + } + } + if ( isDefined( self.zbarrier ) && should_delete_zbarriers() ) + { + self.zbarrier delete(); + self.zbarrier = undefined; + return; + } + self blocker_attack_spots(); + self.trigger_location = getstruct( self.target, "targetname" ); + self thread blocker_think(); +} + +should_delete_zbarriers() +{ + gametype = getDvar( "ui_gametype" ); + if ( !is_classic() && !is_standard() && gametype != "zgrief" ) + { + return 1; + } + return 0; +} + +destructible_glass_barricade( unbroken_section, node ) +{ + unbroken_section setcandamage( 1 ); + unbroken_section.health = 99999; + unbroken_section waittill( "damage", amount, who ); + if ( is_player_valid( who ) || who maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + self thread maps/mp/zombies/_zm_spawner::zombie_boardtear_offset_fx_horizontle( self, node ); + level thread remove_chunk( self, node, 1 ); + self update_states( "destroyed" ); + self notify( "destroyed" ); + self.unbroken = 0; + } +} + +blocker_attack_spots() +{ + spots = []; + numslots = self.zbarrier getzbarriernumattackslots(); + numslots = int( max( numslots, 1 ) ); + if ( numslots % 2 ) + { + spots[ spots.size ] = groundpos_ignore_water_new( self.zbarrier.origin + vectorScale( ( -1, 0, 0 ), 60 ) ); + } + while ( numslots > 1 ) + { + reps = floor( numslots / 2 ); + slot = 1; + i = 0; + while ( i < reps ) + { + offset = self.zbarrier getzbarrierattackslothorzoffset() * ( i + 1 ); + spots[ spots.size ] = groundpos_ignore_water_new( spots[ 0 ] + ( anglesToRight( self.angles ) * offset ) + vectorScale( ( -1, 0, 0 ), 60 ) ); + slot++; + if ( slot < numslots ) + { + spots[ spots.size ] = groundpos_ignore_water_new( spots[ 0 ] + ( anglesToRight( self.angles ) * ( offset * -1 ) ) + vectorScale( ( -1, 0, 0 ), 60 ) ); + slot++; + } + i++; + } + } + taken = []; + i = 0; + while ( i < spots.size ) + { + taken[ i ] = 0; + i++; + } + self.attack_spots_taken = taken; + self.attack_spots = spots; +/# + self thread debug_attack_spots_taken(); +#/ +} + +blocker_choke() +{ + level._blocker_choke = 0; + level endon( "stop_blocker_think" ); + while ( 1 ) + { + wait 0,05; + level._blocker_choke = 0; + } +} + +blocker_think() +{ + level endon( "stop_blocker_think" ); + if ( !isDefined( level._blocker_choke ) ) + { + level thread blocker_choke(); + } + use_choke = 0; + if ( isDefined( level._use_choke_blockers ) && level._use_choke_blockers == 1 ) + { + use_choke = 1; + } + while ( 1 ) + { + wait 0,5; + if ( use_choke ) + { + if ( level._blocker_choke > 3 ) + { + wait 0,05; + } + } + level._blocker_choke++; + while ( all_chunks_intact( self, self.barrier_chunks ) ) + { + continue; + } + while ( no_valid_repairable_boards( self, self.barrier_chunks ) ) + { + continue; + } + self blocker_trigger_think(); + } +} + +player_fails_blocker_repair_trigger_preamble( player, players, trigger, hold_required ) +{ + if ( !isDefined( trigger ) ) + { + return 1; + } + if ( !is_player_valid( player ) ) + { + return 1; + } + if ( players.size == 1 && isDefined( players[ 0 ].intermission ) && players[ 0 ].intermission == 1 ) + { + return 1; + } + if ( hold_required && !player usebuttonpressed() ) + { + return 1; + } + if ( !hold_required && !player use_button_held() ) + { + return 1; + } + if ( player in_revive_trigger() ) + { + return 1; + } + return 0; +} + +has_blocker_affecting_perk() +{ + has_perk = undefined; + if ( self hasperk( "specialty_fastreload" ) ) + { + has_perk = "specialty_fastreload"; + } + return has_perk; +} + +do_post_chunk_repair_delay( has_perk ) +{ + if ( !self script_delay() ) + { + wait 1; + } +} + +handle_post_board_repair_rewards( cost, zbarrier ) +{ + self maps/mp/zombies/_zm_stats::increment_client_stat( "boards" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "boards" ); + if ( isDefined( self.pers[ "boards" ] ) && ( self.pers[ "boards" ] % 10 ) == 0 ) + { + self thread do_player_general_vox( "general", "reboard", 90 ); + } + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_boards_updated( zbarrier ); + self.rebuild_barrier_reward += cost; + if ( self.rebuild_barrier_reward < level.zombie_vars[ "rebuild_barrier_cap_per_round" ] ) + { + self maps/mp/zombies/_zm_score::player_add_points( "rebuild_board", cost ); + self play_sound_on_ent( "purchase" ); + } + if ( isDefined( self.board_repair ) ) + { + self.board_repair += 1; + } +} + +blocker_unitrigger_think() +{ + self endon( "kill_trigger" ); + while ( 1 ) + { + self waittill( "trigger", player ); + self.stub.trigger_target notify( "trigger" ); + } +} + +blocker_trigger_think() +{ + self endon( "blocker_hacked" ); + if ( isDefined( level.no_board_repair ) && level.no_board_repair ) + { + return; + } +/# + println( "ZM >> TRIGGER blocker_trigger_think " ); +#/ + level endon( "stop_blocker_think" ); + cost = 10; + if ( isDefined( self.zombie_cost ) ) + { + cost = self.zombie_cost; + } + original_cost = cost; + if ( !isDefined( self.unitrigger_stub ) ) + { + radius = 94,21; + height = 94,21; + if ( isDefined( self.trigger_location ) ) + { + trigger_location = self.trigger_location; + } + else + { + trigger_location = self; + } + if ( isDefined( trigger_location.radius ) ) + { + radius = trigger_location.radius; + } + if ( isDefined( trigger_location.height ) ) + { + height = trigger_location.height; + } + trigger_pos = groundpos( trigger_location.origin ) + vectorScale( ( -1, 0, 0 ), 4 ); + self.unitrigger_stub = spawnstruct(); + self.unitrigger_stub.origin = trigger_pos; + self.unitrigger_stub.radius = radius; + self.unitrigger_stub.height = height; + self.unitrigger_stub.script_unitrigger_type = "unitrigger_radius"; + self.unitrigger_stub.hint_string = get_hint_string( self, "default_reward_barrier_piece" ); + self.unitrigger_stub.cursor_hint = "HINT_NOICON"; + self.unitrigger_stub.trigger_target = self; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.unitrigger_stub, ::blocker_unitrigger_think ); + maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger_stub ); + if ( !isDefined( trigger_location.angles ) ) + { + trigger_location.angles = ( -1, 0, 0 ); + } + self.unitrigger_stub.origin = ( groundpos( trigger_location.origin ) + vectorScale( ( -1, 0, 0 ), 4 ) ) + ( anglesToForward( trigger_location.angles ) * -11 ); + } + self thread trigger_delete_on_repair(); + thread maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.unitrigger_stub, ::blocker_unitrigger_think ); +/# + if ( getDvarInt( "zombie_debug" ) > 0 ) + { + thread debug_blocker( trigger_pos, radius, height ); +#/ + } + while ( 1 ) + { + self waittill( "trigger", player ); + has_perk = player has_blocker_affecting_perk(); + if ( all_chunks_intact( self, self.barrier_chunks ) ) + { + self notify( "all_boards_repaired" ); + return; + } + if ( no_valid_repairable_boards( self, self.barrier_chunks ) ) + { + self notify( "no valid boards" ); + return; + } + if ( isDefined( level._zm_blocker_trigger_think_return_override ) ) + { + if ( self [[ level._zm_blocker_trigger_think_return_override ]]( player ) ) + { + return; + } + } + while ( 1 ) + { + players = get_players(); + if ( player_fails_blocker_repair_trigger_preamble( player, players, self.unitrigger_stub.trigger, 0 ) ) + { + break; + } + else if ( isDefined( self.zbarrier ) ) + { + chunk = get_random_destroyed_chunk( self, self.barrier_chunks ); + if ( isDefined( player.pers_upgrades_awarded[ "board" ] ) ) + { + self thread replace_chunk( self, chunk, has_perk, player.pers_upgrades_awarded[ "board" ] ); + } + } + else + { + chunk = get_random_destroyed_chunk( self, self.barrier_chunks ); + if ( isDefined( chunk.script_parameter ) || chunk.script_parameters == "repair_board" && chunk.script_parameters == "barricade_vents" ) + { + if ( isDefined( chunk.unbroken_section ) ) + { + chunk show(); + chunk solid(); + chunk.unbroken_section self_delete(); + } + } + else + { + chunk show(); + } + if ( isDefined( chunk.script_parameters ) && chunk.script_parameters != "board" || chunk.script_parameters == "repair_board" && chunk.script_parameters == "barricade_vents" ) + { + if ( isDefined( level.use_clientside_board_fx ) && !level.use_clientside_board_fx ) + { + if ( !isDefined( chunk.material ) || isDefined( chunk.material ) && chunk.material != "rock" ) + { + chunk play_sound_on_ent( "rebuild_barrier_piece" ); + } + playsoundatposition( "zmb_cha_ching", ( -1, 0, 0 ) ); + } + } + if ( chunk.script_parameters == "bar" ) + { + chunk play_sound_on_ent( "rebuild_barrier_piece" ); + playsoundatposition( "zmb_cha_ching", ( -1, 0, 0 ) ); + } + if ( isDefined( chunk.script_parameters ) ) + { + if ( chunk.script_parameters == "bar" ) + { + if ( isDefined( chunk.script_noteworthy ) ) + { + if ( chunk.script_noteworthy == "5" ) + { + chunk hide(); + break; + } + else + { + if ( chunk.script_noteworthy == "3" ) + { + chunk hide(); + } + } + } + } + } + if ( isDefined( player.pers_upgrades_awarded[ "board" ] ) ) + { + self thread replace_chunk( self, chunk, has_perk, player.pers_upgrades_awarded[ "board" ] ); + } + } + if ( isDefined( self.clip ) ) + { + self.clip enable_trigger(); + self.clip disconnectpaths(); + } + else + { + blocker_disconnect_paths( self.neg_start, self.neg_end ); + } + bbprint( "zombie_uses", "playername %s playerscore %d round %d cost %d name %s x %f y %f z %f type %s", player.name, player.score, level.round_number, original_cost, self.target, self.origin, "repair" ); + self do_post_chunk_repair_delay( has_perk ); + if ( !is_player_valid( player ) ) + { + break; + } + else + { + player handle_post_board_repair_rewards( cost, self ); + if ( all_chunks_intact( self, self.barrier_chunks ) ) + { + self notify( "all_boards_repaired" ); + return; + } + if ( no_valid_repairable_boards( self, self.barrier_chunks ) ) + { + self notify( "no valid boards" ); + return; + } + } + } + } +} + +random_destroyed_chunk_show() +{ + wait 0,5; + self show(); +} + +door_repaired_rumble_n_sound() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( distance( players[ i ].origin, self.origin ) < 150 ) + { + if ( isalive( players[ i ] ) ) + { + players[ i ] thread board_completion(); + } + } + i++; + } +} + +board_completion() +{ + self endon( "disconnect" ); +} + +trigger_delete_on_repair() +{ + while ( 1 ) + { + self waittill_either( "all_boards_repaired", "no valid boards" ); + maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger_stub ); + return; + } +} + +rebuild_barrier_reward_reset() +{ + self.rebuild_barrier_reward = 0; +} + +remove_chunk( chunk, node, destroy_immediately, zomb ) +{ + chunk update_states( "mid_tear" ); + if ( isDefined( chunk.script_parameters ) ) + { + if ( chunk.script_parameters != "board" || chunk.script_parameters == "repair_board" && chunk.script_parameters == "barricade_vents" ) + { + chunk thread zombie_boardtear_audio_offset( chunk ); + } + } + if ( isDefined( chunk.script_parameters ) ) + { + if ( chunk.script_parameters == "bar" ) + { + chunk thread zombie_bartear_audio_offset( chunk ); + } + } + chunk notsolid(); + fx = "wood_chunk_destory"; + if ( isDefined( self.script_fxid ) ) + { + fx = self.script_fxid; + } + if ( isDefined( chunk.script_moveoverride ) && chunk.script_moveoverride ) + { + chunk hide(); + } + if ( isDefined( chunk.script_parameters ) && chunk.script_parameters == "bar" ) + { + if ( isDefined( chunk.script_noteworthy ) && chunk.script_noteworthy == "4" ) + { + ent = spawn( "script_origin", chunk.origin ); + ent.angles = node.angles + vectorScale( ( -1, 0, 0 ), 180 ); + dist = 100; + if ( isDefined( chunk.script_move_dist ) ) + { + dist_max = chunk.script_move_dist - 100; + dist = 100 + randomint( dist_max ); + } + else + { + dist = 100 + randomint( 100 ); + } + dest = ent.origin + ( anglesToForward( ent.angles ) * dist ); + trace = bullettrace( dest + vectorScale( ( -1, 0, 0 ), 16 ), dest + vectorScale( ( -1, 0, 0 ), 200 ), 0, undefined ); + if ( trace[ "fraction" ] == 1 ) + { + dest += vectorScale( ( -1, 0, 0 ), 200 ); + } + else + { + dest = trace[ "position" ]; + } + chunk linkto( ent ); + time = ent fake_physicslaunch( dest, 300 + randomint( 100 ) ); + if ( randomint( 100 ) > 40 ) + { + ent rotatepitch( 180, time * 0,5 ); + } + else + { + ent rotatepitch( 90, time, time * 0,5 ); + } + wait time; + chunk hide(); + wait 0,1; + ent delete(); + } + else + { + ent = spawn( "script_origin", chunk.origin ); + ent.angles = node.angles + vectorScale( ( -1, 0, 0 ), 180 ); + dist = 100; + if ( isDefined( chunk.script_move_dist ) ) + { + dist_max = chunk.script_move_dist - 100; + dist = 100 + randomint( dist_max ); + } + else + { + dist = 100 + randomint( 100 ); + } + dest = ent.origin + ( anglesToForward( ent.angles ) * dist ); + trace = bullettrace( dest + vectorScale( ( -1, 0, 0 ), 16 ), dest + vectorScale( ( -1, 0, 0 ), 200 ), 0, undefined ); + if ( trace[ "fraction" ] == 1 ) + { + dest += vectorScale( ( -1, 0, 0 ), 200 ); + } + else + { + dest = trace[ "position" ]; + } + chunk linkto( ent ); + time = ent fake_physicslaunch( dest, 260 + randomint( 100 ) ); + if ( randomint( 100 ) > 40 ) + { + ent rotatepitch( 180, time * 0,5 ); + } + else + { + ent rotatepitch( 90, time, time * 0,5 ); + } + wait time; + chunk hide(); + wait 0,1; + ent delete(); + } + chunk update_states( "destroyed" ); + chunk notify( "destroyed" ); + } + if ( isDefined( chunk.script_parameters ) && chunk.script_parameters != "board" || chunk.script_parameters == "repair_board" && chunk.script_parameters == "barricade_vents" ) + { + ent = spawn( "script_origin", chunk.origin ); + ent.angles = node.angles + vectorScale( ( -1, 0, 0 ), 180 ); + dist = 100; + if ( isDefined( chunk.script_move_dist ) ) + { + dist_max = chunk.script_move_dist - 100; + dist = 100 + randomint( dist_max ); + } + else + { + dist = 100 + randomint( 100 ); + } + dest = ent.origin + ( anglesToForward( ent.angles ) * dist ); + trace = bullettrace( dest + vectorScale( ( -1, 0, 0 ), 16 ), dest + vectorScale( ( -1, 0, 0 ), 200 ), 0, undefined ); + if ( trace[ "fraction" ] == 1 ) + { + dest += vectorScale( ( -1, 0, 0 ), 200 ); + } + else + { + dest = trace[ "position" ]; + } + chunk linkto( ent ); + time = ent fake_physicslaunch( dest, 200 + randomint( 100 ) ); + if ( isDefined( chunk.unbroken_section ) ) + { + if ( !isDefined( chunk.material ) || chunk.material != "metal" ) + { + chunk.unbroken_section self_delete(); + } + } + if ( randomint( 100 ) > 40 ) + { + ent rotatepitch( 180, time * 0,5 ); + } + else + { + ent rotatepitch( 90, time, time * 0,5 ); + } + wait time; + if ( isDefined( chunk.unbroken_section ) ) + { + if ( isDefined( chunk.material ) && chunk.material == "metal" ) + { + chunk.unbroken_section self_delete(); + } + } + chunk hide(); + wait 0,1; + ent delete(); + chunk update_states( "destroyed" ); + chunk notify( "destroyed" ); + } + if ( isDefined( chunk.script_parameters ) && chunk.script_parameters == "grate" ) + { + if ( isDefined( chunk.script_noteworthy ) && chunk.script_noteworthy == "6" ) + { + ent = spawn( "script_origin", chunk.origin ); + ent.angles = node.angles + vectorScale( ( -1, 0, 0 ), 180 ); + dist = 100 + randomint( 100 ); + dest = ent.origin + ( anglesToForward( ent.angles ) * dist ); + trace = bullettrace( dest + vectorScale( ( -1, 0, 0 ), 16 ), dest + vectorScale( ( -1, 0, 0 ), 200 ), 0, undefined ); + if ( trace[ "fraction" ] == 1 ) + { + dest += vectorScale( ( -1, 0, 0 ), 200 ); + } + else + { + dest = trace[ "position" ]; + } + chunk linkto( ent ); + time = ent fake_physicslaunch( dest, 200 + randomint( 100 ) ); + if ( randomint( 100 ) > 40 ) + { + ent rotatepitch( 180, time * 0,5 ); + } + else + { + ent rotatepitch( 90, time, time * 0,5 ); + } + wait time; + chunk hide(); + ent delete(); + chunk update_states( "destroyed" ); + chunk notify( "destroyed" ); + return; + } + else + { + chunk hide(); + chunk update_states( "destroyed" ); + chunk notify( "destroyed" ); + } + } +} + +remove_chunk_rotate_grate( chunk ) +{ + if ( isDefined( chunk.script_parameters ) && chunk.script_parameters == "grate" ) + { + chunk vibrate( vectorScale( ( -1, 0, 0 ), 270 ), 0,2, 0,4, 0,4 ); + return; + } +} + +zombie_boardtear_audio_offset( chunk ) +{ + if ( isDefined( chunk.material ) && !isDefined( chunk.already_broken ) ) + { + chunk.already_broken = 0; + } + if ( isDefined( chunk.material ) && chunk.material == "glass" && chunk.already_broken == 0 ) + { + chunk playsound( "zmb_break_glass_barrier" ); + wait randomfloatrange( 0,3, 0,6 ); + chunk playsound( "zmb_break_glass_barrier" ); + chunk.already_broken = 1; + } + else + { + if ( isDefined( chunk.material ) && chunk.material == "metal" && chunk.already_broken == 0 ) + { + chunk playsound( "grab_metal_bar" ); + wait randomfloatrange( 0,3, 0,6 ); + chunk playsound( "break_metal_bar" ); + chunk.already_broken = 1; + return; + } + else + { + if ( isDefined( chunk.material ) && chunk.material == "rock" ) + { + if ( isDefined( level.use_clientside_rock_tearin_fx ) && !level.use_clientside_rock_tearin_fx ) + { + chunk playsound( "zmb_break_rock_barrier" ); + wait randomfloatrange( 0,3, 0,6 ); + chunk playsound( "zmb_break_rock_barrier" ); + } + chunk.already_broken = 1; + return; + } + else + { + if ( isDefined( chunk.material ) && chunk.material == "metal_vent" ) + { + if ( isDefined( level.use_clientside_board_fx ) && !level.use_clientside_board_fx ) + { + chunk playsound( "evt_vent_slat_remove" ); + } + return; + } + else + { + if ( isDefined( level.use_clientside_board_fx ) && !level.use_clientside_board_fx ) + { + chunk play_sound_on_ent( "break_barrier_piece" ); + wait randomfloatrange( 0,3, 0,6 ); + chunk play_sound_on_ent( "break_barrier_piece" ); + } + chunk.already_broken = 1; + } + } + } + } +} + +zombie_bartear_audio_offset( chunk ) +{ + chunk play_sound_on_ent( "grab_metal_bar" ); + wait randomfloatrange( 0,3, 0,6 ); + chunk play_sound_on_ent( "break_metal_bar" ); + wait randomfloatrange( 1, 1,3 ); + chunk play_sound_on_ent( "drop_metal_bar" ); +} + +ensure_chunk_is_back_to_origin( chunk ) +{ + if ( chunk.origin != chunk.og_origin ) + { + chunk notsolid(); + chunk waittill( "movedone" ); + } +} + +replace_chunk( barrier, chunk, perk, upgrade, via_powerup ) +{ + if ( !isDefined( barrier.zbarrier ) ) + { + chunk update_states( "mid_repair" ); +/# + assert( isDefined( chunk.og_origin ) ); +#/ +/# + assert( isDefined( chunk.og_angles ) ); +#/ + sound = "rebuild_barrier_hover"; + if ( isDefined( chunk.script_presound ) ) + { + sound = chunk.script_presound; + } + } + has_perk = 0; + if ( isDefined( perk ) ) + { + has_perk = 1; + } + if ( !isDefined( via_powerup ) && isDefined( sound ) ) + { + play_sound_at_pos( sound, chunk.origin ); + } + if ( upgrade ) + { + barrier.zbarrier zbarrierpieceuseupgradedmodel( chunk ); + barrier.zbarrier.chunk_health[ chunk ] = barrier.zbarrier getupgradedpiecenumlives( chunk ); + } + else + { + barrier.zbarrier zbarrierpieceusedefaultmodel( chunk ); + barrier.zbarrier.chunk_health[ chunk ] = 0; + } + scalar = 1; + if ( has_perk ) + { + if ( perk == "speciality_fastreload" ) + { + scalar = 0,31; + } + else + { + if ( perk == "speciality_fastreload_upgrade" ) + { + scalar = 0,2112; + } + } + } + barrier.zbarrier showzbarrierpiece( chunk ); + barrier.zbarrier setzbarrierpiecestate( chunk, "closing", scalar ); + waitduration = barrier.zbarrier getzbarrierpieceanimlengthforstate( chunk, "closing", scalar ); + wait waitduration; +} + +open_all_zbarriers() +{ + _a2642 = level.exterior_goals; + _k2642 = getFirstArrayKey( _a2642 ); + while ( isDefined( _k2642 ) ) + { + barrier = _a2642[ _k2642 ]; + while ( isDefined( barrier.zbarrier ) ) + { + x = 0; + while ( x < barrier.zbarrier getnumzbarrierpieces() ) + { + barrier.zbarrier setzbarrierpiecestate( x, "opening" ); + x++; + } + } + if ( isDefined( barrier.clip ) ) + { + barrier.clip disable_trigger(); + barrier.clip connectpaths(); + } + else + { + blocker_connect_paths( barrier.neg_start, barrier.neg_end ); + } + _k2642 = getNextArrayKey( _a2642, _k2642 ); + } +} + +zombie_boardtear_audio_plus_fx_offset_repair_horizontal( chunk ) +{ + if ( isDefined( chunk.material ) && chunk.material == "rock" ) + { + if ( isDefined( level.use_clientside_rock_tearin_fx ) && level.use_clientside_rock_tearin_fx ) + { + chunk clearclientflag( level._zombie_scriptmover_flag_rock_fx ); + } + else + { + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), chunk.origin, 150 ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0,3, 0,6 ); + chunk play_sound_on_ent( "break_barrier_piece" ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + } + } + else + { + if ( isDefined( level.use_clientside_board_fx ) && level.use_clientside_board_fx ) + { + chunk clearclientflag( level._zombie_scriptmover_flag_board_horizontal_fx ); + return; + } + else + { + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), chunk.origin, 150 ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0,3, 0,6 ); + chunk play_sound_on_ent( "break_barrier_piece" ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + } + } +} + +zombie_boardtear_audio_plus_fx_offset_repair_verticle( chunk ) +{ + if ( isDefined( chunk.material ) && chunk.material == "rock" ) + { + if ( isDefined( level.use_clientside_rock_tearin_fx ) && level.use_clientside_rock_tearin_fx ) + { + chunk clearclientflag( level._zombie_scriptmover_flag_rock_fx ); + } + else + { + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), chunk.origin, 150 ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0,3, 0,6 ); + chunk play_sound_on_ent( "break_barrier_piece" ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + } + } + else + { + if ( isDefined( level.use_clientside_board_fx ) && level.use_clientside_board_fx ) + { + chunk clearclientflag( level._zombie_scriptmover_flag_board_vertical_fx ); + return; + } + else + { + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), chunk.origin, 150 ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0,3, 0,6 ); + chunk play_sound_on_ent( "break_barrier_piece" ); + playfx( level._effect[ "wood_chunk_destory" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + } + } +} + +zombie_gratetear_audio_plus_fx_offset_repair_horizontal( chunk ) +{ + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), chunk.origin, 150 ); + chunk play_sound_on_ent( "bar_rebuild_slam" ); + switch( randomint( 9 ) ) + { + case 0: + playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0, 0,3 ); + playfx( level._effect[ "fx_zombie_bar_break_lite" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 1: + playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0, 0,3 ); + playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 2: + playfx( level._effect[ "fx_zombie_bar_break_lite" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0, 0,3 ); + playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 3: + playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0, 0,3 ); + playfx( level._effect[ "fx_zombie_bar_break_lite" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 4: + playfx( level._effect[ "fx_zombie_bar_break_lite" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + wait randomfloatrange( 0, 0,3 ); + playfx( level._effect[ "fx_zombie_bar_break_lite" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 5: + playfx( level._effect[ "fx_zombie_bar_break_lite" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 6: + playfx( level._effect[ "fx_zombie_bar_break_lite" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 7: + playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + case 8: + playfx( level._effect[ "fx_zombie_bar_break" ], chunk.origin + vectorScale( ( -1, 0, 0 ), 30 ) ); + break; + } +} + +zombie_bartear_audio_plus_fx_offset_repair_horizontal( chunk ) +{ + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), chunk.origin, 150 ); + chunk play_sound_on_ent( "bar_rebuild_slam" ); + switch( randomint( 9 ) ) + { + case 0: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" ); + break; + case 1: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_left" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_right" ); + break; + case 2: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_right" ); + break; + case 3: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_left" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" ); + break; + case 4: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" ); + break; + case 5: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_left" ); + break; + case 6: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_right" ); + break; + case 7: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_left" ); + break; + case 8: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_right" ); + break; + } +} + +zombie_bartear_audio_plus_fx_offset_repair_verticle( chunk ) +{ + earthquake( randomfloatrange( 0,3, 0,4 ), randomfloatrange( 0,2, 0,4 ), chunk.origin, 150 ); + chunk play_sound_on_ent( "bar_rebuild_slam" ); + switch( randomint( 9 ) ) + { + case 0: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" ); + break; + case 1: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_top" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_bottom" ); + break; + case 2: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_bottom" ); + break; + case 3: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_top" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" ); + break; + case 4: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" ); + wait randomfloatrange( 0, 0,3 ); + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" ); + break; + case 5: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_top" ); + break; + case 6: + playfxontag( level._effect[ "fx_zombie_bar_break_lite" ], chunk, "Tag_fx_bottom" ); + break; + case 7: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_top" ); + break; + case 8: + playfxontag( level._effect[ "fx_zombie_bar_break" ], chunk, "Tag_fx_bottom" ); + break; + } +} + +add_new_zombie_spawners() +{ + if ( isDefined( self.target ) ) + { + self.possible_spawners = getentarray( self.target, "targetname" ); + } + if ( isDefined( self.script_string ) ) + { + spawners = getentarray( self.script_string, "targetname" ); + self.possible_spawners = arraycombine( self.possible_spawners, spawners, 1, 0 ); + } + if ( !isDefined( self.possible_spawners ) ) + { + return; + } + zombies_to_add = self.possible_spawners; + i = 0; + while ( i < self.possible_spawners.size ) + { + self.possible_spawners[ i ].is_enabled = 1; + add_spawner( self.possible_spawners[ i ] ); + i++; + } +} + +flag_blocker() +{ + if ( !isDefined( self.script_flag_wait ) ) + { +/# + assertmsg( "Flag Blocker at " + self.origin + " does not have a script_flag_wait key value pair" ); +#/ + return; + } + if ( !isDefined( level.flag[ self.script_flag_wait ] ) ) + { + flag_init( self.script_flag_wait ); + } + type = "connectpaths"; + if ( isDefined( self.script_noteworthy ) ) + { + type = self.script_noteworthy; + } + flag_wait( self.script_flag_wait ); + self script_delay(); + if ( type == "connectpaths" ) + { + self connectpaths(); + self disable_trigger(); + return; + } + if ( type == "disconnectpaths" ) + { + self disconnectpaths(); + self disable_trigger(); + return; + } +/# + assertmsg( "flag blocker at " + self.origin + ", the type "" + type + "" is not recognized" ); +#/ +} + +update_states( states ) +{ +/# + assert( isDefined( states ) ); +#/ + self.state = states; +} + +quantum_bomb_open_nearest_door_validation( position ) +{ + range_squared = 32400; + zombie_doors = getentarray( "zombie_door", "targetname" ); + i = 0; + while ( i < zombie_doors.size ) + { + if ( distancesquared( zombie_doors[ i ].origin, position ) < range_squared ) + { + return 1; + } + i++; + } + zombie_airlock_doors = getentarray( "zombie_airlock_buy", "targetname" ); + i = 0; + while ( i < zombie_airlock_doors.size ) + { + if ( distancesquared( zombie_airlock_doors[ i ].origin, position ) < range_squared ) + { + return 1; + } + i++; + } + zombie_debris = getentarray( "zombie_debris", "targetname" ); + i = 0; + while ( i < zombie_debris.size ) + { + if ( distancesquared( zombie_debris[ i ].origin, position ) < range_squared ) + { + return 1; + } + i++; + } + return 0; +} + +quantum_bomb_open_nearest_door_result( position ) +{ + range_squared = 32400; + zombie_doors = getentarray( "zombie_door", "targetname" ); + i = 0; + while ( i < zombie_doors.size ) + { + if ( distancesquared( zombie_doors[ i ].origin, position ) < range_squared ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + zombie_doors[ i ] notify( "trigger" ); + [[ level.quantum_bomb_play_area_effect_func ]]( position ); + return; + } + i++; + } + zombie_airlock_doors = getentarray( "zombie_airlock_buy", "targetname" ); + i = 0; + while ( i < zombie_airlock_doors.size ) + { + if ( distancesquared( zombie_airlock_doors[ i ].origin, position ) < range_squared ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + zombie_airlock_doors[ i ] notify( "trigger" ); + [[ level.quantum_bomb_play_area_effect_func ]]( position ); + return; + } + i++; + } + zombie_debris = getentarray( "zombie_debris", "targetname" ); + i = 0; + while ( i < zombie_debris.size ) + { + if ( distancesquared( zombie_debris[ i ].origin, position ) < range_squared ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + zombie_debris[ i ] notify( "trigger" ); + [[ level.quantum_bomb_play_area_effect_func ]]( position ); + return; + } + i++; + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_buildables.gsc b/patch_zm/maps/mp/zombies/_zm_buildables.gsc new file mode 100644 index 0000000..ac5a68f --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_buildables.gsc @@ -0,0 +1,3195 @@ +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + precachestring( &"ZOMBIE_BUILDING" ); + precachestring( &"ZOMBIE_BUILD_PIECE_MISSING" ); + precachestring( &"ZOMBIE_BUILD_PIECE_GRAB" ); + precacheitem( "zombie_builder_zm" ); + precacheitem( "buildable_piece_zm" ); + level.gameobjswapping = 1; + zombie_buildables_callbacks = []; + level.buildablepickups = []; + level.buildables_built = []; + level.buildable_stubs = []; + level.buildable_piece_count = 0; + level._effect[ "building_dust" ] = loadfx( "maps/zombie/fx_zmb_buildable_assemble_dust" ); + if ( isDefined( level.init_buildables ) ) + { + [[ level.init_buildables ]](); + } + if ( isDefined( level.use_swipe_protection ) ) + { + onplayerconnect_callback( ::buildables_watch_swipes ); + } +} + +anystub_update_prompt( player ) +{ + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() || player in_revive_trigger() ) + { + self.hint_string = ""; + return 0; + } + if ( player isthrowinggrenade() ) + { + self.hint_string = ""; + return 0; + } + if ( isDefined( player.is_drinking ) && player.is_drinking > 0 ) + { + self.hint_string = ""; + return 0; + } + if ( isDefined( player.screecher_weapon ) ) + { + self.hint_string = ""; + return 0; + } + return 1; +} + +anystub_get_unitrigger_origin() +{ + if ( isDefined( self.origin_parent ) ) + { + return self.origin_parent.origin; + } + return self.origin; +} + +anystub_on_spawn_trigger( trigger ) +{ + if ( isDefined( self.link_parent ) ) + { + trigger enablelinkto(); + trigger linkto( self.link_parent ); + trigger setmovingplatformenabled( 1 ); + } +} + +buildables_watch_swipes() +{ + self endon( "disconnect" ); + self notify( "buildables_watch_swipes" ); + self endon( "buildables_watch_swipes" ); + while ( 1 ) + { + self waittill( "melee_swipe", zombie ); + while ( distancesquared( zombie.origin, self.origin ) > ( zombie.meleeattackdist * zombie.meleeattackdist ) ) + { + continue; + } + trigger = level._unitriggers.trigger_pool[ self getentitynumber() ]; + if ( isDefined( trigger ) && isDefined( trigger.stub.piece ) ) + { + piece = trigger.stub.piece; + if ( !isDefined( piece.damage ) ) + { + piece.damage = 0; + } + piece.damage++; + if ( piece.damage > 12 ) + { + thread maps/mp/zombies/_zm_equipment::equipment_disappear_fx( trigger.stub maps/mp/zombies/_zm_unitrigger::unitrigger_origin() ); + piece maps/mp/zombies/_zm_buildables::piece_unspawn(); + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + if ( isalive( self ) ) + { + self playlocalsound( level.zmb_laugh_alias ); + } + } + } + } +} + +explosiondamage( damage, pos ) +{ +/# + println( "ZM BUILDABLE Explode do " + damage + " damage to " + self.name + "\n" ); +#/ + self dodamage( damage, pos ); +} + +add_zombie_buildable( buildable_name, hint, building, bought ) +{ + if ( !isDefined( level.zombie_include_buildables ) ) + { + level.zombie_include_buildables = []; + } + if ( isDefined( level.zombie_include_buildables ) && !isDefined( level.zombie_include_buildables[ buildable_name ] ) ) + { + return; + } + precachestring( hint ); + if ( isDefined( building ) ) + { + precachestring( building ); + } + if ( isDefined( bought ) ) + { + precachestring( bought ); + } + buildable_struct = level.zombie_include_buildables[ buildable_name ]; + if ( !isDefined( level.zombie_buildables ) ) + { + level.zombie_buildables = []; + } + buildable_struct.hint = hint; + buildable_struct.building = building; + buildable_struct.bought = bought; +/# + println( "ZM >> Looking for buildable - " + buildable_struct.name ); +#/ + level.zombie_buildables[ buildable_struct.name ] = buildable_struct; + if ( !level.createfx_enabled ) + { + if ( level.zombie_buildables.size == 1 ) + { + register_clientfields(); + } + } +} + +register_clientfields() +{ + if ( isDefined( level.buildable_slot_count ) ) + { + i = 0; + while ( i < level.buildable_slot_count ) + { + bits = getminbitcountfornum( level.buildable_piece_counts[ i ] ); + registerclientfield( "toplayer", level.buildable_clientfields[ i ], 12000, bits, "int" ); + i++; + } + } + else bits = getminbitcountfornum( level.buildable_piece_count ); + registerclientfield( "toplayer", "buildable", 1, bits, "int" ); +} + +set_buildable_clientfield( slot, newvalue ) +{ + if ( isDefined( level.buildable_slot_count ) ) + { + self setclientfieldtoplayer( level.buildable_clientfields[ slot ], newvalue ); + } + else + { + self setclientfieldtoplayer( "buildable", newvalue ); + } +} + +clear_buildable_clientfield( slot ) +{ + self set_buildable_clientfield( slot, 0 ); +} + +include_zombie_buildable( buiildable_struct ) +{ + if ( !isDefined( level.zombie_include_buildables ) ) + { + level.zombie_include_buildables = []; + } +/# + println( "ZM >> Including buildable - " + buiildable_struct.name ); +#/ + level.zombie_include_buildables[ buiildable_struct.name ] = buiildable_struct; +} + +generate_zombie_buildable_piece( buildablename, modelname, radius, height, drop_offset, hud_icon, onpickup, ondrop, use_spawn_num, part_name, can_reuse, client_field_state, buildable_slot ) +{ + precachemodel( modelname ); + if ( isDefined( hud_icon ) ) + { + precacheshader( hud_icon ); + } + piece = spawnstruct(); + buildable_pieces = []; + buildable_pieces_structs = getstructarray( ( buildablename + "_" ) + modelname, "targetname" ); +/# + if ( buildable_pieces_structs.size < 1 ) + { + println( "ERROR: Missing buildable piece <" + buildablename + "> <" + modelname + ">\n" ); +#/ + } + _a240 = buildable_pieces_structs; + index = getFirstArrayKey( _a240 ); + while ( isDefined( index ) ) + { + struct = _a240[ index ]; + buildable_pieces[ index ] = struct; + buildable_pieces[ index ].hasspawned = 0; + index = getNextArrayKey( _a240, index ); + } + piece.spawns = buildable_pieces; + piece.buildablename = buildablename; + piece.modelname = modelname; + piece.hud_icon = hud_icon; + piece.radius = radius; + piece.height = height; + piece.part_name = part_name; + piece.can_reuse = can_reuse; + piece.drop_offset = drop_offset; + piece.max_instances = 256; + if ( isDefined( buildable_slot ) ) + { + piece.buildable_slot = buildable_slot; + } + else + { + piece.buildable_slot = 0; + } + piece.onpickup = onpickup; + piece.ondrop = ondrop; + piece.use_spawn_num = use_spawn_num; + piece.client_field_state = client_field_state; + return piece; +} + +manage_multiple_pieces( max_instances, min_instances ) +{ + self.max_instances = max_instances; + self.min_instances = min_instances; + self.managing_pieces = 1; + self.piece_allocated = []; +} + +buildable_set_force_spawn_location( str_kvp, str_name ) +{ + self.str_force_spawn_kvp = str_kvp; + self.str_force_spawn_name = str_name; +} + +buildable_use_cyclic_spawns( randomize_start_location ) +{ + self.use_cyclic_spawns = 1; + self.randomize_cyclic_index = randomize_start_location; +} + +combine_buildable_pieces( piece1, piece2, piece3 ) +{ + spawns1 = piece1.spawns; + spawns2 = piece2.spawns; + spawns = arraycombine( spawns1, spawns2, 1, 0 ); + if ( isDefined( piece3 ) ) + { + spawns3 = piece3.spawns; + spawns = arraycombine( spawns, spawns3, 1, 0 ); + spawns = array_randomize( spawns ); + piece3.spawns = spawns; + } + else + { + spawns = array_randomize( spawns ); + } + piece1.spawns = spawns; + piece2.spawns = spawns; +} + +add_buildable_piece( piece, part_name, can_reuse ) +{ + if ( !isDefined( self.buildablepieces ) ) + { + self.buildablepieces = []; + } + if ( isDefined( part_name ) ) + { + piece.part_name = part_name; + } + if ( isDefined( can_reuse ) ) + { + piece.can_reuse = can_reuse; + } + self.buildablepieces[ self.buildablepieces.size ] = piece; + if ( !isDefined( self.buildable_slot ) ) + { + self.buildable_slot = piece.buildable_slot; + } + else + { +/# + assert( self.buildable_slot == piece.buildable_slot ); +#/ + } +} + +create_zombie_buildable_piece( modelname, radius, height, hud_icon ) +{ + piece = generate_zombie_buildable_piece( self.name, modelname, radius, height, hud_icon ); + self add_buildable_piece( piece ); +} + +onplayerlaststand() +{ + pieces = self player_get_buildable_pieces(); + spawn_pos = []; + spawn_pos[ 0 ] = self.origin; + while ( pieces.size >= 2 ) + { + nodes = getnodesinradiussorted( self.origin + vectorScale( ( 0, 0, 1 ), 30 ), 120, 30, 72, "path", 5 ); + i = 0; + while ( i < pieces.size ) + { + if ( i < nodes.size && check_point_in_playable_area( nodes[ i ].origin ) ) + { + spawn_pos[ i ] = nodes[ i ].origin; + i++; + continue; + } + else + { + spawn_pos[ i ] = self.origin + vectorScale( ( 0, 0, 1 ), 5 ); + } + i++; + } + } + spawnidx = 0; + _a366 = pieces; + _k366 = getFirstArrayKey( _a366 ); + while ( isDefined( _k366 ) ) + { + piece = _a366[ _k366 ]; + slot = piece.buildable_slot; + if ( isDefined( piece ) ) + { + return_to_start_pos = 0; + if ( isDefined( level.safe_place_for_buildable_piece ) ) + { + if ( !( self [[ level.safe_place_for_buildable_piece ]]( piece ) ) ) + { + return_to_start_pos = 1; + } + } + if ( return_to_start_pos ) + { + piece piece_spawn_at(); + } + else if ( pieces.size < 2 ) + { + piece piece_spawn_at( self.origin + vectorScale( ( 0, 0, 1 ), 5 ), self.angles ); + } + else + { + piece piece_spawn_at( spawn_pos[ spawnidx ], self.angles ); + } + if ( isDefined( piece.ondrop ) ) + { + piece [[ piece.ondrop ]]( self ); + } + self clear_buildable_clientfield( slot ); + spawnidx++; + } + self player_set_buildable_piece( undefined, slot ); + self notify( "piece_released" + slot ); + _k366 = getNextArrayKey( _a366, _k366 ); + } +} + +piecestub_get_unitrigger_origin() +{ + if ( isDefined( self.origin_parent ) ) + { + return self.origin_parent.origin + vectorScale( ( 0, 0, 1 ), 12 ); + } + return self.origin; +} + +generate_piece_unitrigger( classname, origin, angles, flags, radius, script_height, moving ) +{ + if ( !isDefined( radius ) ) + { + radius = 64; + } + if ( !isDefined( script_height ) ) + { + script_height = 64; + } + script_width = script_height; + if ( !isDefined( script_width ) ) + { + script_width = 64; + } + script_length = script_height; + if ( !isDefined( script_length ) ) + { + script_length = 64; + } + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = origin; + if ( isDefined( script_length ) ) + { + unitrigger_stub.script_length = script_length; + } + else + { + unitrigger_stub.script_length = 13,5; + } + if ( isDefined( script_width ) ) + { + unitrigger_stub.script_width = script_width; + } + else + { + unitrigger_stub.script_width = 27,5; + } + if ( isDefined( script_height ) ) + { + unitrigger_stub.script_height = script_height; + } + else + { + unitrigger_stub.script_height = 24; + } + unitrigger_stub.radius = radius; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + unitrigger_stub.hint_string = &"ZOMBIE_BUILD_PIECE_GRAB"; + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + unitrigger_stub.require_look_at = 0; + switch( classname ) + { + case "trigger_radius": + unitrigger_stub.script_unitrigger_type = "unitrigger_radius"; + break; + case "trigger_radius_use": + unitrigger_stub.script_unitrigger_type = "unitrigger_radius_use"; + break; + case "trigger_box": + unitrigger_stub.script_unitrigger_type = "unitrigger_box"; + break; + case "trigger_box_use": + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + break; + } + unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + unitrigger_stub.prompt_and_visibility_func = ::piecetrigger_update_prompt; + unitrigger_stub.originfunc = ::piecestub_get_unitrigger_origin; + unitrigger_stub.onspawnfunc = ::anystub_on_spawn_trigger; + if ( isDefined( moving ) && moving ) + { + maps/mp/zombies/_zm_unitrigger::register_unitrigger( unitrigger_stub, ::piece_unitrigger_think ); + } + else + { + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::piece_unitrigger_think ); + } + return unitrigger_stub; +} + +piecetrigger_update_prompt( player ) +{ + can_use = self.stub piecestub_update_prompt( player ); + self setinvisibletoplayer( player, !can_use ); + if ( isDefined( self.stub.hint_parm1 ) ) + { + self sethintstring( self.stub.hint_string, self.stub.hint_parm1 ); + } + else + { + self sethintstring( self.stub.hint_string ); + } + if ( isDefined( self.stub.cursor_hint ) ) + { + if ( self.stub.cursor_hint == "HINT_WEAPON" && isDefined( self.stub.cursor_hint_weapon ) ) + { + self setcursorhint( self.stub.cursor_hint, self.stub.cursor_hint_weapon ); + } + else + { + self setcursorhint( self.stub.cursor_hint ); + } + } + return can_use; +} + +piecestub_update_prompt( player ) +{ + if ( !self anystub_update_prompt( player ) ) + { + self.cursor_hint = "HINT_NOICON"; + return 0; + } + if ( isDefined( player player_get_buildable_piece( self.piece.buildable_slot ) ) ) + { + spiece = self.piece; + cpiece = player player_get_buildable_piece( self.piece.buildable_slot ); + if ( spiece.modelname == cpiece.modelname && spiece.buildablename == cpiece.buildablename && isDefined( spiece.script_noteworthy ) || !isDefined( cpiece.script_noteworthy ) && spiece.script_noteworthy == cpiece.script_noteworthy ) + { + self.hint_string = ""; + return 0; + } + if ( isDefined( spiece.hint_swap ) ) + { + self.hint_string = spiece.hint_swap; + self.hint_parm1 = self.piece.hint_swap_parm1; + } + else + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_SWITCH"; + } + if ( isDefined( self.piece.cursor_hint ) ) + { + self.cursor_hint = self.piece.cursor_hint; + } + if ( isDefined( self.piece.cursor_hint_weapon ) ) + { + self.cursor_hint_weapon = self.piece.cursor_hint_weapon; + } + } + else + { + if ( isDefined( self.piece.hint_grab ) ) + { + self.hint_string = self.piece.hint_grab; + self.hint_parm1 = self.piece.hint_grab_parm1; + } + else + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_GRAB"; + } + if ( isDefined( self.piece.cursor_hint ) ) + { + self.cursor_hint = self.piece.cursor_hint; + } + if ( isDefined( self.piece.cursor_hint_weapon ) ) + { + self.cursor_hint_weapon = self.piece.cursor_hint_weapon; + } + } + return 1; +} + +piece_unitrigger_think() +{ + self endon( "kill_trigger" ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( player != self.parent_player ) + { + continue; + } + while ( isDefined( player.screecher_weapon ) ) + { + continue; + } + while ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0,5 ); + } + status = player player_can_take_piece( self.stub.piece ); + if ( !status ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + continue; + } + else + { + player thread player_take_piece( self.stub.piece ); + } + } +} + +player_get_buildable_pieces() +{ + if ( !isDefined( self.current_buildable_pieces ) ) + { + self.current_buildable_pieces = []; + } + return self.current_buildable_pieces; +} + +player_get_buildable_piece( slot ) +{ + if ( !isDefined( slot ) ) + { + slot = 0; + } + if ( !isDefined( self.current_buildable_pieces ) ) + { + self.current_buildable_pieces = []; + } + return self.current_buildable_pieces[ slot ]; +} + +player_set_buildable_piece( piece, slot ) +{ + if ( !isDefined( slot ) ) + { + slot = 0; + } +/# + if ( isDefined( slot ) && isDefined( piece ) && isDefined( piece.buildable_slot ) ) + { + assert( slot == piece.buildable_slot ); +#/ + } + if ( !isDefined( self.current_buildable_pieces ) ) + { + self.current_buildable_pieces = []; + } + self.current_buildable_pieces[ slot ] = piece; +} + +player_can_take_piece( piece ) +{ + if ( !isDefined( piece ) ) + { + return 0; + } + return 1; +} + +dbline( from, to ) +{ +/# + time = 20; + while ( time > 0 ) + { + line( from, to, ( 0, 0, 1 ), 0, 1 ); + time -= 0,05; + wait 0,05; +#/ + } +} + +player_throw_piece( piece, origin, dir, return_to_spawn, return_time, endangles ) +{ +/# + assert( isDefined( piece ) ); +#/ + if ( isDefined( piece ) ) + { +/# + thread dbline( origin, origin + dir ); +#/ + pass = 0; + done = 0; + altmodel = undefined; + while ( pass < 2 && !done ) + { + grenade = self magicgrenadetype( "buildable_piece_zm", origin, dir, 30000 ); + grenade thread watch_hit_players(); + grenade ghost(); + if ( !isDefined( altmodel ) ) + { + altmodel = spawn( "script_model", grenade.origin ); + altmodel setmodel( piece.modelname ); + } + altmodel.origin = grenade.angles; + altmodel.angles = grenade.angles; + altmodel linkto( grenade, "", ( 0, 0, 1 ), ( 0, 0, 1 ) ); + grenade.altmodel = altmodel; + grenade waittill( "stationary" ); + grenade_origin = grenade.origin; + grenade_angles = grenade.angles; + landed_on = grenade getgroundent(); + grenade delete(); + if ( isDefined( landed_on ) && landed_on == level ) + { + done = 1; + continue; + } + else + { + origin = grenade_origin; + dir = ( ( dir[ 0 ] * -1 ) / 10, ( dir[ 1 ] * -1 ) / 10, -1 ); + pass++; + } + } + if ( !isDefined( endangles ) ) + { + endangles = grenade_angles; + } + piece piece_spawn_at( grenade_origin, endangles ); + if ( isDefined( altmodel ) ) + { + altmodel delete(); + } + if ( isDefined( piece.ondrop ) ) + { + piece [[ piece.ondrop ]]( self ); + } + if ( isDefined( return_to_spawn ) && return_to_spawn ) + { + piece piece_wait_and_return( return_time ); + } + } +} + +watch_hit_players() +{ + self endon( "death" ); + self endon( "stationary" ); + while ( isDefined( self ) ) + { + self waittill( "grenade_bounce", pos, normal, ent ); + if ( isplayer( ent ) ) + { + ent explosiondamage( 25, pos ); + } + } +} + +piece_wait_and_return( return_time ) +{ + self endon( "pickup" ); + wait 0,15; + if ( isDefined( level.exploding_jetgun_fx ) ) + { + playfxontag( level.exploding_jetgun_fx, self.model, "tag_origin" ); + } + else + { + playfxontag( level._effect[ "powerup_on" ], self.model, "tag_origin" ); + } + wait ( return_time - 6 ); + self piece_hide(); + wait 1; + self piece_show(); + wait 1; + self piece_hide(); + wait 1; + self piece_show(); + wait 1; + self piece_hide(); + wait 1; + self piece_show(); + wait 1; + self notify( "respawn" ); + self piece_unspawn(); + self piece_spawn_at(); +} + +player_return_piece_to_original_spawn( slot ) +{ + if ( !isDefined( slot ) ) + { + slot = 0; + } + self notify( "piece_released" + slot ); + piece = self player_get_buildable_piece( slot ); + self player_set_buildable_piece( undefined, slot ); + if ( isDefined( piece ) ) + { + piece piece_spawn_at(); + self clear_buildable_clientfield( slot ); + } +} + +player_drop_piece_on_death( slot ) +{ + self notify( "piece_released" + slot ); + self endon( "piece_released" + slot ); + origin = self.origin; + angles = self.angles; + piece = self player_get_buildable_piece( slot ); + self waittill( "death_or_disconnect" ); + piece piece_spawn_at( origin, angles ); + if ( isDefined( self ) ) + { + self clear_buildable_clientfield( slot ); + } + if ( isDefined( piece.ondrop ) ) + { + piece [[ piece.ondrop ]]( self ); + } +} + +player_drop_piece( piece, slot ) +{ + if ( !isDefined( slot ) ) + { + slot = 0; + } + if ( !isDefined( piece ) ) + { + piece = self player_get_buildable_piece( slot ); + } + else + { + slot = piece.buildable_slot; + } + if ( isDefined( piece ) ) + { + origin = self.origin; + origintrace = groundtrace( origin + vectorScale( ( 0, 0, 1 ), 5 ), origin - vectorScale( ( 0, 0, 1 ), 999999 ), 0, self ); + if ( isDefined( origintrace[ "entity" ] ) ) + { + origintrace = groundtrace( origintrace[ "entity" ].origin, origintrace[ "entity" ].origin - vectorScale( ( 0, 0, 1 ), 999999 ), 0, origintrace[ "entity" ] ); + } + if ( isDefined( origintrace[ "position" ] ) ) + { + origin = origintrace[ "position" ]; + } + piece.damage = 0; + piece piece_spawn_at( origin, self.angles ); + if ( isplayer( self ) ) + { + self clear_buildable_clientfield( slot ); + } + if ( isDefined( piece.ondrop ) ) + { + piece [[ piece.ondrop ]]( self ); + } + } + self player_set_buildable_piece( undefined, slot ); + self notify( "piece_released" + slot ); +} + +player_take_piece( piece ) +{ + piece_slot = piece.buildable_slot; + damage = piece.damage; + if ( isDefined( self player_get_buildable_piece( piece_slot ) ) ) + { + other_piece = self player_get_buildable_piece( piece_slot ); + self player_drop_piece( self player_get_buildable_piece( piece_slot ), piece_slot ); + other_piece.damage = damage; + self do_player_general_vox( "general", "build_swap" ); + } + if ( isDefined( piece.onpickup ) ) + { + piece [[ piece.onpickup ]]( self ); + } + piece piece_unspawn(); + piece notify( "pickup" ); + if ( isplayer( self ) ) + { + if ( isDefined( piece.client_field_state ) ) + { + self set_buildable_clientfield( piece_slot, piece.client_field_state ); + } + self player_set_buildable_piece( piece, piece_slot ); + self thread player_drop_piece_on_death( piece_slot ); + self track_buildable_piece_pickedup( piece ); + } +} + +player_destroy_piece( piece ) +{ + if ( !isDefined( piece ) ) + { + piece = self player_get_buildable_piece(); + } + if ( isplayer( self ) ) + { + slot = piece.buildable_slot; + if ( isDefined( piece ) ) + { + piece piece_destroy(); + self clear_buildable_clientfield( slot ); + } + self player_set_buildable_piece( undefined, slot ); + self notify( "piece_released" + slot ); + } +} + +claim_location( location ) +{ + if ( !isDefined( level.buildable_claimed_locations ) ) + { + level.buildable_claimed_locations = []; + } + if ( !isDefined( level.buildable_claimed_locations[ location ] ) ) + { + level.buildable_claimed_locations[ location ] = 1; + return 1; + } + return 0; +} + +is_point_in_build_trigger( point ) +{ + candidate_list = []; + _a911 = level.zones; + _k911 = getFirstArrayKey( _a911 ); + while ( isDefined( _k911 ) ) + { + zone = _a911[ _k911 ]; + if ( isDefined( zone.unitrigger_stubs ) ) + { + candidate_list = arraycombine( candidate_list, zone.unitrigger_stubs, 1, 0 ); + } + _k911 = getNextArrayKey( _a911, _k911 ); + } + valid_range = 128; + closest = maps/mp/zombies/_zm_unitrigger::get_closest_unitriggers( point, candidate_list, valid_range ); + index = 0; + while ( index < closest.size ) + { + if ( isDefined( closest[ index ].registered ) && closest[ index ].registered && isDefined( closest[ index ].piece ) ) + { + return 1; + } + index++; + } + return 0; +} + +piece_allocate_spawn( piecespawn ) +{ + self.current_spawn = 0; + self.managed_spawn = 1; + self.piecespawn = piecespawn; + while ( isDefined( piecespawn.str_force_spawn_kvp ) ) + { + s_struct = getstruct( piecespawn.str_force_spawn_name, piecespawn.str_force_spawn_kvp ); + while ( isDefined( s_struct ) ) + { + i = 0; + while ( i < self.spawns.size ) + { + if ( s_struct == self.spawns[ i ] ) + { + self.current_spawn = i; + piecespawn.piece_allocated[ self.current_spawn ] = 1; + piecespawn.str_force_spawn_kvp = undefined; + piecespawn.str_force_spawn_name = undefined; + return; + } + i++; + } + } + } + if ( isDefined( piecespawn.use_cyclic_spawns ) ) + { + piece_allocate_cyclic( piecespawn ); + return; + } + if ( self.spawns.size >= 1 && self.spawns.size > 1 ) + { + any_good = 0; + any_okay = 0; + totalweight = 0; + spawnweights = []; + i = 0; + while ( i < self.spawns.size ) + { + if ( isDefined( piecespawn.piece_allocated[ i ] ) && piecespawn.piece_allocated[ i ] ) + { + spawnweights[ i ] = 0; + } + else + { + if ( isDefined( self.spawns[ i ].script_forcespawn ) && self.spawns[ i ].script_forcespawn ) + { + switch( self.spawns[ i ].script_forcespawn ) + { + case 4: + spawnweights[ i ] = 0; + break; + case 1: + self.spawns[ i ].script_forcespawn = 0; + case 2: + self.current_spawn = i; + piecespawn.piece_allocated[ self.current_spawn ] = 1; + return; + case 3: + self.spawns[ i ].script_forcespawn = 4; + self.current_spawn = i; + piecespawn.piece_allocated[ self.current_spawn ] = 1; + return; + default: + any_okay = 1; + spawnweights[ i ] = 0,01; + break; + } + break; + } + else + { + if ( is_point_in_build_trigger( self.spawns[ i ].origin ) ) + { + any_okay = 1; + spawnweights[ i ] = 0,01; + break; + } + else + { + any_good = 1; + spawnweights[ i ] = 1; + } + } + } + totalweight += spawnweights[ i ]; + i++; + } +/# + if ( !any_good ) + { + assert( any_okay, "There is nowhere to spawn this piece" ); + } +#/ + if ( any_good ) + { + totalweight = float( int( totalweight ) ); + } + r = randomfloat( totalweight ); + i = 0; + while ( i < self.spawns.size ) + { + if ( !any_good || spawnweights[ i ] >= 1 ) + { + r -= spawnweights[ i ]; + if ( r < 0 ) + { + self.current_spawn = i; + piecespawn.piece_allocated[ self.current_spawn ] = 1; + return; + } + } + i++; + } + self.current_spawn = randomint( self.spawns.size ); + piecespawn.piece_allocated[ self.current_spawn ] = 1; + } + } + } + } +} + +piece_allocate_cyclic( piecespawn ) +{ + if ( self.spawns.size > 1 ) + { + if ( isDefined( piecespawn.randomize_cyclic_index ) ) + { + piecespawn.randomize_cyclic_index = undefined; + piecespawn.cyclic_index = randomint( self.spawns.size ); + } + if ( !isDefined( piecespawn.cyclic_index ) ) + { + piecespawn.cyclic_index = 0; + } + piecespawn.cyclic_index++; + if ( piecespawn.cyclic_index >= self.spawns.size ) + { + piecespawn.cyclic_index = 0; + } + } + else + { + piecespawn.cyclic_index = 0; + } + self.current_spawn = piecespawn.cyclic_index; + piecespawn.piece_allocated[ self.current_spawn ] = 1; +} + +piece_deallocate_spawn() +{ + if ( isDefined( self.current_spawn ) ) + { + self.piecespawn.piece_allocated[ self.current_spawn ] = 0; + self.current_spawn = undefined; + } + self.start_origin = undefined; +} + +piece_pick_random_spawn() +{ + self.current_spawn = 0; + while ( self.spawns.size >= 1 && self.spawns.size > 1 ) + { + self.current_spawn = randomint( self.spawns.size ); + while ( isDefined( self.spawns[ self.current_spawn ].claim_location ) && !claim_location( self.spawns[ self.current_spawn ].claim_location ) ) + { + arrayremoveindex( self.spawns, self.current_spawn ); + if ( self.spawns.size < 1 ) + { + self.current_spawn = 0; +/# + println( "ERROR: All buildable spawn locations claimed" ); +#/ + return; + } + self.current_spawn = randomint( self.spawns.size ); + } + } +} + +piece_set_spawn( num ) +{ + self.current_spawn = 0; + if ( self.spawns.size >= 1 && self.spawns.size > 1 ) + { + self.current_spawn = int( min( num, self.spawns.size - 1 ) ); + } +} + +piece_spawn_in( piecespawn ) +{ + if ( self.spawns.size < 1 ) + { + return; + } + if ( isDefined( self.managed_spawn ) && self.managed_spawn ) + { + if ( !isDefined( self.current_spawn ) ) + { + self piece_allocate_spawn( self.piecespawn ); + } + } + if ( !isDefined( self.current_spawn ) ) + { + self.current_spawn = 0; + } + spawndef = self.spawns[ self.current_spawn ]; + self.script_noteworthy = spawndef.script_noteworthy; + self.script_parameters = spawndef.script_parameters; + self.unitrigger = generate_piece_unitrigger( "trigger_radius_use", spawndef.origin + vectorScale( ( 0, 0, 1 ), 12 ), spawndef.angles, 0, piecespawn.radius, piecespawn.height, 0 ); + self.unitrigger.piece = self; + self.buildable_slot = piecespawn.buildable_slot; + self.radius = piecespawn.radius; + self.height = piecespawn.height; + self.buildablename = piecespawn.buildablename; + self.modelname = piecespawn.modelname; + self.hud_icon = piecespawn.hud_icon; + self.part_name = piecespawn.part_name; + self.drop_offset = piecespawn.drop_offset; + self.start_origin = spawndef.origin; + self.start_angles = spawndef.angles; + self.client_field_state = piecespawn.client_field_state; + self.hint_grab = piecespawn.hint_grab; + self.hint_swap = piecespawn.hint_swap; + self.model = spawn( "script_model", self.start_origin ); + if ( isDefined( self.start_angles ) ) + { + self.model.angles = self.start_angles; + } + self.model setmodel( piecespawn.modelname ); + self.model ghostindemo(); + self.model.hud_icon = piecespawn.hud_icon; + self.piecespawn = piecespawn; + self.unitrigger.origin_parent = self.model; + self.building = undefined; + self.onunspawn = piecespawn.onunspawn; + self.ondestroy = piecespawn.ondestroy; + if ( isDefined( piecespawn.onspawn ) ) + { + self.onspawn = piecespawn.onspawn; + self [[ piecespawn.onspawn ]](); + } +} + +piece_spawn_at_with_notify_delay( origin, angles, str_notify, unbuild_respawn_fn ) +{ + level waittill( str_notify ); + piece_spawn_at( origin, angles ); + if ( isDefined( unbuild_respawn_fn ) ) + { + self [[ unbuild_respawn_fn ]](); + } +} + +piece_spawn_at( origin, angles ) +{ + if ( self.spawns.size < 1 ) + { + return; + } + if ( isDefined( self.managed_spawn ) && self.managed_spawn ) + { + if ( !isDefined( self.current_spawn ) && !isDefined( origin ) ) + { + self piece_allocate_spawn( self.piecespawn ); + spawndef = self.spawns[ self.current_spawn ]; + self.start_origin = spawndef.origin; + self.start_angles = spawndef.angles; + } + } + else + { + if ( !isDefined( self.current_spawn ) ) + { + self.current_spawn = 0; + } + } + unitrigger_offset = vectorScale( ( 0, 0, 1 ), 12 ); + if ( !isDefined( origin ) ) + { + origin = self.start_origin; + } + else + { + origin += ( 0, 0, self.drop_offset ); + unitrigger_offset -= ( 0, 0, self.drop_offset ); + } + if ( !isDefined( angles ) ) + { + angles = self.start_angles; + } +/# + if ( !isDefined( level.drop_offset ) ) + { + level.drop_offset = 0; + } + origin += ( 0, 0, level.drop_offset ); + unitrigger_offset -= ( 0, 0, level.drop_offset ); +#/ + self.model = spawn( "script_model", origin ); + if ( isDefined( angles ) ) + { + self.model.angles = angles; + } + self.model setmodel( self.modelname ); + if ( isDefined( level.equipment_safe_to_drop ) ) + { + if ( !( [[ level.equipment_safe_to_drop ]]( self.model ) ) ) + { + origin = self.start_origin; + angles = self.start_angles; + self.model.origin = origin; + self.model.angles = angles; + } + } + if ( isDefined( self.model.canmove ) ) + { + self.unitrigger = generate_piece_unitrigger( "trigger_radius_use", origin + unitrigger_offset, angles, 0, self.radius, self.height, self.model.canmove ); + } + self.unitrigger.piece = self; + self.model.hud_icon = self.hud_icon; + self.unitrigger.origin_parent = self.model; + self.building = undefined; + if ( isDefined( self.onspawn ) ) + { + self [[ self.onspawn ]](); + } +} + +piece_unspawn() +{ + if ( isDefined( self.onunspawn ) ) + { + self [[ self.onunspawn ]](); + } + if ( isDefined( self.managed_spawn ) && self.managed_spawn ) + { + self piece_deallocate_spawn(); + } + if ( isDefined( self.model ) ) + { + self.model delete(); + } + self.model = undefined; + if ( isDefined( self.unitrigger ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger ); + } + self.unitrigger = undefined; +} + +piece_hide() +{ + if ( isDefined( self.model ) ) + { + self.model ghost(); + } +} + +piece_show() +{ + if ( isDefined( self.model ) ) + { + self.model show(); + } +} + +piece_destroy() +{ + if ( isDefined( self.ondestroy ) ) + { + self [[ self.ondestroy ]](); + } +} + +generate_piece( buildable_piece_spawns ) +{ + piece = spawnstruct(); + piece.spawns = buildable_piece_spawns.spawns; + if ( isDefined( buildable_piece_spawns.managing_pieces ) && buildable_piece_spawns.managing_pieces ) + { + piece piece_allocate_spawn( buildable_piece_spawns ); + } + else + { + if ( isDefined( buildable_piece_spawns.use_spawn_num ) ) + { + piece piece_set_spawn( buildable_piece_spawns.use_spawn_num ); + } + else + { + piece piece_pick_random_spawn(); + } + } + piece piece_spawn_in( buildable_piece_spawns ); + if ( piece.spawns.size >= 1 ) + { + piece.hud_icon = buildable_piece_spawns.hud_icon; + } + if ( isDefined( buildable_piece_spawns.onpickup ) ) + { + piece.onpickup = buildable_piece_spawns.onpickup; + } + else + { + piece.onpickup = ::onpickuputs; + } + if ( isDefined( buildable_piece_spawns.ondrop ) ) + { + piece.ondrop = buildable_piece_spawns.ondrop; + } + else + { + piece.ondrop = ::ondroputs; + } + return piece; +} + +buildable_piece_unitriggers( buildable_name, origin ) +{ +/# + assert( isDefined( buildable_name ) ); +#/ +/# + assert( isDefined( level.zombie_buildables[ buildable_name ] ), "Called buildable_think() without including the buildable - " + buildable_name ); +#/ + buildable = level.zombie_buildables[ buildable_name ]; + if ( !isDefined( buildable.buildablepieces ) ) + { + buildable.buildablepieces = []; + } + flag_wait( "start_zombie_round_logic" ); + buildablezone = spawnstruct(); + buildablezone.buildable_name = buildable_name; + buildablezone.buildable_slot = buildable.buildable_slot; + if ( !isDefined( buildablezone.pieces ) ) + { + buildablezone.pieces = []; + } + buildablepickups = []; + _a1362 = buildable.buildablepieces; + _k1362 = getFirstArrayKey( _a1362 ); + while ( isDefined( _k1362 ) ) + { + buildablepiece = _a1362[ _k1362 ]; + if ( !isDefined( buildablepiece.generated_instances ) ) + { + buildablepiece.generated_instances = 0; + } + if ( isDefined( buildablepiece.generated_piece ) && isDefined( buildablepiece.can_reuse ) && buildablepiece.can_reuse ) + { + piece = buildablepiece.generated_piece; + } + else + { + if ( buildablepiece.generated_instances >= buildablepiece.max_instances ) + { + piece = buildablepiece.generated_piece; + break; + } + else + { + piece = generate_piece( buildablepiece ); + buildablepiece.generated_piece = piece; + buildablepiece.generated_instances++; + while ( isDefined( buildablepiece.min_instances ) ) + { + while ( buildablepiece.generated_instances < buildablepiece.min_instances ) + { + piece = generate_piece( buildablepiece ); + buildablepiece.generated_piece = piece; + buildablepiece.generated_instances++; + } + } + } + } + buildablezone.pieces[ buildablezone.pieces.size ] = piece; + _k1362 = getNextArrayKey( _a1362, _k1362 ); + } + buildablezone.stub = self; + return buildablezone; +} + +hide_buildable_table_model( trigger_targetname ) +{ + trig = getent( trigger_targetname, "targetname" ); + if ( !isDefined( trig ) ) + { + return; + } + if ( isDefined( trig.target ) ) + { + model = getent( trig.target, "targetname" ); + if ( isDefined( model ) ) + { + model hide(); + model notsolid(); + } + } +} + +setup_unitrigger_buildable( trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ) +{ + trig = getent( trigger_targetname, "targetname" ); + if ( !isDefined( trig ) ) + { + return; + } + return setup_unitrigger_buildable_internal( trig, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ); +} + +setup_unitrigger_buildable_array( trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ) +{ + triggers = getentarray( trigger_targetname, "targetname" ); + stubs = []; + _a1431 = triggers; + _k1431 = getFirstArrayKey( _a1431 ); + while ( isDefined( _k1431 ) ) + { + trig = _a1431[ _k1431 ]; + stubs[ stubs.size ] = setup_unitrigger_buildable_internal( trig, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ); + _k1431 = getNextArrayKey( _a1431, _k1431 ); + } + return stubs; +} + +setup_unitrigger_buildable_internal( trig, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ) +{ + if ( !isDefined( trig ) ) + { + return; + } + unitrigger_stub = spawnstruct(); + unitrigger_stub.buildablestruct = level.zombie_include_buildables[ equipname ]; + angles = trig.script_angles; + if ( !isDefined( angles ) ) + { + angles = ( 0, 0, 1 ); + } + unitrigger_stub.origin = trig.origin + ( anglesToRight( angles ) * -6 ); + unitrigger_stub.angles = trig.angles; + if ( isDefined( trig.script_angles ) ) + { + unitrigger_stub.angles = trig.script_angles; + } + unitrigger_stub.equipname = equipname; + unitrigger_stub.weaponname = weaponname; + unitrigger_stub.trigger_hintstring = trigger_hintstring; + unitrigger_stub.delete_trigger = delete_trigger; + unitrigger_stub.built = 0; + unitrigger_stub.persistent = persistent; + unitrigger_stub.usetime = int( 3000 ); + unitrigger_stub.onbeginuse = ::onbeginuseuts; + unitrigger_stub.onenduse = ::onenduseuts; + unitrigger_stub.onuse = ::onuseplantobjectuts; + unitrigger_stub.oncantuse = ::oncantuseuts; + if ( isDefined( trig.script_length ) ) + { + unitrigger_stub.script_length = trig.script_length; + } + else + { + unitrigger_stub.script_length = 32; + } + if ( isDefined( trig.script_width ) ) + { + unitrigger_stub.script_width = trig.script_width; + } + else + { + unitrigger_stub.script_width = 100; + } + if ( isDefined( trig.script_height ) ) + { + unitrigger_stub.script_height = trig.script_height; + } + else + { + unitrigger_stub.script_height = 64; + } + unitrigger_stub.target = trig.target; + unitrigger_stub.targetname = trig.targetname; + unitrigger_stub.script_noteworthy = trig.script_noteworthy; + unitrigger_stub.script_parameters = trig.script_parameters; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + if ( isDefined( level.zombie_buildables[ equipname ].hint ) ) + { + unitrigger_stub.hint_string = level.zombie_buildables[ equipname ].hint; + } + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + unitrigger_stub.require_look_at = 1; + unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + unitrigger_stub.prompt_and_visibility_func = ::buildabletrigger_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::buildable_place_think ); + unitrigger_stub.piece_trigger = trig; + trig.trigger_stub = unitrigger_stub; + unitrigger_stub.zombie_weapon_upgrade = trig.zombie_weapon_upgrade; + if ( isDefined( unitrigger_stub.target ) ) + { + unitrigger_stub.model = getent( unitrigger_stub.target, "targetname" ); + if ( isDefined( unitrigger_stub.model ) ) + { + if ( isDefined( unitrigger_stub.zombie_weapon_upgrade ) ) + { + unitrigger_stub.model useweaponhidetags( unitrigger_stub.zombie_weapon_upgrade ); + } + unitrigger_stub.model hide(); + unitrigger_stub.model notsolid(); + } + } + unitrigger_stub.buildablezone = unitrigger_stub buildable_piece_unitriggers( equipname, unitrigger_stub.origin ); + if ( delete_trigger ) + { + trig delete(); + } + level.buildable_stubs[ level.buildable_stubs.size ] = unitrigger_stub; + return unitrigger_stub; +} + +buildable_has_piece( piece ) +{ + i = 0; + while ( i < self.pieces.size ) + { + if ( self.pieces[ i ].modelname == piece.modelname && self.pieces[ i ].buildablename == piece.buildablename ) + { + return 1; + } + i++; + } + return 0; +} + +buildable_set_piece_built( piece ) +{ + i = 0; + while ( i < self.pieces.size ) + { + if ( self.pieces[ i ].modelname == piece.modelname && self.pieces[ i ].buildablename == piece.buildablename ) + { + self.pieces[ i ].built = 1; + } + i++; + } +} + +buildable_set_piece_building( piece ) +{ + i = 0; + while ( i < self.pieces.size ) + { + if ( self.pieces[ i ].modelname == piece.modelname && self.pieces[ i ].buildablename == piece.buildablename ) + { + self.pieces[ i ] = piece; + self.pieces[ i ].building = 1; + } + i++; + } +} + +buildable_clear_piece_building( piece ) +{ + if ( isDefined( piece ) ) + { + piece.building = 0; + } +} + +buildable_is_piece_built( piece ) +{ + i = 0; + while ( i < self.pieces.size ) + { + if ( self.pieces[ i ].modelname == piece.modelname && self.pieces[ i ].buildablename == piece.buildablename ) + { + if ( isDefined( self.pieces[ i ].built ) ) + { + return self.pieces[ i ].built; + } + } + i++; + } + return 0; +} + +buildable_is_piece_building( piece ) +{ + i = 0; + while ( i < self.pieces.size ) + { + if ( self.pieces[ i ].modelname == piece.modelname && self.pieces[ i ].buildablename == piece.buildablename ) + { + if ( isDefined( self.pieces[ i ].building ) && self.pieces[ i ].building ) + { + return self.pieces[ i ] == piece; + } + } + i++; + } + return 0; +} + +buildable_is_piece_built_or_building( piece ) +{ + i = 0; + while ( i < self.pieces.size ) + { + if ( self.pieces[ i ].modelname == piece.modelname && self.pieces[ i ].buildablename == piece.buildablename ) + { + if ( isDefined( self.pieces[ i ].built ) && !self.pieces[ i ].built ) + { + if ( isDefined( self.pieces[ i ].building ) ) + { + return self.pieces[ i ].building; + } + } + } + i++; + } + return 0; +} + +buildable_all_built() +{ + i = 0; + while ( i < self.pieces.size ) + { + if ( isDefined( self.pieces[ i ].built ) && !self.pieces[ i ].built ) + { + return 0; + } + i++; + } + return 1; +} + +player_can_build( buildable, continuing ) +{ + if ( !isDefined( buildable ) ) + { + return 0; + } + if ( !isDefined( self player_get_buildable_piece( buildable.buildable_slot ) ) ) + { + return 0; + } + if ( !buildable buildable_has_piece( self player_get_buildable_piece( buildable.buildable_slot ) ) ) + { + return 0; + } + if ( isDefined( continuing ) && continuing ) + { + if ( buildable buildable_is_piece_built( self player_get_buildable_piece( buildable.buildable_slot ) ) ) + { + return 0; + } + } + else + { + if ( buildable buildable_is_piece_built_or_building( self player_get_buildable_piece( buildable.buildable_slot ) ) ) + { + return 0; + } + } + if ( isDefined( buildable.stub ) && isDefined( buildable.stub.custom_buildablestub_update_prompt ) && isDefined( buildable.stub.playertrigger[ 0 ] ) && isDefined( buildable.stub.playertrigger[ 0 ].stub ) && !( buildable.stub.playertrigger[ 0 ].stub [[ buildable.stub.custom_buildablestub_update_prompt ]]( self, 1, buildable.stub.playertrigger[ 0 ] ) ) ) + { + return 0; + } + return 1; +} + +player_build( buildable, pieces ) +{ + if ( isDefined( pieces ) ) + { + i = 0; + while ( i < pieces.size ) + { + buildable buildable_set_piece_built( pieces[ i ] ); + player_destroy_piece( pieces[ i ] ); + i++; + } + } + else buildable buildable_set_piece_built( self player_get_buildable_piece( buildable.buildable_slot ) ); + player_destroy_piece( self player_get_buildable_piece( buildable.buildable_slot ) ); + while ( isDefined( buildable.stub.model ) ) + { + i = 0; + while ( i < buildable.pieces.size ) + { + if ( isDefined( buildable.pieces[ i ].part_name ) ) + { + buildable.stub.model notsolid(); + if ( isDefined( buildable.pieces[ i ].built ) && !buildable.pieces[ i ].built ) + { + buildable.stub.model hidepart( buildable.pieces[ i ].part_name ); + i++; + continue; + } + else + { + buildable.stub.model show(); + buildable.stub.model showpart( buildable.pieces[ i ].part_name ); + } + } + i++; + } + } + if ( isplayer( self ) ) + { + self track_buildable_pieces_built( buildable ); + } + if ( buildable buildable_all_built() ) + { + self player_finish_buildable( buildable ); + buildable.stub buildablestub_finish_build( self ); + if ( isplayer( self ) ) + { + self track_buildables_built( buildable ); + } + if ( isDefined( level.buildable_built_custom_func ) ) + { + self thread [[ level.buildable_built_custom_func ]]( buildable ); + } + alias = sndbuildablecompletealias( buildable.buildable_name ); + self playsound( alias ); + } + else + { + self playsound( "zmb_buildable_piece_add" ); +/# + assert( isDefined( level.zombie_buildables[ buildable.buildable_name ].building ), "Missing builing hint" ); +#/ + if ( isDefined( level.zombie_buildables[ buildable.buildable_name ].building ) ) + { + return level.zombie_buildables[ buildable.buildable_name ].building; + } + } + return ""; +} + +sndbuildablecompletealias( name ) +{ + alias = undefined; + switch( name ) + { + case "chalk": + alias = "zmb_chalk_complete"; + break; + default: + alias = "zmb_buildable_complete"; + break; + } + return alias; +} + +player_finish_buildable( buildable ) +{ + buildable.built = 1; + buildable.stub.built = 1; + buildable notify( "built" ); + level.buildables_built[ buildable.buildable_name ] = 1; + level notify( buildable.buildable_name + "_built" ); +} + +buildablestub_finish_build( player ) +{ + player player_finish_buildable( self.buildablezone ); +} + +buildablestub_remove() +{ + arrayremovevalue( level.buildable_stubs, self ); +} + +buildabletrigger_update_prompt( player ) +{ + can_use = self.stub buildablestub_update_prompt( player ); + self sethintstring( self.stub.hint_string ); + if ( isDefined( self.stub.cursor_hint ) ) + { + if ( self.stub.cursor_hint == "HINT_WEAPON" && isDefined( self.stub.cursor_hint_weapon ) ) + { + self setcursorhint( self.stub.cursor_hint, self.stub.cursor_hint_weapon ); + } + else + { + self setcursorhint( self.stub.cursor_hint ); + } + } + return can_use; +} + +buildablestub_update_prompt( player ) +{ + if ( !self anystub_update_prompt( player ) ) + { + return 0; + } + can_use = 1; + if ( isDefined( self.buildablestub_reject_func ) ) + { + rval = self [[ self.buildablestub_reject_func ]]( player ); + if ( rval ) + { + return 0; + } + } + if ( isDefined( self.custom_buildablestub_update_prompt ) && !( self [[ self.custom_buildablestub_update_prompt ]]( player ) ) ) + { + return 0; + } + self.cursor_hint = "HINT_NOICON"; + self.cursor_hint_weapon = undefined; + if ( isDefined( self.built ) && !self.built ) + { + slot = self.buildablestruct.buildable_slot; + if ( !isDefined( player player_get_buildable_piece( slot ) ) ) + { + if ( isDefined( level.zombie_buildables[ self.equipname ].hint_more ) ) + { + self.hint_string = level.zombie_buildables[ self.equipname ].hint_more; + } + else + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_MORE"; + } + return 0; + } + else + { + if ( !self.buildablezone buildable_has_piece( player player_get_buildable_piece( slot ) ) ) + { + if ( isDefined( level.zombie_buildables[ self.equipname ].hint_wrong ) ) + { + self.hint_string = level.zombie_buildables[ self.equipname ].hint_wrong; + } + else + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_WRONG"; + } + return 0; + } + else + { +/# + assert( isDefined( level.zombie_buildables[ self.equipname ].hint ), "Missing buildable hint" ); +#/ + if ( isDefined( level.zombie_buildables[ self.equipname ].hint ) ) + { + self.hint_string = level.zombie_buildables[ self.equipname ].hint; + } + else + { + self.hint_string = "Missing buildable hint"; + } + } + } + } + else + { + if ( self.persistent == 1 ) + { + if ( maps/mp/zombies/_zm_equipment::is_limited_equipment( self.weaponname ) && maps/mp/zombies/_zm_equipment::limited_equipment_in_use( self.weaponname ) ) + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_ONLY_ONE"; + return 0; + } + if ( player has_player_equipment( self.weaponname ) ) + { + self.hint_string = &"ZOMBIE_BUILD_PIECE_HAVE_ONE"; + return 0; + } + if ( getDvarInt( #"1F0A2129" ) ) + { + self.cursor_hint = "HINT_WEAPON"; + self.cursor_hint_weapon = self.weaponname; + } + self.hint_string = self.trigger_hintstring; + } + else if ( self.persistent == 2 ) + { + if ( !maps/mp/zombies/_zm_weapons::limited_weapon_below_quota( self.weaponname, undefined ) ) + { + self.hint_string = &"ZOMBIE_GO_TO_THE_BOX_LIMITED"; + return 0; + } + else + { + if ( isDefined( self.bought ) && self.bought ) + { + self.hint_string = &"ZOMBIE_GO_TO_THE_BOX"; + return 0; + } + } + self.hint_string = self.trigger_hintstring; + } + else + { + self.hint_string = ""; + return 0; + } + } + return 1; +} + +player_continue_building( buildablezone, build_stub ) +{ + if ( !isDefined( build_stub ) ) + { + build_stub = buildablezone.stub; + } + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || self in_revive_trigger() ) + { + return 0; + } + if ( self isthrowinggrenade() ) + { + return 0; + } + if ( !self player_can_build( buildablezone, 1 ) ) + { + return 0; + } + if ( isDefined( self.screecher ) ) + { + return 0; + } + if ( !self usebuttonpressed() ) + { + return 0; + } + slot = build_stub.buildablestruct.buildable_slot; + if ( !buildablezone buildable_is_piece_building( self player_get_buildable_piece( slot ) ) ) + { + return 0; + } + trigger = build_stub maps/mp/zombies/_zm_unitrigger::unitrigger_trigger( self ); + if ( build_stub.script_unitrigger_type == "unitrigger_radius_use" ) + { + torigin = build_stub unitrigger_origin(); + porigin = self geteye(); + radius_sq = 2,25 * build_stub.test_radius_sq; + if ( distance2dsquared( torigin, porigin ) > radius_sq ) + { + return 0; + } + } + else + { + if ( !isDefined( trigger ) || !trigger istouching( self ) ) + { + return 0; + } + } + if ( isDefined( build_stub.require_look_at ) && build_stub.require_look_at && !self is_player_looking_at( trigger.origin, 0,4 ) ) + { + return 0; + } + return 1; +} + +player_progress_bar_update( start_time, build_time ) +{ + self endon( "entering_last_stand" ); + self endon( "death" ); + self endon( "disconnect" ); + self endon( "buildable_progress_end" ); + while ( isDefined( self ) && ( getTime() - start_time ) < build_time ) + { + progress = ( getTime() - start_time ) / build_time; + if ( progress < 0 ) + { + progress = 0; + } + if ( progress > 1 ) + { + progress = 1; + } + self.usebar updatebar( progress ); + wait 0,05; + } +} + +player_progress_bar( start_time, build_time, building_prompt ) +{ + self.usebar = self createprimaryprogressbar(); + self.usebartext = self createprimaryprogressbartext(); + if ( isDefined( building_prompt ) ) + { + self.usebartext settext( building_prompt ); + } + else + { + self.usebartext settext( &"ZOMBIE_BUILDING" ); + } + if ( isDefined( self ) && isDefined( start_time ) && isDefined( build_time ) ) + { + self player_progress_bar_update( start_time, build_time ); + } + self.usebartext destroyelem(); + self.usebar destroyelem(); +} + +buildable_use_hold_think_internal( player, bind_stub ) +{ + if ( !isDefined( bind_stub ) ) + { + bind_stub = self.stub; + } + wait 0,01; + if ( !isDefined( self ) ) + { + self notify( "build_failed" ); + if ( isDefined( player.buildableaudio ) ) + { + player.buildableaudio delete(); + player.buildableaudio = undefined; + } + return; + } + if ( !isDefined( self.usetime ) ) + { + self.usetime = int( 3000 ); + } + self.build_time = self.usetime; + self.build_start_time = getTime(); + build_time = self.build_time; + build_start_time = self.build_start_time; + player disable_player_move_states( 1 ); + player increment_is_drinking(); + orgweapon = player getcurrentweapon(); + build_weapon = "zombie_builder_zm"; + if ( isDefined( bind_stub.build_weapon ) ) + { + build_weapon = bind_stub.build_weapon; + } + player giveweapon( build_weapon ); + player switchtoweapon( build_weapon ); + slot = bind_stub.buildablestruct.buildable_slot; + bind_stub.buildablezone buildable_set_piece_building( player player_get_buildable_piece( slot ) ); + player thread player_progress_bar( build_start_time, build_time, bind_stub.building_prompt ); + if ( isDefined( level.buildable_build_custom_func ) ) + { + player thread [[ level.buildable_build_custom_func ]]( self.stub ); + } + while ( isDefined( self ) && player player_continue_building( bind_stub.buildablezone, self.stub ) && ( getTime() - self.build_start_time ) < self.build_time ) + { + wait 0,05; + } + player notify( "buildable_progress_end" ); + player maps/mp/zombies/_zm_weapons::switch_back_primary_weapon( orgweapon ); + player takeweapon( "zombie_builder_zm" ); + if ( isDefined( player.is_drinking ) && player.is_drinking ) + { + player decrement_is_drinking(); + } + player enable_player_move_states(); + if ( isDefined( self ) && player player_continue_building( bind_stub.buildablezone, self.stub ) && ( getTime() - self.build_start_time ) >= self.build_time ) + { + buildable_clear_piece_building( player player_get_buildable_piece( slot ) ); + self notify( "build_succeed" ); + } + else + { + if ( isDefined( player.buildableaudio ) ) + { + player.buildableaudio delete(); + player.buildableaudio = undefined; + } + buildable_clear_piece_building( player player_get_buildable_piece( slot ) ); + self notify( "build_failed" ); + } +} + +buildable_play_build_fx( player ) +{ + self endon( "kill_trigger" ); + self endon( "build_succeed" ); + self endon( "build_failed" ); + while ( 1 ) + { + playfx( level._effect[ "building_dust" ], player getplayercamerapos(), player.angles ); + wait 0,5; + } +} + +buildable_use_hold_think( player, bind_stub ) +{ + if ( !isDefined( bind_stub ) ) + { + bind_stub = self.stub; + } + self thread buildable_play_build_fx( player ); + self thread buildable_use_hold_think_internal( player, bind_stub ); + retval = self waittill_any_return( "build_succeed", "build_failed" ); + if ( retval == "build_succeed" ) + { + return 1; + } + return 0; +} + +buildable_place_think() +{ + self endon( "kill_trigger" ); + player_built = undefined; + while ( isDefined( self.stub.built ) && !self.stub.built ) + { + self waittill( "trigger", player ); + while ( player != self.parent_player ) + { + continue; + } + while ( isDefined( player.screecher_weapon ) ) + { + continue; + } + while ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0,5 ); + } + status = player player_can_build( self.stub.buildablezone ); + if ( !status ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + if ( isDefined( self.stub.oncantuse ) ) + { + self.stub [[ self.stub.oncantuse ]]( player ); + } + continue; + } + else + { + if ( isDefined( self.stub.onbeginuse ) ) + { + self.stub [[ self.stub.onbeginuse ]]( player ); + } + result = self buildable_use_hold_think( player ); + team = player.pers[ "team" ]; + if ( isDefined( self.stub.onenduse ) ) + { + self.stub [[ self.stub.onenduse ]]( team, player, result ); + } + while ( !result ) + { + continue; + } + if ( isDefined( self.stub.onuse ) ) + { + self.stub [[ self.stub.onuse ]]( player ); + } + slot = self.stub.buildablestruct.buildable_slot; + if ( isDefined( player player_get_buildable_piece( slot ) ) ) + { + prompt = player player_build( self.stub.buildablezone ); + player_built = player; + self.stub.hint_string = prompt; + } + self sethintstring( self.stub.hint_string ); + } + } + if ( isDefined( player_built ) ) + { + } + switch( self.stub.persistent ) + { + case 1: + self bptrigger_think_persistent( player_built ); + break; + case 0: + self bptrigger_think_one_time( player_built ); + break; + case 3: + self bptrigger_think_unbuild( player_built ); + break; + case 2: + self bptrigger_think_one_use_and_fly( player_built ); + break; + case 4: + self [[ self.stub.custom_completion_callback ]]( player_built ); + break; + } +} + +bptrigger_think_one_time( player_built ) +{ + self.stub buildablestub_remove(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.stub ); +} + +bptrigger_think_unbuild( player_built ) +{ + stub_unbuild_buildable( self.stub, 1 ); +} + +bptrigger_think_one_use_and_fly( player_built ) +{ + if ( isDefined( player_built ) ) + { + self buildabletrigger_update_prompt( player_built ); + } + if ( !maps/mp/zombies/_zm_weapons::limited_weapon_below_quota( self.stub.weaponname, undefined ) ) + { + self.stub.hint_string = &"ZOMBIE_GO_TO_THE_BOX_LIMITED"; + self sethintstring( self.stub.hint_string ); + return; + } + if ( isDefined( self.stub.bought ) && self.stub.bought ) + { + self.stub.hint_string = &"ZOMBIE_GO_TO_THE_BOX"; + self sethintstring( self.stub.hint_string ); + return; + } + if ( isDefined( self.stub.model ) ) + { + self.stub.model notsolid(); + self.stub.model show(); + } + while ( self.stub.persistent == 2 ) + { + self waittill( "trigger", player ); + while ( isDefined( player.screecher_weapon ) ) + { + continue; + } + if ( !maps/mp/zombies/_zm_weapons::limited_weapon_below_quota( self.stub.weaponname, undefined ) ) + { + self.stub.hint_string = &"ZOMBIE_GO_TO_THE_BOX_LIMITED"; + self sethintstring( self.stub.hint_string ); + return; + } + if ( isDefined( self.stub.built ) && !self.stub.built ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + return; + } + while ( player != self.parent_player ) + { + continue; + } + while ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0,5 ); + } + self.stub.bought = 1; + if ( isDefined( self.stub.model ) ) + { + self.stub.model thread model_fly_away(); + } + player maps/mp/zombies/_zm_weapons::weapon_give( self.stub.weaponname ); + if ( isDefined( level.zombie_include_buildables[ self.stub.equipname ].onbuyweapon ) ) + { + self [[ level.zombie_include_buildables[ self.stub.equipname ].onbuyweapon ]]( player ); + } + if ( !maps/mp/zombies/_zm_weapons::limited_weapon_below_quota( self.stub.weaponname, undefined ) ) + { + self.stub.hint_string = &"ZOMBIE_GO_TO_THE_BOX_LIMITED"; + } + else + { + self.stub.hint_string = &"ZOMBIE_GO_TO_THE_BOX"; + } + self sethintstring( self.stub.hint_string ); + player track_buildables_pickedup( self.stub.weaponname ); + } +} + +bptrigger_think_persistent( player_built ) +{ + while ( !isDefined( player_built ) || self [[ self.stub.prompt_and_visibility_func ]]( player_built ) ) + { + if ( isDefined( self.stub.model ) ) + { + self.stub.model notsolid(); + self.stub.model show(); + } + while ( self.stub.persistent == 1 ) + { + self waittill( "trigger", player ); + while ( isDefined( player.screecher_weapon ) ) + { + continue; + } + if ( isDefined( self.stub.built ) && !self.stub.built ) + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + self setcursorhint( "HINT_NOICON" ); + return; + } + while ( player != self.parent_player ) + { + continue; + } + while ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0,5 ); + } + while ( player has_player_equipment( self.stub.weaponname ) ) + { + continue; + } + if ( isDefined( self.stub.buildablestruct.onbought ) ) + { + self [[ self.stub.buildablestruct.onbought ]]( player ); + continue; + } + else if ( !maps/mp/zombies/_zm_equipment::is_limited_equipment( self.stub.weaponname ) || !maps/mp/zombies/_zm_equipment::limited_equipment_in_use( self.stub.weaponname ) ) + { + player maps/mp/zombies/_zm_equipment::equipment_buy( self.stub.weaponname ); + player giveweapon( self.stub.weaponname ); + player setweaponammoclip( self.stub.weaponname, 1 ); + if ( isDefined( level.zombie_include_buildables[ self.stub.equipname ].onbuyweapon ) ) + { + self [[ level.zombie_include_buildables[ self.stub.equipname ].onbuyweapon ]]( player ); + } + if ( self.stub.weaponname != "keys_zm" ) + { + player setactionslot( 1, "weapon", self.stub.weaponname ); + } + self.stub.cursor_hint = "HINT_NOICON"; + self.stub.cursor_hint_weapon = undefined; + self setcursorhint( self.stub.cursor_hint ); + if ( isDefined( level.zombie_buildables[ self.stub.equipname ].bought ) ) + { + self.stub.hint_string = level.zombie_buildables[ self.stub.equipname ].bought; + } + else + { + self.stub.hint_string = ""; + } + self sethintstring( self.stub.hint_string ); + player track_buildables_pickedup( self.stub.weaponname ); + continue; + } + else + { + self.stub.hint_string = ""; + self sethintstring( self.stub.hint_string ); + self.stub.cursor_hint = "HINT_NOICON"; + self.stub.cursor_hint_weapon = undefined; + self setcursorhint( self.stub.cursor_hint ); + } + } + } +} + +bptrigger_think_unbuild_no_return( player ) +{ + stub_unbuild_buildable( self.stub, 0 ); +} + +bpstub_set_custom_think_callback( callback ) +{ + self.persistent = 4; + self.custom_completion_callback = callback; +} + +model_fly_away() +{ + self moveto( self.origin + vectorScale( ( 0, 0, 1 ), 40 ), 3 ); + direction = self.origin; + direction = ( direction[ 1 ], direction[ 0 ], 0 ); + if ( direction[ 1 ] < 0 || direction[ 0 ] > 0 && direction[ 1 ] > 0 ) + { + direction = ( direction[ 0 ], direction[ 1 ] * -1, 0 ); + } + else + { + if ( direction[ 0 ] < 0 ) + { + direction = ( direction[ 0 ] * -1, direction[ 1 ], 0 ); + } + } + self vibrate( direction, 10, 0,5, 4 ); + self waittill( "movedone" ); + self hide(); + playfx( level._effect[ "poltergeist" ], self.origin ); +} + +find_buildable_stub( equipname ) +{ + _a2343 = level.buildable_stubs; + _k2343 = getFirstArrayKey( _a2343 ); + while ( isDefined( _k2343 ) ) + { + stub = _a2343[ _k2343 ]; + if ( stub.equipname == equipname ) + { + return stub; + } + _k2343 = getNextArrayKey( _a2343, _k2343 ); + } + return undefined; +} + +unbuild_buildable( equipname, return_pieces, origin, angles ) +{ + stub = find_buildable_stub( equipname ); + stub_unbuild_buildable( stub, return_pieces, origin, angles ); +} + +stub_unbuild_buildable( stub, return_pieces, origin, angles ) +{ + if ( isDefined( stub ) ) + { + buildable = stub.buildablezone; + buildable.built = 0; + buildable.stub.built = 0; + buildable notify( "unbuilt" ); + level.buildables_built[ buildable.buildable_name ] = 0; + level notify( buildable.buildable_name + "_unbuilt" ); + i = 0; + while ( i < buildable.pieces.size ) + { + buildable.pieces[ i ].built = 0; + if ( isDefined( buildable.pieces[ i ].part_name ) ) + { + buildable.stub.model notsolid(); + if ( isDefined( buildable.pieces[ i ].built ) && !buildable.pieces[ i ].built ) + { + buildable.stub.model hidepart( buildable.pieces[ i ].part_name ); + break; + } + else + { + buildable.stub.model show(); + buildable.stub.model showpart( buildable.pieces[ i ].part_name ); + } + } + if ( isDefined( return_pieces ) && return_pieces ) + { + if ( isDefined( buildable.stub.str_unbuild_notify ) ) + { + buildable.pieces[ i ] thread piece_spawn_at_with_notify_delay( origin, angles, buildable.stub.str_unbuild_notify, buildable.stub.unbuild_respawn_fn ); + i++; + continue; + } + else + { + buildable.pieces[ i ] piece_spawn_at( origin, angles ); + } + } + i++; + } + if ( isDefined( buildable.stub.model ) ) + { + buildable.stub.model hide(); + } + } +} + +player_explode_buildable( equipname, origin, speed, return_to_spawn, return_time ) +{ + self explosiondamage( 50, origin ); + stub = find_buildable_stub( equipname ); + if ( isDefined( stub ) ) + { + buildable = stub.buildablezone; + buildable.built = 0; + buildable.stub.built = 0; + buildable notify( "unbuilt" ); + level.buildables_built[ buildable.buildable_name ] = 0; + level notify( buildable.buildable_name + "_unbuilt" ); + i = 0; + while ( i < buildable.pieces.size ) + { + buildable.pieces[ i ].built = 0; + if ( isDefined( buildable.pieces[ i ].part_name ) ) + { + buildable.stub.model notsolid(); + if ( isDefined( buildable.pieces[ i ].built ) && !buildable.pieces[ i ].built ) + { + buildable.stub.model hidepart( buildable.pieces[ i ].part_name ); + break; + } + else + { + buildable.stub.model show(); + buildable.stub.model showpart( buildable.pieces[ i ].part_name ); + } + } + ang = randomfloat( 360 ); + h = 0,25 + randomfloat( 0,5 ); + dir = ( sin( ang ), cos( ang ), h ); + self thread player_throw_piece( buildable.pieces[ i ], origin, speed * dir, return_to_spawn, return_time ); + i++; + } + buildable.stub.model hide(); + } +} + +think_buildables() +{ + _a2447 = level.zombie_include_buildables; + _k2447 = getFirstArrayKey( _a2447 ); + while ( isDefined( _k2447 ) ) + { + buildable = _a2447[ _k2447 ]; + if ( isDefined( buildable.triggerthink ) ) + { + level [[ buildable.triggerthink ]](); + wait_network_frame(); + } + _k2447 = getNextArrayKey( _a2447, _k2447 ); + } + level notify( "buildables_setup" ); +} + +buildable_trigger_think( trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ) +{ + return setup_unitrigger_buildable( trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ); +} + +buildable_trigger_think_array( trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ) +{ + return setup_unitrigger_buildable_array( trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ); +} + +buildable_set_unbuild_notify_delay( str_equipname, str_unbuild_notify, unbuild_respawn_fn ) +{ + stub = find_buildable_stub( str_equipname ); + stub.str_unbuild_notify = str_unbuild_notify; + stub.unbuild_respawn_fn = unbuild_respawn_fn; +} + +setup_vehicle_unitrigger_buildable( parent, trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ) +{ + trig = getent( trigger_targetname, "targetname" ); + if ( !isDefined( trig ) ) + { + return; + } + unitrigger_stub = spawnstruct(); + unitrigger_stub.buildablestruct = level.zombie_include_buildables[ equipname ]; + unitrigger_stub.link_parent = parent; + unitrigger_stub.origin_parent = trig; + unitrigger_stub.trigger_targetname = trigger_targetname; + unitrigger_stub.originfunc = ::anystub_get_unitrigger_origin; + unitrigger_stub.onspawnfunc = ::anystub_on_spawn_trigger; + unitrigger_stub.origin = trig.origin; + unitrigger_stub.angles = trig.angles; + unitrigger_stub.equipname = equipname; + unitrigger_stub.weaponname = weaponname; + unitrigger_stub.trigger_hintstring = trigger_hintstring; + unitrigger_stub.delete_trigger = delete_trigger; + unitrigger_stub.built = 0; + unitrigger_stub.persistent = persistent; + unitrigger_stub.usetime = int( 3000 ); + unitrigger_stub.onbeginuse = ::onbeginuseuts; + unitrigger_stub.onenduse = ::onenduseuts; + unitrigger_stub.onuse = ::onuseplantobjectuts; + unitrigger_stub.oncantuse = ::oncantuseuts; + if ( isDefined( trig.script_length ) ) + { + unitrigger_stub.script_length = trig.script_length; + } + else + { + unitrigger_stub.script_length = 24; + } + if ( isDefined( trig.script_width ) ) + { + unitrigger_stub.script_width = trig.script_width; + } + else + { + unitrigger_stub.script_width = 64; + } + if ( isDefined( trig.script_height ) ) + { + unitrigger_stub.script_height = trig.script_height; + } + else + { + unitrigger_stub.script_height = 24; + } + if ( isDefined( trig.radius ) ) + { + unitrigger_stub.radius = trig.radius; + } + else + { + unitrigger_stub.radius = 64; + } + unitrigger_stub.target = trig.target; + unitrigger_stub.targetname = trig.targetname + "_trigger"; + unitrigger_stub.script_noteworthy = trig.script_noteworthy; + unitrigger_stub.script_parameters = trig.script_parameters; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + if ( isDefined( level.zombie_buildables[ equipname ].hint ) ) + { + unitrigger_stub.hint_string = level.zombie_buildables[ equipname ].hint; + } + unitrigger_stub.script_unitrigger_type = "unitrigger_radius_use"; + unitrigger_stub.require_look_at = 1; + unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + unitrigger_stub.prompt_and_visibility_func = ::buildabletrigger_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_unitrigger( unitrigger_stub, ::buildable_place_think ); + unitrigger_stub.piece_trigger = trig; + trig.trigger_stub = unitrigger_stub; + unitrigger_stub.buildablezone = unitrigger_stub buildable_piece_unitriggers( equipname, unitrigger_stub.origin ); + if ( delete_trigger ) + { + trig delete(); + } + level.buildable_stubs[ level.buildable_stubs.size ] = unitrigger_stub; + return unitrigger_stub; +} + +vehicle_buildable_trigger_think( vehicle, trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ) +{ + return setup_vehicle_unitrigger_buildable( vehicle, trigger_targetname, equipname, weaponname, trigger_hintstring, delete_trigger, persistent ); +} + +ai_buildable_trigger_think( parent, equipname, weaponname, trigger_hintstring, persistent ) +{ + unitrigger_stub = spawnstruct(); + unitrigger_stub.buildablestruct = level.zombie_include_buildables[ equipname ]; + unitrigger_stub.link_parent = parent; + unitrigger_stub.origin_parent = parent; + unitrigger_stub.originfunc = ::anystub_get_unitrigger_origin; + unitrigger_stub.onspawnfunc = ::anystub_on_spawn_trigger; + unitrigger_stub.origin = parent.origin; + unitrigger_stub.angles = parent.angles; + unitrigger_stub.equipname = equipname; + unitrigger_stub.weaponname = weaponname; + unitrigger_stub.trigger_hintstring = trigger_hintstring; + unitrigger_stub.delete_trigger = 1; + unitrigger_stub.built = 0; + unitrigger_stub.persistent = persistent; + unitrigger_stub.usetime = int( 3000 ); + unitrigger_stub.onbeginuse = ::onbeginuseuts; + unitrigger_stub.onenduse = ::onenduseuts; + unitrigger_stub.onuse = ::onuseplantobjectuts; + unitrigger_stub.oncantuse = ::oncantuseuts; + unitrigger_stub.script_length = 64; + unitrigger_stub.script_width = 64; + unitrigger_stub.script_height = 54; + unitrigger_stub.radius = 64; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + if ( isDefined( level.zombie_buildables[ equipname ].hint ) ) + { + unitrigger_stub.hint_string = level.zombie_buildables[ equipname ].hint; + } + unitrigger_stub.script_unitrigger_type = "unitrigger_radius_use"; + unitrigger_stub.require_look_at = 0; + unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + unitrigger_stub.prompt_and_visibility_func = ::buildabletrigger_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_unitrigger( unitrigger_stub, ::buildable_place_think ); + unitrigger_stub.buildablezone = unitrigger_stub buildable_piece_unitriggers( equipname, unitrigger_stub.origin ); + level.buildable_stubs[ level.buildable_stubs.size ] = unitrigger_stub; + return unitrigger_stub; +} + +onpickuputs( player ) +{ +/# + if ( isDefined( player ) && isDefined( player.name ) ) + { + println( "ZM >> Buildable piece recovered by - " + player.name ); +#/ + } +} + +ondroputs( player ) +{ +/# + if ( isDefined( player ) && isDefined( player.name ) ) + { + println( "ZM >> Buildable piece dropped by - " + player.name ); +#/ + } + player notify( "event_ended" ); +} + +onbeginuseuts( player ) +{ +/# + if ( isDefined( player ) && isDefined( player.name ) ) + { + println( "ZM >> Buildable piece begin use by - " + player.name ); +#/ + } + if ( isDefined( self.buildablestruct.onbeginuse ) ) + { + self [[ self.buildablestruct.onbeginuse ]]( player ); + } + if ( isDefined( player ) && !isDefined( player.buildableaudio ) ) + { + alias = sndbuildableusealias( self.targetname ); + player.buildableaudio = spawn( "script_origin", player.origin ); + player.buildableaudio playloopsound( alias ); + } +} + +sndbuildableusealias( name ) +{ + alias = undefined; + switch( name ) + { + case "cell_door_trigger": + alias = "zmb_jail_buildable"; + break; + case "generator_use_trigger": + alias = "zmb_generator_buildable"; + break; + case "chalk_buildable_trigger": + alias = "zmb_chalk_loop"; + break; + default: + alias = "zmb_buildable_loop"; + break; + } + return alias; +} + +onenduseuts( team, player, result ) +{ +/# + if ( isDefined( player ) && isDefined( player.name ) ) + { + println( "ZM >> Buildable piece end use by - " + player.name ); +#/ + } + if ( !isDefined( player ) ) + { + return; + } + if ( isDefined( player.buildableaudio ) ) + { + player.buildableaudio delete(); + player.buildableaudio = undefined; + } + if ( isDefined( self.buildablestruct.onenduse ) ) + { + self [[ self.buildablestruct.onenduse ]]( team, player, result ); + } + player notify( "event_ended" ); +} + +oncantuseuts( player ) +{ +/# + if ( isDefined( player ) && isDefined( player.name ) ) + { + println( "ZM >> Buildable piece can't use by - " + player.name ); +#/ + } + if ( isDefined( self.buildablestruct.oncantuse ) ) + { + self [[ self.buildablestruct.oncantuse ]]( player ); + } +} + +onuseplantobjectuts( player ) +{ +/# + if ( isDefined( player ) && isDefined( player.name ) ) + { + println( "ZM >> Buildable piece crafted by - " + player.name ); +#/ + } + if ( isDefined( self.buildablestruct.onuseplantobject ) ) + { + self [[ self.buildablestruct.onuseplantobject ]]( player ); + } + player notify( "bomb_planted" ); +} + +add_zombie_buildable_vox_category( buildable_name, vox_id ) +{ + buildable_struct = level.zombie_include_buildables[ buildable_name ]; + buildable_struct.vox_id = vox_id; +} + +add_zombie_buildable_piece_vox_category( buildable_name, vox_id, timer ) +{ + buildable_struct = level.zombie_include_buildables[ buildable_name ]; + buildable_struct.piece_vox_id = vox_id; + buildable_struct.piece_vox_timer = timer; +} + +is_buildable() +{ + if ( !isDefined( level.zombie_buildables ) ) + { + return 0; + } + if ( isDefined( self.zombie_weapon_upgrade ) && isDefined( level.zombie_buildables[ self.zombie_weapon_upgrade ] ) ) + { + return 1; + } + if ( isDefined( self.script_noteworthy ) && self.script_noteworthy == "specialty_weapupgrade" ) + { + if ( isDefined( level.buildables_built[ "pap" ] ) && level.buildables_built[ "pap" ] ) + { + return 0; + } + return 1; + } + return 0; +} + +buildable_crafted() +{ + self.pieces--; + +} + +buildable_complete() +{ + if ( self.pieces <= 0 ) + { + return 1; + } + return 0; +} + +get_buildable_hint( buildable_name ) +{ +/# + assert( isDefined( level.zombie_buildables[ buildable_name ] ), buildable_name + " was not included or is not part of the zombie weapon list." ); +#/ + return level.zombie_buildables[ buildable_name ].hint; +} + +delete_on_disconnect( buildable, self_notify, skip_delete ) +{ + buildable endon( "death" ); + self waittill( "disconnect" ); + if ( isDefined( self_notify ) ) + { + self notify( self_notify ); + } + if ( isDefined( skip_delete ) && !skip_delete ) + { + if ( isDefined( buildable.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( buildable.stub ); + buildable.stub = undefined; + } + if ( isDefined( buildable ) ) + { + buildable delete(); + } + } +} + +get_buildable_pickup( buildablename, modelname ) +{ + _a2858 = level.buildablepickups; + _k2858 = getFirstArrayKey( _a2858 ); + while ( isDefined( _k2858 ) ) + { + buildablepickup = _a2858[ _k2858 ]; + if ( buildablepickup[ 0 ].buildablestruct.name == buildablename && buildablepickup[ 0 ].visuals[ 0 ].model == modelname ) + { + return buildablepickup[ 0 ]; + } + _k2858 = getNextArrayKey( _a2858, _k2858 ); + } + return undefined; +} + +track_buildable_piece_pickedup( piece ) +{ + if ( !isDefined( piece ) || !isDefined( piece.buildablename ) ) + { +/# + println( "STAT TRACKING FAILURE: NOT DEFINED IN track_buildable_piece_pickedup() \n" ); +#/ + return; + } + self add_map_buildable_stat( piece.buildablename, "pieces_pickedup", 1 ); + buildable_struct = level.zombie_include_buildables[ piece.buildablename ]; + if ( isDefined( buildable_struct.piece_vox_id ) ) + { + if ( isDefined( self.a_buildable_piece_pickedup_vox_cooldown ) && isinarray( self.a_buildable_piece_pickedup_vox_cooldown, buildable_struct.piece_vox_id ) ) + { + return; + } + self thread do_player_general_vox( "general", buildable_struct.piece_vox_id + "_pickup" ); + if ( isDefined( buildable_struct.piece_vox_timer ) ) + { + self thread buildable_piece_pickedup_vox_cooldown( buildable_struct.piece_vox_id, buildable_struct.piece_vox_timer ); + } + } + else + { + self thread do_player_general_vox( "general", "build_pickup" ); + } +} + +buildable_piece_pickedup_vox_cooldown( piece_vox_id, timer ) +{ + self endon( "disconnect" ); + if ( !isDefined( self.a_buildable_piece_pickedup_vox_cooldown ) ) + { + self.a_buildable_piece_pickedup_vox_cooldown = []; + } + self.a_buildable_piece_pickedup_vox_cooldown[ self.a_buildable_piece_pickedup_vox_cooldown.size ] = piece_vox_id; + wait timer; + arrayremovevalue( self.a_buildable_piece_pickedup_vox_cooldown, piece_vox_id ); +} + +track_buildable_pieces_built( buildable ) +{ + if ( !isDefined( buildable ) || !isDefined( buildable.buildable_name ) ) + { +/# + println( "STAT TRACKING FAILURE: NOT DEFINED IN track_buildable_pieces_built() \n" ); +#/ + return; + } + bname = buildable.buildable_name; + if ( isDefined( buildable.stat_name ) ) + { + bname = buildable.stat_name; + } + self add_map_buildable_stat( bname, "pieces_built", 1 ); + if ( !buildable buildable_all_built() ) + { + if ( isDefined( level.zombie_include_buildables[ buildable.buildable_name ] ) && isDefined( level.zombie_include_buildables[ buildable.buildable_name ].snd_build_add_vo_override ) ) + { + self thread [[ level.zombie_include_buildables[ buildable.buildable_name ].snd_build_add_vo_override ]](); + return; + } + else + { + self thread do_player_general_vox( "general", "build_add" ); + } + } +} + +track_buildables_built( buildable ) +{ + if ( !isDefined( buildable ) || !isDefined( buildable.buildable_name ) ) + { +/# + println( "STAT TRACKING FAILURE: NOT DEFINED IN track_buildables_built() \n" ); +#/ + return; + } + bname = buildable.buildable_name; + if ( isDefined( buildable.stat_name ) ) + { + bname = buildable.stat_name; + } + self add_map_buildable_stat( bname, "buildable_built", 1 ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "buildables_built", 0 ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "buildables_built" ); + if ( isDefined( buildable.stub.buildablestruct.vox_id ) ) + { + self thread do_player_general_vox( "general", "build_" + buildable.stub.buildablestruct.vox_id + "_final" ); + } +} + +track_buildables_pickedup( buildable ) +{ + if ( !isDefined( buildable ) ) + { +/# + println( "STAT TRACKING FAILURE: NOT DEFINED IN track_buildables_pickedup() \n" ); +#/ + return; + } + stat_name = get_buildable_stat_name( buildable ); + if ( !isDefined( stat_name ) ) + { +/# + println( "STAT TRACKING FAILURE: NO STAT NAME FOR " + buildable + "\n" ); +#/ + return; + } + self add_map_buildable_stat( stat_name, "buildable_pickedup", 1 ); + self say_pickup_buildable_vo( buildable, 0 ); +} + +track_buildables_planted( equipment ) +{ + if ( !isDefined( equipment ) ) + { +/# + println( "STAT TRACKING FAILURE: NOT DEFINED for track_buildables_planted() \n" ); +#/ + return; + } + buildable_name = undefined; + if ( isDefined( equipment.name ) ) + { + buildable_name = get_buildable_stat_name( equipment.name ); + } + if ( !isDefined( buildable_name ) ) + { +/# + println( "STAT TRACKING FAILURE: NO BUILDABLE NAME FOR track_buildables_planted() " + equipment.name + "\n" ); +#/ + return; + } + maps/mp/_demo::bookmark( "zm_player_buildable_placed", getTime(), self ); + self add_map_buildable_stat( buildable_name, "buildable_placed", 1 ); + vo_name = "build_plc_" + buildable_name; + if ( buildable_name == "electric_trap" ) + { + vo_name = "build_plc_trap"; + } + if ( isDefined( self.buildable_timer ) && !self.buildable_timer ) + { + self thread do_player_general_vox( "general", vo_name ); + self thread placed_buildable_vo_timer(); + } +} + +placed_buildable_vo_timer() +{ + self endon( "disconnect" ); + self.buildable_timer = 1; + wait 60; + self.buildable_timer = 0; +} + +buildable_pickedup_timer() +{ + self endon( "disconnect" ); + self.buildable_pickedup_timer = 1; + wait 60; + self.buildable_pickedup_timer = 0; +} + +track_planted_buildables_pickedup( equipment ) +{ + if ( !isDefined( equipment ) ) + { + return; + } + if ( equipment != "equip_turbine_zm" && equipment != "equip_turret_zm" || equipment == "equip_electrictrap_zm" && equipment == "riotshield_zm" ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "planted_buildables_pickedup", 0 ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "planted_buildables_pickedup" ); + } + if ( isDefined( self.buildable_pickedup_timer ) && !self.buildable_pickedup_timer ) + { + self say_pickup_buildable_vo( equipment, 1 ); + self thread buildable_pickedup_timer(); + } +} + +track_placed_buildables( buildable_name ) +{ + if ( !isDefined( buildable_name ) ) + { + return; + } + self add_map_buildable_stat( buildable_name, "buildable_placed", 1 ); + vo_name = undefined; + if ( buildable_name == level.riotshield_name ) + { + vo_name = "build_plc_shield"; + } + if ( !isDefined( vo_name ) ) + { + return; + } + self thread do_player_general_vox( "general", vo_name ); +} + +add_map_buildable_stat( piece_name, stat_name, value ) +{ + if ( isDefined( piece_name ) && piece_name != "sq_common" || piece_name == "keys_zm" && piece_name == "oillamp_zm" ) + { + return; + } + if ( isDefined( level.zm_disable_recording_stats ) || level.zm_disable_recording_stats && isDefined( level.zm_disable_recording_buildable_stats ) && level.zm_disable_recording_buildable_stats ) + { + return; + } + self adddstat( "buildables", piece_name, stat_name, value ); +} + +say_pickup_buildable_vo( buildable_name, world ) +{ + if ( isDefined( self.buildable_pickedup_timer ) && self.buildable_pickedup_timer ) + { + return; + } + name = get_buildable_vo_name( buildable_name ); + if ( !isDefined( name ) ) + { + return; + } + vo_name = "build_pck_b" + name; + if ( isDefined( world ) && world ) + { + vo_name = "build_pck_w" + name; + } + if ( !isDefined( level.transit_buildable_vo_override ) || !( self [[ level.transit_buildable_vo_override ]]( name, world ) ) ) + { + self thread do_player_general_vox( "general", vo_name ); + self thread buildable_pickedup_timer(); + } +} + +get_buildable_vo_name( buildable_name ) +{ + switch( buildable_name ) + { + case "equip_turbine_zm": + return "turbine"; + case "equip_turret_zm": + return "turret"; + case "equip_electrictrap_zm": + return "trap"; + case "riotshield_zm": + return "shield"; + case "jetgun_zm": + return "jetgun"; + case "equip_springpad_zm": + return "springpad_zm"; + case "equip_slipgun_zm": + return "slipgun_zm"; + case "equip_headchopper_zm": + return "headchopper_zm"; + case "equip_subwoofer_zm": + return "subwoofer_zm"; + } + return undefined; +} + +get_buildable_stat_name( buildable ) +{ + if ( isDefined( buildable ) ) + { + switch( buildable ) + { + case "equip_turbine_zm": + return "turbine"; + case "equip_turret_zm": + return "turret"; + case "equip_electrictrap_zm": + return "electric_trap"; + case "equip_springpad_zm": + return "springpad_zm"; + case "equip_slipgun_zm": + return "slipgun_zm"; + case "equip_headchopper_zm": + return "headchopper_zm"; + case "equip_subwoofer_zm": + return "subwoofer_zm"; + } + return undefined; + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_devgui.gsc b/patch_zm/maps/mp/zombies/_zm_devgui.gsc new file mode 100644 index 0000000..1aa2351 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_devgui.gsc @@ -0,0 +1,2344 @@ +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_weap_claymore; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_turned; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ +/# + setdvar( "zombie_devgui", "" ); + setdvar( "scr_force_weapon", "" ); + setdvar( "scr_zombie_round", "1" ); + setdvar( "scr_zombie_dogs", "1" ); + setdvar( "scr_spawn_tesla", "" ); + setdvar( "scr_force_quantum_bomb_result", "" ); + level.devgui_add_weapon = ::devgui_add_weapon; + level.devgui_add_ability = ::devgui_add_ability; + level thread zombie_devgui_think(); + thread zombie_devgui_player_commands(); + thread diable_fog_in_noclip(); + thread zombie_weapon_devgui_think(); + thread devgui_zombie_healthbar(); +#/ +} + +zombie_devgui_player_commands() +{ +/# + flag_wait( "start_zombie_round_logic" ); + wait 1; + players = get_players(); + i = 0; + while ( i < players.size ) + { + ip1 = i + 1; + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Give Money:1" "set zombie_devgui player" + ip1 + "_money" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Invulnerable:2" "set zombie_devgui player" + ip1 + "_invul_on" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Vulnerable:3" "set zombie_devgui player" + ip1 + "_invul_off" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Toggle Ignored:4" "set zombie_devgui player" + ip1 + "_ignore" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Mega Health:5" "set zombie_devgui player" + ip1 + "_health" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Down:6" "set zombie_devgui player" + ip1 + "_kill" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Revive:7" "set zombie_devgui player" + ip1 + "_revive" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Turn Player:8" "set zombie_devgui player" + ip1 + "_turnplayer" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Debug Pers:9" "set zombie_devgui player" + ip1 + "_debug_pers" \n" ); + adddebugcommand( "devgui_cmd "Zombies:1/Players:1/Player:1/" + players[ i ].name + "/Take Money:10" "set zombie_devgui player" + ip1 + "_moneydown" \n" ); + i++; +#/ + } +} + +devgui_add_weapon_entry( hint, up, weapon_name, root ) +{ +/# + rootslash = ""; + if ( isDefined( root ) && root.size ) + { + rootslash = root + "/"; + } + uppath = "/" + up; + if ( up.size < 1 ) + { + uppath = ""; + } + cmd = "devgui_cmd "Zombies:1/Weapons:10/" + rootslash + hint + uppath + "" "set zombie_devgui_gun " + weapon_name + "" \n"; + adddebugcommand( cmd ); +#/ +} + +devgui_add_weapon_and_attachments( hint, up, weapon_name, root ) +{ +/# + devgui_add_weapon_entry( hint, up, weapon_name, root ); +#/ +} + +devgui_add_weapon( weapon_name, upgrade_name, hint, cost, weaponvo, weaponvoresp, ammo_cost ) +{ +/# + if ( is_offhand_weapon( weapon_name ) && !is_melee_weapon( weapon_name ) ) + { + return; + } + if ( !isDefined( level.devgui_weapons_added ) ) + { + level.devgui_weapons_added = 0; + } + level.devgui_weapons_added++; + if ( is_melee_weapon( weapon_name ) ) + { + devgui_add_weapon_and_attachments( weapon_name, "", weapon_name, "Melee:8" ); + } + else + { + devgui_add_weapon_and_attachments( weapon_name, "", weapon_name, "" ); +#/ + } +} + +zombie_weapon_devgui_think() +{ +/# + level.zombie_devgui_gun = getDvar( #"CE4F9F97" ); + level.zombie_devgui_att = getDvar( #"A965F402" ); + for ( ;; ) + { + wait 0,25; + cmd = getDvar( #"CE4F9F97" ); + if ( !isDefined( level.zombie_devgui_gun ) || level.zombie_devgui_gun != cmd ) + { + level.zombie_devgui_gun = cmd; + array_thread( get_players(), ::zombie_devgui_weapon_give, level.zombie_devgui_gun ); + } + wait 0,25; + att = getDvar( #"A965F402" ); + if ( !isDefined( level.zombie_devgui_att ) || level.zombie_devgui_att != att ) + { + level.zombie_devgui_att = att; + array_thread( get_players(), ::zombie_devgui_attachment_give, level.zombie_devgui_att ); + } +#/ + } +} + +zombie_devgui_weapon_give( gun ) +{ +/# + self maps/mp/zombies/_zm_weapons::weapon_give( gun, is_weapon_upgraded( gun ), 0 ); +#/ +} + +zombie_devgui_attachment_give( gun ) +{ +/# + newgun = maps/mp/zombies/_zm_weapons::get_base_name( self getcurrentweapon() ) + "+" + gun; + self maps/mp/zombies/_zm_weapons::weapon_give( newgun, is_weapon_upgraded( gun ), 0 ); +#/ +} + +devgui_add_ability( name, upgrade_active_func, stat_name, stat_desired_value, game_end_reset_if_not_achieved ) +{ +/# + online_game = sessionmodeisonlinegame(); + if ( !online_game ) + { + return; + } + if ( !is_true( level.devgui_watch_abilities ) ) + { + cmd = "devgui_cmd "Zombies:1/Players:1/Abilities:3/Disable All:1" "set zombie_devgui_give_ability _disable" \n"; + adddebugcommand( cmd ); + cmd = "devgui_cmd "Zombies:1/Players:1/Abilities:3/Enable All:2" "set zombie_devgui_give_ability _enable" \n"; + adddebugcommand( cmd ); + level thread zombie_ability_devgui_think(); + level.devgui_watch_abilities = 1; + } + cmd = "devgui_cmd "Zombies:1/Players:1/Abilities:3/" + name + "" "set zombie_devgui_give_ability " + name + "" \n"; + adddebugcommand( cmd ); + cmd = "devgui_cmd "Zombies:1/Players:1/Abilities:3/Take:3/" + name + "" "set zombie_devgui_take_ability " + name + "" \n"; + adddebugcommand( cmd ); +#/ +} + +zombie_devgui_ability_give( name ) +{ +/# + pers_upgrade = level.pers_upgrades[ name ]; + while ( isDefined( pers_upgrade ) ) + { + i = 0; + while ( i < pers_upgrade.stat_names.size ) + { + stat_name = pers_upgrade.stat_names[ i ]; + stat_value = pers_upgrade.stat_desired_values[ i ]; + self maps/mp/zombies/_zm_stats::set_global_stat( stat_name, stat_value ); + self.pers_upgrade_force_test = 1; + i++; +#/ + } + } +} + +zombie_devgui_ability_take( name ) +{ +/# + pers_upgrade = level.pers_upgrades[ name ]; + while ( isDefined( pers_upgrade ) ) + { + i = 0; + while ( i < pers_upgrade.stat_names.size ) + { + stat_name = pers_upgrade.stat_names[ i ]; + stat_value = 0; + self maps/mp/zombies/_zm_stats::set_global_stat( stat_name, stat_value ); + self.pers_upgrade_force_test = 1; + i++; +#/ + } + } +} + +zombie_ability_devgui_think() +{ +/# + level.zombie_devgui_give_ability = getDvar( #"E2245F05" ); + level.zombie_devgui_take_ability = getDvar( #"0726367F" ); + for ( ;; ) + { + wait 0,25; + cmd = getDvar( #"E2245F05" ); + if ( !isDefined( level.zombie_devgui_give_ability ) || level.zombie_devgui_give_ability != cmd ) + { + if ( cmd == "_disable" ) + { + flag_set( "sq_minigame_active" ); + break; + } + else if ( cmd == "_enable" ) + { + flag_clear( "sq_minigame_active" ); + break; + } + else + { + level.zombie_devgui_give_ability = cmd; + array_thread( get_players(), ::zombie_devgui_ability_give, level.zombie_devgui_give_ability ); + } + } + wait 0,25; + cmd = getDvar( #"0726367F" ); + if ( !isDefined( level.zombie_devgui_take_ability ) || level.zombie_devgui_take_ability != cmd ) + { + level.zombie_devgui_take_ability = cmd; + array_thread( get_players(), ::zombie_devgui_ability_take, level.zombie_devgui_take_ability ); + } +#/ + } +} + +zombie_healthbar( pos, dsquared ) +{ +/# + if ( distancesquared( pos, self.origin ) > dsquared ) + { + return; + } + rate = 1; + if ( isDefined( self.maxhealth ) ) + { + rate = self.health / self.maxhealth; + } + color = ( 1 - rate, rate, 0 ); + text = "" + int( self.health ); + print3d( self.origin + ( 0, 1, 0 ), text, color, 1, 0,5, 1 ); +#/ +} + +devgui_zombie_healthbar() +{ +/# + while ( 1 ) + { + while ( getDvarInt( #"5B45DCAF" ) == 1 ) + { + lp = get_players()[ 0 ]; + zombies = getaispeciesarray( "all", "all" ); + while ( isDefined( zombies ) ) + { + _a260 = zombies; + _k260 = getFirstArrayKey( _a260 ); + while ( isDefined( _k260 ) ) + { + zombie = _a260[ _k260 ]; + zombie zombie_healthbar( lp.origin, 360000 ); + _k260 = getNextArrayKey( _a260, _k260 ); + } + } + } + wait 0,05; +#/ + } +} + +zombie_devgui_watch_input() +{ +/# + flag_wait( "start_zombie_round_logic" ); + wait 1; + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] thread watch_debug_input(); + i++; +#/ + } +} + +damage_player() +{ +/# + self disableinvulnerability(); + self dodamage( self.health / 2, self.origin ); +#/ +} + +kill_player() +{ +/# + self disableinvulnerability(); + death_from = ( randomfloatrange( -20, 20 ), randomfloatrange( -20, 20 ), randomfloatrange( -20, 20 ) ); + self dodamage( self.health + 666, self.origin + death_from ); +#/ +} + +force_drink() +{ +/# + wait 0,01; + lean = self allowlean( 0 ); + ads = self allowads( 0 ); + sprint = self allowsprint( 0 ); + crouch = self allowcrouch( 1 ); + prone = self allowprone( 0 ); + melee = self allowmelee( 0 ); + self increment_is_drinking(); + orgweapon = self getcurrentweapon(); + self giveweapon( "zombie_builder_zm" ); + self switchtoweapon( "zombie_builder_zm" ); + self.build_time = self.usetime; + self.build_start_time = getTime(); + wait 2; + self maps/mp/zombies/_zm_weapons::switch_back_primary_weapon( orgweapon ); + self takeweapon( "zombie_builder_zm" ); + if ( is_true( self.is_drinking ) ) + { + self decrement_is_drinking(); + } + self allowlean( lean ); + self allowads( ads ); + self allowsprint( sprint ); + self allowprone( prone ); + self allowcrouch( crouch ); + self allowmelee( melee ); +#/ +} + +zombie_devgui_dpad_none() +{ +/# + self thread watch_debug_input(); +#/ +} + +zombie_devgui_dpad_death() +{ +/# + self thread watch_debug_input( ::kill_player ); +#/ +} + +zombie_devgui_dpad_damage() +{ +/# + self thread watch_debug_input( ::damage_player ); +#/ +} + +zombie_devgui_dpad_changeweapon() +{ +/# + self thread watch_debug_input( ::force_drink ); +#/ +} + +watch_debug_input( callback ) +{ +/# + self endon( "disconnect" ); + self notify( "watch_debug_input" ); + self endon( "watch_debug_input" ); + level.devgui_dpad_watch = 0; + while ( isDefined( callback ) ) + { + level.devgui_dpad_watch = 1; + for ( ;; ) + { + while ( self actionslottwobuttonpressed() ) + { + self thread [[ callback ]](); + while ( self actionslottwobuttonpressed() ) + { + wait 0,05; + } + } + wait 0,05; +#/ + } + } +} + +zombie_devgui_think() +{ +/# + for ( ;; ) + { + cmd = getDvar( "zombie_devgui" ); + switch( cmd ) + { + case "money": + players = get_players(); + array_thread( players, ::zombie_devgui_give_money ); + break; + case "player1_money": + players = get_players(); + if ( players.size >= 1 ) + { + players[ 0 ] thread zombie_devgui_give_money(); + } + break; + case "player2_money": + players = get_players(); + if ( players.size >= 2 ) + { + players[ 1 ] thread zombie_devgui_give_money(); + } + break; + case "player3_money": + players = get_players(); + if ( players.size >= 3 ) + { + players[ 2 ] thread zombie_devgui_give_money(); + } + break; + case "player4_money": + players = get_players(); + if ( players.size >= 4 ) + { + players[ 3 ] thread zombie_devgui_give_money(); + } + break; + case "moneydown": + players = get_players(); + array_thread( players, ::zombie_devgui_take_money ); + break; + case "player1_moneydown": + players = get_players(); + if ( players.size >= 1 ) + { + players[ 0 ] thread zombie_devgui_take_money(); + } + break; + case "player2_moneydown": + players = get_players(); + if ( players.size >= 2 ) + { + players[ 1 ] thread zombie_devgui_take_money(); + } + break; + case "player3_moneydown": + players = get_players(); + if ( players.size >= 3 ) + { + players[ 2 ] thread zombie_devgui_take_money(); + } + break; + case "player4_moneydown": + players = get_players(); + if ( players.size >= 4 ) + { + players[ 3 ] thread zombie_devgui_take_money(); + } + break; + case "health": + array_thread( get_players(), ::zombie_devgui_give_health ); + break; + case "player1_health": + players = get_players(); + if ( players.size >= 1 ) + { + players[ 0 ] thread zombie_devgui_give_health(); + } + break; + case "player2_health": + players = get_players(); + if ( players.size >= 2 ) + { + players[ 1 ] thread zombie_devgui_give_health(); + } + break; + case "player3_health": + players = get_players(); + if ( players.size >= 3 ) + { + players[ 2 ] thread zombie_devgui_give_health(); + } + break; + case "player4_health": + players = get_players(); + if ( players.size >= 4 ) + { + players[ 3 ] thread zombie_devgui_give_health(); + } + break; + case "ammo": + array_thread( get_players(), ::zombie_devgui_toggle_ammo ); + break; + case "ignore": + array_thread( get_players(), ::zombie_devgui_toggle_ignore ); + break; + case "player1_ignore": + players = get_players(); + if ( players.size >= 1 ) + { + players[ 0 ] thread zombie_devgui_toggle_ignore(); + } + break; + case "player2_ignore": + players = get_players(); + if ( players.size >= 2 ) + { + players[ 1 ] thread zombie_devgui_toggle_ignore(); + } + break; + case "player3_ignore": + players = get_players(); + if ( players.size >= 3 ) + { + players[ 2 ] thread zombie_devgui_toggle_ignore(); + } + break; + case "player4_ignore": + players = get_players(); + if ( players.size >= 4 ) + { + players[ 3 ] thread zombie_devgui_toggle_ignore(); + } + break; + case "invul_on": + zombie_devgui_invulnerable( undefined, 1 ); + break; + case "invul_off": + zombie_devgui_invulnerable( undefined, 0 ); + break; + case "player1_invul_on": + zombie_devgui_invulnerable( 0, 1 ); + break; + case "player1_invul_off": + zombie_devgui_invulnerable( 0, 0 ); + break; + case "player2_invul_on": + zombie_devgui_invulnerable( 1, 1 ); + break; + case "player2_invul_off": + zombie_devgui_invulnerable( 1, 0 ); + break; + case "player3_invul_on": + zombie_devgui_invulnerable( 2, 1 ); + break; + case "player3_invul_off": + zombie_devgui_invulnerable( 2, 0 ); + break; + case "player4_invul_on": + zombie_devgui_invulnerable( 3, 1 ); + break; + case "player4_invul_off": + zombie_devgui_invulnerable( 3, 0 ); + break; + case "revive_all": + array_thread( get_players(), ::zombie_devgui_revive ); + break; + case "player1_revive": + players = get_players(); + if ( players.size >= 1 ) + { + players[ 0 ] thread zombie_devgui_revive(); + } + break; + case "player2_revive": + players = get_players(); + if ( players.size >= 2 ) + { + players[ 1 ] thread zombie_devgui_revive(); + } + break; + case "player3_revive": + players = get_players(); + if ( players.size >= 3 ) + { + players[ 2 ] thread zombie_devgui_revive(); + } + break; + case "player4_revive": + players = get_players(); + if ( players.size >= 4 ) + { + players[ 3 ] thread zombie_devgui_revive(); + } + break; + case "player1_kill": + players = get_players(); + if ( players.size >= 1 ) + { + players[ 0 ] thread zombie_devgui_kill(); + } + break; + case "player2_kill": + players = get_players(); + if ( players.size >= 2 ) + { + players[ 1 ] thread zombie_devgui_kill(); + } + break; + case "player3_kill": + players = get_players(); + if ( players.size >= 3 ) + { + players[ 2 ] thread zombie_devgui_kill(); + } + break; + case "player4_kill": + players = get_players(); + if ( players.size >= 4 ) + { + players[ 3 ] thread zombie_devgui_kill(); + } + break; + case "spawn_friendly_bot": + player = gethostplayer(); + team = player.team; + devgui_bot_spawn( team ); + break; + case "specialty_quickrevive": + level.solo_lives_given = 0; + case "specialty_additionalprimaryweapon": + case "specialty_armorvest": + case "specialty_deadshot": + case "specialty_fastmeleerecovery": + case "specialty_fastreload": + case "specialty_finalstand": + case "specialty_flakjacket": + case "specialty_grenadepulldeath": + case "specialty_longersprint": + case "specialty_nomotionsensor": + case "specialty_rof": + case "specialty_scavenger": + case "specialty_showonradar": + zombie_devgui_give_perk( cmd ); + break; + case "turnplayer": + zombie_devgui_turn_player(); + break; + case "player1_turnplayer": + zombie_devgui_turn_player( 0 ); + break; + case "player2_turnplayer": + zombie_devgui_turn_player( 1 ); + break; + case "player3_turnplayer": + zombie_devgui_turn_player( 2 ); + break; + case "player4_turnplayer": + zombie_devgui_turn_player( 3 ); + break; + case "player1_debug_pers": + zombie_devgui_debug_pers( 0 ); + break; + case "player2_debug_pers": + zombie_devgui_debug_pers( 1 ); + break; + case "player3_debug_pers": + zombie_devgui_debug_pers( 2 ); + break; + case "player4_debug_pers": + zombie_devgui_debug_pers( 3 ); + break; + case "bonfire_sale": + case "bonus_points_player": + case "bonus_points_team": + case "carpenter": + case "double_points": + case "empty_clip": + case "fire_sale": + case "free_perk": + case "full_ammo": + case "insta_kill": + case "lose_perk": + case "lose_points_team": + case "meat_stink": + case "minigun": + case "nuke": + case "random_weapon": + case "tesla": + zombie_devgui_give_powerup( cmd, 1 ); + break; + case "next_bonfire_sale": + case "next_bonus_points_player": + case "next_bonus_points_team": + case "next_carpenter": + case "next_double_points": + case "next_empty_clip": + case "next_fire_sale": + case "next_free_perk": + case "next_full_ammo": + case "next_insta_kill": + case "next_lose_perk": + case "next_lose_points_team": + case "next_meat_stink": + case "next_minigun": + case "next_nuke": + case "next_random_weapon": + case "next_tesla": + zombie_devgui_give_powerup( getsubstr( cmd, 5 ), 0 ); + break; + case "round": + zombie_devgui_goto_round( getDvarInt( "scr_zombie_round" ) ); + break; + case "round_next": + zombie_devgui_goto_round( level.round_number + 1 ); + break; + case "round_prev": + zombie_devgui_goto_round( level.round_number - 1 ); + break; + case "chest_move": + if ( isDefined( level.chest_accessed ) ) + { + level notify( "devgui_chest_end_monitor" ); + level.chest_accessed = 100; + } + break; + case "chest_never_move": + if ( isDefined( level.chest_accessed ) ) + { + level thread zombie_devgui_chest_never_move(); + } + break; + case "chest": + if ( isDefined( level.zombie_weapons[ getDvar( "scr_force_weapon" ) ] ) ) + { + } + break; + case "quantum_bomb_random_result": + setdvar( "scr_force_quantum_bomb_result", "" ); + break; + case "give_gasmask": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_gasmask_zm" ); + break; + case "give_hacker": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_hacker_zm" ); + break; + case "give_turbine": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_turbine_zm" ); + break; + case "give_turret": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_turret_zm" ); + break; + case "give_electrictrap": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_electrictrap_zm" ); + break; + case "give_riotshield": + array_thread( get_players(), ::zombie_devgui_equipment_give, "riotshield_zm" ); + break; + case "give_jetgun": + array_thread( get_players(), ::zombie_devgui_equipment_give, "jetgun_zm" ); + break; + case "give_springpad": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_springpad_zm" ); + break; + case "give_subwoofer": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_subwoofer_zm" ); + break; + case "give_headchopper": + array_thread( get_players(), ::zombie_devgui_equipment_give, "equip_headchopper_zm" ); + break; + case "cool_jetgun": + array_thread( get_players(), ::zombie_devgui_cool_jetgun ); + break; + case "preserve_turbines": + array_thread( get_players(), ::zombie_devgui_preserve_turbines ); + break; + case "healthy_equipment": + array_thread( get_players(), ::zombie_devgui_equipment_stays_healthy ); + break; + case "disown_equipment": + array_thread( get_players(), ::zombie_devgui_disown_equipment ); + break; + case "buildable_drop": + array_thread( get_players(), ::zombie_devgui_buildable_drop ); + break; + case "build_busladder": + zombie_devgui_build( "busladder" ); + break; + case "build_bushatch": + zombie_devgui_build( "bushatch" ); + break; + case "build_dinerhatch": + zombie_devgui_build( "dinerhatch" ); + break; + case "build_cattlecatcher": + zombie_devgui_build( "cattlecatcher" ); + break; + case "build_pap": + zombie_devgui_build( "pap" ); + break; + case "build_riotshield_zm": + zombie_devgui_build( "riotshield_zm" ); + break; + case "build_powerswitch": + zombie_devgui_build( "powerswitch" ); + break; + case "build_turbine": + zombie_devgui_build( "turbine" ); + break; + case "build_turret": + zombie_devgui_build( "turret" ); + break; + case "build_electric_trap": + zombie_devgui_build( "electric_trap" ); + break; + case "build_jetgun_zm": + zombie_devgui_build( "jetgun_zm" ); + break; + case "build_sq_common": + zombie_devgui_build( "sq_common" ); + break; + case "build_springpad": + zombie_devgui_build( "springpad_zm" ); + break; + case "build_slipgun": + zombie_devgui_build( "slipgun_zm" ); + break; + case "build_keys": + zombie_devgui_build( "keys_zm" ); + break; + case "give_claymores": + array_thread( get_players(), ::zombie_devgui_give_claymores ); + break; + case "give_frags": + array_thread( get_players(), ::zombie_devgui_give_frags ); + break; + case "give_sticky": + array_thread( get_players(), ::zombie_devgui_give_sticky ); + break; + case "give_monkey": + array_thread( get_players(), ::zombie_devgui_give_monkey ); + break; + case "give_beacon": + array_thread( get_players(), ::zombie_devgui_give_beacon ); + break; + case "give_time_bomb": + array_thread( get_players(), ::zombie_devgui_give_time_bomb ); + break; + case "give_black_hole_bomb": + array_thread( get_players(), ::zombie_devgui_give_black_hole_bomb ); + break; + case "give_dolls": + array_thread( get_players(), ::zombie_devgui_give_dolls ); + break; + case "give_quantum_bomb": + array_thread( get_players(), ::zombie_devgui_give_quantum_bomb ); + break; + case "give_emp_bomb": + array_thread( get_players(), ::zombie_devgui_give_emp_bomb ); + break; + case "monkey_round": + zombie_devgui_monkey_round(); + break; + case "thief_round": + zombie_devgui_thief_round(); + break; + case "dog_round": + zombie_devgui_dog_round( getDvarInt( "scr_zombie_dogs" ) ); + break; + case "dog_round_skip": + zombie_devgui_dog_round_skip(); + break; + case "print_variables": + zombie_devgui_dump_zombie_vars(); + break; + case "pack_current_weapon": + zombie_devgui_pack_current_weapon(); + break; + case "unpack_current_weapon": + zombie_devgui_unpack_current_weapon(); + break; + case "reopt_current_weapon": + zombie_devgui_reopt_current_weapon(); + break; + case "weapon_take_all_fallback": + zombie_devgui_take_weapons( 1 ); + break; + case "weapon_take_all": + zombie_devgui_take_weapons( 0 ); + break; + case "weapon_take_current": + zombie_devgui_take_weapon(); + break; + case "power_on": + flag_set( "power_on" ); + break; + case "power_off": + flag_clear( "power_on" ); + break; + case "zombie_dpad_none": + array_thread( get_players(), ::zombie_devgui_dpad_none ); + break; + case "zombie_dpad_damage": + array_thread( get_players(), ::zombie_devgui_dpad_damage ); + break; + case "zombie_dpad_kill": + array_thread( get_players(), ::zombie_devgui_dpad_death ); + break; + case "zombie_dpad_drink": + array_thread( get_players(), ::zombie_devgui_dpad_changeweapon ); + break; + case "director_easy": + zombie_devgui_director_easy(); + break; + case "open_sesame": + zombie_devgui_open_sesame(); + break; + case "allow_fog": + zombie_devgui_allow_fog(); + break; + case "disable_kill_thread_toggle": + zombie_devgui_disable_kill_thread_toggle(); + break; + case "check_kill_thread_every_frame_toggle": + zombie_devgui_check_kill_thread_every_frame_toggle(); + break; + case "kill_thread_test_mode_toggle": + zombie_devgui_kill_thread_test_mode_toggle(); + break; + case "zombie_failsafe_debug_flush": + level notify( "zombie_failsafe_debug_flush" ); + break; + case "spawn": + devgui_zombie_spawn(); + break; + case "spawn_all": + devgui_all_spawn(); + break; + case "toggle_show_spawn_locations": + devgui_toggle_show_spawn_locations(); + break; + case "debug_hud": + array_thread( get_players(), ::devgui_debug_hud ); + break; + case "": + default: + if ( isDefined( level.custom_devgui ) ) + { + if ( isarray( level.custom_devgui ) ) + { + i = 0; + b_found_entry = is_true( [[ level.custom_devgui[ i ] ]]( cmd ) ); + i++; + if ( !b_found_entry} + else [[ level.custom_devgui ]]( cmd ); + break; + } + } + setdvar( "zombie_devgui", "" ); + wait 0,5; +#/ + } + } + } + } +} + +devgui_all_spawn() +{ +/# + player = gethostplayer(); + devgui_bot_spawn( player.team ); + wait 0,1; + devgui_bot_spawn( player.team ); + wait 0,1; + devgui_bot_spawn( player.team ); + wait 0,1; + zombie_devgui_goto_round( 8 ); +#/ +} + +devgui_toggle_show_spawn_locations() +{ +/# + if ( !isDefined( level.toggle_show_spawn_locations ) ) + { + level.toggle_show_spawn_locations = 1; + } + else + { + level.toggle_show_spawn_locations = !level.toggle_show_spawn_locations; +#/ + } +} + +devgui_zombie_spawn() +{ +/# + player = get_players()[ 0 ]; + spawnername = undefined; + spawnername = "zombie_spawner"; + direction = player getplayerangles(); + direction_vec = anglesToForward( direction ); + eye = player geteye(); + scale = 8000; + direction_vec = ( direction_vec[ 0 ] * scale, direction_vec[ 1 ] * scale, direction_vec[ 2 ] * scale ); + trace = bullettrace( eye, eye + direction_vec, 0, undefined ); + guy = undefined; + spawners = getentarray( spawnername, "script_noteworthy" ); + spawner = spawners[ 0 ]; + guy = maps/mp/zombies/_zm_utility::spawn_zombie( spawner ); + if ( isDefined( guy ) ) + { + wait 0,5; + guy.origin = trace[ "position" ]; + guy.angles = player.angles + vectorScale( ( 0, 1, 0 ), 180 ); + guy forceteleport( trace[ "position" ], player.angles + vectorScale( ( 0, 1, 0 ), 180 ) ); + guy thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +#/ + } +} + +devgui_bot_spawn( team ) +{ +/# + player = gethostplayer(); + direction = player getplayerangles(); + direction_vec = anglesToForward( direction ); + eye = player geteye(); + scale = 8000; + direction_vec = ( direction_vec[ 0 ] * scale, direction_vec[ 1 ] * scale, direction_vec[ 2 ] * scale ); + trace = bullettrace( eye, eye + direction_vec, 0, undefined ); + direction_vec = player.origin - trace[ "position" ]; + direction = vectorToAngle( direction_vec ); + bot = addtestclient(); + if ( !isDefined( bot ) ) + { + println( "Could not add test client" ); + return; + } + bot.pers[ "isBot" ] = 1; + bot.equipment_enabled = 0; + bot maps/mp/zombies/_zm::reset_rampage_bookmark_kill_times(); + bot.team = "allies"; + bot._player_entnum = bot getentitynumber(); + yaw = direction[ 1 ]; + bot thread devgui_bot_spawn_think( trace[ "position" ], yaw ); +#/ +} + +devgui_bot_spawn_think( origin, yaw ) +{ +/# + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "spawned_player" ); + self setorigin( origin ); + angles = ( 0, yaw, 0 ); + self setplayerangles( angles ); +#/ + } +} + +zombie_devgui_open_sesame() +{ +/# + setdvar( "zombie_unlock_all", 1 ); + flag_set( "power_on" ); + players = get_players(); + array_thread( players, ::zombie_devgui_give_money ); + zombie_doors = getentarray( "zombie_door", "targetname" ); + i = 0; + while ( i < zombie_doors.size ) + { + zombie_doors[ i ] notify( "trigger" ); + if ( is_true( zombie_doors[ i ].power_door_ignore_flag_wait ) ) + { + zombie_doors[ i ] notify( "power_on" ); + } + wait 0,05; + i++; + } + zombie_airlock_doors = getentarray( "zombie_airlock_buy", "targetname" ); + i = 0; + while ( i < zombie_airlock_doors.size ) + { + zombie_airlock_doors[ i ] notify( "trigger" ); + wait 0,05; + i++; + } + zombie_debris = getentarray( "zombie_debris", "targetname" ); + i = 0; + while ( i < zombie_debris.size ) + { + zombie_debris[ i ] notify( "trigger" ); + wait 0,05; + i++; + } + zombie_devgui_build( undefined ); + level notify( "open_sesame" ); + wait 1; + setdvar( "zombie_unlock_all", 0 ); +#/ +} + +any_player_in_noclip() +{ +/# + _a1161 = get_players(); + _k1161 = getFirstArrayKey( _a1161 ); + while ( isDefined( _k1161 ) ) + { + player = _a1161[ _k1161 ]; + if ( player isinmovemode( "ufo", "noclip" ) ) + { + return 1; + } + _k1161 = getNextArrayKey( _a1161, _k1161 ); + } + return 0; +#/ +} + +diable_fog_in_noclip() +{ +/# + level.fog_disabled_in_noclip = 1; + level endon( "allowfoginnoclip" ); + flag_wait( "start_zombie_round_logic" ); + while ( 1 ) + { + while ( !any_player_in_noclip() ) + { + wait 1; + } + setdvar( "scr_fog_disable", "1" ); + setdvar( "r_fog_disable", "1" ); + if ( isDefined( level.culldist ) ) + { + setculldist( 0 ); + } + while ( any_player_in_noclip() ) + { + wait 1; + } + setdvar( "scr_fog_disable", "0" ); + setdvar( "r_fog_disable", "0" ); + if ( isDefined( level.culldist ) ) + { + setculldist( level.culldist ); + } +#/ + } +} + +zombie_devgui_allow_fog() +{ +/# + if ( level.fog_disabled_in_noclip ) + { + level notify( "allowfoginnoclip" ); + level.fog_disabled_in_noclip = 0; + setdvar( "scr_fog_disable", "0" ); + setdvar( "r_fog_disable", "0" ); + } + else + { + thread diable_fog_in_noclip(); +#/ + } +} + +zombie_devgui_give_money() +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + self maps/mp/zombies/_zm_score::add_to_player_score( 100000 ); +#/ +} + +zombie_devgui_take_money() +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + if ( self.score > 100 ) + { + self maps/mp/zombies/_zm_score::minus_to_player_score( int( self.score / 2 ) ); + } + else + { + self maps/mp/zombies/_zm_score::minus_to_player_score( self.score ); +#/ + } +} + +zombie_devgui_turn_player( index ) +{ +/# + players = get_players(); + if ( !isDefined( index ) || index >= players.size ) + { + player = players[ 0 ]; + } + else + { + player = players[ index ]; + } + assert( isDefined( player ) ); + assert( isplayer( player ) ); + assert( isalive( player ) ); + level.devcheater = 1; + if ( player hasperk( "specialty_noname" ) ) + { + println( "Player turned HUMAN" ); + player maps/mp/zombies/_zm_turned::turn_to_human(); + } + else + { + println( "Player turned ZOMBIE" ); + player maps/mp/zombies/_zm_turned::turn_to_zombie(); +#/ + } +} + +zombie_devgui_debug_pers( index ) +{ +/# + players = get_players(); + if ( !isDefined( index ) || index >= players.size ) + { + player = players[ 0 ]; + } + else + { + player = players[ index ]; + } + assert( isDefined( player ) ); + assert( isplayer( player ) ); + assert( isalive( player ) ); + level.devcheater = 1; + println( "\n\n----------------------------------------------------------------------------------------------" ); + println( "Active Persistent upgrades [count=" + level.pers_upgrades_keys.size + "]" ); + pers_upgrade_index = 0; + while ( pers_upgrade_index < level.pers_upgrades_keys.size ) + { + name = level.pers_upgrades_keys[ pers_upgrade_index ]; + println( ( pers_upgrade_index + ">pers_upgrade name = " ) + name ); + pers_upgrade = level.pers_upgrades[ name ]; + i = 0; + while ( i < pers_upgrade.stat_names.size ) + { + stat_name = pers_upgrade.stat_names[ i ]; + stat_desired_value = pers_upgrade.stat_desired_values[ i ]; + player_current_stat_value = player maps/mp/zombies/_zm_stats::get_global_stat( stat_name ); + println( " " + i + ")stat_name = " + stat_name ); + println( " " + i + ")stat_desired_values = " + stat_desired_value ); + println( " " + i + ")player_current_stat_value = " + player_current_stat_value ); + i++; + } + if ( is_true( player.pers_upgrades_awarded[ name ] ) ) + { + println( "PLAYER HAS - " + name ); + pers_upgrade_index++; + continue; + } + else + { + println( "PLAYER DOES NOT HAVE - " + name ); + } + pers_upgrade_index++; + } + println( "----------------------------------------------------------------------------------------------\n\n" ); +#/ +} + +zombie_devgui_cool_jetgun() +{ +/# + if ( isDefined( level.zm_devgui_jetgun_never_overheat ) ) + { + self thread [[ level.zm_devgui_jetgun_never_overheat ]](); +#/ + } +} + +zombie_devgui_preserve_turbines() +{ +/# + self endon( "disconnect" ); + self notify( "preserve_turbines" ); + self endon( "preserve_turbines" ); + while ( !is_true( self.preserving_turbines ) ) + { + self.preserving_turbines = 1; + while ( 1 ) + { + self.turbine_health = 1200; + wait 1; + } + } + self.preserving_turbines = 0; +#/ +} + +zombie_devgui_equipment_stays_healthy() +{ +/# + self endon( "disconnect" ); + self notify( "preserve_equipment" ); + self endon( "preserve_equipment" ); + while ( !is_true( self.preserving_equipment ) ) + { + self.preserving_equipment = 1; + while ( 1 ) + { + self.equipment_damage = []; + self.shielddamagetaken = 0; + while ( isDefined( level.destructible_equipment ) ) + { + _a1357 = level.destructible_equipment; + _k1357 = getFirstArrayKey( _a1357 ); + while ( isDefined( _k1357 ) ) + { + equip = _a1357[ _k1357 ]; + if ( isDefined( equip ) ) + { + equip.shielddamagetaken = 0; + equip.damage = 0; + equip.headchopper_kills = 0; + equip.springpad_kills = 0; + equip.subwoofer_kills = 0; + } + _k1357 = getNextArrayKey( _a1357, _k1357 ); + } + } + wait 0,1; + } + } + self.preserving_equipment = 0; +#/ +} + +zombie_devgui_disown_equipment() +{ +/# + self.deployed_equipment = []; +#/ +} + +zombie_devgui_equipment_give( equipment ) +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( is_equipment_included( equipment ) ) + { + self maps/mp/zombies/_zm_equipment::equipment_buy( equipment ); +#/ + } +} + +zombie_devgui_buildable_drop() +{ +/# + if ( isDefined( level.buildable_slot_count ) ) + { + i = 0; + while ( i < level.buildable_slot_count ) + { + self maps/mp/zombies/_zm_buildables::player_drop_piece( undefined, i ); + i++; + } + } + else self maps/mp/zombies/_zm_buildables::player_drop_piece(); +#/ +} + +zombie_devgui_build( buildable ) +{ +/# + player = get_players()[ 0 ]; + i = 0; + while ( i < level.buildable_stubs.size ) + { + if ( !isDefined( buildable ) || level.buildable_stubs[ i ].equipname == buildable ) + { + if ( !isDefined( buildable ) && is_true( level.buildable_stubs[ i ].ignore_open_sesame ) ) + { + i++; + continue; + } + else + { + if ( isDefined( buildable ) || level.buildable_stubs[ i ].persistent != 3 ) + { + level.buildable_stubs[ i ] maps/mp/zombies/_zm_buildables::buildablestub_finish_build( player ); + } + } + } + i++; +#/ + } +} + +zombie_devgui_give_claymores() +{ +/# + self endon( "disconnect" ); + self notify( "give_planted_grenade_thread" ); + self endon( "give_planted_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_placeable_mine() ) ) + { + self takeweapon( self get_player_placeable_mine() ); + } + self thread maps/mp/zombies/_zm_weap_claymore::claymore_setup(); + while ( 1 ) + { + self givemaxammo( "claymore_zm" ); + wait 1; +#/ + } +} + +zombie_devgui_give_lethal( weapon ) +{ +/# + self endon( "disconnect" ); + self notify( "give_lethal_grenade_thread" ); + self endon( "give_lethal_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_lethal_grenade() ) ) + { + self takeweapon( self get_player_lethal_grenade() ); + } + self giveweapon( weapon ); + self set_player_lethal_grenade( weapon ); + while ( 1 ) + { + self givemaxammo( weapon ); + wait 1; +#/ + } +} + +zombie_devgui_give_frags() +{ +/# + zombie_devgui_give_lethal( "frag_grenade_zm" ); +#/ +} + +zombie_devgui_give_sticky() +{ +/# + zombie_devgui_give_lethal( "sticky_grenade_zm" ); +#/ +} + +zombie_devgui_give_monkey() +{ +/# + self endon( "disconnect" ); + self notify( "give_tactical_grenade_thread" ); + self endon( "give_tactical_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + while ( isDefined( level.zombiemode_devgui_cymbal_monkey_give ) ) + { + self [[ level.zombiemode_devgui_cymbal_monkey_give ]](); + while ( 1 ) + { + self givemaxammo( "cymbal_monkey_zm" ); + wait 1; +#/ + } + } +} + +zombie_devgui_give_beacon() +{ +/# + self endon( "disconnect" ); + self notify( "give_tactical_grenade_thread" ); + self endon( "give_tactical_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + while ( isDefined( level.zombiemode_devgui_beacon_give ) ) + { + self [[ level.zombiemode_devgui_beacon_give ]](); + while ( 1 ) + { + self givemaxammo( "beacon_zm" ); + wait 1; +#/ + } + } +} + +zombie_devgui_give_time_bomb() +{ +/# + self endon( "disconnect" ); + self notify( "give_tactical_grenade_thread" ); + self endon( "give_tactical_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + if ( isDefined( level.zombiemode_time_bomb_give_func ) ) + { + self [[ level.zombiemode_time_bomb_give_func ]](); +#/ + } +} + +zombie_devgui_give_black_hole_bomb() +{ +/# + self endon( "disconnect" ); + self notify( "give_tactical_grenade_thread" ); + self endon( "give_tactical_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + while ( isDefined( level.zombiemode_devgui_black_hole_bomb_give ) ) + { + self [[ level.zombiemode_devgui_black_hole_bomb_give ]](); + while ( 1 ) + { + self givemaxammo( "zombie_black_hole_bomb" ); + wait 1; +#/ + } + } +} + +zombie_devgui_give_dolls() +{ +/# + self endon( "disconnect" ); + self notify( "give_tactical_grenade_thread" ); + self endon( "give_tactical_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + while ( isDefined( level.zombiemode_devgui_nesting_dolls_give ) ) + { + self [[ level.zombiemode_devgui_nesting_dolls_give ]](); + while ( 1 ) + { + self givemaxammo( "zombie_nesting_dolls" ); + wait 1; +#/ + } + } +} + +zombie_devgui_give_quantum_bomb() +{ +/# + self endon( "disconnect" ); + self notify( "give_tactical_grenade_thread" ); + self endon( "give_tactical_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + while ( isDefined( level.zombiemode_devgui_quantum_bomb_give ) ) + { + self [[ level.zombiemode_devgui_quantum_bomb_give ]](); + while ( 1 ) + { + self givemaxammo( "zombie_quantum_bomb" ); + wait 1; +#/ + } + } +} + +zombie_devgui_give_emp_bomb() +{ +/# + self endon( "disconnect" ); + self notify( "give_tactical_grenade_thread" ); + self endon( "give_tactical_grenade_thread" ); + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + level.devcheater = 1; + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + while ( isDefined( level.zombiemode_devgui_emp_bomb_give ) ) + { + self [[ level.zombiemode_devgui_emp_bomb_give ]](); + while ( 1 ) + { + self givemaxammo( "emp_grenade_zm" ); + wait 1; +#/ + } + } +} + +zombie_devgui_invulnerable( playerindex, onoff ) +{ +/# + players = get_players(); + if ( !isDefined( playerindex ) ) + { + i = 0; + while ( i < players.size ) + { + zombie_devgui_invulnerable( i, onoff ); + i++; + } + } + else if ( players.size > playerindex ) + { + if ( onoff ) + { + players[ playerindex ] enableinvulnerability(); + return; + } + else + { + players[ playerindex ] disableinvulnerability(); +#/ + } + } +} + +zombie_devgui_kill() +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + self disableinvulnerability(); + death_from = ( randomfloatrange( -20, 20 ), randomfloatrange( -20, 20 ), randomfloatrange( -20, 20 ) ); + self dodamage( self.health + 666, self.origin + death_from ); +#/ +} + +zombie_devgui_toggle_ammo() +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + self notify( "devgui_toggle_ammo" ); + self endon( "devgui_toggle_ammo" ); + self.ammo4evah = !is_true( self.ammo4evah ); + while ( isDefined( self ) && self.ammo4evah ) + { + weapon = self getcurrentweapon(); + if ( weapon != "none" ) + { + self setweaponoverheating( 0, 0 ); + max = weaponmaxammo( weapon ); + if ( isDefined( max ) ) + { + self setweaponammostock( weapon, max ); + } + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self givemaxammo( self get_player_tactical_grenade() ); + } + if ( isDefined( self get_player_lethal_grenade() ) ) + { + self givemaxammo( self get_player_lethal_grenade() ); + } + } + wait 1; +#/ + } +} + +zombie_devgui_toggle_ignore() +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + self.ignoreme = !self.ignoreme; + if ( self.ignoreme ) + { + setdvar( "ai_showFailedPaths", 0 ); +#/ + } +} + +zombie_devgui_revive() +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + self reviveplayer(); + self notify( "stop_revive_trigger" ); + if ( isDefined( self.revivetrigger ) ) + { + self.revivetrigger delete(); + self.revivetrigger = undefined; + } + self allowjump( 1 ); + self.ignoreme = 0; + self.laststand = undefined; + self notify( "player_revived" ); +#/ +} + +zombie_devgui_give_health() +{ +/# + assert( isDefined( self ) ); + assert( isplayer( self ) ); + assert( isalive( self ) ); + self notify( "devgui_health" ); + self endon( "devgui_health" ); + self endon( "disconnect" ); + self endon( "death" ); + level.devcheater = 1; + while ( 1 ) + { + self.maxhealth = 100000; + self.health = 100000; + self waittill_any( "player_revived", "perk_used", "spawned_player" ); + wait 2; +#/ + } +} + +zombie_devgui_give_perk( perk ) +{ +/# + vending_triggers = getentarray( "zombie_vending", "targetname" ); + player = get_players()[ 0 ]; + level.devcheater = 1; + if ( vending_triggers.size < 1 ) + { + return; + } + i = 0; + while ( i < vending_triggers.size ) + { + if ( vending_triggers[ i ].script_noteworthy == perk ) + { + vending_triggers[ i ] notify( "trigger" ); + return; + } + i++; +#/ + } +} + +zombie_devgui_give_powerup( powerup_name, now, origin ) +{ +/# + player = get_players()[ 0 ]; + found = 0; + level.devcheater = 1; + i = 0; + while ( i < level.zombie_powerup_array.size ) + { + if ( level.zombie_powerup_array[ i ] == powerup_name ) + { + level.zombie_powerup_index = i; + found = 1; + break; + } + else + { + i++; + } + } + if ( !found ) + { + return; + } + direction = player getplayerangles(); + direction_vec = anglesToForward( direction ); + eye = player geteye(); + scale = 8000; + direction_vec = ( direction_vec[ 0 ] * scale, direction_vec[ 1 ] * scale, direction_vec[ 2 ] * scale ); + trace = bullettrace( eye, eye + direction_vec, 0, undefined ); + level.zombie_devgui_power = 1; + level.zombie_vars[ "zombie_drop_item" ] = 1; + level.powerup_drop_count = 0; + if ( isDefined( origin ) ) + { + level thread maps/mp/zombies/_zm_powerups::powerup_drop( origin ); + } + else + { + if ( !isDefined( now ) || now ) + { + level thread maps/mp/zombies/_zm_powerups::powerup_drop( trace[ "position" ] ); +#/ + } + } +} + +zombie_devgui_goto_round( target_round ) +{ +/# + player = get_players()[ 0 ]; + if ( target_round < 1 ) + { + target_round = 1; + } + level.devcheater = 1; + level.zombie_total = 0; + maps/mp/zombies/_zm::ai_calculate_health( target_round ); + level.round_number = target_round - 1; + level notify( "kill_round" ); + wait 1; + zombies = get_round_enemy_array(); + while ( isDefined( zombies ) ) + { + i = 0; + while ( i < zombies.size ) + { + if ( is_true( zombies[ i ].ignore_devgui_death ) ) + { + i++; + continue; + } + else + { + zombies[ i ] dodamage( zombies[ i ].health + 666, zombies[ i ].origin ); + } + i++; +#/ + } + } +} + +zombie_devgui_monkey_round() +{ +/# + if ( isDefined( level.next_monkey_round ) ) + { + zombie_devgui_goto_round( level.next_monkey_round ); +#/ + } +} + +zombie_devgui_thief_round() +{ +/# + if ( isDefined( level.next_thief_round ) ) + { + zombie_devgui_goto_round( level.next_thief_round ); +#/ + } +} + +zombie_devgui_dog_round( num_dogs ) +{ +/# + if ( !isDefined( level.dogs_enabled ) || !level.dogs_enabled ) + { + return; + } + if ( !isDefined( level.dog_rounds_enabled ) || !level.dog_rounds_enabled ) + { + return; + } + if ( !isDefined( level.enemy_dog_spawns ) || level.enemy_dog_spawns.size < 1 ) + { + return; + } + if ( !flag( "dog_round" ) ) + { + setdvar( "force_dogs", num_dogs ); + } + zombie_devgui_goto_round( level.round_number + 1 ); +#/ +} + +zombie_devgui_dog_round_skip() +{ +/# + if ( isDefined( level.next_dog_round ) ) + { + zombie_devgui_goto_round( level.next_dog_round ); +#/ + } +} + +zombie_devgui_dump_zombie_vars() +{ +/# + if ( !isDefined( level.zombie_vars ) ) + { + return; + } + if ( level.zombie_vars.size > 0 ) + { + println( "#### Zombie Variables ####" ); + } + else + { + return; + } + var_names = getarraykeys( level.zombie_vars ); + i = 0; + while ( i < level.zombie_vars.size ) + { + key = var_names[ i ]; + println( ( key + ": " ) + level.zombie_vars[ key ] ); + i++; + } + println( "##### End Zombie Variables #####" ); +#/ +} + +zombie_devgui_pack_current_weapon() +{ +/# + players = get_players(); + reviver = players[ 0 ]; + level.devcheater = 1; + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + weap = maps/mp/zombies/_zm_weapons::get_base_name( players[ i ] getcurrentweapon() ); + weapon = get_upgrade( weap ); + if ( isDefined( weapon ) ) + { + players[ i ] takeweapon( weap ); + players[ i ] giveweapon( weapon, 0, players[ i ] maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); + players[ i ] givestartammo( weapon ); + players[ i ] switchtoweapon( weapon ); + } + } + i++; +#/ + } +} + +zombie_devgui_unpack_current_weapon() +{ +/# + players = get_players(); + reviver = players[ 0 ]; + level.devcheater = 1; + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + weap = players[ i ] getcurrentweapon(); + weapon = maps/mp/zombies/_zm_weapons::get_base_weapon_name( weap, 1 ); + if ( isDefined( weapon ) ) + { + players[ i ] takeweapon( weap ); + players[ i ] giveweapon( weapon, 0, players[ i ] maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); + players[ i ] givestartammo( weapon ); + players[ i ] switchtoweapon( weapon ); + } + } + i++; +#/ + } +} + +zombie_devgui_reopt_current_weapon() +{ +/# + players = get_players(); + reviver = players[ 0 ]; + level.devcheater = 1; + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + weap = players[ i ] getcurrentweapon(); + weapon = weap; + if ( isDefined( weapon ) ) + { + if ( isDefined( players[ i ].pack_a_punch_weapon_options ) ) + { + } + players[ i ] takeweapon( weap ); + players[ i ] giveweapon( weapon, 0, players[ i ] maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); + players[ i ] givestartammo( weapon ); + players[ i ] switchtoweapon( weapon ); + } + } + i++; +#/ + } +} + +zombie_devgui_take_weapon() +{ +/# + players = get_players(); + reviver = players[ 0 ]; + level.devcheater = 1; + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + weap = players[ i ] getcurrentweapon(); + weapon = weap; + if ( isDefined( weapon ) ) + { + players[ i ] takeweapon( weap ); + players[ i ] switch_back_primary_weapon( undefined ); + } + } + i++; +#/ + } +} + +zombie_devgui_take_weapons( give_fallback ) +{ +/# + players = get_players(); + reviver = players[ 0 ]; + level.devcheater = 1; + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + players[ i ] takeallweapons(); + if ( give_fallback ) + { + players[ i ] give_fallback_weapon(); + } + } + i++; +#/ + } +} + +get_upgrade( weaponname ) +{ +/# + if ( isDefined( level.zombie_weapons[ weaponname ] ) && isDefined( level.zombie_weapons[ weaponname ].upgrade_name ) ) + { + return maps/mp/zombies/_zm_weapons::get_upgrade_weapon( weaponname, 0 ); + } + else + { + return maps/mp/zombies/_zm_weapons::get_upgrade_weapon( weaponname, 1 ); +#/ + } +} + +zombie_devgui_director_easy() +{ +/# + if ( isDefined( level.director_devgui_health ) ) + { + [[ level.director_devgui_health ]](); +#/ + } +} + +zombie_devgui_chest_never_move() +{ +/# + level notify( "devgui_chest_end_monitor" ); + level endon( "devgui_chest_end_monitor" ); + for ( ;; ) + { + level.chest_accessed = 0; + wait 5; +#/ + } +} + +zombie_devgui_disable_kill_thread_toggle() +{ +/# + if ( !is_true( level.disable_kill_thread ) ) + { + level.disable_kill_thread = 1; + } + else + { + level.disable_kill_thread = 0; +#/ + } +} + +zombie_devgui_check_kill_thread_every_frame_toggle() +{ +/# + if ( !is_true( level.check_kill_thread_every_frame ) ) + { + level.check_kill_thread_every_frame = 1; + } + else + { + level.check_kill_thread_every_frame = 0; +#/ + } +} + +zombie_devgui_kill_thread_test_mode_toggle() +{ +/# + if ( !is_true( level.kill_thread_test_mode ) ) + { + level.kill_thread_test_mode = 1; + } + else + { + level.kill_thread_test_mode = 0; +#/ + } +} + +showonespawnpoint( spawn_point, color, notification, height, print ) +{ +/# + if ( !isDefined( height ) || height <= 0 ) + { + height = get_player_height(); + } + if ( !isDefined( print ) ) + { + print = spawn_point.classname; + } + center = spawn_point.origin; + forward = anglesToForward( spawn_point.angles ); + right = anglesToRight( spawn_point.angles ); + forward = vectorScale( forward, 16 ); + right = vectorScale( right, 16 ); + a = ( center + forward ) - right; + b = center + forward + right; + c = ( center - forward ) + right; + d = center - forward - right; + thread lineuntilnotified( a, b, color, 0, notification ); + thread lineuntilnotified( b, c, color, 0, notification ); + thread lineuntilnotified( c, d, color, 0, notification ); + thread lineuntilnotified( d, a, color, 0, notification ); + thread lineuntilnotified( a, a + ( 0, 0, height ), color, 0, notification ); + thread lineuntilnotified( b, b + ( 0, 0, height ), color, 0, notification ); + thread lineuntilnotified( c, c + ( 0, 0, height ), color, 0, notification ); + thread lineuntilnotified( d, d + ( 0, 0, height ), color, 0, notification ); + a += ( 0, 0, height ); + b += ( 0, 0, height ); + c += ( 0, 0, height ); + d += ( 0, 0, height ); + thread lineuntilnotified( a, b, color, 0, notification ); + thread lineuntilnotified( b, c, color, 0, notification ); + thread lineuntilnotified( c, d, color, 0, notification ); + thread lineuntilnotified( d, a, color, 0, notification ); + center += ( 0, 0, height / 2 ); + arrow_forward = anglesToForward( spawn_point.angles ); + arrowhead_forward = anglesToForward( spawn_point.angles ); + arrowhead_right = anglesToRight( spawn_point.angles ); + arrow_forward = vectorScale( arrow_forward, 32 ); + arrowhead_forward = vectorScale( arrowhead_forward, 24 ); + arrowhead_right = vectorScale( arrowhead_right, 8 ); + a = center + arrow_forward; + b = ( center + arrowhead_forward ) - arrowhead_right; + c = center + arrowhead_forward + arrowhead_right; + thread lineuntilnotified( center, a, color, 0, notification ); + thread lineuntilnotified( a, b, color, 0, notification ); + thread lineuntilnotified( a, c, color, 0, notification ); + thread print3duntilnotified( spawn_point.origin + ( 0, 0, height ), print, color, 1, 1, notification ); + return; +#/ +} + +print3duntilnotified( origin, text, color, alpha, scale, notification ) +{ +/# + level endon( notification ); + for ( ;; ) + { + print3d( origin, text, color, alpha, scale ); + wait 0,05; +#/ + } +} + +lineuntilnotified( start, end, color, depthtest, notification ) +{ +/# + level endon( notification ); + for ( ;; ) + { + line( start, end, color, depthtest ); + wait 0,05; +#/ + } +} + +devgui_debug_hud() +{ +/# + if ( isDefined( self get_player_lethal_grenade() ) ) + { + self givemaxammo( self get_player_lethal_grenade() ); + } + self thread maps/mp/zombies/_zm_weap_claymore::claymore_setup(); + if ( isDefined( level.zombiemode_time_bomb_give_func ) ) + { + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + self [[ level.zombiemode_time_bomb_give_func ]](); + } + else if ( isDefined( level.zombiemode_devgui_cymbal_monkey_give ) ) + { + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self takeweapon( self get_player_tactical_grenade() ); + } + self [[ level.zombiemode_devgui_cymbal_monkey_give ]](); + } + else + { + if ( isDefined( self get_player_tactical_grenade() ) ) + { + self givemaxammo( self get_player_tactical_grenade() ); + } + } + if ( isDefined( level.zombie_include_equipment ) && !isDefined( self get_player_equipment() ) ) + { + equipment = getarraykeys( level.zombie_include_equipment ); + if ( isDefined( equipment[ 0 ] ) ) + { + self zombie_devgui_equipment_give( equipment[ 0 ] ); + } + } + candidate_list = []; + _a2327 = level.zones; + _k2327 = getFirstArrayKey( _a2327 ); + while ( isDefined( _k2327 ) ) + { + zone = _a2327[ _k2327 ]; + if ( isDefined( zone.unitrigger_stubs ) ) + { + candidate_list = arraycombine( candidate_list, zone.unitrigger_stubs, 1, 0 ); + } + _k2327 = getNextArrayKey( _a2327, _k2327 ); + } + _a2335 = candidate_list; + _k2335 = getFirstArrayKey( _a2335 ); + while ( isDefined( _k2335 ) ) + { + stub = _a2335[ _k2335 ]; + if ( isDefined( stub.piece ) && isDefined( stub.piece.buildable_slot ) ) + { + if ( !isDefined( self player_get_buildable_piece( stub.piece.buildable_slot ) ) ) + { + self thread maps/mp/zombies/_zm_buildables::player_take_piece( stub.piece ); + } + } + _k2335 = getNextArrayKey( _a2335, _k2335 ); + } + i = 0; + while ( i < 10 ) + { + zombie_devgui_give_powerup( "free_perk", 1, self.origin ); + wait 0,25; + i++; + } + zombie_devgui_give_powerup( "insta_kill", 1, self.origin ); + wait 0,25; + zombie_devgui_give_powerup( "double_points", 1, self.origin ); + wait 0,25; + zombie_devgui_give_powerup( "fire_sale", 1, self.origin ); + wait 0,25; + zombie_devgui_give_powerup( "minigun", 1, self.origin ); + wait 0,25; + zombie_devgui_give_powerup( "bonfire_sale", 1, self.origin ); + wait 0,25; + self weapon_give( "tar21_upgraded_zm+gl" ); +#/ +} diff --git a/patch_zm/maps/mp/zombies/_zm_equip_turbine.gsc b/patch_zm/maps/mp/zombies/_zm_equip_turbine.gsc new file mode 100644 index 0000000..01cc67c --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_equip_turbine.gsc @@ -0,0 +1,789 @@ +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_power; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zombie_turbine" ); + +init( hint, howto ) +{ + if ( !isDefined( hint ) ) + { + hint = &"ZOMBIE_EQUIP_TURBINE_PICKUP_HINT_STRING"; + } + if ( !isDefined( howto ) ) + { + howto = &"ZOMBIE_EQUIP_TURBINE_HOWTO"; + } + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_turbine_zm" ) ) + { + return; + } + level.turbine_name = "equip_turbine_zm"; + maps/mp/zombies/_zm_equipment::register_equipment( "equip_turbine_zm", hint, howto, "turbine_zm_icon", "turbine", undefined, ::transferturbine, ::dropturbine, ::pickupturbine, ::placeturbine ); + maps/mp/zombies/_zm_equipment::add_placeable_equipment( "equip_turbine_zm", "p6_anim_zm_buildable_turbine", ::destroy_placed_turbine ); + level thread onplayerconnect(); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "equip_turbine", hint ); + level._effect[ "turbine_on" ] = loadfx( "maps/zombie/fx_zmb_tranzit_wind_turbine_on" ); + level._effect[ "turbine_med" ] = loadfx( "maps/zombie/fx_zmb_tranzit_wind_turbine_med" ); + level._effect[ "turbine_low" ] = loadfx( "maps/zombie/fx_zmb_tranzit_wind_turbine_low" ); + level._effect[ "turbine_aoe" ] = loadfx( "maps/zombie/fx_zmb_tranzit_wind_turbine_aoe" ); + level._turbine_disappear_fx = loadfx( "maps/zombie/fx_zmb_tranzit_turbine_explo" ); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread onplayerspawned(); + } +} + +onplayerspawned() +{ + self endon( "disconnect" ); + self thread setupwatchers(); + for ( ;; ) + { + self waittill( "spawned_player" ); + self thread watchturbineuse(); + } +} + +setupwatchers() +{ + self waittill( "weapon_watchers_created" ); + watcher = maps/mp/gametypes_zm/_weaponobjects::getweaponobjectwatcher( "equip_turbine" ); + watcher.onspawnretrievetriggers = ::maps/mp/zombies/_zm_equipment::equipment_onspawnretrievableweaponobject; +} + +watchturbineuse() +{ + self notify( "watchTurbineUse" ); + self endon( "watchTurbineUse" ); + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "equipment_placed", weapon, weapname ); + if ( weapname == level.turbine_name ) + { + self cleanupoldturbine(); + self.buildableturbine = weapon; + self thread startturbinedeploy( weapon ); + level notify( "turbine_deployed" ); + } + } +} + +cleanupoldturbine( preserve_state ) +{ + if ( isDefined( self.localpower ) ) + { + maps/mp/zombies/_zm_power::end_local_power( self.localpower ); + self notify( "depower_on_disconnect" ); + self.localpower = undefined; + self.turbine_power_is_on = 0; + } + self.turbine_is_powering_on = 0; + if ( isDefined( self.buildableturbine ) ) + { + if ( isDefined( self.buildableturbine.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildableturbine.stub ); + self.buildableturbine.stub = undefined; + } + self.buildableturbine stoploopsound(); + self.buildableturbine delete(); + if ( isDefined( preserve_state ) && !preserve_state ) + { + self.turbine_health = undefined; + self.turbine_emped = undefined; + self.turbine_emp_time = undefined; + } + } +} + +watchforcleanup() +{ + self notify( "turbine_cleanup" ); + self endon( "turbine_cleanup" ); + evt = self waittill_any_return( "death_or_disconnect", "equip_turbine_zm_taken", "equip_turbine_zm_pickup" ); + if ( isDefined( self ) ) + { + self cleanupoldturbine( evt == "equip_turbine_zm_pickup" ); + } +} + +depower_on_disconnect( localpower ) +{ + self notify( "depower_on_disconnect" ); + self endon( "depower_on_disconnect" ); + self waittill( "disconnect" ); + if ( isDefined( localpower ) ) + { + maps/mp/zombies/_zm_power::end_local_power( localpower ); + } +} + +placeturbine( origin, angles ) +{ + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "p6_anim_zm_buildable_turbine", "equip_turbine_zm", origin, angles ); + return item; +} + +dropturbine() +{ + item = thread maps/mp/zombies/_zm_equipment::dropped_equipment_think( "p6_anim_zm_buildable_turbine", "equip_turbine_zm", self.origin, self.angles ); + if ( isDefined( item ) ) + { + item.turbine_power_on = self.turbine_power_on; + item.turbine_power_level = self.turbine_power_level; + item.turbine_round_start = self.turbine_round_start; + item.turbine_health = self.turbine_health; + item.turbine_emped = self.turbine_emped; + item.turbine_emp_time = self.turbine_emp_time; + } + self.turbine_is_powering_on = undefined; + self.turbine_power_on = undefined; + self.turbine_power_level = undefined; + self.turbine_round_start = undefined; + self.turbine_health = undefined; + self.turbine_emped = undefined; + self.turbine_emp_time = undefined; + return item; +} + +pickupturbine( item ) +{ + item.owner = self; + self.turbine_power_on = item.turbine_power_on; + item.turbine_power_on = undefined; + self.turbine_power_level = item.turbine_power_level; + self.turbine_round_start = item.turbine_round_start; + self.turbine_health = item.turbine_health; + item.turbine_health = undefined; + item.turbine_power_level = undefined; + item.turbine_round_start = undefined; + self.turbine_emped = item.turbine_emped; + self.turbine_emp_time = item.turbine_emp_time; + item.turbine_emped = undefined; + item.turbine_emp_time = undefined; + self.turbine_is_powering_on = undefined; +} + +transferturbine( fromplayer, toplayer ) +{ + while ( isDefined( toplayer.turbine_is_powering_on ) || toplayer.turbine_is_powering_on && isDefined( fromplayer.turbine_is_powering_on ) && fromplayer.turbine_is_powering_on ) + { + wait 0,05; + } + if ( isDefined( fromplayer.buildableturbine ) && isDefined( fromplayer.buildableturbine.dying ) && fromplayer.buildableturbine.dying ) + { + fromplayer cleanupoldturbine( 0 ); + } + if ( isDefined( toplayer.buildableturbine ) && isDefined( toplayer.buildableturbine.dying ) && toplayer.buildableturbine.dying ) + { + toplayer cleanupoldturbine( 0 ); + } + buildableturbine = toplayer.buildableturbine; + localpower = toplayer.localpower; + turbine_power_on = toplayer.turbine_power_on; + turbine_power_is_on = toplayer.turbine_power_is_on; + turbine_power_level = toplayer.turbine_power_level; + turbine_round_start = toplayer.turbine_round_start; + turbine_health = toplayer.turbine_health; + turbine_emped = toplayer.turbine_emped; + turbine_emp_time = toplayer.turbine_emp_time; + toplayer.buildableturbine = fromplayer.buildableturbine; + fromplayer.buildableturbine = buildableturbine; + toplayer.localpower = fromplayer.localpower; + fromplayer.localpower = localpower; + toplayer.turbine_power_on = fromplayer.turbine_power_on; + fromplayer.turbine_power_on = turbine_power_on; + toplayer.turbine_power_is_on = fromplayer.turbine_power_is_on; + fromplayer.turbine_power_is_on = turbine_power_is_on; + toplayer.turbine_power_level = fromplayer.turbine_power_level; + toplayer.turbine_round_start = fromplayer.turbine_round_start; + fromplayer.turbine_power_level = turbine_power_level; + fromplayer.turbine_round_start = turbine_round_start; + toplayer.turbine_health = fromplayer.turbine_health; + fromplayer.turbine_health = turbine_health; + toplayer.turbine_emped = fromplayer.turbine_emped; + fromplayer.turbine_emped = turbine_emped; + toplayer.turbine_emp_time = fromplayer.turbine_emp_time; + fromplayer.turbine_emp_time = turbine_emp_time; + toplayer.turbine_is_powering_on = undefined; + fromplayer.turbine_is_powering_on = undefined; + toplayer notify( "equip_turbine_zm_taken" ); + toplayer.buildableturbine.original_owner = toplayer; + toplayer thread startturbinedeploy( toplayer.buildableturbine ); + fromplayer notify( "equip_turbine_zm_taken" ); + if ( isDefined( fromplayer.buildableturbine ) ) + { + fromplayer thread startturbinedeploy( fromplayer.buildableturbine ); + fromplayer.buildableturbine.original_owner = fromplayer; + fromplayer.buildableturbine.owner = fromplayer; + } + else + { + fromplayer maps/mp/zombies/_zm_equipment::equipment_release( "equip_turbine_zm" ); + } +} + +startturbinedeploy( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self thread watchforcleanup(); + origin = weapon.origin; + powerradius = 335; + if ( !isDefined( self.turbine_health ) ) + { + self.turbine_health = 1200; + self.turbine_power_level = 4; + self.turbine_power_on = 1; + self.turbine_is_powering_on = undefined; + } + if ( !isDefined( self.turbine_round_start ) ) + { + self.turbine_round_start = level.round_number; + self.turbine_power_on = 1; + } + self thread turbinedecay(); + self thread turbinepowerdiminish( origin, powerradius ); + if ( isDefined( weapon ) ) + { +/# + self thread debugturbine( powerradius ); +#/ + self thread turbineaudio(); + self thread turbineanim(); + self thread turbinepowerthink( weapon, powerradius ); + if ( isDefined( weapon.equipment_can_move ) && weapon.equipment_can_move ) + { + self thread turbinepowermove( weapon ); + } + self thread maps/mp/zombies/_zm_buildables::delete_on_disconnect( weapon ); + weapon waittill( "death" ); + self thread turbinepoweroff( origin, powerradius ); + self notify( "turbine_cleanup" ); + } +} + +turbine_watch_for_emp( weapon, powerradius ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self.buildableturbine endon( "death" ); + if ( !should_watch_for_emp() ) + { + return; + } + while ( 1 ) + { + level waittill( "emp_detonate", origin, radius ); + if ( distancesquared( origin, self.buildableturbine.origin ) < ( radius * radius ) ) + { + break; + } + else + { + } + } + self.turbine_emped = 1; + self.turbine_emp_time = getTime(); + self notify( "turbine_power_change" ); +} + +turbinepowerthink( weapon, powerradius ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self.buildableturbine endon( "death" ); + origin = weapon.origin; + self thread turbine_watch_for_emp( weapon, powerradius ); + if ( isDefined( self.turbine_power_on ) || self.turbine_power_on && isDefined( self.turbine_emped ) && self.turbine_emped ) + { + self thread turbinepoweron( origin, powerradius ); + } + while ( isDefined( self.buildableturbine ) ) + { + self waittill( "turbine_power_change" ); + if ( isDefined( self.turbine_emped ) && self.turbine_emped ) + { + self thread turbinepoweroff( origin, powerradius ); + if ( isDefined( weapon ) ) + { + origin = weapon.origin; + } + self thread turbinepoweron( origin, powerradius ); + continue; + } + else + { + if ( isDefined( self.turbine_power_is_on ) && !self.turbine_power_is_on ) + { + self thread turbinepoweroff( origin, powerradius ); + break; + } + else + { + if ( isDefined( weapon ) ) + { + origin = weapon.origin; + } + self thread turbinepoweron( origin, powerradius ); + } + } + } +} + +turbinepowermove( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self.buildableturbine endon( "death" ); + origin = weapon.origin; + while ( 1 ) + { + if ( origin != weapon.origin ) + { + if ( isDefined( self.localpower ) ) + { + self.localpower = maps/mp/zombies/_zm_power::move_local_power( self.localpower, origin ); + } + origin = weapon.origin; + } + wait 0,5; + } +} + +turbinewarmup() +{ + if ( isDefined( self.turbine_emped ) && self.turbine_emped ) + { + emp_time = level.zombie_vars[ "emp_perk_off_time" ]; + now = getTime(); + emp_time_left = emp_time - ( ( now - self.turbine_emp_time ) / 1000 ); + if ( emp_time_left > 0 ) + { + wait emp_time_left; + } + self.turbine_emped = undefined; + self.turbine_emp_time = undefined; + } + self.buildableturbine maps/mp/zombies/_zm_equipment::signal_equipment_activated( 3 ); + wait 0,5; + self.buildableturbine maps/mp/zombies/_zm_equipment::signal_equipment_activated( 2 ); + wait 0,5; + self.buildableturbine maps/mp/zombies/_zm_equipment::signal_equipment_activated( 1 ); + wait 0,5; +} + +turbinepoweron( origin, powerradius ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self.buildableturbine endon( "death" ); + if ( isDefined( self.turbine_power_is_on ) && !self.turbine_power_is_on && isDefined( self.turbine_is_powering_on ) && !self.turbine_is_powering_on && isDefined( self.buildableturbine.dying ) && !self.buildableturbine.dying ) + { + self.turbine_is_powering_on = 1; + self.buildableturbine playloopsound( "zmb_turbine_loop", 2 ); + self turbinewarmup(); + if ( isDefined( self.localpower ) ) + { + maps/mp/zombies/_zm_power::end_local_power( self.localpower ); + } + self.localpower = undefined; + self.turbine_power_is_on = 0; + if ( isDefined( self.turbine_emped ) && !self.turbine_emped ) + { + self.localpower = maps/mp/zombies/_zm_power::add_local_power( origin, powerradius ); + self thread depower_on_disconnect( self.localpower ); + self.turbine_power_is_on = 1; + self thread turbineaudio(); + } + self.turbine_is_powering_on = 0; + self thread turbinefx(); + self thread turbinedecay(); + } +} + +turbinepoweroff( origin, powerradius ) +{ + if ( isDefined( self.turbine_power_is_on ) && self.turbine_power_is_on ) + { + if ( isDefined( self.localpower ) ) + { + maps/mp/zombies/_zm_power::end_local_power( self.localpower ); + } + self notify( "depower_on_disconnect" ); + self.localpower = undefined; + self.turbine_power_is_on = 0; + self thread turbineaudio(); + if ( isDefined( self.buildableturbine.dying ) && !self.buildableturbine.dying ) + { + self thread turbineanim(); + } + } +} + +turbine_disappear_fx( origin, waittime ) +{ + if ( isDefined( waittime ) && waittime > 0 ) + { + wait waittime; + } + playfx( level._turbine_disappear_fx, origin ); + if ( isDefined( self.buildableturbine ) ) + { + playsoundatposition( "zmb_turbine_explo", self.buildableturbine.origin ); + } +} + +turbinefxonce( withaoe ) +{ + if ( isDefined( self ) && isDefined( self.buildableturbine ) && isDefined( self.turbine_power_is_on ) && self.turbine_power_is_on ) + { + value = 0; + switch( self.turbine_power_level ) + { + case 3: + case 4: + value = 1; + break; + case 2: + value = 2; + break; + case 1: + value = 3; + break; + } + if ( withaoe ) + { + if ( isDefined( self.buildableturbine.equipment_can_move ) && self.buildableturbine.equipment_can_move && isDefined( self.buildableturbine.move_parent.ismoving ) && self.buildableturbine.move_parent.ismoving ) + { + value |= 4; + } + else + { + value |= 8; + } + } + if ( value && isDefined( self.buildableturbine ) && isDefined( self.turbine_power_is_on ) && self.turbine_power_is_on ) + { + self.buildableturbine thread maps/mp/zombies/_zm_equipment::signal_equipment_activated( value ); + } + } +} + +turbinefx() +{ + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + while ( isDefined( self ) && isDefined( self.buildableturbine ) && isDefined( self.turbine_power_is_on ) && self.turbine_power_is_on ) + { + self turbinefxonce( 1 ); + wait 0,5; + self turbinefxonce( 0 ); + wait 0,5; + } +} + +turbineaudio() +{ + if ( !isDefined( self.buildableturbine ) ) + { + return; + } + if ( isDefined( self.turbine_power_is_on ) || !self.turbine_power_is_on && isDefined( self.turbine_emped ) && self.turbine_emped ) + { + self.buildableturbine stoploopsound(); + return; + } + self.buildableturbine playloopsound( "zmb_turbine_loop", 2 ); +} + +init_animtree() +{ + scriptmodelsuseanimtree( -1 ); +} + +turbineanim( wait_for_end ) +{ + if ( !isDefined( self.buildableturbine ) ) + { + return; + } + animlength = 0; + self.buildableturbine useanimtree( -1 ); + if ( isDefined( self.buildableturbine.dying ) && self.buildableturbine.dying ) + { + animlength = getanimlength( %o_zombie_buildable_turbine_death ); + self.buildableturbine setanim( %o_zombie_buildable_turbine_death ); + break; +} +else +{ + if ( isDefined( self.turbine_emped ) && self.turbine_emped ) + { + self.buildableturbine clearanim( %o_zombie_buildable_turbine_fullpower, 0 ); + return; + break; +} +else +{ + switch( self.turbine_power_level ) + { + case 3: + case 4: + animlength = getanimlength( %o_zombie_buildable_turbine_fullpower ); + self.buildableturbine setanim( %o_zombie_buildable_turbine_fullpower ); + break; + case 2: + animlength = getanimlength( %o_zombie_buildable_turbine_halfpower ); + self.buildableturbine setanim( %o_zombie_buildable_turbine_halfpower ); + break; + case 1: + animlength = getanimlength( %o_zombie_buildable_turbine_neardeath ); + self.buildableturbine setanim( %o_zombie_buildable_turbine_neardeath ); + break; + } +} +} +if ( isDefined( wait_for_end ) && wait_for_end ) +{ +wait animlength; +} +} + +turbinedecay() +{ + self notify( "turbineDecay" ); + self endon( "turbineDecay" ); + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self.buildableturbine endon( "death" ); + roundlives = 4; + if ( !isDefined( self.turbine_power_level ) ) + { + self.turbine_power_level = roundlives; + } + while ( self.turbine_health > 0 ) + { + old_power_level = self.turbine_power_level; + if ( isDefined( self.turbine_emped ) && self.turbine_emped && isDefined( self.turbine_is_powering_on ) && self.turbine_is_powering_on ) + { + emp_time = level.zombie_vars[ "emp_perk_off_time" ]; + now = getTime(); + emp_time_left = emp_time - ( ( now - self.turbine_emp_time ) / 1000 ); + if ( emp_time_left <= 0 ) + { + self.turbine_emped = undefined; + self.turbine_emp_time = undefined; + self.turbine_power_is_on = 0; + old_power_level = -1; + } + } + if ( isDefined( self.turbine_emped ) && self.turbine_emped ) + { + self.turbine_power_level = 0; + } + else + { + if ( isDefined( self.turbine_power_is_on ) && self.turbine_power_is_on ) + { + cost = 1; + if ( isDefined( self.localpower ) ) + { + cost += maps/mp/zombies/_zm_power::get_local_power_cost( self.localpower ); + } + self.turbine_health -= cost; + if ( self.turbine_health < 200 ) + { + self.turbine_power_level = 1; + break; + } + else if ( self.turbine_health < 600 ) + { + self.turbine_power_level = 2; + break; + } + else + { + self.turbine_power_level = 4; + } + } + } + if ( old_power_level != self.turbine_power_level ) + { + self notify( "turbine_power_change" ); + self thread turbineaudio(); + if ( isDefined( self.buildableturbine.dying ) && !self.buildableturbine.dying ) + { + self thread turbineanim(); + } + } + wait 1; + } + self destroy_placed_turbine(); + if ( isDefined( self.buildableturbine ) ) + { + turbine_disappear_fx( self.buildableturbine.origin ); + } + self thread wait_and_take_equipment(); + self.turbine_health = undefined; + self.turbine_power_level = undefined; + self.turbine_round_start = undefined; + self.turbine_power_on = undefined; + self.turbine_emped = undefined; + self.turbine_emp_time = undefined; + self cleanupoldturbine(); +} + +destroy_placed_turbine() +{ + if ( isDefined( self.buildableturbine ) ) + { + if ( isDefined( self.buildableturbine.dying ) && self.buildableturbine.dying ) + { + while ( isDefined( self.buildableturbine ) ) + { + wait 0,05; + } + return; + } + if ( isDefined( self.buildableturbine.stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.buildableturbine.stub ); + } + thread turbine_disappear_fx( self.buildableturbine.origin, 0,75 ); + self.buildableturbine.dying = 1; + self turbineanim( 1 ); + } +} + +wait_and_take_equipment() +{ + wait 0,05; + self thread maps/mp/zombies/_zm_equipment::equipment_release( "equip_turbine_zm" ); +} + +turbinepowerdiminish( origin, powerradius ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self.buildableturbine endon( "death" ); + while ( isDefined( self.buildableturbine.dying ) && !self.buildableturbine.dying ) + { + if ( isDefined( self.turbine_power_level ) && isDefined( self.buildableturbine ) ) + { + switch( self.turbine_power_level ) + { + case 4: + break; + case 3: + case 2: + self.turbine_power_on = 1; + wait randomintrange( 12, 20 ); + self turbinepoweroff( origin, powerradius ); + self.turbine_power_on = 0; + wait randomintrange( 3, 8 ); + self turbinepoweron( origin, powerradius ); + break; + case 1: + self.turbine_power_on = 1; + wait randomintrange( 3, 7 ); + self turbinepoweroff( origin, powerradius ); + self.turbine_power_on = 0; + wait randomintrange( 6, 12 ); + self turbinepoweron( origin, powerradius ); + break; + } + } + wait 0,05; + } + } +} + +debugturbine( radius ) +{ +/# + self endon( "death" ); + self endon( "disconnect" ); + self endon( "equip_turbine_zm_taken" ); + self.buildableturbine endon( "death" ); + while ( isDefined( self.buildableturbine ) ) + { + if ( getDvarInt( #"EB512CB7" ) ) + { + color = ( 0, 0, 1 ); + text = ""; + if ( isDefined( self.turbine_health ) ) + { + text = "" + self.turbine_health + ""; + } + if ( isDefined( self.buildableturbine.dying ) && self.buildableturbine.dying ) + { + text = "dying"; + color = ( 0, 0, 1 ); + } + else + { + if ( isDefined( self.turbine_emped ) && self.turbine_emped ) + { + color = ( 0, 0, 1 ); + emp_time = level.zombie_vars[ "emp_perk_off_time" ]; + now = getTime(); + emp_time_left = int( emp_time - ( ( now - self.turbine_emp_time ) / 1000 ) ); + text = ( text + " emp(" ) + emp_time_left + ")"; + break; + } + else + { + if ( isDefined( self.turbine_is_powering_on ) && self.turbine_is_powering_on ) + { + text += " warmup"; + break; + } + else + { + if ( isDefined( self.turbine_power_is_on ) && self.turbine_power_is_on ) + { + if ( self.turbine_health < 200 ) + { + color = ( 0, 0, 1 ); + break; + } + else if ( self.turbine_health < 600 ) + { + color = ( 1, 0,7, 0 ); + break; + } + else + { + color = ( 0, 0, 1 ); + } + } + } + } + } + print3d( self.buildableturbine.origin + vectorScale( ( 0, 0, 1 ), 60 ), text, color, 1, 0,5, 1 ); + } + wait 0,05; +#/ + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_game_module.gsc b/patch_zm/maps/mp/zombies/_zm_game_module.gsc new file mode 100644 index 0000000..07e1d1c --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_game_module.gsc @@ -0,0 +1,491 @@ +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +register_game_module( index, module_name, pre_init_func, post_init_func, pre_init_zombie_spawn_func, post_init_zombie_spawn_func, hub_start_func ) +{ + if ( !isDefined( level._game_modules ) ) + { + level._game_modules = []; + level._num_registered_game_modules = 0; + } + i = 0; + while ( i < level._num_registered_game_modules ) + { + if ( !isDefined( level._game_modules[ i ] ) ) + { + i++; + continue; + } + else + { + if ( isDefined( level._game_modules[ i ].index ) && level._game_modules[ i ].index == index ) + { +/# + assert( level._game_modules[ i ].index != index, "A Game module is already registered for index (" + index + ")" ); +#/ + } + } + i++; + } + level._game_modules[ level._num_registered_game_modules ] = spawnstruct(); + level._game_modules[ level._num_registered_game_modules ].index = index; + level._game_modules[ level._num_registered_game_modules ].module_name = module_name; + level._game_modules[ level._num_registered_game_modules ].pre_init_func = pre_init_func; + level._game_modules[ level._num_registered_game_modules ].post_init_func = post_init_func; + level._game_modules[ level._num_registered_game_modules ].pre_init_zombie_spawn_func = pre_init_zombie_spawn_func; + level._game_modules[ level._num_registered_game_modules ].post_init_zombie_spawn_func = post_init_zombie_spawn_func; + level._game_modules[ level._num_registered_game_modules ].hub_start_func = hub_start_func; + level._num_registered_game_modules++; +} + +set_current_game_module( game_module_index ) +{ + if ( !isDefined( game_module_index ) ) + { + level.current_game_module = level.game_module_classic_index; + level.scr_zm_game_module = level.game_module_classic_index; + return; + } + game_module = get_game_module( game_module_index ); + if ( !isDefined( game_module ) ) + { +/# + assert( isDefined( game_module ), "unknown game module (" + game_module_index + ")" ); +#/ + return; + } + level.current_game_module = game_module_index; +} + +get_current_game_module() +{ + return get_game_module( level.current_game_module ); +} + +get_game_module( game_module_index ) +{ + if ( !isDefined( game_module_index ) ) + { + return undefined; + } + i = 0; + while ( i < level._game_modules.size ) + { + if ( level._game_modules[ i ].index == game_module_index ) + { + return level._game_modules[ i ]; + } + i++; + } + return undefined; +} + +game_module_pre_zombie_spawn_init() +{ + current_module = get_current_game_module(); + if ( !isDefined( current_module ) || !isDefined( current_module.pre_init_zombie_spawn_func ) ) + { + return; + } + self [[ current_module.pre_init_zombie_spawn_func ]](); +} + +game_module_post_zombie_spawn_init() +{ + current_module = get_current_game_module(); + if ( !isDefined( current_module ) || !isDefined( current_module.post_init_zombie_spawn_func ) ) + { + return; + } + self [[ current_module.post_init_zombie_spawn_func ]](); +} + +kill_all_zombies() +{ + ai = get_round_enemy_array(); + _a115 = ai; + _k115 = getFirstArrayKey( _a115 ); + while ( isDefined( _k115 ) ) + { + zombie = _a115[ _k115 ]; + if ( isDefined( zombie ) ) + { + zombie dodamage( zombie.maxhealth * 2, zombie.origin, zombie, zombie, "none", "MOD_SUICIDE" ); + wait 0,05; + } + _k115 = getNextArrayKey( _a115, _k115 ); + } +} + +freeze_players( freeze ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] freeze_player_controls( freeze ); + i++; + } +} + +turn_power_on_and_open_doors() +{ + level.local_doors_stay_open = 1; + level.power_local_doors_globally = 1; + flag_set( "power_on" ); + level setclientfield( "zombie_power_on", 1 ); + zombie_doors = getentarray( "zombie_door", "targetname" ); + _a144 = zombie_doors; + _k144 = getFirstArrayKey( _a144 ); + while ( isDefined( _k144 ) ) + { + door = _a144[ _k144 ]; + if ( isDefined( door.script_noteworthy ) && door.script_noteworthy == "electric_door" ) + { + door notify( "power_on" ); + } + else + { + if ( isDefined( door.script_noteworthy ) && door.script_noteworthy == "local_electric_door" ) + { + door notify( "local_power_on" ); + } + } + _k144 = getNextArrayKey( _a144, _k144 ); + } +} + +respawn_spectators_and_freeze_players() +{ + players = get_players(); + _a161 = players; + _k161 = getFirstArrayKey( _a161 ); + while ( isDefined( _k161 ) ) + { + player = _a161[ _k161 ]; + if ( player.sessionstate == "spectator" ) + { + if ( isDefined( player.spectate_hud ) ) + { + player.spectate_hud destroy(); + } + player [[ level.spawnplayer ]](); + } + player freeze_player_controls( 1 ); + _k161 = getNextArrayKey( _a161, _k161 ); + } +} + +damage_callback_no_pvp_damage( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + if ( isDefined( eattacker ) && isplayer( eattacker ) && eattacker == self ) + { + return idamage; + } + if ( isDefined( eattacker ) && !isplayer( eattacker ) ) + { + return idamage; + } + if ( !isDefined( eattacker ) ) + { + return idamage; + } + return 0; +} + +respawn_players() +{ + players = get_players(); + _a196 = players; + _k196 = getFirstArrayKey( _a196 ); + while ( isDefined( _k196 ) ) + { + player = _a196[ _k196 ]; + player [[ level.spawnplayer ]](); + player freeze_player_controls( 1 ); + _k196 = getNextArrayKey( _a196, _k196 ); + } +} + +zombie_goto_round( target_round ) +{ + level notify( "restart_round" ); + if ( target_round < 1 ) + { + target_round = 1; + } + level.zombie_total = 0; + maps/mp/zombies/_zm::ai_calculate_health( target_round ); + zombies = get_round_enemy_array(); + while ( isDefined( zombies ) ) + { + i = 0; + while ( i < zombies.size ) + { + zombies[ i ] dodamage( zombies[ i ].health + 666, zombies[ i ].origin ); + i++; + } + } + respawn_players(); + wait 1; +} + +wait_for_team_death_and_round_end() +{ + level endon( "game_module_ended" ); + level endon( "end_game" ); + checking_for_round_end = 0; + level.isresetting_grief = 0; + while ( 1 ) + { + cdc_alive = 0; + cia_alive = 0; + players = get_players(); + _a244 = players; + _k244 = getFirstArrayKey( _a244 ); + while ( isDefined( _k244 ) ) + { + player = _a244[ _k244 ]; + if ( !isDefined( player._encounters_team ) ) + { + } + else if ( player._encounters_team == "A" ) + { + if ( is_player_valid( player ) ) + { + cia_alive++; + } + } + else + { + if ( is_player_valid( player ) ) + { + cdc_alive++; + } + } + _k244 = getNextArrayKey( _a244, _k244 ); + } + if ( cia_alive == 0 && cdc_alive == 0 && !level.isresetting_grief && isDefined( level.host_ended_game ) && !level.host_ended_game ) + { + wait 0,5; + if ( isDefined( level._grief_reset_message ) ) + { + level thread [[ level._grief_reset_message ]](); + } + level.isresetting_grief = 1; + level notify( "end_round_think" ); + level.zombie_vars[ "spectators_respawn" ] = 1; + level notify( "keep_griefing" ); + checking_for_round_end = 0; + zombie_goto_round( level.round_number ); + level thread reset_grief(); + level thread maps/mp/zombies/_zm::round_think( 1 ); + } + else + { + if ( !checking_for_round_end ) + { + if ( cia_alive == 0 ) + { + level thread check_for_round_end( "B" ); + checking_for_round_end = 1; + break; + } + else + { + if ( cdc_alive == 0 ) + { + level thread check_for_round_end( "A" ); + checking_for_round_end = 1; + } + } + } + } + if ( cia_alive > 0 && cdc_alive > 0 ) + { + level notify( "stop_round_end_check" ); + checking_for_round_end = 0; + } + wait 0,05; + } +} + +reset_grief() +{ + wait 1; + level.isresetting_grief = 0; +} + +check_for_round_end( winner ) +{ + level endon( "keep_griefing" ); + level endon( "stop_round_end_check" ); + level waittill( "end_of_round" ); + level.gamemodulewinningteam = winner; + level.zombie_vars[ "spectators_respawn" ] = 0; + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] freezecontrols( 1 ); + if ( players[ i ]._encounters_team == winner ) + { + players[ i ] thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "grief_won" ); + i++; + continue; + } + else + { + players[ i ] thread maps/mp/zombies/_zm_audio_announcer::leaderdialogonplayer( "grief_lost" ); + } + i++; + } + level notify( "game_module_ended" ); + level._game_module_game_end_check = undefined; + maps/mp/gametypes_zm/_zm_gametype::track_encounters_win_stats( level.gamemodulewinningteam ); + level notify( "end_game" ); +} + +wait_for_team_death() +{ + wait 15; + winner = undefined; + while ( !isDefined( winner ) ) + { + cdc_alive = 0; + cia_alive = 0; + players = get_players(); + _a418 = players; + _k418 = getFirstArrayKey( _a418 ); + while ( isDefined( _k418 ) ) + { + player = _a418[ _k418 ]; + if ( player._encounters_team == "A" ) + { + if ( is_player_valid( player ) || isDefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive && isDefined( player.lives ) && player.lives > 0 ) + { + cia_alive++; + } + } + else + { + if ( is_player_valid( player ) || isDefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive && isDefined( player.lives ) && player.lives > 0 ) + { + cdc_alive++; + } + } + _k418 = getNextArrayKey( _a418, _k418 ); + } + if ( cia_alive == 0 ) + { + winner = "B"; + } + else + { + if ( cdc_alive == 0 ) + { + winner = "A"; + } + } + wait 0,05; + } + level notify( "game_module_ended" ); +} + +make_supersprinter() +{ + self set_zombie_run_cycle( "super_sprint" ); +} + +game_module_custom_intermission( intermission_struct ) +{ + self closemenu(); + self closeingamemenu(); + level endon( "stop_intermission" ); + self endon( "disconnect" ); + self endon( "death" ); + self notify( "_zombie_game_over" ); + self.score = self.score_total; + self.sessionstate = "intermission"; + self.spectatorclient = -1; + self.killcamentity = -1; + self.archivetime = 0; + self.psoffsettime = 0; + self.friendlydamage = undefined; + s_point = getstruct( intermission_struct, "targetname" ); + if ( !isDefined( level.intermission_cam_model ) ) + { + level.intermission_cam_model = spawn( "script_model", s_point.origin ); + level.intermission_cam_model.angles = s_point.angles; + level.intermission_cam_model setmodel( "tag_origin" ); + } + self.game_over_bg = newclienthudelem( self ); + self.game_over_bg.horzalign = "fullscreen"; + self.game_over_bg.vertalign = "fullscreen"; + self.game_over_bg setshader( "black", 640, 480 ); + self.game_over_bg.alpha = 1; + self spawn( level.intermission_cam_model.origin, level.intermission_cam_model.angles ); + self camerasetposition( level.intermission_cam_model ); + self camerasetlookat(); + self cameraactivate( 1 ); + self linkto( level.intermission_cam_model ); + level.intermission_cam_model moveto( getstruct( s_point.target, "targetname" ).origin, 12 ); + if ( isDefined( level.intermission_cam_model.angles ) ) + { + level.intermission_cam_model rotateto( getstruct( s_point.target, "targetname" ).angles, 12 ); + } + self.game_over_bg fadeovertime( 2 ); + self.game_over_bg.alpha = 0; + wait 2; + self.game_over_bg thread maps/mp/zombies/_zm::fade_up_over_time( 1 ); +} + +create_fireworks( launch_spots, min_wait, max_wait, randomize ) +{ + level endon( "stop_fireworks" ); + while ( 1 ) + { + if ( isDefined( randomize ) && randomize ) + { + launch_spots = array_randomize( launch_spots ); + } + _a516 = launch_spots; + _k516 = getFirstArrayKey( _a516 ); + while ( isDefined( _k516 ) ) + { + spot = _a516[ _k516 ]; + level thread fireworks_launch( spot ); + wait randomfloatrange( min_wait, max_wait ); + _k516 = getNextArrayKey( _a516, _k516 ); + } + wait randomfloatrange( min_wait, max_wait ); + } +} + +fireworks_launch( launch_spot ) +{ + firework = spawn( "script_model", launch_spot.origin + ( randomintrange( -60, 60 ), randomintrange( -60, 60 ), 0 ) ); + firework setmodel( "tag_origin" ); + wait_network_frame(); + playfxontag( level._effect[ "fw_trail_cheap" ], firework, "tag_origin" ); + firework playloopsound( "zmb_souls_loop", 0,75 ); + dest = launch_spot; + while ( isDefined( dest ) && isDefined( dest.target ) ) + { + random_offset = ( randomintrange( -60, 60 ), randomintrange( -60, 60 ), 0 ); + new_dests = getstructarray( dest.target, "targetname" ); + new_dest = random( new_dests ); + dest = new_dest; + dist = distance( new_dest.origin + random_offset, firework.origin ); + time = dist / 700; + firework moveto( new_dest.origin + random_offset, time ); + firework waittill( "movedone" ); + } + firework playsound( "zmb_souls_end" ); + playfx( level._effect[ "fw_pre_burst" ], firework.origin ); + firework delete(); +} diff --git a/patch_zm/maps/mp/zombies/_zm_jump_pad.gsc b/patch_zm/maps/mp/zombies/_zm_jump_pad.gsc new file mode 100644 index 0000000..22c1830 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_jump_pad.gsc @@ -0,0 +1,557 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( is_true( level._uses_jump_pads ) ) + { + level jump_pad_init(); + } +} + +jump_pad_init() +{ + level._jump_pad_override = []; + jump_pad_triggers = getentarray( "trig_jump_pad", "targetname" ); + if ( !isDefined( jump_pad_triggers ) ) + { + return; + } + i = 0; + while ( i < jump_pad_triggers.size ) + { + jump_pad_triggers[ i ].start = getstruct( jump_pad_triggers[ i ].target, "targetname" ); + jump_pad_triggers[ i ].destination = getstructarray( jump_pad_triggers[ i ].start.target, "targetname" ); + if ( isDefined( jump_pad_triggers[ i ].script_string ) ) + { + jump_pad_triggers[ i ].overrides = strtok( jump_pad_triggers[ i ].script_string, "," ); + } + jump_pad_triggers[ i ] thread jump_pad_think(); + i++; + } + onplayerconnect_callback( ::jump_pad_player_variables ); +} + +jump_pad_player_variables() +{ + self._padded = 0; + self.lander = 0; +} + +jump_pad_think() +{ + self endon( "destroyed" ); + end_point = undefined; + start_point = undefined; + z_velocity = undefined; + z_dist = undefined; + fling_this_way = undefined; + jump_time = undefined; + world_gravity = getDvarInt( "bg_gravity" ); + gravity_pulls = -13,3; + top_velocity_sq = 810000; + forward_scaling = 1; + if ( isDefined( self.script_flag_wait ) ) + { + if ( !isDefined( level.flag[ self.script_flag_wait ] ) ) + { + flag_init( self.script_flag_wait ); + } + flag_wait( self.script_flag_wait ); + } + while ( isDefined( self ) ) + { + self waittill( "trigger", who ); + if ( isplayer( who ) ) + { + self thread trigger_thread( who, ::jump_pad_start, ::jump_pad_cancel ); + } + } +} + +jump_pad_start( ent_player, endon_condition ) +{ + self endon( "endon_condition" ); + ent_player endon( "left_jump_pad" ); + ent_player endon( "death" ); + ent_player endon( "disconnect" ); + end_point = undefined; + start_point = undefined; + z_velocity = undefined; + z_dist = undefined; + fling_this_way = undefined; + jump_time = undefined; + world_gravity = getDvarInt( "bg_gravity" ); + gravity_pulls = -13,3; + top_velocity_sq = 810000; + forward_scaling = 1; + start_point = self.start; + while ( isDefined( self.name ) ) + { + self._action_overrides = strtok( self.name, "," ); + while ( isDefined( self._action_overrides ) ) + { + i = 0; + while ( i < self._action_overrides.size ) + { + ent_player jump_pad_player_overrides( self._action_overrides[ i ] ); + i++; + } + } + } + if ( isDefined( self.script_wait ) ) + { + if ( self.script_wait < 1 ) + { + self playsound( "evt_jump_pad_charge_short" ); + } + else + { + self playsound( "evt_jump_pad_charge" ); + } + wait self.script_wait; + } + else + { + self playsound( "evt_jump_pad_charge" ); + wait 1; + } + if ( isDefined( self.script_parameters ) && isDefined( level._jump_pad_override[ self.script_parameters ] ) ) + { + end_point = self [[ level._jump_pad_override[ self.script_parameters ] ]]( ent_player ); + } + if ( !isDefined( end_point ) ) + { + end_point = self.destination[ randomint( self.destination.size ) ]; + } + if ( isDefined( self.script_string ) && isDefined( level._jump_pad_override[ self.script_string ] ) ) + { + info_array = self [[ level._jump_pad_override[ self.script_string ] ]]( start_point, end_point ); + fling_this_way = info_array[ 0 ]; + jump_time = info_array[ 1 ]; + } + else + { + end_spot = end_point.origin; + if ( !is_true( self.script_airspeed ) ) + { + rand_end = ( randomfloatrange( -1, 1 ), randomfloatrange( -1, 1 ), 0 ); + rand_scale = randomint( 100 ); + rand_spot = vectorScale( rand_end, rand_scale ); + end_spot = end_point.origin + rand_spot; + } + pad_dist = distance( start_point.origin, end_spot ); + z_dist = end_spot[ 2 ] - start_point.origin[ 2 ]; + jump_velocity = end_spot - start_point.origin; + if ( z_dist > 40 && z_dist < 135 ) + { + z_dist *= 2,5; + forward_scaling = 1,1; +/# + if ( getDvarInt( #"D5FD01C3" ) ) + { + if ( getDvar( #"E2494021" ) != "" ) + { + z_dist *= getDvarFloat( #"E2494021" ); + } + if ( getDvar( #"4E3BC729" ) != "" ) + { + forward_scaling = getDvarFloat( #"4E3BC729" ); +#/ + } + } + } + else + { + if ( z_dist >= 135 ) + { + z_dist *= 2,7; + forward_scaling = 1,3; +/# + if ( getDvarInt( #"D5FD01C3" ) ) + { + if ( getDvar( #"E2494021" ) != "" ) + { + z_dist *= getDvarFloat( #"E2494021" ); + } + if ( getDvar( #"4E3BC729" ) != "" ) + { + forward_scaling = getDvarFloat( #"4E3BC729" ); +#/ + } + } + } + else + { + if ( z_dist < 0 ) + { + z_dist *= 2,4; + forward_scaling = 1; +/# + if ( getDvarInt( #"D5FD01C3" ) ) + { + if ( getDvar( #"E2494021" ) != "" ) + { + z_dist *= getDvarFloat( #"E2494021" ); + } + if ( getDvar( #"4E3BC729" ) != "" ) + { + forward_scaling = getDvarFloat( #"4E3BC729" ); +#/ + } + } + } + } + } + z_velocity = 2 * z_dist * world_gravity; + if ( z_velocity < 0 ) + { + z_velocity *= -1; + } + if ( z_dist < 0 ) + { + z_dist *= -1; + } + jump_time = sqrt( ( 2 * pad_dist ) / world_gravity ); + jump_time_2 = sqrt( ( 2 * z_dist ) / world_gravity ); + jump_time += jump_time_2; + if ( jump_time < 0 ) + { + jump_time *= -1; + } + x = ( jump_velocity[ 0 ] * forward_scaling ) / jump_time; + y = ( jump_velocity[ 1 ] * forward_scaling ) / jump_time; + z = z_velocity / jump_time; + fling_this_way = ( x, y, z ); + } + if ( isDefined( end_point.target ) ) + { + poi_spot = getstruct( end_point.target, "targetname" ); + } + else + { + poi_spot = end_point; + } + if ( !isDefined( self.script_index ) ) + { + ent_player.script_index = undefined; + } + else + { + ent_player.script_index = self.script_index; + } + if ( isDefined( self.script_start ) && self.script_start == 1 ) + { + if ( !is_true( ent_player._padded ) ) + { + self playsound( "evt_jump_pad_launch" ); + playfx( level._effect[ "jump_pad_jump" ], self.origin ); + ent_player thread jump_pad_move( fling_this_way, jump_time, poi_spot, self ); + if ( isDefined( self.script_label ) ) + { + level notify( self.script_label ); + } + return; + } + } + else + { + if ( ent_player isonground() && !is_true( ent_player._padded ) ) + { + self playsound( "evt_jump_pad_launch" ); + playfx( level._effect[ "jump_pad_jump" ], self.origin ); + ent_player thread jump_pad_move( fling_this_way, jump_time, poi_spot, self ); + if ( isDefined( self.script_label ) ) + { + level notify( self.script_label ); + } + return; + } + } + wait 0,5; + if ( ent_player istouching( self ) ) + { + self jump_pad_start( ent_player, endon_condition ); + } +} + +jump_pad_cancel( ent_player ) +{ + ent_player notify( "left_jump_pad" ); + if ( isDefined( ent_player.poi_spot ) && !is_true( ent_player._padded ) ) + { + } + while ( isDefined( self.name ) ) + { + self._action_overrides = strtok( self.name, "," ); + while ( isDefined( self._action_overrides ) ) + { + i = 0; + while ( i < self._action_overrides.size ) + { + ent_player jump_pad_player_overrides( self._action_overrides[ i ] ); + i++; + } + } + } +} + +jump_pad_move( vec_direction, flt_time, struct_poi, trigger ) +{ + self endon( "death" ); + self endon( "disconnect" ); + start_time = getTime(); + jump_time = flt_time * 500; + attract_dist = undefined; + num_attractors = 30; + added_poi_value = 0; + start_turned_on = 1; + poi_start_func = undefined; + while ( is_true( self.divetoprone ) || is_true( self._padded ) ) + { + wait 0,05; + } + self._padded = 1; + self.lander = 1; + self setstance( "stand" ); + wait 0,1; + if ( isDefined( trigger.script_label ) ) + { + if ( issubstr( trigger.script_label, "low" ) ) + { + self.jump_pad_current = undefined; + self.jump_pad_previous = undefined; + } + else if ( !isDefined( self.jump_pad_current ) ) + { + self.jump_pad_current = trigger; + } + else + { + self.jump_pad_previous = self.jump_pad_current; + self.jump_pad_current = trigger; + } + } + if ( isDefined( self.poi_spot ) ) + { + level jump_pad_ignore_poi_cleanup( self.poi_spot ); + self.poi_spot deactivate_zombie_point_of_interest(); + self.poi_spot delete(); + } + if ( isDefined( struct_poi ) ) + { + self.poi_spot = spawn( "script_origin", struct_poi.origin ); + if ( isDefined( level._pad_poi_ignore ) ) + { + level [[ level._pad_poi_ignore ]]( self.poi_spot ); + } + self thread jump_pad_enemy_follow_or_ignore( self.poi_spot ); + if ( isDefined( level._jump_pad_poi_start_override ) && !is_true( self.script_index ) ) + { + poi_start_func = level._jump_pad_poi_start_override; + } + if ( isDefined( level._jump_pad_poi_end_override ) ) + { + poi_end_func = level._jump_pad_poi_end_override; + } + self.poi_spot create_zombie_point_of_interest( attract_dist, num_attractors, added_poi_value, start_turned_on, poi_start_func ); + self thread disconnect_failsafe_pad_poi_clean(); + } + self setorigin( self.origin + ( 0, 0, 1 ) ); + if ( randomintrange( 0, 101 ) < 20 ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "jumppad" ); + } + while ( ( getTime() - start_time ) < jump_time ) + { + self setvelocity( vec_direction ); + wait 0,05; + } + while ( !self isonground() ) + { + wait 0,05; + } + self._padded = 0; + self.lander = 0; + jump_pad_triggers = getentarray( "trig_jump_pad", "targetname" ); + i = 0; + while ( i < jump_pad_triggers.size ) + { + if ( self istouching( jump_pad_triggers[ i ] ) ) + { + level thread failsafe_pad_poi_clean( jump_pad_triggers[ i ], self.poi_spot ); + return; + } + i++; + } + if ( isDefined( self.poi_spot ) ) + { + level jump_pad_ignore_poi_cleanup( self.poi_spot ); + self.poi_spot delete(); + } +} + +disconnect_failsafe_pad_poi_clean() +{ + self notify( "kill_disconnect_failsafe_pad_poi_clean" ); + self endon( "kill_disconnect_failsafe_pad_poi_clean" ); + self.poi_spot endon( "death" ); + self waittill( "disconnect" ); + if ( isDefined( self.poi_spot ) ) + { + level jump_pad_ignore_poi_cleanup( self.poi_spot ); + self.poi_spot deactivate_zombie_point_of_interest(); + self.poi_spot delete(); + } +} + +failsafe_pad_poi_clean( ent_trig, ent_poi ) +{ + if ( isDefined( ent_trig.script_wait ) ) + { + wait ent_trig.script_wait; + } + else + { + wait 0,5; + } + if ( isDefined( ent_poi ) ) + { + level jump_pad_ignore_poi_cleanup( ent_poi ); + ent_poi deactivate_zombie_point_of_interest(); + ent_poi delete(); + } +} + +jump_pad_enemy_follow_or_ignore( ent_poi ) +{ + self endon( "death" ); + self endon( "disconnect" ); + zombies = getaiarray( level.zombie_team ); + players = getplayers(); + valid_players = 0; + p = 0; + while ( p < players.size ) + { + if ( is_player_valid( players[ p ] ) ) + { + valid_players++; + } + p++; + } + i = 0; + while ( i < zombies.size ) + { + ignore_poi = 0; + if ( !isDefined( zombies[ i ] ) ) + { + i++; + continue; + } + else enemy = zombies[ i ].favoriteenemy; + if ( isDefined( enemy ) ) + { + if ( players.size > 1 && valid_players > 1 ) + { + if ( enemy != self || isDefined( enemy.jump_pad_previous ) && enemy.jump_pad_previous == enemy.jump_pad_current ) + { + ignore_poi = 1; + } + } + } + if ( is_true( ignore_poi ) ) + { + zombies[ i ] thread add_poi_to_ignore_list( ent_poi ); + i++; + continue; + } + else + { + zombies[ i ].ignore_distance_tracking = 1; + zombies[ i ]._pad_follow = 1; + zombies[ i ] thread stop_chasing_the_sky( ent_poi ); + } + i++; + } +} + +jump_pad_ignore_poi_cleanup( ent_poi ) +{ + zombies = getaiarray( level.zombie_team ); + i = 0; + while ( i < zombies.size ) + { + if ( isDefined( zombies[ i ] ) ) + { + if ( is_true( zombies[ i ]._pad_follow ) ) + { + zombies[ i ]._pad_follow = 0; + zombies[ i ] notify( "stop_chasing_the_sky" ); + zombies[ i ].ignore_distance_tracking = 0; + } + if ( isDefined( ent_poi ) ) + { + zombies[ i ] thread remove_poi_from_ignore_list( ent_poi ); + } + } + i++; + } +} + +stop_chasing_the_sky( ent_poi ) +{ + self endon( "death" ); + self endon( "stop_chasing_the_sky" ); + while ( is_true( self._pad_follow ) ) + { + while ( isDefined( self.favoriteenemy ) ) + { + players = getplayers(); + i = 0; + while ( i < players.size ) + { + if ( is_player_valid( players[ i ] ) && players[ i ] != self.favoriteenemy ) + { + if ( distance2dsquared( players[ i ].origin, self.origin ) < 10000 ) + { + self add_poi_to_ignore_list( ent_poi ); + return; + } + } + i++; + } + } + wait 0,1; + } + self._pad_follow = 0; + self.ignore_distance_tracking = 0; + self notify( "stop_chasing_the_sky" ); +} + +jump_pad_player_overrides( st_behavior, int_clean ) +{ + if ( !isDefined( st_behavior ) || !isstring( st_behavior ) ) + { + return; + } + if ( !isDefined( int_clean ) ) + { + int_clean = 0; + } + switch( st_behavior ) + { + case "no_sprint": + if ( !int_clean ) + { + } + default: + if ( isDefined( level._jump_pad_level_behavior ) ) + { + self [[ level._jump_pad_level_behavior ]]( st_behavior, int_clean ); + } + } + } + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_laststand.gsc b/patch_zm/maps/mp/zombies/_zm_laststand.gsc new file mode 100644 index 0000000..0b46dac --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_laststand.gsc @@ -0,0 +1,1459 @@ +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_chugabud; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/_demo; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +laststand_global_init() +{ + level.const_laststand_getup_count_start = 0; + level.const_laststand_getup_bar_start = 0,5; + level.const_laststand_getup_bar_regen = 0,0025; + level.const_laststand_getup_bar_damage = 0,1; +} + +init() +{ + if ( level.script == "frontend" ) + { + return; + } + laststand_global_init(); + level.revive_tool = "syrette_zm"; + precacheitem( level.revive_tool ); + precachestring( &"ZOMBIE_BUTTON_TO_REVIVE_PLAYER" ); + precachestring( &"ZOMBIE_PLAYER_NEEDS_TO_BE_REVIVED" ); + precachestring( &"ZOMBIE_PLAYER_IS_REVIVING_YOU" ); + precachestring( &"ZOMBIE_REVIVING" ); + if ( !isDefined( level.laststandpistol ) ) + { + level.laststandpistol = "m1911"; + precacheitem( level.laststandpistol ); + } + level thread revive_hud_think(); + level.primaryprogressbarx = 0; + level.primaryprogressbary = 110; + level.primaryprogressbarheight = 4; + level.primaryprogressbarwidth = 120; + level.primaryprogressbary_ss = 280; + if ( getDvar( "revive_trigger_radius" ) == "" ) + { + setdvar( "revive_trigger_radius", "40" ); + } + level.laststandgetupallowed = 0; +} + +player_is_in_laststand() +{ + if ( isDefined( self.no_revive_trigger ) && !self.no_revive_trigger ) + { + return isDefined( self.revivetrigger ); + } + else + { + if ( isDefined( self.laststand ) ) + { + return self.laststand; + } + } +} + +player_num_in_laststand() +{ + num = 0; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] player_is_in_laststand() ) + { + num++; + } + i++; + } + return num; +} + +player_all_players_in_laststand() +{ + return player_num_in_laststand() == get_players().size; +} + +player_any_player_in_laststand() +{ + return player_num_in_laststand() > 0; +} + +player_last_stand_stats( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ + if ( isDefined( attacker ) && isplayer( attacker ) && attacker != self ) + { + if ( level.gametype == "zcleansed" ) + { + maps/mp/_demo::bookmark( "kill", getTime(), self, attacker, 0, einflictor ); + } + if ( level.gametype == "zcleansed" ) + { + if ( isDefined( attacker.is_zombie ) && !attacker.is_zombie ) + { + attacker.kills++; + } + else + { + attacker.downs++; + } + } + else + { + attacker.kills++; + } + attacker maps/mp/zombies/_zm_stats::increment_client_stat( "kills" ); + attacker maps/mp/zombies/_zm_stats::increment_player_stat( "kills" ); + if ( isDefined( sweapon ) ) + { + dmgweapon = sweapon; + if ( is_alt_weapon( dmgweapon ) ) + { + dmgweapon = weaponaltweaponname( dmgweapon ); + } + attacker addweaponstat( dmgweapon, "kills", 1 ); + } + if ( is_headshot( sweapon, shitloc, smeansofdeath ) ) + { + attacker.headshots++; + attacker maps/mp/zombies/_zm_stats::increment_client_stat( "headshots" ); + attacker addweaponstat( sweapon, "headshots", 1 ); + attacker maps/mp/zombies/_zm_stats::increment_player_stat( "headshots" ); + } + } + self increment_downed_stat(); + if ( flag( "solo_game" ) && !self.lives && getnumconnectedplayers() < 2 ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "deaths" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "deaths" ); + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_jugg_player_death_stat(); + } +} + +increment_downed_stat() +{ + if ( level.gametype != "zcleansed" ) + { + self.downs++; + } + self maps/mp/zombies/_zm_stats::increment_client_stat( "downs" ); + self add_weighted_down(); + self maps/mp/zombies/_zm_stats::increment_player_stat( "downs" ); + zonename = self get_current_zone(); + if ( !isDefined( zonename ) ) + { + zonename = ""; + } + self recordplayerdownzombies( zonename ); +} + +playerlaststand( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ + self notify( "entering_last_stand" ); + if ( isDefined( level._game_module_player_laststand_callback ) ) + { + self [[ level._game_module_player_laststand_callback ]]( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ); + } + if ( self player_is_in_laststand() ) + { + return; + } + if ( isDefined( self.in_zombify_call ) && self.in_zombify_call ) + { + return; + } + self thread player_last_stand_stats( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ); + if ( isDefined( level.playerlaststand_func ) ) + { + [[ level.playerlaststand_func ]]( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ); + } + self.health = 1; + self.laststand = 1; + self.ignoreme = 1; + self thread maps/mp/gametypes_zm/_gameobjects::onplayerlaststand(); + self thread maps/mp/zombies/_zm_buildables::onplayerlaststand(); + if ( isDefined( self.no_revive_trigger ) && !self.no_revive_trigger ) + { + self revive_trigger_spawn(); + } + else + { + self undolaststand(); + } + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + self takeallweapons(); + if ( isDefined( attacker ) && isplayer( attacker ) && attacker != self ) + { + attacker notify( "killed_a_zombie_player" ); + } + } + else + { + self laststand_disable_player_weapons(); + self laststand_give_pistol(); + } + if ( isDefined( level.playersuicideallowed ) && level.playersuicideallowed && get_players().size > 1 ) + { + if ( !isDefined( level.canplayersuicide ) || self [[ level.canplayersuicide ]]() ) + { + self thread suicide_trigger_spawn(); + } + } + if ( isDefined( self.disabled_perks ) ) + { + self.disabled_perks = []; + } + if ( level.laststandgetupallowed ) + { + self thread laststand_getup(); + } + else + { + bleedout_time = getDvarFloat( "player_lastStandBleedoutTime" ); + self thread laststand_bleedout( bleedout_time ); + } + if ( level.gametype != "zcleansed" ) + { + maps/mp/_demo::bookmark( "zm_player_downed", getTime(), self ); + } + self notify( "player_downed" ); + self thread refire_player_downed(); + self thread cleanup_laststand_on_disconnect(); +} + +refire_player_downed() +{ + self endon( "player_revived" ); + self endon( "death" ); + self endon( "disconnect" ); + wait 1; + if ( self.num_perks ) + { + self notify( "player_downed" ); + } +} + +laststand_allowed( sweapon, smeansofdeath, shitloc ) +{ + if ( level.laststandpistol == "none" ) + { + return 0; + } + return 1; +} + +laststand_disable_player_weapons() +{ + weaponinventory = self getweaponslist( 1 ); + self.lastactiveweapon = self getcurrentweapon(); + if ( self isthrowinggrenade() && is_offhand_weapon( self.lastactiveweapon ) ) + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self.lastactiveweapon = primaryweapons[ 0 ]; + self switchtoweaponimmediate( self.lastactiveweapon ); + } + } + self setlaststandprevweap( self.lastactiveweapon ); + self.laststandpistol = undefined; + self.hadpistol = 0; + if ( isDefined( self.weapon_taken_by_losing_specialty_additionalprimaryweapon ) && self.lastactiveweapon == self.weapon_taken_by_losing_specialty_additionalprimaryweapon ) + { + self.lastactiveweapon = "none"; + self.weapon_taken_by_losing_specialty_additionalprimaryweapon = undefined; + } + i = 0; + while ( i < weaponinventory.size ) + { + weapon = weaponinventory[ i ]; + class = weaponclass( weapon ); + if ( issubstr( weapon, "knife_ballistic_" ) ) + { + class = "knife"; + } + if ( class != "pistol" && class != "pistol spread" && class == "pistolspread" && !isDefined( self.laststandpistol ) ) + { + self.laststandpistol = weapon; + self.hadpistol = 1; + } + if ( weapon == "syrette_zm" ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "failed_sacrifices" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "failed_sacrifices" ); + } + else + { + if ( is_zombie_perk_bottle( weapon ) ) + { + self takeweapon( weapon ); + self.lastactiveweapon = "none"; + i++; + continue; + } + } + else if ( isDefined( get_gamemode_var( "item_meat_name" ) ) ) + { + if ( weapon == get_gamemode_var( "item_meat_name" ) ) + { + self takeweapon( weapon ); + self.lastactiveweapon = "none"; + i++; + continue; + } + } + i++; + } + if ( isDefined( self.hadpistol ) && self.hadpistol == 1 && isDefined( level.zombie_last_stand_pistol_memory ) ) + { + self [[ level.zombie_last_stand_pistol_memory ]](); + } + if ( !isDefined( self.laststandpistol ) ) + { + self.laststandpistol = level.laststandpistol; + } + self disableweaponcycling(); + self notify( "weapons_taken_for_last_stand" ); +} + +laststand_enable_player_weapons() +{ + if ( isDefined( self.hadpistol ) && !self.hadpistol && isDefined( self.laststandpistol ) ) + { + self takeweapon( self.laststandpistol ); + } + if ( isDefined( self.hadpistol ) && self.hadpistol == 1 && isDefined( level.zombie_last_stand_ammo_return ) ) + { + [[ level.zombie_last_stand_ammo_return ]](); + } + self enableweaponcycling(); + self enableoffhandweapons(); + if ( isDefined( self.lastactiveweapon ) && self.lastactiveweapon != "none" && self hasweapon( self.lastactiveweapon ) && !is_placeable_mine( self.lastactiveweapon ) && !is_equipment( self.lastactiveweapon ) ) + { + self switchtoweapon( self.lastactiveweapon ); + } + else + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } +} + +laststand_clean_up_on_disconnect( playerbeingrevived, revivergun ) +{ + self endon( "do_revive_ended_normally" ); + revivetrigger = playerbeingrevived.revivetrigger; + playerbeingrevived waittill( "disconnect" ); + if ( isDefined( revivetrigger ) ) + { + revivetrigger delete(); + } + self cleanup_suicide_hud(); + if ( isDefined( self.reviveprogressbar ) ) + { + self.reviveprogressbar destroyelem(); + } + if ( isDefined( self.revivetexthud ) ) + { + self.revivetexthud destroy(); + } + self revive_give_back_weapons( revivergun ); +} + +laststand_clean_up_reviving_any( playerbeingrevived ) +{ + self endon( "do_revive_ended_normally" ); + playerbeingrevived waittill_any( "disconnect", "zombified", "stop_revive_trigger" ); + self.is_reviving_any--; + + if ( self.is_reviving_any <= 0 ) + { + self.is_reviving_any = 0; + } +} + +laststand_give_pistol() +{ +/# + assert( isDefined( self.laststandpistol ) ); +#/ +/# + assert( self.laststandpistol != "none" ); +#/ + if ( isDefined( level.zombie_last_stand ) ) + { + [[ level.zombie_last_stand ]](); + } + else + { + self giveweapon( self.laststandpistol ); + self givemaxammo( self.laststandpistol ); + self switchtoweapon( self.laststandpistol ); + } +} + +laststand_bleedout( delay ) +{ + self endon( "player_revived" ); + self endon( "player_suicide" ); + self endon( "zombified" ); + self endon( "disconnect" ); + if ( isDefined( self.is_zombie ) || self.is_zombie && isDefined( self.no_revive_trigger ) && self.no_revive_trigger ) + { + self notify( "bled_out" ); + wait_network_frame(); + self bleed_out(); + return; + } + setclientsysstate( "lsm", "1", self ); + self.bleedout_time = delay; + while ( self.bleedout_time > int( delay * 0,5 ) ) + { + self.bleedout_time -= 1; + wait 1; + } + visionsetlaststand( "zombie_death", delay * 0,5 ); + while ( self.bleedout_time > 0 ) + { + self.bleedout_time -= 1; + wait 1; + } + while ( isDefined( self.revivetrigger ) && isDefined( self.revivetrigger.beingrevived ) && self.revivetrigger.beingrevived == 1 ) + { + wait 0,1; + } + self notify( "bled_out" ); + wait_network_frame(); + self bleed_out(); +} + +bleed_out() +{ + self cleanup_suicide_hud(); + if ( isDefined( self.revivetrigger ) ) + { + self.revivetrigger delete(); + } + self.revivetrigger = undefined; + setclientsysstate( "lsm", "0", self ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "deaths" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "deaths" ); + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_jugg_player_death_stat(); + self recordplayerdeathzombies(); + self maps/mp/zombies/_zm_equipment::equipment_take(); + if ( level.gametype != "zcleansed" ) + { + maps/mp/_demo::bookmark( "zm_player_bledout", getTime(), self, undefined, 1 ); + } + level notify( "bleed_out" ); + self undolaststand(); + if ( isDefined( level.is_zombie_level ) && level.is_zombie_level ) + { + self thread [[ level.player_becomes_zombie ]](); + } + else + { + if ( isDefined( level.is_specops_level ) && level.is_specops_level ) + { + self thread [[ level.spawnspectator ]](); + return; + } + else + { + self.ignoreme = 0; + } + } +} + +cleanup_suicide_hud() +{ + if ( isDefined( self.suicideprompt ) ) + { + self.suicideprompt destroy(); + } + self.suicideprompt = undefined; +} + +clean_up_suicide_hud_on_end_game() +{ + self endon( "disconnect" ); + self endon( "zombified" ); + self endon( "stop_revive_trigger" ); + self endon( "player_revived" ); + self endon( "bled_out" ); + level waittill_any( "end_game", "stop_suicide_trigger" ); + self cleanup_suicide_hud(); + if ( isDefined( self.suicidetexthud ) ) + { + self.suicidetexthud destroy(); + } + if ( isDefined( self.suicideprogressbar ) ) + { + self.suicideprogressbar destroyelem(); + } +} + +clean_up_suicide_hud_on_bled_out() +{ + self endon( "disconnect" ); + self endon( "zombified" ); + self endon( "stop_revive_trigger" ); + self waittill_any( "bled_out", "player_revived", "fake_death" ); + self cleanup_suicide_hud(); + if ( isDefined( self.suicideprogressbar ) ) + { + self.suicideprogressbar destroyelem(); + } + if ( isDefined( self.suicidetexthud ) ) + { + self.suicidetexthud destroy(); + } +} + +suicide_trigger_spawn() +{ + radius = getDvarInt( "revive_trigger_radius" ); + self.suicideprompt = newclienthudelem( self ); + self.suicideprompt.alignx = "center"; + self.suicideprompt.aligny = "middle"; + self.suicideprompt.horzalign = "center"; + self.suicideprompt.vertalign = "bottom"; + self.suicideprompt.y = -170; + if ( self issplitscreen() ) + { + self.suicideprompt.y = -132; + } + self.suicideprompt.foreground = 1; + self.suicideprompt.font = "default"; + self.suicideprompt.fontscale = 1,5; + self.suicideprompt.alpha = 1; + self.suicideprompt.color = ( 1, 1, 1 ); + self.suicideprompt.hidewheninmenu = 1; + self thread suicide_trigger_think(); +} + +suicide_trigger_think() +{ + self endon( "disconnect" ); + self endon( "zombified" ); + self endon( "stop_revive_trigger" ); + self endon( "player_revived" ); + self endon( "bled_out" ); + self endon( "fake_death" ); + level endon( "end_game" ); + level endon( "stop_suicide_trigger" ); + self thread clean_up_suicide_hud_on_end_game(); + self thread clean_up_suicide_hud_on_bled_out(); + while ( self usebuttonpressed() ) + { + wait 1; + } + if ( !isDefined( self.suicideprompt ) ) + { + return; + } + while ( 1 ) + { + wait 0,1; + while ( !isDefined( self.suicideprompt ) ) + { + continue; + } + self.suicideprompt settext( &"ZOMBIE_BUTTON_TO_SUICIDE" ); + while ( !self is_suiciding() ) + { + continue; + } + self.pre_suicide_weapon = self getcurrentweapon(); + self giveweapon( level.suicide_weapon ); + self switchtoweapon( level.suicide_weapon ); + duration = self docowardswayanims(); + suicide_success = suicide_do_suicide( duration ); + self.laststand = undefined; + self takeweapon( level.suicide_weapon ); + if ( suicide_success ) + { + self notify( "player_suicide" ); + wait_network_frame(); + self maps/mp/zombies/_zm_stats::increment_client_stat( "suicides" ); + self bleed_out(); + return; + } + self switchtoweapon( self.pre_suicide_weapon ); + self.pre_suicide_weapon = undefined; + } +} + +suicide_do_suicide( duration ) +{ + level endon( "end_game" ); + level endon( "stop_suicide_trigger" ); + suicidetime = duration; + timer = 0; + suicided = 0; + self.suicideprompt settext( "" ); + if ( !isDefined( self.suicideprogressbar ) ) + { + self.suicideprogressbar = self createprimaryprogressbar(); + } + if ( !isDefined( self.suicidetexthud ) ) + { + self.suicidetexthud = newclienthudelem( self ); + } + self.suicideprogressbar updatebar( 0,01, 1 / suicidetime ); + self.suicidetexthud.alignx = "center"; + self.suicidetexthud.aligny = "middle"; + self.suicidetexthud.horzalign = "center"; + self.suicidetexthud.vertalign = "bottom"; + self.suicidetexthud.y = -173; + if ( self issplitscreen() ) + { + self.suicidetexthud.y = -147; + } + self.suicidetexthud.foreground = 1; + self.suicidetexthud.font = "default"; + self.suicidetexthud.fontscale = 1,8; + self.suicidetexthud.alpha = 1; + self.suicidetexthud.color = ( 1, 1, 1 ); + self.suicidetexthud.hidewheninmenu = 1; + self.suicidetexthud settext( &"ZOMBIE_SUICIDING" ); + while ( self is_suiciding() ) + { + wait 0,05; + timer += 0,05; + if ( timer >= suicidetime ) + { + suicided = 1; + break; + } + else + { + } + } + if ( isDefined( self.suicideprogressbar ) ) + { + self.suicideprogressbar destroyelem(); + } + if ( isDefined( self.suicidetexthud ) ) + { + self.suicidetexthud destroy(); + } + if ( isDefined( self.suicideprompt ) ) + { + self.suicideprompt settext( &"ZOMBIE_BUTTON_TO_SUICIDE" ); + } + return suicided; +} + +can_suicide() +{ + if ( !isalive( self ) ) + { + return 0; + } + if ( !self player_is_in_laststand() ) + { + return 0; + } + if ( !isDefined( self.suicideprompt ) ) + { + return 0; + } + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + return 0; + } + if ( isDefined( level.intermission ) && level.intermission ) + { + return 0; + } + return 1; +} + +is_suiciding( revivee ) +{ + if ( self usebuttonpressed() ) + { + return can_suicide(); + } +} + +revive_trigger_spawn() +{ + if ( isDefined( level.revive_trigger_spawn_override_link ) ) + { + [[ level.revive_trigger_spawn_override_link ]]( self ); + } + else + { + radius = getDvarInt( "revive_trigger_radius" ); + self.revivetrigger = spawn( "trigger_radius", ( 1, 1, 1 ), 0, radius, radius ); + self.revivetrigger sethintstring( "" ); + self.revivetrigger setcursorhint( "HINT_NOICON" ); + self.revivetrigger setmovingplatformenabled( 1 ); + self.revivetrigger enablelinkto(); + self.revivetrigger.origin = self.origin; + self.revivetrigger linkto( self ); + self.revivetrigger.beingrevived = 0; + self.revivetrigger.createtime = getTime(); + } + self thread revive_trigger_think(); +} + +revive_trigger_think() +{ + self endon( "disconnect" ); + self endon( "zombified" ); + self endon( "stop_revive_trigger" ); + level endon( "end_game" ); + self endon( "death" ); + while ( 1 ) + { + wait 0,1; + self.revivetrigger sethintstring( "" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + d = 0; + d = self depthinwater(); + if ( players[ i ] can_revive( self ) || d > 20 ) + { + self.revivetrigger setrevivehintstring( &"ZOMBIE_BUTTON_TO_REVIVE_PLAYER", self.team ); + break; + } + else + { + i++; + } + } + i = 0; + while ( i < players.size ) + { + reviver = players[ i ]; + if ( self == reviver || !reviver is_reviving( self ) ) + { + i++; + continue; + } + else + { + gun = reviver getcurrentweapon(); +/# + assert( isDefined( gun ) ); +#/ + if ( gun == level.revive_tool ) + { + i++; + continue; + } + else + { + reviver giveweapon( level.revive_tool ); + reviver switchtoweapon( level.revive_tool ); + reviver setweaponammostock( level.revive_tool, 1 ); + revive_success = reviver revive_do_revive( self, gun ); + reviver revive_give_back_weapons( gun ); + if ( isplayer( self ) ) + { + self allowjump( 1 ); + } + self.laststand = undefined; + if ( revive_success ) + { + if ( isplayer( self ) ) + { + maps/mp/zombies/_zm_chugabud::player_revived_cleanup_chugabud_corpse(); + } + self thread revive_success( reviver ); + self cleanup_suicide_hud(); + return; + } + } + } + i++; + } + } +} + +revive_give_back_weapons( gun ) +{ + self takeweapon( level.revive_tool ); + if ( self player_is_in_laststand() ) + { + return; + } + if ( gun != "none" && !is_placeable_mine( gun ) && gun != "equip_gasmask_zm" && gun != "lower_equip_gasmask_zm" && self hasweapon( gun ) ) + { + self switchtoweapon( gun ); + } + else + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } +} + +can_revive( revivee ) +{ + if ( !isDefined( revivee.revivetrigger ) ) + { + return 0; + } + if ( !isalive( self ) ) + { + return 0; + } + if ( self player_is_in_laststand() ) + { + return 0; + } + if ( self.team != revivee.team ) + { + return 0; + } + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + return 0; + } + if ( self has_powerup_weapon() ) + { + return 0; + } + if ( isDefined( level.can_revive_use_depthinwater_test ) && level.can_revive_use_depthinwater_test && revivee depthinwater() > 10 ) + { + return 1; + } + if ( isDefined( level.can_revive ) && !( [[ level.can_revive ]]( revivee ) ) ) + { + return 0; + } + if ( isDefined( level.can_revive_game_module ) && !( [[ level.can_revive_game_module ]]( revivee ) ) ) + { + return 0; + } + ignore_sight_checks = 0; + ignore_touch_checks = 0; + if ( isDefined( level.revive_trigger_should_ignore_sight_checks ) ) + { + ignore_sight_checks = [[ level.revive_trigger_should_ignore_sight_checks ]]( self ); + if ( ignore_sight_checks && isDefined( revivee.revivetrigger.beingrevived ) && revivee.revivetrigger.beingrevived == 1 ) + { + ignore_touch_checks = 1; + } + } + if ( !ignore_touch_checks ) + { + if ( !self istouching( revivee.revivetrigger ) ) + { + return 0; + } + } + if ( !ignore_sight_checks ) + { + if ( !self is_facing( revivee ) ) + { + return 0; + } + if ( !sighttracepassed( self.origin + vectorScale( ( 1, 1, 1 ), 50 ), revivee.origin + vectorScale( ( 1, 1, 1 ), 30 ), 0, undefined ) ) + { + return 0; + } + if ( !bullettracepassed( self.origin + vectorScale( ( 1, 1, 1 ), 50 ), revivee.origin + vectorScale( ( 1, 1, 1 ), 30 ), 0, undefined ) ) + { + return 0; + } + } + return 1; +} + +is_reviving( revivee ) +{ + if ( self usebuttonpressed() ) + { + return can_revive( revivee ); + } +} + +is_reviving_any() +{ + if ( isDefined( self.is_reviving_any ) ) + { + return self.is_reviving_any; + } +} + +is_facing( facee ) +{ + orientation = self getplayerangles(); + forwardvec = anglesToForward( orientation ); + forwardvec2d = ( forwardvec[ 0 ], forwardvec[ 1 ], 0 ); + unitforwardvec2d = vectornormalize( forwardvec2d ); + tofaceevec = facee.origin - self.origin; + tofaceevec2d = ( tofaceevec[ 0 ], tofaceevec[ 1 ], 0 ); + unittofaceevec2d = vectornormalize( tofaceevec2d ); + dotproduct = vectordot( unitforwardvec2d, unittofaceevec2d ); + return dotproduct > 0,9; +} + +revive_do_revive( playerbeingrevived, revivergun ) +{ +/# + assert( self is_reviving( playerbeingrevived ) ); +#/ + revivetime = 3; + if ( self hasperk( "specialty_quickrevive" ) ) + { + revivetime /= 2; + } + if ( self maps/mp/zombies/_zm_pers_upgrades_functions::pers_revive_active() ) + { + revivetime *= 0,5; + } + timer = 0; + revived = 0; + playerbeingrevived.revivetrigger.beingrevived = 1; + playerbeingrevived.revive_hud settext( &"ZOMBIE_PLAYER_IS_REVIVING_YOU", self ); + playerbeingrevived revive_hud_show_n_fade( 3 ); + playerbeingrevived.revivetrigger sethintstring( "" ); + if ( isplayer( playerbeingrevived ) ) + { + playerbeingrevived startrevive( self ); + } + if ( !isDefined( self.reviveprogressbar ) ) + { + self.reviveprogressbar = self createprimaryprogressbar(); + } + if ( !isDefined( self.revivetexthud ) ) + { + self.revivetexthud = newclienthudelem( self ); + } + self thread laststand_clean_up_on_disconnect( playerbeingrevived, revivergun ); + if ( !isDefined( self.is_reviving_any ) ) + { + self.is_reviving_any = 0; + } + self.is_reviving_any++; + self thread laststand_clean_up_reviving_any( playerbeingrevived ); + self.reviveprogressbar updatebar( 0,01, 1 / revivetime ); + self.revivetexthud.alignx = "center"; + self.revivetexthud.aligny = "middle"; + self.revivetexthud.horzalign = "center"; + self.revivetexthud.vertalign = "bottom"; + self.revivetexthud.y = -113; + if ( self issplitscreen() ) + { + self.revivetexthud.y = -347; + } + self.revivetexthud.foreground = 1; + self.revivetexthud.font = "default"; + self.revivetexthud.fontscale = 1,8; + self.revivetexthud.alpha = 1; + self.revivetexthud.color = ( 1, 1, 1 ); + self.revivetexthud.hidewheninmenu = 1; + if ( self maps/mp/zombies/_zm_pers_upgrades_functions::pers_revive_active() ) + { + self.revivetexthud.color = ( 0,5, 0,5, 1 ); + } + self.revivetexthud settext( &"ZOMBIE_REVIVING" ); + self thread check_for_failed_revive( playerbeingrevived ); + while ( self is_reviving( playerbeingrevived ) ) + { + wait 0,05; + timer += 0,05; + if ( self player_is_in_laststand() ) + { + break; + } + else if ( isDefined( playerbeingrevived.revivetrigger.auto_revive ) && playerbeingrevived.revivetrigger.auto_revive == 1 ) + { + break; + } + else + { + if ( timer >= revivetime ) + { + revived = 1; + break; + } + else + { + } + } + } + if ( isDefined( self.reviveprogressbar ) ) + { + self.reviveprogressbar destroyelem(); + } + if ( isDefined( self.revivetexthud ) ) + { + self.revivetexthud destroy(); + } + if ( isDefined( playerbeingrevived.revivetrigger.auto_revive ) && playerbeingrevived.revivetrigger.auto_revive == 1 ) + { + } + else if ( !revived ) + { + if ( isplayer( playerbeingrevived ) ) + { + playerbeingrevived stoprevive( self ); + } + } + playerbeingrevived.revivetrigger sethintstring( &"ZOMBIE_BUTTON_TO_REVIVE_PLAYER" ); + playerbeingrevived.revivetrigger.beingrevived = 0; + self notify( "do_revive_ended_normally" ); + self.is_reviving_any--; + + if ( !revived ) + { + playerbeingrevived thread checkforbleedout( self ); + } + return revived; +} + +checkforbleedout( player ) +{ + self endon( "player_revived" ); + self endon( "player_suicide" ); + self endon( "disconnect" ); + player endon( "disconnect" ); + if ( is_classic() ) + { + player.failed_revives++; + player notify( "player_failed_revive" ); + } +} + +auto_revive( reviver, dont_enable_weapons ) +{ + if ( isDefined( self.revivetrigger ) ) + { + self.revivetrigger.auto_revive = 1; + while ( self.revivetrigger.beingrevived == 1 ) + { + while ( 1 ) + { + if ( self.revivetrigger.beingrevived == 0 ) + { + break; + } + else + { + wait_network_frame(); + } + } + } + self.revivetrigger.auto_trigger = 0; + } + self reviveplayer(); + self maps/mp/zombies/_zm_perks::perk_set_max_health_if_jugg( "health_reboot", 1, 0 ); + setclientsysstate( "lsm", "0", self ); + self notify( "stop_revive_trigger" ); + if ( isDefined( self.revivetrigger ) ) + { + self.revivetrigger delete(); + self.revivetrigger = undefined; + } + self cleanup_suicide_hud(); + if ( !isDefined( dont_enable_weapons ) || dont_enable_weapons == 0 ) + { + self laststand_enable_player_weapons(); + } + self allowjump( 1 ); + self.ignoreme = 0; + self.laststand = undefined; + if ( isDefined( level.isresetting_grief ) && !level.isresetting_grief ) + { + reviver.revives++; + reviver maps/mp/zombies/_zm_stats::increment_client_stat( "revives" ); + reviver maps/mp/zombies/_zm_stats::increment_player_stat( "revives" ); + self recordplayerrevivezombies( reviver ); + maps/mp/_demo::bookmark( "zm_player_revived", getTime(), self, reviver ); + } + self notify( "player_revived" ); +} + +remote_revive( reviver ) +{ + if ( !self player_is_in_laststand() ) + { + return; + } + self auto_revive( reviver ); +} + +revive_success( reviver, b_track_stats ) +{ + if ( !isDefined( b_track_stats ) ) + { + b_track_stats = 1; + } + if ( !isplayer( self ) ) + { + self notify( "player_revived" ); + return; + } + if ( isDefined( b_track_stats ) && b_track_stats ) + { + maps/mp/_demo::bookmark( "zm_player_revived", getTime(), self, reviver ); + } + self notify( "player_revived" ); + self reviveplayer(); + self maps/mp/zombies/_zm_perks::perk_set_max_health_if_jugg( "health_reboot", 1, 0 ); + if ( isDefined( self.pers_upgrades_awarded[ "perk_lose" ] ) && self.pers_upgrades_awarded[ "perk_lose" ] ) + { + self thread maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_perk_lose_restore(); + } + if ( isDefined( level.isresetting_grief ) && !level.isresetting_grief && isDefined( b_track_stats ) && b_track_stats ) + { + reviver.revives++; + reviver maps/mp/zombies/_zm_stats::increment_client_stat( "revives" ); + reviver maps/mp/zombies/_zm_stats::increment_player_stat( "revives" ); + self recordplayerrevivezombies( reviver ); + reviver.upgrade_fx_origin = self.origin; + } + if ( is_classic() && isDefined( b_track_stats ) && b_track_stats ) + { + maps/mp/zombies/_zm_pers_upgrades_functions::pers_increment_revive_stat( reviver ); + } + if ( isDefined( b_track_stats ) && b_track_stats ) + { + reviver thread check_for_sacrifice(); + } + if ( isDefined( level.missioncallbacks ) ) + { + } + setclientsysstate( "lsm", "0", self ); + self.revivetrigger delete(); + self.revivetrigger = undefined; + self cleanup_suicide_hud(); + self laststand_enable_player_weapons(); + self.ignoreme = 0; +} + +revive_force_revive( reviver ) +{ +/# + assert( isDefined( self ) ); +#/ +/# + assert( isplayer( self ) ); +#/ +/# + assert( self player_is_in_laststand() ); +#/ + self thread revive_success( reviver ); +} + +revive_hud_create() +{ + self.revive_hud = newclienthudelem( self ); + self.revive_hud.alignx = "center"; + self.revive_hud.aligny = "middle"; + self.revive_hud.horzalign = "center"; + self.revive_hud.vertalign = "bottom"; + self.revive_hud.foreground = 1; + self.revive_hud.font = "default"; + self.revive_hud.fontscale = 1,5; + self.revive_hud.alpha = 0; + self.revive_hud.color = ( 1, 1, 1 ); + self.revive_hud.hidewheninmenu = 1; + self.revive_hud settext( "" ); + self.revive_hud.y = -160; +} + +revive_hud_think() +{ + self endon( "disconnect" ); + while ( 1 ) + { + wait 0,1; + while ( !player_any_player_in_laststand() ) + { + continue; + } + players = get_players(); + playertorevive = undefined; + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ].revivetrigger ) || !isDefined( players[ i ].revivetrigger.createtime ) ) + { + i++; + continue; + } + else + { + if ( !isDefined( playertorevive ) || playertorevive.revivetrigger.createtime > players[ i ].revivetrigger.createtime ) + { + playertorevive = players[ i ]; + } + } + i++; + } + if ( isDefined( playertorevive ) ) + { + i = 0; + while ( i < players.size ) + { + if ( players[ i ] player_is_in_laststand() ) + { + i++; + continue; + } + else if ( getDvar( "g_gametype" ) == "vs" ) + { + if ( players[ i ].team != playertorevive.team ) + { + i++; + continue; + } + } + else if ( is_encounter() ) + { + if ( players[ i ].sessionteam != playertorevive.sessionteam ) + { + i++; + continue; + } + else if ( isDefined( level.hide_revive_message ) && level.hide_revive_message ) + { + i++; + continue; + } + } + else + { + players[ i ] thread faderevivemessageover( playertorevive, 3 ); + } + i++; + } + playertorevive.revivetrigger.createtime = undefined; + wait 3,5; + } + } +} + +faderevivemessageover( playertorevive, time ) +{ + revive_hud_show(); + self.revive_hud settext( &"ZOMBIE_PLAYER_NEEDS_TO_BE_REVIVED", playertorevive ); + self.revive_hud fadeovertime( time ); + self.revive_hud.alpha = 0; +} + +revive_hud_show() +{ +/# + assert( isDefined( self ) ); +#/ +/# + assert( isDefined( self.revive_hud ) ); +#/ + self.revive_hud.alpha = 1; +} + +revive_hud_show_n_fade( time ) +{ + revive_hud_show(); + self.revive_hud fadeovertime( time ); + self.revive_hud.alpha = 0; +} + +drawcylinder( pos, rad, height ) +{ +/# + currad = rad; + curheight = height; + r = 0; + while ( r < 20 ) + { + theta = ( r / 20 ) * 360; + theta2 = ( ( r + 1 ) / 20 ) * 360; + line( pos + ( cos( theta ) * currad, sin( theta ) * currad, 0 ), pos + ( cos( theta2 ) * currad, sin( theta2 ) * currad, 0 ) ); + line( pos + ( cos( theta ) * currad, sin( theta ) * currad, curheight ), pos + ( cos( theta2 ) * currad, sin( theta2 ) * currad, curheight ) ); + line( pos + ( cos( theta ) * currad, sin( theta ) * currad, 0 ), pos + ( cos( theta ) * currad, sin( theta ) * currad, curheight ) ); + r++; +#/ + } +} + +get_lives_remaining() +{ +/# + assert( level.laststandgetupallowed, "Lives only exist in the Laststand type GETUP." ); +#/ + if ( level.laststandgetupallowed && isDefined( self.laststand_info ) && isDefined( self.laststand_info.type_getup_lives ) ) + { + return max( 0, self.laststand_info.type_getup_lives ); + } + return 0; +} + +update_lives_remaining( increment ) +{ +/# + assert( level.laststandgetupallowed, "Lives only exist in the Laststand type GETUP." ); +#/ +/# + assert( isDefined( increment ), "Must specify increment true or false" ); +#/ + if ( isDefined( increment ) ) + { + } + else + { + } + increment = 0; + if ( increment ) + { + } + else + { + } + self.laststand_info.type_getup_lives = max( 0, self.laststand_info.type_getup_lives - 1, self.laststand_info.type_getup_lives + 1 ); + self notify( "laststand_lives_updated" ); +} + +player_getup_setup() +{ +/# + println( "ZM >> player_getup_setup called" ); +#/ + self.laststand_info = spawnstruct(); + self.laststand_info.type_getup_lives = level.const_laststand_getup_count_start; +} + +laststand_getup() +{ + self endon( "player_revived" ); + self endon( "disconnect" ); +/# + println( "ZM >> laststand_getup called" ); +#/ + self update_lives_remaining( 0 ); + setclientsysstate( "lsm", "1", self ); + self.laststand_info.getup_bar_value = level.const_laststand_getup_bar_start; + self thread laststand_getup_hud(); + self thread laststand_getup_damage_watcher(); + while ( self.laststand_info.getup_bar_value < 1 ) + { + self.laststand_info.getup_bar_value += level.const_laststand_getup_bar_regen; + wait 0,05; + } + self auto_revive( self ); + setclientsysstate( "lsm", "0", self ); +} + +laststand_getup_damage_watcher() +{ + self endon( "player_revived" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "damage" ); + self.laststand_info.getup_bar_value -= level.const_laststand_getup_bar_damage; + if ( self.laststand_info.getup_bar_value < 0 ) + { + self.laststand_info.getup_bar_value = 0; + } + } +} + +laststand_getup_hud() +{ + self endon( "player_revived" ); + self endon( "disconnect" ); + hudelem = newclienthudelem( self ); + hudelem.alignx = "left"; + hudelem.aligny = "middle"; + hudelem.horzalign = "left"; + hudelem.vertalign = "middle"; + hudelem.x = 5; + hudelem.y = 170; + hudelem.font = "big"; + hudelem.fontscale = 1,5; + hudelem.foreground = 1; + hudelem.hidewheninmenu = 1; + hudelem.hidewhendead = 1; + hudelem.sort = 2; + hudelem.label = &"SO_WAR_LASTSTAND_GETUP_BAR"; + self thread laststand_getup_hud_destroy( hudelem ); + while ( 1 ) + { + hudelem setvalue( self.laststand_info.getup_bar_value ); + wait 0,05; + } +} + +laststand_getup_hud_destroy( hudelem ) +{ + self waittill_either( "player_revived", "disconnect" ); + hudelem destroy(); +} + +check_for_sacrifice() +{ + self delay_notify( "sacrifice_denied", 1 ); + self endon( "sacrifice_denied" ); + self waittill( "player_downed" ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "sacrifices" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "sacrifices" ); +} + +check_for_failed_revive( playerbeingrevived ) +{ + self endon( "disconnect" ); + playerbeingrevived endon( "disconnect" ); + playerbeingrevived endon( "player_suicide" ); + self notify( "checking_for_failed_revive" ); + self endon( "checking_for_failed_revive" ); + playerbeingrevived endon( "player_revived" ); + playerbeingrevived waittill( "bled_out" ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "failed_revives" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "failed_revives" ); +} + +add_weighted_down() +{ + if ( !level.curr_gametype_affects_rank ) + { + return; + } + weighted_down = 1000; + if ( level.round_number > 0 ) + { + weighted_down = int( 1000 / ceil( level.round_number / 5 ) ); + } + self addplayerstat( "weighted_downs", weighted_down ); +} + +cleanup_laststand_on_disconnect() +{ + self endon( "player_revived" ); + self endon( "player_suicide" ); + self endon( "bled_out" ); + trig = self.revivetrigger; + self waittill( "disconnect" ); + if ( isDefined( trig ) ) + { + trig delete(); + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_magicbox_lock.gsc b/patch_zm/maps/mp/zombies/_zm_magicbox_lock.gsc new file mode 100644 index 0000000..72881ca --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_magicbox_lock.gsc @@ -0,0 +1,98 @@ +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_magicbox_lock; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + precachemodel( "p6_anim_zm_al_magic_box_lock_red" ); + level.locked_magic_box_cost = 2000; + level.custom_magicbox_state_handler = ::set_locked_magicbox_state; + add_zombie_hint( "locked_magic_box_cost", &"ZOMBIE_LOCKED_COST_2000" ); +} + +watch_for_lock() +{ + self endon( "user_grabbed_weapon" ); + self endon( "chest_accessed" ); + self waittill( "box_locked" ); + self notify( "kill_chest_think" ); + self.grab_weapon_hint = 0; + self.chest_user = undefined; + wait 0,1; + self thread maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.unitrigger_stub, ::magicbox_unitrigger_think ); + self.unitrigger_stub run_visibility_function_for_all_triggers(); + self thread treasure_chest_think(); +} + +clean_up_locked_box() +{ + self endon( "box_spin_done" ); + self.owner waittill( "box_locked" ); + if ( isDefined( self.weapon_model ) ) + { + self.weapon_model delete(); + self.weapon_model = undefined; + } + if ( isDefined( self.weapon_model_dw ) ) + { + self.weapon_model_dw delete(); + self.weapon_model_dw = undefined; + } + self hidezbarrierpiece( 3 ); + self hidezbarrierpiece( 4 ); + self setzbarrierpiecestate( 3, "closed" ); + self setzbarrierpiecestate( 4, "closed" ); +} + +magic_box_locks() +{ + self.owner.is_locked = 1; + self.owner notify( "box_locked" ); + self playsound( "zmb_hellbox_lock" ); + self setclientfield( "magicbox_open_fx", 0 ); + self setclientfield( "magicbox_amb_fx", 2 ); + self setzbarrierpiecestate( 5, "closing" ); + while ( self getzbarrierpiecestate( 5 ) == "closing" ) + { + wait 0,5; + } + self notify( "locked" ); +} + +magic_box_unlocks() +{ + maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.owner.unitrigger_stub ); + self playsound( "zmb_hellbox_unlock" ); + self setzbarrierpiecestate( 5, "opening" ); + while ( self getzbarrierpiecestate( 5 ) == "opening" ) + { + wait 0,5; + } + self setzbarrierpiecestate( 2, "closed" ); + self showzbarrierpiece( 2 ); + self hidezbarrierpiece( 5 ); + self notify( "unlocked" ); + self.owner.is_locked = 0; + maps/mp/zombies/_zm_unitrigger::register_unitrigger( self.owner.unitrigger_stub ); + self setclientfield( "magicbox_amb_fx", 1 ); +} + +set_locked_magicbox_state( state ) +{ + switch( state ) + { + case "locking": + self showzbarrierpiece( 5 ); + self thread magic_box_locks(); + self.state = "locking"; + break; + case "unlocking": + self showzbarrierpiece( 5 ); + self magic_box_unlocks(); + self.state = "close"; + break; + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_mgturret.gsc b/patch_zm/maps/mp/zombies/_zm_mgturret.gsc new file mode 100644 index 0000000..d3aee82 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_mgturret.gsc @@ -0,0 +1,339 @@ +#include common_scripts/utility; +#include maps/mp/_utility; + +main() +{ + if ( getDvar( #"7C9A91DF" ) == "" ) + { + setdvar( "mgTurret", "off" ); + } + level.magic_distance = 24; + turretinfos = getentarray( "turretInfo", "targetname" ); + index = 0; + while ( index < turretinfos.size ) + { + turretinfos[ index ] delete(); + index++; + } +} + +set_difficulty( difficulty ) +{ + init_turret_difficulty_settings(); + turrets = getentarray( "misc_turret", "classname" ); + index = 0; + while ( index < turrets.size ) + { + if ( isDefined( turrets[ index ].script_skilloverride ) ) + { + switch( turrets[ index ].script_skilloverride ) + { + case "easy": + difficulty = "easy"; + break; + break; + case "medium": + difficulty = "medium"; + break; + break; + case "hard": + difficulty = "hard"; + break; + break; + case "fu": + difficulty = "fu"; + break; + break; + default: + } + } + turret_set_difficulty( turrets[ index ], difficulty ); + index++; + } + } +} + +init_turret_difficulty_settings() +{ + level.mgturretsettings[ "easy" ][ "convergenceTime" ] = 2,5; + level.mgturretsettings[ "easy" ][ "suppressionTime" ] = 3; + level.mgturretsettings[ "easy" ][ "accuracy" ] = 0,38; + level.mgturretsettings[ "easy" ][ "aiSpread" ] = 2; + level.mgturretsettings[ "easy" ][ "playerSpread" ] = 0,5; + level.mgturretsettings[ "medium" ][ "convergenceTime" ] = 1,5; + level.mgturretsettings[ "medium" ][ "suppressionTime" ] = 3; + level.mgturretsettings[ "medium" ][ "accuracy" ] = 0,38; + level.mgturretsettings[ "medium" ][ "aiSpread" ] = 2; + level.mgturretsettings[ "medium" ][ "playerSpread" ] = 0,5; + level.mgturretsettings[ "hard" ][ "convergenceTime" ] = 0,8; + level.mgturretsettings[ "hard" ][ "suppressionTime" ] = 3; + level.mgturretsettings[ "hard" ][ "accuracy" ] = 0,38; + level.mgturretsettings[ "hard" ][ "aiSpread" ] = 2; + level.mgturretsettings[ "hard" ][ "playerSpread" ] = 0,5; + level.mgturretsettings[ "fu" ][ "convergenceTime" ] = 0,4; + level.mgturretsettings[ "fu" ][ "suppressionTime" ] = 3; + level.mgturretsettings[ "fu" ][ "accuracy" ] = 0,38; + level.mgturretsettings[ "fu" ][ "aiSpread" ] = 2; + level.mgturretsettings[ "fu" ][ "playerSpread" ] = 0,5; +} + +turret_set_difficulty( turret, difficulty ) +{ + turret.convergencetime = level.mgturretsettings[ difficulty ][ "convergenceTime" ]; + turret.suppressiontime = level.mgturretsettings[ difficulty ][ "suppressionTime" ]; + turret.accuracy = level.mgturretsettings[ difficulty ][ "accuracy" ]; + turret.aispread = level.mgturretsettings[ difficulty ][ "aiSpread" ]; + turret.playerspread = level.mgturretsettings[ difficulty ][ "playerSpread" ]; +} + +turret_suppression_fire( targets ) +{ + self endon( "death" ); + self endon( "stop_suppression_fire" ); + if ( !isDefined( self.suppresionfire ) ) + { + self.suppresionfire = 1; + } + for ( ;; ) + { + while ( self.suppresionfire ) + { + self settargetentity( targets[ randomint( targets.size ) ] ); + wait ( 2 + randomfloat( 2 ) ); + } + self cleartargetentity(); + while ( !self.suppresionfire ) + { + wait 1; + } + } +} + +burst_fire_settings( setting ) +{ + if ( setting == "delay" ) + { + return 0,2; + } + else + { + if ( setting == "delay_range" ) + { + return 0,5; + } + else + { + if ( setting == "burst" ) + { + return 0,5; + } + else + { + if ( setting == "burst_range" ) + { + return 4; + } + } + } + } +} + +burst_fire( turret, manual_target ) +{ + turret endon( "death" ); + turret endon( "stopfiring" ); + self endon( "stop_using_built_in_burst_fire" ); + if ( isDefined( turret.script_delay_min ) ) + { + turret_delay = turret.script_delay_min; + } + else + { + turret_delay = burst_fire_settings( "delay" ); + } + if ( isDefined( turret.script_delay_max ) ) + { + turret_delay_range = turret.script_delay_max - turret_delay; + } + else + { + turret_delay_range = burst_fire_settings( "delay_range" ); + } + if ( isDefined( turret.script_burst_min ) ) + { + turret_burst = turret.script_burst_min; + } + else + { + turret_burst = burst_fire_settings( "burst" ); + } + if ( isDefined( turret.script_burst_max ) ) + { + turret_burst_range = turret.script_burst_max - turret_burst; + } + else + { + turret_burst_range = burst_fire_settings( "burst_range" ); + } + while ( 1 ) + { + turret startfiring(); + if ( isDefined( manual_target ) ) + { + turret thread random_spread( manual_target ); + } + turret do_shoot(); + wait ( turret_burst + randomfloat( turret_burst_range ) ); + turret stopshootturret(); + turret stopfiring(); + wait ( turret_delay + randomfloat( turret_delay_range ) ); + } +} + +burst_fire_unmanned() +{ + self notify( "stop_burst_fire_unmanned" ); + self endon( "stop_burst_fire_unmanned" ); + self endon( "death" ); + self endon( "remote_start" ); + level endon( "game_ended" ); + if ( isDefined( self.controlled ) && self.controlled ) + { + return; + } + if ( isDefined( self.script_delay_min ) ) + { + turret_delay = self.script_delay_min; + } + else + { + turret_delay = burst_fire_settings( "delay" ); + } + if ( isDefined( self.script_delay_max ) ) + { + turret_delay_range = self.script_delay_max - turret_delay; + } + else + { + turret_delay_range = burst_fire_settings( "delay_range" ); + } + if ( isDefined( self.script_burst_min ) ) + { + turret_burst = self.script_burst_min; + } + else + { + turret_burst = burst_fire_settings( "burst" ); + } + if ( isDefined( self.script_burst_max ) ) + { + turret_burst_range = self.script_burst_max - turret_burst; + } + else + { + turret_burst_range = burst_fire_settings( "burst_range" ); + } + pauseuntiltime = getTime(); + turretstate = "start"; + self.script_shooting = 0; + for ( ;; ) + { + if ( isDefined( self.manual_targets ) ) + { + self cleartargetentity(); + self settargetentity( self.manual_targets[ randomint( self.manual_targets.size ) ] ); + } + duration = ( pauseuntiltime - getTime() ) * 0,001; + if ( self isfiringturret() && duration <= 0 ) + { + if ( turretstate != "fire" ) + { + turretstate = "fire"; + self playsound( "mpl_turret_alert" ); + self thread do_shoot(); + self.script_shooting = 1; + } + duration = turret_burst + randomfloat( turret_burst_range ); + self thread turret_timer( duration ); + self waittill( "turretstatechange" ); + self.script_shooting = 0; + duration = turret_delay + randomfloat( turret_delay_range ); + pauseuntiltime = getTime() + int( duration * 1000 ); + continue; + } + else + { + if ( turretstate != "aim" ) + { + turretstate = "aim"; + } + self thread turret_timer( duration ); + self waittill( "turretstatechange" ); + } + } +} + +avoid_synchronization( time ) +{ + if ( !isDefined( level._zm_mgturret_firing ) ) + { + level._zm_mgturret_firing = 0; + } + level._zm_mgturret_firing++; + wait time; + level._zm_mgturret_firing--; + +} + +do_shoot() +{ + self endon( "death" ); + self endon( "turretstatechange" ); + for ( ;; ) + { + while ( is_true( level._zm_mgturret_firing ) ) + { + wait 0,1; + } + thread avoid_synchronization( 0,1 ); + self shootturret(); + wait 0,112; + } +} + +turret_timer( duration ) +{ + if ( duration <= 0 ) + { + return; + } + self endon( "turretstatechange" ); + wait duration; + if ( isDefined( self ) ) + { + self notify( "turretstatechange" ); + } +} + +random_spread( ent ) +{ + self endon( "death" ); + self notify( "stop random_spread" ); + self endon( "stop random_spread" ); + self endon( "stopfiring" ); + self settargetentity( ent ); + self.manual_target = ent; + while ( 1 ) + { + if ( isplayer( ent ) ) + { + ent.origin = self.manual_target getorigin(); + } + else + { + ent.origin = self.manual_target.origin; + } + ent.origin += ( 20 - randomfloat( 40 ), 20 - randomfloat( 40 ), 20 - randomfloat( 60 ) ); + wait 0,2; + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_perks.gsc b/patch_zm/maps/mp/zombies/_zm_perks.gsc index 775d95c..7248a84 100644 --- a/patch_zm/maps/mp/zombies/_zm_perks.gsc +++ b/patch_zm/maps/mp/zombies/_zm_perks.gsc @@ -37,7 +37,6 @@ init() //checked partially changed to match cerberus output } initialize_custom_perk_arrays(); perk_machine_spawn_init(); - //not broken vending_weapon_upgrade_trigger = []; vending_triggers = getentarray( "zombie_vending", "targetname" ); for ( i = 0; i < vending_triggers.size; i++ ) @@ -450,7 +449,7 @@ can_pack_weapon( weaponname ) //checked did not match cebrerus output changed at } if ( flag( "pack_machine_in_use" ) ) { - return 0; //was 1 + return 1; } weaponname = self get_nonalternate_weapon( weaponname ); if ( !maps/mp/zombies/_zm_weapons::is_weapon_or_base_included( weaponname ) ) @@ -492,14 +491,17 @@ vending_machine_trigger_think() //changed 3/30/20 4:17 pm //checked matches cerb while( 1 ) { players = get_players(); - for ( i = 0; i < players.size; i++ ) + i = 0; + while ( i < players.size ) { if ( isdefined( self.pack_player ) && self.pack_player != players[ i ] || !players[ i ] player_use_can_pack_now() ) { self setinvisibletoplayer( players[ i ], 1 ); + i++; continue; } self setinvisibletoplayer( players[ i ], 0 ); + i++; } wait 0.1; } @@ -752,8 +754,7 @@ wait_for_player_to_take( player, weapon, packa_timer, upgrade_as_attachment ) // while ( 1 ) { packa_timer playloopsound( "zmb_perks_packa_ticktock" ); - self waittill( "trigger", trigger_player ); //working - + self waittill( "trigger", trigger_player ); if ( isDefined( level.pap_grab_by_anyone ) && level.pap_grab_by_anyone ) { player = trigger_player; @@ -773,7 +774,7 @@ wait_for_player_to_take( player, weapon, packa_timer, upgrade_as_attachment ) // #/ } */ - if ( is_player_valid( player ) && !player.is_drinking > 0 && !is_placeable_mine( current_weapon ) && !is_equipment( current_weapon ) && level.revive_tool != current_weapon && current_weapon != "none" && !player hacker_active() ) + if ( is_player_valid( player ) && !player.is_drinking && !is_placeable_mine( current_weapon ) && !is_equipment( current_weapon ) && level.revive_tool != current_weapon && current_weapon != "none" && !player hacker_active() ) { maps/mp/_demo::bookmark( "zm_player_grabbed_packapunch", getTime(), player ); self notify( "pap_taken" ); @@ -816,7 +817,7 @@ wait_for_player_to_take( player, weapon, packa_timer, upgrade_as_attachment ) // return; } } - wait 0.05; + //wait 0.05; } } @@ -841,15 +842,11 @@ wait_for_disconnect( player ) //checked //checked matches cerberus output { self endon( "pap_taken" ); self endon( "pap_timeout" ); + name = player.name; while ( isDefined( player ) ) { wait 0.1; } - /* -/# - println( "*** PAP : User disconnected." ); -#/ - */ self notify( "pap_player_disconnected" ); } @@ -1604,7 +1601,10 @@ electric_perks_dialog() //checked partially changed to match cerberus output i++; continue; } - else dist = distancesquared( players[ i ].origin, self.origin ); + else + { + dist = distancesquared( players[ i ].origin, self.origin ); + } if ( dist > 4900 ) { timer = 0; @@ -1853,72 +1853,34 @@ vending_trigger_think() //checked changed to match cerberus output for ( ;; ) { self waittill( "trigger", player ); - if ( level.debugLogging_zm_perks ) - { - if ( !isDefined( player ) ) - { - logline10 = "_zm_perks.gsc vending_trigger_think() player is not defined for trigger!" + "\n"; - logprint( logline10 ); - } - } index = maps/mp/zombies/_zm_weapons::get_player_index( player ); if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( player.intermission ) && player.intermission ) { - if ( level.debugLogging_zm_perks ) - { - logline11 = "_zm_perks.gsc vending_trigger_think() player is in laststand or game is intermission; continue" + "\n"; - logprint( logline11 ); - } wait 0.1; continue; } if ( player in_revive_trigger() ) { - if ( level.debugLogging_zm_perks ) - { - logline11 = "_zm_perks.gsc vending_trigger_think() player is in revive trigger; continue" + "\n"; - logprint( logline11 ); - } wait 0.1; continue; } if ( !player maps/mp/zombies/_zm_magicbox::can_buy_weapon() ) { - if ( level.debugLogging_zm_perks ) - { - logline12 = "_zm_perks.gsc vending_trigger_think() player is in revive trigger; continue" + "\n"; - logprint( logline12 ); - } wait 0.1; continue; } if ( player isthrowinggrenade() ) { - if ( level.debugLogging_zm_perks ) - { - logline13 = "_zm_perks.gsc vending_trigger_think() player is throwing grenade; continue" + "\n"; - logprint( logline13 ); - } wait 0.1; continue; } if ( player isswitchingweapons() ) { - if ( level.debugLogging_zm_perks ) - { - logline14 = "_zm_perks.gsc vending_trigger_think() player is switching weapons; continue" + "\n"; - logprint( logline14 ); - } wait 0.1; continue; } if ( player.is_drinking > 0 ) { - if ( level.debugLogging_zm_perks ) - { - logline15 = "_zm_perks.gsc vending_trigger_think() player is drinking; continue" + "\n"; - logprint( logline15 ); - } wait 0.1; continue; } @@ -1935,11 +1897,6 @@ vending_trigger_think() //checked changed to match cerberus output */ if ( cheat != 1 ) { - if ( level.debugLogging_zm_perks ) - { - logline16 = "_zm_perks.gsc vending_trigger_think() player has perk; continue!" + "\n"; - logprint( logline16 ); - } self playsound( "deny" ); player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "perk_deny", undefined, 1 ); continue; @@ -1950,11 +1907,6 @@ vending_trigger_think() //checked changed to match cerberus output valid = self [[ level.custom_perk_validation ]]( player ); if ( !valid ) { - if ( level.debugLogging_zm_perks ) - { - logline17 = "_zm_perks.gsc vending_trigger_think() [[ level.custom_perk_validation ]] determines player is not eligble for perk; continue" + "\n"; - logprint( logline17 ); - } continue; } } @@ -1965,11 +1917,6 @@ vending_trigger_think() //checked changed to match cerberus output } if ( player.score < current_cost ) { - if ( level.debugLogging_zm_perks ) - { - logline18 = "_zm_perks.gsc vending_trigger_think() player does not have enough points for perk; continue" + "\n"; - logprint( logline18 ); - } self playsound( "evt_perk_deny" ); player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "perk_deny", undefined, 0 ); continue; @@ -1977,11 +1924,6 @@ vending_trigger_think() //checked changed to match cerberus output if ( player.num_perks >= player get_player_perk_purchase_limit() ) { - if ( level.debugLogging_zm_perks ) - { - logline19 = "_zm_perks.gsc vending_trigger_think() player has reach their perk limit; continue" + "\n"; - logprint( logline19 ); - } self playsound( "evt_perk_deny" ); player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sigh" ); continue; @@ -2001,32 +1943,11 @@ vending_trigger_post_think( player, perk ) //checked matches cerberus output player endon( "end_game" ); player endon( "perk_abort_drinking" ); gun = player perk_give_bottle_begin( perk ); - if ( level.debugLogging_zm_perks ) - { - logline29 = "_zm_perks.gsc vending_trigger_post_think(); perk_give_bottle_begin() completed its operation " + " \n"; - logprint( logline29 ); - } evt = player waittill_any_return( "fake_death", "death", "player_downed", "weapon_change_complete" ); - //evt = waittill( "weapon_change_complete" ); - if ( level.debugLogging_zm_perks ) - { - logline28 = "_zm_perks.gsc vending_trigger_post_think() finished waiting for event: " + evt + " \n"; - logprint( logline28 ); - } if ( evt == "weapon_change_complete" ) { - if ( level.debugLogging_zm_perks ) - { - logline26 = "_zm_perks.gsc vending_trigger_post_think() weapon_change_complete occured calling wait_give_perk() " + " \n"; - logprint( logline26 ); - } player thread wait_give_perk( perk, 1 ); } - if ( level.debugLogging_zm_perks ) - { - logline27 = "_zm_perks.gsc vending_trigger_post_think(); wait_give_perk() finished; calling perk_give_bottle_end() " + " \n"; - logprint( logline27 ); - } player perk_give_bottle_end( gun, perk ); if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( player.intermission ) && player.intermission ) { @@ -2091,11 +2012,6 @@ wait_give_perk( perk, bought ) //checked matches cerberus output self endon( "end_game" ); self endon( "perk_abort_drinking" ); self waittill_notify_or_timeout( "burp", 0.5 ); - if ( level.debugLogging_zm_perks ) - { - logline23 = "_zm_perks.gsc wait_give_perk() gives player a perk" + "\n"; - logprint( logline23 ); - } self give_perk( perk, bought ); } @@ -2116,11 +2032,6 @@ return_retained_perks() //checked changed to match cerberus output give_perk( perk, bought ) //checked changed to match cerberus output { - if ( level.debugLogging_zm_perks ) - { - logline24 = "_zm_perks.gsc give_perk() gives player perk: " + perk + " \n"; - logprint( logline24 ); - } self setperk( perk ); self.num_perks++; if ( isDefined( bought ) && bought ) @@ -2204,11 +2115,6 @@ give_perk( perk, bought ) //checked changed to match cerberus output } self.perks_active[ self.perks_active.size ] = perk; self notify( "perk_acquired" ); - if ( level.debugLogging_zm_perks ) - { - logline25 = "_zm_perks.gsc give_perk() calls perk_think" + " \n"; - logprint( logline25 ); - } self thread perk_think( perk ); } @@ -2578,18 +2484,8 @@ perk_give_bottle_begin( perk ) //checked matches cerberus output { weapon = level._custom_perks[ perk ].perk_bottle; } - if ( level.debugLogging_zm_perks ) - { - logline20 = "_zm_perks.gsc perk_give_bottle_begin() gives perk bottle to player" + "\n"; - logprint( logline20 ); - } self giveweapon( weapon ); self switchtoweapon( weapon ); - if ( level.debugLogging_zm_perks ) - { - logline21 = "_zm_perks.gsc perk_give_bottle_begin() returns gun" + "\n"; - logprint( logline21 ); - } return gun; } @@ -2689,11 +2585,7 @@ perk_give_bottle_end( gun, perk ) //checked matches cerberus output { self decrement_is_drinking(); } - if ( level.debugLogging_zm_perks ) - { - logline22 = "_zm_perks.gsc perk_give_bottle_end() finishes returning gun to player" + "\n"; - logprint( logline22 ); - } + } perk_abort_drinking( post_delay ) //checked matches cerberus output @@ -3075,90 +2967,40 @@ perk_machine_spawn_init() } if ( match_string == "zclassic_perks_rooftop" || match_string == "zclassic_perks_tomb" || match_string == "zstandard_perks_nuked" ) { - if ( level.debugLogging_zm_perks ) - { - logline1 = "_zm_perks.gsc: perk_machine_spawn_init() uses default location " + "\n"; - logprint( logline1 ); - } useDefaultLocation = 1; } - if ( level.debugLogging_zm_perks ) - { - logline2 = "_zm_perks.gsc: perk_machine_spawn_init() found: " + structs.size + " zm_perk_machines" + " \n"; - logprint( logline2 ); - } i = 0; while ( i < structs.size ) { if ( isdefined( structs[ i ].script_string ) ) { tokens = strtok( structs[ i ].script_string, " " ); - if ( level.debugLogging_zm_perks ) - { - logline3 = "_zm_perks.gsc: perk_machine_spawn_init() found: " + tokens.size + " match_strings" + " \n"; - logprint( logline3 ); - } k = 0; while ( k < tokens.size ) { if ( tokens[ k ] == match_string ) { - if ( level.debugLogging_zm_perks ) - { - logline4 = "_zm_perks.gsc: perk_machine_spawn_init() found that token matches match_string, setting perk location to match_string location" + " \n"; - logprint( logline4 ); - } pos[ pos.size ] = structs[ i ]; - k++; - } - else - { - if ( level.debugLogging_zm_perks ) - { - logline5 = "_zm_perks.gsc: perk_machine_spawn_init() found that token did not match match_string, skipping " + "\n"; - logprint( logline5 ); - } - //pos[ pos.size ] = structs[ i ]; - k++; } + k++; } } else if ( isDefined( useDefaultLocation ) && useDefaultLocation ) { - if ( level.debugLogging_zm_perks ) - { - logline6 = "_zm_perks.gsc: perk_machine_spawn_init() found that map only has one location, setting to match_string by default " + "\n"; - logprint( logline6 ); - } pos[ pos.size ] = structs[ i ]; } i++; } if ( !IsDefined( pos ) || pos.size == 0 ) { - if ( level.debugLogging_zm_perks ) - { - logline7 = "_zm_perks.gsc: perk_machine_spawn_init() returning because pos is undefined or pos.size is 0 " + "\n"; - logprint( logline7 ); - } return; } PreCacheModel("zm_collision_perks1"); for ( i = 0; i < pos.size; i++ ) { perk = pos[ i ].script_noteworthy; - if ( level.debugLogging_zm_perks ) - { - logline8 = "_zm_perks.gsc: perk_machine_spawn_init() checking perk: " + perk + " \n"; - logprint( logline8 ); - } if ( IsDefined( perk ) && IsDefined( pos[ i ].model ) ) { - if ( level.debugLogging_zm_perks ) - { - logline9 = "_zm_perks.gsc: perk_machine_spawn_init() found perk and perk model; spawning in: " + perk + " \n"; - logprint( logline9 ); - } use_trigger = Spawn( "trigger_radius_use", pos[ i ].origin + ( 0, 0, 30 ), 0, 40, 70 ); use_trigger.targetname = "zombie_vending"; use_trigger.script_noteworthy = perk; @@ -3350,11 +3192,6 @@ perk_machine_spawn_init() if ( isdefined( level._custom_perks[ perk ] ) && isdefined( level._custom_perks[ perk ].perk_machine_set_kvps ) ) { [[ level._custom_perks[ perk ].perk_machine_set_kvps ]]( use_trigger, perk_machine, bump_trigger, collision ); - if ( level.debugLogging_zm_perks ) - { - logline30 = "_zm_perks.gsc: perk_machine_spawn_init() called level._custom_perks[ perk ].perk_machine_set_kvps on perk: " + perk + " \n"; - logprint( logline30 ); - } } break; } @@ -4098,3 +3935,6 @@ _register_undefined_perk( str_perk ) //checked matches cerberus output + + + diff --git a/patch_zm/maps/mp/zombies/_zm_playerhealth.gsc b/patch_zm/maps/mp/zombies/_zm_playerhealth.gsc new file mode 100644 index 0000000..5c641f1 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_playerhealth.gsc @@ -0,0 +1,583 @@ +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !isDefined( level.script ) ) + { + level.script = tolower( getDvar( "mapname" ) ); + } + precacheshader( "overlay_low_health" ); + level.global_damage_func_ads = ::empty_kill_func; + level.global_damage_func = ::empty_kill_func; + level.difficultytype[ 0 ] = "easy"; + level.difficultytype[ 1 ] = "normal"; + level.difficultytype[ 2 ] = "hardened"; + level.difficultytype[ 3 ] = "veteran"; + level.difficultystring[ "easy" ] = &"GAMESKILL_EASY"; + level.difficultystring[ "normal" ] = &"GAMESKILL_NORMAL"; + level.difficultystring[ "hardened" ] = &"GAMESKILL_HARDENED"; + level.difficultystring[ "veteran" ] = &"GAMESKILL_VETERAN"; +/# + thread playerhealthdebug(); +#/ + level.gameskill = 1; + switch( level.gameskill ) + { + case 0: + setdvar( "currentDifficulty", "easy" ); + break; + case 1: + setdvar( "currentDifficulty", "normal" ); + break; + case 2: + setdvar( "currentDifficulty", "hardened" ); + break; + case 3: + setdvar( "currentDifficulty", "veteran" ); + break; + } + logstring( "difficulty: " + level.gameskill ); + level.player_deathinvulnerabletime = 1700; + level.longregentime = 5000; + level.healthoverlaycutoff = 0,2; + level.invultime_preshield = 0,35; + level.invultime_onshield = 0,5; + level.invultime_postshield = 0,3; + level.playerhealth_regularregendelay = 2400; + level.worthydamageratio = 0,1; + setdvar( "player_meleeDamageMultiplier", 0,4 ); + onplayerconnect_callback( ::onplayerconnect ); +} + +onplayerconnect() +{ + self thread onplayerspawned(); +} + +onplayerspawned() +{ + for ( ;; ) + { + self waittill( "spawned_player" ); + self maps/mp/zombies/_zm_perks::perk_set_max_health_if_jugg( "health_reboot", 1, 0 ); + if ( level.createfx_enabled ) + { + continue; + } + else + { + self notify( "noHealthOverlay" ); + self thread playerhealthregen(); + } + } +} + +playerhurtcheck() +{ + self endon( "noHealthOverlay" ); + self.hurtagain = 0; + for ( ;; ) + { + self waittill( "damage", amount, attacker, dir, point, mod ); + if ( isDefined( attacker ) && isplayer( attacker ) && attacker.team == self.team ) + { + continue; + } + else + { + self.hurtagain = 1; + self.damagepoint = point; + self.damageattacker = attacker; + } + } +} + +playerhealthregen() +{ + self notify( "playerHealthRegen" ); + self endon( "playerHealthRegen" ); + self endon( "death" ); + self endon( "disconnect" ); + if ( !isDefined( self.flag ) ) + { + self.flag = []; + self.flags_lock = []; + } + if ( !isDefined( self.flag[ "player_has_red_flashing_overlay" ] ) ) + { + self player_flag_init( "player_has_red_flashing_overlay" ); + self player_flag_init( "player_is_invulnerable" ); + } + self player_flag_clear( "player_has_red_flashing_overlay" ); + self player_flag_clear( "player_is_invulnerable" ); + self thread healthoverlay(); + oldratio = 1; + health_add = 0; + regenrate = 0,1; + veryhurt = 0; + playerjustgotredflashing = 0; + invultime = 0; + hurttime = 0; + newhealth = 0; + lastinvulratio = 1; + self thread playerhurtcheck(); + if ( !isDefined( self.veryhurt ) ) + { + self.veryhurt = 0; + } + self.bolthit = 0; + if ( getDvar( "scr_playerInvulTimeScale" ) == "" ) + { + setdvar( "scr_playerInvulTimeScale", 1 ); + } + playerinvultimescale = getDvarFloat( "scr_playerInvulTimeScale" ); + for ( ;; ) + { + wait 0,05; + waittillframeend; + if ( self.health == self.maxhealth ) + { + if ( self player_flag( "player_has_red_flashing_overlay" ) ) + { + player_flag_clear( "player_has_red_flashing_overlay" ); + } + lastinvulratio = 1; + playerjustgotredflashing = 0; + veryhurt = 0; + continue; + } + else if ( self.health <= 0 ) + { +/# + showhitlog(); +#/ + return; + } + wasveryhurt = veryhurt; + health_ratio = self.health / self.maxhealth; + if ( health_ratio <= level.healthoverlaycutoff ) + { + veryhurt = 1; + if ( !wasveryhurt ) + { + hurttime = getTime(); + self startfadingblur( 3,6, 2 ); + self player_flag_set( "player_has_red_flashing_overlay" ); + playerjustgotredflashing = 1; + } + } + if ( self.hurtagain ) + { + hurttime = getTime(); + self.hurtagain = 0; + } + if ( health_ratio >= oldratio ) + { + if ( ( getTime() - hurttime ) < level.playerhealth_regularregendelay ) + { + continue; + } + else if ( veryhurt ) + { + self.veryhurt = 1; + newhealth = health_ratio; + if ( getTime() > ( hurttime + level.longregentime ) ) + { + newhealth += regenrate; + } + } + else + { + newhealth = 1; + self.veryhurt = 0; + } + if ( newhealth > 1 ) + { + newhealth = 1; + } + if ( newhealth <= 0 ) + { + return; + } +/# + if ( newhealth > health_ratio ) + { + logregen( newhealth ); +#/ + } + self setnormalhealth( newhealth ); + oldratio = self.health / self.maxhealth; + continue; + } + else invulworthyhealthdrop = ( lastinvulratio - health_ratio ) > level.worthydamageratio; + if ( self.health <= 1 ) + { + self setnormalhealth( 2 / self.maxhealth ); + invulworthyhealthdrop = 1; +/# + if ( !isDefined( level.player_deathinvulnerabletimeout ) ) + { + level.player_deathinvulnerabletimeout = 0; + } + if ( level.player_deathinvulnerabletimeout < getTime() ) + { + level.player_deathinvulnerabletimeout = getTime() + getDvarInt( "player_deathInvulnerableTime" ); +#/ + } + } + oldratio = self.health / self.maxhealth; + level notify( "hit_again" ); + health_add = 0; + hurttime = getTime(); + self startfadingblur( 3, 0,8 ); + if ( !invulworthyhealthdrop || playerinvultimescale <= 0 ) + { +/# + loghit( self.health, 0 ); +#/ + continue; + } + else + { + if ( self player_flag( "player_is_invulnerable" ) ) + { + break; + } + else + { + self player_flag_set( "player_is_invulnerable" ); + level notify( "player_becoming_invulnerable" ); + if ( playerjustgotredflashing ) + { + invultime = level.invultime_onshield; + playerjustgotredflashing = 0; + } + else if ( veryhurt ) + { + invultime = level.invultime_postshield; + } + else + { + invultime = level.invultime_preshield; + } + invultime *= playerinvultimescale; +/# + loghit( self.health, invultime ); +#/ + lastinvulratio = self.health / self.maxhealth; + self thread playerinvul( invultime ); + } + } + } +} + +playerinvul( timer ) +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( timer > 0 ) + { +/# + level.playerinvultimeend = getTime() + ( timer * 1000 ); +#/ + wait timer; + } + self player_flag_clear( "player_is_invulnerable" ); +} + +healthoverlay() +{ + self endon( "disconnect" ); + self endon( "noHealthOverlay" ); + if ( !isDefined( self._health_overlay ) ) + { + self._health_overlay = newclienthudelem( self ); + self._health_overlay.x = 0; + self._health_overlay.y = 0; + self._health_overlay setshader( "overlay_low_health", 640, 480 ); + self._health_overlay.alignx = "left"; + self._health_overlay.aligny = "top"; + self._health_overlay.horzalign = "fullscreen"; + self._health_overlay.vertalign = "fullscreen"; + self._health_overlay.alpha = 0; + } + overlay = self._health_overlay; + self thread healthoverlay_remove( overlay ); + self thread watchhideredflashingoverlay( overlay ); + pulsetime = 0,8; + for ( ;; ) + { + if ( overlay.alpha > 0 ) + { + overlay fadeovertime( 0,5 ); + } + overlay.alpha = 0; + self player_flag_wait( "player_has_red_flashing_overlay" ); + self redflashingoverlay( overlay ); + } +} + +fadefunc( overlay, severity, mult, hud_scaleonly ) +{ + pulsetime = 0,8; + scalemin = 0,5; + fadeintime = pulsetime * 0,1; + stayfulltime = pulsetime * ( 0,1 + ( severity * 0,2 ) ); + fadeouthalftime = pulsetime * ( 0,1 + ( severity * 0,1 ) ); + fadeoutfulltime = pulsetime * 0,3; + remainingtime = pulsetime - fadeintime - stayfulltime - fadeouthalftime - fadeoutfulltime; +/# + assert( remainingtime >= -0,001 ); +#/ + if ( remainingtime < 0 ) + { + remainingtime = 0; + } + halfalpha = 0,8 + ( severity * 0,1 ); + leastalpha = 0,5 + ( severity * 0,3 ); + overlay fadeovertime( fadeintime ); + overlay.alpha = mult * 1; + wait ( fadeintime + stayfulltime ); + overlay fadeovertime( fadeouthalftime ); + overlay.alpha = mult * halfalpha; + wait fadeouthalftime; + overlay fadeovertime( fadeoutfulltime ); + overlay.alpha = mult * leastalpha; + wait fadeoutfulltime; + wait remainingtime; +} + +watchhideredflashingoverlay( overlay ) +{ + self endon( "death_or_disconnect" ); + while ( isDefined( overlay ) ) + { + self waittill( "clear_red_flashing_overlay" ); + self player_flag_clear( "player_has_red_flashing_overlay" ); + overlay fadeovertime( 0,05 ); + overlay.alpha = 0; + setclientsysstate( "levelNotify", "rfo3", self ); + self notify( "hit_again" ); + } +} + +redflashingoverlay( overlay ) +{ + self endon( "hit_again" ); + self endon( "damage" ); + self endon( "death" ); + self endon( "disconnect" ); + self endon( "clear_red_flashing_overlay" ); + self.stopflashingbadlytime = getTime() + level.longregentime; + if ( isDefined( self.is_in_process_of_zombify ) && !self.is_in_process_of_zombify && isDefined( self.is_zombie ) && !self.is_zombie ) + { + fadefunc( overlay, 1, 1, 0 ); + while ( getTime() < self.stopflashingbadlytime && isalive( self ) && isDefined( self.is_in_process_of_zombify ) && !self.is_in_process_of_zombify && isDefined( self.is_zombie ) && !self.is_zombie ) + { + fadefunc( overlay, 0,9, 1, 0 ); + } + if ( isDefined( self.is_in_process_of_zombify ) && !self.is_in_process_of_zombify && isDefined( self.is_zombie ) && !self.is_zombie ) + { + if ( isalive( self ) ) + { + fadefunc( overlay, 0,65, 0,8, 0 ); + } + fadefunc( overlay, 0, 0,6, 1 ); + } + } + overlay fadeovertime( 0,5 ); + overlay.alpha = 0; + self player_flag_clear( "player_has_red_flashing_overlay" ); + setclientsysstate( "levelNotify", "rfo3", self ); + wait 0,5; + self notify( "hit_again" ); +} + +healthoverlay_remove( overlay ) +{ + self endon( "disconnect" ); + self waittill_any( "noHealthOverlay", "death" ); + overlay fadeovertime( 3,5 ); + overlay.alpha = 0; +} + +empty_kill_func( type, loc, point, attacker, amount ) +{ +} + +loghit( newhealth, invultime ) +{ +/# +#/ +} + +logregen( newhealth ) +{ +/# +#/ +} + +showhitlog() +{ +/# +#/ +} + +playerhealthdebug() +{ +/# + if ( getDvar( "scr_health_debug" ) == "" ) + { + setdvar( "scr_health_debug", "0" ); + } + waittillframeend; + while ( 1 ) + { + while ( 1 ) + { + if ( getDvar( "scr_health_debug" ) != "0" ) + { + break; + } + else + { + wait 0,5; + } + } + thread printhealthdebug(); + while ( 1 ) + { + if ( getDvar( "scr_health_debug" ) == "0" ) + { + break; + } + else + { + wait 0,5; + } + } + level notify( "stop_printing_grenade_timers" ); + destroyhealthdebug(); +#/ + } +} + +printhealthdebug() +{ +/# + level notify( "stop_printing_health_bars" ); + level endon( "stop_printing_health_bars" ); + x = 40; + y = 40; + level.healthbarhudelems = []; + level.healthbarkeys[ 0 ] = "Health"; + level.healthbarkeys[ 1 ] = "No Hit Time"; + level.healthbarkeys[ 2 ] = "No Die Time"; + if ( !isDefined( level.playerinvultimeend ) ) + { + level.playerinvultimeend = 0; + } + if ( !isDefined( level.player_deathinvulnerabletimeout ) ) + { + level.player_deathinvulnerabletimeout = 0; + } + i = 0; + while ( i < level.healthbarkeys.size ) + { + key = level.healthbarkeys[ i ]; + textelem = newhudelem(); + textelem.x = x; + textelem.y = y; + textelem.alignx = "left"; + textelem.aligny = "top"; + textelem.horzalign = "fullscreen"; + textelem.vertalign = "fullscreen"; + textelem settext( key ); + bgbar = newhudelem(); + bgbar.x = x + 79; + bgbar.y = y + 1; + bgbar.alignx = "left"; + bgbar.aligny = "top"; + bgbar.horzalign = "fullscreen"; + bgbar.vertalign = "fullscreen"; + bgbar.maxwidth = 3; + bgbar setshader( "white", bgbar.maxwidth, 10 ); + bgbar.color = vectorScale( ( 1, 1, 1 ), 0,5 ); + bar = newhudelem(); + bar.x = x + 80; + bar.y = y + 2; + bar.alignx = "left"; + bar.aligny = "top"; + bar.horzalign = "fullscreen"; + bar.vertalign = "fullscreen"; + bar setshader( "black", 1, 8 ); + textelem.bar = bar; + textelem.bgbar = bgbar; + textelem.key = key; + y += 10; + level.healthbarhudelems[ key ] = textelem; + i++; + } + flag_wait( "start_zombie_round_logic" ); + while ( 1 ) + { + wait 0,05; + players = get_players(); + i = 0; + while ( i < level.healthbarkeys.size && players.size > 0 ) + { + key = level.healthbarkeys[ i ]; + player = players[ 0 ]; + width = 0; + if ( i == 0 ) + { + width = ( player.health / player.maxhealth ) * 300; + } + else if ( i == 1 ) + { + width = ( ( level.playerinvultimeend - getTime() ) / 1000 ) * 40; + } + else + { + if ( i == 2 ) + { + width = ( ( level.player_deathinvulnerabletimeout - getTime() ) / 1000 ) * 40; + } + } + width = int( max( width, 1 ) ); + width = int( min( width, 300 ) ); + bar = level.healthbarhudelems[ key ].bar; + bar setshader( "black", width, 8 ); + bgbar = level.healthbarhudelems[ key ].bgbar; + if ( ( width + 2 ) > bgbar.maxwidth ) + { + bgbar.maxwidth = width + 2; + bgbar setshader( "white", bgbar.maxwidth, 10 ); + bgbar.color = vectorScale( ( 1, 1, 1 ), 0,5 ); + } + i++; + } +#/ + } +} + +destroyhealthdebug() +{ +/# + if ( !isDefined( level.healthbarhudelems ) ) + { + return; + } + i = 0; + while ( i < level.healthbarkeys.size ) + { + level.healthbarhudelems[ level.healthbarkeys[ i ] ].bgbar destroy(); + level.healthbarhudelems[ level.healthbarkeys[ i ] ].bar destroy(); + level.healthbarhudelems[ level.healthbarkeys[ i ] ] destroy(); + i++; +#/ + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_power.gsc b/patch_zm/maps/mp/zombies/_zm_power.gsc new file mode 100644 index 0000000..f46d80e --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_power.gsc @@ -0,0 +1,741 @@ +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !isDefined( level.powered_items ) ) + { + level.powered_items = []; + } + if ( !isDefined( level.local_power ) ) + { + level.local_power = []; + } + thread standard_powered_items(); +/# + thread debug_powered_items(); +#/ +} + +debug_powered_items() +{ +/# + while ( 1 ) + { + while ( getDvarInt( #"EB512CB7" ) ) + { + while ( isDefined( level.local_power ) ) + { + _a32 = level.local_power; + _k32 = getFirstArrayKey( _a32 ); + while ( isDefined( _k32 ) ) + { + localpower = _a32[ _k32 ]; + circle( localpower.origin, localpower.radius, ( 0, 0, 1 ), 0, 1, 1 ); + _k32 = getNextArrayKey( _a32, _k32 ); + } + } + } + wait 0,05; +#/ + } +} + +watch_global_power() +{ + while ( 1 ) + { + flag_wait( "power_on" ); + level thread set_global_power( 1 ); + flag_waitopen( "power_on" ); + level thread set_global_power( 0 ); + } +} + +standard_powered_items() +{ + flag_wait( "start_zombie_round_logic" ); + vending_triggers = getentarray( "zombie_vending", "targetname" ); + _a67 = vending_triggers; + _k67 = getFirstArrayKey( _a67 ); + while ( isDefined( _k67 ) ) + { + trigger = _a67[ _k67 ]; + if ( trigger.script_noteworthy == "specialty_weapupgrade" ) + { + } + else + { + powered_on = maps/mp/zombies/_zm_perks::get_perk_machine_start_state( trigger.script_noteworthy ); + add_powered_item( ::perk_power_on, ::perk_power_off, ::perk_range, ::cost_low_if_local, 0, powered_on, trigger ); + } + _k67 = getNextArrayKey( _a67, _k67 ); + } + pack_a_punch = getentarray( "specialty_weapupgrade", "script_noteworthy" ); + _a77 = pack_a_punch; + _k77 = getFirstArrayKey( _a77 ); + while ( isDefined( _k77 ) ) + { + trigger = _a77[ _k77 ]; + powered_on = maps/mp/zombies/_zm_perks::get_perk_machine_start_state( trigger.script_noteworthy ); + trigger.powered = add_powered_item( ::pap_power_on, ::pap_power_off, ::pap_range, ::cost_low_if_local, 0, powered_on, trigger ); + _k77 = getNextArrayKey( _a77, _k77 ); + } + zombie_doors = getentarray( "zombie_door", "targetname" ); + _a86 = zombie_doors; + _k86 = getFirstArrayKey( _a86 ); + while ( isDefined( _k86 ) ) + { + door = _a86[ _k86 ]; + if ( isDefined( door.script_noteworthy ) && door.script_noteworthy == "electric_door" ) + { + add_powered_item( ::door_power_on, ::door_power_off, ::door_range, ::cost_door, 0, 0, door ); + } + else + { + if ( isDefined( door.script_noteworthy ) && door.script_noteworthy == "local_electric_door" ) + { + power_sources = 0; + if ( isDefined( level.power_local_doors_globally ) && !level.power_local_doors_globally ) + { + power_sources = 1; + } + add_powered_item( ::door_local_power_on, ::door_local_power_off, ::door_range, ::cost_door, power_sources, 0, door ); + } + } + _k86 = getNextArrayKey( _a86, _k86 ); + } + thread watch_global_power(); +} + +add_powered_item( power_on_func, power_off_func, range_func, cost_func, power_sources, self_powered, target ) +{ + powered = spawnstruct(); + powered.power_on_func = power_on_func; + powered.power_off_func = power_off_func; + powered.range_func = range_func; + powered.power_sources = power_sources; + powered.self_powered = self_powered; + powered.target = target; + powered.cost_func = cost_func; + powered.power = self_powered; + powered.powered_count = self_powered; + powered.depowered_count = 0; + if ( !isDefined( level.powered_items ) ) + { + level.powered_items = []; + } + level.powered_items[ level.powered_items.size ] = powered; + return powered; +} + +remove_powered_item( powered ) +{ + arrayremovevalue( level.powered_items, powered, 0 ); +} + +add_temp_powered_item( power_on_func, power_off_func, range_func, cost_func, power_sources, self_powered, target ) +{ + powered = add_powered_item( power_on_func, power_off_func, range_func, cost_func, power_sources, self_powered, target ); + while ( isDefined( level.local_power ) ) + { + _a140 = level.local_power; + _k140 = getFirstArrayKey( _a140 ); + while ( isDefined( _k140 ) ) + { + localpower = _a140[ _k140 ]; + if ( powered [[ powered.range_func ]]( 1, localpower.origin, localpower.radius ) ) + { + powered change_power( 1, localpower.origin, localpower.radius ); + if ( !isDefined( localpower.added_list ) ) + { + localpower.added_list = []; + } + localpower.added_list[ localpower.added_list.size ] = powered; + } + _k140 = getNextArrayKey( _a140, _k140 ); + } + } + thread watch_temp_powered_item( powered ); + return powered; +} + +watch_temp_powered_item( powered ) +{ + powered.target waittill( "death" ); + remove_powered_item( powered ); + while ( isDefined( level.local_power ) ) + { + _a161 = level.local_power; + _k161 = getFirstArrayKey( _a161 ); + while ( isDefined( _k161 ) ) + { + localpower = _a161[ _k161 ]; + if ( isDefined( localpower.added_list ) ) + { + arrayremovevalue( localpower.added_list, powered, 0 ); + } + if ( isDefined( localpower.enabled_list ) ) + { + arrayremovevalue( localpower.enabled_list, powered, 0 ); + } + _k161 = getNextArrayKey( _a161, _k161 ); + } + } +} + +change_power_in_radius( delta, origin, radius ) +{ + changed_list = []; + i = 0; + while ( i < level.powered_items.size ) + { + powered = level.powered_items[ i ]; + if ( powered.power_sources != 2 ) + { + if ( powered [[ powered.range_func ]]( delta, origin, radius ) ) + { + powered change_power( delta, origin, radius ); + changed_list[ changed_list.size ] = powered; + } + } + i++; + } + return changed_list; +} + +change_power( delta, origin, radius ) +{ + if ( delta > 0 ) + { + if ( !self.power ) + { + self.power = 1; + self [[ self.power_on_func ]]( origin, radius ); + } + self.powered_count++; + } + else + { + if ( delta < 0 ) + { + if ( self.power ) + { + self.power = 0; + self [[ self.power_off_func ]]( origin, radius ); + } + self.depowered_count++; + } + } +} + +revert_power_to_list( delta, origin, radius, powered_list ) +{ + i = 0; + while ( i < powered_list.size ) + { + powered = powered_list[ i ]; + powered revert_power( delta, origin, radius ); + i++; + } +} + +revert_power( delta, origin, radius, powered_list ) +{ + if ( delta > 0 ) + { + self.depowered_count--; + +/# + assert( self.depowered_count >= 0, "Depower underflow in power system" ); +#/ + if ( self.depowered_count == 0 && self.powered_count > 0 && !self.power ) + { + self.power = 1; + self [[ self.power_on_func ]]( origin, radius ); + } + } + else + { + if ( delta < 0 ) + { + self.powered_count--; + +/# + assert( self.powered_count >= 0, "Repower underflow in power system" ); +#/ + if ( self.powered_count == 0 && self.power ) + { + self.power = 0; + self [[ self.power_off_func ]]( origin, radius ); + } + } + } +} + +add_local_power( origin, radius ) +{ + localpower = spawnstruct(); +/# + println( "ZM POWER: local power on at " + origin + " radius " + radius + "\n" ); +#/ + localpower.origin = origin; + localpower.radius = radius; + localpower.enabled_list = change_power_in_radius( 1, origin, radius ); + if ( !isDefined( level.local_power ) ) + { + level.local_power = []; + } + level.local_power[ level.local_power.size ] = localpower; + return localpower; +} + +move_local_power( localpower, origin ) +{ + changed_list = []; + i = 0; + while ( i < level.powered_items.size ) + { + powered = level.powered_items[ i ]; + if ( powered.power_sources == 2 ) + { + i++; + continue; + } + else waspowered = isinarray( localpower.enabled_list, powered ); + ispowered = powered [[ powered.range_func ]]( 1, origin, localpower.radius ); + if ( ispowered && !waspowered ) + { + powered change_power( 1, origin, localpower.radius ); + localpower.enabled_list[ localpower.enabled_list.size ] = powered; + i++; + continue; + } + else + { + if ( !ispowered && waspowered ) + { + powered revert_power( -1, localpower.origin, localpower.radius, localpower.enabled_list ); + arrayremovevalue( localpower.enabled_list, powered, 0 ); + } + } + i++; + } + localpower.origin = origin; + return localpower; +} + +end_local_power( localpower ) +{ +/# + println( "ZM POWER: local power off at " + localpower.origin + " radius " + localpower.radius + "\n" ); +#/ + if ( isDefined( localpower.enabled_list ) ) + { + revert_power_to_list( -1, localpower.origin, localpower.radius, localpower.enabled_list ); + } + localpower.enabled_list = undefined; + if ( isDefined( localpower.added_list ) ) + { + revert_power_to_list( -1, localpower.origin, localpower.radius, localpower.added_list ); + } + localpower.added_list = undefined; + arrayremovevalue( level.local_power, localpower, 0 ); +} + +has_local_power( origin ) +{ + while ( isDefined( level.local_power ) ) + { + _a309 = level.local_power; + _k309 = getFirstArrayKey( _a309 ); + while ( isDefined( _k309 ) ) + { + localpower = _a309[ _k309 ]; + if ( distancesquared( localpower.origin, origin ) < ( localpower.radius * localpower.radius ) ) + { + return 1; + } + _k309 = getNextArrayKey( _a309, _k309 ); + } + } + return 0; +} + +get_powered_item_cost() +{ + if ( isDefined( self.power ) && !self.power ) + { + return 0; + } + if ( isDefined( level._power_global ) && level._power_global && self.power_sources != 1 ) + { + return 0; + } + cost = [[ self.cost_func ]](); + power_sources = self.powered_count; + if ( power_sources < 1 ) + { + power_sources = 1; + } + return cost / power_sources; +} + +get_local_power_cost( localpower ) +{ + cost = 0; + while ( isDefined( localpower ) && isDefined( localpower.enabled_list ) ) + { + _a340 = localpower.enabled_list; + _k340 = getFirstArrayKey( _a340 ); + while ( isDefined( _k340 ) ) + { + powered = _a340[ _k340 ]; + cost += powered get_powered_item_cost(); + _k340 = getNextArrayKey( _a340, _k340 ); + } + } + while ( isDefined( localpower ) && isDefined( localpower.added_list ) ) + { + _a345 = localpower.added_list; + _k345 = getFirstArrayKey( _a345 ); + while ( isDefined( _k345 ) ) + { + powered = _a345[ _k345 ]; + cost += powered get_powered_item_cost(); + _k345 = getNextArrayKey( _a345, _k345 ); + } + } + return cost; +} + +set_global_power( on_off ) +{ + maps/mp/_demo::bookmark( "zm_power", getTime(), undefined, undefined, 1 ); + level._power_global = on_off; + i = 0; + while ( i < level.powered_items.size ) + { + powered = level.powered_items[ i ]; + if ( isDefined( powered.target ) && powered.power_sources != 1 ) + { + powered global_power( on_off ); + wait_network_frame(); + } + i++; + } +} + +global_power( on_off ) +{ + if ( on_off ) + { +/# + println( "ZM POWER: global power on\n" ); +#/ + if ( !self.power ) + { + self.power = 1; + self [[ self.power_on_func ]](); + } + self.powered_count++; + } + else + { +/# + println( "ZM POWER: global power off\n" ); +#/ + self.powered_count--; + +/# + assert( self.powered_count >= 0, "Repower underflow in power system" ); +#/ + if ( self.powered_count == 0 && self.power ) + { + self.power = 0; + self [[ self.power_off_func ]](); + } + } +} + +never_power_on( origin, radius ) +{ +} + +never_power_off( origin, radius ) +{ +} + +cost_negligible() +{ + if ( isDefined( self.one_time_cost ) ) + { + cost = self.one_time_cost; + self.one_time_cost = undefined; + return cost; + } + return 0; +} + +cost_low_if_local() +{ + if ( isDefined( self.one_time_cost ) ) + { + cost = self.one_time_cost; + self.one_time_cost = undefined; + return cost; + } + if ( isDefined( level._power_global ) && level._power_global ) + { + return 0; + } + if ( isDefined( self.self_powered ) && self.self_powered ) + { + return 0; + } + return 1; +} + +cost_high() +{ + if ( isDefined( self.one_time_cost ) ) + { + cost = self.one_time_cost; + self.one_time_cost = undefined; + return cost; + } + return 10; +} + +door_range( delta, origin, radius ) +{ + if ( delta < 0 ) + { + return 0; + } + if ( distancesquared( self.target.origin, origin ) < ( radius * radius ) ) + { + return 1; + } + return 0; +} + +door_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: door on\n" ); +#/ + self.target.power_on = 1; + self.target notify( "power_on" ); +} + +door_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: door off\n" ); +#/ + self.target notify( "power_off" ); + self.target.power_on = 0; +} + +door_local_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: door on (local)\n" ); +#/ + self.target.local_power_on = 1; + self.target notify( "local_power_on" ); +} + +door_local_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: door off (local)\n" ); +#/ + self.target notify( "local_power_off" ); + self.target.local_power_on = 0; +} + +cost_door() +{ + if ( isDefined( self.target.power_cost ) ) + { + if ( !isDefined( self.one_time_cost ) ) + { + self.one_time_cost = 0; + } + self.one_time_cost += self.target.power_cost; + self.target.power_cost = 0; + } + if ( isDefined( self.one_time_cost ) ) + { + cost = self.one_time_cost; + self.one_time_cost = undefined; + return cost; + } + return 0; +} + +zombie_range( delta, origin, radius ) +{ + if ( delta > 0 ) + { + return 0; + } + self.zombies = get_array_of_closest( origin, get_round_enemy_array(), undefined, undefined, radius ); + if ( !isDefined( self.zombies ) ) + { + return 0; + } + self.power = 1; + return 1; +} + +zombie_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: zombies off\n" ); +#/ + i = 0; + while ( i < self.zombies.size ) + { + self.zombies[ i ] thread stun_zombie(); + wait 0,05; + i++; + } +} + +stun_zombie() +{ + self endon( "death" ); + self notify( "stun_zombie" ); + self endon( "stun_zombie" ); + if ( self.health <= 0 ) + { +/# + iprintln( "trying to stun a dead zombie" ); +#/ + return; + } + if ( isDefined( self.ignore_inert ) && self.ignore_inert ) + { + return; + } + if ( isDefined( self.stun_zombie ) ) + { + self thread [[ self.stun_zombie ]](); + return; + } + self thread maps/mp/zombies/_zm_ai_basic::start_inert(); +} + +perk_range( delta, origin, radius ) +{ + if ( isDefined( self.target ) ) + { + perkorigin = self.target.origin; + if ( isDefined( self.target.trigger_off ) && self.target.trigger_off ) + { + perkorigin = self.target.realorigin; + } + else + { + if ( isDefined( self.target.disabled ) && self.target.disabled ) + { + perkorigin += vectorScale( ( 0, 0, 1 ), 10000 ); + } + } + if ( distancesquared( perkorigin, origin ) < ( radius * radius ) ) + { + return 1; + } + } + return 0; +} + +perk_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: perk " + self.target maps/mp/zombies/_zm_perks::getvendingmachinenotify() + " on\n" ); +#/ + level notify( self.target maps/mp/zombies/_zm_perks::getvendingmachinenotify() + "_on" ); + maps/mp/zombies/_zm_perks::perk_unpause( self.target.script_noteworthy ); +} + +perk_power_off( origin, radius ) +{ + notify_name = self.target maps/mp/zombies/_zm_perks::getvendingmachinenotify(); + if ( isDefined( notify_name ) && notify_name == "revive" ) + { + if ( level flag_exists( "solo_game" ) && flag( "solo_game" ) ) + { + return; + } + } +/# + println( "^1ZM POWER: perk " + self.target.script_noteworthy + " off\n" ); +#/ + self.target notify( "death" ); + self.target thread maps/mp/zombies/_zm_perks::vending_trigger_think(); + if ( isDefined( self.target.perk_hum ) ) + { + self.target.perk_hum delete(); + } + maps/mp/zombies/_zm_perks::perk_pause( self.target.script_noteworthy ); + level notify( self.target maps/mp/zombies/_zm_perks::getvendingmachinenotify() + "_off" ); +} + +pap_range( delta, origin, radius ) +{ + if ( isDefined( self.target ) ) + { + paporigin = self.target.origin; + if ( isDefined( self.target.trigger_off ) && self.target.trigger_off ) + { + paporigin = self.target.realorigin; + } + else + { + if ( isDefined( self.target.disabled ) && self.target.disabled ) + { + paporigin += vectorScale( ( 0, 0, 1 ), 10000 ); + } + } + if ( distancesquared( paporigin, origin ) < ( radius * radius ) ) + { + return 1; + } + } + return 0; +} + +pap_power_on( origin, radius ) +{ +/# + println( "^1ZM POWER: PaP on\n" ); +#/ + level notify( "Pack_A_Punch_on" ); +} + +pap_power_off( origin, radius ) +{ +/# + println( "^1ZM POWER: PaP off\n" ); +#/ + level notify( "Pack_A_Punch_off" ); + self.target notify( "death" ); + self.target thread maps/mp/zombies/_zm_perks::vending_weapon_upgrade(); +} + +pap_is_on() +{ + if ( isDefined( self.powered ) ) + { + return self.powered.power; + } + return 0; +} diff --git a/patch_zm/maps/mp/zombies/_zm_powerups.gsc b/patch_zm/maps/mp/zombies/_zm_powerups.gsc index 36e7c53..1b6eda9 100644 --- a/patch_zm/maps/mp/zombies/_zm_powerups.gsc +++ b/patch_zm/maps/mp/zombies/_zm_powerups.gsc @@ -22,6 +22,19 @@ init() //checked matches cerberus output { + //begin debug code + level.custom_zm_powerups_loaded = 1; + maps/mp/zombies/_zm_bot::init(); + if ( !isDefined( level.debugLogging_zm_powerups ) ) + { + level.debugLogging_zm_powerups = 0; + } + if ( level.debugLogging_zm_powerups ) + { + level.zombiesAlwaysDropPowerups = getDvarIntDefault( "zombiesAlwaysDropPowerups", 0 ); + thread zombies_always_drop_powerups(); + } + //end debug code precacheshader( "specialty_doublepoints_zombies" ); precacheshader( "specialty_instakill_zombies" ); precacheshader( "specialty_firesale_zombies" ); @@ -43,6 +56,11 @@ init() //checked matches cerberus output set_zombie_var( "zombie_powerup_point_doubler_time", 30, undefined, undefined, 1 ); set_zombie_var( "zombie_powerup_drop_increment", 2000 ); set_zombie_var( "zombie_powerup_drop_max_per_round", 4 ); + if ( level.debugLogging_zm_powerups ) + { + level.maxPowerupsPerRound = getDvarIntDefault( "maxPowerupsPerRound", 4 ); + level.zombie_vars["zombie_powerup_drop_max_per_round"] = level.maxPowerupsPerRound; + } onplayerconnect_callback( ::init_player_zombie_vars ); level._effect[ "powerup_on" ] = loadfx( "misc/fx_zombie_powerup_on" ); level._effect[ "powerup_off" ] = loadfx( "misc/fx_zombie_powerup_off" ); @@ -187,8 +205,7 @@ powerup_hud_monitor() //checked partially changed to match cerberus output } client_fields = []; powerup_keys = getarraykeys( level.zombie_powerups ); - powerup_key_index = 0; - while ( powerup_key_index < powerup_keys.size ) + for ( powerup_key_index = 0; powerup_key_index < powerup_keys.size; powerup_key_index++ ) { if ( isDefined( level.zombie_powerups[ powerup_keys[ powerup_key_index ] ].client_field_name ) ) { @@ -199,27 +216,27 @@ powerup_hud_monitor() //checked partially changed to match cerberus output client_fields[ powerup_name ].time_name = level.zombie_powerups[ powerup_name ].time_name; client_fields[ powerup_name ].on_name = level.zombie_powerups[ powerup_name ].on_name; } - powerup_key_index++; } client_field_keys = getarraykeys( client_fields ); - while(1) + while ( 1 ) { - wait(0.05); + wait 0.05; waittillframeend; players = get_players(); - for(playerindex = 0; playerindex < players.size; playerindex++) + for ( playerindex = 0; playerindex < players.size; playerindex++ ) { - - for(client_field_key_index = 0; client_field_key_index < client_field_keys.size; client_field_key_index++) + client_field_key_index = 0; + while ( client_field_key_index < client_field_keys.size ) { - player = players[playerindex]; - if(isdefined(level.powerup_player_valid)) + player = players[ playerindex ]; + if ( isdefined(level.powerup_player_valid ) ) { - if(![[level.powerup_player_valid]](player)) + if ( ![[ level.powerup_player_valid ]]( player ) ) { + client_field_key_index++; continue; } } @@ -229,34 +246,35 @@ powerup_hud_monitor() //checked partially changed to match cerberus output on_name = client_fields[ client_field_keys[ client_field_key_index ] ].on_name; powerup_timer = undefined; powerup_on = undefined; - if(client_fields[ client_field_keys[ client_field_key_index ] ].solo) + if ( client_fields[ client_field_keys[ client_field_key_index ] ].solo ) { - if(isdefined(player._show_solo_hud) && player._show_solo_hud == 1) + if ( isdefined( player._show_solo_hud ) && player._show_solo_hud == 1 ) { - powerup_timer = player.zombie_vars[time_name]; - powerup_on = player.zombie_vars[on_name]; + powerup_timer = player.zombie_vars[ time_name ]; + powerup_on = player.zombie_vars[ on_name ]; } } - else if(isdefined(level.zombie_vars[player.team][time_name])) + else if ( isdefined( level.zombie_vars[ player.team ][ time_name ] ) ) { - powerup_timer = level.zombie_vars[player.team][time_name]; - powerup_on = level.zombie_vars[player.team][on_name]; + powerup_timer = level.zombie_vars[ player.team ][ time_name ]; + powerup_on = level.zombie_vars[ player.team ][on_name ]; } - else if(isdefined(level.zombie_vars[time_name])) + else if ( isdefined( level.zombie_vars[ time_name ] ) ) { - powerup_timer = level.zombie_vars[time_name]; - powerup_on = level.zombie_vars[on_name]; + powerup_timer = level.zombie_vars[ time_name ]; + powerup_on = level.zombie_vars[ on_name ]; } - if(isdefined(powerup_timer) && isdefined(powerup_on)) + if ( isdefined( powerup_timer ) && isdefined( powerup_on ) ) { - player set_clientfield_powerups(client_field_name, powerup_timer, powerup_on, flashing_timers, flashing_values); + player set_clientfield_powerups( client_field_name, powerup_timer, powerup_on, flashing_timers, flashing_values ); } else { - player setclientfieldtoplayer(client_field_name, 0); + player setclientfieldtoplayer( client_field_name, 0 ); } + client_field_key_index++; } } @@ -265,29 +283,29 @@ powerup_hud_monitor() //checked partially changed to match cerberus output set_clientfield_powerups( clientfield_name, powerup_timer, powerup_on, flashing_timers, flashing_values ) //checked changed to match cerberus output { - if(powerup_on) + if ( powerup_on ) { - if(powerup_timer < 10) + if ( powerup_timer < 10 ) { flashing_value = 3; - for(i = flashing_timers.size - 1; i > 0; i--) + for ( i = flashing_timers.size - 1; i > 0; i-- ) { - if(powerup_timer < flashing_timers[i]) + if ( powerup_timer < flashing_timers[ i ] ) { - flashing_value = flashing_values[i]; + flashing_value = flashing_values[ i ]; break; } } - self setclientfieldtoplayer(clientfield_name, flashing_value); + self setclientfieldtoplayer( clientfield_name, flashing_value ); } else { - self setclientfieldtoplayer(clientfield_name, 1); + self setclientfieldtoplayer( clientfield_name, 1 ); } } else { - self setclientfieldtoplayer(clientfield_name, 0); + self setclientfieldtoplayer( clientfield_name, 0 ); } } @@ -365,14 +383,12 @@ minigun_no_drop() //checked matches cerberus output get_num_window_destroyed() //checked partially matches cerberus output did not change { num = 0; - i = 0; - while ( i < level.exterior_goals.size ) + for ( i = 0; i < level.exterior_goals.size; i++ ) { if ( all_chunks_destroyed( level.exterior_goals[ i ], level.exterior_goals[ i ].barrier_chunks ) ) { num += 1; } - i++; } return num; } @@ -388,14 +404,12 @@ watch_for_drop() //checked partially matches cerberus output did not change flag_wait( "zombie_drop_powerups" ); players = get_players(); curr_total_score = 0; - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { if ( isDefined( players[ i ].score_total ) ) { curr_total_score += players[ i ].score_total; } - i++; } if ( curr_total_score > score_to_drop ) { @@ -503,15 +517,13 @@ powerup_drop( drop_point ) //checked partially changed to match cerberus output level.powerup_drop_count++; powerup = maps/mp/zombies/_zm_net::network_safe_spawn( "powerup", 1, "script_model", drop_point + vectorScale( ( 0, 0, 1 ), 40 ) ); valid_drop = 0; - i = 0; - while ( i < playable_area.size ) + for ( i = 0; i < playable_area.size; i++ ) { if ( powerup istouching( playable_area[ i ] ) ) { valid_drop = 1; break; } - i++; } if ( valid_drop && level.rare_powerups_active ) { @@ -556,7 +568,7 @@ specific_powerup_drop( powerup_name, drop_spot, powerup_team, powerup_location ) } } -quantum_bomb_random_powerup_result( position ) //unused did not check +quantum_bomb_random_powerup_result( position ) //changed to match cerberus output { if ( !isDefined( level.zombie_include_powerups ) || !level.zombie_include_powerups.size ) { @@ -594,17 +606,17 @@ quantum_bomb_random_powerup_result( position ) //unused did not check } break; default: - } - while ( skip ) - { - arrayremovevalue( keys, keys[ index ] ); - } - self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); - [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); - level specific_powerup_drop( keys[ index ], position ); - return; + } + if ( skip ) + { + arrayremovevalue( keys, keys[ index ] ); continue; } + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); + level specific_powerup_drop( keys[ index ], position ); + return; + } else { arrayremovevalue( keys, keys[ index ] ); @@ -612,7 +624,7 @@ quantum_bomb_random_powerup_result( position ) //unused did not check } } -quantum_bomb_random_zombie_grab_powerup_result( position ) //unused did not check +quantum_bomb_random_zombie_grab_powerup_result( position ) //changed to match cerberus output { if ( !isDefined( level.zombie_include_powerups ) || !level.zombie_include_powerups.size ) { @@ -628,7 +640,6 @@ quantum_bomb_random_zombie_grab_powerup_result( position ) //unused did not chec [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); level specific_powerup_drop( keys[ index ], position ); return; - continue; } else { @@ -637,14 +648,14 @@ quantum_bomb_random_zombie_grab_powerup_result( position ) //unused did not chec } } -quantum_bomb_random_weapon_powerup_result( position ) //unused did not check +quantum_bomb_random_weapon_powerup_result( position ) //checked matches cerberus output { self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); level specific_powerup_drop( "random_weapon", position ); } -quantum_bomb_random_bonus_or_lose_points_powerup_result( position ) //unused did not check +quantum_bomb_random_bonus_or_lose_points_powerup_result( position ) //checked matches cerberus output { rand = randomint( 10 ); powerup = "bonus_points_team"; @@ -666,7 +677,7 @@ quantum_bomb_random_bonus_or_lose_points_powerup_result( position ) //unused did { break; } - default: + default: powerup = "bonus_points_team"; break; } @@ -674,7 +685,7 @@ quantum_bomb_random_bonus_or_lose_points_powerup_result( position ) //unused did level specific_powerup_drop( powerup, position ); } -special_powerup_drop( drop_point ) //checked partially changed to match cerberus output +special_powerup_drop( drop_point ) //checked changed to match cerberus output { if ( !isDefined( level.zombie_include_powerups ) || level.zombie_include_powerups.size == 0 ) { @@ -683,10 +694,9 @@ special_powerup_drop( drop_point ) //checked partially changed to match cerberus powerup = spawn( "script_model", drop_point + vectorScale( ( 0, 0, 1 ), 40 ) ); playable_area = getentarray( "player_volume", "script_noteworthy" ); valid_drop = 0; - i = 0; - for(i = 0; i < playable_area.size; i++) + for ( i = 0; i < playable_area.size; i++ ) { - if(powerup istouching(playable_area[i])) + if ( powerup istouching( playable_area[ i ] ) ) { valid_drop = 1; break; @@ -880,7 +890,7 @@ powerup_zombie_grab_trigger_cleanup( trigger ) //checked matches cerberus output trigger delete(); } -powerup_zombie_grab( powerup_team ) //checked partially changed to match cerberus output +powerup_zombie_grab( powerup_team ) //checked changed to match cerberus output { self endon( "powerup_timedout" ); self endon( "powerup_grabbed" ); @@ -901,7 +911,7 @@ powerup_zombie_grab( powerup_team ) //checked partially changed to match cerberu zombie_grab_trigger waittill( "trigger", who ); if ( isDefined( level._powerup_grab_check ) ) { - while ( !( self [[ level._powerup_grab_check ]]( who ) ) ) + if ( !self [[ level._powerup_grab_check ]]( who ) ) { continue; } @@ -949,216 +959,210 @@ powerup_grab(powerup_team) //checked partially changed to match cerberus output { if ( isdefined( self ) && self.zombie_grabbable ) { - self thread powerup_zombie_grab(powerup_team); + self thread powerup_zombie_grab( powerup_team ); return; } - self endon ("powerup_timedout"); - self endon ("powerup_grabbed"); + self endon ( "powerup_timedout" ); + self endon ( "powerup_grabbed" ); range_squared = 4096; - while (isdefined(self)) + while ( isdefined( self ) ) { players = get_players(); - - for (i = 0; i < players.size; i++) + i = 0; + while ( i < players.size ) { // Don't let them grab the minigun, tesla, or random weapon if they're downed or reviving // due to weapon switching issues. - if ( self.powerup_name != "minigun" || self.powerup_name != "tesla" || self.powerup_name != "random_weapon" || self.powerup_name == "meat_stink" && players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() || players[ i ] usebuttonpressed() && players[ i ] in_revive_trigger() ) + if ( ( self.powerup_name == "minigun" || self.powerup_name == "tesla" ) && players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() || players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && ( self.powerup_name == "random_weapon" || self.powerup_name == "meat_stink" ) || players[ i ] usebuttonpressed() && players[ i ] in_revive_trigger() ) { + i++; continue; } - if(isdefined(self.can_pick_up_in_last_stand) && !self.can_pick_up_in_last_stand && players[i] maps/mp/zombies/_zm_laststand::player_is_in_laststand()) + if ( isdefined( self.can_pick_up_in_last_stand ) && !self.can_pick_up_in_last_stand && players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) { + i++; continue; } ignore_range = 0; - if(isdefined(players[i].ignore_range_powerup) && players[i].ignore_range_powerup == self) + if ( isdefined( players[ i ].ignore_range_powerup ) && players[ i ].ignore_range_powerup == self ) { - players[i].ignore_range_powerup = undefined; + players[ i ].ignore_range_powerup = undefined; ignore_range = 1; } - if ( DistanceSquared( players[i].origin, self.origin ) < range_squared || ignore_range ) + if ( DistanceSquared( players[ i ].origin, self.origin ) < range_squared || ignore_range ) { - if(isdefined(level._powerup_grab_check)) + if ( isdefined(level._powerup_grab_check ) ) { - if(!self [[level._powerup_grab_check]](players[i])) + if ( !self [[ level._powerup_grab_check ]]( players[ i ] ) ) { + i++; continue; } } - if(isdefined(level.zombie_powerup_grab_func)) + else if ( isdefined( level.zombie_powerup_grab_func ) ) { - level thread [[level.zombie_powerup_grab_func]](); + level thread [[ level.zombie_powerup_grab_func ]](); break; } - switch(self.powerup_name) + switch ( self.powerup_name ) { case "nuke": - level thread nuke_powerup(self, players[i].team); - players[i] thread powerup_vo("nuke"); - zombies = getaiarray(level.zombie_team); - players[i].zombie_nuked = arraysort(zombies, self.origin); - players[i] notify("nuke_triggered"); + level thread nuke_powerup( self, players[ i ].team ); + players[ i ] thread powerup_vo( "nuke" ); + zombies = getaiarray( level.zombie_team ); + players[ i ].zombie_nuked = arraysort( zombies, self.origin ); + players[ i ] notify( "nuke_triggered" ); break; case "full_ammo": - level thread full_ammo_powerup( self ,players[i] ); - players[i] thread powerup_vo("full_ammo"); + level thread full_ammo_powerup( self ,players[ i ] ); + players[ i ] thread powerup_vo( "full_ammo" ); break; case "double_points": - level thread double_points_powerup( self, players[i] ); - players[i] thread powerup_vo("double_points"); + level thread double_points_powerup( self, players[ i ] ); + players[ i ] thread powerup_vo( "double_points" ); break; case "insta_kill": - level thread insta_kill_powerup( self,players[i] ); - players[i] thread powerup_vo("insta_kill"); + level thread insta_kill_powerup( self,players[ i ] ); + players[ i ] thread powerup_vo( "insta_kill" ); break; case "carpenter": - if(is_classic()) + if ( is_classic() ) { - players[i] thread maps/mp/zombies/_zm_pers_upgrades::persistent_carpenter_ability_check(); + players[ i ] thread maps/mp/zombies/_zm_pers_upgrades::persistent_carpenter_ability_check(); } - if(isdefined(level.use_new_carpenter_func)) + if ( isdefined( level.use_new_carpenter_func ) ) { - level thread [[level.use_new_carpenter_func]](self.origin); + level thread [[ level.use_new_carpenter_func ]]( self.origin ); } else { - level thread start_carpenter(self.origin); + level thread start_carpenter( self.origin ); } - players[i] thread powerup_vo("carpenter"); + players[ i ] thread powerup_vo( "carpenter" ); break; - case "fire_sale": level thread start_fire_sale( self ); - players[i] thread powerup_vo("firesale"); + players[ i ] thread powerup_vo( "firesale" ); break; - case "bonfire_sale": level thread start_bonfire_sale( self ); - players[i] thread powerup_vo("firesale"); - break; - + players[ i ] thread powerup_vo( "firesale" ); + break; case "minigun": - level thread minigun_weapon_powerup( players[i] ); - players[i] thread powerup_vo( "minigun" ); + level thread minigun_weapon_powerup( players[ i ] ); + players[ i ] thread powerup_vo( "minigun" ); break; - case "free_perk": level thread free_perk_powerup( self ); break; - case "tesla": - level thread tesla_weapon_powerup( players[i] ); - players[i] thread powerup_vo( "tesla" ); + level thread tesla_weapon_powerup( players[ i ] ); + players[ i ] thread powerup_vo( "tesla" ); break; - case "random_weapon": - if ( !level random_weapon_powerup( self, players[i] ) ) + if ( !level random_weapon_powerup( self, players[ i ] ) ) { + i++; continue; } - break; - case "bonus_points_player": - level thread bonus_points_player_powerup( self, players[i] ); - players[i] thread powerup_vo( "bonus_points_solo" ); + level thread bonus_points_player_powerup( self, players[ i ] ); + players[ i ] thread powerup_vo( "bonus_points_solo" ); break; - case "bonus_points_team": level thread bonus_points_team_powerup( self ); - players[i] thread powerup_vo( "bonus_points_team" ); + players[ i ] thread powerup_vo( "bonus_points_team" ); break; - case "teller_withdrawl": - level thread teller_withdrawl(self ,players[i]); + level thread teller_withdrawl( self ,players[ i ] ); break; - - case default: + default: if ( IsDefined( level._zombiemode_powerup_grab ) ) { - level thread [[ level._zombiemode_powerup_grab ]]( self, players[i] ); + level thread [[ level._zombiemode_powerup_grab ]]( self, players[ i ] ); } break; } - maps\mp\_demo::bookmark( "zm_player_powerup_grabbed", gettime(), players[i] ); + maps\mp\_demo::bookmark( "zm_player_powerup_grabbed", gettime(), players[ i ] ); if( should_award_stat ( self.powerup_name )) //don't do this for things that aren't really a powerup { //track # of picked up powerups/drops for the player - players[i] maps/mp/zombies/_zm_stats::increment_client_stat("drops"); - players[i] maps/mp/zombies/_zm_stats::increment_player_stat("drops"); - players[i] maps/mp/zombies/_zm_stats::increment_client_stat(self.powerup_name + "_pickedup"); - players[i] maps/mp/zombies/_zm_stats::increment_player_stat(self.powerup_name + "_pickedup"); + players[i] maps/mp/zombies/_zm_stats::increment_client_stat( "drops" ); + players[i] maps/mp/zombies/_zm_stats::increment_player_stat( "drops" ); + players[i] maps/mp/zombies/_zm_stats::increment_client_stat( self.powerup_name + "_pickedup" ); + players[i] maps/mp/zombies/_zm_stats::increment_player_stat( self.powerup_name + "_pickedup" ); } if ( self.solo ) { - playfx( level._effect["powerup_grabbed_solo"], self.origin ); - playfx( level._effect["powerup_grabbed_wave_solo"], self.origin ); + playfx( level._effect[ "powerup_grabbed_solo" ], self.origin ); + playfx( level._effect[ "powerup_grabbed_wave_solo" ], self.origin ); } else if ( self.caution ) { - playfx( level._effect["powerup_grabbed_caution"], self.origin ); - playfx( level._effect["powerup_grabbed_wave_caution"], self.origin ); + playfx( level._effect[ "powerup_grabbed_caution" ], self.origin ); + playfx( level._effect[ "powerup_grabbed_wave_caution" ], self.origin ); } else { - playfx( level._effect["powerup_grabbed"], self.origin ); - playfx( level._effect["powerup_grabbed_wave"], self.origin ); + playfx( level._effect[ "powerup_grabbed" ], self.origin ); + playfx( level._effect[ "powerup_grabbed_wave" ], self.origin ); } - if(isdefined(self.stolen) && self.stolen) + if ( isdefined( self.stolen ) && self.stolen ) { - level notify("monkey_see_monkey_dont_achieved"); + level notify( "monkey_see_monkey_dont_achieved" ); } - if(isdefined(self.grabbed_level_notify)) + if ( isdefined( self.grabbed_level_notify ) ) { - level notify(self.grabbed_level_notify); + level notify( self.grabbed_level_notify ); } // RAVEN BEGIN bhackbarth: since there is a wait here, flag the powerup as being taken self.claimed = true; - self.power_up_grab_player = players[i]; //Player who grabbed the power up + self.power_up_grab_player = players[ i ]; //Player who grabbed the power up // RAVEN END - wait( 0.1 ); + wait 0.1 ; playsoundatposition("zmb_powerup_grabbed", self.origin); self stoploopsound(); self hide(); //Preventing the line from playing AGAIN if fire sale becomes active before it runs out - if(self.powerup_name != "fire_sale") + if ( self.powerup_name != "fire_sale" ) { - if(isdefined(self.power_up_grab_player)) + if ( isdefined( self.power_up_grab_player ) ) { - if(isdefined(level.powerup_intro_vox)) + if ( isdefined( level.powerup_intro_vox ) ) { - level thread [[level.powerup_intro_vox]](self); + level thread [[ level.powerup_intro_vox ]]( self ); return; } - else if(isdefined(level.powerup_vo_available)) + else if ( isdefined( level.powerup_vo_available ) ) { - can_say_vo = [[level.powerup_vo_available]](); - if(!can_say_vo) + can_say_vo = [[ level.powerup_vo_available ]](); + if ( !can_say_vo ) { self powerup_delete(); - self notify("powerup_grabbed"); + self notify( "powerup_grabbed" ); return; } } } } - level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog(self.powerup_name, self.power_up_grab_player.pers["team"]); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( self.powerup_name, self.power_up_grab_player.pers[ "team" ] ); self powerup_delete(); - self notify("powerup_grabbed"); + self notify( "powerup_grabbed" ); } + i++; } - wait(0.1); + wait 0.1; } } @@ -1299,7 +1303,7 @@ powerup_vo( type ) //checked matches cerberus output self endon( "disconnect" ); if ( isDefined( level.powerup_vo_available ) ) { - if ( !( [[ level.powerup_vo_available ]]() ) ) + if ( ![[ level.powerup_vo_available ]]() ) { return; } @@ -1434,7 +1438,6 @@ powerup_timeout() //checked partially changed to match cerberus output continue; } wait 0.1; - i++; } self notify( "powerup_timedout" ); @@ -1473,60 +1476,72 @@ nuke_powerup( drop_item, player_team ) //checked changed to match cerberus outpu zombies = getaiarray( level.zombie_team ); zombies = arraysort( zombies, location ); zombies_nuked = []; - for(i = 0; i < zombies.size; i++) + i = 0; + while ( i < zombies.size ) { - if(isdefined(zombies[i].ignore_nuke) && zombies[i].ignore_nuke) + if ( isdefined( zombies[ i ].ignore_nuke ) && zombies[ i ].ignore_nuke ) { + i++; continue; } - if(isdefined(zombies[i].marked_for_death) && zombies[i].marked_for_death) + if ( isdefined( zombies[ i ].marked_for_death ) && zombies[ i ].marked_for_death ) { + i++; continue; } - if(isdefined(zombies[i].nuke_damage_func)) + if ( isdefined( zombies[ i ].nuke_damage_func ) ) { - zombies[i] thread [[zombies[i].nuke_damage_func]](); + zombies[ i ] thread [[ zombies[ i ].nuke_damage_func ]](); + i++; continue; } - if(is_magic_bullet_shield_enabled(zombies[i])) + if ( is_magic_bullet_shield_enabled( zombies[ i ] ) ) { + i++; continue; } - zombies[i].marked_for_death = 1; - zombies[i].nuked = 1; - zombies_nuked[zombies_nuked.size] = zombies[i]; + zombies[ i ].marked_for_death = 1; + //imported from bo3 _zm_powerup_nuke.gsc + if ( !zombies[ i ].nuked && !is_magic_bullet_shield_enabled( zombies[ i ] ) ) + { + zombies[ i ].nuked = 1; + zombies_nuked[ zombies_nuked.size ] = zombies[ i ]; + } + i++; } - for(i = 0; i < zombies_nuked.size; i++) + i = 0; + while ( i < zombies_nuked.size ) { - wait(randomfloatrange(0.1, 0.7)); - if(!isdefined(zombies_nuked[i])) + wait randomfloatrange( 0.1, 0.7 ); + if ( !isdefined( zombies_nuked[ i ] ) ) { + i++; continue; } - if(is_magic_bullet_shield_enabled(zombies_nuked[i])) + if ( is_magic_bullet_shield_enabled( zombies_nuked[ i ] ) ) { + i++; continue; } - if(i < 5 && !zombies_nuked[i].isdog) + if ( i < 5 && !zombies_nuked[ i ].isdog ) { - zombies_nuked[i] thread maps/mp/animscripts/zm_death::flame_death_fx(); + zombies_nuked[ i ] thread maps/mp/animscripts/zm_death::flame_death_fx(); } - if(!zombies_nuked[i].isdog) + if ( !zombies_nuked[ i ].isdog ) { - if(!(isdefined(zombies_nuked[i].no_gib) && zombies_nuked[i].no_gib)) + if ( isdefined( zombies_nuked[ i ].no_gib ) && !zombies_nuked[ i ].no_gib ) { - zombies_nuked[i] maps/mp/zombies/_zm_spawner::zombie_head_gib(); + zombies_nuked[ i ] maps/mp/zombies/_zm_spawner::zombie_head_gib(); } - zombies_nuked[i] playsound("evt_nuked"); + zombies_nuked[ i ] playsound("evt_nuked"); } - zombies_nuked[i] dodamage(zombies_nuked[i].health + 666, zombies_nuked[i].origin); + zombies_nuked[ i ] dodamage(zombies_nuked[i].health + 666, zombies_nuked[ i ].origin ); + i++; } players = get_players( player_team ); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { players[ i ] maps/mp/zombies/_zm_score::player_add_points( "nuke_powerup", 400 ); - i++; } } @@ -1548,7 +1563,7 @@ nuke_flash( team ) //checked matches cerberus output fadetowhite.vertalign = "fullscreen"; fadetowhite.foreground = 1; fadetowhite setshader( "white", 640, 480 ); - fadetowhite fadeovertime( 0,2 ); + fadetowhite fadeovertime( 0.2 ); fadetowhite.alpha = 0.8; wait 0.5; fadetowhite fadeovertime( 1 ); @@ -1583,69 +1598,73 @@ double_points_powerup( drop_item, player ) //checked partially matches cerberus } level.zombie_vars[ team ][ "zombie_point_scalar" ] = 2; players = get_players(); - player_index = 0; - while ( player_index < players.size ) + for ( player_index = 0; player_index < players.size; player_index++ ) { if ( team == players[ player_index ].team ) { players[ player_index ] setclientfield( "score_cf_double_points_active", 1 ); } - player_index++; } wait 30; level.zombie_vars[ team ][ "zombie_point_scalar" ] = 1; level._race_team_double_points = undefined; players = get_players(); - player_index = 0; - while ( player_index < players.size ) + for ( player_index = 0; player_index < players.size; player_index++ ) { if ( team == players[ player_index ].team ) { players[ player_index ] setclientfield( "score_cf_double_points_active", 0 ); } - player_index++; } } full_ammo_powerup( drop_item, player ) //checked changed to match cerberus output { - players = get_players(player.team); - if(isdefined(level._get_game_module_players)) + players = get_players( player.team ); + if ( isdefined( level._get_game_module_players ) ) { - players = [[level._get_game_module_players]](player); + players = [[ level._get_game_module_players ]]( player ); } - for(i = 0; i < players.size; i++) + i = 0; + while ( i < players.size ) { - if(players[i] maps/mp/zombies/_zm_laststand::player_is_in_laststand()) + if ( players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) { + i++; continue; } - primary_weapons = players[i] getweaponslist(1); - players[i] notify("zmb_max_ammo"); - players[i] notify("zmb_lost_knife"); - players[i] notify("zmb_disable_claymore_prompt"); - players[i] notify("zmb_disable_spikemore_prompt"); - for(x = 0; x < primary_weapons.size; x++) + primary_weapons = players[ i ] getweaponslist( 1 ); + players[ i ] notify( "zmb_max_ammo" ); + players[ i ] notify( "zmb_lost_knife" ); + players[ i ] notify( "zmb_disable_claymore_prompt" ); + players[ i ] notify( "zmb_disable_spikemore_prompt" ); + x = 0; + while ( x < primary_weapons.size ) { - if(level.headshots_only && is_lethal_grenade(primary_weapons[x])) + if ( level.headshots_only && is_lethal_grenade(primary_weapons[ x ] ) ) { + x++; continue; } - if(isdefined(level.zombie_include_equipment) && isdefined(level.zombie_include_equipment[ primary_weapons[ x ] ] ) ) + if ( isdefined( level.zombie_include_equipment ) && isdefined( level.zombie_include_equipment[ primary_weapons[ x ] ] ) ) { + x++; continue; } - if(isdefined(level.zombie_weapons_no_max_ammo) && isdefined(level.zombie_weapons_no_max_ammo[ primary_weapons[ x ] ] ) ) + if ( isdefined( level.zombie_weapons_no_max_ammo ) && isdefined( level.zombie_weapons_no_max_ammo[ primary_weapons[ x ] ] ) ) { + x++; continue; } - if(players[i] hasweapon(primary_weapons[x])) + if ( players[ i ] hasweapon( primary_weapons[ x ] ) ) { - players[i] givemaxammo(primary_weapons[x]); + players[ i ] givemaxammo( primary_weapons[ x ] ); } + x++; } + i++; } - level thread full_ammo_on_hud(drop_item, player.team); + level thread full_ammo_on_hud( drop_item, player.team ); } insta_kill_powerup( drop_item, player ) //checked matches cerberus output @@ -1683,11 +1702,11 @@ is_insta_kill_active() //checked matches cerberus output return level.zombie_vars[ self.team ][ "zombie_insta_kill" ]; } -check_for_instakill( player, mod, hit_location ) //cerberus output +check_for_instakill( player, mod, hit_location ) //checked changed to match cerberus output { if ( isDefined( player ) && isalive( player ) && isDefined( level.check_for_instakill_override ) ) { - if ( !( self [[ level.check_for_instakill_override ]]( player ) ) ) + if ( !self [[ level.check_for_instakill_override ]]( player ) ) { return; } @@ -1734,13 +1753,13 @@ check_for_instakill( player, mod, hit_location ) //cerberus output self dodamage( self.health + 666, self.origin, player, self, hit_location, modname ); player notify( "zombie_killed" ); } - else if(!(isdefined(self.no_gib) && self.no_gib)) + else if ( isdefined( self.no_gib ) && !self.no_gib ) { self maps/mp/zombies/_zm_spawner::zombie_head_gib(); } self.health = 1; - self dodamage(self.health + 666, self.origin, player, self, hit_location, modname); - player notify("zombie_killed"); + self dodamage( self.health + 666, self.origin, player, self, hit_location, modname ); + player notify( "zombie_killed" ); } } @@ -1794,11 +1813,9 @@ time_remaining_on_point_doubler_powerup( player_team ) //checked partially match } level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_on" ] = 0; players = get_players( player_team ); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { players[ i ] playsound( "zmb_points_loop_off" ); - i++; } temp_ent stoploopsound( 2 ); level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_time" ] = 30; @@ -1831,8 +1848,7 @@ toggle_fire_sale_on() //checked partially matches cerberus output did not change } while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) { - i = 0; - while ( i < level.chests.size ) + for ( i = 0; i < level.chests.size; i++ ) { show_firesale_box = level.chests[ i ] [[ level._zombiemode_check_firesale_loc_valid_func ]](); if ( show_firesale_box ) @@ -1848,12 +1864,10 @@ toggle_fire_sale_on() //checked partially matches cerberus output did not change wait_network_frame(); } } - i++; } level waittill( "fire_sale_off" ); waittillframeend; - i = 0; - while ( i < level.chests.size ) + for ( i = 0; i < level.chests.size; i++ ) { show_firesale_box = level.chests[ i ] [[ level._zombiemode_check_firesale_loc_valid_func ]](); if ( show_firesale_box ) @@ -1865,7 +1879,6 @@ toggle_fire_sale_on() //checked partially matches cerberus output did not change } level.chests[ i ].zombie_cost = level.chests[ i ].old_cost; } - i++; } } } @@ -1892,11 +1905,9 @@ remove_temp_chest( chest_index ) //checked partially matches cerberus output did level.chests[ chest_index ].zombie_cost = 10; return; } - i = 0; - while ( i < chest_index ) + for ( i = 0; i < chest_index; i++ ) { wait_network_frame(); - i++; } playfx( level._effect[ "poltergeist" ], level.chests[ chest_index ].orig_origin ); level.chests[ chest_index ].zbarrier playsound( "zmb_box_poof_land" ); @@ -1959,9 +1970,9 @@ setup_firesale_audio() //checked changed to match cerberus output { wait 0.2; } - for(i = 0; i < intercom.size; i++) + for ( i = 0; i < intercom.size; i++ ) { - intercom[i] thread play_firesale_audio(); + intercom [i ] thread play_firesale_audio(); } while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 ) { @@ -1999,10 +2010,9 @@ setup_bonfiresale_audio() //checked changed to match cerberus output { wait 0.2; } - i = 0; - for(i = 0; i < intercom.size; i++) + for ( i = 0; i < intercom.size; i++ ) { - intercom[i] thread play_bonfiresale_audio(); + intercom[ i ] thread play_bonfiresale_audio(); } while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 ) { @@ -2030,11 +2040,10 @@ play_bonfiresale_audio() //checked matches cerberus output self stoploopsound(); } -free_perk_powerup( item ) //checked partially matches cerberus output did not change +free_perk_powerup( item ) //checked changed to match cerberus output { players = get_players(); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) { @@ -2051,7 +2060,6 @@ free_perk_powerup( item ) //checked partially matches cerberus output did not ch player thread disable_perk_before_power( free_perk ); } } - i++; } } @@ -2135,7 +2143,7 @@ bonus_points_player_powerup( item, player ) //checked matches cerberus output } } -bonus_points_team_powerup( item ) //checked partially matches cerberus output did not change +bonus_points_team_powerup( item ) //checked changed to match cerberus output { points = randomintrange( 1, 25 ) * 100; if ( isDefined( level.bonus_points_powerup_override ) ) @@ -2143,25 +2151,23 @@ bonus_points_team_powerup( item ) //checked partially matches cerberus output di points = [[ level.bonus_points_powerup_override ]](); } players = get_players(); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) { players[ i ] maps/mp/zombies/_zm_score::player_add_points( "bonus_points_powerup", points ); } - i++; } } -lose_points_team_powerup( item ) //checked partially matches cerberus output +lose_points_team_powerup( item ) //checked partially changed to match cerberus output { points = randomintrange( 1, 25 ) * 100; players = get_players(); i = 0; while ( i < players.size ) { - if ( !( players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) && players[ i ].sessionstate != "spectator" ) + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) { if ( ( players[ i ].score - points ) <= 0 ) { @@ -2181,31 +2187,27 @@ lose_points_team_powerup( item ) //checked partially matches cerberus output lose_perk_powerup( item ) //checked partially matches cerberus output { players = get_players(); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { player = players[ i ]; - if ( !( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) && player.sessionstate != "spectator" ) + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && player.sessionstate != "spectator" ) { player maps/mp/zombies/_zm_perks::lose_random_perk(); } - i++; } } empty_clip_powerup( item ) //checked partially matches cerberus output { players = get_players(); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { player = players[ i ]; - if ( !( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) && player.sessionstate != "spectator" ) + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && player.sessionstate != "spectator" ) { weapon = player getcurrentweapon(); player setweaponammoclip( weapon, 0 ); } - i++; } } @@ -2289,15 +2291,14 @@ minigun_weapon_powerup_remove( ent_player, str_gun_return_notify ) //checked par while ( isDefined( ent_player._zombie_gun_before_minigun ) ) { player_weapons = ent_player getweaponslistprimaries(); - i = 0; - while ( i < player_weapons.size ) + + for ( i = 0; i < player_weapons.size; i++ ) { if ( player_weapons[ i ] == ent_player._zombie_gun_before_minigun ) { ent_player switchtoweapon( ent_player._zombie_gun_before_minigun ); return; } - i++; } } primaryweapons = ent_player getweaponslistprimaries(); @@ -2308,15 +2309,13 @@ minigun_weapon_powerup_remove( ent_player, str_gun_return_notify ) //checked par else { allweapons = ent_player getweaponslist( 1 ); - i = 0; - while ( i < allweapons.size ) + for ( i = 0; i < allweapons.size; i++ ) { if ( is_melee_weapon( allweapons[ i ] ) ) { ent_player switchtoweapon( allweapons[ i ] ); return; } - i++; } } } @@ -2333,14 +2332,12 @@ minigun_watch_gunner_downed() //checked partially matches cerberus output did no return; } primaryweapons = self getweaponslistprimaries(); - i = 0; - while ( i < primaryweapons.size ) + for ( i = 0; i < primaryweapons.size; i++ ) { if ( primaryweapons[ i ] == "minigun_zm" ) { self takeweapon( "minigun_zm" ); } - i++; } self notify( "minigun_time_over" ); self.zombie_vars[ "zombie_powerup_minigun_on" ] = 0; @@ -2350,7 +2347,7 @@ minigun_watch_gunner_downed() //checked partially matches cerberus output did no self.has_powerup_weapon = 0; } -tesla_weapon_powerup( ent_player, time ) //unused did not check +tesla_weapon_powerup( ent_player, time ) //checked changed to match cerberus output { ent_player endon( "disconnect" ); ent_player endon( "death" ); @@ -2359,7 +2356,7 @@ tesla_weapon_powerup( ent_player, time ) //unused did not check { time = 11; } - if ( ent_player.zombie_vars[ "zombie_powerup_tesla_on" ] || ent_player getcurrentweapon() == "tesla_gun_zm" && isDefined( ent_player.has_tesla ) && ent_player.has_tesla ) + if ( ent_player.zombie_vars[ "zombie_powerup_tesla_on" ] && ent_player getcurrentweapon() == "tesla_gun_zm" || isDefined( ent_player.has_tesla ) && ent_player.has_tesla ) { ent_player givemaxammo( "tesla_gun_zm" ); if ( ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] < time ) @@ -2383,7 +2380,7 @@ tesla_weapon_powerup( ent_player, time ) //unused did not check level thread tesla_weapon_powerup_replace( ent_player, "tesla_time_over" ); } -tesla_weapon_powerup_countdown( ent_player, str_gun_return_notify, time ) //unused did not check +tesla_weapon_powerup_countdown( ent_player, str_gun_return_notify, time ) //checked changed to match cerberus output { ent_player endon( "death" ); ent_player endon( "player_downed" ); @@ -2405,14 +2402,10 @@ tesla_weapon_powerup_countdown( ent_player, str_gun_return_notify, time ) //unus { ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = 1; } - else + else if ( clip_count == 3 ) { - if ( clip_count == 3 ) - { - ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = 6; - } + ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = 6; } - continue; } else { @@ -2423,7 +2416,7 @@ tesla_weapon_powerup_countdown( ent_player, str_gun_return_notify, time ) //unus level thread tesla_weapon_powerup_remove( ent_player, str_gun_return_notify ); } -tesla_weapon_powerup_replace( ent_player, str_gun_return_notify ) //unused did not check +tesla_weapon_powerup_replace( ent_player, str_gun_return_notify ) //checked matches cerberus output { ent_player endon( "death" ); ent_player endon( "disconnect" ); @@ -2436,7 +2429,7 @@ tesla_weapon_powerup_replace( ent_player, str_gun_return_notify ) //unused did n ent_player decrement_is_drinking(); } -tesla_weapon_powerup_remove( ent_player, str_gun_return_notify ) //unused did not check +tesla_weapon_powerup_remove( ent_player, str_gun_return_notify ) //checked changed to match cerberus output { ent_player endon( "death" ); ent_player endon( "player_downed" ); @@ -2447,18 +2440,16 @@ tesla_weapon_powerup_remove( ent_player, str_gun_return_notify ) //unused did no ent_player.has_powerup_weapon = 0; ent_player notify( str_gun_return_notify ); ent_player decrement_is_drinking(); - while ( isDefined( ent_player._zombie_gun_before_tesla ) ) + if ( isDefined( ent_player._zombie_gun_before_tesla ) ) { player_weapons = ent_player getweaponslistprimaries(); - i = 0; - while ( i < player_weapons.size ) + for ( i = 0; i < player_weapons.size; i++ ) { if ( player_weapons[ i ] == ent_player._zombie_gun_before_tesla ) { ent_player switchtoweapon( ent_player._zombie_gun_before_tesla ); return; } - i++; } } primaryweapons = ent_player getweaponslistprimaries(); @@ -2466,42 +2457,35 @@ tesla_weapon_powerup_remove( ent_player, str_gun_return_notify ) //unused did no { ent_player switchtoweapon( primaryweapons[ 0 ] ); } - else + allweapons = ent_player getweaponslist( 1 ); + for ( i = 0; i < allweapons.size; i++ ) { - allweapons = ent_player getweaponslist( 1 ); - i = 0; - while ( i < allweapons.size ) + if ( is_melee_weapon( allweapons[ i ] ) ) { - if ( is_melee_weapon( allweapons[ i ] ) ) - { - ent_player switchtoweapon( allweapons[ i ] ); - return; - } - i++; + ent_player switchtoweapon( allweapons[ i ] ); + return; } } } -tesla_weapon_powerup_off() //unused did not check +tesla_weapon_powerup_off() //checked matches cerberus output { self.zombie_vars[ "zombie_powerup_tesla_time" ] = 0; } -tesla_watch_gunner_downed() //unused did not check +tesla_watch_gunner_downed() //checked changed to match cerberus output { if ( isDefined( self.has_tesla ) && !self.has_tesla ) { return; } primaryweapons = self getweaponslistprimaries(); - i = 0; - while ( i < primaryweapons.size ) + for ( i = 0; i < primaryweapons.size; i++ ) { if ( primaryweapons[ i ] == "tesla_gun_zm" ) { self takeweapon( "tesla_gun_zm" ); } - i++; } self notify( "tesla_time_over" ); self.zombie_vars[ "zombie_powerup_tesla_on" ] = 0; @@ -2511,23 +2495,49 @@ tesla_watch_gunner_downed() //unused did not check self.has_powerup_weapon = 0; } -tesla_powerup_active() //unused did not check +tesla_powerup_active() //checked changed to match cerberus output { players = get_players(); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { if ( players[ i ].zombie_vars[ "zombie_powerup_tesla_on" ] ) { return 1; } - i++; } return 0; } print_powerup_drop( powerup, type ) //devcall only, deleted { + /* + /# + if(!isdefined(level.powerup_drop_time)) + { + level.powerup_drop_time = 0; + level.powerup_random_count = 0; + level.powerup_score_count = 0; + } + time = GetTime() - level.powerup_drop_time * 0.001; + level.powerup_drop_time = GetTime(); + if(type == "random") + { + level.powerup_random_count++; + } + else + { + level.powerup_score_count++; + } + println("========== POWER UP DROPPED =========="); + println("DROPPED: " + powerup); + println("HOW IT DROPPED: " + type); + println("--------------------"); + println("Drop Time: " + time); + println("Random Powerup Count: " + level.powerup_random_count); + println("Random Powerup Count: " + level.powerup_score_count); + println("======================================"); + #/ + */ } register_carpenter_node( node, callback ) //checked matches cerberus output @@ -2552,8 +2562,7 @@ start_carpenter_new( origin ) //checked partially changed to match cerberus outp carp_ent playloopsound( "evt_carpenter" ); boards_near_players = get_near_boards( window_boards ); boards_far_from_players = get_far_boards( window_boards ); - //broken non essential - //level repair_far_boards( boards_far_from_players, maps/mp/zombies/_zm_powerups::is_carpenter_boards_upgraded() ); + level repair_far_boards( boards_far_from_players, maps/mp/zombies/_zm_powerups::is_carpenter_boards_upgraded() ); i = 0; while ( i < boards_near_players.size ) @@ -2616,11 +2625,9 @@ start_carpenter_new( origin ) //checked partially changed to match cerberus outp carp_ent playsoundwithnotify( "evt_carpenter_end", "sound_done" ); carp_ent waittill( "sound_done" ); players = get_players(); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { players[ i ] maps/mp/zombies/_zm_score::player_add_points( "carpenter_powerup", 200 ); - i++; } carp_ent delete(); level notify( "carpenter_finished" ); @@ -2640,29 +2647,29 @@ get_near_boards( windows ) //checked changed to match cerberus output { players = get_players(); boards_near_players = []; - for(j = 0; j < windows.size; j++) + for ( j = 0; j < windows.size; j++ ) { close = 0; - for(i = 0; i < players.size; i++) + for ( i = 0; i < players.size; i++ ) { origin = undefined; - if(isdefined(windows[j].zbarrier)) + if ( isdefined( windows[ j ].zbarrier ) ) { - origin = windows[j].zbarrier.origin; + origin = windows[ j ].zbarrier.origin; } else { - origin = windows[j].origin; + origin = windows[ j ].origin; } - if(distancesquared(players[i].origin, origin) <= level.board_repair_distance_squared) + if ( distancesquared( players[ i ].origin, origin ) <= level.board_repair_distance_squared ) { close = 1; break; } } - if(close) + if ( close ) { - boards_near_players[boards_near_players.size] = windows[j]; + boards_near_players[ boards_near_players.size ] = windows[ j ]; } } return boards_near_players; @@ -2672,29 +2679,29 @@ get_far_boards( windows ) //checked changed to match cerberus output { players = get_players(); boards_far_from_players = []; - for(j = 0; j < windows.size; j++) + for ( j = 0; j < windows.size; j++ ) { close = 0; - for(i = 0; i < players.size; i++) + for ( i = 0; i < players.size; i++ ) { origin = undefined; - if(isdefined(windows[j].zbarrier)) + if ( isdefined( windows[ j ].zbarrier ) ) { - origin = windows[j].zbarrier.origin; + origin = windows[ j ].zbarrier.origin; } else { - origin = windows[j].origin; + origin = windows[ j ].origin; } - if(distancesquared(players[i].origin, origin) >= level.board_repair_distance_squared) + if ( distancesquared( players[ i ].origin, origin ) >= level.board_repair_distance_squared ) { close = 1; break; } } - if(close) + if ( close ) { - boards_far_from_players[boards_far_from_players.size] = windows[j]; + boards_far_from_players[ boards_far_from_players.size ] = windows[ j ]; } } return boards_far_from_players; @@ -2702,50 +2709,56 @@ get_far_boards( windows ) //checked changed to match cerberus output repair_far_boards( barriers, upgrade ) //checked changed to match cerberus output { - for(i = 0; i < barriers.size; i++) + i = 0; + while ( i < barriers.size ) { - barrier = barriers[i]; - if(all_chunks_intact(barrier, barrier.barrier_chunks)) + barrier = barriers[ i ]; + if ( all_chunks_intact( barrier, barrier.barrier_chunks ) ) { + i++; continue; } - if(isdefined(barrier.zbarrier)) + if ( isdefined( barrier.zbarrier ) ) { - a_pieces = barrier.zbarrier getzbarrierpieceindicesinstate("open"); - if(isdefined(a_pieces)) + a_pieces = barrier.zbarrier getzbarrierpieceindicesinstate( "open" ); + if ( isdefined( a_pieces ) ) { - for(xx = 0; xx < a_pieces.size; xx++) + xx = 0; + while ( xx < a_pieces.size ) { - chunk = a_pieces[xx]; - if(upgrade) + chunk = a_pieces[ xx ]; + if ( upgrade ) { - barrier.zbarrier zbarrierpieceuseupgradedmodel(chunk); - barrier.zbarrier.chunk_health[chunk] = barrier.zbarrier getupgradedpiecenumlives(chunk); + barrier.zbarrier zbarrierpieceuseupgradedmodel( chunk ); + barrier.zbarrier.chunk_health[ chunk ] = barrier.zbarrier getupgradedpiecenumlives( chunk ); + xx++; continue; } - barrier.zbarrier zbarrierpieceusedefaultmodel(chunk); - barrier.zbarrier.chunk_health[chunk] = 0; + barrier.zbarrier zbarrierpieceusedefaultmodel( chunk ); + barrier.zbarrier.chunk_health[ chunk ] = 0; + xx++; } } - for(x = 0; x < barrier.zbarrier getnumzbarrierpieces(); x++) + for ( x = 0; x < barrier.zbarrier getnumzbarrierpieces(); x++ ) { - barrier.zbarrier setzbarrierpiecestate(x, "closed"); - barrier.zbarrier showzbarrierpiece(x); + barrier.zbarrier setzbarrierpiecestate( x, "closed" ); + barrier.zbarrier showzbarrierpiece( x ); } } - else if(isdefined(barrier.clip)) + else if ( isdefined( barrier.clip ) ) { barrier.clip enable_trigger(); barrier.clip disconnectpaths(); } else { - blocker_disconnect_paths(barrier.neg_start, barrier.neg_end); + blocker_disconnect_paths( barrier.neg_start, barrier.neg_end ); } - if(i % 4 == 0) + if ( i % 4 == 0 ) { wait_network_frame(); } + i++; } } @@ -2826,21 +2839,17 @@ powerup_emp() //checked matches cerberus output } } -get_powerups( origin, radius ) //checked partially matches cerberus output did not change +get_powerups( origin, radius ) //checked changed to match cerberus output { if ( isDefined( origin ) && isDefined( radius ) ) { powerups = []; - _a3603 = level.active_powerups; - _k3603 = getFirstArrayKey( _a3603 ); - while ( isDefined( _k3603 ) ) + foreach ( powerup in level.active_powerups ) { - powerup = _a3603[ _k3603 ]; - if ( distancesquared( origin, powerup.origin ) < ( radius * radius ) ) + if ( distancesquared( origin, powerup.origin ) < radius * radius ) { powerups[ powerups.size ] = powerup; } - _k3603 = getNextArrayKey( _a3603, _k3603 ); } return powerups; } @@ -2865,6 +2874,19 @@ teller_withdrawl( powerup, player ) //checked matches cerberus output player maps/mp/zombies/_zm_score::add_to_player_score( powerup.value ); } +zombies_always_drop_powerups() //debug code added +{ + if ( !level.zombiesAlwaysDropPowerups ) + { + return; + } + while ( 1 ) + { + level.zombie_vars[ "zombie_drop_item" ] = level.zombiesAlwaysDropPowerups; + wait 0.05; + } +} + diff --git a/patch_zm/maps/mp/zombies/_zm_score.gsc b/patch_zm/maps/mp/zombies/_zm_score.gsc index 6d833af..91101e7 100644 --- a/patch_zm/maps/mp/zombies/_zm_score.gsc +++ b/patch_zm/maps/mp/zombies/_zm_score.gsc @@ -4,7 +4,7 @@ #include maps/mp/_utility; #include common_scripts/utility; -init() +init() //checked matches cerberus output { level.score_cf_info = []; score_cf_register_info( "damage", 1, 7 ); @@ -19,7 +19,7 @@ init() } } -score_cf_register_info( name, version, max_count ) +score_cf_register_info( name, version, max_count ) //checked matches cerberus output { if ( level.createfx_enabled ) { @@ -36,7 +36,7 @@ score_cf_register_info( name, version, max_count ) registerclientfield( "allplayers", info.cf_field, info.version, info.bit_count, "int" ); } -score_cf_increment_info( name ) +score_cf_increment_info( name ) //checked matches cerberus output { info = level.score_cf_info[ name ]; player_ent_index = self getentitynumber(); @@ -52,7 +52,7 @@ score_cf_increment_info( name ) self setclientfield( info.cf_field, info.players[ player_ent_index ] ); } -score_cf_monitor() +score_cf_monitor() //checked changed to match cerberus output { if ( level.createfx_enabled ) { @@ -63,25 +63,22 @@ score_cf_monitor() { wait_network_frame(); players = get_players(); - player_index = 0; - while ( player_index < players.size ) + for ( player_index = 0; player_index < players.size; player_index++ ) { player = players[ player_index ]; player_ent_index = player getentitynumber(); info_index = 0; - while ( info_index < info_keys.size ) + for ( info_index = 0; info_index < info_keys.size; info_index++ ) { info = level.score_cf_info[ info_keys[ info_index ] ]; info.players[ player_ent_index ] = 0; player setclientfield( info.cf_field, 0 ); - info_index++; } - player_index++; } } } -player_add_points( event, mod, hit_location, is_dog, zombie_team, damage_weapon ) +player_add_points( event, mod, hit_location, is_dog, zombie_team, damage_weapon ) //checked changed to match cerberus output { if ( level.intermission ) { @@ -169,7 +166,7 @@ player_add_points( event, mod, hit_location, is_dog, zombie_team, damage_weapon } player_points = multiplier * round_up_score( player_points, 5 ); team_points = multiplier * round_up_score( team_points, 5 ); - if ( isDefined( self.point_split_receiver ) || event == "death" && event == "ballistic_knife_death" ) + if ( isDefined( self.point_split_receiver ) && event == "death" || isDefined( self.point_split_receiver ) && event == "ballistic_knife_death" ) { split_player_points = player_points - round_up_score( player_points * self.point_split_keep_percent, 10 ); self.point_split_receiver add_to_player_score( split_player_points ); @@ -187,7 +184,7 @@ player_add_points( event, mod, hit_location, is_dog, zombie_team, damage_weapon } } -get_points_multiplier( player ) +get_points_multiplier( player ) //checked matches cerberus output { multiplier = level.zombie_vars[ player.team ][ "zombie_point_scalar" ]; if ( isDefined( level.current_game_module ) && level.current_game_module == 2 ) @@ -204,7 +201,7 @@ get_points_multiplier( player ) return multiplier; } -get_zombie_death_player_points() +get_zombie_death_player_points() //checked matches cerberus output { players = get_players(); if ( players.size == 1 ) @@ -226,7 +223,7 @@ get_zombie_death_player_points() return points; } -get_zombie_death_team_points() +get_zombie_death_team_points() //checked matches cerberus output { players = get_players(); if ( players.size == 1 ) @@ -248,7 +245,7 @@ get_zombie_death_team_points() return points; } -player_add_points_kill_bonus( mod, hit_location ) +player_add_points_kill_bonus( mod, hit_location ) //checked matches cerberus output { if ( mod == "MOD_MELEE" ) { @@ -287,7 +284,7 @@ player_add_points_kill_bonus( mod, hit_location ) return score; } -player_reduce_points( event, mod, hit_location ) +player_reduce_points( event, mod, hit_location ) //checked matches cerberus output { if ( level.intermission ) { @@ -326,7 +323,7 @@ player_reduce_points( event, mod, hit_location ) self.score = points; } -add_to_player_score( points, add_to_total ) +add_to_player_score( points, add_to_total ) //checked matches cerberus output { if ( !isDefined( add_to_total ) ) { @@ -345,7 +342,7 @@ add_to_player_score( points, add_to_total ) self incrementplayerstat( "score", points ); } -minus_to_player_score( points, ignore_double_points_upgrade ) +minus_to_player_score( points, ignore_double_points_upgrade ) //checked matches cerberus output { if ( !isDefined( points ) || level.intermission ) { @@ -363,29 +360,27 @@ minus_to_player_score( points, ignore_double_points_upgrade ) level notify( "spent_points" ); } -add_to_team_score( points ) +add_to_team_score( points ) //checked matches cerberus output { } -minus_to_team_score( points ) +minus_to_team_score( points ) //checked matches cerberus output { } -player_died_penalty() +player_died_penalty() //checked changed to match cerberus output { players = get_players( self.team ); - i = 0; - while ( i < players.size ) + for ( i = 0; i < players.size; i++ ) { if ( players[ i ] != self && !players[ i ].is_zombie ) { players[ i ] player_reduce_points( "no_revive_penalty" ); } - i++; } } -player_downed_penalty() +player_downed_penalty() //checked matches cerberus output { /* /# @@ -395,3 +390,4 @@ player_downed_penalty() self player_reduce_points( "downed" ); } + diff --git a/patch_zm/maps/mp/zombies/_zm_sidequests.gsc b/patch_zm/maps/mp/zombies/_zm_sidequests.gsc new file mode 100644 index 0000000..72aa244 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_sidequests.gsc @@ -0,0 +1,1130 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init_sidequests() +{ + level._sidequest_icons_base_x = -225; + level._zombie_sidequests = []; +/# + level thread sidequest_debug(); +#/ +} + +is_sidequest_allowed( a_gametypes ) +{ + if ( isDefined( level.gamedifficulty ) && level.gamedifficulty == 0 ) + { + return 0; + } + b_is_gametype_active = 0; + if ( !isarray( a_gametypes ) ) + { + a_gametypes = array( a_gametypes ); + } + i = 0; + while ( i < a_gametypes.size ) + { + if ( getDvar( "g_gametype" ) == a_gametypes[ i ] ) + { + b_is_gametype_active = 1; + } + i++; + } + return b_is_gametype_active; +} + +sidequest_debug() +{ +/# + if ( getDvar( #"A7AC338D" ) != "1" ) + { + return; + } + while ( 1 ) + { + wait 1; +#/ + } +} + +damager_trigger_thread( dam_types, trigger_func ) +{ + while ( 1 ) + { + self waittill( "damage", amount, attacker, dir, point, type ); + self.dam_amount = amount; + self.attacker = attacker; + self.dam_dir = dir; + self.dam_point = point; + self.dam_type = type; + i = 0; + while ( i < dam_types.size ) + { + if ( type == dam_types[ i ] ) + { + break; + } + else + { + i++; + } + } + } + if ( isDefined( trigger_func ) ) + { + self [[ trigger_func ]](); + } + self notify( "triggered" ); +} + +damage_trigger_thread() +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( "damage" ); + self.owner_ent notify( "triggered" ); + } +} + +sidequest_uses_teleportation( name ) +{ + level._zombie_sidequests[ name ].uses_teleportation = 1; +} + +declare_sidequest_icon( sidequest_name, icon_name, shader_name ) +{ + sidequest = level._zombie_sidequests[ sidequest_name ]; + sidequest.icons[ icon_name ] = shader_name; +} + +create_icon( shader_name, x ) +{ + icon = create_simple_hud( self ); + icon.foreground = 1; + icon.sort = 2; + icon.hidewheninmenu = 0; + icon.alignx = "center"; + icon.aligny = "bottom"; + icon.horzalign = "user_right"; + icon.vertalign = "user_bottom"; + icon.x = x; + icon.y = 0; + icon.alpha = 1; + icon setshader( shader_name, 32, 32 ); + return icon; +} + +add_sidequest_icon( sidequest_name, icon_name ) +{ + if ( !isDefined( self.sidequest_icons ) ) + { + self.sidequest_icons = []; + } + if ( isDefined( self.sidequest_icons[ icon_name ] ) ) + { + return; + } + sq = level._zombie_sidequests[ sidequest_name ]; + base_x = level._sidequest_icons_base_x; + if ( isDefined( level._zombiemode_sidequest_icon_offset ) ) + { + base_x += level._zombiemode_sidequest_icon_offset; + } + self.sidequest_icons[ icon_name ] = self create_icon( sq.icons[ icon_name ], base_x + ( self.sidequest_icons.size * 34 ) ); +} + +remove_sidequest_icon( sidequest_name, icon_name ) +{ + if ( !isDefined( self.sidequest_icons ) ) + { + return; + } + if ( !isDefined( self.sidequest_icons[ icon_name ] ) ) + { + return; + } + icon = self.sidequest_icons[ icon_name ]; + new_array = []; + keys = getarraykeys( self.sidequest_icons ); + i = 0; + while ( i < keys.size ) + { + if ( keys[ i ] != icon_name ) + { + new_array[ keys[ i ] ] = self.sidequest_icons[ keys[ i ] ]; + } + i++; + } + self.sidequest_icons = new_array; + icon destroy(); + keys = getarraykeys( self.sidequest_icons ); + base_x = level._sidequest_icons_base_x; + if ( isDefined( level._zombiemode_sidequest_icon_offset ) ) + { + base_x += level._zombiemode_sidequest_icon_offset; + } + i = 0; + while ( i < keys.size ) + { + self.sidequest_icons[ keys[ i ] ].x = base_x + ( i * 34 ); + i++; + } +} + +declare_sidequest( name, init_func, logic_func, complete_func, generic_stage_start_func, generic_stage_end_func ) +{ + if ( !isDefined( level._zombie_sidequests ) ) + { + init_sidequests(); + } +/# + if ( isDefined( level._zombie_sidequests[ name ] ) ) + { + println( "*** ERROR: Attempt to re-declare sidequest with name " + name ); + return; +#/ + } + sq = spawnstruct(); + sq.name = name; + sq.stages = []; + sq.last_completed_stage = -1; + sq.active_stage = -1; + sq.sidequest_complete = 0; + sq.init_func = init_func; + sq.logic_func = logic_func; + sq.complete_func = complete_func; + sq.generic_stage_start_func = generic_stage_start_func; + sq.generic_stage_end_func = generic_stage_end_func; + sq.assets = []; + sq.uses_teleportation = 0; + sq.active_assets = []; + sq.icons = []; + sq.num_reps = 0; + level._zombie_sidequests[ name ] = sq; +} + +declare_sidequest_stage( sidequest_name, stage_name, init_func, logic_func, exit_func ) +{ +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to declare a side quest stage before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to add stage " + stage_name + " to side quest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( isDefined( level._zombie_sidequests[ sidequest_name ].stages[ stage_name ] ) ) + { + println( "*** ERROR: Sidequest " + sidequest_name + " already has a stage called " + stage_name ); + return; +#/ + } + stage = spawnstruct(); + stage.name = stage_name; + stage.stage_number = level._zombie_sidequests[ sidequest_name ].stages.size; + stage.assets = []; + stage.active_assets = []; + stage.logic_func = logic_func; + stage.init_func = init_func; + stage.exit_func = exit_func; + stage.completed = 0; + stage.time_limit = 0; + level._zombie_sidequests[ sidequest_name ].stages[ stage_name ] = stage; +} + +set_stage_time_limit( sidequest_name, stage_name, time_limit, timer_func ) +{ +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to set a side quest stage time limit before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to add timelimit to stage " + stage_name + " in side quest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ].stages[ stage_name ] ) ) + { + println( "*** ERROR: Attempt to add timelimit to stage " + stage_name + " in Sidequest " + sidequest_name + " but stage does not exist." ); + return; +#/ + } + level._zombie_sidequests[ sidequest_name ].stages[ stage_name ].time_limit = time_limit; + level._zombie_sidequests[ sidequest_name ].stages[ stage_name ].time_limit_func = timer_func; +} + +declare_stage_asset_from_struct( sidequest_name, stage_name, target_name, thread_func, trigger_thread_func ) +{ + structs = getstructarray( target_name, "targetname" ); +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to declare a side quest asset " + target_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to add asset " + target_name + " to side quest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ].stages[ stage_name ] ) ) + { + println( "*** ERROR: Attempt to add asset " + target_name + " to side quest " + sidequest_name + " : " + stage_name + " but no such stage exists." ); + return; + } + if ( !structs.size ) + { + println( "*** ERROR: No Structs with " + target_name + " not found." ); + return; +#/ + } + i = 0; + while ( i < structs.size ) + { + asset = spawnstruct(); + asset.type = "struct"; + asset.struct = structs[ i ]; + asset.thread_func = thread_func; + asset.trigger_thread_func = trigger_thread_func; + level._zombie_sidequests[ sidequest_name ].stages[ stage_name ].assets[ level._zombie_sidequests[ sidequest_name ].stages[ stage_name ].assets.size ] = asset; + i++; + } +} + +declare_stage_title( sidequest_name, stage_name, title ) +{ +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to declare a stage title " + title + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to declare a stage title " + title + " to side quest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ].stages[ stage_name ] ) ) + { + println( "*** ERROR: Attempt to declare stage title " + title + " to side quest " + sidequest_name + " : " + stage_name + " but no such stage exists." ); + return; +#/ + } + level._zombie_sidequests[ sidequest_name ].stages[ stage_name ].title = title; +} + +declare_stage_asset( sidequest_name, stage_name, target_name, thread_func, trigger_thread_func ) +{ + ents = getentarray( target_name, "targetname" ); +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to declare a side quest asset " + target_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to add asset " + target_name + " to side quest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ].stages[ stage_name ] ) ) + { + println( "*** ERROR: Attempt to add asset " + target_name + " to side quest " + sidequest_name + " : " + stage_name + " but no such stage exists." ); + return; + } + if ( !ents.size ) + { + println( "*** ERROR: No Ents with " + target_name + " not found." ); + return; +#/ + } + i = 0; + while ( i < ents.size ) + { + asset = spawnstruct(); + asset.type = "entity"; + asset.ent = ents[ i ]; + asset.thread_func = thread_func; + asset.trigger_thread_func = trigger_thread_func; + level._zombie_sidequests[ sidequest_name ].stages[ stage_name ].assets[ level._zombie_sidequests[ sidequest_name ].stages[ stage_name ].assets.size ] = asset; + i++; + } +} + +declare_sidequest_asset( sidequest_name, target_name, thread_func, trigger_thread_func ) +{ + ents = getentarray( target_name, "targetname" ); +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to declare a side quest asset " + target_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to add asset " + target_name + " to side quest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( !ents.size ) + { + println( "*** ERROR: No Ents with " + target_name + " not found." ); + return; +#/ + } + i = 0; + while ( i < ents.size ) + { + asset = spawnstruct(); + asset.type = "entity"; + asset.ent = ents[ i ]; + asset.thread_func = thread_func; + asset.trigger_thread_func = trigger_thread_func; + asset.ent.thread_func = thread_func; + asset.ent.trigger_thread_func = trigger_thread_func; + level._zombie_sidequests[ sidequest_name ].assets[ level._zombie_sidequests[ sidequest_name ].assets.size ] = asset; + i++; + } +} + +declare_sidequest_asset_from_struct( sidequest_name, target_name, thread_func, trigger_thread_func ) +{ + structs = getstructarray( target_name, "targetname" ); +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to declare a side quest asset " + target_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to add asset " + target_name + " to side quest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( !structs.size ) + { + println( "*** ERROR: No Structs with " + target_name + " not found." ); + return; +#/ + } + i = 0; + while ( i < structs.size ) + { + asset = spawnstruct(); + asset.type = "struct"; + asset.struct = structs[ i ]; + asset.thread_func = thread_func; + asset.trigger_thread_func = trigger_thread_func; + level._zombie_sidequests[ sidequest_name ].assets[ level._zombie_sidequests[ sidequest_name ].assets.size ] = asset; + i++; + } +} + +build_asset_from_struct( asset, parent_struct ) +{ + ent = spawn( "script_model", asset.origin ); + if ( isDefined( asset.model ) ) + { + ent setmodel( asset.model ); + } + if ( isDefined( asset.angles ) ) + { + ent.angles = asset.angles; + } + ent.script_noteworthy = asset.script_noteworthy; + ent.type = "struct"; + ent.radius = asset.radius; + ent.thread_func = parent_struct.thread_func; + ent.trigger_thread_func = parent_struct.trigger_thread_func; + ent.script_vector = parent_struct.script_vector; + asset.trigger_thread_func = parent_struct.trigger_thread_func; + asset.script_vector = parent_struct.script_vector; + ent.target = asset.target; + ent.script_float = asset.script_float; + ent.script_int = asset.script_int; + ent.script_trigger_spawnflags = asset.script_trigger_spawnflags; + ent.targetname = asset.targetname; + return ent; +} + +delete_stage_assets() +{ + i = 0; + while ( i < self.active_assets.size ) + { + asset = self.active_assets[ i ]; + switch( asset.type ) + { + case "struct": + if ( isDefined( asset.trigger ) ) + { +/# + println( "Deleting trigger from struct type asset." ); +#/ + asset.trigger delete(); + asset.trigger = undefined; + } + asset delete(); + break; + i++; + continue; + case "entity": + if ( isDefined( asset.trigger ) ) + { +/# + println( "Deleting trigger from ent type asset." ); +#/ + asset.trigger delete(); + asset.trigger = undefined; + } + break; + i++; + continue; + } + i++; + } + remaining_assets = []; + i = 0; + while ( i < self.active_assets.size ) + { + if ( isDefined( self.active_assets[ i ] ) ) + { + remaining_assets[ remaining_assets.size ] = self.active_assets[ i ]; + } + i++; + } + self.active_assets = remaining_assets; +} + +build_assets() +{ + i = 0; + while ( i < self.assets.size ) + { + asset = undefined; + switch( self.assets[ i ].type ) + { + case "struct": + asset = self.assets[ i ].struct; + self.active_assets[ self.active_assets.size ] = build_asset_from_struct( asset, self.assets[ i ] ); + break; + case "entity": + j = 0; + while ( j < self.active_assets.size ) + { + if ( self.active_assets[ j ] == self.assets[ i ].ent ) + { + asset = self.active_assets[ j ]; + break; + } + else + { + j++; + } + } + asset = self.assets[ i ].ent; + asset.type = "entity"; + self.active_assets[ self.active_assets.size ] = asset; + break; + default: +/# + println( "*** ERROR: Don't know how to build asset of type " + self.assets.type ); +#/ + break; + } + if ( isDefined( asset.script_noteworthy ) && self.assets[ i ].type == "entity" || !isDefined( asset.trigger ) && isDefined( asset.script_noteworthy ) ) + { + trigger_radius = 15; + trigger_height = 72; + if ( isDefined( asset.radius ) ) + { + trigger_radius = asset.radius; + } + if ( isDefined( asset.height ) ) + { + trigger_height = asset.height; + } + trigger_spawnflags = 0; + if ( isDefined( asset.script_trigger_spawnflags ) ) + { + trigger_spawnflags = asset.script_trigger_spawnflags; + } + trigger_offset = ( 0, 1, 0 ); + if ( isDefined( asset.script_vector ) ) + { + trigger_offset = asset.script_vector; + } + switch( asset.script_noteworthy ) + { + case "trigger_radius_use": + use_trigger = spawn( "trigger_radius_use", asset.origin + trigger_offset, trigger_spawnflags, trigger_radius, trigger_height ); + use_trigger setcursorhint( "HINT_NOICON" ); + use_trigger triggerignoreteam(); + if ( isDefined( asset.radius ) ) + { + use_trigger.radius = asset.radius; + } + use_trigger.owner_ent = self.active_assets[ self.active_assets.size - 1 ]; + if ( isDefined( asset.trigger_thread_func ) ) + { + use_trigger thread [[ asset.trigger_thread_func ]](); + } + else + { + use_trigger thread use_trigger_thread(); + } + self.active_assets[ self.active_assets.size - 1 ].trigger = use_trigger; + break; + break; + case "trigger_radius_damage": + damage_trigger = spawn( "trigger_damage", asset.origin + trigger_offset, trigger_spawnflags, trigger_radius, trigger_height ); + if ( isDefined( asset.radius ) ) + { + damage_trigger.radius = asset.radius; + } + damage_trigger.owner_ent = self.active_assets[ self.active_assets.size - 1 ]; + if ( isDefined( asset.trigger_thread_func ) ) + { + damage_trigger thread [[ asset.trigger_thread_func ]](); + } + else + { + damage_trigger thread damage_trigger_thread(); + } + self.active_assets[ self.active_assets.size - 1 ].trigger = damage_trigger; + break; + break; + case "trigger_radius": + radius_trigger = spawn( "trigger_radius", asset.origin + trigger_offset, trigger_spawnflags, trigger_radius, trigger_height ); + if ( isDefined( asset.radius ) ) + { + radius_trigger.radius = asset.radius; + } + radius_trigger.owner_ent = self.active_assets[ self.active_assets.size - 1 ]; + if ( isDefined( asset.trigger_thread_func ) ) + { + radius_trigger thread [[ asset.trigger_thread_func ]](); + } + else + { + radius_trigger thread radius_trigger_thread(); + } + self.active_assets[ self.active_assets.size - 1 ].trigger = radius_trigger; + break; + break; + } + } + if ( isDefined( self.assets[ i ].thread_func ) && !isDefined( self.active_assets[ self.active_assets.size - 1 ].dont_rethread ) ) + { + self.active_assets[ self.active_assets.size - 1 ] thread [[ self.assets[ i ].thread_func ]](); + } + if ( ( i % 2 ) == 0 ) + { + wait_network_frame(); + } + i++; + } +} + +radius_trigger_thread() +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( !isplayer( player ) ) + { + continue; + } + self.owner_ent notify( "triggered" ); + while ( player istouching( self ) ) + { + wait 0,05; + } + self.owner_ent notify( "untriggered" ); + } +} + +thread_on_assets( target_name, thread_func ) +{ + i = 0; + while ( i < self.active_assets.size ) + { + if ( self.active_assets[ i ].targetname == target_name ) + { + self.active_assets[ i ] thread [[ thread_func ]](); + } + i++; + } +} + +stage_logic_func_wrapper( sidequest, stage ) +{ + if ( isDefined( stage.logic_func ) ) + { + level endon( ( sidequest.name + "_" ) + stage.name + "_over" ); + stage [[ stage.logic_func ]](); + } +} + +sidequest_start( sidequest_name ) +{ +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt start a side quest asset " + sidequest_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to start " + sidequest_name + " but no such side quest exists." ); + return; +#/ + } + sidequest = level._zombie_sidequests[ sidequest_name ]; + sidequest build_assets(); + if ( isDefined( sidequest.init_func ) ) + { + sidequest [[ sidequest.init_func ]](); + } + if ( isDefined( sidequest.logic_func ) ) + { + sidequest thread [[ sidequest.logic_func ]](); + } +} + +stage_start( sidequest, stage ) +{ + if ( isstring( sidequest ) ) + { + sidequest = level._zombie_sidequests[ sidequest ]; + } + if ( isstring( stage ) ) + { + stage = sidequest.stages[ stage ]; + } + stage build_assets(); + sidequest.active_stage = stage.stage_number; + level notify( ( sidequest.name + "_" ) + stage.name + "_started" ); + stage.completed = 0; + if ( isDefined( sidequest.generic_stage_start_func ) ) + { + stage [[ sidequest.generic_stage_start_func ]](); + } + if ( isDefined( stage.init_func ) ) + { + stage [[ stage.init_func ]](); + } + level._last_stage_started = stage.name; + level thread stage_logic_func_wrapper( sidequest, stage ); + if ( stage.time_limit > 0 ) + { + stage thread time_limited_stage( sidequest ); + } + if ( isDefined( stage.title ) ) + { + stage thread display_stage_title( sidequest.uses_teleportation ); + } +} + +display_stage_title( wait_for_teleport_done_notify ) +{ + if ( wait_for_teleport_done_notify ) + { + level waittill( "teleport_done" ); + wait 2; + } + stage_text = newhudelem(); + stage_text.location = 0; + stage_text.alignx = "center"; + stage_text.aligny = "middle"; + stage_text.foreground = 1; + stage_text.fontscale = 1,6; + stage_text.sort = 20; + stage_text.x = 320; + stage_text.y = 300; + stage_text.og_scale = 1; + stage_text.color = vectorScale( ( 0, 1, 0 ), 128 ); + stage_text.alpha = 0; + stage_text.fontstyle3d = "shadowedmore"; + stage_text settext( self.title ); + stage_text fadeovertime( 0,5 ); + stage_text.alpha = 1; + wait 5; + stage_text fadeovertime( 1 ); + stage_text.alpha = 0; + wait 1; + stage_text destroy(); +} + +time_limited_stage( sidequest ) +{ +/# + println( "*** Starting timer for sidequest " + sidequest.name + " stage " + self.name + " : " + self.time_limit + " seconds." ); +#/ + level endon( ( sidequest.name + "_" ) + self.name + "_over" ); + level endon( "suspend_timer" ); + level endon( "end_game" ); + time_limit = undefined; + if ( isDefined( self.time_limit_func ) ) + { + time_limit = [[ self.time_limit_func ]]() * 0,25; + } + else + { + time_limit = self.time_limit * 0,25; + } + wait time_limit; + level notify( "timed_stage_75_percent" ); + wait time_limit; + level notify( "timed_stage_50_percent" ); + wait time_limit; + level notify( "timed_stage_25_percent" ); + wait ( time_limit - 10 ); + level notify( "timed_stage_10_seconds_to_go" ); + wait 10; + stage_failed( sidequest, self ); +} + +sidequest_println( str ) +{ +/# + if ( getDvar( #"A7AC338D" ) != "1" ) + { + return; + } + println( str ); +#/ +} + +precache_sidequest_assets() +{ + sidequest_names = getarraykeys( level._zombie_sidequests ); + i = 0; + while ( i < sidequest_names.size ) + { + sq = level._zombie_sidequests[ sidequest_names[ i ] ]; + icon_keys = getarraykeys( sq.icons ); + j = 0; + while ( j < icon_keys.size ) + { + precacheshader( sq.icons[ icon_keys[ j ] ] ); + j++; + } + stage_names = getarraykeys( sq.stages ); + j = 0; + while ( j < stage_names.size ) + { + stage = sq.stages[ stage_names[ j ] ]; + k = 0; + while ( k < stage.assets.size ) + { + asset = stage.assets[ k ]; + if ( isDefined( asset.type ) && asset.type == "struct" ) + { + if ( isDefined( asset.model ) ) + { + precachemodel( asset.model ); + } + } + k++; + } + j++; + } + i++; + } +} + +sidequest_complete( sidequest_name ) +{ +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to call sidequest_complete for sidequest " + sidequest_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to call sidequest_complete for sidequest " + sidequest_name + " but no such side quest exists." ); + return; +#/ + } + return level._zombie_sidequests[ sidequest_name ].sidequest_complete; +} + +stage_completed( sidequest_name, stage_name ) +{ +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt to call stage_complete for sidequest " + sidequest_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to call stage_complete for sidequest " + sidequest_name + " but no such side quest exists." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ].stages[ stage_name ] ) ) + { + println( "*** ERROR: Attempt to call stage_complete in sq " + sidequest_name + " : " + stage_name + " but no such stage exists." ); + return; + } + println( "*** stage completed called." ); +#/ + sidequest = level._zombie_sidequests[ sidequest_name ]; + stage = sidequest.stages[ stage_name ]; + level thread stage_completed_internal( sidequest, stage ); +} + +stage_completed_internal( sidequest, stage ) +{ + level notify( ( sidequest.name + "_" ) + stage.name + "_over" ); + level notify( ( sidequest.name + "_" ) + stage.name + "_completed" ); + if ( isDefined( sidequest.generic_stage_end_func ) ) + { +/# + println( "Calling generic end func." ); +#/ + stage [[ sidequest.generic_stage_end_func ]](); + } + if ( isDefined( stage.exit_func ) ) + { +/# + println( "Calling stage end func." ); +#/ + stage [[ stage.exit_func ]]( 1 ); + } + stage.completed = 1; + sidequest.last_completed_stage = sidequest.active_stage; + sidequest.active_stage = -1; + stage delete_stage_assets(); + all_complete = 1; + stage_names = getarraykeys( sidequest.stages ); + i = 0; + while ( i < stage_names.size ) + { + if ( sidequest.stages[ stage_names[ i ] ].completed == 0 ) + { + all_complete = 0; + break; + } + else + { + i++; + } + } + if ( all_complete == 1 ) + { + if ( isDefined( sidequest.complete_func ) ) + { + sidequest thread [[ sidequest.complete_func ]](); + } + level notify( "sidequest_" + sidequest.name + "_complete" ); + sidequest.sidequest_completed = 1; + } +} + +stage_failed_internal( sidequest, stage ) +{ + level notify( ( sidequest.name + "_" ) + stage.name + "_over" ); + level notify( ( sidequest.name + "_" ) + stage.name + "_failed" ); + if ( isDefined( sidequest.generic_stage_end_func ) ) + { + stage [[ sidequest.generic_stage_end_func ]](); + } + if ( isDefined( stage.exit_func ) ) + { + stage [[ stage.exit_func ]]( 0 ); + } + sidequest.active_stage = -1; + stage delete_stage_assets(); +} + +stage_failed( sidequest, stage ) +{ +/# + println( "*** Stage failed called." ); +#/ + if ( isstring( sidequest ) ) + { + sidequest = level._zombie_sidequests[ sidequest ]; + } + if ( isstring( stage ) ) + { + stage = sidequest.stages[ stage ]; + } + level thread stage_failed_internal( sidequest, stage ); +} + +get_sidequest_stage( sidequest, stage_number ) +{ + stage = undefined; + stage_names = getarraykeys( sidequest.stages ); + i = 0; + while ( i < stage_names.size ) + { + if ( sidequest.stages[ stage_names[ i ] ].stage_number == stage_number ) + { + stage = sidequest.stages[ stage_names[ i ] ]; + break; + } + else + { + i++; + } + } + return stage; +} + +get_damage_trigger( radius, origin, damage_types ) +{ + trig = spawn( "trigger_damage", origin, 0, radius, 72 ); + trig thread dam_trigger_thread( damage_types ); + return trig; +} + +dam_trigger_thread( damage_types ) +{ + self endon( "death" ); + damage_type = "NONE"; + while ( 1 ) + { + self waittill( "damage", amount, attacker, dir, point, mod ); + i = 0; + while ( i < damage_types.size ) + { + if ( mod == damage_types[ i ] ) + { + self notify( "triggered" ); + } + i++; + } + } +} + +use_trigger_thread() +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( "trigger", player ); + self.owner_ent notify( "triggered" ); + wait 0,1; + } +} + +sidequest_stage_active( sidequest_name, stage_name ) +{ + sidequest = level._zombie_sidequests[ sidequest_name ]; + stage = sidequest.stages[ stage_name ]; + if ( sidequest.active_stage == stage.stage_number ) + { + return 1; + } + else + { + return 0; + } +} + +sidequest_start_next_stage( sidequest_name ) +{ +/# + if ( !isDefined( level._zombie_sidequests ) ) + { + println( "*** ERROR: Attempt start next stage in side quest asset " + sidequest_name + " before sidequests declared." ); + return; + } + if ( !isDefined( level._zombie_sidequests[ sidequest_name ] ) ) + { + println( "*** ERROR: Attempt to start next sidequest in sidequest " + sidequest_name + " but no such side quest exists." ); + return; +#/ + } + sidequest = level._zombie_sidequests[ sidequest_name ]; + if ( sidequest.sidequest_complete == 1 ) + { + return; + } + last_completed = sidequest.last_completed_stage; + if ( last_completed == -1 ) + { + last_completed = 0; + } + else + { + last_completed++; + } + stage = get_sidequest_stage( sidequest, last_completed ); + if ( !isDefined( stage ) ) + { +/# + println( "*** ERROR: Sidequest " + sidequest_name + " has no stage number " + last_completed ); +#/ + return; + } + stage_start( sidequest, stage ); + return stage; +} + +main() +{ +} + +is_facing( facee ) +{ + orientation = self getplayerangles(); + forwardvec = anglesToForward( orientation ); + forwardvec2d = ( forwardvec[ 0 ], forwardvec[ 1 ], 0 ); + unitforwardvec2d = vectornormalize( forwardvec2d ); + tofaceevec = facee.origin - self.origin; + tofaceevec2d = ( tofaceevec[ 0 ], tofaceevec[ 1 ], 0 ); + unittofaceevec2d = vectornormalize( tofaceevec2d ); + dotproduct = vectordot( unitforwardvec2d, unittofaceevec2d ); + return dotproduct > 0,9; +} + +fake_use( notify_string, qualifier_func ) +{ + waittillframeend; + while ( 1 ) + { + if ( !isDefined( self ) ) + { + return; + } +/# + print3d( self.origin, "+", vectorScale( ( 0, 1, 0 ), 255 ), 1 ); +#/ + players = get_players(); + i = 0; + while ( i < players.size ) + { + qualifier_passed = 1; + if ( isDefined( qualifier_func ) ) + { + qualifier_passed = players[ i ] [[ qualifier_func ]](); + } + if ( qualifier_passed && distancesquared( self.origin, players[ i ].origin ) < 4096 ) + { + if ( players[ i ] is_facing( self ) ) + { + if ( players[ i ] usebuttonpressed() ) + { + self notify( notify_string ); + return; + } + } + } + i++; + } + wait 0,1; + } +} diff --git a/patch_zm/maps/mp/zombies/_zm_stats.gsc b/patch_zm/maps/mp/zombies/_zm_stats.gsc new file mode 100644 index 0000000..9bfce24 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_stats.gsc @@ -0,0 +1,1079 @@ +#include maps/mp/gametypes_zm/_globallogic; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_pers_upgrades; +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + level.player_stats_init = ::player_stats_init; + level.add_client_stat = ::add_client_stat; + level.increment_client_stat = ::increment_client_stat; + level.track_gibs = ::do_stats_for_gibs; +} + +player_stats_init() +{ + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "kills", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "suicides", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "downs", 0 ); + self.downs = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "downs" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "revives", 0 ); + self.revives = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "revives" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "perks_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "headshots", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "gibs", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "head_gibs", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "right_arm_gibs", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "left_arm_gibs", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "right_leg_gibs", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "left_leg_gibs", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "melee_kills", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "grenade_kills", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "doors_purchased", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "distance_traveled", 0 ); + self.distance_traveled = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "distance_traveled" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "total_shots", 0 ); + self.total_shots = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "total_shots" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "hits", 0 ); + self.hits = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "hits" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "deaths", 0 ); + self.deaths = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "deaths" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "boards", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "wins", 0 ); + self.totalwins = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "totalwins" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "losses", 0 ); + self.totallosses = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "totallosses" ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "failed_revives", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "sacrifices", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "failed_sacrifices", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "drops", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "nuke_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "insta_kill_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "full_ammo_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "double_points_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "meat_stink_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "carpenter_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "fire_sale_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zombie_blood_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "time_bomb_ammo_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "use_magicbox", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "grabbed_from_magicbox", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "use_perk_random", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "grabbed_from_perk_random", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "use_pap", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pap_weapon_grabbed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pap_weapon_not_grabbed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_armorvest_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_quickrevive_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_rof_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_fastreload_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_flakjacket_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_additionalprimaryweapon_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_longersprint_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_deadshot_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_scavenger_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_finalstand_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_grenadepulldeath_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "specialty_nomotionsensor" + "_drank", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "claymores_planted", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "claymores_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "ballistic_knives_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "wallbuy_weapons_purchased", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "ammo_purchased", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "upgraded_ammo_purchased", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "power_turnedon", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "power_turnedoff", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "planted_buildables_pickedup", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buildables_built", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "time_played_total", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "weighted_rounds_played", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "contaminations_received", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "contaminations_given", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zdogs_killed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zdog_rounds_finished", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zdog_rounds_lost", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "killed_by_zdog", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "screecher_minigames_won", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "screecher_minigames_lost", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "screechers_killed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "screecher_teleporters_used", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "avogadro_defeated", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "killed_by_avogadro", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "cheat_too_many_weapons", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "cheat_out_of_playable", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "cheat_too_friendly", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "cheat_total", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_tomahawk_acquired", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_fan_trap_used", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_acid_trap_used", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_sniper_tower_used", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_ee_good_ending", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_ee_bad_ending", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_ee_spoon_acquired", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "prison_brutus_killed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_lsat_purchased", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_fountain_transporter_used", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_ghost_killed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_ghost_drained_player", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_ghost_perk_acquired", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_booze_given", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_booze_break_barricade", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_given", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_protect", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_build_buildable", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_wallbuy", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_fetch_buildable", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_box_lock", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_box_move", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_box_spin", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_powerup_cycle", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_dance", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_sloth_candy_crawler", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_wallbuy_placed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_wallbuy_placed_ak74u_zm", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_wallbuy_placed_an94_zm", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_wallbuy_placed_pdw57_zm", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_wallbuy_placed_svu_zm", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_wallbuy_placed_tazer_knuckles_zm", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "buried_wallbuy_placed_870mcs_zm", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_mechz_killed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_giant_robot_stomped", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_giant_robot_accessed", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_generator_captured", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_generator_defended", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_generator_lost", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_dig", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_golden_shovel", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_golden_hard_hat", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "tomb_perk_extension", 0 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_boarding", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_revivenoperk", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_multikill_headshots", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_cash_back_bought", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_cash_back_prone", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_insta_kill", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_nube_5_times", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_jugg", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_jugg_downgrade_count", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_carpenter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_max_round_reached", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_flopper_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_perk_lose_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_pistol_points_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_double_points_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_sniper_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_marathon_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_box_weapon_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_zombie_kiting_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_max_ammo_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_melee_bonus_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_nube_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_last_man_standing_counter", 0, 1 ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "pers_reload_speed_counter", 0, 1 ); + self maps/mp/zombies/_zm_pers_upgrades::pers_abilities_init_globals(); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "score", 0 ); + if ( level.resetplayerscoreeveryround ) + { + self.pers[ "score" ] = 0; + } + self.pers[ "score" ] = level.player_starting_points; + self.score = self.pers[ "score" ]; + self incrementplayerstat( "score", self.score ); + self maps/mp/gametypes_zm/_globallogic_score::initpersstat( "zteam", 0 ); + if ( isDefined( level.level_specific_stats_init ) ) + { + [[ level.level_specific_stats_init ]](); + } + if ( !isDefined( self.stats_this_frame ) ) + { + self.pers_upgrade_force_test = 1; + self.stats_this_frame = []; + self.pers_upgrades_awarded = []; + } +} + +update_players_stats_at_match_end( players ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + game_mode = getDvar( "ui_gametype" ); + game_mode_group = level.scr_zm_ui_gametype_group; + map_location_name = level.scr_zm_map_start_location; + if ( map_location_name == "" ) + { + map_location_name = "default"; + } + if ( isDefined( level.gamemodulewinningteam ) ) + { + if ( level.gamemodulewinningteam == "B" ) + { + matchrecorderincrementheaderstat( "winningTeam", 1 ); + } + else + { + if ( level.gamemodulewinningteam == "A" ) + { + matchrecorderincrementheaderstat( "winningTeam", 2 ); + } + } + } + recordmatchsummaryzombieendgamedata( game_mode, game_mode_group, map_location_name, level.round_number ); + newtime = getTime(); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( player is_bot() ) + { + i++; + continue; + } + else + { + distance = player get_stat_distance_traveled(); + player addplayerstatwithgametype( "distance_traveled", distance ); + player add_location_gametype_stat( level.scr_zm_map_start_location, level.scr_zm_ui_gametype, "time_played_total", player.pers[ "time_played_total" ] ); + recordplayermatchend( player ); + recordplayerstats( player, "presentAtEnd", 1 ); + player maps/mp/zombies/_zm_weapons::updateweapontimingszm( newtime ); + if ( isDefined( level._game_module_stat_update_func ) ) + { + player [[ level._game_module_stat_update_func ]](); + } + old_high_score = player get_game_mode_stat( game_mode, "score" ); + if ( player.score_total > old_high_score ) + { + player set_game_mode_stat( game_mode, "score", player.score_total ); + } + if ( gamemodeismode( level.gamemode_public_match ) ) + { + player gamehistoryfinishmatch( 4, 0, 0, 0, 0, 0 ); + if ( isDefined( player.pers[ "matchesPlayedStatsTracked" ] ) ) + { + gamemode = maps/mp/gametypes_zm/_globallogic::getcurrentgamemode(); + player maps/mp/gametypes_zm/_globallogic::incrementmatchcompletionstat( gamemode, "played", "completed" ); + if ( isDefined( player.pers[ "matchesHostedStatsTracked" ] ) ) + { + player maps/mp/gametypes_zm/_globallogic::incrementmatchcompletionstat( gamemode, "hosted", "completed" ); + } + } + } + if ( !isDefined( player.pers[ "previous_distance_traveled" ] ) ) + { + player.pers[ "previous_distance_traveled" ] = 0; + } + distancethisround = int( player.pers[ "distance_traveled" ] - player.pers[ "previous_distance_traveled" ] ); + player.pers[ "previous_distance_traveled" ] = player.pers[ "distance_traveled" ]; + player incrementplayerstat( "distance_traveled", distancethisround ); + } + i++; + } +} + +update_playing_utc_time( matchendutctime ) +{ + current_days = int( matchendutctime / 86400 ); + last_days = self get_global_stat( "TIMESTAMPLASTDAY1" ); + last_days = int( last_days / 86400 ); + diff_days = current_days - last_days; + timestamp_name = ""; + if ( diff_days > 0 ) + { + i = 5; + while ( i > diff_days ) + { + timestamp_name = "TIMESTAMPLASTDAY" + ( i - diff_days ); + timestamp_name_to = "TIMESTAMPLASTDAY" + i; + timestamp_value = self get_global_stat( timestamp_name ); + self set_global_stat( timestamp_name_to, timestamp_value ); + i--; + + } + i = 2; + while ( i <= diff_days && i < 6 ) + { + timestamp_name = "TIMESTAMPLASTDAY" + i; + self set_global_stat( timestamp_name, 0 ); + i++; + } + self set_global_stat( "TIMESTAMPLASTDAY1", matchendutctime ); + } +} + +survival_classic_custom_stat_update() +{ +} + +grief_custom_stat_update() +{ +} + +add_game_mode_group_stat( game_mode, stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( "PlayerStatsByGameTypeGroup", game_mode, stat_name, "statValue", value ); +} + +set_game_mode_group_stat( game_mode, stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self setdstat( "PlayerStatsByGameTypeGroup", game_mode, stat_name, "statValue", value ); +} + +get_game_mode_group_stat( game_mode, stat_name ) +{ + return self getdstat( "PlayerStatsByGameTypeGroup", game_mode, stat_name, "statValue" ); +} + +add_game_mode_stat( game_mode, stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( "PlayerStatsByGameType", game_mode, stat_name, "statValue", value ); +} + +set_game_mode_stat( game_mode, stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self setdstat( "PlayerStatsByGameType", game_mode, stat_name, "statValue", value ); +} + +get_game_mode_stat( game_mode, stat_name ) +{ + return self getdstat( "PlayerStatsByGameType", game_mode, stat_name, "statValue" ); +} + +get_global_stat( stat_name ) +{ + return self getdstat( "PlayerStatsList", stat_name, "StatValue" ); +} + +set_global_stat( stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self setdstat( "PlayerStatsList", stat_name, "StatValue", value ); +} + +add_global_stat( stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( "PlayerStatsList", stat_name, "StatValue", value ); +} + +get_map_stat( stat_name, map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + return self getdstat( "PlayerStatsByMap", map, stat_name ); +} + +set_map_stat( stat_name, value, map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self setdstat( "PlayerStatsByMap", map, stat_name, value ); +} + +add_map_stat( stat_name, value, map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( "PlayerStatsByMap", map, stat_name, value ); +} + +get_location_gametype_stat( start_location, game_type, stat_name ) +{ + return self getdstat( "PlayerStatsByStartLocation", start_location, "startLocationGameTypeStats", game_type, "stats", stat_name, "StatValue" ); +} + +set_location_gametype_stat( start_location, game_type, stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self setdstat( "PlayerStatsByStartLocation", start_location, "startLocationGameTypeStats", game_type, "stats", stat_name, "StatValue", value ); +} + +add_location_gametype_stat( start_location, game_type, stat_name, value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( "PlayerStatsByStartLocation", start_location, "startLocationGameTypeStats", game_type, "stats", stat_name, "StatValue", value ); +} + +get_map_weaponlocker_stat( stat_name, map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + return self getdstat( "PlayerStatsByMap", map, "weaponLocker", stat_name ); +} + +set_map_weaponlocker_stat( stat_name, value, map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + if ( isDefined( value ) ) + { + self setdstat( "PlayerStatsByMap", map, "weaponLocker", stat_name, value ); + } + else + { + self setdstat( "PlayerStatsByMap", map, "weaponLocker", stat_name, 0 ); + } +} + +add_map_weaponlocker_stat( stat_name, value, map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( "PlayerStatsByMap", map, "weaponLocker", stat_name, value ); +} + +has_stored_weapondata( map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + storedweapon = self get_map_weaponlocker_stat( "name", map ); + if ( isDefined( storedweapon ) && isstring( storedweapon ) || storedweapon == "" && isint( storedweapon ) && storedweapon == 0 ) + { + return 0; + } + return 1; +} + +get_stored_weapondata( map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + if ( self has_stored_weapondata( map ) ) + { + weapondata = []; + weapondata[ "name" ] = self get_map_weaponlocker_stat( "name", map ); + weapondata[ "lh_clip" ] = self get_map_weaponlocker_stat( "lh_clip", map ); + weapondata[ "clip" ] = self get_map_weaponlocker_stat( "clip", map ); + weapondata[ "stock" ] = self get_map_weaponlocker_stat( "stock", map ); + weapondata[ "alt_clip" ] = self get_map_weaponlocker_stat( "alt_clip", map ); + weapondata[ "alt_stock" ] = self get_map_weaponlocker_stat( "alt_stock", map ); + return weapondata; + } + return undefined; +} + +clear_stored_weapondata( map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + self set_map_weaponlocker_stat( "name", "", map ); + self set_map_weaponlocker_stat( "lh_clip", 0, map ); + self set_map_weaponlocker_stat( "clip", 0, map ); + self set_map_weaponlocker_stat( "stock", 0, map ); + self set_map_weaponlocker_stat( "alt_clip", 0, map ); + self set_map_weaponlocker_stat( "alt_stock", 0, map ); +} + +set_stored_weapondata( weapondata, map ) +{ + if ( !isDefined( map ) ) + { + map = level.script; + } + self set_map_weaponlocker_stat( "name", weapondata[ "name" ], map ); + self set_map_weaponlocker_stat( "lh_clip", weapondata[ "lh_clip" ], map ); + self set_map_weaponlocker_stat( "clip", weapondata[ "clip" ], map ); + self set_map_weaponlocker_stat( "stock", weapondata[ "stock" ], map ); + self set_map_weaponlocker_stat( "alt_clip", weapondata[ "alt_clip" ], map ); + self set_map_weaponlocker_stat( "alt_stock", weapondata[ "alt_stock" ], map ); +} + +add_client_stat( stat_name, stat_value, include_gametype ) +{ + if ( getDvar( "ui_zm_mapstartlocation" ) == "" || is_true( level.zm_disable_recording_stats ) ) + { + return; + } + if ( !isDefined( include_gametype ) ) + { + include_gametype = 1; + } + self maps/mp/gametypes_zm/_globallogic_score::incpersstat( stat_name, stat_value, 0, include_gametype ); + self.stats_this_frame[ stat_name ] = 1; +} + +increment_player_stat( stat_name ) +{ + if ( getDvar( "ui_zm_mapstartlocation" ) == "" || is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self incrementplayerstat( stat_name, 1 ); +} + +increment_root_stat( stat_name, stat_value ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( stat_name, stat_value ); +} + +increment_client_stat( stat_name, include_gametype ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + add_client_stat( stat_name, 1, include_gametype ); +} + +set_client_stat( stat_name, stat_value, include_gametype ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + current_stat_count = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( stat_name ); + self maps/mp/gametypes_zm/_globallogic_score::incpersstat( stat_name, stat_value - current_stat_count, 0, include_gametype ); + self.stats_this_frame[ stat_name ] = 1; +} + +zero_client_stat( stat_name, include_gametype ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + current_stat_count = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( stat_name ); + self maps/mp/gametypes_zm/_globallogic_score::incpersstat( stat_name, current_stat_count * -1, 0, include_gametype ); + self.stats_this_frame[ stat_name ] = 1; +} + +increment_map_cheat_stat( stat_name ) +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + self adddstat( "PlayerStatsByMap", level.script, "cheats", stat_name, 1 ); +} + +get_stat_distance_traveled() +{ + miles = int( self.pers[ "distance_traveled" ] / 63360 ); + remainder = ( self.pers[ "distance_traveled" ] / 63360 ) - miles; + if ( miles < 1 && remainder < 0,5 ) + { + miles = 1; + } + else + { + if ( remainder >= 0,5 ) + { + miles++; + } + } + return miles; +} + +get_stat_round_number() +{ + return level.round_number; +} + +get_stat_combined_rank_value_survival_classic() +{ + rounds = get_stat_round_number(); + kills = self.pers[ "kills" ]; + if ( rounds > 99 ) + { + rounds = 99; + } + result = ( rounds * 10000000 ) + kills; + return result; +} + +get_stat_combined_rank_value_grief() +{ + wins = self.pers[ "wins" ]; + losses = self.pers[ "losses" ]; + if ( wins > 9999 ) + { + wins = 9999; + } + if ( losses > 9999 ) + { + losses = 9999; + } + losses_value = 9999 - losses; + result = ( wins * 10000 ) + losses_value; + return result; +} + +update_global_counters_on_match_end() +{ + if ( is_true( level.zm_disable_recording_stats ) ) + { + return; + } + deaths = 0; + kills = 0; + melee_kills = 0; + headshots = 0; + suicides = 0; + downs = 0; + revives = 0; + perks_drank = 0; + gibs = 0; + doors_purchased = 0; + distance_traveled = 0; + total_shots = 0; + boards = 0; + sacrifices = 0; + drops = 0; + nuke_pickedup = 0; + insta_kill_pickedup = 0; + full_ammo_pickedup = 0; + double_points_pickedup = 0; + meat_stink_pickedup = 0; + carpenter_pickedup = 0; + fire_sale_pickedup = 0; + zombie_blood_pickedup = 0; + use_magicbox = 0; + grabbed_from_magicbox = 0; + use_perk_random = 0; + grabbed_from_perk_random = 0; + use_pap = 0; + pap_weapon_grabbed = 0; + specialty_armorvest_drank = 0; + specialty_quickrevive_drank = 0; + specialty_fastreload_drank = 0; + specialty_longersprint_drank = 0; + specialty_scavenger_drank = 0; + specialty_rof_drank = 0; + specialty_deadshot_drank = 0; + specialty_flakjacket_drank = 0; + specialty_additionalprimaryweapon_drank = 0; + specialty_finalstand_drank = 0; + specialty_grenadepulldeath_drank = 0; + specialty_nomotionsensor_drank = 0; + claymores_planted = 0; + claymores_pickedup = 0; + ballistic_knives_pickedup = 0; + wallbuy_weapons_purchased = 0; + power_turnedon = 0; + power_turnedoff = 0; + planted_buildables_pickedup = 0; + ammo_purchased = 0; + upgraded_ammo_purchased = 0; + buildables_built = 0; + time_played = 0; + contaminations_received = 0; + contaminations_given = 0; + cheat_too_many_weapons = 0; + cheat_out_of_playable_area = 0; + cheat_too_friendly = 0; + cheat_total = 0; + prison_tomahawk_acquired = 0; + prison_fan_trap_used = 0; + prison_acid_trap_used = 0; + prison_sniper_tower_used = 0; + prison_ee_good_ending = 0; + prison_ee_bad_ending = 0; + prison_ee_spoon_acquired = 0; + prison_brutus_killed = 0; + buried_lsat_purchased = 0; + buried_fountain_transporter_used = 0; + buried_ghost_killed = 0; + buried_ghost_drained_player = 0; + buried_ghost_perk_acquired = 0; + buried_sloth_booze_given = 0; + buried_sloth_booze_break_barricade = 0; + buried_sloth_candy_given = 0; + buried_sloth_candy_protect = 0; + buried_sloth_candy_build_buildable = 0; + buried_sloth_candy_wallbuy = 0; + buried_sloth_candy_fetch_buildable = 0; + buried_sloth_candy_box_lock = 0; + buried_sloth_candy_box_move = 0; + buried_sloth_candy_box_spin = 0; + buried_sloth_candy_powerup_cycle = 0; + buried_sloth_candy_dance = 0; + buried_sloth_candy_crawler = 0; + buried_wallbuy_placed = 0; + buried_wallbuy_placed_ak74u_zm = 0; + buried_wallbuy_placed_an94_zm = 0; + buried_wallbuy_placed_pdw57_zm = 0; + buried_wallbuy_placed_svu_zm = 0; + buried_wallbuy_placed_tazer_knuckles_zm = 0; + buried_wallbuy_placed_870mcs_zm = 0; + tomb_mechz_killed = 0; + tomb_giant_robot_stomped = 0; + tomb_giant_robot_accessed = 0; + tomb_generator_captured = 0; + tomb_generator_defended = 0; + tomb_generator_lost = 0; + tomb_dig = 0; + tomb_golden_shovel = 0; + tomb_golden_hard_hat = 0; + tomb_perk_extension = 0; + players = get_players(); + _a838 = players; + _k838 = getFirstArrayKey( _a838 ); + while ( isDefined( _k838 ) ) + { + player = _a838[ _k838 ]; + deaths += player.pers[ "deaths" ]; + kills += player.pers[ "kills" ]; + headshots += player.pers[ "headshots" ]; + suicides += player.pers[ "suicides" ]; + melee_kills += player.pers[ "melee_kills" ]; + downs += player.pers[ "downs" ]; + revives += player.pers[ "revives" ]; + perks_drank += player.pers[ "perks_drank" ]; + specialty_armorvest_drank += player.pers[ "specialty_armorvest_drank" ]; + specialty_quickrevive_drank += player.pers[ "specialty_quickrevive_drank" ]; + specialty_fastreload_drank += player.pers[ "specialty_fastreload_drank" ]; + specialty_longersprint_drank += player.pers[ "specialty_longersprint_drank" ]; + specialty_rof_drank += player.pers[ "specialty_rof_drank" ]; + specialty_deadshot_drank += player.pers[ "specialty_deadshot_drank" ]; + specialty_scavenger_drank += player.pers[ "specialty_scavenger_drank" ]; + specialty_flakjacket_drank += player.pers[ "specialty_flakjacket_drank" ]; + specialty_additionalprimaryweapon_drank += player.pers[ "specialty_additionalprimaryweapon_drank" ]; + specialty_finalstand_drank += player.pers[ "specialty_finalstand_drank" ]; + specialty_grenadepulldeath_drank += player.pers[ "specialty_grenadepulldeath_drank" ]; + specialty_nomotionsensor_drank += player.pers[ "specialty_nomotionsensor" + "_drank" ]; + gibs += player.pers[ "gibs" ]; + doors_purchased += player.pers[ "doors_purchased" ]; + distance_traveled += player get_stat_distance_traveled(); + boards += player.pers[ "boards" ]; + sacrifices += player.pers[ "sacrifices" ]; + drops += player.pers[ "drops" ]; + nuke_pickedup += player.pers[ "nuke_pickedup" ]; + insta_kill_pickedup += player.pers[ "insta_kill_pickedup" ]; + full_ammo_pickedup += player.pers[ "full_ammo_pickedup" ]; + double_points_pickedup += player.pers[ "double_points_pickedup" ]; + meat_stink_pickedup += player.pers[ "meat_stink_pickedup" ]; + carpenter_pickedup += player.pers[ "carpenter_pickedup" ]; + fire_sale_pickedup += player.pers[ "fire_sale_pickedup" ]; + zombie_blood_pickedup += player.pers[ "zombie_blood_pickedup" ]; + use_magicbox += player.pers[ "use_magicbox" ]; + grabbed_from_magicbox += player.pers[ "grabbed_from_magicbox" ]; + use_perk_random += player.pers[ "use_perk_random" ]; + grabbed_from_perk_random += player.pers[ "grabbed_from_perk_random" ]; + use_pap += player.pers[ "use_pap" ]; + pap_weapon_grabbed += player.pers[ "pap_weapon_grabbed" ]; + claymores_planted += player.pers[ "claymores_planted" ]; + claymores_pickedup += player.pers[ "claymores_pickedup" ]; + ballistic_knives_pickedup += player.pers[ "ballistic_knives_pickedup" ]; + wallbuy_weapons_purchased += player.pers[ "wallbuy_weapons_purchased" ]; + power_turnedon += player.pers[ "power_turnedon" ]; + power_turnedoff += player.pers[ "power_turnedoff" ]; + planted_buildables_pickedup += player.pers[ "planted_buildables_pickedup" ]; + buildables_built += player.pers[ "buildables_built" ]; + ammo_purchased += player.pers[ "ammo_purchased" ]; + upgraded_ammo_purchased += player.pers[ "upgraded_ammo_purchased" ]; + total_shots += player.total_shots; + time_played += player.pers[ "time_played_total" ]; + contaminations_received += player.pers[ "contaminations_received" ]; + contaminations_given += player.pers[ "contaminations_given" ]; + cheat_too_many_weapons += player.pers[ "cheat_too_many_weapons" ]; + cheat_out_of_playable_area += player.pers[ "cheat_out_of_playable" ]; + cheat_too_friendly += player.pers[ "cheat_too_friendly" ]; + cheat_total += player.pers[ "cheat_total" ]; + prison_tomahawk_acquired += player.pers[ "prison_tomahawk_acquired" ]; + prison_fan_trap_used += player.pers[ "prison_fan_trap_used" ]; + prison_acid_trap_used += player.pers[ "prison_acid_trap_used" ]; + prison_sniper_tower_used += player.pers[ "prison_sniper_tower_used" ]; + prison_ee_good_ending += player.pers[ "prison_ee_good_ending" ]; + prison_ee_bad_ending += player.pers[ "prison_ee_bad_ending" ]; + prison_ee_spoon_acquired += player.pers[ "prison_ee_spoon_acquired" ]; + prison_brutus_killed += player.pers[ "prison_brutus_killed" ]; + buried_lsat_purchased += player.pers[ "buried_lsat_purchased" ]; + buried_fountain_transporter_used += player.pers[ "buried_fountain_transporter_used" ]; + buried_ghost_killed += player.pers[ "buried_ghost_killed" ]; + buried_ghost_drained_player += player.pers[ "buried_ghost_drained_player" ]; + buried_ghost_perk_acquired += player.pers[ "buried_ghost_perk_acquired" ]; + buried_sloth_booze_given += player.pers[ "buried_sloth_booze_given" ]; + buried_sloth_booze_break_barricade += player.pers[ "buried_sloth_booze_break_barricade" ]; + buried_sloth_candy_given += player.pers[ "buried_sloth_candy_given" ]; + buried_sloth_candy_protect += player.pers[ "buried_sloth_candy_protect" ]; + buried_sloth_candy_build_buildable += player.pers[ "buried_sloth_candy_build_buildable" ]; + buried_sloth_candy_wallbuy += player.pers[ "buried_sloth_candy_wallbuy" ]; + buried_sloth_candy_fetch_buildable += player.pers[ "buried_sloth_candy_fetch_buildable" ]; + buried_sloth_candy_box_lock += player.pers[ "buried_sloth_candy_box_lock" ]; + buried_sloth_candy_box_move += player.pers[ "buried_sloth_candy_box_move" ]; + buried_sloth_candy_box_spin += player.pers[ "buried_sloth_candy_box_spin" ]; + buried_sloth_candy_powerup_cycle += player.pers[ "buried_sloth_candy_powerup_cycle" ]; + buried_sloth_candy_dance += player.pers[ "buried_sloth_candy_dance" ]; + buried_sloth_candy_crawler += player.pers[ "buried_sloth_candy_crawler" ]; + buried_wallbuy_placed += player.pers[ "buried_wallbuy_placed" ]; + buried_wallbuy_placed_ak74u_zm += player.pers[ "buried_wallbuy_placed_ak74u_zm" ]; + buried_wallbuy_placed_an94_zm += player.pers[ "buried_wallbuy_placed_an94_zm" ]; + buried_wallbuy_placed_pdw57_zm += player.pers[ "buried_wallbuy_placed_pdw57_zm" ]; + buried_wallbuy_placed_svu_zm += player.pers[ "buried_wallbuy_placed_svu_zm" ]; + buried_wallbuy_placed_tazer_knuckles_zm += player.pers[ "buried_wallbuy_placed_tazer_knuckles_zm" ]; + buried_wallbuy_placed_870mcs_zm += player.pers[ "buried_wallbuy_placed_870mcs_zm" ]; + tomb_mechz_killed += player.pers[ "tomb_mechz_killed" ]; + tomb_giant_robot_stomped += player.pers[ "tomb_giant_robot_stomped" ]; + tomb_giant_robot_accessed += player.pers[ "tomb_giant_robot_accessed" ]; + tomb_generator_captured += player.pers[ "tomb_generator_captured" ]; + tomb_generator_defended += player.pers[ "tomb_generator_defended" ]; + tomb_generator_lost += player.pers[ "tomb_generator_lost" ]; + tomb_dig += player.pers[ "tomb_dig" ]; + tomb_golden_shovel += player.pers[ "tomb_golden_shovel" ]; + tomb_golden_hard_hat += player.pers[ "tomb_golden_hard_hat" ]; + tomb_perk_extension += player.pers[ "tomb_perk_extension" ]; + _k838 = getNextArrayKey( _a838, _k838 ); + } + game_mode = getDvar( "ui_gametype" ); + incrementcounter( "global_zm_" + game_mode, 1 ); + incrementcounter( "global_zm_games", 1 ); + if ( game_mode == "zclassic" || level.script == "zm_nuked" ) + { + incrementcounter( "global_zm_games_" + level.script, 1 ); + } + incrementcounter( "global_zm_killed", level.global_zombies_killed ); + incrementcounter( "global_zm_killed_by_players", kills ); + incrementcounter( "global_zm_killed_by_traps", level.zombie_trap_killed_count ); + incrementcounter( "global_zm_headshots", headshots ); + incrementcounter( "global_zm_suicides", suicides ); + incrementcounter( "global_zm_melee_kills", melee_kills ); + incrementcounter( "global_zm_downs", downs ); + incrementcounter( "global_zm_deaths", deaths ); + incrementcounter( "global_zm_revives", revives ); + incrementcounter( "global_zm_perks_drank", perks_drank ); + incrementcounter( "global_zm_specialty_armorvest_drank", specialty_armorvest_drank ); + incrementcounter( "global_zm_specialty_quickrevive_drank", specialty_quickrevive_drank ); + incrementcounter( "global_zm_specialty_fastreload_drank", specialty_fastreload_drank ); + incrementcounter( "global_zm_specialty_longersprint_drank", specialty_longersprint_drank ); + incrementcounter( "global_zm_specialty_rof_drank", specialty_rof_drank ); + incrementcounter( "global_zm_specialty_deadshot_drank", specialty_deadshot_drank ); + incrementcounter( "global_zm_specialty_scavenger_drank", specialty_scavenger_drank ); + incrementcounter( "global_zm_specialty_flakjacket_drank", specialty_flakjacket_drank ); + incrementcounter( "global_zm_specialty_additionalprimaryweapon_drank", specialty_additionalprimaryweapon_drank ); + incrementcounter( "global_zm_specialty_finalstand_drank", specialty_finalstand_drank ); + incrementcounter( "global_zm_specialty_grenadepulldeath_drank", specialty_grenadepulldeath_drank ); + incrementcounter( "global_zm_" + "specialty_nomotionsensor" + "_drank", specialty_nomotionsensor_drank ); + incrementcounter( "global_zm_gibs", gibs ); + incrementcounter( "global_zm_distance_traveled", int( distance_traveled ) ); + incrementcounter( "global_zm_doors_purchased", doors_purchased ); + incrementcounter( "global_zm_boards", boards ); + incrementcounter( "global_zm_sacrifices", sacrifices ); + incrementcounter( "global_zm_drops", drops ); + incrementcounter( "global_zm_total_nuke_pickedup", nuke_pickedup ); + incrementcounter( "global_zm_total_insta_kill_pickedup", insta_kill_pickedup ); + incrementcounter( "global_zm_total_full_ammo_pickedup", full_ammo_pickedup ); + incrementcounter( "global_zm_total_double_points_pickedup", double_points_pickedup ); + incrementcounter( "global_zm_total_meat_stink_pickedup", double_points_pickedup ); + incrementcounter( "global_zm_total_carpenter_pickedup", carpenter_pickedup ); + incrementcounter( "global_zm_total_fire_sale_pickedup", fire_sale_pickedup ); + incrementcounter( "global_zm_total_zombie_blood_pickedup", zombie_blood_pickedup ); + incrementcounter( "global_zm_use_magicbox", use_magicbox ); + incrementcounter( "global_zm_grabbed_from_magicbox", grabbed_from_magicbox ); + incrementcounter( "global_zm_use_perk_random", use_perk_random ); + incrementcounter( "global_zm_grabbed_from_perk_random", grabbed_from_perk_random ); + incrementcounter( "global_zm_use_pap", use_pap ); + incrementcounter( "global_zm_pap_weapon_grabbed", pap_weapon_grabbed ); + incrementcounter( "global_zm_claymores_planted", claymores_planted ); + incrementcounter( "global_zm_claymores_pickedup", claymores_pickedup ); + incrementcounter( "global_zm_ballistic_knives_pickedup", ballistic_knives_pickedup ); + incrementcounter( "global_zm_wallbuy_weapons_purchased", wallbuy_weapons_purchased ); + incrementcounter( "global_zm_power_turnedon", power_turnedon ); + incrementcounter( "global_zm_power_turnedoff", power_turnedoff ); + incrementcounter( "global_zm_planted_buildables_pickedup", planted_buildables_pickedup ); + incrementcounter( "global_zm_buildables_built", buildables_built ); + incrementcounter( "global_zm_ammo_purchased", ammo_purchased ); + incrementcounter( "global_zm_upgraded_ammo_purchased", upgraded_ammo_purchased ); + incrementcounter( "global_zm_total_shots", total_shots ); + incrementcounter( "global_zm_time_played", time_played ); + incrementcounter( "global_zm_contaminations_received", contaminations_received ); + incrementcounter( "global_zm_contaminations_given", contaminations_given ); + incrementcounter( "global_zm_cheat_players_too_friendly", cheat_too_friendly ); + incrementcounter( "global_zm_cheats_cheat_too_many_weapons", cheat_too_many_weapons ); + incrementcounter( "global_zm_cheats_out_of_playable", cheat_out_of_playable_area ); + incrementcounter( "global_zm_total_cheats", cheat_total ); + incrementcounter( "global_zm_prison_tomahawk_acquired", prison_tomahawk_acquired ); + incrementcounter( "global_zm_prison_fan_trap_used", prison_fan_trap_used ); + incrementcounter( "global_zm_prison_acid_trap_used", prison_acid_trap_used ); + incrementcounter( "global_zm_prison_sniper_tower_used", prison_sniper_tower_used ); + incrementcounter( "global_zm_prison_ee_good_ending", prison_ee_good_ending ); + incrementcounter( "global_zm_prison_ee_bad_ending", prison_ee_bad_ending ); + incrementcounter( "global_zm_prison_ee_spoon_acquired", prison_ee_spoon_acquired ); + incrementcounter( "global_zm_prison_brutus_killed", prison_brutus_killed ); + incrementcounter( "global_zm_buried_lsat_purchased", buried_lsat_purchased ); + incrementcounter( "global_zm_buried_fountain_transporter_used", buried_fountain_transporter_used ); + incrementcounter( "global_zm_buried_ghost_killed", buried_ghost_killed ); + incrementcounter( "global_zm_buried_ghost_drained_player", buried_ghost_drained_player ); + incrementcounter( "global_zm_buried_ghost_perk_acquired", buried_ghost_perk_acquired ); + incrementcounter( "global_zm_buried_sloth_booze_given", buried_sloth_booze_given ); + incrementcounter( "global_zm_buried_sloth_booze_break_barricade", buried_sloth_booze_break_barricade ); + incrementcounter( "global_zm_buried_sloth_candy_given", buried_sloth_candy_given ); + incrementcounter( "global_zm_buried_sloth_candy_protect", buried_sloth_candy_protect ); + incrementcounter( "global_zm_buried_sloth_candy_build_buildable", buried_sloth_candy_build_buildable ); + incrementcounter( "global_zm_buried_sloth_candy_wallbuy", buried_sloth_candy_wallbuy ); + incrementcounter( "global_zm_buried_sloth_candy_fetch_buildable", buried_sloth_candy_fetch_buildable ); + incrementcounter( "global_zm_buried_sloth_candy_box_lock", buried_sloth_candy_box_lock ); + incrementcounter( "global_zm_buried_sloth_candy_box_move", buried_sloth_candy_box_move ); + incrementcounter( "global_zm_buried_sloth_candy_box_spin", buried_sloth_candy_box_spin ); + incrementcounter( "global_zm_buried_sloth_candy_powerup_cycle", buried_sloth_candy_powerup_cycle ); + incrementcounter( "global_zm_buried_sloth_candy_dance", buried_sloth_candy_dance ); + incrementcounter( "global_zm_buried_sloth_candy_crawler", buried_sloth_candy_crawler ); + incrementcounter( "global_zm_buried_wallbuy_placed", buried_wallbuy_placed ); + incrementcounter( "global_zm_buried_wallbuy_placed_ak74u_zm", buried_wallbuy_placed_ak74u_zm ); + incrementcounter( "global_zm_buried_wallbuy_placed_an94_zm", buried_wallbuy_placed_an94_zm ); + incrementcounter( "global_zm_buried_wallbuy_placed_pdw57_zm", buried_wallbuy_placed_pdw57_zm ); + incrementcounter( "global_zm_buried_wallbuy_placed_svu_zm", buried_wallbuy_placed_svu_zm ); + incrementcounter( "global_zm_buried_wallbuy_placed_tazer_knuckles_zm", buried_wallbuy_placed_tazer_knuckles_zm ); + incrementcounter( "global_zm_buried_wallbuy_placed_870mcs_zm", buried_wallbuy_placed_870mcs_zm ); + incrementcounter( "global_zm_tomb_mechz_killed", tomb_mechz_killed ); + incrementcounter( "global_zm_tomb_giant_robot_stomped", tomb_giant_robot_stomped ); + incrementcounter( "global_zm_tomb_giant_robot_accessed", tomb_giant_robot_accessed ); + incrementcounter( "global_zm_tomb_generator_captured", tomb_generator_captured ); + incrementcounter( "global_zm_tomb_generator_defended", tomb_generator_defended ); + incrementcounter( "global_zm_tomb_generator_lost", tomb_generator_lost ); + incrementcounter( "global_zm_tomb_dig", tomb_dig ); + incrementcounter( "global_zm_tomb_golden_shovel", tomb_golden_shovel ); + incrementcounter( "global_zm_tomb_golden_hard_hat", tomb_golden_hard_hat ); + incrementcounter( "global_zm_tomb_perk_extension", tomb_perk_extension ); +} + +get_specific_stat( stat_category, stat_name ) +{ + return self getdstat( stat_category, stat_name, "StatValue" ); +} + +do_stats_for_gibs( zombie, limb_tags_array ) +{ + while ( isDefined( zombie ) && isDefined( zombie.attacker ) && isplayer( zombie.attacker ) ) + { + _a1069 = limb_tags_array; + _k1069 = getFirstArrayKey( _a1069 ); + while ( isDefined( _k1069 ) ) + { + limb = _a1069[ _k1069 ]; + stat_name = undefined; + if ( limb == level._zombie_gib_piece_index_right_arm ) + { + stat_name = "right_arm_gibs"; + } + else if ( limb == level._zombie_gib_piece_index_left_arm ) + { + stat_name = "left_arm_gibs"; + } + else if ( limb == level._zombie_gib_piece_index_right_leg ) + { + stat_name = "right_leg_gibs"; + } + else if ( limb == level._zombie_gib_piece_index_left_leg ) + { + stat_name = "left_leg_gibs"; + } + else + { + if ( limb == level._zombie_gib_piece_index_head ) + { + stat_name = "head_gibs"; + } + } + if ( !isDefined( stat_name ) ) + { + } + else + { + zombie.attacker increment_client_stat( stat_name, 0 ); + zombie.attacker increment_client_stat( "gibs" ); + } + _k1069 = getNextArrayKey( _a1069, _k1069 ); + } + } +} + +initializematchstats() +{ + if ( !level.onlinegame || !gamemodeismode( level.gamemode_public_match ) ) + { + return; + } + self.pers[ "lastHighestScore" ] = self getdstat( "HighestStats", "highest_score" ); + currgametype = level.gametype; + self gamehistorystartmatch( getgametypeenumfromname( currgametype, 0 ) ); +} + +adjustrecentstats() +{ +/# + if ( getDvarInt( "scr_writeConfigStrings" ) == 1 || getDvarInt( "scr_hostmigrationtest" ) == 1 ) + { + return; +#/ + } + initializematchstats(); +} + +uploadstatssoon() +{ + self notify( "upload_stats_soon" ); + self endon( "upload_stats_soon" ); + self endon( "disconnect" ); + wait 1; + uploadstats( self ); +} diff --git a/patch_zm/maps/mp/zombies/_zm_tombstone.gsc b/patch_zm/maps/mp/zombies/_zm_tombstone.gsc index 1833f9b..3ba6007 100644 --- a/patch_zm/maps/mp/zombies/_zm_tombstone.gsc +++ b/patch_zm/maps/mp/zombies/_zm_tombstone.gsc @@ -7,7 +7,7 @@ #include common_scripts/utility; #include maps/mp/_utility; -init() +init() //checked matches cerberus output { onplayerconnect_callback( ::tombstone_player_init ); level.tombstone_laststand_func = ::tombstone_laststand; @@ -19,7 +19,7 @@ init() } } -tombstone_player_init() +tombstone_player_init() //checked matches cerberus output { while ( !isDefined( self.tombstone_index ) ) { @@ -28,7 +28,7 @@ tombstone_player_init() level.tombstones[ self.tombstone_index ] = spawnstruct(); } -tombstone_spawn() +tombstone_spawn() //checked matches cerberus output { dc = spawn( "script_model", self.origin + vectorScale( ( 0, 0, 1 ), 40 ) ); dc.angles = self.angles; @@ -56,13 +56,13 @@ tombstone_spawn() dc thread tombstone_grab(); } -tombstone_clear() +tombstone_clear() //checked matches cerberus output { result = self waittill_any_return( "tombstone_timedout", "tombstone_grabbed" ); level.tombstones[ self.tombstone_index ] = spawnstruct(); } -tombstone_revived( player ) +tombstone_revived( player ) //checked changed to match cerberus output { self endon( "tombstone_timedout" ); player endon( "disconnect" ); @@ -77,19 +77,16 @@ tombstone_revived( player ) self.icon hide(); } } - else + else if ( !shown ) { - if ( !shown ) - { - shown = 1; - self.icon show(); - } + shown = 1; + self.icon show(); } wait 0.05; } } -tombstone_laststand() +tombstone_laststand() //checked changed to match cerberus output { primaries = self getweaponslistprimaries(); currentweapon = self getcurrentweapon(); @@ -97,18 +94,14 @@ tombstone_laststand() dc.player = self; dc.weapon = []; dc.current_weapon = -1; - _a134 = primaries; - index = getFirstArrayKey( _a134 ); - while ( isDefined( index ) ) + foreach ( weapon in primaries ) { - weapon = _a134[ index ]; dc.weapon[ index ] = weapon; dc.stockcount[ index ] = self getweaponammostock( weapon ); if ( weapon == currentweapon ) { dc.current_weapon = index; } - index = getNextArrayKey( _a134, index ); } if ( isDefined( self.hasriotshield ) && self.hasriotshield ) { @@ -141,7 +134,7 @@ tombstone_laststand() } } -tombstone_save_perks( ent ) +tombstone_save_perks( ent ) //checked matches cerberus output { perk_array = []; if ( ent hasperk( "specialty_armorvest" ) ) @@ -175,7 +168,7 @@ tombstone_save_perks( ent ) return perk_array; } -tombstone_grab() +tombstone_grab() //checked partially changed to match cerberus output { self endon( "tombstone_timedout" ); wait 1; @@ -190,41 +183,34 @@ tombstone_grab() i++; continue; } - else + if ( isDefined( self.player ) && players[ i ] == self.player ) { - if ( isDefined( self.player ) && players[ i ] == self.player ) + tombstone_machine_triggers = getentarray( "specialty_scavenger", "script_noteworthy" ); + istombstonepowered = 0; + foreach ( trigger in tombstone_machine_triggers ) { - tombstone_machine_triggers = getentarray( "specialty_scavenger", "script_noteworthy" ); - istombstonepowered = 0; - _a258 = tombstone_machine_triggers; - _k258 = getFirstArrayKey( _a258 ); - while ( isDefined( _k258 ) ) + if ( isdefined( trigger.power_on ) && trigger.power_on || isdefined( trigger.turbine_power_on ) && trigger.turbine_power_on ) { - trigger = _a258[ _k258 ]; - if ( isDefined( trigger.power_on ) || trigger.power_on && isDefined( trigger.turbine_power_on ) && trigger.turbine_power_on ) - { - istombstonepowered = 1; - } - _k258 = getNextArrayKey( _a258, _k258 ); + istombstonepowered = 1; } - if ( istombstonepowered ) + } + if ( istombstonepowered ) + { + dist = distance( players[ i ].origin, self.origin ); + if ( dist < 64 ) { - dist = distance( players[ i ].origin, self.origin ); - if ( dist < 64 ) - { - playfx( level._effect[ "powerup_grabbed" ], self.origin ); - playfx( level._effect[ "powerup_grabbed_wave" ], self.origin ); - players[ i ] tombstone_give(); - wait 0.1; - playsoundatposition( "zmb_tombstone_grab", self.origin ); - self stoploopsound(); - self.icon unlink(); - self.icon delete(); - self delete(); - self notify( "tombstone_grabbed" ); - players[ i ] clientnotify( "dc0" ); - players[ i ] notify( "dance_on_my_grave" ); - } + playfx( level._effect[ "powerup_grabbed" ], self.origin ); + playfx( level._effect[ "powerup_grabbed_wave" ], self.origin ); + players[ i ] tombstone_give(); + wait 0.1; + playsoundatposition( "zmb_tombstone_grab", self.origin ); + self stoploopsound(); + self.icon unlink(); + self.icon delete(); + self delete(); + self notify( "tombstone_grabbed" ); + players[ i ] clientnotify( "dc0" ); + players[ i ] notify( "dance_on_my_grave" ); } } } @@ -234,21 +220,17 @@ tombstone_grab() } } -tombstone_give() +tombstone_give() //checked partially changed to match cerberus output { dc = level.tombstones[ self.tombstone_index ]; - while ( !flag( "solo_game" ) ) + if ( !flag( "solo_game" ) ) { primaries = self getweaponslistprimaries(); - while ( dc.weapon.size > 1 || primaries.size > 1 ) + if ( dc.weapon.size > 1 || primaries.size > 1 ) { - _a310 = primaries; - _k310 = getFirstArrayKey( _a310 ); - while ( isDefined( _k310 ) ) + foreach ( weapon in primaries ) { - weapon = _a310[ _k310 ]; self takeweapon( weapon ); - _k310 = getNextArrayKey( _a310, _k310 ); } } i = 0; @@ -259,24 +241,21 @@ tombstone_give() i++; continue; } - else if ( dc.weapon[ i ] == "none" ) + if ( dc.weapon[ i ] == "none" ) { i++; continue; } - else + weapon = dc.weapon[ i ]; + stock = dc.stockcount[ i ]; + if ( !self hasweapon( weapon ) ) { - weapon = dc.weapon[ i ]; - stock = dc.stockcount[ i ]; - if ( !self hasweapon( weapon ) ) + self giveweapon( weapon, 0, self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); + self setweaponammoclip( weapon, weaponclipsize( weapon ) ); + self setweaponammostock( weapon, stock ); + if ( i == dc.current_weapon ) { - self giveweapon( weapon, 0, self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); - self setweaponammoclip( weapon, weaponclipsize( weapon ) ); - self setweaponammostock( weapon, stock ); - if ( i == dc.current_weapon ) - { - self switchtoweapon( weapon ); - } + self switchtoweapon( weapon ); } } i++; @@ -303,7 +282,7 @@ tombstone_give() self giveweapon( "emp_grenade_zm" ); self setweaponammoclip( "emp_grenade_zm", dc.empclip ); } - while ( isDefined( dc.perk ) && dc.perk.size > 0 ) + if ( isDefined( dc.perk ) && dc.perk.size > 0 ) { i = 0; while ( i < dc.perk.size ) @@ -313,19 +292,16 @@ tombstone_give() i++; continue; } - else if ( dc.perk[ i ] == "specialty_quickrevive" && flag( "solo_game" ) ) + if ( dc.perk[ i ] == "specialty_quickrevive" && flag( "solo_game" ) ) { i++; continue; } - else - { - maps/mp/zombies/_zm_perks::give_perk( dc.perk[ i ] ); - } + maps/mp/zombies/_zm_perks::give_perk( dc.perk[ i ] ); i++; } } - if ( dc.grenade > 0 && !flag( "solo_game" ) ) + else if ( dc.grenade > 0 && !flag( "solo_game" ) ) { curgrenadecount = 0; if ( self hasweapon( self get_player_lethal_grenade() ) ) @@ -348,7 +324,7 @@ tombstone_give() } } -tombstone_wobble() +tombstone_wobble() //checked matches cerberus output { self endon( "tombstone_grabbed" ); self endon( "tombstone_timedout" ); @@ -366,7 +342,7 @@ tombstone_wobble() } } -tombstone_timeout() +tombstone_timeout() //checked partially changed to match cerberus output { self endon( "tombstone_grabbed" ); self thread playtombstonetimeraudio(); @@ -388,16 +364,13 @@ tombstone_timeout() i++; continue; } - else if ( i < 25 ) + if ( i < 25 ) { wait 0.25; i++; continue; } - else - { - wait 0.1; - } + wait 0.1; i++; } self notify( "tombstone_timedout" ); @@ -406,7 +379,7 @@ tombstone_timeout() self delete(); } -playtombstonetimeraudio() +playtombstonetimeraudio() //checked matches cerberus output { self endon( "tombstone_grabbed" ); self endon( "tombstone_timedout" ); @@ -419,25 +392,24 @@ playtombstonetimeraudio() } } -playtombstonetimerout( player ) +playtombstonetimerout( player ) //checked matches cerberus output { self endon( "tombstone_grabbed" ); self waittill( "tombstone_timedout" ); player playsoundtoplayer( "zmb_tombstone_timer_out", player ); } -save_weapons_for_tombstone( player ) +save_weapons_for_tombstone( player ) //checked changed to match cerberus output { self.tombstone_melee_weapons = []; - i = 0; - while ( i < level._melee_weapons.size ) + + for ( i = 0; i < level._melee_weapons.size; i++; ) { self save_weapon_for_tombstone( player, level._melee_weapons[ i ].weapon_name ); - i++; } } -save_weapon_for_tombstone( player, weapon_name ) +save_weapon_for_tombstone( player, weapon_name ) //checked matches cerberus output { if ( player hasweapon( weapon_name ) ) { @@ -447,18 +419,16 @@ save_weapon_for_tombstone( player, weapon_name ) restore_weapons_for_tombstone( player ) { - i = 0; - while ( i < level._melee_weapons.size ) + for ( i = 0; i < level._melee_weapons.size; i++ ) { self restore_weapon_for_tombstone( player, level._melee_weapons[ i ].weapon_name ); - i++; } self.tombstone_melee_weapons = undefined; } -restore_weapon_for_tombstone( player, weapon_name ) +restore_weapon_for_tombstone( player, weapon_name ) //checked changed to match cerberus output { - if ( isDefined( weapon_name ) || !isDefined( self.tombstone_melee_weapons ) && !isDefined( self.tombstone_melee_weapons[ weapon_name ] ) ) + if ( !isDefined( weapon_name ) || !isDefined( self.tombstone_melee_weapons ) || !isDefined( self.tombstone_melee_weapons[ weapon_name ] ) ) { return; } @@ -470,7 +440,7 @@ restore_weapon_for_tombstone( player, weapon_name ) } } -tombstone_hostmigration() +tombstone_hostmigration() //checked changed to match cerberus output { level endon( "end_game" ); level notify( "tombstone_hostmigration" ); @@ -479,18 +449,14 @@ tombstone_hostmigration() { level waittill( "host_migration_end" ); tombstones = getentarray( "player_tombstone_model", "script_noteworthy" ); - _a580 = tombstones; - _k580 = getFirstArrayKey( _a580 ); - while ( isDefined( _k580 ) ) + foreach ( model in tombstones ) { - model = _a580[ _k580 ]; playfxontag( level._effect[ "powerup_on" ], model, "tag_origin" ); - _k580 = getNextArrayKey( _a580, _k580 ); } } } -is_weapon_available_in_tombstone( weapon, player_to_check ) +is_weapon_available_in_tombstone( weapon, player_to_check ) //checked partially changed to match cerberus output { count = 0; upgradedweapon = weapon; @@ -507,34 +473,30 @@ is_weapon_available_in_tombstone( weapon, player_to_check ) tombstone_index++; continue; } - else if ( isDefined( player_to_check ) && dc.player != player_to_check ) + if ( isDefined( player_to_check ) && dc.player != player_to_check ) { tombstone_index++; continue; } - else + weapon_index = 0; + while ( weapon_index < dc.weapon.size ) { - weapon_index = 0; - while ( weapon_index < dc.weapon.size ) + if ( !isDefined( dc.weapon[ weapon_index ] ) ) { - if ( !isDefined( dc.weapon[ weapon_index ] ) ) - { - weapon_index++; - continue; - } - else - { - tombstone_weapon = dc.weapon[ weapon_index ]; - if ( tombstone_weapon == weapon || tombstone_weapon == upgradedweapon ) - { - count++; - } - } weapon_index++; + continue; } + tombstone_weapon = dc.weapon[ weapon_index ]; + if ( tombstone_weapon == weapon || tombstone_weapon == upgradedweapon ) + { + count++; + } + weapon_index++; } tombstone_index++; } return count; } + + diff --git a/patch_zm/maps/mp/zombies/_zm_traps.gsc b/patch_zm/maps/mp/zombies/_zm_traps.gsc new file mode 100644 index 0000000..43ca83d --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_traps.gsc @@ -0,0 +1,948 @@ +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + level.trap_kills = 0; + traps = getentarray( "zombie_trap", "targetname" ); + array_thread( traps, ::trap_init ); + level thread register_visionsets( traps ); + level.burning_zombies = []; + level.elec_trap_time = 40; + level.elec_trap_cooldown_time = 60; +} + +trap_init() +{ + self ent_flag_init( "flag_active" ); + self ent_flag_init( "flag_cooldown" ); + self._trap_type = ""; + if ( isDefined( self.script_noteworthy ) ) + { + self._trap_type = self.script_noteworthy; + if ( isDefined( level._zombiemode_trap_activate_funcs ) && isDefined( level._zombiemode_trap_activate_funcs[ self._trap_type ] ) ) + { + self._trap_activate_func = level._zombiemode_trap_activate_funcs[ self._trap_type ]; + break; + } + else + { + switch( self.script_noteworthy ) + { + case "rotating": + self._trap_activate_func = ::trap_activate_rotating; + break; + case "electric": + self._trap_activate_func = ::trap_activate_electric; + break; + case "flipper": + self._trap_activate_func = ::trap_activate_flipper; + break; + case "fire": + default: + self._trap_activate_func = ::trap_activate_fire; + } + } + if ( isDefined( level._zombiemode_trap_use_funcs ) && isDefined( level._zombiemode_trap_use_funcs[ self._trap_type ] ) ) + { + self._trap_use_func = level._zombiemode_trap_use_funcs[ self._trap_type ]; + } + else + { + self._trap_use_func = ::trap_use_think; + } +} +self trap_model_type_init(); +self._trap_use_trigs = []; +self._trap_lights = []; +self._trap_movers = []; +self._trap_switches = []; +components = getentarray( self.target, "targetname" ); +i = 0; +while ( i < components.size ) +{ + if ( isDefined( components[ i ].script_noteworthy ) ) + { + switch( components[ i ].script_noteworthy ) + { + case "counter_1s": + self.counter_1s = components[ i ]; + break; + i++; + continue; + case "counter_10s": + self.counter_10s = components[ i ]; + break; + i++; + continue; + case "counter_100s": + self.counter_100s = components[ i ]; + break; + i++; + continue; + case "mover": + self._trap_movers[ self._trap_movers.size ] = components[ i ]; + break; + i++; + continue; + case "switch": + self._trap_switches[ self._trap_switches.size ] = components[ i ]; + break; + i++; + continue; + case "light": + self._trap_lightes[ self._trap_lightes.size ] = components[ i ]; + break; + i++; + continue; + } + } + if ( isDefined( components[ i ].script_string ) ) + { + switch( components[ i ].script_string ) + { + case "flipper1": + self.flipper1 = components[ i ]; + break; + i++; + continue; + case "flipper2": + self.flipper2 = components[ i ]; + break; + i++; + continue; + case "flipper1_radius_check": + self.flipper1_radius_check = components[ i ]; + break; + i++; + continue; + case "flipper2_radius_check": + self.flipper2_radius_check = components[ i ]; + break; + i++; + continue; + case "target1": + self.target1 = components[ i ]; + break; + i++; + continue; + case "target2": + self.target2 = components[ i ]; + break; + i++; + continue; + case "target3": + self.target3 = components[ i ]; + break; + i++; + continue; + } + } + switch( components[ i ].classname ) + { + case "trigger_use": + self._trap_use_trigs[ self._trap_use_trigs.size ] = components[ i ]; + break; + i++; + continue; + case "script_model": + if ( components[ i ].model == self._trap_light_model_off ) + { + self._trap_lights[ self._trap_lights.size ] = components[ i ]; + } + else if ( components[ i ].model == self._trap_switch_model ) + { + self._trap_switches[ self._trap_switches.size ] = components[ i ]; + } + } + i++; +} +self._trap_fx_structs = []; +components = getstructarray( self.target, "targetname" ); +i = 0; +while ( i < components.size ) +{ + if ( isDefined( components[ i ].script_string ) && components[ i ].script_string == "use_this_angle" ) + { + self.use_this_angle = components[ i ]; + i++; + continue; + } + else + { + self._trap_fx_structs[ self._trap_fx_structs.size ] = components[ i ]; + } + i++; +} +/# +assert( self._trap_use_trigs.size > 0, "_zm_traps::init no use triggers found for " + self.target ); +#/ +if ( !isDefined( self.zombie_cost ) ) +{ + self.zombie_cost = 1000; +} +self._trap_in_use = 0; +self._trap_cooling_down = 0; +self thread trap_dialog(); +flag_wait( "start_zombie_round_logic" ); +self trap_lights_red(); +i = 0; +while ( i < self._trap_use_trigs.size ) +{ + self._trap_use_trigs[ i ] setcursorhint( "HINT_NOICON" ); + i++; +} +if ( !isDefined( self.script_flag_wait ) ) +{ + self trap_set_string( &"ZOMBIE_NEED_POWER" ); + flag_wait( "power_on" ); +} +else +{ + if ( !isDefined( level.flag[ self.script_flag_wait ] ) ) + { + flag_init( self.script_flag_wait ); + } + flag_wait( self.script_flag_wait ); +} +self trap_set_string( &"ZOMBIE_BUTTON_BUY_TRAP", self.zombie_cost ); +self trap_lights_green(); +i = 0; +while ( i < self._trap_use_trigs.size ) +{ + self._trap_use_trigs[ i ] thread [[ self._trap_use_func ]]( self ); + i++; +} +} + +trap_use_think( trap ) +{ + for ( ;; ) + { + while ( 1 ) + { + self waittill( "trigger", who ); + while ( who in_revive_trigger() ) + { + continue; + } + if ( is_player_valid( who ) && !trap._trap_in_use ) + { + if ( who.score >= trap.zombie_cost ) + { + who maps/mp/zombies/_zm_score::minus_to_player_score( trap.zombie_cost ); + break; + } + else + { + } + } + trap._trap_in_use = 1; + trap trap_set_string( &"ZOMBIE_TRAP_ACTIVE" ); + play_sound_at_pos( "purchase", who.origin ); + if ( trap._trap_switches.size ) + { + trap thread trap_move_switches(); + trap waittill( "switch_activated" ); + } + trap trigger_on(); + trap thread [[ trap._trap_activate_func ]](); + trap waittill( "trap_done" ); + trap trigger_off(); + trap._trap_cooling_down = 1; + trap trap_set_string( &"ZOMBIE_TRAP_COOLDOWN" ); +/# + if ( getDvarInt( "zombie_cheat" ) >= 1 ) + { + trap._trap_cooldown_time = 5; +#/ + } + wait trap._trap_cooldown_time; + trap._trap_cooling_down = 0; + trap notify( "available" ); + trap._trap_in_use = 0; + trap trap_set_string( &"ZOMBIE_BUTTON_BUY_TRAP", trap.zombie_cost ); + } + } +} + +trap_lights_red() +{ + i = 0; + while ( i < self._trap_lights.size ) + { + light = self._trap_lights[ i ]; + light setmodel( self._trap_light_model_red ); + if ( isDefined( light.fx ) ) + { + light.fx delete(); + } + light.fx = maps/mp/zombies/_zm_net::network_safe_spawn( "trap_lights_red", 2, "script_model", light.origin ); + light.fx setmodel( "tag_origin" ); + light.fx.angles = light.angles; + playfxontag( level._effect[ "zapper_light_notready" ], light.fx, "tag_origin" ); + i++; + } +} + +trap_lights_green() +{ + i = 0; + while ( i < self._trap_lights.size ) + { + light = self._trap_lights[ i ]; + if ( isDefined( light._switch_disabled ) ) + { + i++; + continue; + } + else + { + light setmodel( self._trap_light_model_green ); + if ( isDefined( light.fx ) ) + { + light.fx delete(); + } + light.fx = maps/mp/zombies/_zm_net::network_safe_spawn( "trap_lights_green", 2, "script_model", light.origin ); + light.fx setmodel( "tag_origin" ); + light.fx.angles = light.angles; + playfxontag( level._effect[ "zapper_light_ready" ], light.fx, "tag_origin" ); + } + i++; + } +} + +trap_set_string( string, param1, param2 ) +{ + i = 0; + while ( i < self._trap_use_trigs.size ) + { + if ( !isDefined( param1 ) ) + { + self._trap_use_trigs[ i ] sethintstring( string ); + i++; + continue; + } + else if ( !isDefined( param2 ) ) + { + self._trap_use_trigs[ i ] sethintstring( string, param1 ); + i++; + continue; + } + else + { + self._trap_use_trigs[ i ] sethintstring( string, param1, param2 ); + } + i++; + } +} + +trap_move_switches() +{ + self trap_lights_red(); + i = 0; + while ( i < self._trap_switches.size ) + { + self._trap_switches[ i ] rotatepitch( 180, 0,5 ); + self._trap_switches[ i ] playsound( "amb_sparks_l_b" ); + i++; + } + self._trap_switches[ 0 ] waittill( "rotatedone" ); + self notify( "switch_activated" ); + self waittill( "available" ); + i = 0; + while ( i < self._trap_switches.size ) + { + self._trap_switches[ i ] rotatepitch( -180, 0,5 ); + i++; + } + self._trap_switches[ 0 ] waittill( "rotatedone" ); + self trap_lights_green(); +} + +trap_activate_electric() +{ + self._trap_duration = 40; + self._trap_cooldown_time = 60; + self notify( "trap_activate" ); + if ( isDefined( self.script_string ) ) + { + number = int( self.script_string ); + if ( number != 0 ) + { + exploder( number ); + } + else + { + clientnotify( self.script_string + "1" ); + } + } + fx_points = getstructarray( self.target, "targetname" ); + i = 0; + while ( i < fx_points.size ) + { + wait_network_frame(); + fx_points[ i ] thread trap_audio_fx( self ); + i++; + } + self thread trap_damage(); + wait self._trap_duration; + self notify( "trap_done" ); + if ( isDefined( self.script_string ) ) + { + clientnotify( self.script_string + "0" ); + } +} + +trap_activate_fire() +{ + self._trap_duration = 40; + self._trap_cooldown_time = 60; + clientnotify( self.script_string + "1" ); + clientnotify( self.script_parameters ); + fx_points = getstructarray( self.target, "targetname" ); + i = 0; + while ( i < fx_points.size ) + { + wait_network_frame(); + fx_points[ i ] thread trap_audio_fx( self ); + i++; + } + self thread trap_damage(); + wait self._trap_duration; + self notify( "trap_done" ); + clientnotify( self.script_string + "0" ); + clientnotify( self.script_parameters ); +} + +trap_activate_rotating() +{ + self endon( "trap_done" ); + self._trap_duration = 30; + self._trap_cooldown_time = 60; + self thread trap_damage(); + self thread trig_update( self._trap_movers[ 0 ] ); + old_angles = self._trap_movers[ 0 ].angles; + i = 0; + while ( i < self._trap_movers.size ) + { + self._trap_movers[ i ] rotateyaw( 360, 5, 4,5 ); + i++; + } + wait 5; + step = 1,5; + t = 0; + while ( t < self._trap_duration ) + { + i = 0; + while ( i < self._trap_movers.size ) + { + self._trap_movers[ i ] rotateyaw( 360, step ); + i++; + } + wait step; + t += step; + } + i = 0; + while ( i < self._trap_movers.size ) + { + self._trap_movers[ i ] rotateyaw( 360, 5, 0, 4,5 ); + i++; + } + wait 5; + i = 0; + while ( i < self._trap_movers.size ) + { + self._trap_movers[ i ].angles = old_angles; + i++; + } + self notify( "trap_done" ); +} + +trap_activate_flipper() +{ +} + +trap_audio_fx( trap ) +{ + sound_origin = undefined; + if ( trap.script_noteworthy == "electric" ) + { + sound_origin = spawn( "script_origin", self.origin ); + sound_origin playsound( "zmb_elec_start" ); + sound_origin playloopsound( "zmb_elec_loop" ); + self thread play_electrical_sound( trap ); + } + else + { + if ( trap.script_noteworthy == "fire" ) + { + sound_origin = spawn( "script_origin", self.origin ); + sound_origin playsound( "zmb_firetrap_start" ); + sound_origin playloopsound( "zmb_firetrap_loop" ); + } + } + trap waittill_any_or_timeout( trap._trap_duration, "trap_done" ); + if ( isDefined( sound_origin ) ) + { + if ( trap.script_noteworthy == "fire" ) + { + playsoundatposition( "zmb_firetrap_end", sound_origin.origin ); + } + sound_origin stoploopsound(); + wait 0,05; + sound_origin delete(); + } +} + +play_electrical_sound( trap ) +{ + trap endon( "trap_done" ); + while ( 1 ) + { + wait randomfloatrange( 0,1, 0,5 ); + playsoundatposition( "zmb_elec_arc", self.origin ); + } +} + +trap_damage() +{ + self endon( "trap_done" ); + while ( 1 ) + { + self waittill( "trigger", ent ); + if ( isplayer( ent ) ) + { + switch( self._trap_type ) + { + case "electric": + ent thread player_elec_damage(); + break; + case "fire": + case "rocket": + ent thread player_fire_damage(); + break; + case "rotating": + if ( ent getstance() == "stand" ) + { + ent dodamage( 50, ent.origin + vectorScale( ( 0, 0, 1 ), 20 ) ); + ent setstance( "crouch" ); + } + break; + } + break; + continue; + } + else if ( !isDefined( ent.marked_for_death ) ) + { + switch( self._trap_type ) + { + case "rocket": + ent thread zombie_trap_death( self, 100 ); + break; + break; + case "rotating": + ent thread zombie_trap_death( self, 200 ); + break; + break; + case "electric": + case "fire": + default: + ent thread zombie_trap_death( self, randomint( 100 ) ); + break; + break; + } + } +} +} + +trig_update( parent ) +{ + self endon( "trap_done" ); + start_angles = self.angles; + while ( 1 ) + { + self.angles = parent.angles; + wait 0,05; + } +} + +player_elec_damage() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( !isDefined( level.elec_loop ) ) + { + level.elec_loop = 0; + } + if ( !isDefined( self.is_burning ) && is_player_valid( self ) ) + { + self.is_burning = 1; + if ( is_true( level.trap_electric_visionset_registered ) ) + { + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_trap_electric", self, 1,25, 1,25 ); + } + else + { + self setelectrified( 1,25 ); + } + shocktime = 2,5; + self shellshock( "electrocution", shocktime ); + if ( level.elec_loop == 0 ) + { + elec_loop = 1; + self playsound( "zmb_zombie_arc" ); + } + if ( !self hasperk( "specialty_armorvest" ) || ( self.health - 100 ) < 1 ) + { + radiusdamage( self.origin, 10, self.health + 100, self.health + 100 ); + self.is_burning = undefined; + return; + } + else + { + self dodamage( 50, self.origin ); + wait 0,1; + self.is_burning = undefined; + } + } +} + +player_fire_damage() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( !isDefined( self.is_burning ) && !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + self.is_burning = 1; + if ( is_true( level.trap_fire_visionset_registered ) ) + { + maps/mp/_visionset_mgr::vsmgr_activate( "overlay", "zm_trap_burn", self, 1,25, 1,25 ); + } + else + { + self setburn( 1,25 ); + } + self notify( "burned" ); + if ( !self hasperk( "specialty_armorvest" ) || ( self.health - 100 ) < 1 ) + { + radiusdamage( self.origin, 10, self.health + 100, self.health + 100 ); + self.is_burning = undefined; + return; + } + else + { + self dodamage( 50, self.origin ); + wait 0,1; + self.is_burning = undefined; + } + } +} + +zombie_trap_death( trap, param ) +{ + self endon( "death" ); + self.marked_for_death = 1; + switch( trap._trap_type ) + { + case "electric": + case "fire": + case "rocket": + if ( isDefined( self.animname ) && self.animname != "zombie_dog" ) + { + if ( param > 90 && level.burning_zombies.size < 6 ) + { + level.burning_zombies[ level.burning_zombies.size ] = self; + self thread zombie_flame_watch(); + self playsound( "ignite" ); + self thread maps/mp/animscripts/zm_death::flame_death_fx(); + playfxontag( level._effect[ "character_fire_death_torso" ], self, "J_SpineLower" ); + wait randomfloat( 1,25 ); + } + else + { + refs[ 0 ] = "guts"; + refs[ 1 ] = "right_arm"; + refs[ 2 ] = "left_arm"; + refs[ 3 ] = "right_leg"; + refs[ 4 ] = "left_leg"; + refs[ 5 ] = "no_legs"; + refs[ 6 ] = "head"; + self.a.gib_ref = refs[ randomint( refs.size ) ]; + playsoundatposition( "zmb_zombie_arc", self.origin ); + if ( trap._trap_type == "electric" ) + { + if ( randomint( 100 ) > 50 ) + { + self thread electroctute_death_fx(); + self thread play_elec_vocals(); + } + } + wait randomfloat( 1,25 ); + self playsound( "zmb_zombie_arc" ); + } + } + if ( isDefined( self.fire_damage_func ) ) + { + self [[ self.fire_damage_func ]]( trap ); + } + else + { + level notify( "trap_kill" ); + self dodamage( self.health + 666, self.origin, trap ); + } + break; + case "centrifuge": + case "rotating": + ang = vectorToAngle( trap.origin - self.origin ); + direction_vec = vectorScale( anglesToRight( ang ), param ); + if ( isDefined( self.trap_reaction_func ) ) + { + self [[ self.trap_reaction_func ]]( trap ); + } + level notify( "trap_kill" ); + self startragdoll(); + self launchragdoll( direction_vec ); + wait_network_frame(); + self.a.gib_ref = "head"; + self dodamage( self.health, self.origin, trap ); + break; + } +} + +zombie_flame_watch() +{ + self waittill( "death" ); + self stoploopsound(); + arrayremovevalue( level.burning_zombies, self ); +} + +play_elec_vocals() +{ + if ( isDefined( self ) ) + { + org = self.origin; + wait 0,15; + playsoundatposition( "zmb_elec_vocals", org ); + playsoundatposition( "zmb_zombie_arc", org ); + playsoundatposition( "zmb_exp_jib_zombie", org ); + } +} + +electroctute_death_fx() +{ + self endon( "death" ); + if ( isDefined( self.is_electrocuted ) && self.is_electrocuted ) + { + return; + } + self.is_electrocuted = 1; + self thread electrocute_timeout(); + if ( self.team == level.zombie_team ) + { + level.bconfiretime = getTime(); + level.bconfireorg = self.origin; + } + if ( isDefined( level._effect[ "elec_torso" ] ) ) + { + playfxontag( level._effect[ "elec_torso" ], self, "J_SpineLower" ); + } + self playsound( "zmb_elec_jib_zombie" ); + wait 1; + tagarray = []; + tagarray[ 0 ] = "J_Elbow_LE"; + tagarray[ 1 ] = "J_Elbow_RI"; + tagarray[ 2 ] = "J_Knee_RI"; + tagarray[ 3 ] = "J_Knee_LE"; + tagarray = array_randomize( tagarray ); + if ( isDefined( level._effect[ "elec_md" ] ) ) + { + playfxontag( level._effect[ "elec_md" ], self, tagarray[ 0 ] ); + } + self playsound( "zmb_elec_jib_zombie" ); + wait 1; + self playsound( "zmb_elec_jib_zombie" ); + tagarray[ 0 ] = "J_Wrist_RI"; + tagarray[ 1 ] = "J_Wrist_LE"; + if ( !isDefined( self.a.gib_ref ) || self.a.gib_ref != "no_legs" ) + { + tagarray[ 2 ] = "J_Ankle_RI"; + tagarray[ 3 ] = "J_Ankle_LE"; + } + tagarray = array_randomize( tagarray ); + if ( isDefined( level._effect[ "elec_sm" ] ) ) + { + playfxontag( level._effect[ "elec_sm" ], self, tagarray[ 0 ] ); + playfxontag( level._effect[ "elec_sm" ], self, tagarray[ 1 ] ); + } +} + +electrocute_timeout() +{ + self endon( "death" ); + self playloopsound( "fire_manager_0" ); + wait 12; + self stoploopsound(); + if ( isDefined( self ) && isalive( self ) ) + { + self.is_electrocuted = 0; + self notify( "stop_flame_damage" ); + } +} + +trap_dialog() +{ + self endon( "warning_dialog" ); + level endon( "switch_flipped" ); + timer = 0; + while ( 1 ) + { + wait 0,5; + players = get_players(); + i = 0; + while ( i < players.size ) + { + dist = distancesquared( players[ i ].origin, self.origin ); + if ( dist > 4900 ) + { + timer = 0; + i++; + continue; + } + else + { + if ( dist < 4900 && timer < 3 ) + { + wait 0,5; + timer++; + } + if ( dist < 4900 && timer == 3 ) + { + index = maps/mp/zombies/_zm_weapons::get_player_index( players[ i ] ); + plr = "plr_" + index + "_"; + wait 3; + self notify( "warning_dialog" ); + } + } + i++; + } + } +} + +get_trap_array( trap_type ) +{ + ents = getentarray( "zombie_trap", "targetname" ); + traps = []; + i = 0; + while ( i < ents.size ) + { + if ( ents[ i ].script_noteworthy == trap_type ) + { + traps[ traps.size ] = ents[ i ]; + } + i++; + } + return traps; +} + +trap_disable() +{ + cooldown = self._trap_cooldown_time; + if ( self._trap_in_use ) + { + self notify( "trap_done" ); + self._trap_cooldown_time = 0,05; + self waittill( "available" ); + } + array_thread( self._trap_use_trigs, ::trigger_off ); + self trap_lights_red(); + self._trap_cooldown_time = cooldown; +} + +trap_enable() +{ + array_thread( self._trap_use_trigs, ::trigger_on ); + self trap_lights_green(); +} + +trap_model_type_init() +{ + if ( !isDefined( self.script_parameters ) ) + { + self.script_parameters = "default"; + } + switch( self.script_parameters ) + { + case "pentagon_electric": + self._trap_light_model_off = "zombie_trap_switch_light"; + self._trap_light_model_green = "zombie_trap_switch_light_on_green"; + self._trap_light_model_red = "zombie_trap_switch_light_on_red"; + self._trap_switch_model = "zombie_trap_switch_handle"; + break; + case "default": + default: + self._trap_light_model_off = "zombie_zapper_cagelight"; + self._trap_light_model_green = "zombie_zapper_cagelight_green"; + self._trap_light_model_red = "zombie_zapper_cagelight_red"; + self._trap_switch_model = "zombie_zapper_handle"; + break; + } +} + +register_visionsets( a_traps ) +{ + a_registered_traps = []; + _a1177 = a_traps; + _k1177 = getFirstArrayKey( _a1177 ); + while ( isDefined( _k1177 ) ) + { + trap = _a1177[ _k1177 ]; + if ( isDefined( trap.script_noteworthy ) ) + { + if ( !trap is_trap_registered( a_registered_traps ) ) + { + a_registered_traps[ trap.script_noteworthy ] = 1; + } + } + _k1177 = getNextArrayKey( _a1177, _k1177 ); + } + keys = getarraykeys( a_registered_traps ); + _a1190 = keys; + _k1190 = getFirstArrayKey( _a1190 ); + while ( isDefined( _k1190 ) ) + { + key = _a1190[ _k1190 ]; + switch( key ) + { + case "electric": + if ( !isDefined( level.vsmgr_prio_overlay_zm_trap_electrified ) ) + { + level.vsmgr_prio_overlay_zm_trap_electrified = 60; + } + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_trap_electric", 16000, level.vsmgr_prio_overlay_zm_trap_electrified, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 ); + level.trap_electric_visionset_registered = 1; + break; + case "fire": + if ( !isDefined( level.vsmgr_prio_overlay_zm_trap_burn ) ) + { + level.vsmgr_prio_overlay_zm_trap_burn = 61; + } + maps/mp/_visionset_mgr::vsmgr_register_info( "overlay", "zm_trap_burn", 16000, level.vsmgr_prio_overlay_zm_trap_burn, 15, 1, ::maps/mp/_visionset_mgr::vsmgr_duration_lerp_thread_per_player, 0 ); + level.trap_fire_visionset_registered = 1; + break; + } + _k1190 = getNextArrayKey( _a1190, _k1190 ); + } +} + +is_trap_registered( a_registered_traps ) +{ + return isDefined( a_registered_traps[ self.script_noteworthy ] ); +} diff --git a/patch_zm/maps/mp/zombies/_zm_turned.gsc b/patch_zm/maps/mp/zombies/_zm_turned.gsc new file mode 100644 index 0000000..4a8660f --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_turned.gsc @@ -0,0 +1,447 @@ +#include maps/mp/gametypes_zm/_spawnlogic; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/_visionset_mgr; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + level.turnedmeleeweapon = "zombiemelee_zm"; + level.turnedmeleeweapon_dw = "zombiemelee_dw"; + precacheitem( level.turnedmeleeweapon ); + precacheitem( level.turnedmeleeweapon_dw ); + if ( isDefined( level.custom_zombie_player_loadout_init ) && !level.custom_zombie_player_loadout_init ) + { + precachemodel( "c_zom_player_zombie_fb" ); + precachemodel( "c_zom_zombie_viewhands" ); + } + if ( !isDefined( level.vsmgr_prio_visionset_zombie_turned ) ) + { + level.vsmgr_prio_visionset_zombie_turned = 123; + } + maps/mp/_visionset_mgr::vsmgr_register_info( "visionset", "zm_turned", 3000, level.vsmgr_prio_visionset_zombie_turned, 1, 1 ); + registerclientfield( "toplayer", "turned_ir", 3000, 1, "int" ); + registerclientfield( "allplayers", "player_has_eyes", 3000, 1, "int" ); + registerclientfield( "allplayers", "player_eyes_special", 5000, 1, "int" ); + level._effect[ "player_eye_glow" ] = loadfx( "maps/zombie/fx_zombie_eye_returned_blue" ); + level._effect[ "player_eye_glow_orng" ] = loadfx( "maps/zombie/fx_zombie_eye_returned_orng" ); + thread setup_zombie_exerts(); +} + +setup_zombie_exerts() +{ + wait 0,05; + level.exert_sounds[ 1 ][ "burp" ] = "null"; + level.exert_sounds[ 1 ][ "hitmed" ] = "null"; + level.exert_sounds[ 1 ][ "hitlrg" ] = "null"; +} + +delay_turning_on_eyes() +{ + self endon( "death" ); + self endon( "disconnect" ); + wait_network_frame(); + wait 0,1; + self setclientfield( "player_has_eyes", 1 ); +} + +turn_to_zombie() +{ + if ( self.sessionstate == "playing" && isDefined( self.is_zombie ) && self.is_zombie && isDefined( self.laststand ) && !self.laststand ) + { + return; + } + if ( isDefined( self.is_in_process_of_zombify ) && self.is_in_process_of_zombify ) + { + return; + } + while ( isDefined( self.is_in_process_of_humanify ) && self.is_in_process_of_humanify ) + { + wait 0,1; + } + if ( !flag( "pregame" ) ) + { + self playsoundtoplayer( "evt_spawn", self ); + playsoundatposition( "evt_disappear_3d", self.origin ); + if ( !self.is_zombie ) + { + playsoundatposition( "vox_plr_" + randomintrange( 0, 4 ) + "_exert_death_high_" + randomintrange( 0, 4 ), self.origin ); + } + } + self._can_score = 1; + self setclientfield( "player_has_eyes", 0 ); + self ghost(); + self turned_disable_player_weapons(); + self notify( "clear_red_flashing_overlay" ); + self notify( "zombify" ); + self.is_in_process_of_zombify = 1; + self.team = level.zombie_team; + self.pers[ "team" ] = level.zombie_team; + self.sessionteam = level.zombie_team; + wait_network_frame(); + self maps/mp/gametypes_zm/_zm_gametype::onspawnplayer(); + self freezecontrols( 1 ); + self.is_zombie = 1; + self setburn( 0 ); + if ( isDefined( self.turned_visionset ) && self.turned_visionset ) + { + maps/mp/_visionset_mgr::vsmgr_deactivate( "visionset", "zm_turned", self ); + wait_network_frame(); + wait_network_frame(); + if ( !isDefined( self ) ) + { + return; + } + } + maps/mp/_visionset_mgr::vsmgr_activate( "visionset", "zm_turned", self ); + self.turned_visionset = 1; + self setclientfieldtoplayer( "turned_ir", 1 ); + self maps/mp/zombies/_zm_audio::setexertvoice( 1 ); + self.laststand = undefined; + wait_network_frame(); + if ( !isDefined( self ) ) + { + return; + } + self enableweapons(); + self show(); + playsoundatposition( "evt_appear_3d", self.origin ); + playsoundatposition( "zmb_zombie_spawn", self.origin ); + self thread delay_turning_on_eyes(); + self thread turned_player_buttons(); + self setperk( "specialty_noname" ); + self setperk( "specialty_unlimitedsprint" ); + self setperk( "specialty_fallheight" ); + self turned_give_melee_weapon(); + self setmovespeedscale( 1 ); + self.animname = "zombie"; + self disableoffhandweapons(); + self allowstand( 1 ); + self allowprone( 0 ); + self allowcrouch( 0 ); + self allowads( 0 ); + self allowjump( 0 ); + self disableweaponcycling(); + self setmovespeedscale( 1 ); + self setsprintduration( 4 ); + self setsprintcooldown( 0 ); + self stopshellshock(); + self.maxhealth = 256; + self.health = 256; + self.meleedamage = 1000; + self detachall(); + if ( isDefined( level.custom_zombie_player_loadout ) ) + { + self [[ level.custom_zombie_player_loadout ]](); + } + else + { + self setmodel( "c_zom_player_zombie_fb" ); + self.voice = "american"; + self.skeleton = "base"; + self setviewmodel( "c_zom_zombie_viewhands" ); + } + self.shock_onpain = 0; + self disableinvulnerability(); + if ( isDefined( level.player_movement_suppressed ) ) + { + self freezecontrols( level.player_movement_suppressed ); + } + else + { + if ( isDefined( self.hostmigrationcontrolsfrozen ) && !self.hostmigrationcontrolsfrozen ) + { + self freezecontrols( 0 ); + } + } + self.is_in_process_of_zombify = 0; +} + +turn_to_human() +{ + if ( self.sessionstate == "playing" && isDefined( self.is_zombie ) && !self.is_zombie && isDefined( self.laststand ) && !self.laststand ) + { + return; + } + if ( isDefined( self.is_in_process_of_humanify ) && self.is_in_process_of_humanify ) + { + return; + } + while ( isDefined( self.is_in_process_of_zombify ) && self.is_in_process_of_zombify ) + { + wait 0,1; + } + self playsoundtoplayer( "evt_spawn", self ); + playsoundatposition( "evt_disappear_3d", self.origin ); + self setclientfield( "player_has_eyes", 0 ); + self ghost(); + self notify( "humanify" ); + self.is_in_process_of_humanify = 1; + self.is_zombie = 0; + self notify( "clear_red_flashing_overlay" ); + self.team = self.prevteam; + self.pers[ "team" ] = self.prevteam; + self.sessionteam = self.prevteam; + wait_network_frame(); + self maps/mp/gametypes_zm/_zm_gametype::onspawnplayer(); + self.maxhealth = 100; + self.health = 100; + self freezecontrols( 1 ); + if ( self hasweapon( "death_throe_zm" ) ) + { + self takeweapon( "death_throe_zm" ); + } + self unsetperk( "specialty_noname" ); + self unsetperk( "specialty_unlimitedsprint" ); + self unsetperk( "specialty_fallheight" ); + self turned_enable_player_weapons(); + self maps/mp/zombies/_zm_audio::setexertvoice( 0 ); + self.turned_visionset = 0; + maps/mp/_visionset_mgr::vsmgr_deactivate( "visionset", "zm_turned", self ); + self setclientfieldtoplayer( "turned_ir", 0 ); + self setmovespeedscale( 1 ); + self.ignoreme = 0; + self.shock_onpain = 1; + self enableweaponcycling(); + self allowstand( 1 ); + self allowprone( 1 ); + self allowcrouch( 1 ); + self allowads( 1 ); + self allowjump( 1 ); + self turnedhuman(); + self enableoffhandweapons(); + self stopshellshock(); + self.laststand = undefined; + self.is_burning = undefined; + self.meleedamage = undefined; + self detachall(); + self [[ level.givecustomcharacters ]](); + if ( !self hasweapon( "knife_zm" ) ) + { + self giveweapon( "knife_zm" ); + } + wait_network_frame(); + if ( !isDefined( self ) ) + { + return; + } + self disableinvulnerability(); + if ( isDefined( level.player_movement_suppressed ) ) + { + self freezecontrols( level.player_movement_suppressed ); + } + else + { + if ( isDefined( self.hostmigrationcontrolsfrozen ) && !self.hostmigrationcontrolsfrozen ) + { + self freezecontrols( 0 ); + } + } + self show(); + playsoundatposition( "evt_appear_3d", self.origin ); + self.is_in_process_of_humanify = 0; +} + +deletezombiesinradius( origin ) +{ + zombies = get_round_enemy_array(); + maxradius = 128; + _a328 = zombies; + _k328 = getFirstArrayKey( _a328 ); + while ( isDefined( _k328 ) ) + { + zombie = _a328[ _k328 ]; + if ( isDefined( zombie ) && isalive( zombie ) && isDefined( zombie.is_being_used_as_spawner ) && !zombie.is_being_used_as_spawner ) + { + if ( distancesquared( zombie.origin, origin ) < ( maxradius * maxradius ) ) + { + playfx( level._effect[ "wood_chunk_destory" ], zombie.origin ); + zombie thread silentlyremovezombie(); + } + wait 0,05; + } + _k328 = getNextArrayKey( _a328, _k328 ); + } +} + +turned_give_melee_weapon() +{ +/# + assert( isDefined( self.turnedmeleeweapon ) ); +#/ +/# + assert( self.turnedmeleeweapon != "none" ); +#/ + self.turned_had_knife = self hasweapon( "knife_zm" ); + if ( isDefined( self.turned_had_knife ) && self.turned_had_knife ) + { + self takeweapon( "knife_zm" ); + } + self giveweapon( self.turnedmeleeweapon_dw ); + self givemaxammo( self.turnedmeleeweapon_dw ); + self giveweapon( self.turnedmeleeweapon ); + self givemaxammo( self.turnedmeleeweapon ); + self switchtoweapon( self.turnedmeleeweapon_dw ); + self switchtoweapon( self.turnedmeleeweapon ); +} + +turned_player_buttons() +{ + self endon( "disconnect" ); + self endon( "humanify" ); + level endon( "end_game" ); + while ( isDefined( self.is_zombie ) && self.is_zombie ) + { + while ( !self attackbuttonpressed() || self adsbuttonpressed() && self meleebuttonpressed() ) + { + if ( cointoss() ) + { + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "attack", undefined ); + } + while ( !self attackbuttonpressed() || self adsbuttonpressed() && self meleebuttonpressed() ) + { + wait 0,05; + } + } + while ( self usebuttonpressed() ) + { + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "taunt", undefined ); + while ( self usebuttonpressed() ) + { + wait 0,05; + } + } + while ( self issprinting() ) + { + while ( self issprinting() ) + { + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "sprint", undefined ); + wait 0,05; + } + } + wait 0,05; + } +} + +turned_disable_player_weapons() +{ + if ( isDefined( self.is_zombie ) && self.is_zombie ) + { + return; + } + weaponinventory = self getweaponslist(); + self.lastactiveweapon = self getcurrentweapon(); + self setlaststandprevweap( self.lastactiveweapon ); + self.laststandpistol = undefined; + self.hadpistol = 0; + if ( !isDefined( self.turnedmeleeweapon ) ) + { + self.turnedmeleeweapon = level.turnedmeleeweapon; + } + if ( !isDefined( self.turnedmeleeweapon_dw ) ) + { + self.turnedmeleeweapon_dw = level.turnedmeleeweapon_dw; + } + self takeallweapons(); + self disableweaponcycling(); +} + +turned_enable_player_weapons() +{ + self takeallweapons(); + self enableweaponcycling(); + self enableoffhandweapons(); + self.turned_had_knife = undefined; + if ( isDefined( level.humanify_custom_loadout ) ) + { + self thread [[ level.humanify_custom_loadout ]](); + return; + } + else + { + if ( !self hasweapon( "rottweil72_zm" ) ) + { + self giveweapon( "rottweil72_zm" ); + self switchtoweapon( "rottweil72_zm" ); + } + } + if ( isDefined( self.is_zombie ) && !self.is_zombie && !self hasweapon( level.start_weapon ) ) + { + if ( !self hasweapon( "knife_zm" ) ) + { + self giveweapon( "knife_zm" ); + } + self give_start_weapon( 0 ); + } + if ( self hasweapon( "rottweil72_zm" ) ) + { + self setweaponammoclip( "rottweil72_zm", 2 ); + self setweaponammostock( "rottweil72_zm", 0 ); + } + if ( self hasweapon( level.start_weapon ) ) + { + self givemaxammo( level.start_weapon ); + } + if ( self hasweapon( self get_player_lethal_grenade() ) ) + { + self getweaponammoclip( self get_player_lethal_grenade() ); + } + else + { + self giveweapon( self get_player_lethal_grenade() ); + } + self setweaponammoclip( self get_player_lethal_grenade(), 2 ); +} + +get_farthest_available_zombie( player ) +{ + while ( 1 ) + { + zombies = get_array_of_closest( player.origin, getaiarray( level.zombie_team ) ); + x = 0; + while ( x < zombies.size ) + { + zombie = zombies[ x ]; + if ( isDefined( zombie ) && isalive( zombie ) && isDefined( zombie.in_the_ground ) && !zombie.in_the_ground && isDefined( zombie.gibbed ) && !zombie.gibbed && isDefined( zombie.head_gibbed ) && !zombie.head_gibbed && isDefined( zombie.is_being_used_as_spawnpoint ) && !zombie.is_being_used_as_spawnpoint && zombie in_playable_area() ) + { + zombie.is_being_used_as_spawnpoint = 1; + return zombie; + } + x++; + } + wait 0,05; + } +} + +get_available_human() +{ + players = get_players(); + _a539 = players; + _k539 = getFirstArrayKey( _a539 ); + while ( isDefined( _k539 ) ) + { + player = _a539[ _k539 ]; + if ( isDefined( player.is_zombie ) && !player.is_zombie ) + { + return player; + } + _k539 = getNextArrayKey( _a539, _k539 ); + } +} + +silentlyremovezombie() +{ + self.skip_death_notetracks = 1; + self.nodeathragdoll = 1; + self dodamage( self.maxhealth * 2, self.origin, self, self, "none", "MOD_SUICIDE" ); + self self_delete(); +} + +getspawnpoint() +{ + spawnpoint = self maps/mp/gametypes_zm/_spawnlogic::getspawnpoint_dm( level._turned_zombie_respawnpoints ); + return spawnpoint; +} diff --git a/patch_zm/maps/mp/zombies/_zm_unitrigger.gsc b/patch_zm/maps/mp/zombies/_zm_unitrigger.gsc new file mode 100644 index 0000000..0fa35ef --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_unitrigger.gsc @@ -0,0 +1,800 @@ +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + level._unitriggers = spawnstruct(); + level._unitriggers._deferredinitlist = []; + level._unitriggers.trigger_pool = []; + level._unitriggers.trigger_stubs = []; + level._unitriggers.dynamic_stubs = []; + level._unitriggers.system_trigger_funcs = []; + level._unitriggers.largest_radius = 64; + stubs_keys = array( "unitrigger_radius", "unitrigger_radius_use", "unitrigger_box", "unitrigger_box_use" ); + stubs = []; + i = 0; + while ( i < stubs_keys.size ) + { + stubs = arraycombine( stubs, getstructarray( stubs_keys[ i ], "script_unitrigger_type" ), 1, 0 ); + i++; + } + i = 0; + while ( i < stubs.size ) + { + register_unitrigger( stubs[ i ] ); + i++; + } +} + +register_unitrigger_system_func( system, trigger_func ) +{ + level._unitriggers.system_trigger_funcs[ system ] = trigger_func; +} + +unitrigger_force_per_player_triggers( unitrigger_stub, opt_on_off ) +{ + if ( !isDefined( opt_on_off ) ) + { + opt_on_off = 1; + } + unitrigger_stub.trigger_per_player = opt_on_off; +} + +unitrigger_trigger( player ) +{ + if ( self.trigger_per_player ) + { + return self.playertrigger[ player getentitynumber() ]; + } + else + { + return self.trigger; + } +} + +unitrigger_origin() +{ + if ( isDefined( self.originfunc ) ) + { + origin = self [[ self.originfunc ]](); + } + else + { + origin = self.origin; + } + return origin; +} + +register_unitrigger_internal( unitrigger_stub, trigger_func ) +{ + if ( !isDefined( unitrigger_stub.script_unitrigger_type ) ) + { +/# + println( "Cannot register a unitrigger with no script_unitrigger_type. Ignoring." ); +#/ + return; + } + if ( isDefined( trigger_func ) ) + { + unitrigger_stub.trigger_func = trigger_func; + } + else + { + if ( isDefined( unitrigger_stub.unitrigger_system ) && isDefined( level._unitriggers.system_trigger_funcs[ unitrigger_stub.unitrigger_system ] ) ) + { + unitrigger_stub.trigger_func = level._unitriggers.system_trigger_funcs[ unitrigger_stub.unitrigger_system ]; + } + } + switch( unitrigger_stub.script_unitrigger_type ) + { + case "unitrigger_radius": + case "unitrigger_radius_use": + if ( !isDefined( unitrigger_stub.radius ) ) + { + unitrigger_stub.radius = 32; + } + if ( !isDefined( unitrigger_stub.script_height ) ) + { + unitrigger_stub.script_height = 64; + } + unitrigger_stub.test_radius_sq = ( unitrigger_stub.radius + 15 ) * ( unitrigger_stub.radius + 15 ); + break; + case "unitrigger_box": + case "unitrigger_box_use": + if ( !isDefined( unitrigger_stub.script_width ) ) + { + unitrigger_stub.script_width = 64; + } + if ( !isDefined( unitrigger_stub.script_height ) ) + { + unitrigger_stub.script_height = 64; + } + if ( !isDefined( unitrigger_stub.script_length ) ) + { + unitrigger_stub.script_length = 64; + } + box_radius = length( ( unitrigger_stub.script_width / 2, unitrigger_stub.script_length / 2, unitrigger_stub.script_height / 2 ) ); + if ( !isDefined( unitrigger_stub.radius ) || unitrigger_stub.radius < box_radius ) + { + unitrigger_stub.radius = box_radius; + } + unitrigger_stub.test_radius_sq = ( box_radius + 15 ) * ( box_radius + 15 ); + break; + default: +/# + println( "Unknown unitrigger type registered : " + unitrigger_stub.targetname + " - ignoring." ); +#/ + return; + } + if ( unitrigger_stub.radius > level._unitriggers.largest_radius ) + { + level._unitriggers.largest_radius = min( 113, unitrigger_stub.radius ); + if ( isDefined( level.fixed_max_player_use_radius ) ) + { + if ( level.fixed_max_player_use_radius > getDvarFloat( "player_useRadius_zm" ) ) + { + setdvar( "player_useRadius_zm", level.fixed_max_player_use_radius ); + } + } + else + { + if ( level._unitriggers.largest_radius > getDvarFloat( "player_useRadius_zm" ) ) + { + setdvar( "player_useRadius_zm", level._unitriggers.largest_radius ); + } + } + } + level._unitriggers.trigger_stubs[ level._unitriggers.trigger_stubs.size ] = unitrigger_stub; + unitrigger_stub.registered = 1; +} + +register_unitrigger( unitrigger_stub, trigger_func ) +{ + register_unitrigger_internal( unitrigger_stub, trigger_func ); + level._unitriggers.dynamic_stubs[ level._unitriggers.dynamic_stubs.size ] = unitrigger_stub; +} + +unregister_unitrigger( unitrigger_stub ) +{ + thread unregister_unitrigger_internal( unitrigger_stub ); +} + +unregister_unitrigger_internal( unitrigger_stub ) +{ + if ( !isDefined( unitrigger_stub ) ) + { + return; + } + unitrigger_stub.registered = 0; + if ( isDefined( unitrigger_stub.trigger_per_player ) && unitrigger_stub.trigger_per_player ) + { + if ( isDefined( unitrigger_stub.playertrigger ) && unitrigger_stub.playertrigger.size > 0 ) + { + keys = getarraykeys( unitrigger_stub.playertrigger ); + _a181 = keys; + _k181 = getFirstArrayKey( _a181 ); + while ( isDefined( _k181 ) ) + { + key = _a181[ _k181 ]; + trigger = unitrigger_stub.playertrigger[ key ]; + trigger notify( "kill_trigger" ); + if ( isDefined( trigger ) ) + { + trigger delete(); + } + _k181 = getNextArrayKey( _a181, _k181 ); + } + unitrigger_stub.playertrigger = []; + } + } + else + { + if ( isDefined( unitrigger_stub.trigger ) ) + { + trigger = unitrigger_stub.trigger; + trigger notify( "kill_trigger" ); + trigger.stub.trigger = undefined; + trigger delete(); + } + } + if ( isDefined( unitrigger_stub.in_zone ) ) + { + arrayremovevalue( level.zones[ unitrigger_stub.in_zone ].unitrigger_stubs, unitrigger_stub ); + unitrigger_stub.in_zone = undefined; + } + arrayremovevalue( level._unitriggers.trigger_stubs, unitrigger_stub ); + arrayremovevalue( level._unitriggers.dynamic_stubs, unitrigger_stub ); +} + +delay_delete_contact_ent() +{ + self.last_used_time = 0; + while ( 1 ) + { + wait 1; + if ( ( getTime() - self.last_used_time ) > 1000 ) + { + self delete(); + level._unitriggers.contact_ent = undefined; + return; + } + } +} + +register_static_unitrigger( unitrigger_stub, trigger_func, recalculate_zone ) +{ + if ( level.zones.size == 0 ) + { + unitrigger_stub.trigger_func = trigger_func; + level._unitriggers._deferredinitlist[ level._unitriggers._deferredinitlist.size ] = unitrigger_stub; + return; + } + if ( !isDefined( level._unitriggers.contact_ent ) ) + { + level._unitriggers.contact_ent = spawn( "script_origin", ( 0, 0, 1 ) ); + level._unitriggers.contact_ent thread delay_delete_contact_ent(); + } + register_unitrigger_internal( unitrigger_stub, trigger_func ); + while ( !isDefined( level._no_static_unitriggers ) ) + { + level._unitriggers.contact_ent.last_used_time = getTime(); + level._unitriggers.contact_ent.origin = unitrigger_stub.origin; + if ( isDefined( unitrigger_stub.in_zone ) && !isDefined( recalculate_zone ) ) + { + level.zones[ unitrigger_stub.in_zone ].unitrigger_stubs[ level.zones[ unitrigger_stub.in_zone ].unitrigger_stubs.size ] = unitrigger_stub; + return; + } + keys = getarraykeys( level.zones ); + i = 0; + while ( i < keys.size ) + { + if ( level._unitriggers.contact_ent maps/mp/zombies/_zm_zonemgr::entity_in_zone( keys[ i ], 1 ) ) + { + if ( !isDefined( level.zones[ keys[ i ] ].unitrigger_stubs ) ) + { + level.zones[ keys[ i ] ].unitrigger_stubs = []; + } + level.zones[ keys[ i ] ].unitrigger_stubs[ level.zones[ keys[ i ] ].unitrigger_stubs.size ] = unitrigger_stub; + unitrigger_stub.in_zone = keys[ i ]; + return; + } + i++; + } + } + level._unitriggers.dynamic_stubs[ level._unitriggers.dynamic_stubs.size ] = unitrigger_stub; + unitrigger_stub.registered = 1; +} + +reregister_unitrigger_as_dynamic( unitrigger_stub ) +{ + unregister_unitrigger_internal( unitrigger_stub ); + register_unitrigger( unitrigger_stub, unitrigger_stub.trigger_func ); +} + +debug_unitriggers() +{ +/# + while ( 1 ) + { + while ( getDvarInt( #"D256F24B" ) > 0 ) + { + i = 0; + while ( i < level._unitriggers.trigger_stubs.size ) + { + triggerstub = level._unitriggers.trigger_stubs[ i ]; + color = vectorScale( ( 0, 0, 1 ), 0,75 ); + if ( !isDefined( triggerstub.in_zone ) ) + { + color = vectorScale( ( 0, 0, 1 ), 0,65 ); + } + else + { + if ( level.zones[ triggerstub.in_zone ].is_active ) + { + color = ( 0, 0, 1 ); + } + } + if ( isDefined( triggerstub.trigger ) || isDefined( triggerstub.playertrigger ) && triggerstub.playertrigger.size > 0 ) + { + color = ( 0, 0, 1 ); + if ( isDefined( triggerstub.playertrigger ) && triggerstub.playertrigger.size > 0 ) + { + print3d( triggerstub.origin, triggerstub.playertrigger.size, color, 1, 1, 1 ); + } + } + origin = triggerstub unitrigger_origin(); + switch( triggerstub.script_unitrigger_type ) + { + case "unitrigger_radius": + case "unitrigger_radius_use": + if ( triggerstub.radius ) + { + circle( origin, triggerstub.radius, color, 0, 0, 1 ); + } + if ( triggerstub.script_height ) + { + line( origin, origin + ( 0, 0, triggerstub.script_height ), color, 0, 1 ); + } + break; + i++; + continue; + case "unitrigger_box": + case "unitrigger_box_use": + vec = ( triggerstub.script_width / 2, triggerstub.script_length / 2, triggerstub.script_height / 2 ); + box( origin, vec * -1, vec, triggerstub.angles[ 1 ], color, 1, 0, 1 ); + break; + i++; + continue; + } + i++; + } + } + wait 0,05; +#/ + } +} + +cleanup_trigger( trigger, player ) +{ + trigger notify( "kill_trigger" ); + if ( isDefined( trigger.stub.trigger_per_player ) && trigger.stub.trigger_per_player ) + { + } + else + { + trigger.stub.trigger = undefined; + } + trigger delete(); +} + +assess_and_apply_visibility( trigger, stub, player, default_keep ) +{ + if ( !isDefined( trigger ) || !isDefined( stub ) ) + { + return 0; + } + keep_thread = default_keep; + if ( !isDefined( stub.prompt_and_visibility_func ) || trigger [[ stub.prompt_and_visibility_func ]]( player ) ) + { + keep_thread = 1; + if ( isDefined( trigger.thread_running ) && !trigger.thread_running ) + { + trigger thread trigger_thread( trigger.stub.trigger_func ); + } + trigger.thread_running = 1; + if ( isDefined( trigger.reassess_time ) && trigger.reassess_time <= 0 ) + { + trigger.reassess_time = undefined; + } + } + else + { + if ( isDefined( trigger.thread_running ) && trigger.thread_running ) + { + keep_thread = 0; + } + trigger.thread_running = 0; + if ( isDefined( stub.inactive_reasses_time ) ) + { + trigger.reassess_time = stub.inactive_reasses_time; + } + else + { + trigger.reassess_time = 1; + } + } + return keep_thread; +} + +main() +{ + level thread debug_unitriggers(); + if ( level._unitriggers._deferredinitlist.size ) + { + i = 0; + while ( i < level._unitriggers._deferredinitlist.size ) + { + register_static_unitrigger( level._unitriggers._deferredinitlist[ i ], level._unitriggers._deferredinitlist[ i ].trigger_func ); + i++; + } + i = 0; + while ( i < level._unitriggers._deferredinitlist.size ) + { + i++; + } + level._unitriggers._deferredinitlist = undefined; + } + valid_range = level._unitriggers.largest_radius + 15; + valid_range_sq = valid_range * valid_range; + while ( !isDefined( level.active_zone_names ) ) + { + wait 0,1; + } + while ( 1 ) + { + waited = 0; + active_zone_names = level.active_zone_names; + candidate_list = []; + j = 0; + while ( j < active_zone_names.size ) + { + if ( isDefined( level.zones[ active_zone_names[ j ] ].unitrigger_stubs ) ) + { + candidate_list = arraycombine( candidate_list, level.zones[ active_zone_names[ j ] ].unitrigger_stubs, 1, 0 ); + } + j++; + } + candidate_list = arraycombine( candidate_list, level._unitriggers.dynamic_stubs, 1, 0 ); + players = getplayers(); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( !isDefined( player ) ) + { + i++; + continue; + } + else player_origin = player.origin + vectorScale( ( 0, 0, 1 ), 35 ); + trigger = level._unitriggers.trigger_pool[ player getentitynumber() ]; + closest = []; + if ( isDefined( trigger ) ) + { + dst = valid_range_sq; + origin = trigger unitrigger_origin(); + dst = trigger.stub.test_radius_sq; + time_to_ressess = 0; + if ( distance2dsquared( player_origin, origin ) < dst ) + { + if ( isDefined( trigger.reassess_time ) ) + { + trigger.reassess_time -= 0,05; + if ( trigger.reassess_time > 0 ) + { + i++; + continue; + } + else time_to_ressess = 1; + break; + } + else + { + } + } + else closest = get_closest_unitriggers( player_origin, candidate_list, valid_range ); + if ( isDefined( trigger ) && time_to_ressess || closest.size < 2 && isDefined( trigger.thread_running ) && trigger.thread_running ) + { + if ( assess_and_apply_visibility( trigger, trigger.stub, player, 1 ) ) + { + i++; + continue; + } + } + else if ( isDefined( trigger ) ) + { + cleanup_trigger( trigger, player ); + } + } + else + { + closest = get_closest_unitriggers( player_origin, candidate_list, valid_range ); + } + index = 0; + last_trigger = undefined; + while ( index < closest.size ) + { + while ( !is_player_valid( player ) && isDefined( closest[ index ].ignore_player_valid ) && !closest[ index ].ignore_player_valid ) + { + index++; + } + while ( isDefined( closest[ index ].registered ) && !closest[ index ].registered ) + { + index++; + } + if ( isDefined( last_trigger ) ) + { + cleanup_trigger( last_trigger, player ); + last_trigger = undefined; + } + trigger = undefined; + if ( isDefined( closest[ index ].trigger_per_player ) && closest[ index ].trigger_per_player ) + { + if ( !isDefined( closest[ index ].playertrigger ) ) + { + closest[ index ].playertrigger = []; + } + if ( !isDefined( closest[ index ].playertrigger[ player getentitynumber() ] ) ) + { + trigger = build_trigger_from_unitrigger_stub( closest[ index ], player ); + level._unitriggers.trigger_pool[ player getentitynumber() ] = trigger; + } + } + else + { + if ( !isDefined( closest[ index ].trigger ) ) + { + trigger = build_trigger_from_unitrigger_stub( closest[ index ], player ); + level._unitriggers.trigger_pool[ player getentitynumber() ] = trigger; + } + } + if ( isDefined( trigger ) ) + { + trigger.parent_player = player; + if ( assess_and_apply_visibility( trigger, closest[ index ], player, 0 ) ) + { + i++; + continue; + } + else + { + last_trigger = trigger; + } + index++; + waited = 1; + wait 0,05; + } + } + i++; + } + if ( !waited ) + { + wait 0,05; + } + } +} + +run_visibility_function_for_all_triggers() +{ + if ( !isDefined( self.prompt_and_visibility_func ) ) + { + return; + } + if ( isDefined( self.trigger_per_player ) && self.trigger_per_player ) + { + if ( !isDefined( self.playertrigger ) ) + { + return; + } + players = getplayers(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( self.playertrigger[ players[ i ] getentitynumber() ] ) ) + { + self.playertrigger[ players[ i ] getentitynumber() ] [[ self.prompt_and_visibility_func ]]( players[ i ] ); + } + i++; + } + } + else if ( isDefined( self.trigger ) ) + { + self.trigger [[ self.prompt_and_visibility_func ]]( getplayers()[ 0 ] ); + } +} + +build_trigger_from_unitrigger_stub( stub, player ) +{ + if ( isDefined( level._zm_build_trigger_from_unitrigger_stub_override ) ) + { + if ( stub [[ level._zm_build_trigger_from_unitrigger_stub_override ]]( player ) ) + { + return; + } + } + radius = stub.radius; + if ( !isDefined( radius ) ) + { + radius = 64; + } + script_height = stub.script_height; + if ( !isDefined( script_height ) ) + { + script_height = 64; + } + script_width = stub.script_width; + if ( !isDefined( script_width ) ) + { + script_width = 64; + } + script_length = stub.script_length; + if ( !isDefined( script_length ) ) + { + script_length = 64; + } + trigger = undefined; + origin = stub unitrigger_origin(); + switch( stub.script_unitrigger_type ) + { + case "unitrigger_radius": + trigger = spawn( "trigger_radius", origin, 0, radius, script_height ); + break; + case "unitrigger_radius_use": + trigger = spawn( "trigger_radius_use", origin, 0, radius, script_height ); + break; + case "unitrigger_box": + trigger = spawn( "trigger_box", origin, 0, script_width, script_length, script_height ); + break; + case "unitrigger_box_use": + trigger = spawn( "trigger_box_use", origin, 0, script_width, script_length, script_height ); + break; + } + if ( isDefined( trigger ) ) + { + if ( isDefined( stub.angles ) ) + { + trigger.angles = stub.angles; + } + if ( isDefined( stub.onspawnfunc ) ) + { + stub [[ stub.onspawnfunc ]]( trigger ); + } + if ( isDefined( stub.cursor_hint ) ) + { + if ( stub.cursor_hint == "HINT_WEAPON" && isDefined( stub.cursor_hint_weapon ) ) + { + trigger setcursorhint( stub.cursor_hint, stub.cursor_hint_weapon ); + } + else + { + trigger setcursorhint( stub.cursor_hint ); + } + } + trigger triggerignoreteam(); + if ( isDefined( stub.require_look_at ) && stub.require_look_at ) + { + trigger usetriggerrequirelookat(); + } + if ( isDefined( stub.hint_string ) ) + { + if ( isDefined( stub.hint_parm2 ) ) + { + trigger sethintstring( stub.hint_string, stub.hint_parm1, stub.hint_parm2 ); + } + else if ( isDefined( stub.hint_parm1 ) ) + { + trigger sethintstring( stub.hint_string, stub.hint_parm1 ); + } + else if ( isDefined( stub.cost ) ) + { + trigger sethintstring( stub.hint_string, stub.cost ); + } + else + { + trigger sethintstring( stub.hint_string ); + } + } + trigger.stub = stub; + } + copy_zombie_keys_onto_trigger( trigger, stub ); + if ( isDefined( stub.trigger_per_player ) && stub.trigger_per_player ) + { + if ( isDefined( trigger ) ) + { + trigger setinvisibletoall(); + trigger setvisibletoplayer( player ); + } + if ( !isDefined( stub.playertrigger ) ) + { + stub.playertrigger = []; + } + stub.playertrigger[ player getentitynumber() ] = trigger; + } + else + { + stub.trigger = trigger; + } + trigger.thread_running = 0; + return trigger; +} + +copy_zombie_keys_onto_trigger( trig, stub ) +{ + trig.script_noteworthy = stub.script_noteworthy; + trig.targetname = stub.targetname; + trig.target = stub.target; + trig.zombie_weapon_upgrade = stub.zombie_weapon_upgrade; + trig.clientfieldname = stub.clientfieldname; + trig.usetime = stub.usetime; +} + +trigger_thread( trigger_func ) +{ + self endon( "kill_trigger" ); + if ( isDefined( trigger_func ) ) + { + self [[ trigger_func ]](); + } +} + +get_closest_unitrigger_index( org, array, dist ) +{ + if ( !isDefined( dist ) ) + { + dist = 9999999; + } + distsq = dist * dist; + if ( array.size < 1 ) + { + return; + } + index = undefined; + i = 0; + while ( i < array.size ) + { + origin = array[ i ] unitrigger_origin(); + radius_sq = array[ i ].test_radius_sq; + newdistsq = distance2dsquared( origin, org ); + if ( newdistsq >= radius_sq ) + { + i++; + continue; + } + else if ( newdistsq >= distsq ) + { + i++; + continue; + } + else + { + distsq = newdistsq; + index = i; + } + i++; + } + return index; +} + +get_closest_unitriggers( org, array, dist ) +{ + triggers = []; + if ( !isDefined( dist ) ) + { + dist = 9999999; + } + distsq = dist * dist; + if ( array.size < 1 ) + { + return triggers; + } + index = undefined; + i = 0; + while ( i < array.size ) + { + if ( !isDefined( array[ i ] ) ) + { + i++; + continue; + } + else origin = array[ i ] unitrigger_origin(); + radius_sq = array[ i ].test_radius_sq; + newdistsq = distance2dsquared( origin, org ); + if ( newdistsq >= radius_sq ) + { + i++; + continue; + } + else if ( abs( origin[ 2 ] - org[ 2 ] ) > 42 ) + { + i++; + continue; + } + else + { + array[ i ].dsquared = newdistsq; + j = 0; + while ( j < triggers.size && newdistsq > triggers[ j ].dsquared ) + { + j++; + } + arrayinsert( triggers, array[ i ], j ); + if ( ( i % 10 ) == 9 ) + { + wait 0,05; + } + } + i++; + } + return triggers; +} diff --git a/patch_zm/maps/mp/zombies/_zm_utility.gsc b/patch_zm/maps/mp/zombies/_zm_utility.gsc new file mode 100644 index 0000000..c6bc2e5 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_utility.gsc @@ -0,0 +1,5861 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/gametypes_zm/_hud_message; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_power; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_server_throttle; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/animscripts/zm_run; +#include common_scripts/utility; +#include maps/mp/_utility; + +init_utility() +{ +} + +is_classic() +{ + var = getDvar( "ui_zm_gamemodegroup" ); + if ( var == "zclassic" ) + { + return 1; + } + return 0; +} + +is_standard() +{ + var = getDvar( "ui_gametype" ); + if ( var == "zstandard" ) + { + return 1; + } + return 0; +} + +convertsecondstomilliseconds( seconds ) +{ + return seconds * 1000; +} + +is_player() +{ + if ( !isplayer( self ) ) + { + if ( isDefined( self.pers ) ) + { + if ( isDefined( self.pers[ "isBot" ] ) ) + { + return self.pers[ "isBot" ]; + } + } + } +} + +lerp( chunk ) +{ + link = spawn( "script_origin", self getorigin() ); + link.angles = self.first_node.angles; + self linkto( link ); + link rotateto( self.first_node.angles, level._contextual_grab_lerp_time ); + link moveto( self.attacking_spot, level._contextual_grab_lerp_time ); + link waittill_multiple( "rotatedone", "movedone" ); + self unlink(); + link delete(); + return; +} + +clear_mature_blood() +{ + blood_patch = getentarray( "mature_blood", "targetname" ); + if ( is_mature() ) + { + return; + } + while ( isDefined( blood_patch ) ) + { + i = 0; + while ( i < blood_patch.size ) + { + blood_patch[ i ] delete(); + i++; + } + } +} + +recalc_zombie_array() +{ +} + +clear_all_corpses() +{ + corpse_array = getcorpsearray(); + i = 0; + while ( i < corpse_array.size ) + { + if ( isDefined( corpse_array[ i ] ) ) + { + corpse_array[ i ] delete(); + } + i++; + } +} + +get_current_corpse_count() +{ + corpse_array = getcorpsearray(); + if ( isDefined( corpse_array ) ) + { + return corpse_array.size; + } + return 0; +} + +get_current_actor_count() +{ + count = 0; + actors = getaispeciesarray( level.zombie_team, "all" ); + if ( isDefined( actors ) ) + { + count += actors.size; + } + count += get_current_corpse_count(); + return count; +} + +get_current_zombie_count() +{ + enemies = get_round_enemy_array(); + return enemies.size; +} + +get_round_enemy_array() +{ + enemies = []; + valid_enemies = []; + enemies = getaispeciesarray( level.zombie_team, "all" ); + i = 0; + while ( i < enemies.size ) + { + if ( isDefined( enemies[ i ].ignore_enemy_count ) && enemies[ i ].ignore_enemy_count ) + { + i++; + continue; + } + else + { + valid_enemies[ valid_enemies.size ] = enemies[ i ]; + } + i++; + } + return valid_enemies; +} + +init_zombie_run_cycle() +{ + if ( isDefined( level.speed_change_round ) ) + { + if ( level.round_number >= level.speed_change_round ) + { + speed_percent = 0,2 + ( ( level.round_number - level.speed_change_round ) * 0,2 ); + speed_percent = min( speed_percent, 1 ); + change_round_max = int( level.speed_change_max * speed_percent ); + change_left = change_round_max - level.speed_change_num; + if ( change_left == 0 ) + { + self set_zombie_run_cycle(); + return; + } + change_speed = randomint( 100 ); + if ( change_speed > 80 ) + { + self change_zombie_run_cycle(); + return; + } + zombie_count = get_current_zombie_count(); + zombie_left = level.zombie_ai_limit - zombie_count; + if ( zombie_left == change_left ) + { + self change_zombie_run_cycle(); + return; + } + } + } + self set_zombie_run_cycle(); +} + +change_zombie_run_cycle() +{ + level.speed_change_num++; + if ( level.gamedifficulty == 0 ) + { + self set_zombie_run_cycle( "sprint" ); + } + else + { + self set_zombie_run_cycle( "walk" ); + } + self thread speed_change_watcher(); +} + +speed_change_watcher() +{ + self waittill( "death" ); + if ( level.speed_change_num > 0 ) + { + level.speed_change_num--; + + } +} + +set_zombie_run_cycle( new_move_speed ) +{ + self.zombie_move_speed_original = self.zombie_move_speed; + if ( isDefined( new_move_speed ) ) + { + self.zombie_move_speed = new_move_speed; + } + else if ( level.gamedifficulty == 0 ) + { + self set_run_speed_easy(); + } + else + { + self set_run_speed(); + } + self maps/mp/animscripts/zm_run::needsupdate(); + self.deathanim = self maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "zm_death" ); +} + +set_run_speed() +{ + rand = randomintrange( level.zombie_move_speed, level.zombie_move_speed + 35 ); + if ( rand <= 35 ) + { + self.zombie_move_speed = "walk"; + } + else if ( rand <= 70 ) + { + self.zombie_move_speed = "run"; + } + else + { + self.zombie_move_speed = "sprint"; + } +} + +set_run_speed_easy() +{ + rand = randomintrange( level.zombie_move_speed, level.zombie_move_speed + 25 ); + if ( rand <= 35 ) + { + self.zombie_move_speed = "walk"; + } + else + { + self.zombie_move_speed = "run"; + } +} + +spawn_zombie( spawner, target_name, spawn_point, round_number ) +{ + if ( !isDefined( spawner ) ) + { +/# + println( "ZM >> spawn_zombie - NO SPAWNER DEFINED" ); +#/ + return undefined; + } + while ( getfreeactorcount() < 1 ) + { + wait 0,05; + } + spawner.script_moveoverride = 1; + if ( isDefined( spawner.script_forcespawn ) && spawner.script_forcespawn ) + { + guy = spawner spawnactor(); + if ( isDefined( level.giveextrazombies ) ) + { + guy [[ level.giveextrazombies ]](); + } + guy enableaimassist(); + if ( isDefined( round_number ) ) + { + guy._starting_round_number = round_number; + } + guy.aiteam = level.zombie_team; + guy clearentityowner(); + level.zombiemeleeplayercounter = 0; + guy thread run_spawn_functions(); + guy forceteleport( spawner.origin ); + guy show(); + } + spawner.count = 666; + if ( !spawn_failed( guy ) ) + { + if ( isDefined( target_name ) ) + { + guy.targetname = target_name; + } + return guy; + } + return undefined; +} + +run_spawn_functions() +{ + self endon( "death" ); + waittillframeend; + i = 0; + while ( i < level.spawn_funcs[ self.team ].size ) + { + func = level.spawn_funcs[ self.team ][ i ]; + single_thread( self, func[ "function" ], func[ "param1" ], func[ "param2" ], func[ "param3" ], func[ "param4" ], func[ "param5" ] ); + i++; + } + if ( isDefined( self.spawn_funcs ) ) + { + i = 0; + while ( i < self.spawn_funcs.size ) + { + func = self.spawn_funcs[ i ]; + single_thread( self, func[ "function" ], func[ "param1" ], func[ "param2" ], func[ "param3" ], func[ "param4" ] ); + i++; + } +/# + self.saved_spawn_functions = self.spawn_funcs; +#/ + self.spawn_funcs = undefined; +/# + self.spawn_funcs = self.saved_spawn_functions; + self.saved_spawn_functions = undefined; +#/ + self.spawn_funcs = undefined; + } +} + +create_simple_hud( client, team ) +{ + if ( isDefined( team ) ) + { + hud = newteamhudelem( team ); + hud.team = team; + } + else if ( isDefined( client ) ) + { + hud = newclienthudelem( client ); + } + else + { + hud = newhudelem(); + } + level.hudelem_count++; + hud.foreground = 1; + hud.sort = 1; + hud.hidewheninmenu = 0; + return hud; +} + +destroy_hud() +{ + level.hudelem_count--; + + self destroy(); +} + +all_chunks_intact( barrier, barrier_chunks ) +{ + if ( isDefined( barrier.zbarrier ) ) + { + pieces = barrier.zbarrier getzbarrierpieceindicesinstate( "closed" ); + if ( pieces.size != barrier.zbarrier getnumzbarrierpieces() ) + { + return 0; + } + } + else + { + i = 0; + while ( i < barrier_chunks.size ) + { + if ( barrier_chunks[ i ] get_chunk_state() != "repaired" ) + { + return 0; + } + i++; + } + } + return 1; +} + +no_valid_repairable_boards( barrier, barrier_chunks ) +{ + if ( isDefined( barrier.zbarrier ) ) + { + pieces = barrier.zbarrier getzbarrierpieceindicesinstate( "open" ); + if ( pieces.size ) + { + return 0; + } + } + else + { + i = 0; + while ( i < barrier_chunks.size ) + { + if ( barrier_chunks[ i ] get_chunk_state() == "destroyed" ) + { + return 0; + } + i++; + } + } + return 1; +} + +is_survival() +{ + var = getDvar( "ui_zm_gamemodegroup" ); + if ( var == "zsurvival" ) + { + return 1; + } + return 0; +} + +is_encounter() +{ + if ( isDefined( level._is_encounter ) && level._is_encounter ) + { + return 1; + } + var = getDvar( "ui_zm_gamemodegroup" ); + if ( var == "zencounter" ) + { + level._is_encounter = 1; + return 1; + } + return 0; +} + +all_chunks_destroyed( barrier, barrier_chunks ) +{ + if ( isDefined( barrier.zbarrier ) ) + { + pieces = arraycombine( barrier.zbarrier getzbarrierpieceindicesinstate( "open" ), barrier.zbarrier getzbarrierpieceindicesinstate( "opening" ), 1, 0 ); + if ( pieces.size != barrier.zbarrier getnumzbarrierpieces() ) + { + return 0; + } + } + else + { + while ( isDefined( barrier_chunks ) ) + { +/# + assert( isDefined( barrier_chunks ), "_zm_utility::all_chunks_destroyed - Barrier chunks undefined" ); +#/ + i = 0; + while ( i < barrier_chunks.size ) + { + if ( barrier_chunks[ i ] get_chunk_state() != "destroyed" ) + { + return 0; + } + i++; + } + } + } + return 1; +} + +check_point_in_playable_area( origin ) +{ + playable_area = getentarray( "player_volume", "script_noteworthy" ); + check_model = spawn( "script_model", origin + vectorScale( ( 0, 0, 1 ), 40 ) ); + valid_point = 0; + i = 0; + while ( i < playable_area.size ) + { + if ( check_model istouching( playable_area[ i ] ) ) + { + valid_point = 1; + } + i++; + } + check_model delete(); + return valid_point; +} + +check_point_in_enabled_zone( origin, zone_is_active, player_zones ) +{ + if ( !isDefined( player_zones ) ) + { + player_zones = getentarray( "player_volume", "script_noteworthy" ); + } + if ( !isDefined( level.zones ) || !isDefined( player_zones ) ) + { + return 1; + } + scr_org = spawn( "script_origin", origin + vectorScale( ( 0, 0, 1 ), 40 ) ); + one_valid_zone = 0; + i = 0; + while ( i < player_zones.size ) + { + if ( scr_org istouching( player_zones[ i ] ) ) + { + zone = level.zones[ player_zones[ i ].targetname ]; + if ( isDefined( zone ) && isDefined( zone.is_enabled ) && zone.is_enabled ) + { + if ( isDefined( zone_is_active ) && zone_is_active == 1 && isDefined( zone.is_active ) && !zone.is_active ) + { + i++; + continue; + } + else + { + one_valid_zone = 1; + break; + } + } + } + else + { + i++; + } + } + scr_org delete(); + return one_valid_zone; +} + +round_up_to_ten( score ) +{ + new_score = score - ( score % 10 ); + if ( new_score < score ) + { + new_score += 10; + } + return new_score; +} + +round_up_score( score, value ) +{ + score = int( score ); + new_score = score - ( score % value ); + if ( new_score < score ) + { + new_score += value; + } + return new_score; +} + +random_tan() +{ + rand = randomint( 100 ); + if ( isDefined( level.char_percent_override ) ) + { + percentnotcharred = level.char_percent_override; + } + else + { + percentnotcharred = 65; + } +} + +places_before_decimal( num ) +{ + abs_num = abs( num ); + count = 0; + while ( 1 ) + { + abs_num *= 0,1; + count += 1; + if ( abs_num < 1 ) + { + return count; + } + } +} + +create_zombie_point_of_interest( attract_dist, num_attractors, added_poi_value, start_turned_on, initial_attract_func, arrival_attract_func, poi_team ) +{ + if ( !isDefined( added_poi_value ) ) + { + self.added_poi_value = 0; + } + else + { + self.added_poi_value = added_poi_value; + } + if ( !isDefined( start_turned_on ) ) + { + start_turned_on = 1; + } + self.script_noteworthy = "zombie_poi"; + self.poi_active = start_turned_on; + if ( isDefined( attract_dist ) ) + { + self.poi_radius = attract_dist * attract_dist; + } + else + { + self.poi_radius = undefined; + } + self.num_poi_attracts = num_attractors; + self.attract_to_origin = 1; + self.attractor_array = []; + self.initial_attract_func = undefined; + self.arrival_attract_func = undefined; + if ( isDefined( poi_team ) ) + { + self._team = poi_team; + } + if ( isDefined( initial_attract_func ) ) + { + self.initial_attract_func = initial_attract_func; + } + if ( isDefined( arrival_attract_func ) ) + { + self.arrival_attract_func = arrival_attract_func; + } +} + +create_zombie_point_of_interest_attractor_positions( num_attract_dists, diff_per_dist, attractor_width ) +{ + self endon( "death" ); + forward = ( 0, 0, 1 ); + if ( !isDefined( self.num_poi_attracts ) || isDefined( self.script_noteworthy ) && self.script_noteworthy != "zombie_poi" ) + { + return; + } + if ( !isDefined( num_attract_dists ) ) + { + num_attract_dists = 4; + } + if ( !isDefined( diff_per_dist ) ) + { + diff_per_dist = 45; + } + if ( !isDefined( attractor_width ) ) + { + attractor_width = 45; + } + self.attract_to_origin = 0; + self.num_attract_dists = num_attract_dists; + self.last_index = []; + i = 0; + while ( i < num_attract_dists ) + { + self.last_index[ i ] = -1; + i++; + } + self.attract_dists = []; + i = 0; + while ( i < self.num_attract_dists ) + { + self.attract_dists[ i ] = diff_per_dist * ( i + 1 ); + i++; + } + max_positions = []; + i = 0; + while ( i < self.num_attract_dists ) + { + max_positions[ i ] = int( ( 6,28 * self.attract_dists[ i ] ) / attractor_width ); + i++; + } + num_attracts_per_dist = self.num_poi_attracts / self.num_attract_dists; + self.max_attractor_dist = self.attract_dists[ self.attract_dists.size - 1 ] * 1,1; + diff = 0; + actual_num_positions = []; + i = 0; + while ( i < self.num_attract_dists ) + { + if ( num_attracts_per_dist > ( max_positions[ i ] + diff ) ) + { + actual_num_positions[ i ] = max_positions[ i ]; + diff += num_attracts_per_dist - max_positions[ i ]; + i++; + continue; + } + else + { + actual_num_positions[ i ] = num_attracts_per_dist + diff; + diff = 0; + } + i++; + } + self.attractor_positions = []; + failed = 0; + angle_offset = 0; + prev_last_index = -1; + j = 0; + while ( j < 4 ) + { + if ( ( actual_num_positions[ j ] + failed ) < max_positions[ j ] ) + { + actual_num_positions[ j ] += failed; + failed = 0; + } + else + { + if ( actual_num_positions[ j ] < max_positions[ j ] ) + { + actual_num_positions[ j ] = max_positions[ j ]; + failed = max_positions[ j ] - actual_num_positions[ j ]; + } + } + failed += self generated_radius_attract_positions( forward, angle_offset, actual_num_positions[ j ], self.attract_dists[ j ] ); + angle_offset += 15; + self.last_index[ j ] = int( ( actual_num_positions[ j ] - failed ) + prev_last_index ); + prev_last_index = self.last_index[ j ]; + j++; + } + self notify( "attractor_positions_generated" ); + level notify( "attractor_positions_generated" ); +} + +generated_radius_attract_positions( forward, offset, num_positions, attract_radius ) +{ + self endon( "death" ); + epsilon = 0,1; + failed = 0; + degs_per_pos = 360 / num_positions; + i = offset; + while ( i < ( 360 + offset ) ) + { + altforward = forward * attract_radius; + rotated_forward = ( ( cos( i ) * altforward[ 0 ] ) - ( sin( i ) * altforward[ 1 ] ), ( sin( i ) * altforward[ 0 ] ) + ( cos( i ) * altforward[ 1 ] ), altforward[ 2 ] ); + if ( isDefined( level.poi_positioning_func ) ) + { + pos = [[ level.poi_positioning_func ]]( self.origin, rotated_forward ); + } + else if ( isDefined( level.use_alternate_poi_positioning ) && level.use_alternate_poi_positioning ) + { + pos = maps/mp/zombies/_zm_server_throttle::server_safe_ground_trace( "poi_trace", 10, self.origin + rotated_forward + vectorScale( ( 0, 0, 1 ), 10 ) ); + } + else + { + pos = maps/mp/zombies/_zm_server_throttle::server_safe_ground_trace( "poi_trace", 10, self.origin + rotated_forward + vectorScale( ( 0, 0, 1 ), 100 ) ); + } + if ( !isDefined( pos ) ) + { + failed++; + } + else if ( isDefined( level.use_alternate_poi_positioning ) && level.use_alternate_poi_positioning ) + { + if ( isDefined( self ) && isDefined( self.origin ) ) + { + if ( self.origin[ 2 ] >= ( pos[ 2 ] - epsilon ) && ( self.origin[ 2 ] - pos[ 2 ] ) <= 150 ) + { + pos_array = []; + pos_array[ 0 ] = pos; + pos_array[ 1 ] = self; + self.attractor_positions[ self.attractor_positions.size ] = pos_array; + } + } + else + { + failed++; + } + } + else + { + if ( abs( pos[ 2 ] - self.origin[ 2 ] ) < 60 ) + { + pos_array = []; + pos_array[ 0 ] = pos; + pos_array[ 1 ] = self; + self.attractor_positions[ self.attractor_positions.size ] = pos_array; + break; + } + else + { + failed++; + } + } + i += degs_per_pos; + } + return failed; +} + +debug_draw_attractor_positions() +{ +/# + while ( 1 ) + { + for ( ;; ) + { + while ( !isDefined( self.attractor_positions ) ) + { + wait 0,05; + } + } + i = 0; + while ( i < self.attractor_positions.size ) + { + line( self.origin, self.attractor_positions[ i ][ 0 ], ( 0, 0, 1 ), 1, 1 ); + i++; + } + wait 0,05; + if ( !isDefined( self ) ) + { + return; + } +#/ + } +} + +get_zombie_point_of_interest( origin, poi_array ) +{ + if ( isDefined( self.ignore_all_poi ) && self.ignore_all_poi ) + { + return undefined; + } + curr_radius = undefined; + if ( isDefined( poi_array ) ) + { + ent_array = poi_array; + } + else + { + ent_array = getentarray( "zombie_poi", "script_noteworthy" ); + } + best_poi = undefined; + position = undefined; + best_dist = 100000000; + i = 0; + while ( i < ent_array.size ) + { + if ( !isDefined( ent_array[ i ].poi_active ) || !ent_array[ i ].poi_active ) + { + i++; + continue; + } + else + { + if ( isDefined( self.ignore_poi_targetname ) && self.ignore_poi_targetname.size > 0 ) + { + if ( isDefined( ent_array[ i ].targetname ) ) + { + ignore = 0; + j = 0; + while ( j < self.ignore_poi_targetname.size ) + { + if ( ent_array[ i ].targetname == self.ignore_poi_targetname[ j ] ) + { + ignore = 1; + break; + } + else + { + j++; + } + } + if ( ignore ) + { + i++; + continue; + } + } + } + else if ( isDefined( self.ignore_poi ) && self.ignore_poi.size > 0 ) + { + ignore = 0; + j = 0; + while ( j < self.ignore_poi.size ) + { + if ( self.ignore_poi[ j ] == ent_array[ i ] ) + { + ignore = 1; + break; + } + else + { + j++; + } + } + if ( ignore ) + { + i++; + continue; + } + } + else + { + dist = distancesquared( origin, ent_array[ i ].origin ); + dist -= ent_array[ i ].added_poi_value; + if ( isDefined( ent_array[ i ].poi_radius ) ) + { + curr_radius = ent_array[ i ].poi_radius; + } + if ( isDefined( curr_radius ) && dist < curr_radius && dist < best_dist && ent_array[ i ] can_attract( self ) ) + { + best_poi = ent_array[ i ]; + best_dist = dist; + } + } + } + i++; + } + if ( isDefined( best_poi ) ) + { + if ( isDefined( best_poi._team ) ) + { + if ( isDefined( self._race_team ) && self._race_team != best_poi._team ) + { + return undefined; + } + } + if ( isDefined( best_poi._new_ground_trace ) && best_poi._new_ground_trace ) + { + position = []; + position[ 0 ] = groundpos_ignore_water_new( best_poi.origin + vectorScale( ( 0, 0, 1 ), 100 ) ); + position[ 1 ] = self; + } + else + { + if ( isDefined( best_poi.attract_to_origin ) && best_poi.attract_to_origin ) + { + position = []; + position[ 0 ] = groundpos( best_poi.origin + vectorScale( ( 0, 0, 1 ), 100 ) ); + position[ 1 ] = self; + } + else + { + position = self add_poi_attractor( best_poi ); + } + } + if ( isDefined( best_poi.initial_attract_func ) ) + { + self thread [[ best_poi.initial_attract_func ]]( best_poi ); + } + if ( isDefined( best_poi.arrival_attract_func ) ) + { + self thread [[ best_poi.arrival_attract_func ]]( best_poi ); + } + } + return position; +} + +activate_zombie_point_of_interest() +{ + if ( self.script_noteworthy != "zombie_poi" ) + { + return; + } + self.poi_active = 1; +} + +deactivate_zombie_point_of_interest() +{ + if ( self.script_noteworthy != "zombie_poi" ) + { + return; + } + i = 0; + while ( i < self.attractor_array.size ) + { + self.attractor_array[ i ] notify( "kill_poi" ); + i++; + } + self.attractor_array = []; + self.claimed_attractor_positions = []; + self.poi_active = 0; +} + +assign_zombie_point_of_interest( origin, poi ) +{ + position = undefined; + doremovalthread = 0; + if ( isDefined( poi ) && poi can_attract( self ) ) + { + if ( !isDefined( poi.attractor_array ) || isDefined( poi.attractor_array ) && array_check_for_dupes( poi.attractor_array, self ) ) + { + doremovalthread = 1; + } + position = self add_poi_attractor( poi ); + if ( isDefined( position ) && doremovalthread && !array_check_for_dupes( poi.attractor_array, self ) ) + { + self thread update_on_poi_removal( poi ); + } + } + return position; +} + +remove_poi_attractor( zombie_poi ) +{ + if ( !isDefined( zombie_poi.attractor_array ) ) + { + return; + } + i = 0; + while ( i < zombie_poi.attractor_array.size ) + { + if ( zombie_poi.attractor_array[ i ] == self ) + { + self notify( "kill_poi" ); + arrayremovevalue( zombie_poi.attractor_array, zombie_poi.attractor_array[ i ] ); + arrayremovevalue( zombie_poi.claimed_attractor_positions, zombie_poi.claimed_attractor_positions[ i ] ); + } + i++; + } +} + +array_check_for_dupes_using_compare( array, single, is_equal_fn ) +{ + i = 0; + while ( i < array.size ) + { + if ( [[ is_equal_fn ]]( array[ i ], single ) ) + { + return 0; + } + i++; + } + return 1; +} + +poi_locations_equal( loc1, loc2 ) +{ + return loc1[ 0 ] == loc2[ 0 ]; +} + +add_poi_attractor( zombie_poi ) +{ + if ( !isDefined( zombie_poi ) ) + { + return; + } + if ( !isDefined( zombie_poi.attractor_array ) ) + { + zombie_poi.attractor_array = []; + } + if ( array_check_for_dupes( zombie_poi.attractor_array, self ) ) + { + if ( !isDefined( zombie_poi.claimed_attractor_positions ) ) + { + zombie_poi.claimed_attractor_positions = []; + } + if ( !isDefined( zombie_poi.attractor_positions ) || zombie_poi.attractor_positions.size <= 0 ) + { + return undefined; + } + start = -1; + end = -1; + last_index = -1; + i = 0; + while ( i < 4 ) + { + if ( zombie_poi.claimed_attractor_positions.size < zombie_poi.last_index[ i ] ) + { + start = last_index + 1; + end = zombie_poi.last_index[ i ]; + break; + } + else + { + last_index = zombie_poi.last_index[ i ]; + i++; + } + } + best_dist = 100000000; + best_pos = undefined; + if ( start < 0 ) + { + start = 0; + } + if ( end < 0 ) + { + return undefined; + } + i = int( start ); + while ( i <= int( end ) ) + { + if ( !isDefined( zombie_poi.attractor_positions[ i ] ) ) + { + i++; + continue; + } + else + { + if ( array_check_for_dupes_using_compare( zombie_poi.claimed_attractor_positions, zombie_poi.attractor_positions[ i ], ::poi_locations_equal ) ) + { + if ( isDefined( zombie_poi.attractor_positions[ i ][ 0 ] ) && isDefined( self.origin ) ) + { + dist = distancesquared( zombie_poi.attractor_positions[ i ][ 0 ], self.origin ); + if ( dist < best_dist || !isDefined( best_pos ) ) + { + best_dist = dist; + best_pos = zombie_poi.attractor_positions[ i ]; + } + } + } + } + i++; + } + if ( !isDefined( best_pos ) ) + { + return undefined; + } + zombie_poi.attractor_array[ zombie_poi.attractor_array.size ] = self; + self thread update_poi_on_death( zombie_poi ); + zombie_poi.claimed_attractor_positions[ zombie_poi.claimed_attractor_positions.size ] = best_pos; + return best_pos; + } + else + { + i = 0; + while ( i < zombie_poi.attractor_array.size ) + { + if ( zombie_poi.attractor_array[ i ] == self ) + { + if ( isDefined( zombie_poi.claimed_attractor_positions ) && isDefined( zombie_poi.claimed_attractor_positions[ i ] ) ) + { + return zombie_poi.claimed_attractor_positions[ i ]; + } + } + i++; + } + } + return undefined; +} + +can_attract( attractor ) +{ + if ( !isDefined( self.attractor_array ) ) + { + self.attractor_array = []; + } + if ( isDefined( self.attracted_array ) && !isinarray( self.attracted_array, attractor ) ) + { + return 0; + } + if ( !array_check_for_dupes( self.attractor_array, attractor ) ) + { + return 1; + } + if ( isDefined( self.num_poi_attracts ) && self.attractor_array.size >= self.num_poi_attracts ) + { + return 0; + } + return 1; +} + +update_poi_on_death( zombie_poi ) +{ + self endon( "kill_poi" ); + self waittill( "death" ); + self remove_poi_attractor( zombie_poi ); +} + +update_on_poi_removal( zombie_poi ) +{ + zombie_poi waittill( "death" ); + if ( !isDefined( zombie_poi.attractor_array ) ) + { + return; + } + i = 0; + while ( i < zombie_poi.attractor_array.size ) + { + if ( zombie_poi.attractor_array[ i ] == self ) + { + arrayremoveindex( zombie_poi.attractor_array, i ); + arrayremoveindex( zombie_poi.claimed_attractor_positions, i ); + } + i++; + } +} + +invalidate_attractor_pos( attractor_pos, zombie ) +{ + if ( !isDefined( self ) || !isDefined( attractor_pos ) ) + { + wait 0,1; + return undefined; + } + if ( isDefined( self.attractor_positions ) && !array_check_for_dupes_using_compare( self.attractor_positions, attractor_pos, ::poi_locations_equal ) ) + { + index = 0; + i = 0; + while ( i < self.attractor_positions.size ) + { + if ( poi_locations_equal( self.attractor_positions[ i ], attractor_pos ) ) + { + index = i; + } + i++; + } + i = 0; + while ( i < self.last_index.size ) + { + if ( index <= self.last_index[ i ] ) + { + self.last_index[ i ]--; + + } + i++; + } + arrayremovevalue( self.attractor_array, zombie ); + arrayremovevalue( self.attractor_positions, attractor_pos ); + i = 0; + while ( i < self.claimed_attractor_positions.size ) + { + if ( self.claimed_attractor_positions[ i ][ 0 ] == attractor_pos[ 0 ] ) + { + arrayremovevalue( self.claimed_attractor_positions, self.claimed_attractor_positions[ i ] ); + } + i++; + } + } + else wait 0,1; + return get_zombie_point_of_interest( zombie.origin ); +} + +remove_poi_from_ignore_list( poi ) +{ + while ( isDefined( self.ignore_poi ) && self.ignore_poi.size > 0 ) + { + i = 0; + while ( i < self.ignore_poi.size ) + { + if ( self.ignore_poi[ i ] == poi ) + { + arrayremovevalue( self.ignore_poi, self.ignore_poi[ i ] ); + return; + } + i++; + } + } +} + +add_poi_to_ignore_list( poi ) +{ + if ( !isDefined( self.ignore_poi ) ) + { + self.ignore_poi = []; + } + add_poi = 1; + while ( self.ignore_poi.size > 0 ) + { + i = 0; + while ( i < self.ignore_poi.size ) + { + if ( self.ignore_poi[ i ] == poi ) + { + add_poi = 0; + break; + } + else + { + i++; + } + } + } + if ( add_poi ) + { + self.ignore_poi[ self.ignore_poi.size ] = poi; + } +} + +default_validate_enemy_path_length( player ) +{ + max_dist = 1296; + d = distancesquared( self.origin, player.origin ); + if ( d <= max_dist ) + { + return 1; + } + return 0; +} + +get_path_length_to_enemy( enemy ) +{ + path_length = self calcpathlength( enemy.origin ); + return path_length; +} + +get_closest_player_using_paths( origin, players ) +{ + min_length_to_player = 9999999; + n_2d_distance_squared = 9999999; + player_to_return = undefined; + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + length_to_player = get_path_length_to_enemy( player ); + if ( isDefined( level.validate_enemy_path_length ) ) + { + if ( length_to_player == 0 ) + { + valid = self thread [[ level.validate_enemy_path_length ]]( player ); + if ( !valid ) + { + i++; + continue; + } + } + } + else if ( length_to_player < min_length_to_player ) + { + min_length_to_player = length_to_player; + player_to_return = player; + n_2d_distance_squared = distance2dsquared( self.origin, player.origin ); + i++; + continue; + } + else + { + if ( length_to_player == min_length_to_player && length_to_player <= 5 ) + { + n_new_distance = distance2dsquared( self.origin, player.origin ); + if ( n_new_distance < n_2d_distance_squared ) + { + min_length_to_player = length_to_player; + player_to_return = player; + n_2d_distance_squared = n_new_distance; + } + } + } + i++; + } + return player_to_return; +} + +get_closest_valid_player( origin, ignore_player ) +{ + valid_player_found = 0; + players = get_players(); + if ( isDefined( level._zombie_using_humangun ) && level._zombie_using_humangun ) + { + players = arraycombine( players, level._zombie_human_array, 0, 0 ); + } + while ( isDefined( ignore_player ) ) + { + i = 0; + while ( i < ignore_player.size ) + { + arrayremovevalue( players, ignore_player[ i ] ); + i++; + } + } + done = 0; + while ( players.size && !done ) + { + done = 1; + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( !is_player_valid( player, 1 ) ) + { + arrayremovevalue( players, player ); + done = 0; + break; + } + else + { + i++; + } + } + } + if ( players.size == 0 ) + { + return undefined; + } + while ( !valid_player_found ) + { + if ( isDefined( self.closest_player_override ) ) + { + player = [[ self.closest_player_override ]]( origin, players ); + } + else if ( isDefined( level.closest_player_override ) ) + { + player = [[ level.closest_player_override ]]( origin, players ); + } + else if ( isDefined( level.calc_closest_player_using_paths ) && level.calc_closest_player_using_paths ) + { + player = get_closest_player_using_paths( origin, players ); + } + else + { + player = getclosest( origin, players ); + } + if ( !isDefined( player ) || players.size == 0 ) + { + return undefined; + } + if ( isDefined( level._zombie_using_humangun ) && level._zombie_using_humangun && isai( player ) ) + { + return player; + } + while ( !is_player_valid( player, 1 ) ) + { + arrayremovevalue( players, player ); + if ( players.size == 0 ) + { + return undefined; + } + } + return player; + } +} + +is_player_valid( player, checkignoremeflag, ignore_laststand_players ) +{ + if ( !isDefined( player ) ) + { + return 0; + } + if ( !isalive( player ) ) + { + return 0; + } + if ( !isplayer( player ) ) + { + return 0; + } + if ( isDefined( player.is_zombie ) && player.is_zombie == 1 ) + { + return 0; + } + if ( player.sessionstate == "spectator" ) + { + return 0; + } + if ( player.sessionstate == "intermission" ) + { + return 0; + } + if ( isDefined( self.intermission ) && self.intermission ) + { + return 0; + } + if ( isDefined( ignore_laststand_players ) && !ignore_laststand_players ) + { + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return 0; + } + } + if ( isDefined( checkignoremeflag ) && checkignoremeflag && player.ignoreme ) + { + return 0; + } + if ( isDefined( level.is_player_valid_override ) ) + { + return [[ level.is_player_valid_override ]]( player ); + } + return 1; +} + +get_number_of_valid_players() +{ + players = get_players(); + num_player_valid = 0; + i = 0; + while ( i < players.size ) + { + if ( is_player_valid( players[ i ] ) ) + { + num_player_valid += 1; + } + i++; + } + return num_player_valid; +} + +in_revive_trigger() +{ + if ( isDefined( self.rt_time ) && ( self.rt_time + 100 ) >= getTime() ) + { + return self.in_rt_cached; + } + self.rt_time = getTime(); + players = level.players; + i = 0; + while ( i < players.size ) + { + current_player = players[ i ]; + if ( isDefined( current_player ) && isDefined( current_player.revivetrigger ) && isalive( current_player ) ) + { + if ( self istouching( current_player.revivetrigger ) ) + { + self.in_rt_cached = 1; + return 1; + } + } + i++; + } + self.in_rt_cached = 0; + return 0; +} + +get_closest_node( org, nodes ) +{ + return getclosest( org, nodes ); +} + +non_destroyed_bar_board_order( origin, chunks ) +{ + first_bars = []; + first_bars1 = []; + first_bars2 = []; + i = 0; + while ( i < chunks.size ) + { + if ( isDefined( chunks[ i ].script_team ) && chunks[ i ].script_team == "classic_boards" ) + { + if ( isDefined( chunks[ i ].script_parameters ) && chunks[ i ].script_parameters == "board" ) + { + return get_closest_2d( origin, chunks ); + } + else + { + if ( isDefined( chunks[ i ].script_team ) && chunks[ i ].script_team != "bar_board_variant1" && chunks[ i ].script_team != "bar_board_variant2" || chunks[ i ].script_team == "bar_board_variant4" && chunks[ i ].script_team == "bar_board_variant5" ) + { + return undefined; + } + } + } + else + { + if ( isDefined( chunks[ i ].script_team ) && chunks[ i ].script_team == "new_barricade" ) + { + if ( isDefined( chunks[ i ].script_parameters ) || chunks[ i ].script_parameters == "repair_board" && chunks[ i ].script_parameters == "barricade_vents" ) + { + return get_closest_2d( origin, chunks ); + } + } + } + i++; + } + i = 0; + while ( i < chunks.size ) + { + if ( isDefined( chunks[ i ].script_team ) || chunks[ i ].script_team == "6_bars_bent" && chunks[ i ].script_team == "6_bars_prestine" ) + { + if ( isDefined( chunks[ i ].script_parameters ) && chunks[ i ].script_parameters == "bar" ) + { + if ( isDefined( chunks[ i ].script_noteworthy ) ) + { + if ( chunks[ i ].script_noteworthy == "4" || chunks[ i ].script_noteworthy == "6" ) + { + first_bars[ first_bars.size ] = chunks[ i ]; + } + } + } + } + i++; + } + i = 0; + while ( i < first_bars.size ) + { + if ( isDefined( chunks[ i ].script_team ) || chunks[ i ].script_team == "6_bars_bent" && chunks[ i ].script_team == "6_bars_prestine" ) + { + if ( isDefined( chunks[ i ].script_parameters ) && chunks[ i ].script_parameters == "bar" ) + { + if ( !first_bars[ i ].destroyed ) + { + return first_bars[ i ]; + } + } + } + i++; + } + i = 0; + while ( i < chunks.size ) + { + if ( isDefined( chunks[ i ].script_team ) || chunks[ i ].script_team == "6_bars_bent" && chunks[ i ].script_team == "6_bars_prestine" ) + { + if ( isDefined( chunks[ i ].script_parameters ) && chunks[ i ].script_parameters == "bar" ) + { + if ( !chunks[ i ].destroyed ) + { + return get_closest_2d( origin, chunks ); + } + } + } + i++; + } +} + +non_destroyed_grate_order( origin, chunks_grate ) +{ + grate_order = []; + grate_order1 = []; + grate_order2 = []; + grate_order3 = []; + grate_order4 = []; + grate_order5 = []; + grate_order6 = []; + while ( isDefined( chunks_grate ) ) + { + i = 0; + while ( i < chunks_grate.size ) + { + if ( isDefined( chunks_grate[ i ].script_parameters ) && chunks_grate[ i ].script_parameters == "grate" ) + { + if ( isDefined( chunks_grate[ i ].script_noteworthy ) && chunks_grate[ i ].script_noteworthy == "1" ) + { + grate_order1[ grate_order1.size ] = chunks_grate[ i ]; + } + if ( isDefined( chunks_grate[ i ].script_noteworthy ) && chunks_grate[ i ].script_noteworthy == "2" ) + { + grate_order2[ grate_order2.size ] = chunks_grate[ i ]; + } + if ( isDefined( chunks_grate[ i ].script_noteworthy ) && chunks_grate[ i ].script_noteworthy == "3" ) + { + grate_order3[ grate_order3.size ] = chunks_grate[ i ]; + } + if ( isDefined( chunks_grate[ i ].script_noteworthy ) && chunks_grate[ i ].script_noteworthy == "4" ) + { + grate_order4[ grate_order4.size ] = chunks_grate[ i ]; + } + if ( isDefined( chunks_grate[ i ].script_noteworthy ) && chunks_grate[ i ].script_noteworthy == "5" ) + { + grate_order5[ grate_order5.size ] = chunks_grate[ i ]; + } + if ( isDefined( chunks_grate[ i ].script_noteworthy ) && chunks_grate[ i ].script_noteworthy == "6" ) + { + grate_order6[ grate_order6.size ] = chunks_grate[ i ]; + } + } + i++; + } + i = 0; + while ( i < chunks_grate.size ) + { + if ( isDefined( chunks_grate[ i ].script_parameters ) && chunks_grate[ i ].script_parameters == "grate" ) + { + if ( isDefined( grate_order1[ i ] ) ) + { + if ( grate_order1[ i ].state == "repaired" ) + { + grate_order2[ i ] thread show_grate_pull(); + return grate_order1[ i ]; + } + if ( grate_order2[ i ].state == "repaired" ) + { +/# + iprintlnbold( " pull bar2 " ); +#/ + grate_order3[ i ] thread show_grate_pull(); + return grate_order2[ i ]; + } + else + { + if ( grate_order3[ i ].state == "repaired" ) + { +/# + iprintlnbold( " pull bar3 " ); +#/ + grate_order4[ i ] thread show_grate_pull(); + return grate_order3[ i ]; + } + else + { + if ( grate_order4[ i ].state == "repaired" ) + { +/# + iprintlnbold( " pull bar4 " ); +#/ + grate_order5[ i ] thread show_grate_pull(); + return grate_order4[ i ]; + } + else + { + if ( grate_order5[ i ].state == "repaired" ) + { +/# + iprintlnbold( " pull bar5 " ); +#/ + grate_order6[ i ] thread show_grate_pull(); + return grate_order5[ i ]; + } + else + { + if ( grate_order6[ i ].state == "repaired" ) + { + return grate_order6[ i ]; + } + } + } + } + } + } + } + i++; + } + } +} + +non_destroyed_variant1_order( origin, chunks_variant1 ) +{ + variant1_order = []; + variant1_order1 = []; + variant1_order2 = []; + variant1_order3 = []; + variant1_order4 = []; + variant1_order5 = []; + variant1_order6 = []; + while ( isDefined( chunks_variant1 ) ) + { + i = 0; + while ( i < chunks_variant1.size ) + { + if ( isDefined( chunks_variant1[ i ].script_team ) && chunks_variant1[ i ].script_team == "bar_board_variant1" ) + { + if ( isDefined( chunks_variant1[ i ].script_noteworthy ) ) + { + if ( chunks_variant1[ i ].script_noteworthy == "1" ) + { + variant1_order1[ variant1_order1.size ] = chunks_variant1[ i ]; + } + if ( chunks_variant1[ i ].script_noteworthy == "2" ) + { + variant1_order2[ variant1_order2.size ] = chunks_variant1[ i ]; + } + if ( chunks_variant1[ i ].script_noteworthy == "3" ) + { + variant1_order3[ variant1_order3.size ] = chunks_variant1[ i ]; + } + if ( chunks_variant1[ i ].script_noteworthy == "4" ) + { + variant1_order4[ variant1_order4.size ] = chunks_variant1[ i ]; + } + if ( chunks_variant1[ i ].script_noteworthy == "5" ) + { + variant1_order5[ variant1_order5.size ] = chunks_variant1[ i ]; + } + if ( chunks_variant1[ i ].script_noteworthy == "6" ) + { + variant1_order6[ variant1_order6.size ] = chunks_variant1[ i ]; + } + } + } + i++; + } + i = 0; + while ( i < chunks_variant1.size ) + { + if ( isDefined( chunks_variant1[ i ].script_team ) && chunks_variant1[ i ].script_team == "bar_board_variant1" ) + { + if ( isDefined( variant1_order2[ i ] ) ) + { + if ( variant1_order2[ i ].state == "repaired" ) + { + return variant1_order2[ i ]; + } + else + { + if ( variant1_order3[ i ].state == "repaired" ) + { + return variant1_order3[ i ]; + } + else + { + if ( variant1_order4[ i ].state == "repaired" ) + { + return variant1_order4[ i ]; + } + else + { + if ( variant1_order6[ i ].state == "repaired" ) + { + return variant1_order6[ i ]; + } + else + { + if ( variant1_order5[ i ].state == "repaired" ) + { + return variant1_order5[ i ]; + } + else + { + if ( variant1_order1[ i ].state == "repaired" ) + { + return variant1_order1[ i ]; + } + } + } + } + } + } + } + } + i++; + } + } +} + +non_destroyed_variant2_order( origin, chunks_variant2 ) +{ + variant2_order = []; + variant2_order1 = []; + variant2_order2 = []; + variant2_order3 = []; + variant2_order4 = []; + variant2_order5 = []; + variant2_order6 = []; + while ( isDefined( chunks_variant2 ) ) + { + i = 0; + while ( i < chunks_variant2.size ) + { + if ( isDefined( chunks_variant2[ i ].script_team ) && chunks_variant2[ i ].script_team == "bar_board_variant2" ) + { + if ( isDefined( chunks_variant2[ i ].script_noteworthy ) && chunks_variant2[ i ].script_noteworthy == "1" ) + { + variant2_order1[ variant2_order1.size ] = chunks_variant2[ i ]; + } + if ( isDefined( chunks_variant2[ i ].script_noteworthy ) && chunks_variant2[ i ].script_noteworthy == "2" ) + { + variant2_order2[ variant2_order2.size ] = chunks_variant2[ i ]; + } + if ( isDefined( chunks_variant2[ i ].script_noteworthy ) && chunks_variant2[ i ].script_noteworthy == "3" ) + { + variant2_order3[ variant2_order3.size ] = chunks_variant2[ i ]; + } + if ( isDefined( chunks_variant2[ i ].script_noteworthy ) && chunks_variant2[ i ].script_noteworthy == "4" ) + { + variant2_order4[ variant2_order4.size ] = chunks_variant2[ i ]; + } + if ( isDefined( chunks_variant2[ i ].script_noteworthy ) && chunks_variant2[ i ].script_noteworthy == "5" && isDefined( chunks_variant2[ i ].script_location ) && chunks_variant2[ i ].script_location == "5" ) + { + variant2_order5[ variant2_order5.size ] = chunks_variant2[ i ]; + } + if ( isDefined( chunks_variant2[ i ].script_noteworthy ) && chunks_variant2[ i ].script_noteworthy == "5" && isDefined( chunks_variant2[ i ].script_location ) && chunks_variant2[ i ].script_location == "6" ) + { + variant2_order6[ variant2_order6.size ] = chunks_variant2[ i ]; + } + } + i++; + } + i = 0; + while ( i < chunks_variant2.size ) + { + if ( isDefined( chunks_variant2[ i ].script_team ) && chunks_variant2[ i ].script_team == "bar_board_variant2" ) + { + if ( isDefined( variant2_order1[ i ] ) ) + { + if ( variant2_order1[ i ].state == "repaired" ) + { + return variant2_order1[ i ]; + } + else + { + if ( variant2_order2[ i ].state == "repaired" ) + { + return variant2_order2[ i ]; + } + else + { + if ( variant2_order3[ i ].state == "repaired" ) + { + return variant2_order3[ i ]; + } + else + { + if ( variant2_order5[ i ].state == "repaired" ) + { + return variant2_order5[ i ]; + } + else + { + if ( variant2_order4[ i ].state == "repaired" ) + { + return variant2_order4[ i ]; + } + else + { + if ( variant2_order6[ i ].state == "repaired" ) + { + return variant2_order6[ i ]; + } + } + } + } + } + } + } + } + i++; + } + } +} + +non_destroyed_variant4_order( origin, chunks_variant4 ) +{ + variant4_order = []; + variant4_order1 = []; + variant4_order2 = []; + variant4_order3 = []; + variant4_order4 = []; + variant4_order5 = []; + variant4_order6 = []; + while ( isDefined( chunks_variant4 ) ) + { + i = 0; + while ( i < chunks_variant4.size ) + { + if ( isDefined( chunks_variant4[ i ].script_team ) && chunks_variant4[ i ].script_team == "bar_board_variant4" ) + { + if ( isDefined( chunks_variant4[ i ].script_noteworthy ) && chunks_variant4[ i ].script_noteworthy == "1" && !isDefined( chunks_variant4[ i ].script_location ) ) + { + variant4_order1[ variant4_order1.size ] = chunks_variant4[ i ]; + } + if ( isDefined( chunks_variant4[ i ].script_noteworthy ) && chunks_variant4[ i ].script_noteworthy == "2" ) + { + variant4_order2[ variant4_order2.size ] = chunks_variant4[ i ]; + } + if ( isDefined( chunks_variant4[ i ].script_noteworthy ) && chunks_variant4[ i ].script_noteworthy == "3" ) + { + variant4_order3[ variant4_order3.size ] = chunks_variant4[ i ]; + } + if ( isDefined( chunks_variant4[ i ].script_noteworthy ) && chunks_variant4[ i ].script_noteworthy == "1" && isDefined( chunks_variant4[ i ].script_location ) && chunks_variant4[ i ].script_location == "3" ) + { + variant4_order4[ variant4_order4.size ] = chunks_variant4[ i ]; + } + if ( isDefined( chunks_variant4[ i ].script_noteworthy ) && chunks_variant4[ i ].script_noteworthy == "5" ) + { + variant4_order5[ variant4_order5.size ] = chunks_variant4[ i ]; + } + if ( isDefined( chunks_variant4[ i ].script_noteworthy ) && chunks_variant4[ i ].script_noteworthy == "6" ) + { + variant4_order6[ variant4_order6.size ] = chunks_variant4[ i ]; + } + } + i++; + } + i = 0; + while ( i < chunks_variant4.size ) + { + if ( isDefined( chunks_variant4[ i ].script_team ) && chunks_variant4[ i ].script_team == "bar_board_variant4" ) + { + if ( isDefined( variant4_order1[ i ] ) ) + { + if ( variant4_order1[ i ].state == "repaired" ) + { + return variant4_order1[ i ]; + } + else + { + if ( variant4_order6[ i ].state == "repaired" ) + { + return variant4_order6[ i ]; + } + else + { + if ( variant4_order3[ i ].state == "repaired" ) + { + return variant4_order3[ i ]; + } + else + { + if ( variant4_order4[ i ].state == "repaired" ) + { + return variant4_order4[ i ]; + } + else + { + if ( variant4_order2[ i ].state == "repaired" ) + { + return variant4_order2[ i ]; + } + else + { + if ( variant4_order5[ i ].state == "repaired" ) + { + return variant4_order5[ i ]; + } + } + } + } + } + } + } + } + i++; + } + } +} + +non_destroyed_variant5_order( origin, chunks_variant5 ) +{ + variant5_order = []; + variant5_order1 = []; + variant5_order2 = []; + variant5_order3 = []; + variant5_order4 = []; + variant5_order5 = []; + variant5_order6 = []; + while ( isDefined( chunks_variant5 ) ) + { + i = 0; + while ( i < chunks_variant5.size ) + { + if ( isDefined( chunks_variant5[ i ].script_team ) && chunks_variant5[ i ].script_team == "bar_board_variant5" ) + { + if ( isDefined( chunks_variant5[ i ].script_noteworthy ) ) + { + if ( chunks_variant5[ i ].script_noteworthy == "1" && !isDefined( chunks_variant5[ i ].script_location ) ) + { + variant5_order1[ variant5_order1.size ] = chunks_variant5[ i ]; + } + if ( chunks_variant5[ i ].script_noteworthy == "2" ) + { + variant5_order2[ variant5_order2.size ] = chunks_variant5[ i ]; + } + if ( isDefined( chunks_variant5[ i ].script_noteworthy ) && chunks_variant5[ i ].script_noteworthy == "1" && isDefined( chunks_variant5[ i ].script_location ) && chunks_variant5[ i ].script_location == "3" ) + { + variant5_order3[ variant5_order3.size ] = chunks_variant5[ i ]; + } + if ( chunks_variant5[ i ].script_noteworthy == "4" ) + { + variant5_order4[ variant5_order4.size ] = chunks_variant5[ i ]; + } + if ( chunks_variant5[ i ].script_noteworthy == "5" ) + { + variant5_order5[ variant5_order5.size ] = chunks_variant5[ i ]; + } + if ( chunks_variant5[ i ].script_noteworthy == "6" ) + { + variant5_order6[ variant5_order6.size ] = chunks_variant5[ i ]; + } + } + } + i++; + } + i = 0; + while ( i < chunks_variant5.size ) + { + if ( isDefined( chunks_variant5[ i ].script_team ) && chunks_variant5[ i ].script_team == "bar_board_variant5" ) + { + if ( isDefined( variant5_order1[ i ] ) ) + { + if ( variant5_order1[ i ].state == "repaired" ) + { + return variant5_order1[ i ]; + } + else + { + if ( variant5_order6[ i ].state == "repaired" ) + { + return variant5_order6[ i ]; + } + else + { + if ( variant5_order3[ i ].state == "repaired" ) + { + return variant5_order3[ i ]; + } + else + { + if ( variant5_order2[ i ].state == "repaired" ) + { + return variant5_order2[ i ]; + } + else + { + if ( variant5_order5[ i ].state == "repaired" ) + { + return variant5_order5[ i ]; + } + else + { + if ( variant5_order4[ i ].state == "repaired" ) + { + return variant5_order4[ i ]; + } + } + } + } + } + } + } + } + i++; + } + } +} + +show_grate_pull() +{ + wait 0,53; + self show(); + self vibrate( vectorScale( ( 0, 0, 1 ), 270 ), 0,2, 0,4, 0,4 ); +} + +get_closest_2d( origin, ents ) +{ + if ( !isDefined( ents ) ) + { + return undefined; + } + dist = distance2d( origin, ents[ 0 ].origin ); + index = 0; + temp_array = []; + i = 1; + while ( i < ents.size ) + { + if ( isDefined( ents[ i ].unbroken ) && ents[ i ].unbroken == 1 ) + { + ents[ i ].index = i; + temp_array[ temp_array.size ] = ents[ i ]; + } + i++; + } + if ( temp_array.size > 0 ) + { + index = temp_array[ randomintrange( 0, temp_array.size ) ].index; + return ents[ index ]; + } + else + { + i = 1; + while ( i < ents.size ) + { + temp_dist = distance2d( origin, ents[ i ].origin ); + if ( temp_dist < dist ) + { + dist = temp_dist; + index = i; + } + i++; + } + return ents[ index ]; + } +} + +disable_trigger() +{ + if ( !isDefined( self.disabled ) || !self.disabled ) + { + self.disabled = 1; + self.origin -= vectorScale( ( 0, 0, 1 ), 10000 ); + } +} + +enable_trigger() +{ + if ( !isDefined( self.disabled ) || !self.disabled ) + { + return; + } + self.disabled = 0; + self.origin += vectorScale( ( 0, 0, 1 ), 10000 ); +} + +in_playable_area() +{ + playable_area = getentarray( "player_volume", "script_noteworthy" ); + if ( !isDefined( playable_area ) ) + { +/# + println( "No playable area playable_area found! Assume EVERYWHERE is PLAYABLE" ); +#/ + return 1; + } + i = 0; + while ( i < playable_area.size ) + { + if ( self istouching( playable_area[ i ] ) ) + { + return 1; + } + i++; + } + return 0; +} + +get_closest_non_destroyed_chunk( origin, barrier, barrier_chunks ) +{ + chunks = undefined; + chunks_grate = undefined; + chunks_grate = get_non_destroyed_chunks_grate( barrier, barrier_chunks ); + chunks = get_non_destroyed_chunks( barrier, barrier_chunks ); + if ( isDefined( barrier.zbarrier ) ) + { + if ( isDefined( chunks ) ) + { + return array_randomize( chunks )[ 0 ]; + } + if ( isDefined( chunks_grate ) ) + { + return array_randomize( chunks_grate )[ 0 ]; + } + } + else + { + if ( isDefined( chunks ) ) + { + return non_destroyed_bar_board_order( origin, chunks ); + } + else + { + if ( isDefined( chunks_grate ) ) + { + return non_destroyed_grate_order( origin, chunks_grate ); + } + } + } + return undefined; +} + +get_random_destroyed_chunk( barrier, barrier_chunks ) +{ + if ( isDefined( barrier.zbarrier ) ) + { + ret = undefined; + pieces = barrier.zbarrier getzbarrierpieceindicesinstate( "open" ); + if ( pieces.size ) + { + ret = array_randomize( pieces )[ 0 ]; + } + return ret; + } + else + { + chunk = undefined; + chunks_repair_grate = undefined; + chunks = get_destroyed_chunks( barrier_chunks ); + chunks_repair_grate = get_destroyed_repair_grates( barrier_chunks ); + if ( isDefined( chunks ) ) + { + return chunks[ randomint( chunks.size ) ]; + } + else + { + if ( isDefined( chunks_repair_grate ) ) + { + return grate_order_destroyed( chunks_repair_grate ); + } + } + return undefined; + } +} + +get_destroyed_repair_grates( barrier_chunks ) +{ + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( isDefined( barrier_chunks[ i ] ) ) + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "grate" ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; +} + +get_non_destroyed_chunks( barrier, barrier_chunks ) +{ + if ( isDefined( barrier.zbarrier ) ) + { + return barrier.zbarrier getzbarrierpieceindicesinstate( "closed" ); + } + else + { + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "classic_boards" ) + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "board" ) + { + if ( barrier_chunks[ i ] get_chunk_state() == "repaired" ) + { + if ( barrier_chunks[ i ].origin == barrier_chunks[ i ].og_origin ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + } + } + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "new_barricade" ) + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) || barrier_chunks[ i ].script_parameters == "repair_board" && barrier_chunks[ i ].script_parameters == "barricade_vents" ) + { + if ( barrier_chunks[ i ] get_chunk_state() == "repaired" ) + { + if ( barrier_chunks[ i ].origin == barrier_chunks[ i ].og_origin ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + } + i++; + continue; + } + else + { + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "6_bars_bent" ) + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "bar" ) + { + if ( barrier_chunks[ i ] get_chunk_state() == "repaired" ) + { + if ( barrier_chunks[ i ].origin == barrier_chunks[ i ].og_origin ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + } + i++; + continue; + } + else + { + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "6_bars_prestine" ) + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "bar" ) + { + if ( barrier_chunks[ i ] get_chunk_state() == "repaired" ) + { + if ( barrier_chunks[ i ].origin == barrier_chunks[ i ].og_origin ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + } + } + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; + } +} + +get_non_destroyed_chunks_grate( barrier, barrier_chunks ) +{ + if ( isDefined( barrier.zbarrier ) ) + { + return barrier.zbarrier getzbarrierpieceindicesinstate( "closed" ); + } + else + { + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "grate" ) + { + if ( isDefined( barrier_chunks[ i ] ) ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; + } +} + +get_non_destroyed_variant1( barrier_chunks ) +{ + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "bar_board_variant1" ) + { + if ( isDefined( barrier_chunks[ i ] ) ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; +} + +get_non_destroyed_variant2( barrier_chunks ) +{ + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "bar_board_variant2" ) + { + if ( isDefined( barrier_chunks[ i ] ) ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; +} + +get_non_destroyed_variant4( barrier_chunks ) +{ + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "bar_board_variant4" ) + { + if ( isDefined( barrier_chunks[ i ] ) ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; +} + +get_non_destroyed_variant5( barrier_chunks ) +{ + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( isDefined( barrier_chunks[ i ].script_team ) && barrier_chunks[ i ].script_team == "bar_board_variant5" ) + { + if ( isDefined( barrier_chunks[ i ] ) ) + { + array[ array.size ] = barrier_chunks[ i ]; + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; +} + +get_destroyed_chunks( barrier_chunks ) +{ + array = []; + i = 0; + while ( i < barrier_chunks.size ) + { + if ( barrier_chunks[ i ] get_chunk_state() == "destroyed" ) + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "board" ) + { + array[ array.size ] = barrier_chunks[ i ]; + i++; + continue; + } + else + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) || barrier_chunks[ i ].script_parameters == "repair_board" && barrier_chunks[ i ].script_parameters == "barricade_vents" ) + { + array[ array.size ] = barrier_chunks[ i ]; + i++; + continue; + } + else + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "bar" ) + { + array[ array.size ] = barrier_chunks[ i ]; + i++; + continue; + } + else + { + if ( isDefined( barrier_chunks[ i ].script_parameters ) && barrier_chunks[ i ].script_parameters == "grate" ) + { + return undefined; + } + } + } + } + } + i++; + } + if ( array.size == 0 ) + { + return undefined; + } + return array; +} + +grate_order_destroyed( chunks_repair_grate ) +{ + grate_repair_order = []; + grate_repair_order1 = []; + grate_repair_order2 = []; + grate_repair_order3 = []; + grate_repair_order4 = []; + grate_repair_order5 = []; + grate_repair_order6 = []; + i = 0; + while ( i < chunks_repair_grate.size ) + { + if ( isDefined( chunks_repair_grate[ i ].script_parameters ) && chunks_repair_grate[ i ].script_parameters == "grate" ) + { + if ( isDefined( chunks_repair_grate[ i ].script_noteworthy ) && chunks_repair_grate[ i ].script_noteworthy == "1" ) + { + grate_repair_order1[ grate_repair_order1.size ] = chunks_repair_grate[ i ]; + } + if ( isDefined( chunks_repair_grate[ i ].script_noteworthy ) && chunks_repair_grate[ i ].script_noteworthy == "2" ) + { + grate_repair_order2[ grate_repair_order2.size ] = chunks_repair_grate[ i ]; + } + if ( isDefined( chunks_repair_grate[ i ].script_noteworthy ) && chunks_repair_grate[ i ].script_noteworthy == "3" ) + { + grate_repair_order3[ grate_repair_order3.size ] = chunks_repair_grate[ i ]; + } + if ( isDefined( chunks_repair_grate[ i ].script_noteworthy ) && chunks_repair_grate[ i ].script_noteworthy == "4" ) + { + grate_repair_order4[ grate_repair_order4.size ] = chunks_repair_grate[ i ]; + } + if ( isDefined( chunks_repair_grate[ i ].script_noteworthy ) && chunks_repair_grate[ i ].script_noteworthy == "5" ) + { + grate_repair_order5[ grate_repair_order5.size ] = chunks_repair_grate[ i ]; + } + if ( isDefined( chunks_repair_grate[ i ].script_noteworthy ) && chunks_repair_grate[ i ].script_noteworthy == "6" ) + { + grate_repair_order6[ grate_repair_order6.size ] = chunks_repair_grate[ i ]; + } + } + i++; + } + i = 0; + while ( i < chunks_repair_grate.size ) + { + if ( isDefined( chunks_repair_grate[ i ].script_parameters ) && chunks_repair_grate[ i ].script_parameters == "grate" ) + { + if ( isDefined( grate_repair_order1[ i ] ) ) + { + if ( grate_repair_order6[ i ].state == "destroyed" ) + { +/# + iprintlnbold( " Fix grate6 " ); +#/ + return grate_repair_order6[ i ]; + } + if ( grate_repair_order5[ i ].state == "destroyed" ) + { +/# + iprintlnbold( " Fix grate5 " ); +#/ + grate_repair_order6[ i ] thread show_grate_repair(); + return grate_repair_order5[ i ]; + } + else + { + if ( grate_repair_order4[ i ].state == "destroyed" ) + { +/# + iprintlnbold( " Fix grate4 " ); +#/ + grate_repair_order5[ i ] thread show_grate_repair(); + return grate_repair_order4[ i ]; + } + else + { + if ( grate_repair_order3[ i ].state == "destroyed" ) + { +/# + iprintlnbold( " Fix grate3 " ); +#/ + grate_repair_order4[ i ] thread show_grate_repair(); + return grate_repair_order3[ i ]; + } + else + { + if ( grate_repair_order2[ i ].state == "destroyed" ) + { +/# + iprintlnbold( " Fix grate2 " ); +#/ + grate_repair_order3[ i ] thread show_grate_repair(); + return grate_repair_order2[ i ]; + } + else + { + if ( grate_repair_order1[ i ].state == "destroyed" ) + { +/# + iprintlnbold( " Fix grate1 " ); +#/ + grate_repair_order2[ i ] thread show_grate_repair(); + return grate_repair_order1[ i ]; + } + } + } + } + } + } + } + i++; + } +} + +show_grate_repair() +{ + wait 0,34; + self hide(); +} + +get_chunk_state() +{ +/# + assert( isDefined( self.state ) ); +#/ + return self.state; +} + +is_float( num ) +{ + val = num - int( num ); + if ( val != 0 ) + { + return 1; + } + else + { + return 0; + } +} + +array_limiter( array, total ) +{ + new_array = []; + i = 0; + while ( i < array.size ) + { + if ( i < total ) + { + new_array[ new_array.size ] = array[ i ]; + } + i++; + } + return new_array; +} + +array_validate( array ) +{ + if ( isDefined( array ) && array.size > 0 ) + { + return 1; + } + else + { + return 0; + } +} + +add_spawner( spawner ) +{ + if ( isDefined( spawner.script_start ) && level.round_number < spawner.script_start ) + { + return; + } + if ( isDefined( spawner.is_enabled ) && !spawner.is_enabled ) + { + return; + } + if ( isDefined( spawner.has_been_added ) && spawner.has_been_added ) + { + return; + } + spawner.has_been_added = 1; + level.zombie_spawn_locations[ level.zombie_spawn_locations.size ] = spawner; +} + +fake_physicslaunch( target_pos, power ) +{ + start_pos = self.origin; + gravity = getDvarInt( "bg_gravity" ) * -1; + dist = distance( start_pos, target_pos ); + time = dist / power; + delta = target_pos - start_pos; + drop = ( 0,5 * gravity ) * ( time * time ); + velocity = ( delta[ 0 ] / time, delta[ 1 ] / time, ( delta[ 2 ] - drop ) / time ); + level thread draw_line_ent_to_pos( self, target_pos ); + self movegravity( velocity, time ); + return time; +} + +add_zombie_hint( ref, text ) +{ + if ( !isDefined( level.zombie_hints ) ) + { + level.zombie_hints = []; + } + precachestring( text ); + level.zombie_hints[ ref ] = text; +} + +get_zombie_hint( ref ) +{ + if ( isDefined( level.zombie_hints[ ref ] ) ) + { + return level.zombie_hints[ ref ]; + } +/# + println( "UNABLE TO FIND HINT STRING " + ref ); +#/ + return level.zombie_hints[ "undefined" ]; +} + +set_hint_string( ent, default_ref, cost ) +{ + ref = default_ref; + if ( isDefined( ent.script_hint ) ) + { + ref = ent.script_hint; + } + if ( isDefined( level.legacy_hint_system ) && level.legacy_hint_system ) + { + ref = ( ref + "_" ) + cost; + self sethintstring( get_zombie_hint( ref ) ); + } + else + { + hint = get_zombie_hint( ref ); + if ( isDefined( cost ) ) + { + self sethintstring( hint, cost ); + return; + } + else + { + self sethintstring( hint ); + } + } +} + +get_hint_string( ent, default_ref, cost ) +{ + ref = default_ref; + if ( isDefined( ent.script_hint ) ) + { + ref = ent.script_hint; + } + if ( isDefined( level.legacy_hint_system ) && level.legacy_hint_system && isDefined( cost ) ) + { + ref = ( ref + "_" ) + cost; + } + return get_zombie_hint( ref ); +} + +unitrigger_set_hint_string( ent, default_ref, cost ) +{ + triggers = []; + if ( self.trigger_per_player ) + { + triggers = self.playertrigger; + } + else + { + triggers[ 0 ] = self.trigger; + } + _a3000 = triggers; + _k3000 = getFirstArrayKey( _a3000 ); + while ( isDefined( _k3000 ) ) + { + trigger = _a3000[ _k3000 ]; + ref = default_ref; + if ( isDefined( ent.script_hint ) ) + { + ref = ent.script_hint; + } + if ( isDefined( level.legacy_hint_system ) && level.legacy_hint_system ) + { + ref = ( ref + "_" ) + cost; + trigger sethintstring( get_zombie_hint( ref ) ); + } + else + { + hint = get_zombie_hint( ref ); + if ( isDefined( cost ) ) + { + trigger sethintstring( hint, cost ); + break; + } + else + { + trigger sethintstring( hint ); + } + } + _k3000 = getNextArrayKey( _a3000, _k3000 ); + } +} + +add_sound( ref, alias ) +{ + if ( !isDefined( level.zombie_sounds ) ) + { + level.zombie_sounds = []; + } + level.zombie_sounds[ ref ] = alias; +} + +play_sound_at_pos( ref, pos, ent ) +{ + if ( isDefined( ent ) ) + { + if ( isDefined( ent.script_soundalias ) ) + { + playsoundatposition( ent.script_soundalias, pos ); + return; + } + if ( isDefined( self.script_sound ) ) + { + ref = self.script_sound; + } + } + if ( ref == "none" ) + { + return; + } + if ( !isDefined( level.zombie_sounds[ ref ] ) ) + { +/# + assertmsg( "Sound "" + ref + "" was not put to the zombie sounds list, please use add_sound( ref, alias ) at the start of your level." ); +#/ + return; + } + playsoundatposition( level.zombie_sounds[ ref ], pos ); +} + +play_sound_on_ent( ref ) +{ + if ( isDefined( self.script_soundalias ) ) + { + self playsound( self.script_soundalias ); + return; + } + if ( isDefined( self.script_sound ) ) + { + ref = self.script_sound; + } + if ( ref == "none" ) + { + return; + } + if ( !isDefined( level.zombie_sounds[ ref ] ) ) + { +/# + assertmsg( "Sound "" + ref + "" was not put to the zombie sounds list, please use add_sound( ref, alias ) at the start of your level." ); +#/ + return; + } + self playsound( level.zombie_sounds[ ref ] ); +} + +play_loopsound_on_ent( ref ) +{ + if ( isDefined( self.script_firefxsound ) ) + { + ref = self.script_firefxsound; + } + if ( ref == "none" ) + { + return; + } + if ( !isDefined( level.zombie_sounds[ ref ] ) ) + { +/# + assertmsg( "Sound "" + ref + "" was not put to the zombie sounds list, please use add_sound( ref, alias ) at the start of your level." ); +#/ + return; + } + self playsound( level.zombie_sounds[ ref ] ); +} + +string_to_float( string ) +{ + floatparts = strtok( string, "." ); + if ( floatparts.size == 1 ) + { + return int( floatparts[ 0 ] ); + } + whole = int( floatparts[ 0 ] ); + decimal = 0; + i = floatparts[ 1 ].size - 1; + while ( i >= 0 ) + { + decimal = ( decimal / 10 ) + ( int( floatparts[ 1 ][ i ] ) / 10 ); + i--; + + } + if ( whole >= 0 ) + { + return whole + decimal; + } + else + { + return whole - decimal; + } +} + +onplayerconnect_callback( func ) +{ + addcallback( "on_player_connect", func ); +} + +onplayerdisconnect_callback( func ) +{ + addcallback( "on_player_disconnect", func ); +} + +set_zombie_var( var, value, is_float, column, is_team_based ) +{ + if ( !isDefined( is_float ) ) + { + is_float = 0; + } + if ( !isDefined( column ) ) + { + column = 1; + } + table = "mp/zombiemode.csv"; + table_value = tablelookup( table, 0, var, column ); + if ( isDefined( table_value ) && table_value != "" ) + { + if ( is_float ) + { + value = float( table_value ); + } + else + { + value = int( table_value ); + } + } + if ( isDefined( is_team_based ) && is_team_based ) + { + _a3185 = level.teams; + _k3185 = getFirstArrayKey( _a3185 ); + while ( isDefined( _k3185 ) ) + { + team = _a3185[ _k3185 ]; + level.zombie_vars[ team ][ var ] = value; + _k3185 = getNextArrayKey( _a3185, _k3185 ); + } + } + else level.zombie_vars[ var ] = value; + return value; +} + +get_table_var( table, var_name, value, is_float, column ) +{ + if ( !isDefined( table ) ) + { + table = "mp/zombiemode.csv"; + } + if ( !isDefined( is_float ) ) + { + is_float = 0; + } + if ( !isDefined( column ) ) + { + column = 1; + } + table_value = tablelookup( table, 0, var_name, column ); + if ( isDefined( table_value ) && table_value != "" ) + { + if ( is_float ) + { + value = string_to_float( table_value ); + } + else + { + value = int( table_value ); + } + } + return value; +} + +hudelem_count() +{ +/# + max = 0; + curr_total = 0; + while ( 1 ) + { + if ( level.hudelem_count > max ) + { + max = level.hudelem_count; + } + println( "HudElems: " + level.hudelem_count + "[Peak: " + max + "]" ); + wait 0,05; +#/ + } +} + +debug_round_advancer() +{ +/# + while ( 1 ) + { + zombs = get_round_enemy_array(); + i = 0; + while ( i < zombs.size ) + { + zombs[ i ] dodamage( zombs[ i ].health + 666, ( 0, 0, 1 ) ); + wait 0,5; + i++; + } +#/ + } +} + +print_run_speed( speed ) +{ +/# + self endon( "death" ); + while ( 1 ) + { + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 64 ), speed, ( 0, 0, 1 ) ); + wait 0,05; +#/ + } +} + +draw_line_ent_to_ent( ent1, ent2 ) +{ +/# + if ( getDvarInt( "zombie_debug" ) != 1 ) + { + return; + } + ent1 endon( "death" ); + ent2 endon( "death" ); + while ( 1 ) + { + line( ent1.origin, ent2.origin ); + wait 0,05; +#/ + } +} + +draw_line_ent_to_pos( ent, pos, end_on ) +{ +/# + if ( getDvarInt( "zombie_debug" ) != 1 ) + { + return; + } + ent endon( "death" ); + ent notify( "stop_draw_line_ent_to_pos" ); + ent endon( "stop_draw_line_ent_to_pos" ); + if ( isDefined( end_on ) ) + { + ent endon( end_on ); + } + while ( 1 ) + { + line( ent.origin, pos ); + wait 0,05; +#/ + } +} + +debug_print( msg ) +{ +/# + if ( getDvarInt( "zombie_debug" ) > 0 ) + { + println( "######### ZOMBIE: " + msg ); +#/ + } +} + +debug_blocker( pos, rad, height ) +{ +/# + self notify( "stop_debug_blocker" ); + self endon( "stop_debug_blocker" ); + for ( ;; ) + { + if ( getDvarInt( "zombie_debug" ) != 1 ) + { + return; + } + wait 0,05; + drawcylinder( pos, rad, height ); +#/ + } +} + +drawcylinder( pos, rad, height ) +{ +/# + currad = rad; + curheight = height; + r = 0; + while ( r < 20 ) + { + theta = ( r / 20 ) * 360; + theta2 = ( ( r + 1 ) / 20 ) * 360; + line( pos + ( cos( theta ) * currad, sin( theta ) * currad, 0 ), pos + ( cos( theta2 ) * currad, sin( theta2 ) * currad, 0 ) ); + line( pos + ( cos( theta ) * currad, sin( theta ) * currad, curheight ), pos + ( cos( theta2 ) * currad, sin( theta2 ) * currad, curheight ) ); + line( pos + ( cos( theta ) * currad, sin( theta ) * currad, 0 ), pos + ( cos( theta ) * currad, sin( theta ) * currad, curheight ) ); + r++; +#/ + } +} + +print3d_at_pos( msg, pos, thread_endon, offset ) +{ +/# + self endon( "death" ); + if ( isDefined( thread_endon ) ) + { + self notify( thread_endon ); + self endon( thread_endon ); + } + if ( !isDefined( offset ) ) + { + offset = ( 0, 0, 1 ); + } + while ( 1 ) + { + print3d( self.origin + offset, msg ); + wait 0,05; +#/ + } +} + +debug_breadcrumbs() +{ +/# + self endon( "disconnect" ); + self notify( "stop_debug_breadcrumbs" ); + self endon( "stop_debug_breadcrumbs" ); + while ( 1 ) + { + while ( getDvarInt( "zombie_debug" ) != 1 ) + { + wait 1; + } + i = 0; + while ( i < self.zombie_breadcrumbs.size ) + { + drawcylinder( self.zombie_breadcrumbs[ i ], 5, 5 ); + i++; + } + wait 0,05; +#/ + } +} + +debug_attack_spots_taken() +{ +/# + self notify( "stop_debug_breadcrumbs" ); + self endon( "stop_debug_breadcrumbs" ); + while ( 1 ) + { + while ( getDvarInt( "zombie_debug" ) != 2 ) + { + wait 1; + } + wait 0,05; + count = 0; + i = 0; + while ( i < self.attack_spots_taken.size ) + { + if ( self.attack_spots_taken[ i ] ) + { + count++; + circle( self.attack_spots[ i ], 12, ( 0, 0, 1 ), 0, 1, 1 ); + i++; + continue; + } + else + { + circle( self.attack_spots[ i ], 12, ( 0, 0, 1 ), 0, 1, 1 ); + } + i++; + } + msg = "" + count + " / " + self.attack_spots_taken.size; + print3d( self.origin, msg ); +#/ + } +} + +float_print3d( msg, time ) +{ +/# + self endon( "death" ); + time = getTime() + ( time * 1000 ); + offset = vectorScale( ( 0, 0, 1 ), 72 ); + while ( getTime() < time ) + { + offset += vectorScale( ( 0, 0, 1 ), 2 ); + print3d( self.origin + offset, msg, ( 0, 0, 1 ) ); + wait 0,05; +#/ + } +} + +do_player_vo( snd, variation_count ) +{ + index = maps/mp/zombies/_zm_weapons::get_player_index( self ); + sound = "zmb_vox_plr_" + index + "_" + snd; + if ( isDefined( variation_count ) ) + { + sound = ( sound + "_" ) + randomintrange( 0, variation_count ); + } + if ( !isDefined( level.player_is_speaking ) ) + { + level.player_is_speaking = 0; + } + if ( level.player_is_speaking == 0 ) + { + level.player_is_speaking = 1; + self playsoundwithnotify( sound, "sound_done" ); + self waittill( "sound_done" ); + wait 2; + level.player_is_speaking = 0; + } +} + +stop_magic_bullet_shield() +{ + self.attackeraccuracy = 1; + self notify( "stop_magic_bullet_shield" ); + self.magic_bullet_shield = undefined; + self._mbs = undefined; +} + +magic_bullet_shield() +{ + if ( isDefined( self.magic_bullet_shield ) && !self.magic_bullet_shield ) + { + if ( isai( self ) || isplayer( self ) ) + { + self.magic_bullet_shield = 1; +/# + level thread debug_magic_bullet_shield_death( self ); +#/ + if ( !isDefined( self._mbs ) ) + { + self._mbs = spawnstruct(); + } + if ( isai( self ) ) + { +/# + assert( isalive( self ), "Tried to do magic_bullet_shield on a dead or undefined guy." ); +#/ + self._mbs.last_pain_time = 0; + self._mbs.ignore_time = 2; + self._mbs.turret_ignore_time = 5; + } + self.attackeraccuracy = 0,1; + return; + } + else + { +/# + assertmsg( "magic_bullet_shield does not support entity of classname '" + self.classname + "'." ); +#/ + } + } +} + +debug_magic_bullet_shield_death( guy ) +{ + targetname = "none"; + if ( isDefined( guy.targetname ) ) + { + targetname = guy.targetname; + } + guy endon( "stop_magic_bullet_shield" ); + guy waittill( "death" ); +/# + assert( !isDefined( guy ), "Guy died with magic bullet shield on with targetname: " + targetname ); +#/ +} + +is_magic_bullet_shield_enabled( ent ) +{ + if ( !isDefined( ent ) ) + { + return 0; + } + if ( isDefined( ent.magic_bullet_shield ) ) + { + return ent.magic_bullet_shield == 1; + } +} + +really_play_2d_sound( sound ) +{ + temp_ent = spawn( "script_origin", ( 0, 0, 1 ) ); + temp_ent playsoundwithnotify( sound, sound + "wait" ); + temp_ent waittill( sound + "wait" ); + wait 0,05; + temp_ent delete(); +} + +play_sound_2d( sound ) +{ + level thread really_play_2d_sound( sound ); +} + +include_weapon( weapon_name, in_box, collector, weighting_func ) +{ +/# + println( "ZM >> include_weapon = " + weapon_name ); +#/ + if ( !isDefined( in_box ) ) + { + in_box = 1; + } + if ( !isDefined( collector ) ) + { + collector = 0; + } + maps/mp/zombies/_zm_weapons::include_zombie_weapon( weapon_name, in_box, collector, weighting_func ); +} + +include_buildable( buildable_struct ) +{ +/# + println( "ZM >> include_buildable = " + buildable_struct.name ); +#/ + maps/mp/zombies/_zm_buildables::include_zombie_buildable( buildable_struct ); +} + +is_buildable_included( name ) +{ + if ( isDefined( level.zombie_include_buildables[ name ] ) ) + { + return 1; + } + return 0; +} + +create_zombie_buildable_piece( modelname, radius, height, hud_icon ) +{ +/# + println( "ZM >> create_zombie_buildable_piece = " + modelname ); +#/ + self maps/mp/zombies/_zm_buildables::create_zombie_buildable_piece( modelname, radius, height, hud_icon ); +} + +is_buildable() +{ + return self maps/mp/zombies/_zm_buildables::is_buildable(); +} + +wait_for_buildable( buildable_name ) +{ + level waittill( buildable_name + "_built", player ); + return player; +} + +include_powered_item( power_on_func, power_off_func, range_func, cost_func, power_sources, start_power, target ) +{ + return maps/mp/zombies/_zm_power::add_powered_item( power_on_func, power_off_func, range_func, cost_func, power_sources, start_power, target ); +} + +include_powerup( powerup_name ) +{ + maps/mp/zombies/_zm_powerups::include_zombie_powerup( powerup_name ); +} + +include_equipment( equipment_name ) +{ + maps/mp/zombies/_zm_equipment::include_zombie_equipment( equipment_name ); +} + +limit_equipment( equipment_name, limited ) +{ + maps/mp/zombies/_zm_equipment::limit_zombie_equipment( equipment_name, limited ); +} + +trigger_invisible( enable ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ] ) ) + { + self setinvisibletoplayer( players[ i ], enable ); + } + i++; + } +} + +print3d_ent( text, color, scale, offset, end_msg, overwrite ) +{ + self endon( "death" ); + if ( isDefined( overwrite ) && overwrite && isDefined( self._debug_print3d_msg ) ) + { + self notify( "end_print3d" ); + wait 0,05; + } + self endon( "end_print3d" ); + if ( !isDefined( color ) ) + { + color = ( 0, 0, 1 ); + } + if ( !isDefined( scale ) ) + { + scale = 1; + } + if ( !isDefined( offset ) ) + { + offset = ( 0, 0, 1 ); + } + if ( isDefined( end_msg ) ) + { + self endon( end_msg ); + } + self._debug_print3d_msg = text; +/# + while ( 1 ) + { + print3d( self.origin + offset, self._debug_print3d_msg, color, scale ); + wait 0,05; +#/ + } +} + +isexplosivedamage( meansofdeath ) +{ + explosivedamage = "MOD_GRENADE MOD_GRENADE_SPLASH MOD_PROJECTILE_SPLASH MOD_EXPLOSIVE"; + if ( issubstr( explosivedamage, meansofdeath ) ) + { + return 1; + } + return 0; +} + +isprimarydamage( meansofdeath ) +{ + if ( meansofdeath == "MOD_RIFLE_BULLET" || meansofdeath == "MOD_PISTOL_BULLET" ) + { + return 1; + } + return 0; +} + +isfiredamage( weapon, meansofdeath ) +{ + if ( !issubstr( weapon, "flame" ) && !issubstr( weapon, "molotov_" ) && issubstr( weapon, "napalmblob_" ) && meansofdeath != "MOD_BURNED" || meansofdeath == "MOD_GRENADE" && meansofdeath == "MOD_GRENADE_SPLASH" ) + { + return 1; + } + return 0; +} + +isplayerexplosiveweapon( weapon, meansofdeath ) +{ + if ( !isexplosivedamage( meansofdeath ) ) + { + return 0; + } + if ( weapon == "artillery_mp" ) + { + return 0; + } + if ( issubstr( weapon, "turret" ) ) + { + return 0; + } + return 1; +} + +create_counter_hud( x ) +{ + if ( !isDefined( x ) ) + { + x = 0; + } + hud = create_simple_hud(); + hud.alignx = "left"; + hud.aligny = "top"; + hud.horzalign = "user_left"; + hud.vertalign = "user_top"; + hud.color = ( 0, 0, 1 ); + hud.fontscale = 32; + hud.x = x; + hud.alpha = 0; + hud setshader( "hud_chalk_1", 64, 64 ); + return hud; +} + +get_current_zone( return_zone ) +{ + flag_wait( "zones_initialized" ); + z = 0; + while ( z < level.zone_keys.size ) + { + zone_name = level.zone_keys[ z ]; + zone = level.zones[ zone_name ]; + i = 0; + while ( i < zone.volumes.size ) + { + if ( self istouching( zone.volumes[ i ] ) ) + { + if ( isDefined( return_zone ) && return_zone ) + { + return zone; + } + return zone_name; + } + i++; + } + z++; + } + return undefined; +} + +remove_mod_from_methodofdeath( mod ) +{ + return mod; +} + +clear_fog_threads() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] notify( "stop_fog" ); + i++; + } +} + +display_message( titletext, notifytext, duration ) +{ + notifydata = spawnstruct(); + notifydata.titletext = notifytext; + notifydata.notifytext = titletext; + notifydata.sound = "mus_level_up"; + notifydata.duration = duration; + notifydata.glowcolor = ( 0, 0, 1 ); + notifydata.color = ( 0, 0, 1 ); + notifydata.iconname = "hud_zombies_meat"; + self thread maps/mp/gametypes_zm/_hud_message::notifymessage( notifydata ); +} + +is_quad() +{ + return self.animname == "quad_zombie"; +} + +is_leaper() +{ + return self.animname == "leaper_zombie"; +} + +shock_onpain() +{ + self endon( "death" ); + self endon( "disconnect" ); + self notify( "stop_shock_onpain" ); + self endon( "stop_shock_onpain" ); + if ( getDvar( "blurpain" ) == "" ) + { + setdvar( "blurpain", "on" ); + } + for ( ;; ) + { + while ( 1 ) + { + oldhealth = self.health; + self waittill( "damage", damage, attacker, direction_vec, point, mod ); + if ( isDefined( level.shock_onpain ) && !level.shock_onpain ) + { + continue; + } + if ( isDefined( self.shock_onpain ) && !self.shock_onpain ) + { + continue; + } + while ( self.health < 1 ) + { + continue; + } + if ( mod == "MOD_PROJECTILE" || mod == "MOD_PROJECTILE_SPLASH" ) + { + } + } + else if ( mod != "MOD_GRENADE_SPLASH" || mod == "MOD_GRENADE" && mod == "MOD_EXPLOSIVE" ) + { + shocktype = undefined; + shocklight = undefined; + if ( isDefined( self.is_burning ) && self.is_burning ) + { + shocktype = "lava"; + shocklight = "lava_small"; + } + self shock_onexplosion( damage, shocktype, shocklight ); + continue; + } + else + { + if ( getDvar( "blurpain" ) == "on" ) + { + self shellshock( "pain", 0,5 ); + } + } + } +} + +shock_onexplosion( damage, shocktype, shocklight ) +{ + time = 0; + scaled_damage = ( 100 * damage ) / self.maxhealth; + if ( scaled_damage >= 90 ) + { + time = 4; + } + else if ( scaled_damage >= 50 ) + { + time = 3; + } + else if ( scaled_damage >= 25 ) + { + time = 2; + } + else + { + if ( scaled_damage > 10 ) + { + time = 1; + } + } + if ( time ) + { + if ( !isDefined( shocktype ) ) + { + shocktype = "explosion"; + } + self shellshock( shocktype, time ); + } + else + { + if ( isDefined( shocklight ) ) + { + self shellshock( shocklight, time ); + } + } +} + +increment_is_drinking() +{ +/# + if ( isDefined( level.devgui_dpad_watch ) && level.devgui_dpad_watch ) + { + self.is_drinking++; + return; +#/ + } + if ( !isDefined( self.is_drinking ) ) + { + self.is_drinking = 0; + } + if ( self.is_drinking == 0 ) + { + self disableoffhandweapons(); + self disableweaponcycling(); + } + self.is_drinking++; +} + +is_multiple_drinking() +{ + return self.is_drinking > 1; +} + +decrement_is_drinking() +{ + if ( self.is_drinking > 0 ) + { + self.is_drinking--; + + } + else + { +/# + assertmsg( "making is_drinking less than 0" ); +#/ + } + if ( self.is_drinking == 0 ) + { + self enableoffhandweapons(); + self enableweaponcycling(); + } +} + +clear_is_drinking() +{ + self.is_drinking = 0; + self enableoffhandweapons(); + self enableweaponcycling(); +} + +getweaponclasszm( weapon ) +{ +/# + assert( isDefined( weapon ) ); +#/ + if ( !isDefined( weapon ) ) + { + return undefined; + } + if ( !isDefined( level.weaponclassarray ) ) + { + level.weaponclassarray = []; + } + if ( isDefined( level.weaponclassarray[ weapon ] ) ) + { + return level.weaponclassarray[ weapon ]; + } + baseweaponindex = getbaseweaponitemindex( weapon ) + 1; + weaponclass = tablelookupcolumnforrow( "zm/zm_statstable.csv", baseweaponindex, 2 ); + level.weaponclassarray[ weapon ] = weaponclass; + return weaponclass; +} + +spawn_weapon_model( weapon, model, origin, angles, options ) +{ + if ( !isDefined( model ) ) + { + model = getweaponmodel( weapon ); + } + weapon_model = spawn( "script_model", origin ); + if ( isDefined( angles ) ) + { + weapon_model.angles = angles; + } + if ( isDefined( options ) ) + { + weapon_model useweaponmodel( weapon, model, options ); + } + else + { + weapon_model useweaponmodel( weapon, model ); + } + return weapon_model; +} + +is_limited_weapon( weapname ) +{ + if ( isDefined( level.limited_weapons ) ) + { + if ( isDefined( level.limited_weapons[ weapname ] ) ) + { + return 1; + } + } + return 0; +} + +is_alt_weapon( weapname ) +{ + if ( getsubstr( weapname, 0, 3 ) == "gl_" ) + { + return 1; + } + if ( getsubstr( weapname, 0, 3 ) == "sf_" ) + { + return 1; + } + if ( getsubstr( weapname, 0, 10 ) == "dualoptic_" ) + { + return 1; + } + return 0; +} + +is_grenade_launcher( weapname ) +{ + if ( weapname != "m32_zm" ) + { + return weapname == "m32_upgraded_zm"; + } +} + +register_lethal_grenade_for_level( weaponname ) +{ + if ( is_lethal_grenade( weaponname ) ) + { + return; + } + if ( !isDefined( level.zombie_lethal_grenade_list ) ) + { + level.zombie_lethal_grenade_list = []; + } + level.zombie_lethal_grenade_list[ weaponname ] = weaponname; +} + +is_lethal_grenade( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( level.zombie_lethal_grenade_list ) ) + { + return 0; + } + return isDefined( level.zombie_lethal_grenade_list[ weaponname ] ); +} + +is_player_lethal_grenade( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( self.current_lethal_grenade ) ) + { + return 0; + } + return self.current_lethal_grenade == weaponname; +} + +get_player_lethal_grenade() +{ + grenade = ""; + if ( isDefined( self.current_lethal_grenade ) ) + { + grenade = self.current_lethal_grenade; + } + return grenade; +} + +set_player_lethal_grenade( weaponname ) +{ + self.current_lethal_grenade = weaponname; +} + +init_player_lethal_grenade() +{ + self set_player_lethal_grenade( level.zombie_lethal_grenade_player_init ); +} + +register_tactical_grenade_for_level( weaponname ) +{ + if ( is_tactical_grenade( weaponname ) ) + { + return; + } + if ( !isDefined( level.zombie_tactical_grenade_list ) ) + { + level.zombie_tactical_grenade_list = []; + } + level.zombie_tactical_grenade_list[ weaponname ] = weaponname; +} + +is_tactical_grenade( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( level.zombie_tactical_grenade_list ) ) + { + return 0; + } + return isDefined( level.zombie_tactical_grenade_list[ weaponname ] ); +} + +is_player_tactical_grenade( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( self.current_tactical_grenade ) ) + { + return 0; + } + return self.current_tactical_grenade == weaponname; +} + +get_player_tactical_grenade() +{ + tactical = ""; + if ( isDefined( self.current_tactical_grenade ) ) + { + tactical = self.current_tactical_grenade; + } + return tactical; +} + +set_player_tactical_grenade( weaponname ) +{ + self notify( "new_tactical_grenade" ); + self.current_tactical_grenade = weaponname; +} + +init_player_tactical_grenade() +{ + self set_player_tactical_grenade( level.zombie_tactical_grenade_player_init ); +} + +register_placeable_mine_for_level( weaponname ) +{ + if ( is_placeable_mine( weaponname ) ) + { + return; + } + if ( !isDefined( level.zombie_placeable_mine_list ) ) + { + level.zombie_placeable_mine_list = []; + } + level.zombie_placeable_mine_list[ weaponname ] = weaponname; +} + +is_placeable_mine( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( level.zombie_placeable_mine_list ) ) + { + return 0; + } + return isDefined( level.zombie_placeable_mine_list[ weaponname ] ); +} + +is_player_placeable_mine( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( self.current_placeable_mine ) ) + { + return 0; + } + return self.current_placeable_mine == weaponname; +} + +get_player_placeable_mine() +{ + return self.current_placeable_mine; +} + +set_player_placeable_mine( weaponname ) +{ + self.current_placeable_mine = weaponname; +} + +init_player_placeable_mine() +{ + self set_player_placeable_mine( level.zombie_placeable_mine_player_init ); +} + +register_melee_weapon_for_level( weaponname ) +{ + if ( is_melee_weapon( weaponname ) ) + { + return; + } + if ( !isDefined( level.zombie_melee_weapon_list ) ) + { + level.zombie_melee_weapon_list = []; + } + level.zombie_melee_weapon_list[ weaponname ] = weaponname; +} + +is_melee_weapon( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( level.zombie_melee_weapon_list ) ) + { + return 0; + } + return isDefined( level.zombie_melee_weapon_list[ weaponname ] ); +} + +is_player_melee_weapon( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( self.current_melee_weapon ) ) + { + return 0; + } + return self.current_melee_weapon == weaponname; +} + +get_player_melee_weapon() +{ + return self.current_melee_weapon; +} + +set_player_melee_weapon( weaponname ) +{ + self.current_melee_weapon = weaponname; +} + +init_player_melee_weapon() +{ + self set_player_melee_weapon( level.zombie_melee_weapon_player_init ); +} + +should_watch_for_emp() +{ + return isDefined( level.zombie_weapons[ "emp_grenade_zm" ] ); +} + +register_equipment_for_level( weaponname ) +{ + if ( is_equipment( weaponname ) ) + { + return; + } + if ( !isDefined( level.zombie_equipment_list ) ) + { + level.zombie_equipment_list = []; + } + level.zombie_equipment_list[ weaponname ] = weaponname; +} + +is_equipment( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( level.zombie_equipment_list ) ) + { + return 0; + } + return isDefined( level.zombie_equipment_list[ weaponname ] ); +} + +is_equipment_that_blocks_purchase( weaponname ) +{ + return is_equipment( weaponname ); +} + +is_player_equipment( weaponname ) +{ + if ( !isDefined( weaponname ) || !isDefined( self.current_equipment ) ) + { + return 0; + } + return self.current_equipment == weaponname; +} + +has_deployed_equipment( weaponname ) +{ + if ( isDefined( weaponname ) || !isDefined( self.deployed_equipment ) && self.deployed_equipment.size < 1 ) + { + return 0; + } + i = 0; + while ( i < self.deployed_equipment.size ) + { + if ( self.deployed_equipment[ i ] == weaponname ) + { + return 1; + } + i++; + } + return 0; +} + +has_player_equipment( weaponname ) +{ + if ( !self is_player_equipment( weaponname ) ) + { + return self has_deployed_equipment( weaponname ); + } +} + +get_player_equipment() +{ + return self.current_equipment; +} + +hacker_active() +{ + return self maps/mp/zombies/_zm_equipment::is_equipment_active( "equip_hacker_zm" ); +} + +set_player_equipment( weaponname ) +{ + if ( !isDefined( self.current_equipment_active ) ) + { + self.current_equipment_active = []; + } + if ( isDefined( weaponname ) ) + { + self.current_equipment_active[ weaponname ] = 0; + } + if ( !isDefined( self.equipment_got_in_round ) ) + { + self.equipment_got_in_round = []; + } + if ( isDefined( weaponname ) ) + { + self.equipment_got_in_round[ weaponname ] = level.round_number; + } + self.current_equipment = weaponname; +} + +init_player_equipment() +{ + self set_player_equipment( level.zombie_equipment_player_init ); +} + +register_offhand_weapons_for_level_defaults() +{ + if ( isDefined( level.register_offhand_weapons_for_level_defaults_override ) ) + { + [[ level.register_offhand_weapons_for_level_defaults_override ]](); + return; + } + register_lethal_grenade_for_level( "frag_grenade_zm" ); + level.zombie_lethal_grenade_player_init = "frag_grenade_zm"; + register_tactical_grenade_for_level( "cymbal_monkey_zm" ); + level.zombie_tactical_grenade_player_init = undefined; + register_placeable_mine_for_level( "claymore_zm" ); + level.zombie_placeable_mine_player_init = undefined; + register_melee_weapon_for_level( "knife_zm" ); + register_melee_weapon_for_level( "bowie_knife_zm" ); + level.zombie_melee_weapon_player_init = "knife_zm"; + level.zombie_equipment_player_init = undefined; +} + +init_player_offhand_weapons() +{ + init_player_lethal_grenade(); + init_player_tactical_grenade(); + init_player_placeable_mine(); + init_player_melee_weapon(); + init_player_equipment(); +} + +is_offhand_weapon( weaponname ) +{ + if ( !is_lethal_grenade( weaponname ) && !is_tactical_grenade( weaponname ) && !is_placeable_mine( weaponname ) && !is_melee_weapon( weaponname ) ) + { + return is_equipment( weaponname ); + } +} + +is_player_offhand_weapon( weaponname ) +{ + if ( !self is_player_lethal_grenade( weaponname ) && !self is_player_tactical_grenade( weaponname ) && !self is_player_placeable_mine( weaponname ) && !self is_player_melee_weapon( weaponname ) ) + { + return self is_player_equipment( weaponname ); + } +} + +has_powerup_weapon() +{ + if ( isDefined( self.has_powerup_weapon ) ) + { + return self.has_powerup_weapon; + } +} + +give_start_weapon( switch_to_weapon ) +{ + self giveweapon( level.start_weapon ); + self givestartammo( level.start_weapon ); + if ( isDefined( switch_to_weapon ) && switch_to_weapon ) + { + self switchtoweapon( level.start_weapon ); + } +} + +array_flag_wait_any( flag_array ) +{ + if ( !isDefined( level._array_flag_wait_any_calls ) ) + { + level._n_array_flag_wait_any_calls = 0; + } + else + { + level._n_array_flag_wait_any_calls++; + } + str_condition = "array_flag_wait_call_" + level._n_array_flag_wait_any_calls; + index = 0; + while ( index < flag_array.size ) + { + level thread array_flag_wait_any_thread( flag_array[ index ], str_condition ); + index++; + } + level waittill( str_condition ); +} + +array_flag_wait_any_thread( flag_name, condition ) +{ + level endon( condition ); + flag_wait( flag_name ); + level notify( condition ); +} + +array_removedead( array ) +{ + newarray = []; + if ( !isDefined( array ) ) + { + return undefined; + } + i = 0; + while ( i < array.size ) + { + if ( !isalive( array[ i ] ) || isDefined( array[ i ].isacorpse ) && array[ i ].isacorpse ) + { + i++; + continue; + } + else + { + newarray[ newarray.size ] = array[ i ]; + } + i++; + } + return newarray; +} + +groundpos( origin ) +{ + return bullettrace( origin, origin + vectorScale( ( 0, 0, 1 ), 100000 ), 0, self )[ "position" ]; +} + +groundpos_ignore_water( origin ) +{ + return bullettrace( origin, origin + vectorScale( ( 0, 0, 1 ), 100000 ), 0, self, 1 )[ "position" ]; +} + +groundpos_ignore_water_new( origin ) +{ + return groundtrace( origin, origin + vectorScale( ( 0, 0, 1 ), 100000 ), 0, self, 1 )[ "position" ]; +} + +waittill_notify_or_timeout( msg, timer ) +{ + self endon( msg ); + wait timer; + return timer; +} + +self_delete() +{ + if ( isDefined( self ) ) + { + self delete(); + } +} + +script_delay() +{ + if ( isDefined( self.script_delay ) ) + { + wait self.script_delay; + return 1; + } + else + { + if ( isDefined( self.script_delay_min ) && isDefined( self.script_delay_max ) ) + { + wait randomfloatrange( self.script_delay_min, self.script_delay_max ); + return 1; + } + } + return 0; +} + +button_held_think( which_button ) +{ + self endon( "disconnect" ); + if ( !isDefined( self._holding_button ) ) + { + self._holding_button = []; + } + self._holding_button[ which_button ] = 0; + time_started = 0; + use_time = 250; + while ( 1 ) + { + if ( self._holding_button[ which_button ] ) + { + if ( !( self [[ level._button_funcs[ which_button ] ]]() ) ) + { + self._holding_button[ which_button ] = 0; + } + } + else if ( self [[ level._button_funcs[ which_button ] ]]() ) + { + if ( time_started == 0 ) + { + time_started = getTime(); + } + if ( ( getTime() - time_started ) > use_time ) + { + self._holding_button[ which_button ] = 1; + } + } + else + { + if ( time_started != 0 ) + { + time_started = 0; + } + } + wait 0,05; + } +} + +use_button_held() +{ + init_button_wrappers(); + if ( !isDefined( self._use_button_think_threaded ) ) + { + self thread button_held_think( level.button_use ); + self._use_button_think_threaded = 1; + } + return self._holding_button[ level.button_use ]; +} + +ads_button_held() +{ + init_button_wrappers(); + if ( !isDefined( self._ads_button_think_threaded ) ) + { + self thread button_held_think( level.button_ads ); + self._ads_button_think_threaded = 1; + } + return self._holding_button[ level.button_ads ]; +} + +attack_button_held() +{ + init_button_wrappers(); + if ( !isDefined( self._attack_button_think_threaded ) ) + { + self thread button_held_think( level.button_attack ); + self._attack_button_think_threaded = 1; + } + return self._holding_button[ level.button_attack ]; +} + +use_button_pressed() +{ + return self usebuttonpressed(); +} + +ads_button_pressed() +{ + return self adsbuttonpressed(); +} + +attack_button_pressed() +{ + return self attackbuttonpressed(); +} + +init_button_wrappers() +{ + if ( !isDefined( level._button_funcs ) ) + { + level.button_use = 0; + level.button_ads = 1; + level.button_attack = 2; + level._button_funcs[ level.button_use ] = ::use_button_pressed; + level._button_funcs[ level.button_ads ] = ::ads_button_pressed; + level._button_funcs[ level.button_attack ] = ::attack_button_pressed; + } +} + +wait_network_frame() +{ + if ( numremoteclients() ) + { + snapshot_ids = getsnapshotindexarray(); + acked = undefined; + while ( !isDefined( acked ) ) + { + level waittill( "snapacknowledged" ); + acked = snapshotacknowledged( snapshot_ids ); + } + } + else wait 0,1; +} + +ignore_triggers( timer ) +{ + self endon( "death" ); + self.ignoretriggers = 1; + if ( isDefined( timer ) ) + { + wait timer; + } + else + { + wait 0,5; + } + self.ignoretriggers = 0; +} + +giveachievement_wrapper( achievement, all_players ) +{ + if ( achievement == "" ) + { + return; + } + if ( isDefined( level.zm_disable_recording_stats ) && level.zm_disable_recording_stats ) + { + return; + } + achievement_lower = tolower( achievement ); + global_counter = 0; + if ( isDefined( all_players ) && all_players ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] giveachievement( achievement ); + has_achievement = players[ i ] maps/mp/zombies/_zm_stats::get_global_stat( achievement_lower ); + if ( isDefined( has_achievement ) && !has_achievement ) + { + global_counter++; + } + players[ i ] maps/mp/zombies/_zm_stats::increment_client_stat( achievement_lower, 0 ); + if ( issplitscreen() || i == 0 && !issplitscreen() ) + { + if ( isDefined( level.achievement_sound_func ) ) + { + players[ i ] thread [[ level.achievement_sound_func ]]( achievement_lower ); + } + } + i++; + } + } + else if ( !isplayer( self ) ) + { +/# + println( "^1self needs to be a player for _utility::giveachievement_wrapper()" ); +#/ + return; + } + self giveachievement( achievement ); + has_achievement = self maps/mp/zombies/_zm_stats::get_global_stat( achievement_lower ); + if ( isDefined( has_achievement ) && !has_achievement ) + { + global_counter++; + } + self maps/mp/zombies/_zm_stats::increment_client_stat( achievement_lower, 0 ); + if ( isDefined( level.achievement_sound_func ) ) + { + self thread [[ level.achievement_sound_func ]]( achievement_lower ); + } + if ( global_counter ) + { + incrementcounter( "global_" + achievement_lower, global_counter ); + } +} + +spawn_failed( spawn ) +{ + if ( isDefined( spawn ) && isalive( spawn ) ) + { + if ( isalive( spawn ) ) + { + return 0; + } + } + return 1; +} + +getyaw( org ) +{ + angles = vectorToAngle( org - self.origin ); + return angles[ 1 ]; +} + +getyawtospot( spot ) +{ + pos = spot; + yaw = self.angles[ 1 ] - getyaw( pos ); + yaw = angleClamp180( yaw ); + return yaw; +} + +add_spawn_function( function, param1, param2, param3, param4 ) +{ +/# + if ( isDefined( level._loadstarted ) ) + { + assert( !isalive( self ), "Tried to add_spawn_function to a living guy." ); + } +#/ + func = []; + func[ "function" ] = function; + func[ "param1" ] = param1; + func[ "param2" ] = param2; + func[ "param3" ] = param3; + func[ "param4" ] = param4; + if ( !isDefined( self.spawn_funcs ) ) + { + self.spawn_funcs = []; + } + self.spawn_funcs[ self.spawn_funcs.size ] = func; +} + +disable_react() +{ +/# + assert( isalive( self ), "Tried to disable react on a non ai" ); +#/ + self.a.disablereact = 1; + self.allowreact = 0; +} + +enable_react() +{ +/# + assert( isalive( self ), "Tried to enable react on a non ai" ); +#/ + self.a.disablereact = 0; + self.allowreact = 1; +} + +flag_wait_or_timeout( flagname, timer ) +{ + start_time = getTime(); + for ( ;; ) + { + if ( level.flag[ flagname ] ) + { + return; + } + else if ( getTime() >= ( start_time + ( timer * 1000 ) ) ) + { + return; + } + else + { + wait_for_flag_or_time_elapses( flagname, timer ); + } + } +} + +wait_for_flag_or_time_elapses( flagname, timer ) +{ + level endon( flagname ); + wait timer; +} + +isads( player ) +{ + return player playerads() > 0,5; +} + +bullet_attack( type ) +{ + if ( type == "MOD_PISTOL_BULLET" ) + { + return 1; + } + return type == "MOD_RIFLE_BULLET"; +} + +pick_up() +{ + player = self.owner; + self destroy_ent(); + clip_ammo = player getweaponammoclip( self.name ); + clip_max_ammo = weaponclipsize( self.name ); + if ( clip_ammo < clip_max_ammo ) + { + clip_ammo++; + } + player setweaponammoclip( self.name, clip_ammo ); +} + +destroy_ent() +{ + self delete(); +} + +waittill_not_moving() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "detonated" ); + level endon( "game_ended" ); + if ( self.classname == "grenade" ) + { + self waittill( "stationary" ); + } + else prevorigin = self.origin; + while ( 1 ) + { + wait 0,15; + if ( self.origin == prevorigin ) + { + return; + } + else + { + prevorigin = self.origin; + } + } +} + +get_closest_player( org ) +{ + players = []; + players = get_players(); + return getclosest( org, players ); +} + +ent_flag_wait( msg ) +{ + self endon( "death" ); + while ( !self.ent_flag[ msg ] ) + { + self waittill( msg ); + } +} + +ent_flag_wait_either( flag1, flag2 ) +{ + self endon( "death" ); + for ( ;; ) + { + if ( ent_flag( flag1 ) ) + { + return; + } + if ( ent_flag( flag2 ) ) + { + return; + } + self waittill_either( flag1, flag2 ); + } +} + +ent_wait_for_flag_or_time_elapses( flagname, timer ) +{ + self endon( flagname ); + wait timer; +} + +ent_flag_wait_or_timeout( flagname, timer ) +{ + self endon( "death" ); + start_time = getTime(); + for ( ;; ) + { + if ( self.ent_flag[ flagname ] ) + { + return; + } + else if ( getTime() >= ( start_time + ( timer * 1000 ) ) ) + { + return; + } + else + { + self ent_wait_for_flag_or_time_elapses( flagname, timer ); + } + } +} + +ent_flag_waitopen( msg ) +{ + self endon( "death" ); + while ( self.ent_flag[ msg ] ) + { + self waittill( msg ); + } +} + +ent_flag_init( message, val ) +{ + if ( !isDefined( self.ent_flag ) ) + { + self.ent_flag = []; + self.ent_flags_lock = []; + } + if ( !isDefined( level.first_frame ) ) + { +/# + assert( !isDefined( self.ent_flag[ message ] ), "Attempt to reinitialize existing flag '" + message + "' on entity." ); +#/ + } + if ( isDefined( val ) && val ) + { + self.ent_flag[ message ] = 1; +/# + self.ent_flags_lock[ message ] = 1; +#/ + } + else + { + self.ent_flag[ message ] = 0; +/# + self.ent_flags_lock[ message ] = 0; +#/ + } +} + +ent_flag_exist( message ) +{ + if ( isDefined( self.ent_flag ) && isDefined( self.ent_flag[ message ] ) ) + { + return 1; + } + return 0; +} + +ent_flag_set_delayed( message, delay ) +{ + wait delay; + self ent_flag_set( message ); +} + +ent_flag_set( message ) +{ +/# + assert( isDefined( self ), "Attempt to set a flag on entity that is not defined" ); + assert( isDefined( self.ent_flag[ message ] ), "Attempt to set a flag before calling flag_init: '" + message + "'." ); + assert( self.ent_flag[ message ] == self.ent_flags_lock[ message ] ); + self.ent_flags_lock[ message ] = 1; +#/ + self.ent_flag[ message ] = 1; + self notify( message ); +} + +ent_flag_toggle( message ) +{ + if ( self ent_flag( message ) ) + { + self ent_flag_clear( message ); + } + else + { + self ent_flag_set( message ); + } +} + +ent_flag_clear( message ) +{ +/# + assert( isDefined( self ), "Attempt to clear a flag on entity that is not defined" ); + assert( isDefined( self.ent_flag[ message ] ), "Attempt to set a flag before calling flag_init: '" + message + "'." ); + assert( self.ent_flag[ message ] == self.ent_flags_lock[ message ] ); + self.ent_flags_lock[ message ] = 0; +#/ + if ( self.ent_flag[ message ] ) + { + self.ent_flag[ message ] = 0; + self notify( message ); + } +} + +ent_flag_clear_delayed( message, delay ) +{ + wait delay; + self ent_flag_clear( message ); +} + +ent_flag( message ) +{ +/# + assert( isDefined( message ), "Tried to check flag but the flag was not defined." ); +#/ +/# + assert( isDefined( self.ent_flag[ message ] ), "Tried to check entity flag '" + message + "', but the flag was not initialized." ); +#/ + if ( !self.ent_flag[ message ] ) + { + return 0; + } + return 1; +} + +ent_flag_init_ai_standards() +{ + message_array = []; + message_array[ message_array.size ] = "goal"; + message_array[ message_array.size ] = "damage"; + i = 0; + while ( i < message_array.size ) + { + self ent_flag_init( message_array[ i ] ); + self thread ent_flag_wait_ai_standards( message_array[ i ] ); + i++; + } +} + +ent_flag_wait_ai_standards( message ) +{ + self endon( "death" ); + self waittill( message ); + self.ent_flag[ message ] = 1; +} + +flat_angle( angle ) +{ + rangle = ( 0, angle[ 1 ], 0 ); + return rangle; +} + +waittill_any_or_timeout( timer, string1, string2, string3, string4, string5 ) +{ +/# + assert( isDefined( string1 ) ); +#/ + self endon( string1 ); + if ( isDefined( string2 ) ) + { + self endon( string2 ); + } + if ( isDefined( string3 ) ) + { + self endon( string3 ); + } + if ( isDefined( string4 ) ) + { + self endon( string4 ); + } + if ( isDefined( string5 ) ) + { + self endon( string5 ); + } + wait timer; +} + +clear_run_anim() +{ + self.alwaysrunforward = undefined; + self.a.combatrunanim = undefined; + self.run_noncombatanim = undefined; + self.walk_combatanim = undefined; + self.walk_noncombatanim = undefined; + self.precombatrunenabled = 1; +} + +track_players_intersection_tracker() +{ + self endon( "disconnect" ); + self endon( "death" ); + level endon( "end_game" ); + wait 5; + while ( 1 ) + { + killed_players = 0; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() || players[ i ].sessionstate != "playing" ) + { + i++; + continue; + } + else + { + j = 0; + while ( j < players.size ) + { + if ( j != i || players[ j ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ j ].sessionstate != "playing" ) + { + j++; + continue; + } + else + { + if ( isDefined( level.player_intersection_tracker_override ) ) + { + if ( players[ i ] [[ level.player_intersection_tracker_override ]]( players[ j ] ) ) + { + j++; + continue; + } + } + else playeri_origin = players[ i ].origin; + playerj_origin = players[ j ].origin; + if ( abs( playeri_origin[ 2 ] - playerj_origin[ 2 ] ) > 60 ) + { + j++; + continue; + } + else distance_apart = distance2d( playeri_origin, playerj_origin ); + if ( abs( distance_apart ) > 18 ) + { + j++; + continue; + } + else + { +/# + iprintlnbold( "PLAYERS ARE TOO FRIENDLY!!!!!" ); +#/ + players[ i ] dodamage( 1000, ( 0, 0, 1 ) ); + players[ j ] dodamage( 1000, ( 0, 0, 1 ) ); + if ( !killed_players ) + { + players[ i ] playlocalsound( level.zmb_laugh_alias ); + } + players[ i ] maps/mp/zombies/_zm_stats::increment_map_cheat_stat( "cheat_too_friendly" ); + players[ i ] maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_too_friendly", 0 ); + players[ i ] maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + players[ j ] maps/mp/zombies/_zm_stats::increment_map_cheat_stat( "cheat_too_friendly" ); + players[ j ] maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_too_friendly", 0 ); + players[ j ] maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + killed_players = 1; + } + } + j++; + } + } + i++; + } + wait 0,5; + } +} + +get_eye() +{ + if ( isplayer( self ) ) + { + linked_ent = self getlinkedent(); + if ( isDefined( linked_ent ) && getDvarInt( "cg_cameraUseTagCamera" ) > 0 ) + { + camera = linked_ent gettagorigin( "tag_camera" ); + if ( isDefined( camera ) ) + { + return camera; + } + } + } + pos = self geteye(); + return pos; +} + +is_player_looking_at( origin, dot, do_trace, ignore_ent ) +{ +/# + assert( isplayer( self ), "player_looking_at must be called on a player." ); +#/ + if ( !isDefined( dot ) ) + { + dot = 0,7; + } + if ( !isDefined( do_trace ) ) + { + do_trace = 1; + } + eye = self get_eye(); + delta_vec = anglesToForward( vectorToAngle( origin - eye ) ); + view_vec = anglesToForward( self getplayerangles() ); + new_dot = vectordot( delta_vec, view_vec ); + if ( new_dot >= dot ) + { + if ( do_trace ) + { + return bullettracepassed( origin, eye, 0, ignore_ent ); + } + else + { + return 1; + } + } + return 0; +} + +add_gametype( gt, dummy1, name, dummy2 ) +{ +} + +add_gameloc( gl, dummy1, name, dummy2 ) +{ +} + +get_closest_index( org, array, dist ) +{ + if ( !isDefined( dist ) ) + { + dist = 9999999; + } + distsq = dist * dist; + if ( array.size < 1 ) + { + return; + } + index = undefined; + i = 0; + while ( i < array.size ) + { + newdistsq = distancesquared( array[ i ].origin, org ); + if ( newdistsq >= distsq ) + { + i++; + continue; + } + else + { + distsq = newdistsq; + index = i; + } + i++; + } + return index; +} + +is_valid_zombie_spawn_point( point ) +{ + liftedorigin = point.origin + vectorScale( ( 0, 0, 1 ), 5 ); + size = 48; + height = 64; + mins = ( -1 * size, -1 * size, 0 ); + maxs = ( size, size, height ); + absmins = liftedorigin + mins; + absmaxs = liftedorigin + maxs; + if ( boundswouldtelefrag( absmins, absmaxs ) ) + { + return 0; + } + return 1; +} + +get_closest_index_to_entity( entity, array, dist, extra_check ) +{ + org = entity.origin; + if ( !isDefined( dist ) ) + { + dist = 9999999; + } + distsq = dist * dist; + if ( array.size < 1 ) + { + return; + } + index = undefined; + i = 0; + while ( i < array.size ) + { + if ( isDefined( extra_check ) && !( [[ extra_check ]]( entity, array[ i ] ) ) ) + { + i++; + continue; + } + else + { + newdistsq = distancesquared( array[ i ].origin, org ); + if ( newdistsq >= distsq ) + { + i++; + continue; + } + else + { + distsq = newdistsq; + index = i; + } + } + i++; + } + return index; +} + +set_gamemode_var( var, val ) +{ + if ( !isDefined( game[ "gamemode_match" ] ) ) + { + game[ "gamemode_match" ] = []; + } + game[ "gamemode_match" ][ var ] = val; +} + +set_gamemode_var_once( var, val ) +{ + if ( !isDefined( game[ "gamemode_match" ] ) ) + { + game[ "gamemode_match" ] = []; + } + if ( !isDefined( game[ "gamemode_match" ][ var ] ) ) + { + game[ "gamemode_match" ][ var ] = val; + } +} + +set_game_var( var, val ) +{ + game[ var ] = val; +} + +set_game_var_once( var, val ) +{ + if ( !isDefined( game[ var ] ) ) + { + game[ var ] = val; + } +} + +get_game_var( var ) +{ + if ( isDefined( game[ var ] ) ) + { + return game[ var ]; + } + return undefined; +} + +get_gamemode_var( var ) +{ + if ( isDefined( game[ "gamemode_match" ] ) && isDefined( game[ "gamemode_match" ][ var ] ) ) + { + return game[ "gamemode_match" ][ var ]; + } + return undefined; +} + +waittill_subset( min_num, string1, string2, string3, string4, string5 ) +{ + self endon( "death" ); + ent = spawnstruct(); + ent.threads = 0; + returned_threads = 0; + if ( isDefined( string1 ) ) + { + self thread waittill_string( string1, ent ); + ent.threads++; + } + if ( isDefined( string2 ) ) + { + self thread waittill_string( string2, ent ); + ent.threads++; + } + if ( isDefined( string3 ) ) + { + self thread waittill_string( string3, ent ); + ent.threads++; + } + if ( isDefined( string4 ) ) + { + self thread waittill_string( string4, ent ); + ent.threads++; + } + if ( isDefined( string5 ) ) + { + self thread waittill_string( string5, ent ); + ent.threads++; + } + while ( ent.threads ) + { + ent waittill( "returned" ); + ent.threads--; + + returned_threads++; + if ( returned_threads >= min_num ) + { + break; + } + else + { + } + } + ent notify( "die" ); +} + +is_headshot( sweapon, shitloc, smeansofdeath ) +{ + if ( shitloc != "head" && shitloc != "helmet" ) + { + return 0; + } + if ( smeansofdeath == "MOD_IMPACT" && issubstr( sweapon, "knife_ballistic" ) ) + { + return 1; + } + if ( smeansofdeath != "MOD_MELEE" && smeansofdeath != "MOD_BAYONET" && smeansofdeath != "MOD_IMPACT" ) + { + return smeansofdeath != "MOD_UNKNOWN"; + } +} + +is_jumping() +{ + ground_ent = self getgroundent(); + return !isDefined( ground_ent ); +} + +is_explosive_damage( mod ) +{ + if ( !isDefined( mod ) ) + { + return 0; + } + if ( mod != "MOD_GRENADE" && mod != "MOD_GRENADE_SPLASH" && mod != "MOD_PROJECTILE" || mod == "MOD_PROJECTILE_SPLASH" && mod == "MOD_EXPLOSIVE" ) + { + return 1; + } + return 0; +} + +sndswitchannouncervox( who ) +{ + switch( who ) + { + case "sam": + game[ "zmbdialog" ][ "prefix" ] = "vox_zmba_sam"; + level.zmb_laugh_alias = "zmb_laugh_sam"; + level.sndannouncerisrich = 0; + break; + case "richtofen": + game[ "zmbdialog" ][ "prefix" ] = "vox_zmba"; + level.zmb_laugh_alias = "zmb_laugh_richtofen"; + level.sndannouncerisrich = 1; + break; + } +} + +do_player_general_vox( category, type, timer, chance ) +{ + if ( isDefined( timer ) && isDefined( level.votimer[ type ] ) && level.votimer[ type ] > 0 ) + { + return; + } + if ( !isDefined( chance ) ) + { + chance = maps/mp/zombies/_zm_audio::get_response_chance( type ); + } + if ( chance > randomint( 100 ) ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( category, type ); + if ( isDefined( timer ) ) + { + level.votimer[ type ] = timer; + level thread general_vox_timer( level.votimer[ type ], type ); + } + } +} + +general_vox_timer( timer, type ) +{ + level endon( "end_game" ); +/# + println( "ZM >> VOX TIMER STARTED FOR " + type + " ( " + timer + ")" ); +#/ + while ( timer > 0 ) + { + wait 1; + timer--; + + } + level.votimer[ type ] = timer; +/# + println( "ZM >> VOX TIMER ENDED FOR " + type + " ( " + timer + ")" ); +#/ +} + +create_vox_timer( type ) +{ + level.votimer[ type ] = 0; +} + +play_vox_to_player( category, type, force_variant ) +{ + self thread maps/mp/zombies/_zm_audio::playvoxtoplayer( category, type, force_variant ); +} + +is_favorite_weapon( weapon_to_check ) +{ + if ( !isDefined( self.favorite_wall_weapons_list ) ) + { + return 0; + } + _a6174 = self.favorite_wall_weapons_list; + _k6174 = getFirstArrayKey( _a6174 ); + while ( isDefined( _k6174 ) ) + { + weapon = _a6174[ _k6174 ]; + if ( weapon_to_check == weapon ) + { + return 1; + } + _k6174 = getNextArrayKey( _a6174, _k6174 ); + } + return 0; +} + +add_vox_response_chance( event, chance ) +{ + level.response_chances[ event ] = chance; +} + +set_demo_intermission_point() +{ + spawnpoints = getentarray( "mp_global_intermission", "classname" ); + if ( !spawnpoints.size ) + { + return; + } + spawnpoint = spawnpoints[ 0 ]; + match_string = ""; + location = level.scr_zm_map_start_location; + if ( location != "default" && location == "" && isDefined( level.default_start_location ) ) + { + location = level.default_start_location; + } + match_string = ( level.scr_zm_ui_gametype + "_" ) + location; + i = 0; + while ( i < spawnpoints.size ) + { + while ( isDefined( spawnpoints[ i ].script_string ) ) + { + tokens = strtok( spawnpoints[ i ].script_string, " " ); + _a6214 = tokens; + _k6214 = getFirstArrayKey( _a6214 ); + while ( isDefined( _k6214 ) ) + { + token = _a6214[ _k6214 ]; + if ( token == match_string ) + { + spawnpoint = spawnpoints[ i ]; + i = spawnpoints.size; + i++; + continue; + } + else + { + _k6214 = getNextArrayKey( _a6214, _k6214 ); + } + } + } + i++; + } + setdemointermissionpoint( spawnpoint.origin, spawnpoint.angles ); +} + +register_map_navcard( navcard_on_map, navcard_needed_for_computer ) +{ + level.navcard_needed = navcard_needed_for_computer; + level.map_navcard = navcard_on_map; +} + +does_player_have_map_navcard( player ) +{ + return player maps/mp/zombies/_zm_stats::get_global_stat( level.map_navcard ); +} + +does_player_have_correct_navcard( player ) +{ + if ( !isDefined( level.navcard_needed ) ) + { + return 0; + } + return player maps/mp/zombies/_zm_stats::get_global_stat( level.navcard_needed ); +} + +place_navcard( str_model, str_stat, org, angles ) +{ + navcard = spawn( "script_model", org ); + navcard setmodel( str_model ); + navcard.angles = angles; + wait 1; + navcard_pickup_trig = spawn( "trigger_radius_use", org, 0, 84, 72 ); + navcard_pickup_trig setcursorhint( "HINT_NOICON" ); + navcard_pickup_trig sethintstring( &"ZOMBIE_NAVCARD_PICKUP" ); + navcard_pickup_trig triggerignoreteam(); + a_navcard_stats = array( "navcard_held_zm_transit", "navcard_held_zm_highrise", "navcard_held_zm_buried" ); + is_holding_card = 0; + str_placing_stat = undefined; + while ( 1 ) + { + navcard_pickup_trig waittill( "trigger", who ); + if ( is_player_valid( who ) ) + { + _a6274 = a_navcard_stats; + _k6274 = getFirstArrayKey( _a6274 ); + while ( isDefined( _k6274 ) ) + { + str_cur_stat = _a6274[ _k6274 ]; + if ( who maps/mp/zombies/_zm_stats::get_global_stat( str_cur_stat ) ) + { + str_placing_stat = str_cur_stat; + is_holding_card = 1; + who maps/mp/zombies/_zm_stats::set_global_stat( str_cur_stat, 0 ); + } + _k6274 = getNextArrayKey( _a6274, _k6274 ); + } + who playsound( "zmb_buildable_piece_add" ); + who maps/mp/zombies/_zm_stats::set_global_stat( str_stat, 1 ); + who.navcard_grabbed = str_stat; + wait_network_frame(); + is_stat = who maps/mp/zombies/_zm_stats::get_global_stat( str_stat ); + thread sq_refresh_player_navcard_hud(); + break; + } + else + { + } + } + navcard delete(); + navcard_pickup_trig delete(); + if ( is_holding_card ) + { + level thread place_navcard( str_model, str_placing_stat, org, angles ); + } +} + +sq_refresh_player_navcard_hud() +{ + if ( !isDefined( level.navcards ) ) + { + return; + } + players = get_players(); + _a6311 = players; + _k6311 = getFirstArrayKey( _a6311 ); + while ( isDefined( _k6311 ) ) + { + player = _a6311[ _k6311 ]; + player thread sq_refresh_player_navcard_hud_internal(); + _k6311 = getNextArrayKey( _a6311, _k6311 ); + } +} + +sq_refresh_player_navcard_hud_internal() +{ + self endon( "disconnect" ); + navcard_bits = 0; + i = 0; + while ( i < level.navcards.size ) + { + hasit = self maps/mp/zombies/_zm_stats::get_global_stat( level.navcards[ i ] ); + if ( isDefined( self.navcard_grabbed ) && self.navcard_grabbed == level.navcards[ i ] ) + { + hasit = 1; + } + if ( hasit ) + { + navcard_bits += 1 << i; + } + i++; + } + wait_network_frame(); + self setclientfield( "navcard_held", 0 ); + if ( navcard_bits > 0 ) + { + wait_network_frame(); + self setclientfield( "navcard_held", navcard_bits ); + } +} + +set_player_is_female( onoff ) +{ + if ( isDefined( level.use_female_animations ) && level.use_female_animations ) + { + female_perk = "specialty_gpsjammer"; + if ( onoff ) + { + self setperk( female_perk ); + return; + } + else + { + self unsetperk( female_perk ); + } + } +} + +disable_player_move_states( forcestancechange ) +{ + self allowcrouch( 1 ); + self allowlean( 0 ); + self allowads( 0 ); + self allowsprint( 0 ); + self allowprone( 0 ); + self allowmelee( 0 ); + if ( isDefined( forcestancechange ) && forcestancechange == 1 ) + { + if ( self getstance() == "prone" ) + { + self setstance( "crouch" ); + } + } +} + +enable_player_move_states() +{ + if ( !isDefined( self._allow_lean ) || self._allow_lean == 1 ) + { + self allowlean( 1 ); + } + if ( !isDefined( self._allow_ads ) || self._allow_ads == 1 ) + { + self allowads( 1 ); + } + if ( !isDefined( self._allow_sprint ) || self._allow_sprint == 1 ) + { + self allowsprint( 1 ); + } + if ( !isDefined( self._allow_prone ) || self._allow_prone == 1 ) + { + self allowprone( 1 ); + } + if ( !isDefined( self._allow_melee ) || self._allow_melee == 1 ) + { + self allowmelee( 1 ); + } +} + +check_and_create_node_lists() +{ + if ( !isDefined( level._link_node_list ) ) + { + level._link_node_list = []; + } + if ( !isDefined( level._unlink_node_list ) ) + { + level._unlink_node_list = []; + } +} + +link_nodes( a, b, bdontunlinkonmigrate ) +{ + if ( !isDefined( bdontunlinkonmigrate ) ) + { + bdontunlinkonmigrate = 0; + } + if ( nodesarelinked( a, b ) ) + { + return; + } + check_and_create_node_lists(); + a_index_string = "" + a.origin; + b_index_string = "" + b.origin; + if ( !isDefined( level._link_node_list[ a_index_string ] ) ) + { + level._link_node_list[ a_index_string ] = spawnstruct(); + level._link_node_list[ a_index_string ].node = a; + level._link_node_list[ a_index_string ].links = []; + level._link_node_list[ a_index_string ].ignore_on_migrate = []; + } + if ( !isDefined( level._link_node_list[ a_index_string ].links[ b_index_string ] ) ) + { + level._link_node_list[ a_index_string ].links[ b_index_string ] = b; + level._link_node_list[ a_index_string ].ignore_on_migrate[ b_index_string ] = bdontunlinkonmigrate; + } + if ( isDefined( level._unlink_node_list[ a_index_string ] ) ) + { + if ( isDefined( level._unlink_node_list[ a_index_string ].links[ b_index_string ] ) ) + { + } + } + linknodes( a, b ); +} + +unlink_nodes( a, b, bdontlinkonmigrate ) +{ + if ( !isDefined( bdontlinkonmigrate ) ) + { + bdontlinkonmigrate = 0; + } + if ( !nodesarelinked( a, b ) ) + { + return; + } + check_and_create_node_lists(); + a_index_string = "" + a.origin; + b_index_string = "" + b.origin; + if ( !isDefined( level._unlink_node_list[ a_index_string ] ) ) + { + level._unlink_node_list[ a_index_string ] = spawnstruct(); + level._unlink_node_list[ a_index_string ].node = a; + level._unlink_node_list[ a_index_string ].links = []; + level._unlink_node_list[ a_index_string ].ignore_on_migrate = []; + } + if ( !isDefined( level._unlink_node_list[ a_index_string ].links[ b_index_string ] ) ) + { + level._unlink_node_list[ a_index_string ].links[ b_index_string ] = b; + level._unlink_node_list[ a_index_string ].ignore_on_migrate[ b_index_string ] = bdontlinkonmigrate; + } + if ( isDefined( level._link_node_list[ a_index_string ] ) ) + { + if ( isDefined( level._link_node_list[ a_index_string ].links[ b_index_string ] ) ) + { + } + } + unlinknodes( a, b ); +} + +spawn_path_node( origin, angles, k1, v1, k2, v2 ) +{ + if ( !isDefined( level._spawned_path_nodes ) ) + { + level._spawned_path_nodes = []; + } + node = spawnstruct(); + node.origin = origin; + node.angles = angles; + node.k1 = k1; + node.v1 = v1; + node.k2 = k2; + node.v2 = v2; + node.node = spawn_path_node_internal( origin, angles, k1, v1, k2, v2 ); + level._spawned_path_nodes[ level._spawned_path_nodes.size ] = node; + return node.node; +} + +spawn_path_node_internal( origin, angles, k1, v1, k2, v2 ) +{ + if ( isDefined( k2 ) ) + { + return spawnpathnode( "node_pathnode", origin, angles, k1, v1, k2, v2 ); + } + else + { + if ( isDefined( k1 ) ) + { + return spawnpathnode( "node_pathnode", origin, angles, k1, v1 ); + } + else + { + return spawnpathnode( "node_pathnode", origin, angles ); + } + } + return undefined; +} + +delete_spawned_path_nodes() +{ +} + +respawn_path_nodes() +{ + if ( !isDefined( level._spawned_path_nodes ) ) + { + return; + } + i = 0; + while ( i < level._spawned_path_nodes.size ) + { + node_struct = level._spawned_path_nodes[ i ]; +/# + println( "Re-spawning spawned path node @ " + node_struct.origin ); +#/ + node_struct.node = spawn_path_node_internal( node_struct.origin, node_struct.angles, node_struct.k1, node_struct.v1, node_struct.k2, node_struct.v2 ); + i++; + } +} + +link_changes_internal_internal( list, func ) +{ + keys = getarraykeys( list ); + i = 0; + while ( i < keys.size ) + { + node = list[ keys[ i ] ].node; + node_keys = getarraykeys( list[ keys[ i ] ].links ); + j = 0; + while ( j < node_keys.size ) + { + if ( isDefined( list[ keys[ i ] ].links[ node_keys[ j ] ] ) ) + { + if ( isDefined( list[ keys[ i ] ].ignore_on_migrate[ node_keys[ j ] ] ) && list[ keys[ i ] ].ignore_on_migrate[ node_keys[ j ] ] ) + { +/# + println( "Node at " + keys[ i ] + " to node at " + node_keys[ j ] + " - IGNORED" ); +#/ + j++; + continue; + } + else + { +/# + println( "Node at " + keys[ i ] + " to node at " + node_keys[ j ] ); +#/ + [[ func ]]( node, list[ keys[ i ] ].links[ node_keys[ j ] ] ); + } + } + j++; + } + i++; + } +} + +link_changes_internal( func_for_link_list, func_for_unlink_list ) +{ + if ( isDefined( level._link_node_list ) ) + { +/# + println( "Link List" ); +#/ + link_changes_internal_internal( level._link_node_list, func_for_link_list ); + } + if ( isDefined( level._unlink_node_list ) ) + { +/# + println( "UnLink List" ); +#/ + link_changes_internal_internal( level._unlink_node_list, func_for_unlink_list ); + } +} + +link_nodes_wrapper( a, b ) +{ + if ( !nodesarelinked( a, b ) ) + { + linknodes( a, b ); + } +} + +unlink_nodes_wrapper( a, b ) +{ + if ( nodesarelinked( a, b ) ) + { + unlinknodes( a, b ); + } +} + +undo_link_changes() +{ +/# + println( "***" ); + println( "***" ); + println( "*** Undoing link changes" ); +#/ + link_changes_internal( ::unlink_nodes_wrapper, ::link_nodes_wrapper ); + delete_spawned_path_nodes(); +} + +redo_link_changes() +{ +/# + println( "***" ); + println( "***" ); + println( "*** Redoing link changes" ); +#/ + respawn_path_nodes(); + link_changes_internal( ::link_nodes_wrapper, ::unlink_nodes_wrapper ); +} + +set_player_tombstone_index() +{ + if ( !isDefined( level.tombstone_index ) ) + { + level.tombstone_index = 0; + } + if ( !isDefined( self.tombstone_index ) ) + { + self.tombstone_index = level.tombstone_index; + level.tombstone_index++; + } +} + +hotjoin_setup_player( viewmodel ) +{ + if ( is_true( level.passed_introscreen ) && !isDefined( self.first_spawn ) && !isDefined( self.characterindex ) ) + { + self.first_spawn = 1; + self setviewmodel( viewmodel ); + return 1; + } + return 0; +} + +is_temporary_zombie_weapon( str_weapon ) +{ + if ( !is_zombie_perk_bottle( str_weapon ) && level.revive_tool != str_weapon && str_weapon != "zombie_builder_zm" && str_weapon != "chalk_draw_zm" && str_weapon != "no_hands_zm" ) + { + return str_weapon == level.machine_assets[ "packapunch" ].weapon; + } +} + +is_gametype_active( a_gametypes ) +{ + b_is_gametype_active = 0; + if ( !isarray( a_gametypes ) ) + { + a_gametypes = array( a_gametypes ); + } + i = 0; + while ( i < a_gametypes.size ) + { + if ( getDvar( "g_gametype" ) == a_gametypes[ i ] ) + { + b_is_gametype_active = 1; + } + i++; + } + return b_is_gametype_active; +} + +is_createfx_active() +{ + if ( !isDefined( level.createfx_enabled ) ) + { + level.createfx_enabled = getDvar( "createfx" ) != ""; + } + return level.createfx_enabled; +} + +is_zombie_perk_bottle( str_weapon ) +{ + switch( str_weapon ) + { + case "zombie_perk_bottle_additionalprimaryweapon": + case "zombie_perk_bottle_cherry": + case "zombie_perk_bottle_deadshot": + case "zombie_perk_bottle_doubletap": + case "zombie_perk_bottle_jugg": + case "zombie_perk_bottle_marathon": + case "zombie_perk_bottle_nuke": + case "zombie_perk_bottle_oneinch": + case "zombie_perk_bottle_revive": + case "zombie_perk_bottle_sixth_sense": + case "zombie_perk_bottle_sleight": + case "zombie_perk_bottle_tombstone": + case "zombie_perk_bottle_vulture": + case "zombie_perk_bottle_whoswho": + b_is_perk_bottle = 1; + break; + default: + b_is_perk_bottle = 0; + break; + } + return b_is_perk_bottle; +} + +register_custom_spawner_entry( spot_noteworthy, func ) +{ + if ( !isDefined( level.custom_spawner_entry ) ) + { + level.custom_spawner_entry = []; + } + level.custom_spawner_entry[ spot_noteworthy ] = func; +} + +get_player_weapon_limit( player ) +{ + if ( isDefined( level.get_player_weapon_limit ) ) + { + return [[ level.get_player_weapon_limit ]]( player ); + } + weapon_limit = 2; + if ( player hasperk( "specialty_additionalprimaryweapon" ) ) + { + weapon_limit = level.additionalprimaryweapon_limit; + } + return weapon_limit; +} + +get_player_perk_purchase_limit() +{ + if ( isDefined( level.get_player_perk_purchase_limit ) ) + { + return self [[ level.get_player_perk_purchase_limit ]](); + } + return level.perk_purchase_limit; +} diff --git a/patch_zm/maps/mp/zombies/_zm_weap_cymbal_monkey.gsc b/patch_zm/maps/mp/zombies/_zm_weap_cymbal_monkey.gsc new file mode 100644 index 0000000..8e9558b --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_weap_cymbal_monkey.gsc @@ -0,0 +1,577 @@ +#include maps/mp/zombies/_zm_clone; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +#using_animtree( "zombie_cymbal_monkey" ); + +init() +{ + if ( !cymbal_monkey_exists() ) + { + return; + } +/# + level.zombiemode_devgui_cymbal_monkey_give = ::player_give_cymbal_monkey; +#/ + if ( isDefined( level.legacy_cymbal_monkey ) && level.legacy_cymbal_monkey ) + { + level.cymbal_monkey_model = "weapon_zombie_monkey_bomb"; + } + else + { + level.cymbal_monkey_model = "t6_wpn_zmb_monkey_bomb_world"; + } + level._effect[ "monkey_glow" ] = loadfx( "maps/zombie/fx_zombie_monkey_light" ); + level._effect[ "grenade_samantha_steal" ] = loadfx( "maps/zombie/fx_zmb_blackhole_trap_end" ); + level.cymbal_monkeys = []; + scriptmodelsuseanimtree( -1 ); +} + +player_give_cymbal_monkey() +{ + self giveweapon( "cymbal_monkey_zm" ); + self set_player_tactical_grenade( "cymbal_monkey_zm" ); + self thread player_handle_cymbal_monkey(); +} + +player_handle_cymbal_monkey() +{ + self notify( "starting_monkey_watch" ); + self endon( "disconnect" ); + self endon( "starting_monkey_watch" ); + attract_dist_diff = level.monkey_attract_dist_diff; + if ( !isDefined( attract_dist_diff ) ) + { + attract_dist_diff = 45; + } + num_attractors = level.num_monkey_attractors; + if ( !isDefined( num_attractors ) ) + { + num_attractors = 96; + } + max_attract_dist = level.monkey_attract_dist; + if ( !isDefined( max_attract_dist ) ) + { + max_attract_dist = 1536; + } + while ( 1 ) + { + grenade = get_thrown_monkey(); + self player_throw_cymbal_monkey( grenade, num_attractors, max_attract_dist, attract_dist_diff ); + wait 0,05; + } +} + +watch_for_dud( model, actor ) +{ + self endon( "death" ); + self waittill( "grenade_dud" ); + model.dud = 1; + self playsound( "zmb_vox_monkey_scream" ); + self.monk_scream_vox = 1; + wait 3; + if ( isDefined( model ) ) + { + model delete(); + } + if ( isDefined( actor ) ) + { + actor delete(); + } + if ( isDefined( self.damagearea ) ) + { + self.damagearea delete(); + } + if ( isDefined( self ) ) + { + self delete(); + } +} + +watch_for_emp( model, actor ) +{ + self endon( "death" ); + if ( !should_watch_for_emp() ) + { + return; + } + while ( 1 ) + { + level waittill( "emp_detonate", origin, radius ); + if ( distancesquared( origin, self.origin ) < ( radius * radius ) ) + { + break; + } + else + { + } + } + self.stun_fx = 1; + if ( isDefined( level._equipment_emp_destroy_fx ) ) + { + playfx( level._equipment_emp_destroy_fx, self.origin + vectorScale( ( 0, 0, -1 ), 5 ), ( 0, randomfloat( 360 ), 0 ) ); + } + wait 0,15; + self.attract_to_origin = 0; + self deactivate_zombie_point_of_interest(); + model clearanim( %o_monkey_bomb, 0 ); + wait 1; + self detonate(); + wait 1; + if ( isDefined( model ) ) + { + model delete(); + } + if ( isDefined( actor ) ) + { + actor delete(); + } + if ( isDefined( self.damagearea ) ) + { + self.damagearea delete(); + } + if ( isDefined( self ) ) + { + self delete(); + } +} + +clone_player_angles( owner ) +{ + self endon( "death" ); + owner endon( "death" ); + while ( isDefined( self ) ) + { + self.angles = owner.angles; + wait 0,05; + } +} + +show_briefly( showtime ) +{ + self endon( "show_owner" ); + if ( isDefined( self.show_for_time ) ) + { + self.show_for_time = showtime; + return; + } + self.show_for_time = showtime; + self setvisibletoall(); + while ( self.show_for_time > 0 ) + { + self.show_for_time -= 0,05; + wait 0,05; + } + self setvisibletoallexceptteam( level.zombie_team ); + self.show_for_time = undefined; +} + +show_owner_on_attack( owner ) +{ + owner endon( "hide_owner" ); + owner endon( "show_owner" ); + self endon( "explode" ); + self endon( "death" ); + self endon( "grenade_dud" ); + owner.show_for_time = undefined; + for ( ;; ) + { + owner waittill( "weapon_fired" ); + owner thread show_briefly( 0,5 ); + } +} + +hide_owner( owner ) +{ + owner notify( "hide_owner" ); + owner endon( "hide_owner" ); + owner setperk( "specialty_immunemms" ); + owner.no_burning_sfx = 1; + owner notify( "stop_flame_sounds" ); + owner setvisibletoallexceptteam( level.zombie_team ); + owner.hide_owner = 1; + if ( isDefined( level._effect[ "human_disappears" ] ) ) + { + playfx( level._effect[ "human_disappears" ], owner.origin ); + } + self thread show_owner_on_attack( owner ); + evt = self waittill_any_return( "explode", "death", "grenade_dud" ); +/# + println( "ZMCLONE: Player visible again because of " + evt ); +#/ + owner notify( "show_owner" ); + owner unsetperk( "specialty_immunemms" ); + if ( isDefined( level._effect[ "human_disappears" ] ) ) + { + playfx( level._effect[ "human_disappears" ], owner.origin ); + } + owner.no_burning_sfx = undefined; + owner setvisibletoall(); + owner.hide_owner = undefined; + owner show(); +} + +proximity_detonate( owner ) +{ + wait 1,5; + if ( !isDefined( self ) ) + { + return; + } + detonateradius = 96; + explosionradius = detonateradius * 2; + damagearea = spawn( "trigger_radius", self.origin + ( 0, 0, 0 - detonateradius ), 4, detonateradius, detonateradius * 1,5 ); + damagearea setexcludeteamfortrigger( owner.team ); + damagearea enablelinkto(); + damagearea linkto( self ); + self.damagearea = damagearea; + while ( isDefined( self ) ) + { + damagearea waittill( "trigger", ent ); + if ( isDefined( owner ) && ent == owner ) + { + continue; + } + if ( isDefined( ent.team ) && ent.team == owner.team ) + { + continue; + } + self playsound( "wpn_claymore_alert" ); + dist = distance( self.origin, ent.origin ); + radiusdamage( self.origin + vectorScale( ( 0, 0, -1 ), 12 ), explosionradius, 1, 1, owner, "MOD_GRENADE_SPLASH", "cymbal_monkey_zm" ); + if ( isDefined( owner ) ) + { + self detonate( owner ); + } + else + { + self detonate( undefined ); + } + break; + } + if ( isDefined( damagearea ) ) + { + damagearea delete(); + } +} + +player_throw_cymbal_monkey( grenade, num_attractors, max_attract_dist, attract_dist_diff ) +{ + self endon( "disconnect" ); + self endon( "starting_monkey_watch" ); + if ( isDefined( grenade ) ) + { + grenade endon( "death" ); + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + if ( isDefined( grenade.damagearea ) ) + { + grenade.damagearea delete(); + } + grenade delete(); + return; + } + grenade hide(); + model = spawn( "script_model", grenade.origin ); + model setmodel( level.cymbal_monkey_model ); + model useanimtree( -1 ); + model linkto( grenade ); + model.angles = grenade.angles; + model thread monkey_cleanup( grenade ); + clone = undefined; + if ( isDefined( level.cymbal_monkey_dual_view ) && level.cymbal_monkey_dual_view ) + { + model setvisibletoallexceptteam( level.zombie_team ); + clone = maps/mp/zombies/_zm_clone::spawn_player_clone( self, vectorScale( ( 0, 0, -1 ), 999 ), level.cymbal_monkey_clone_weapon, undefined ); + model.simulacrum = clone; + clone maps/mp/zombies/_zm_clone::clone_animate( "idle" ); + clone thread clone_player_angles( self ); + clone notsolid(); + clone ghost(); + } + grenade thread watch_for_dud( model, clone ); + grenade thread watch_for_emp( model, clone ); + info = spawnstruct(); + info.sound_attractors = []; + grenade thread monitor_zombie_groans( info ); + grenade waittill( "stationary" ); + if ( isDefined( level.grenade_planted ) ) + { + self thread [[ level.grenade_planted ]]( grenade, model ); + } + if ( isDefined( grenade ) ) + { + if ( isDefined( model ) ) + { + model setanim( %o_monkey_bomb ); + if ( isDefined( grenade.backlinked ) && !grenade.backlinked ) + { + model unlink(); + model.origin = grenade.origin; + model.angles = grenade.angles; + } + } + if ( isDefined( clone ) ) + { + clone forceteleport( grenade.origin, grenade.angles ); + clone thread hide_owner( self ); + grenade thread proximity_detonate( self ); + clone show(); + clone setinvisibletoall(); + clone setvisibletoteam( level.zombie_team ); + } + grenade resetmissiledetonationtime(); + playfxontag( level._effect[ "monkey_glow" ], model, "origin_animate_jnt" ); + valid_poi = check_point_in_enabled_zone( grenade.origin, undefined, undefined ); + if ( isDefined( level.check_valid_poi ) ) + { + valid_poi = grenade [[ level.check_valid_poi ]]( valid_poi ); + } + if ( valid_poi ) + { + grenade create_zombie_point_of_interest( max_attract_dist, num_attractors, 10000 ); + grenade.attract_to_origin = 1; + grenade thread create_zombie_point_of_interest_attractor_positions( 4, attract_dist_diff ); + grenade thread wait_for_attractor_positions_complete(); + grenade thread do_monkey_sound( model, info ); + level.cymbal_monkeys[ level.cymbal_monkeys.size ] = grenade; + } + else + { + grenade.script_noteworthy = undefined; + level thread grenade_stolen_by_sam( grenade, model, clone ); + } + return; + } + else + { + grenade.script_noteworthy = undefined; + level thread grenade_stolen_by_sam( grenade, model, clone ); + } + } +} + +grenade_stolen_by_sam( ent_grenade, ent_model, ent_actor ) +{ + if ( !isDefined( ent_model ) ) + { + return; + } + direction = ent_model.origin; + direction = ( direction[ 1 ], direction[ 0 ], 0 ); + if ( direction[ 1 ] < 0 || direction[ 0 ] > 0 && direction[ 1 ] > 0 ) + { + direction = ( direction[ 0 ], direction[ 1 ] * -1, 0 ); + } + else + { + if ( direction[ 0 ] < 0 ) + { + direction = ( direction[ 0 ] * -1, direction[ 1 ], 0 ); + } + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isalive( players[ i ] ) ) + { + players[ i ] playlocalsound( level.zmb_laugh_alias ); + } + i++; + } + playfxontag( level._effect[ "grenade_samantha_steal" ], ent_model, "tag_origin" ); + ent_model movez( 60, 1, 0,25, 0,25 ); + ent_model vibrate( direction, 1,5, 2,5, 1 ); + ent_model waittill( "movedone" ); + if ( isDefined( self.damagearea ) ) + { + self.damagearea delete(); + } + ent_model delete(); + if ( isDefined( ent_actor ) ) + { + ent_actor delete(); + } + if ( isDefined( ent_grenade ) ) + { + if ( isDefined( ent_grenade.damagearea ) ) + { + ent_grenade.damagearea delete(); + } + ent_grenade delete(); + } +} + +wait_for_attractor_positions_complete() +{ + self waittill( "attractor_positions_generated" ); + self.attract_to_origin = 0; +} + +monkey_cleanup( parent ) +{ + while ( 1 ) + { + if ( !isDefined( parent ) ) + { + if ( isDefined( self ) && isDefined( self.dud ) && self.dud ) + { + wait 6; + } + if ( isDefined( self.simulacrum ) ) + { + self.simulacrum delete(); + } + self_delete(); + return; + } + wait 0,05; + } +} + +do_monkey_sound( model, info ) +{ + self.monk_scream_vox = 0; + if ( isDefined( level.grenade_safe_to_bounce ) ) + { + if ( !( [[ level.grenade_safe_to_bounce ]]( self.owner, "cymbal_monkey_zm" ) ) ) + { + self playsound( "zmb_vox_monkey_scream" ); + self.monk_scream_vox = 1; + } + } + if ( !self.monk_scream_vox && level.music_override == 0 ) + { + if ( isDefined( level.cymbal_monkey_dual_view ) && level.cymbal_monkey_dual_view ) + { + self playsoundtoteam( "zmb_monkey_song", "allies" ); + } + else + { + self playsound( "zmb_monkey_song" ); + } + } + if ( !self.monk_scream_vox ) + { + self thread play_delayed_explode_vox(); + } + self waittill( "explode", position ); + level notify( "grenade_exploded" ); + monkey_index = -1; + i = 0; + while ( i < level.cymbal_monkeys.size ) + { + if ( !isDefined( level.cymbal_monkeys[ i ] ) ) + { + monkey_index = i; + break; + } + else + { + i++; + } + } + if ( monkey_index >= 0 ) + { + arrayremoveindex( level.cymbal_monkeys, monkey_index ); + } + if ( isDefined( model ) ) + { + model clearanim( %o_monkey_bomb, 0,2 ); + } + i = 0; + while ( i < info.sound_attractors.size ) + { + if ( isDefined( info.sound_attractors[ i ] ) ) + { + info.sound_attractors[ i ] notify( "monkey_blown_up" ); + } + i++; + } +} + +play_delayed_explode_vox() +{ + wait 6,5; + if ( isDefined( self ) ) + { + self playsound( "zmb_vox_monkey_explode" ); + } +} + +get_thrown_monkey() +{ + self endon( "disconnect" ); + self endon( "starting_monkey_watch" ); + while ( 1 ) + { + self waittill( "grenade_fire", grenade, weapname ); + if ( weapname == "cymbal_monkey_zm" ) + { + grenade.use_grenade_special_long_bookmark = 1; + grenade.grenade_multiattack_bookmark_count = 1; + return grenade; + } + wait 0,05; + } +} + +monitor_zombie_groans( info ) +{ + self endon( "explode" ); + while ( 1 ) + { + if ( !isDefined( self ) ) + { + return; + } + while ( !isDefined( self.attractor_array ) ) + { + wait 0,05; + } + i = 0; + while ( i < self.attractor_array.size ) + { + if ( array_check_for_dupes( info.sound_attractors, self.attractor_array[ i ] ) ) + { + if ( isDefined( self.origin ) && isDefined( self.attractor_array[ i ].origin ) ) + { + if ( distancesquared( self.origin, self.attractor_array[ i ].origin ) < 250000 ) + { + info.sound_attractors[ info.sound_attractors.size ] = self.attractor_array[ i ]; + self.attractor_array[ i ] thread play_zombie_groans(); + } + } + } + i++; + } + wait 0,05; + } +} + +play_zombie_groans() +{ + self endon( "death" ); + self endon( "monkey_blown_up" ); + while ( 1 ) + { + if ( isDefined( self ) ) + { + self playsound( "zmb_vox_zombie_groan" ); + wait randomfloatrange( 2, 3 ); + continue; + } + else + { + return; + } + } +} + +cymbal_monkey_exists() +{ + return isDefined( level.zombie_weapons[ "cymbal_monkey_zm" ] ); +} diff --git a/patch_zm/readme.md b/patch_zm/readme.md index 34c0a23..59aa682 100644 --- a/patch_zm/readme.md +++ b/patch_zm/readme.md @@ -5,29 +5,15 @@ patch_zm/maps/mp/gametypes_zm/_globalentities.gsc patch_zm/maps/mp/gametypes_zm/_scoreboard.gsc patch_zm/maps/mp/gametypes_zm/_shellshock.gsc patch_zm/maps/mp/gametypes_zm/zclassic.gsc -patch_zm/maps/mp/zombies/_zm_ai_basic.gsc patch_zm/maps/mp/zombies/_zm_ai_dogs.gsc -patch_zm/maps/mp/zombies/_zm_ai_faller.gsc patch_zm/maps/mp/zombies/_zm_audio.gsc patch_zm/maps/mp/zombies/_zm_audio_announcer.gsc patch_zm/maps/mp/zombies/_zm_bot.gsc -patch_zm/maps/mp/zombies/_zm_clone.gsc -patch_zm/maps/mp/zombies/_zm_equip_hacker.gsc -patch_zm/maps/mp/zombies/_zm_equip_gasmask.gsc -patch_zm/maps/mp/zombies/_zm_ffotd.gsc -patch_zm/maps/mp/zombies/_zm_hackables_boards.gsc -patch_zm/maps/mp/zombies/_zm_hackables_box.gsc -patch_zm/maps/mp/zombies/_zm_hackables_doors.gsc -patch_zm/maps/mp/zombies/_zm_hackables_packapunch.gsc -patch_zm/maps/mp/zombies/_zm_hackables_perks.gsc -patch_zm/maps/mp/zombies/_zm_hackables_powerups.gsc -patch_zm/maps/mp/zombies/_zm_hackables_wallbuys.gsc patch_zm/maps/mp/zombies/_zm_magicbox.gsc patch_zm/maps/mp/zombies/_zm_net.gsc patch_zm/maps/mp/zombies/_zm_perk_electric_cherry.gsc -patch_zm/maps/mp/zombies/_zm_pers_upgrades.gsc -patch_zm/maps/mp/zombies/_zm_pers_upgrades_functions.gsc -patch_zm/maps/mp/zombies/_zm_pers_upgrades_system.gsc +patch_zm/maps/mp/zombies/_zm_perks.gsc +patch_zm/maps/mp/zombies/_zm_powerups.gsc patch_zm/maps/mp/zombies/_zm_server_throttle.gsc patch_zm/maps/mp/zombies/_zm_score.gsc patch_zm/maps/mp/zombies/_zm_tombstone.gsc @@ -41,8 +27,6 @@ patch_zm/maps/mp/zombies/_zm_timer.gsc ``` patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc patch_zm/maps/mp/zombies/_zm_chugabud.gsc -patch_zm/maps/mp/zombies/_zm_perks.gsc -patch_zm/maps/mp/zombies/_zm_powerups.gsc patch_zm/maps/mp/zombies/_zm_spawner.gsc patch_zm/maps/mp/zombies/_zm_weapons.gsc ``` @@ -58,7 +42,46 @@ patch_zm/maps/mp/zombies/_load.gsc ``` ### The following scripts are not tested yet, uploaded to setup a baseline: ``` +patch_zm/maps/mp/zombies/_zm_blockers.gsc +patch_zm/maps/mp/zombies/_zm_buildables.gsc +patch_zm/maps/mp/zombies/_zm_devgui.gsc +patch_zm/maps/mp/zombies/_zm_equip_turbine.gsc +patch_zm/maps/mp/zombies/_zm_game_module.gsc +patch_zm/maps/mp/zombies/_zm_jump_pad.gsc +patch_zm/maps/mp/zombies/_zm_laststand.gsc +patch_zm/maps/mp/zombies/_zm_magicbox_lock.gsc +patch_zm/maps/mp/zombies/_zm_mgturret.gsc +patch_zm/maps/mp/zombies/_zm_playerhealth.gsc +patch_zm/maps/mp/zombies/_zm_power.gsc +patch_zm/maps/mp/zombies/_zm_sidequests.gsc +patch_zm/maps/mp/zombies/_zm_stats.gsc +patch_zm/maps/mp/zombies/_zm_traps.gsc +patch_zm/maps/mp/zombies/_zm_turned.gsc +patch_zm/maps/mp/zombies/_zm_unitrigger.gsc +patch_zm/maps/mp/zombies/_zm_utility.gsc +patch_zm/maps/mp/zombies/_zm_weap_cymbal_monkey.gsc ``` + +### The following scripts have not been checked using the proper debugging methods: +``` +patch_zm/maps/mp/zombies/_zm_ai_basic.gsc +patch_zm/maps/mp/zombies/_zm_ai_faller.gsc +patch_zm/maps/mp/zombies/_zm_clone.gsc +patch_zm/maps/mp/zombies/_zm_equip_hacker.gsc +patch_zm/maps/mp/zombies/_zm_equip_gasmask.gsc +patch_zm/maps/mp/zombies/_zm_ffotd.gsc +patch_zm/maps/mp/zombies/_zm_hackables_boards.gsc +patch_zm/maps/mp/zombies/_zm_hackables_box.gsc +patch_zm/maps/mp/zombies/_zm_hackables_doors.gsc +patch_zm/maps/mp/zombies/_zm_hackables_packapunch.gsc +patch_zm/maps/mp/zombies/_zm_hackables_perks.gsc +patch_zm/maps/mp/zombies/_zm_hackables_powerups.gsc +patch_zm/maps/mp/zombies/_zm_hackables_wallbuys.gsc +patch_zm/maps/mp/zombies/_zm_pers_upgrades.gsc +patch_zm/maps/mp/zombies/_zm_pers_upgrades_functions.gsc +patch_zm/maps/mp/zombies/_zm_pers_upgrades_system.gsc +``` + ### notes: ``` The shaders that _zm_timer.gsc relies on do not exist.