From 18b75a333db5dc500c248ed4792309b3a039e5a3 Mon Sep 17 00:00:00 2001 From: JezuzLizard Date: Thu, 26 Mar 2020 01:42:33 -0700 Subject: [PATCH] added more files --- .../patch_zm/maps/mp/zombies/_load.gsc | 523 +++ .../patch_zm/maps/mp/zombies/_zm_ai_basic.gsc | 571 +++ .../maps/mp/zombies/_zm_ai_faller.gsc | 642 +++ .../maps/mp/zombies/_zm_equip_hacker.gsc | 915 ++++ .../maps/mp/zombies/_zm_equipment.gsc | 1953 ++++++++ .../patch_zm/maps/mp/zombies/_zm_gump.gsc | 81 + .../maps/mp/zombies/_zm_hackables_boards.gsc | 131 + .../maps/mp/zombies/_zm_hackables_box.gsc | 371 ++ .../maps/mp/zombies/_zm_hackables_doors.gsc | 108 + .../mp/zombies/_zm_hackables_packapunch.gsc | 46 + .../maps/mp/zombies/_zm_hackables_perks.gsc | 87 + .../mp/zombies/_zm_hackables_powerups.gsc | 79 + .../mp/zombies/_zm_hackables_wallbuys.gsc | 55 + .../maps/mp/zombies/_zm_perk_upgrades.gsc | 685 +++ .../patch_zm/maps/mp/zombies/_zm_perks.gsc | 4165 +++++++++++++++++ .../zombies/_zm_pers_upgrades_functions.gsc | 1445 ++++++ .../mp/zombies/_zm_pers_upgrades_system.gsc | 278 ++ .../patch_zm/maps/mp/zombies/_zm_score.gsc | 397 ++ Fixed Zombies GSCs for compiling/readme.md | 56 +- 19 files changed, 12575 insertions(+), 13 deletions(-) create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_load.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_basic.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_faller.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equip_hacker.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equipment.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_gump.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_boards.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_box.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_doors.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_packapunch.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_perks.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_powerups.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_wallbuys.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perk_upgrades.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perks.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_functions.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_system.gsc create mode 100644 Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_score.gsc diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_load.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_load.gsc new file mode 100644 index 0000000..cd154dd --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_load.gsc @@ -0,0 +1,523 @@ +#include maps/mp/gametypes_zm/_spawnlogic; +#include maps/mp/animscripts/traverse/shared; +#include maps/mp/animscripts/utility; +#include maps/mp/zombies/_load; +#include maps/mp/_createfx; +#include maps/mp/_music; +#include maps/mp/_busing; +#include maps/mp/_script_gen; +#include maps/mp/_utility; +#include common_scripts/utility; + +main( bscriptgened, bcsvgened, bsgenabled ) +{ + if ( !isDefined( level.script_gen_dump_reasons ) ) + { + level.script_gen_dump_reasons = []; + } + if ( !isDefined( bsgenabled ) ) + { + level.script_gen_dump_reasons[ level.script_gen_dump_reasons.size ] = "First run"; + } + if ( !isDefined( bcsvgened ) ) + { + bcsvgened = 0; + } + level.bcsvgened = bcsvgened; + if ( !isDefined( bscriptgened ) ) + { + bscriptgened = 0; + } + else + { + bscriptgened = 1; + } + level.bscriptgened = bscriptgened; + level._loadstarted = 1; + struct_class_init(); + level.clientscripts = getDvar( "cg_usingClientScripts" ) != ""; + level._client_exploders = []; + level._client_exploder_ids = []; + if ( !isDefined( level.flag ) ) + { + level.flag = []; + level.flags_lock = []; + } + if ( !isDefined( level.timeofday ) ) + { + level.timeofday = "day"; + } + flag_init( "scriptgen_done" ); + level.script_gen_dump_reasons = []; + if ( !isDefined( level.script_gen_dump ) ) + { + level.script_gen_dump = []; + level.script_gen_dump_reasons[ 0 ] = "First run"; + } + if ( !isDefined( level.script_gen_dump2 ) ) + { + level.script_gen_dump2 = []; + } + if ( isDefined( level.createfxent ) && isDefined( level.script ) ) + { + script_gen_dump_addline( "maps\\mp\\createfx\\" + level.script + "_fx::main();", level.script + "_fx" ); + } + while ( isDefined( level.script_gen_dump_preload ) ) + { + i = 0; + while ( i < level.script_gen_dump_preload.size ) + { + script_gen_dump_addline( level.script_gen_dump_preload[ i ].string, level.script_gen_dump_preload[ i ].signature ); + i++; + } + } + if ( getDvar( "scr_RequiredMapAspectratio" ) == "" ) + { + setdvar( "scr_RequiredMapAspectratio", "1" ); + } + setdvar( "r_waterFogTest", 0 ); + precacherumble( "reload_small" ); + precacherumble( "reload_medium" ); + precacherumble( "reload_large" ); + precacherumble( "reload_clipin" ); + precacherumble( "reload_clipout" ); + precacherumble( "reload_rechamber" ); + precacherumble( "pullout_small" ); + precacherumble( "buzz_high" ); + precacherumble( "riotshield_impact" ); + registerclientsys( "levelNotify" ); + level.aitriggerspawnflags = getaitriggerflags(); + level.vehicletriggerspawnflags = getvehicletriggerflags(); + level.physicstracemaskphysics = 1; + level.physicstracemaskvehicle = 2; + level.physicstracemaskwater = 4; + level.physicstracemaskclip = 8; + level.physicstracecontentsvehicleclip = 16; + level.createfx_enabled = getDvar( "createfx" ) != ""; + level thread start_intro_screen_zm(); + thread maps/mp/_interactive_objects::init(); + maps/mp/_audio::init(); + thread maps/mp/_busing::businit(); + thread maps/mp/_music::music_init(); + thread maps/mp/_fxanim::init(); + thread maps/mp/_serverfaceanim_mp::init(); + if ( level.createfx_enabled ) + { + setinitialplayersconnected(); + } + visionsetnight( "default_night" ); + setup_traversals(); + maps/mp/_art::main(); + setupexploders(); + parse_structs(); + thread footsteps(); + /* +/# + level thread level_notify_listener(); + level thread client_notify_listener(); +#/ + */ + thread maps/mp/_createfx::fx_init(); + if ( level.createfx_enabled ) + { + calculate_map_center(); + maps/mp/_createfx::createfx(); + } + if ( getDvar( "r_reflectionProbeGenerate" ) == "1" ) + { + maps/mp/_global_fx::main(); + level waittill( "eternity" ); + } + thread maps/mp/_global_fx::main(); + maps/mp/_demo::init(); + p = 0; + while ( p < 6 ) + { + switch( p ) + { + case 0: + triggertype = "trigger_multiple"; + break; + case 1: + triggertype = "trigger_once"; + break; + case 2: + triggertype = "trigger_use"; + break; + case 3: + triggertype = "trigger_radius"; + break; + case 4: + triggertype = "trigger_lookat"; + break; + default: + /* +/# + assert( p == 5 ); +#/ + */ + triggertype = "trigger_damage"; + break; + } + triggers = getentarray( triggertype, "classname" ); + i = 0; + while ( i < triggers.size ) + { + if ( isDefined( triggers[ i ].script_prefab_exploder ) ) + { + triggers[ i ].script_exploder = triggers[ i ].script_prefab_exploder; + } + if ( isDefined( triggers[ i ].script_exploder ) ) + { + level thread maps/mp/zombies/_load::exploder_load( triggers[ i ] ); + } + i++; + } + p++; + } +} + +level_notify_listener() +{ + while ( 1 ) + { + val = getDvar( "level_notify" ); + if ( val != "" ) + { + level notify( val ); + setdvar( "level_notify", "" ); + } + wait 0.2; + } +} + +client_notify_listener() +{ + while ( 1 ) + { + val = getDvar( "client_notify" ); + if ( val != "" ) + { + clientnotify( val ); + setdvar( "client_notify", "" ); + } + wait 0.2; + } +} + +footsteps() +{ + if ( is_true( level.fx_exclude_footsteps ) ) + { + return; + } + maps/mp/animscripts/utility::setfootstepeffect( "asphalt", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "brick", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "carpet", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "cloth", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "concrete", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "dirt", loadfx( "bio/player/fx_footstep_sand" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "foliage", loadfx( "bio/player/fx_footstep_sand" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "gravel", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "grass", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "metal", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "mud", loadfx( "bio/player/fx_footstep_mud" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "paper", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "plaster", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "rock", loadfx( "bio/player/fx_footstep_dust" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "sand", loadfx( "bio/player/fx_footstep_sand" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "water", loadfx( "bio/player/fx_footstep_water" ) ); + maps/mp/animscripts/utility::setfootstepeffect( "wood", loadfx( "bio/player/fx_footstep_dust" ) ); +} + +parse_structs() +{ + i = 0; + while ( i < level.struct.size ) + { + if ( isDefined( level.struct[ i ].targetname ) ) + { + if ( level.struct[ i ].targetname == "flak_fire_fx" ) + { + level._effect[ "flak20_fire_fx" ] = loadfx( "weapon/tracer/fx_tracer_flak_single_noExp" ); + level._effect[ "flak38_fire_fx" ] = loadfx( "weapon/tracer/fx_tracer_quad_20mm_Flak38_noExp" ); + level._effect[ "flak_cloudflash_night" ] = loadfx( "weapon/flak/fx_flak_cloudflash_night" ); + level._effect[ "flak_burst_single" ] = loadfx( "weapon/flak/fx_flak_single_day_dist" ); + } + if ( level.struct[ i ].targetname == "fake_fire_fx" ) + { + level._effect[ "distant_muzzleflash" ] = loadfx( "weapon/muzzleflashes/heavy" ); + } + if ( level.struct[ i ].targetname == "spotlight_fx" ) + { + level._effect[ "spotlight_beam" ] = loadfx( "env/light/fx_ray_spotlight_md" ); + } + } + i++; + } +} + +exploder_load( trigger ) +{ + level endon( "killexplodertridgers" + trigger.script_exploder ); + trigger waittill( "trigger" ); + if ( isDefined( trigger.script_chance ) && randomfloat( 1 ) > trigger.script_chance ) + { + if ( isDefined( trigger.script_delay ) ) + { + wait trigger.script_delay; + } + else + { + wait 4; + } + level thread exploder_load( trigger ); + return; + } + maps/mp/_utility::exploder( trigger.script_exploder ); + level notify( "killexplodertridgers" + trigger.script_exploder ); +} + +setupexploders() +{ + ents = getentarray( "script_brushmodel", "classname" ); + smodels = getentarray( "script_model", "classname" ); + i = 0; + while ( i < smodels.size ) + { + ents[ ents.size ] = smodels[ i ]; + i++; + } + i = 0; + while ( i < ents.size ) + { + if ( isDefined( ents[ i ].script_prefab_exploder ) ) + { + ents[ i ].script_exploder = ents[ i ].script_prefab_exploder; + } + if ( isDefined( ents[ i ].script_exploder ) ) + { + if ( ents[ i ].model == "fx" || !isDefined( ents[ i ].targetname ) && ents[ i ].targetname != "exploderchunk" ) + { + ents[ i ] hide(); + i++; + continue; + } + else + { + 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(); + } + } + } + } + i++; + } + script_exploders = []; + potentialexploders = getentarray( "script_brushmodel", "classname" ); + i = 0; + while ( i < potentialexploders.size ) + { + if ( isDefined( potentialexploders[ i ].script_prefab_exploder ) ) + { + potentialexploders[ i ].script_exploder = potentialexploders[ i ].script_prefab_exploder; + } + if ( isDefined( potentialexploders[ i ].script_exploder ) ) + { + script_exploders[ script_exploders.size ] = potentialexploders[ i ]; + } + i++; + } + potentialexploders = getentarray( "script_model", "classname" ); + i = 0; + while ( i < potentialexploders.size ) + { + if ( isDefined( potentialexploders[ i ].script_prefab_exploder ) ) + { + potentialexploders[ i ].script_exploder = potentialexploders[ i ].script_prefab_exploder; + } + if ( isDefined( potentialexploders[ i ].script_exploder ) ) + { + script_exploders[ script_exploders.size ] = potentialexploders[ i ]; + } + i++; + } + potentialexploders = getentarray( "item_health", "classname" ); + i = 0; + while ( i < potentialexploders.size ) + { + if ( isDefined( potentialexploders[ i ].script_prefab_exploder ) ) + { + potentialexploders[ i ].script_exploder = potentialexploders[ i ].script_prefab_exploder; + } + if ( isDefined( potentialexploders[ i ].script_exploder ) ) + { + script_exploders[ script_exploders.size ] = potentialexploders[ i ]; + } + i++; + } + if ( !isDefined( level.createfxent ) ) + { + level.createfxent = []; + } + acceptabletargetnames = []; + acceptabletargetnames[ "exploderchunk visible" ] = 1; + acceptabletargetnames[ "exploderchunk" ] = 1; + acceptabletargetnames[ "exploder" ] = 1; + i = 0; + while ( i < script_exploders.size ) + { + exploder = script_exploders[ i ]; + ent = createexploder( exploder.script_fxid ); + ent.v = []; + ent.v[ "origin" ] = exploder.origin; + ent.v[ "angles" ] = exploder.angles; + ent.v[ "delay" ] = exploder.script_delay; + ent.v[ "firefx" ] = exploder.script_firefx; + ent.v[ "firefxdelay" ] = exploder.script_firefxdelay; + ent.v[ "firefxsound" ] = exploder.script_firefxsound; + ent.v[ "firefxtimeout" ] = exploder.script_firefxtimeout; + ent.v[ "earthquake" ] = exploder.script_earthquake; + ent.v[ "damage" ] = exploder.script_damage; + ent.v[ "damage_radius" ] = exploder.script_radius; + ent.v[ "soundalias" ] = exploder.script_soundalias; + ent.v[ "repeat" ] = exploder.script_repeat; + ent.v[ "delay_min" ] = exploder.script_delay_min; + ent.v[ "delay_max" ] = exploder.script_delay_max; + ent.v[ "target" ] = exploder.target; + ent.v[ "ender" ] = exploder.script_ender; + ent.v[ "type" ] = "exploder"; + if ( !isDefined( exploder.script_fxid ) ) + { + ent.v[ "fxid" ] = "No FX"; + } + else + { + ent.v[ "fxid" ] = exploder.script_fxid; + } + ent.v[ "exploder" ] = exploder.script_exploder; + /* +/# + assert( isDefined( exploder.script_exploder ), "Exploder at origin " + exploder.origin + " has no script_exploder" ); +#/ + */ + if ( !isDefined( ent.v[ "delay" ] ) ) + { + ent.v[ "delay" ] = 0; + } + if ( isDefined( exploder.target ) ) + { + org = getent( ent.v[ "target" ], "targetname" ).origin; + ent.v[ "angles" ] = vectorToAngles( org - ent.v[ "origin" ] ); + } + if ( exploder.classname == "script_brushmodel" || isDefined( exploder.model ) ) + { + ent.model = exploder; + ent.model.disconnect_paths = exploder.script_disconnectpaths; + } + if ( isDefined( exploder.targetname ) && isDefined( acceptabletargetnames[ exploder.targetname ] ) ) + { + ent.v[ "exploder_type" ] = exploder.targetname; + } + else + { + ent.v[ "exploder_type" ] = "normal"; + } + ent maps/mp/_createfx::post_entity_creation_function(); + i++; + } + level.createfxexploders = []; + i = 0; + while ( i < level.createfxent.size ) + { + ent = level.createfxent[ i ]; + if ( ent.v[ "type" ] != "exploder" ) + { + i++; + continue; + } + else + { + 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; + } + i++; + } +} + +setup_traversals() +{ + potential_traverse_nodes = getallnodes(); + i = 0; + while ( i < potential_traverse_nodes.size ) + { + node = potential_traverse_nodes[ i ]; + if ( node.type == "Begin" ) + { + node maps/mp/animscripts/traverse/shared::init_traverse(); + } + i++; + } +} + +calculate_map_center() +{ + if ( !isDefined( level.mapcenter ) ) + { + level.nodesmins = ( 0, 0, 0 ); + level.nodesmaxs = ( 0, 0, 0 ); + level.mapcenter = maps/mp/gametypes_zm/_spawnlogic::findboxcenter( level.nodesmins, level.nodesmaxs ); + /* +/# + println( "map center: ", level.mapcenter ); +#/ + */ + setmapcenter( level.mapcenter ); + } +} + +start_intro_screen_zm() +{ + if ( level.createfx_enabled ) + { + return; + } + if ( !isDefined( level.introscreen ) ) + { + level.introscreen = newhudelem(); + level.introscreen.x = 0; + level.introscreen.y = 0; + level.introscreen.horzalign = "fullscreen"; + level.introscreen.vertalign = "fullscreen"; + level.introscreen.foreground = 0; + level.introscreen setshader( "black", 640, 480 ); + level.introscreen.immunetodemogamehudsettings = 1; + level.introscreen.immunetodemofreecamera = 1; + wait 0.05; + } + level.introscreen.alpha = 1; + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] freezecontrols( 1 ); + i++; + } + wait 1; +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_basic.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_basic.gsc new file mode 100644 index 0000000..f5a13ed --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_basic.gsc @@ -0,0 +1,571 @@ +#include maps/mp/animscripts/zm_shared; +#include maps/mp/animscripts/zm_run; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +find_flesh() +{ + self endon( "death" ); + level endon( "intermission" ); + self endon( "stop_find_flesh" ); + if ( level.intermission ) + { + return; + } + self.ai_state = "find_flesh"; + self.helitarget = 1; + self.ignoreme = 0; + self.nododgemove = 1; + self.ignore_player = []; + self maps/mp/zombies/_zm_spawner::zombie_history( "find flesh -> start" ); + self.goalradius = 32; + if ( isDefined( self.custom_goalradius_override ) ) + { + self.goalradius = self.custom_goalradius_override; + } + while ( 1 ) + { + zombie_poi = undefined; + if ( isDefined( level.zombietheaterteleporterseeklogicfunc ) ) + { + self [[ level.zombietheaterteleporterseeklogicfunc ]](); + } + if ( isDefined( level._poi_override ) ) + { + zombie_poi = self [[ level._poi_override ]](); + } + if ( !isDefined( zombie_poi ) ) + { + zombie_poi = self get_zombie_point_of_interest( self.origin ); + } + players = get_players(); + if ( !isDefined( self.ignore_player ) || players.size == 1 ) + { + self.ignore_player = []; + } + else + { + while ( !isDefined( level._should_skip_ignore_player_logic ) || !( [[ level._should_skip_ignore_player_logic ]]() ) ) + { + i = 0; + while ( i < self.ignore_player.size ) + { + while ( isDefined( self.ignore_player[ i ] ) && isDefined( self.ignore_player[ i ].ignore_counter ) && self.ignore_player[ i ].ignore_counter > 3 ) + { + self.ignore_player[ i ].ignore_counter = 0; + self.ignore_player = arrayremovevalue( self.ignore_player, self.ignore_player[ i ] ); + if ( !isDefined( self.ignore_player ) ) + { + self.ignore_player = []; + } + i = 0; + } + i++; + } + } + } + player = get_closest_valid_player( self.origin, self.ignore_player ); + while ( !isDefined( player ) && !isDefined( zombie_poi ) ) + { + self maps/mp/zombies/_zm_spawner::zombie_history( "find flesh -> can't find player, continue" ); + if ( isDefined( self.ignore_player ) ) + { + while ( isDefined( level._should_skip_ignore_player_logic ) && [[ level._should_skip_ignore_player_logic ]]() ) + { + wait 1; + } + self.ignore_player = []; + } + wait 1; + } + if ( !isDefined( level.check_for_alternate_poi ) || !( [[ level.check_for_alternate_poi ]]() ) ) + { + self.enemyoverride = zombie_poi; + self.favoriteenemy = player; + } + self thread zombie_pathing(); + while ( players.size > 1 ) + { + i = 0; + while ( i < self.ignore_player.size ) + { + if ( isDefined( self.ignore_player[ i ] ) ) + { + if ( !isDefined( self.ignore_player[ i ].ignore_counter ) ) + { + self.ignore_player[ i ].ignore_counter = 0; + i++; + continue; + } + else + { + self.ignore_player[ i ].ignore_counter += 1; + } + } + i++; + } + } + self thread attractors_generated_listener(); + if ( isDefined( level._zombie_path_timer_override ) ) + { + self.zombie_path_timer = [[ level._zombie_path_timer_override ]](); + } + else + { + self.zombie_path_timer = getTime() + ( randomfloatrange( 1, 3 ) * 1000 ); + } + while ( getTime() < self.zombie_path_timer ) + { + wait 0.1; + } + self notify( "path_timer_done" ); + self maps/mp/zombies/_zm_spawner::zombie_history( "find flesh -> bottom of loop" ); + debug_print( "Zombie is re-acquiring enemy, ending breadcrumb search" ); + self notify( "zombie_acquire_enemy" ); + } +} + +init_inert_zombies() +{ + level init_inert_substates(); +} + +init_inert_substates() +{ + level.inert_substates = []; + level.inert_substates[ level.inert_substates.size ] = "inert1"; + level.inert_substates[ level.inert_substates.size ] = "inert2"; + level.inert_substates[ level.inert_substates.size ] = "inert3"; + level.inert_substates[ level.inert_substates.size ] = "inert4"; + level.inert_substates[ level.inert_substates.size ] = "inert5"; + level.inert_substates[ level.inert_substates.size ] = "inert6"; + level.inert_substates[ level.inert_substates.size ] = "inert7"; + level.inert_substates = array_randomize( level.inert_substates ); + level.inert_substate_index = 0; + level.inert_trans_walk = []; + level.inert_trans_walk[ level.inert_trans_walk.size ] = "inert_2_walk_1"; + level.inert_trans_walk[ level.inert_trans_walk.size ] = "inert_2_walk_2"; + level.inert_trans_walk[ level.inert_trans_walk.size ] = "inert_2_walk_3"; + level.inert_trans_walk[ level.inert_trans_walk.size ] = "inert_2_walk_4"; + level.inert_trans_run = []; + level.inert_trans_run[ level.inert_trans_run.size ] = "inert_2_run_1"; + level.inert_trans_run[ level.inert_trans_run.size ] = "inert_2_run_2"; + level.inert_trans_sprint = []; + level.inert_trans_sprint[ level.inert_trans_sprint.size ] = "inert_2_sprint_1"; + level.inert_trans_sprint[ level.inert_trans_sprint.size ] = "inert_2_sprint_2"; + level.inert_crawl_substates = []; + level.inert_crawl_substates[ level.inert_crawl_substates.size ] = "inert1"; + level.inert_crawl_substates[ level.inert_crawl_substates.size ] = "inert2"; + level.inert_crawl_substates[ level.inert_crawl_substates.size ] = "inert3"; + level.inert_crawl_substates[ level.inert_crawl_substates.size ] = "inert4"; + level.inert_crawl_substates[ level.inert_crawl_substates.size ] = "inert5"; + level.inert_crawl_substates[ level.inert_crawl_substates.size ] = "inert6"; + level.inert_crawl_substates[ level.inert_crawl_substates.size ] = "inert7"; + level.inert_crawl_trans_walk = []; + level.inert_crawl_trans_walk[ level.inert_crawl_trans_walk.size ] = "inert_2_walk_1"; + level.inert_crawl_trans_run = []; + level.inert_crawl_trans_run[ level.inert_crawl_trans_run.size ] = "inert_2_run_1"; + level.inert_crawl_trans_run[ level.inert_crawl_trans_run.size ] = "inert_2_run_2"; + level.inert_crawl_trans_sprint = []; + level.inert_crawl_trans_sprint[ level.inert_crawl_trans_sprint.size ] = "inert_2_sprint_1"; + level.inert_crawl_trans_sprint[ level.inert_crawl_trans_sprint.size ] = "inert_2_sprint_2"; + level.inert_crawl_substates = array_randomize( level.inert_crawl_substates ); + level.inert_crawl_substate_index = 0; +} + +get_inert_substate() +{ + substate = level.inert_substates[ level.inert_substate_index ]; + level.inert_substate_index++; + if ( level.inert_substate_index >= level.inert_substates.size ) + { + level.inert_substates = array_randomize( level.inert_substates ); + level.inert_substate_index = 0; + } + return substate; +} + +get_inert_crawl_substate() +{ + substate = level.inert_crawl_substates[ level.inert_crawl_substate_index ]; + level.inert_crawl_substate_index++; + if ( level.inert_crawl_substate_index >= level.inert_crawl_substates.size ) + { + level.inert_crawl_substates = array_randomize( level.inert_crawl_substates ); + level.inert_crawl_substate_index = 0; + } + return substate; +} + +start_inert( in_place ) +{ + self endon( "death" ); + if ( isDefined( self.is_inert ) && self.is_inert ) + { + self maps/mp/zombies/_zm_spawner::zombie_history( "is_inert already set " + getTime() ); + return; + } + self.is_inert = 1; + self notify( "start_inert" ); + self maps/mp/zombies/_zm_spawner::zombie_eye_glow_stop(); + self maps/mp/zombies/_zm_spawner::zombie_history( "is_inert set " + getTime() ); + self playsound( "zmb_zombie_go_inert" ); + if ( isDefined( self.barricade_enter ) && self.barricade_enter ) + { + while ( isDefined( self.barricade_enter ) && self.barricade_enter ) + { + wait 0.1; + } + } + else if ( isDefined( self.ai_state ) && self.ai_state == "zombie_goto_entrance" ) + { + self notify( "stop_zombie_goto_entrance" ); + self maps/mp/zombies/_zm_spawner::reset_attack_spot(); + } + if ( isDefined( self.completed_emerging_into_playable_area ) && self.completed_emerging_into_playable_area ) + { + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + } + else + { + in_place = 1; + } + if ( isDefined( self.in_the_ground ) && self.in_the_ground ) + { + self waittill( "risen", find_flesh_struct_string ); + if ( self maps/mp/zombies/_zm_spawner::should_skip_teardown( find_flesh_struct_string ) ) + { + if ( isDefined( self.completed_emerging_into_playable_area ) && !self.completed_emerging_into_playable_area ) + { + self waittill( "completed_emerging_into_playable_area" ); + } + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + } + } + while ( isDefined( self.is_traversing ) && self.is_traversing ) + { + while ( self isinscriptedstate() ) + { + wait 0,1; + } + } + if ( isDefined( self.doing_equipment_attack ) && self.doing_equipment_attack ) + { + self stopanimscripted(); + } + if ( isDefined( self.inert_delay ) ) + { + self [[ self.inert_delay ]](); + self maps/mp/zombies/_zm_spawner::zombie_history( "inert_delay done " + getTime() ); + } + self inert_think( in_place ); +} + +inert_think( in_place ) +{ + self endon( "death" ); + self.ignoreall = 1; + self animmode( "normal" ); + if ( self.has_legs ) + { + if ( isDefined( in_place ) && in_place ) + { + self setgoalpos( self.origin ); + if ( randomint( 100 ) > 50 ) + { + self maps/mp/zombies/_zm_spawner::zombie_history( "inert 1 " + getTime() ); + self setanimstatefromasd( "zm_inert", "inert1" ); + } + else + { + self maps/mp/zombies/_zm_spawner::zombie_history( "inert 2 " + getTime() ); + self setanimstatefromasd( "zm_inert", "inert2" ); + } + self.in_place = 1; + } + else + { + substate = get_inert_substate(); + if ( isDefined( level.inert_substate_override ) ) + { + substate = self [[ level.inert_substate_override ]]( substate ); + } + self setanimstatefromasd( "zm_inert", substate ); + self maps/mp/zombies/_zm_spawner::zombie_history( "zm_inert ASD " + getTime() ); + if ( substate != "inert3" && substate != "inert4" || substate == "inert5" && substate == "inert6" ) + { + self thread inert_watch_goal(); + } + else + { + self.in_place = 1; + } + } + } + else + { + self setanimstatefromasd( "zm_inert_crawl", get_inert_crawl_substate() ); + self maps/mp/zombies/_zm_spawner::zombie_history( "zm_inert_crawl ASD " + getTime() ); + } + self thread inert_wakeup(); + self waittill( "stop_zombie_inert" ); + self maps/mp/zombies/_zm_spawner::zombie_history( "stop_zombie_inert " + getTime() ); + self playsound( "zmb_zombie_end_inert" ); + self inert_transition(); + self maps/mp/zombies/_zm_spawner::zombie_history( "inert transition done" ); + if ( isDefined( self.ai_state ) && self.ai_state == "zombie_goto_entrance" ) + { + self thread maps/mp/zombies/_zm_spawner::zombie_goto_entrance( self.first_node ); + } + if ( isDefined( self.inert_wakeup_override ) ) + { + self [[ self.inert_wakeup_override ]](); + } + else + { + if ( isDefined( self.completed_emerging_into_playable_area ) && self.completed_emerging_into_playable_area ) + { + self.ignoreall = 0; + if ( isDefined( level.ignore_find_flesh ) && !( self [[ level.ignore_find_flesh ]]() ) ) + { + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); + } + } + } + self.becoming_inert = undefined; + self.is_inert = undefined; + self.in_place = undefined; + self maps/mp/animscripts/zm_run::needsupdate(); + self maps/mp/zombies/_zm_spawner::zombie_history( "is_inert cleared " + getTime() ); +} + +inert_watch_goal() +{ + self endon( "death" ); + self endon( "stop_zombie_inert" ); + while ( 1 ) + { + self waittill( "goal" ); + locs = array_randomize( level.enemy_dog_locations ); + _a481 = locs; + _k481 = getFirstArrayKey( _a481 ); + while ( isDefined( _k481 ) ) + { + loc = _a481[ _k481 ]; + dist_sq = distancesquared( self.origin, loc.origin ); + if ( dist_sq > 90000 ) + { + self setgoalpos( loc.origin ); + break; + } + _k481 = getNextArrayKey( _a481, _k481 ); + } + if ( locs.size > 0 ) + { + self setgoalpos( locs[ 0 ].origin ); + } + } +} + +inert_wakeup() +{ + self endon( "death" ); + self endon( "stop_zombie_inert" ); + wait 0.1; + self thread inert_damage(); + self thread inert_bump(); + while ( 1 ) + { + current_time = getTime(); + players = get_players(); + _a522 = players; + _k522 = getFirstArrayKey( _a522 ); + while ( isDefined( _k522 ) ) + { + player = _a522[ _k522 ]; + dist_sq = distancesquared( self.origin, player.origin ); + if ( dist_sq < 4096 ) + { + self stop_inert(); + return; + } + if ( dist_sq < 360000 ) + { + if ( player issprinting() ) + { + self stop_inert(); + return; + } + } + if ( dist_sq < 5760000 ) + { + if ( ( current_time - player.lastfiretime ) < 100 ) + { + self stop_inert(); + return; + } + } + _k522 = getNextArrayKey( _a522, _k522 ); + } + wait 0.1; + } +} + +inert_bump() +{ + self endon( "death" ); + self endon( "stop_zombie_inert" ); + while ( 1 ) + { + zombies = getaiarray( level.zombie_team ); + _a562 = zombies; + _k562 = getFirstArrayKey( _a562 ); + while ( isDefined( _k562 ) ) + { + zombie = _a562[ _k562 ]; + if ( zombie == self ) + { + } + else if ( isDefined( zombie.is_inert ) && zombie.is_inert ) + { + } + else + { + if ( isDefined( zombie.becoming_inert ) && zombie.becoming_inert ) + { + break; + } + else + { + dist_sq = distancesquared( self.origin, zombie.origin ); + if ( dist_sq < 1296 ) + { + self stop_inert(); + return; + } + } + } + _k562 = getNextArrayKey( _a562, _k562 ); + } + wait 0.2; + } +} + +inert_damage() +{ + self endon( "death" ); + self endon( "stop_zombie_inert" ); + while ( 1 ) + { + self waittill( "damage", amount, inflictor, direction, point, type, tagname, modelname, partname, weaponname, idflags ); + while ( weaponname == "emp_grenade_zm" ) + { + continue; + } + while ( isDefined( inflictor ) ) + { + if ( isDefined( inflictor._trap_type ) && inflictor._trap_type == "fire" ) + { + continue; + } + } + } + self stop_inert(); +} + +grenade_watcher( grenade ) +{ + grenade waittill( "explode", grenade_origin ); + zombies = get_array_of_closest( grenade_origin, get_round_enemy_array(), undefined, undefined, 2400 ); + if ( !isDefined( zombies ) ) + { + return; + } + _a633 = zombies; + _k633 = getFirstArrayKey( _a633 ); + while ( isDefined( _k633 ) ) + { + zombie = _a633[ _k633 ]; + zombie stop_inert(); + _k633 = getNextArrayKey( _a633, _k633 ); + } +} + +stop_inert() +{ + self notify( "stop_zombie_inert" ); +} + +inert_transition() +{ + self endon( "death" ); + self endon( "stop_zombie_inert_transition" ); + trans_num = 4; + trans_set = level.inert_trans_walk; + animstate = "zm_inert_trans"; + if ( !self.has_legs ) + { + trans_num = 1; + trans_set = level.inert_crawl_trans_walk; + animstate = "zm_inert_crawl_trans"; + } + if ( self.zombie_move_speed == "run" ) + { + if ( self.has_legs ) + { + trans_set = level.inert_trans_run; + } + else + { + trans_set = level.inert_crawl_trans_run; + } + trans_num = 2; + } + else + { + if ( self.zombie_move_speed == "sprint" ) + { + if ( self.has_legs ) + { + trans_set = level.inert_trans_sprint; + } + else + { + trans_set = level.inert_crawl_trans_sprint; + } + trans_num = 2; + } + } + self thread inert_eye_glow(); + self setanimstatefromasd( animstate, trans_set[ randomint( trans_num ) ] ); + self maps/mp/zombies/_zm_spawner::zombie_history( "inert_trans_anim " + getTime() ); + maps/mp/animscripts/zm_shared::donotetracks( "inert_trans_anim" ); +} + +inert_eye_glow() +{ + self endon( "death" ); + while ( 1 ) + { + self waittill( "inert_trans_anim", note ); + if ( note == "end" ) + { + return; + continue; + } + else + { + if ( note == "zmb_awaken" ) + { + self maps/mp/zombies/_zm_spawner::zombie_eye_glow(); + return; + } + } + } +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_faller.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_faller.gsc new file mode 100644 index 0000000..8a3191f --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_ai_faller.gsc @@ -0,0 +1,642 @@ +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +zombie_faller_delete() +{ + level.zombie_total++; + self maps/mp/zombies/_zm_spawner::reset_attack_spot(); + if ( isDefined( self.zombie_faller_location ) ) + { + self.zombie_faller_location.is_enabled = 1; + self.zombie_faller_location = undefined; + } + self delete(); +} + +faller_script_parameters() +{ + while ( isDefined( self.script_parameters ) ) + { + parms = strtok( self.script_parameters, ";" ); + while ( isDefined( parms ) && parms.size > 0 ) + { + i = 0; + while ( i < parms.size ) + { + if ( parms[ i ] == "drop_now" ) + { + self.drop_now = 1; + } + if ( parms[ i ] == "drop_not_occupied" ) + { + self.drop_not_occupied = 1; + } + if ( parms[ i ] == "emerge_top" ) + { + self.emerge_top = 1; + } + if ( parms[ i ] == "emerge_bottom" ) + { + self.emerge_bottom = 1; + } + i++; + } + } + } +} + +setup_deathfunc( func_name ) +{ + self endon( "death" ); + while ( isDefined( self.zombie_init_done ) && !self.zombie_init_done ) + { + wait_network_frame(); + } + if ( isDefined( func_name ) ) + { + self.deathfunction = func_name; + } + else if ( isDefined( level.custom_faller_death ) ) + { + self.deathfunction = level.custom_faller_death; + } + else + { + self.deathfunction = ::zombie_fall_death_func; + } +} + +do_zombie_fall( spot ) +{ + self endon( "death" ); + self.zombie_faller_location = spot; + self.zombie_faller_location.is_enabled = 0; + self.zombie_faller_location faller_script_parameters(); + if ( isDefined( self.zombie_faller_location.emerge_bottom ) || self.zombie_faller_location.emerge_bottom && isDefined( self.zombie_faller_location.emerge_top ) && self.zombie_faller_location.emerge_top ) + { + self do_zombie_emerge( spot ); + return; + } + self thread setup_deathfunc(); + self.no_powerups = 1; + self.in_the_ceiling = 1; + self.anchor = spawn( "script_origin", self.origin ); + self.anchor.angles = self.angles; + self linkto( self.anchor ); + if ( !isDefined( spot.angles ) ) + { + spot.angles = ( 0, 0, -1 ); + } + anim_org = spot.origin; + anim_ang = spot.angles; + self ghost(); + self.anchor moveto( anim_org, 0,05 ); + self.anchor waittill( "movedone" ); + target_org = get_desired_origin(); + if ( isDefined( target_org ) ) + { + anim_ang = vectorToAngles( target_org - self.origin ); + self.anchor rotateto( ( 0, anim_ang[ 1 ], 0 ), 0,05 ); + self.anchor waittill( "rotatedone" ); + } + self unlink(); + if ( isDefined( self.anchor ) ) + { + self.anchor delete(); + } + self thread maps/mp/zombies/_zm_spawner::hide_pop(); + self thread zombie_fall_death( spot ); + self thread zombie_fall_fx( spot ); + self thread zombie_faller_death_wait(); + self thread zombie_faller_do_fall(); + self.no_powerups = 0; + self notify( "risen" ); +} + +zombie_faller_do_fall() +{ + self endon( "death" ); + self animscripted( self.origin, self.zombie_faller_location.angles, "zm_faller_emerge" ); + self maps/mp/animscripts/zm_shared::donotetracks( "emerge_anim", ::handle_fall_notetracks, self.zombie_faller_location ); + self.zombie_faller_wait_start = getTime(); + self.zombie_faller_should_drop = 0; + self thread zombie_fall_wait(); + self thread zombie_faller_watch_all_players(); + while ( !self.zombie_faller_should_drop ) + { + if ( self zombie_fall_should_attack( self.zombie_faller_location ) ) + { + self animscripted( self.origin, self.zombie_faller_location.angles, "zm_faller_attack" ); + self maps/mp/animscripts/zm_shared::donotetracks( "attack_anim", ::handle_fall_notetracks, self.zombie_faller_location ); + if ( !self zombie_faller_always_drop() && randomfloat( 1 ) > 0.5 ) + { + self.zombie_faller_should_drop = 1; + } + continue; + } + else if ( self zombie_faller_always_drop() ) + { + self.zombie_faller_should_drop = 1; + break; + } + else if ( getTime() >= ( self.zombie_faller_wait_start + 20000 ) ) + { + self.zombie_faller_should_drop = 1; + break; + } + else if ( self zombie_faller_drop_not_occupied() ) + { + self.zombie_faller_should_drop = 1; + break; + } + else self animscripted( self.origin, self.zombie_faller_location.angles, "zm_faller_attack" ); + self maps/mp/animscripts/zm_shared::donotetracks( "attack_anim", ::handle_fall_notetracks, self.zombie_faller_location ); + } + self notify( "falling" ); + spot = self.zombie_faller_location; + self zombie_faller_enable_location(); + self animscripted( self.origin, spot.angles, "zm_faller_fall" ); + self maps/mp/animscripts/zm_shared::donotetracks( "fall_anim", ::handle_fall_notetracks, spot ); + self.deathfunction = ::zombie_death_animscript; + self notify( "fall_anim_finished" ); + spot notify( "stop_zombie_fall_fx" ); + self stopanimscripted(); + landanimdelta = 15; + ground_pos = groundpos_ignore_water_new( self.origin ); + physdist = ( self.origin[ 2 ] - ground_pos[ 2 ] ) + landanimdelta; + if ( physdist > 0 ) + { + self animcustom( ::zombie_fall_loop ); + self waittill( "faller_on_ground" ); + self animcustom( ::zombie_land ); + self waittill( "zombie_land_done" ); + } + self.in_the_ceiling = 0; + self traversemode( "gravity" ); + self.no_powerups = 0; +} + +zombie_fall_loop() +{ + self endon( "death" ); + self setanimstatefromasd( "zm_faller_fall_loop" ); + while ( 1 ) + { + ground_pos = groundpos_ignore_water_new( self.origin ); + if ( ( self.origin[ 2 ] - ground_pos[ 2 ] ) < 20 ) + { + self notify( "faller_on_ground" ); + return; + } + else + { + wait 0.05; + } + } +} + +zombie_land() +{ + self setanimstatefromasd( "zm_faller_land" ); + maps/mp/animscripts/zm_shared::donotetracks( "land_anim" ); + self notify( "zombie_land_done" ); +} + +zombie_faller_always_drop() +{ + if ( isDefined( self.zombie_faller_location.drop_now ) && self.zombie_faller_location.drop_now ) + { + return 1; + } + return 0; +} + +zombie_faller_drop_not_occupied() +{ + if ( isDefined( self.zombie_faller_location.drop_not_occupied ) && self.zombie_faller_location.drop_not_occupied ) + { + if ( isDefined( self.zone_name ) && isDefined( level.zones[ self.zone_name ] ) ) + { + return !level.zones[ self.zone_name ].is_occupied; + } + } + return 0; +} + +zombie_faller_watch_all_players() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + self thread zombie_faller_watch_player( players[ i ] ); + i++; + } +} + +zombie_faller_watch_player( player ) +{ + self endon( "falling" ); + self endon( "death" ); + player endon( "disconnect" ); + range = 200; + rangesqr = range * range; + timer = 5000; + inrange = 0; + inrangetime = 0; + closerange = 60; + closerangesqr = closerange * closerange; + dirtoplayerenter = ( 0, 0, -1 ); + incloserange = 0; + while ( 1 ) + { + distsqr = distance2dsquared( self.origin, player.origin ); + if ( distsqr < rangesqr ) + { + if ( inrange ) + { + if ( ( inrangetime + timer ) < getTime() ) + { + self.zombie_faller_should_drop = 1; + return; + } + } + else + { + inrange = 1; + inrangetime = getTime(); + } + } + else + { + inrange = 0; + } + if ( distsqr < closerangesqr ) + { + if ( !incloserange ) + { + dirtoplayerenter = player.origin - self.origin; + dirtoplayerenter = ( dirtoplayerenter[ 0 ], dirtoplayerenter[ 1 ], 0 ); + dirtoplayerenter = vectornormalize( dirtoplayerenter ); + } + incloserange = 1; + } + else + { + if ( incloserange ) + { + dirtoplayerexit = player.origin - self.origin; + dirtoplayerexit = ( dirtoplayerexit[ 0 ], dirtoplayerexit[ 1 ], 0 ); + dirtoplayerexit = vectornormalize( dirtoplayerexit ); + if ( vectordot( dirtoplayerenter, dirtoplayerexit ) < 0 ) + { + self.zombie_faller_should_drop = 1; + return; + } + } + else + { + incloserange = 0; + } + wait 0.1; + } + } +} + +zombie_fall_wait() +{ + self endon( "falling" ); + self endon( "death" ); + while ( isDefined( self.zone_name ) ) + { + while ( isDefined( level.zones ) && isDefined( level.zones[ self.zone_name ] ) ) + { + zone = level.zones[ self.zone_name ]; + while ( 1 ) + { + if ( !zone.is_enabled || !zone.is_active ) + { + if ( !self potentially_visible( 2250000 ) ) + { + if ( self.health != level.zombie_health ) + { + self.zombie_faller_should_drop = 1; + return; + } + else self zombie_faller_delete(); + return; + } + } + wait 0.5; + } + } + } +} + +zombie_fall_should_attack( spot ) +{ + victims = zombie_fall_get_vicitims( spot ); + return victims.size > 0; +} + +zombie_fall_get_vicitims( spot ) +{ + ret = []; + players = getplayers(); + checkdist2 = 40; + checkdist2 *= checkdist2; + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + i++; + continue; + } + else stance = player getstance(); + if ( stance == "crouch" || stance == "prone" ) + { + i++; + continue; + } + else + { + zcheck = self.origin[ 2 ] - player.origin[ 2 ]; + if ( zcheck < 0 || zcheck > 120 ) + { + i++; + continue; + } + else + { + dist2 = distance2dsquared( player.origin, self.origin ); + if ( dist2 < checkdist2 ) + { + ret[ ret.size ] = player; + } + } + } + i++; + } + return ret; +} + +get_fall_anim( spot ) +{ + return level._zombie_fall_anims[ self.animname ][ "fall" ]; +} + +zombie_faller_enable_location() +{ + if ( isDefined( self.zombie_faller_location ) ) + { + self.zombie_faller_location.is_enabled = 1; + self.zombie_faller_location = undefined; + } +} + +zombie_faller_death_wait( endon_notify ) +{ + self endon( "falling" ); + if ( isDefined( endon_notify ) ) + { + self endon( endon_notify ); + } + self waittill( "death" ); + self zombie_faller_enable_location(); +} + +zombie_fall_death_func() +{ + self animmode( "noclip" ); + self.deathanim = "zm_faller_emerge_death"; + return self maps/mp/zombies/_zm_spawner::zombie_death_animscript(); +} + +zombie_fall_death( spot ) +{ + self endon( "fall_anim_finished" ); + while ( self.health > 1 ) + { + self waittill( "damage", amount, attacker, dir, p, type ); + } + self stopanimscripted(); + spot notify( "stop_zombie_fall_fx" ); +} + +_damage_mod_to_damage_type( type ) +{ + toks = strtok( type, "_" ); + if ( toks.size < 2 ) + { + return type; + } + returnstr = toks[ 1 ]; + i = 2; + while ( i < toks.size ) + { + returnstr += toks[ i ]; + i++; + } + returnstr = tolower( returnstr ); + return returnstr; +} + +zombie_fall_fx( spot ) +{ + spot thread zombie_fall_dust_fx( self ); + spot thread zombie_fall_burst_fx(); + playsoundatposition( "zmb_zombie_spawn", spot.origin ); + self endon( "death" ); + spot endon( "stop_zombie_fall_fx" ); + wait 1; + if ( self.zombie_move_speed != "sprint" ) + { + wait 1; + } +} + +zombie_fall_burst_fx() +{ + self endon( "stop_zombie_fall_fx" ); + self endon( "fall_anim_finished" ); + playfx( level._effect[ "rise_burst" ], self.origin + ( 0, 0, randomintrange( 5, 10 ) ) ); + wait 0.25; + playfx( level._effect[ "rise_billow" ], self.origin + ( randomintrange( -10, 10 ), randomintrange( -10, 10 ), randomintrange( 5, 10 ) ) ); +} + +zombie_fall_dust_fx( zombie ) +{ + dust_tag = "J_SpineUpper"; + self endon( "stop_zombie_fall_dust_fx" ); + self thread stop_zombie_fall_dust_fx( zombie ); + dust_time = 4.5; + dust_interval = 0.3; + t = 0; + while ( t < dust_time ) + { + playfxontag( level._effect[ "rise_dust" ], zombie, dust_tag ); + wait dust_interval; + t += dust_interval; + } +} + +stop_zombie_fall_dust_fx( zombie ) +{ + zombie waittill( "death" ); + self notify( "stop_zombie_fall_dust_fx" ); +} + +handle_fall_notetracks( note, spot ) +{ + if ( note == "deathout" ) + { + self.deathfunction = ::faller_death_ragdoll; + } + else + { + while ( note == "fire" ) + { + victims = zombie_fall_get_vicitims( spot ); + i = 0; + while ( i < victims.size ) + { + victims[ i ] dodamage( self.meleedamage, self.origin, self, self, "none", "MOD_MELEE" ); + self.zombie_faller_should_drop = 1; + i++; + } + } + } +} + +faller_death_ragdoll() +{ + self startragdoll(); + self launchragdoll( ( 0, 0, -1 ) ); + return self maps/mp/zombies/_zm_spawner::zombie_death_animscript(); +} + +in_player_fov( player ) +{ + playerangles = player getplayerangles(); + playerforwardvec = anglesToForward( playerangles ); + playerunitforwardvec = vectornormalize( playerforwardvec ); + banzaipos = self.origin; + playerpos = player getorigin(); + playertobanzaivec = banzaipos - playerpos; + playertobanzaiunitvec = vectornormalize( playertobanzaivec ); + forwarddotbanzai = vectordot( playerunitforwardvec, playertobanzaiunitvec ); + anglefromcenter = acos( forwarddotbanzai ); + playerfov = getDvarFloat( "cg_fov" ); + banzaivsplayerfovbuffer = getDvarFloat( "g_banzai_player_fov_buffer" ); + if ( banzaivsplayerfovbuffer <= 0 ) + { + banzaivsplayerfovbuffer = 0.2; + } + inplayerfov = anglefromcenter <= ( ( playerfov * 0.5 ) * ( 1 - banzaivsplayerfovbuffer ) ); + return inplayerfov; +} + +potentially_visible( how_close ) +{ + if ( !isDefined( how_close ) ) + { + how_close = 1000000; + } + potentiallyvisible = 0; + players = getplayers(); + i = 0; + while ( i < players.size ) + { + dist = distancesquared( self.origin, players[ i ].origin ); + if ( dist < how_close ) + { + inplayerfov = self in_player_fov( players[ i ] ); + if ( inplayerfov ) + { + potentiallyvisible = 1; + break; + } + } + else + { + i++; + } + } + return potentiallyvisible; +} + +do_zombie_emerge( spot ) +{ + self endon( "death" ); + self thread setup_deathfunc( ::faller_death_ragdoll ); + self.no_powerups = 1; + self.in_the_ceiling = 1; + anim_org = spot.origin; + anim_ang = spot.angles; + self thread zombie_emerge_fx( spot ); + self thread zombie_faller_death_wait( "risen" ); + if ( isDefined( level.custom_faller_entrance_logic ) ) + { + self thread [[ level.custom_faller_entrance_logic ]](); + } + self zombie_faller_emerge( spot ); + self.create_eyes = 1; + wait 0.1; + self notify( "risen" ); + self zombie_faller_enable_location(); +} + +zombie_faller_emerge( spot ) +{ + self endon( "death" ); + if ( isDefined( self.zombie_faller_location.emerge_bottom ) && self.zombie_faller_location.emerge_bottom ) + { + self animscripted( self.zombie_faller_location.origin, self.zombie_faller_location.angles, "zombie_riser_elevator_from_floor" ); + } + else + { + self animscripted( self.zombie_faller_location.origin, self.zombie_faller_location.angles, "zombie_riser_elevator_from_ceiling" ); + } + self maps/mp/animscripts/zm_shared::donotetracks( "rise_anim" ); + self.deathfunction = ::zombie_death_animscript; + self.in_the_ceiling = 0; + self.no_powerups = 0; +} + +zombie_emerge_fx( spot ) +{ + spot thread zombie_emerge_dust_fx( self ); + playsoundatposition( "zmb_zombie_spawn", spot.origin ); + self endon( "death" ); + spot endon( "stop_zombie_fall_fx" ); + wait 1; +} + +zombie_emerge_dust_fx( zombie ) +{ + dust_tag = "J_SpineUpper"; + self endon( "stop_zombie_fall_dust_fx" ); + self thread stop_zombie_fall_dust_fx( zombie ); + dust_time = 3.5; + dust_interval = 0.5; + t = 0; + while ( t < dust_time ) + { + playfxontag( level._effect[ "rise_dust" ], zombie, dust_tag ); + wait dust_interval; + t += dust_interval; + } +} + +stop_zombie_emerge_dust_fx( zombie ) +{ + zombie waittill( "death" ); + self notify( "stop_zombie_fall_dust_fx" ); +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equip_hacker.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equip_hacker.gsc new file mode 100644 index 0000000..29bb3d6 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equip_hacker.gsc @@ -0,0 +1,915 @@ +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !maps/mp/zombies/_zm_equipment::is_equipment_included( "equip_hacker_zm" ) ) + { + return; + } + maps/mp/zombies/_zm_equipment::register_equipment( "equip_hacker_zm", &"ZOMBIE_EQUIP_HACKER_PICKUP_HINT_STRING", &"ZOMBIE_EQUIP_HACKER_HOWTO", undefined, "hacker" ); + level._hackable_objects = []; + level._pooled_hackable_objects = []; + onplayerconnect_callback( ::hacker_on_player_connect ); + level thread hack_trigger_think(); + level thread hacker_trigger_pool_think(); + level thread hacker_round_reward(); + /* + if ( getDvarInt( #"53BD7080" ) == 1 ) + { + level thread hacker_debug(); + } + */ +} + +hacker_round_reward() +{ + while ( 1 ) + { + level waittill( "end_of_round" ); + if ( !isDefined( level._from_nml ) ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ] get_player_equipment() ) && players[ i ] get_player_equipment() == "equip_hacker_zm" ) + { + if ( isDefined( players[ i ].equipment_got_in_round[ "equip_hacker_zm" ] ) ) + { + got_in_round = players[ i ].equipment_got_in_round[ "equip_hacker_zm" ]; + rounds_kept = level.round_number - got_in_round; + rounds_kept -= 1; + if ( rounds_kept > 0 ) + { + rounds_kept = min( rounds_kept, 5 ); + score = rounds_kept * 500; + players[ i ] maps/mp/zombies/_zm_score::add_to_player_score( int( score ) ); + } + } + } + i++; + } + } + else level._from_nml = undefined; + } +} + +hacker_debug() +{ + while ( 1 ) + { + i = 0; + while ( i < level._hackable_objects.size ) + { + hackable = level._hackable_objects[ i ]; + if ( isDefined( hackable.pooled ) && hackable.pooled ) + { + if ( isDefined( hackable._trigger ) ) + { + col = vectorScale( ( 0, 0, 1 ), 255 ); + if ( isDefined( hackable.custom_debug_color ) ) + { + col = hackable.custom_debug_color; + } +/# + print3d( hackable.origin, "+", col, 1, 1 ); +#/ + } + else + { +/# + print3d( hackable.origin, "+", vectorScale( ( 0, 0, 1 ), 255 ), 1, 1 ); +#/ + } + i++; + continue; + } + else + { +/# + print3d( hackable.origin, "+", vectorScale( ( 0, 0, 1 ), 255 ), 1, 1 ); +#/ + } + i++; + } + wait 0.1; + } +} + +hacker_trigger_pool_think() +{ + if ( !isDefined( level._zombie_hacker_trigger_pool_size ) ) + { + level._zombie_hacker_trigger_pool_size = 8; + } + pool_active = 0; + level._hacker_pool = []; + while ( 1 ) + { + if ( pool_active ) + { + if ( !any_hackers_active() ) + { + destroy_pooled_items(); + } + else + { + sweep_pooled_items(); + add_eligable_pooled_items(); + } + } + else + { + if ( any_hackers_active() ) + { + pool_active = 1; + } + } + wait 0.1; + } +} + +destroy_pooled_items() +{ + pool_active = 0; + i = 0; + while ( i < level._hacker_pool.size ) + { + level._hacker_pool[ i ]._trigger delete(); + level._hacker_pool[ i ]._trigger = undefined; + i++; + } + level._hacker_pool = []; +} + +sweep_pooled_items() +{ + new_hacker_pool = []; + i = 0; + while ( i < level._hacker_pool.size ) + { + if ( level._hacker_pool[ i ] should_pooled_object_exist() ) + { + new_hacker_pool[ new_hacker_pool.size ] = level._hacker_pool[ i ]; + i++; + continue; + } + else + { + if ( isDefined( level._hacker_pool[ i ]._trigger ) ) + { + level._hacker_pool[ i ]._trigger delete(); + } + level._hacker_pool[ i ]._trigger = undefined; + } + i++; + } + level._hacker_pool = new_hacker_pool; +} + +should_pooled_object_exist() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] hacker_active() ) + { + if ( isDefined( self.entity ) ) + { + if ( self.entity != players[ i ] ) + { + if ( distance2dsquared( players[ i ].origin, self.entity.origin ) <= ( self.radius * self.radius ) ) + { + return 1; + } + } + } + else + { + if ( distance2dsquared( players[ i ].origin, self.origin ) <= ( self.radius * self.radius ) ) + { + return 1; + } + } + } + i++; + } + return 0; +} + +add_eligable_pooled_items() +{ + candidates = []; + i = 0; + while ( i < level._hackable_objects.size ) + { + hackable = level._hackable_objects[ i ]; + if ( isDefined( hackable.pooled ) && hackable.pooled && !isDefined( hackable._trigger ) ) + { + if ( !isinarray( level._hacker_pool, hackable ) ) + { + if ( hackable should_pooled_object_exist() ) + { + candidates[ candidates.size ] = hackable; + } + } + } + i++; + } + i = 0; + while ( i < candidates.size ) + { + candidate = candidates[ i ]; + height = 72; + radius = 32; + if ( isDefined( candidate.radius ) ) + { + radius = candidate.radius; + } + if ( isDefined( candidate.height ) ) + { + height = candidate.height; + } + trigger = spawn( "trigger_radius_use", candidate.origin, 0, radius, height ); + trigger usetriggerrequirelookat(); + trigger triggerignoreteam(); + trigger setcursorhint( "HINT_NOICON" ); + trigger.radius = radius; + trigger.height = height; + trigger.beinghacked = 0; + candidate._trigger = trigger; + level._hacker_pool[ level._hacker_pool.size ] = candidate; + i++; + } +} + +get_hackable_trigger() +{ + if ( isDefined( self.door ) ) + { + return self.door; + } + else + { + if ( isDefined( self.perk ) ) + { + return self.perk; + } + else + { + if ( isDefined( self.window ) ) + { + return self.window.unitrigger_stub.trigger; + } + else + { + if ( isDefined( self.classname ) && getsubstr( self.classname, 0, 7 ) == "trigger_" ) + { + return self; + } + } + } + } +} + +any_hackers_active() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] hacker_active() ) + { + return 1; + } + i++; + } + return 0; +} + +register_hackable( name, callback_func, qualifier_func ) +{ + structs = getstructarray( name, "script_noteworthy" ); + if ( !isDefined( structs ) ) + { +/# + println( "Error: register_hackable called on script_noteworthy " + name + " but no such structs exist." ); +#/ + return; + } + i = 0; + while ( i < structs.size ) + { + if ( !isinarray( level._hackable_objects, structs[ i ] ) ) + { + structs[ i ]._hack_callback_func = callback_func; + structs[ i ]._hack_qualifier_func = qualifier_func; + structs[ i ].pooled = level._hacker_pooled; + if ( isDefined( structs[ i ].targetname ) ) + { + structs[ i ].hacker_target = getent( structs[ i ].targetname, "targetname" ); + } + level._hackable_objects[ level._hackable_objects.size ] = structs[ i ]; + if ( isDefined( level._hacker_pooled ) ) + { + level._pooled_hackable_objects[ level._pooled_hackable_objects.size ] = structs[ i ]; + } + structs[ i ] thread hackable_object_thread(); + wait_network_frame(); + } + i++; + } +} + +register_hackable_struct( struct, callback_func, qualifier_func ) +{ + if ( !isinarray( level._hackable_objects, struct ) ) + { + struct._hack_callback_func = callback_func; + struct._hack_qualifier_func = qualifier_func; + struct.pooled = level._hacker_pooled; + if ( isDefined( struct.targetname ) ) + { + struct.hacker_target = getent( struct.targetname, "targetname" ); + } + level._hackable_objects[ level._hackable_objects.size ] = struct; + if ( isDefined( level._hacker_pooled ) ) + { + level._pooled_hackable_objects[ level._pooled_hackable_objects.size ] = struct; + } + struct thread hackable_object_thread(); + } +} + +register_pooled_hackable_struct( struct, callback_func, qualifier_func ) +{ + level._hacker_pooled = 1; + register_hackable_struct( struct, callback_func, qualifier_func ); + level._hacker_pooled = undefined; +} + +register_pooled_hackable( name, callback_func, qualifier_func ) +{ + level._hacker_pooled = 1; + register_hackable( name, callback_func, qualifier_func ); + level._hacker_pooled = undefined; +} + +deregister_hackable_struct( struct ) +{ + if ( isinarray( level._hackable_objects, struct ) ) + { + new_list = []; + i = 0; + while ( i < level._hackable_objects.size ) + { + if ( level._hackable_objects[ i ] != struct ) + { + new_list[ new_list.size ] = level._hackable_objects[ i ]; + i++; + continue; + } + else + { + level._hackable_objects[ i ] notify( "hackable_deregistered" ); + if ( isDefined( level._hackable_objects[ i ]._trigger ) ) + { + level._hackable_objects[ i ]._trigger delete(); + } + if ( isDefined( level._hackable_objects[ i ].pooled ) && level._hackable_objects[ i ].pooled ) + { + arrayremovevalue( level._hacker_pool, level._hackable_objects[ i ] ); + arrayremovevalue( level._pooled_hackable_objects, level._hackable_objects[ i ] ); + } + } + i++; + } + level._hackable_objects = new_list; + } +} + +deregister_hackable( noteworthy ) +{ + new_list = []; + i = 0; + while ( i < level._hackable_objects.size ) + { + if ( !isDefined( level._hackable_objects[ i ].script_noteworthy ) || level._hackable_objects[ i ].script_noteworthy != noteworthy ) + { + new_list[ new_list.size ] = level._hackable_objects[ i ]; + } + else + { + level._hackable_objects[ i ] notify( "hackable_deregistered" ); + if ( isDefined( level._hackable_objects[ i ]._trigger ) ) + { + level._hackable_objects[ i ]._trigger delete(); + } + } + if ( isDefined( level._hackable_objects[ i ].pooled ) && level._hackable_objects[ i ].pooled ) + { + arrayremovevalue( level._hacker_pool, level._hackable_objects[ i ] ); + } + i++; + } + level._hackable_objects = new_list; +} + +hack_trigger_think() +{ + while ( 1 ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + j = 0; + while ( j < level._hackable_objects.size ) + { + hackable = level._hackable_objects[ j ]; + if ( isDefined( hackable._trigger ) ) + { + qualifier_passed = 1; + if ( isDefined( hackable._hack_qualifier_func ) ) + { + qualifier_passed = hackable [[ hackable._hack_qualifier_func ]]( player ); + } + if ( player hacker_active() && qualifier_passed && !hackable._trigger.beinghacked ) + { + hackable._trigger setinvisibletoplayer( player, 0 ); + j++; + continue; + } + else + { + hackable._trigger setinvisibletoplayer( player, 1 ); + } + } + j++; + } + i++; + } + wait 0.1; + } +} + +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 ); + dot_limit = 0.8; + if ( isDefined( facee.dot_limit ) ) + { + dot_limit = facee.dot_limit; + } + return dotproduct > dot_limit; +} + +can_hack( hackable ) +{ + if ( !isalive( self ) ) + { + return 0; + } + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return 0; + } + if ( !self hacker_active() ) + { + return 0; + } + if ( !isDefined( hackable._trigger ) ) + { + return 0; + } + if ( isDefined( hackable.player ) ) + { + if ( hackable.player != self ) + { + return 0; + } + } + if ( self throwbuttonpressed() ) + { + return 0; + } + if ( self fragbuttonpressed() ) + { + return 0; + } + if ( isDefined( hackable._hack_qualifier_func ) ) + { + if ( !( hackable [[ hackable._hack_qualifier_func ]]( self ) ) ) + { + return 0; + } + } + if ( !isinarray( level._hackable_objects, hackable ) ) + { + return 0; + } + radsquared = 1024; + if ( isDefined( hackable.radius ) ) + { + radsquared = hackable.radius * hackable.radius; + } + origin = hackable.origin; + if ( isDefined( hackable.entity ) ) + { + origin = hackable.entity.origin; + } + if ( distance2dsquared( self.origin, origin ) > radsquared ) + { + return 0; + } + if ( !isDefined( hackable.no_touch_check ) && !self istouching( hackable._trigger ) ) + { + return 0; + } + if ( !self is_facing( hackable ) ) + { + return 0; + } + if ( !isDefined( hackable.no_sight_check ) && !sighttracepassed( self.origin + vectorScale( ( 0, 0, 1 ), 50 ), origin, 0, undefined ) ) + { + return 0; + } + if ( !isDefined( hackable.no_bullet_trace ) && !bullettracepassed( self.origin + vectorScale( ( 0, 0, 1 ), 50 ), origin, 0, undefined ) ) + { + return 0; + } + return 1; +} + +is_hacking( hackable ) +{ + if ( can_hack( hackable ) ) + { + return self usebuttonpressed(); + } +} + +set_hack_hint_string() +{ + if ( isDefined( self._trigger ) ) + { + if ( isDefined( self.custom_string ) ) + { + self._trigger sethintstring( self.custom_string ); + return; + } + else if ( !isDefined( self.script_int ) || self.script_int <= 0 ) + { + self._trigger sethintstring( &"ZOMBIE_HACK_NO_COST" ); + return; + } + else + { + self._trigger sethintstring( &"ZOMBIE_HACK", self.script_int ); + } + } +} + +tidy_on_deregister( hackable ) +{ + self endon( "clean_up_tidy_up" ); + hackable waittill( "hackable_deregistered" ); + if ( isDefined( self.hackerprogressbar ) ) + { + self.hackerprogressbar maps/mp/gametypes_zm/_hud_util::destroyelem(); + } + if ( isDefined( self.hackertexthud ) ) + { + self.hackertexthud destroy(); + } +} + +hacker_do_hack( hackable ) +{ + timer = 0; + hacked = 0; + hackable._trigger.beinghacked = 1; + if ( !isDefined( self.hackerprogressbar ) ) + { + self.hackerprogressbar = self maps/mp/gametypes_zm/_hud_util::createprimaryprogressbar(); + } + if ( !isDefined( self.hackertexthud ) ) + { + self.hackertexthud = newclienthudelem( self ); + } + hack_duration = hackable.script_float; + if ( self hasperk( "specialty_fastreload" ) ) + { + hack_duration *= 0.66; + } + hack_duration = max( 1.5, hack_duration ); + self thread tidy_on_deregister( hackable ); + self.hackerprogressbar maps/mp/gametypes_zm/_hud_util::updatebar( 0.01, 1 / hack_duration ); + self.hackertexthud.alignx = "center"; + self.hackertexthud.aligny = "middle"; + self.hackertexthud.horzalign = "center"; + self.hackertexthud.vertalign = "bottom"; + self.hackertexthud.y = -113; + if ( issplitscreen() ) + { + self.hackertexthud.y = -107; + } + self.hackertexthud.foreground = 1; + self.hackertexthud.font = "default"; + self.hackertexthud.fontscale = 1.8; + self.hackertexthud.alpha = 1; + self.hackertexthud.color = ( 0, 0, 1 ); + self.hackertexthud settext( &"ZOMBIE_HACKING" ); + self playloopsound( "zmb_progress_bar", 0,5 ); + while ( self is_hacking( hackable ) ) + { + wait 0.05; + timer += 0.05; + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + break; + } + else if ( timer >= hack_duration ) + { + hacked = 1; + break; + } + else + { + } + } + self stoploopsound( 0.5 ); + if ( hacked ) + { + self playsound( "vox_mcomp_hack_success" ); + } + else self playsound( "vox_mcomp_hack_fail" ); + if ( isDefined( self.hackerprogressbar ) ) + { + self.hackerprogressbar maps/mp/gametypes_zm/_hud_util::destroyelem(); + } + if ( isDefined( self.hackertexthud ) ) + { + self.hackertexthud destroy(); + } + hackable set_hack_hint_string(); + if ( isDefined( hackable._trigger ) ) + { + hackable._trigger.beinghacked = 0; + } + self notify( "clean_up_tidy_up" ); + return hacked; +} + +lowreadywatcher( player ) +{ + player endon( "disconnected" ); + self endon( "kill_lowreadywatcher" ); + self waittill( "hackable_deregistered" ); +} + +hackable_object_thread() +{ + self endon( "hackable_deregistered" ); + height = 72; + radius = 64; + if ( isDefined( self.radius ) ) + { + radius = self.radius; + } + if ( isDefined( self.height ) ) + { + height = self.height; + } + if ( !isDefined( self.pooled ) ) + { + trigger = spawn( "trigger_radius_use", self.origin, 0, radius, height ); + trigger usetriggerrequirelookat(); + trigger setcursorhint( "HINT_NOICON" ); + trigger.radius = radius; + trigger.height = height; + trigger.beinghacked = 0; + self._trigger = trigger; + } + cost = 0; + if ( isDefined( self.script_int ) ) + { + cost = self.script_int; + } + duration = 1; + if ( isDefined( self.script_float ) ) + { + duration = self.script_float; + } + while ( 1 ) + { + wait 0.1; + while ( !isDefined( self._trigger ) ) + { + continue; + } + players = get_players(); + if ( isDefined( self._trigger ) ) + { + if ( isDefined( self.entity ) ) + { + self.origin = self.entity.origin; + self._trigger.origin = self.entity.origin; + if ( isDefined( self.trigger_offset ) ) + { + self._trigger.origin += self.trigger_offset; + } + } + } + i = 0; + while ( i < players.size ) + { + if ( players[ i ] can_hack( self ) ) + { + self set_hack_hint_string(); + break; + } + else + { + i++; + } + } + i = 0; + while ( i < players.size ) + { + hacker = players[ i ]; + if ( !hacker is_hacking( self ) ) + { + i++; + continue; + } + else if ( hacker.score >= cost || cost <= 0 ) + { + self thread lowreadywatcher( hacker ); + hack_success = hacker hacker_do_hack( self ); + self notify( "kill_lowreadywatcher" ); + if ( isDefined( hacker ) ) + { + } + if ( isDefined( hacker ) && hack_success ) + { + if ( cost ) + { + if ( cost > 0 ) + { + hacker maps/mp/zombies/_zm_score::minus_to_player_score( cost ); + break; + } + else + { + hacker maps/mp/zombies/_zm_score::add_to_player_score( cost * -1 ); + } + } + hacker notify( "successful_hack" ); + if ( isDefined( self._hack_callback_func ) ) + { + self thread [[ self._hack_callback_func ]]( hacker ); + } + } + i++; + continue; + } + else + { + hacker play_sound_on_ent( "no_purchase" ); + hacker maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "no_money", undefined, 1 ); + } + i++; + } + } +} + +hacker_on_player_connect() +{ + struct = spawnstruct(); + struct.origin = self.origin; + struct.radius = 48; + struct.height = 64; + struct.script_float = 10; + struct.script_int = 500; + struct.entity = self; + struct.trigger_offset = vectorScale( ( 0, 0, 1 ), 48 ); + register_pooled_hackable_struct( struct, ::player_hack, ::player_qualifier ); + struct thread player_hack_disconnect_watcher( self ); +} + +player_hack_disconnect_watcher( player ) +{ + player waittill( "disconnect" ); + deregister_hackable_struct( self ); +} + +player_hack( hacker ) +{ + if ( isDefined( self.entity ) ) + { + self.entity maps/mp/zombies/_zm_score::player_add_points( "hacker_transfer", 500 ); + } + if ( isDefined( hacker ) ) + { + hacker thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "hack_plr" ); + } +} + +player_qualifier( player ) +{ + if ( player == self.entity ) + { + return 0; + } + if ( self.entity maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return 0; + } + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return 0; + } + if ( isDefined( self.entity.sessionstate == "spectator" ) && self.entity.sessionstate == "spectator" ) + { + return 0; + } + return 1; +} + +hide_hint_when_hackers_active( custom_logic_func, custom_logic_func_param ) +{ + invis_to_any = 0; + while ( 1 ) + { + if ( isDefined( custom_logic_func ) ) + { + self [[ custom_logic_func ]]( custom_logic_func_param ); + } + if ( maps/mp/zombies/_zm_equip_hacker::any_hackers_active() ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] hacker_active() ) + { + self setinvisibletoplayer( players[ i ], 1 ); + invis_to_any = 1; + i++; + continue; + } + else + { + self setinvisibletoplayer( players[ i ], 0 ); + } + i++; + } + } + else while ( invis_to_any ) + { + invis_to_any = 0; + players = get_players(); + i = 0; + while ( i < players.size ) + { + self setinvisibletoplayer( players[ i ], 0 ); + i++; + } + } + wait 0.1; + } +} + +hacker_debug_print( msg, color ) +{ +/# + if ( !getDvarInt( #"428DE100" ) ) + { + return; + } + if ( !isDefined( color ) ) + { + color = ( 0, 0, 1 ); + } + print3d( self.origin + vectorScale( ( 0, 0, 1 ), 60 ), msg, color, 1, 1, 40 ); +#/ +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equipment.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equipment.gsc new file mode 100644 index 0000000..a405923 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_equipment.gsc @@ -0,0 +1,1953 @@ +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + init_equipment_upgrade(); + onplayerconnect_callback( ::equipment_placement_watcher ); + level._equipment_disappear_fx = loadfx( "maps/zombie/fx_zmb_tranzit_electrap_explo" ); + if ( isDefined( level.disable_fx_zmb_tranzit_shield_explo ) && !level.disable_fx_zmb_tranzit_shield_explo ) + { + level._riotshield_dissapear_fx = loadfx( "maps/zombie/fx_zmb_tranzit_shield_explo" ); + } + level.placeable_equipment_destroy_fn = []; + if ( isDefined( level._no_equipment_activated_clientfield ) && !level._no_equipment_activated_clientfield ) + { + registerclientfield( "scriptmover", "equipment_activated", 12000, 4, "int" ); + } +} + +signal_equipment_activated( val ) +{ + if ( !isDefined( val ) ) + { + val = 1; + } + if ( isDefined( level._no_equipment_activated_clientfield ) && level._no_equipment_activated_clientfield ) + { + return; + } + self endon( "death" ); + self setclientfield( "equipment_activated", val ); + i = 0; + while ( i < 2 ) + { + wait_network_frame(); + i++; + } + self setclientfield( "equipment_activated", 0 ); +} + +register_equipment( equipment_name, hint, howto_hint, hint_icon, equipmentvo, watcher_thread, transfer_fn, drop_fn, pickup_fn, place_fn ) +{ + if ( !isDefined( level.zombie_include_equipment ) || isDefined( level.zombie_include_equipment[ equipment_name ] ) && !level.zombie_include_equipment[ equipment_name ] ) + { + return; + } + precachestring( hint ); + if ( isDefined( hint_icon ) ) + { + precacheshader( hint_icon ); + } + struct = spawnstruct(); + if ( !isDefined( level.zombie_equipment ) ) + { + level.zombie_equipment = []; + } + struct.equipment_name = equipment_name; + struct.hint = hint; + struct.howto_hint = howto_hint; + struct.hint_icon = hint_icon; + struct.vox = equipmentvo; + struct.triggers = []; + struct.models = []; + struct.watcher_thread = watcher_thread; + struct.transfer_fn = transfer_fn; + struct.drop_fn = drop_fn; + struct.pickup_fn = pickup_fn; + struct.place_fn = place_fn; + level.zombie_equipment[ equipment_name ] = struct; +} + +is_equipment_included( equipment_name ) +{ + if ( !isDefined( level.zombie_include_equipment ) ) + { + return 0; + } + return isDefined( level.zombie_include_equipment[ equipment_name ] ); +} + +include_zombie_equipment( equipment_name ) +{ + if ( !isDefined( level.zombie_include_equipment ) ) + { + level.zombie_include_equipment = []; + } + level.zombie_include_equipment[ equipment_name ] = 1; + precacheitem( equipment_name ); +} + +limit_zombie_equipment( equipment_name, limited ) +{ + if ( !isDefined( level._limited_equipment ) ) + { + level._limited_equipment = []; + } + if ( limited ) + { + level._limited_equipment[ level._limited_equipment.size ] = equipment_name; + } + else + { + arrayremovevalue( level._limited_equipment, equipment_name, 0 ); + } +} + +init_equipment_upgrade() +{ + equipment_spawns = []; + equipment_spawns = getentarray( "zombie_equipment_upgrade", "targetname" ); + i = 0; + while ( i < equipment_spawns.size ) + { + hint_string = get_equipment_hint( equipment_spawns[ i ].zombie_equipment_upgrade ); + equipment_spawns[ i ] sethintstring( hint_string ); + equipment_spawns[ i ] setcursorhint( "HINT_NOICON" ); + equipment_spawns[ i ] usetriggerrequirelookat(); + equipment_spawns[ i ] add_to_equipment_trigger_list( equipment_spawns[ i ].zombie_equipment_upgrade ); + equipment_spawns[ i ] thread equipment_spawn_think(); + i++; + } +} + +get_equipment_hint( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + return level.zombie_equipment[ equipment_name ].hint; +} + +get_equipment_howto_hint( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + return level.zombie_equipment[ equipment_name ].howto_hint; +} + +get_equipment_icon( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + return level.zombie_equipment[ equipment_name ].hint_icon; +} + +add_to_equipment_trigger_list( equipment_name ) +{ +/* +/# + assert( isDefined( level.zombie_equipment[ equipment_name ] ), equipment_name + " was not included or is not registered with the equipment system." ); +#/ +*/ + level.zombie_equipment[ equipment_name ].triggers[ level.zombie_equipment[ equipment_name ].triggers.size ] = self; + level.zombie_equipment[ equipment_name ].models[ level.zombie_equipment[ equipment_name ].models.size ] = getent( self.target, "targetname" ); +} + +equipment_spawn_think() +{ + for ( ;; ) + { + self waittill( "trigger", player ); + if ( player in_revive_trigger() || player.is_drinking > 0 ) + { + wait 0.1; + continue; + } + else + { + if ( is_limited_equipment( self.zombie_equipment_upgrade ) ) + { + player setup_limited_equipment( self.zombie_equipment_upgrade ); + if ( isDefined( level.hacker_tool_positions ) ) + { + new_pos = random( level.hacker_tool_positions ); + self.origin = new_pos.trigger_org; + model = getent( self.target, "targetname" ); + model.origin = new_pos.model_org; + model.angles = new_pos.model_ang; + } + } + player equipment_give( self.zombie_equipment_upgrade ); + } + } +} + +set_equipment_invisibility_to_player( equipment, invisible ) +{ + triggers = level.zombie_equipment[ equipment ].triggers; + i = 0; + while ( i < triggers.size ) + { + if ( isDefined( triggers[ i ] ) ) + { + triggers[ i ] setinvisibletoplayer( self, invisible ); + } + i++; + } + models = level.zombie_equipment[ equipment ].models; + i = 0; + while ( i < models.size ) + { + if ( isDefined( models[ i ] ) ) + { + models[ i ] setinvisibletoplayer( self, invisible ); + } + i++; + } +} + +equipment_take( equipment ) +{ + if ( !isDefined( equipment ) ) + { + equipment = self get_player_equipment(); + } + if ( !isDefined( equipment ) ) + { + return; + } + if ( !self has_player_equipment( equipment ) ) + { + return; + } + current = 0; + current_weapon = 0; + if ( isDefined( self get_player_equipment() ) && equipment == self get_player_equipment() ) + { + current = 1; + } + if ( equipment == self getcurrentweapon() ) + { + current_weapon = 1; + } + /* +/# + println( "ZM EQUIPMENT: " + self.name + " lost " + equipment + "\n" ); +#/ + */ + if ( isDefined( self.current_equipment_active[ equipment ] ) && self.current_equipment_active[ equipment ] ) + { + self.current_equipment_active[ equipment ] = 0; + self notify( equipment + "_deactivate" ); + } + self notify( equipment + "_taken" ); + self takeweapon( equipment ); + if ( !is_limited_equipment( equipment ) || is_limited_equipment( equipment ) && !limited_equipment_in_use( equipment ) ) + { + self set_equipment_invisibility_to_player( equipment, 0 ); + } + if ( current ) + { + self set_player_equipment( undefined ); + self setactionslot( 1, "" ); + } + else + { + arrayremovevalue( self.deployed_equipment, equipment ); + } + if ( current_weapon ) + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } +} + +equipment_give( equipment ) +{ + if ( !isDefined( equipment ) ) + { + return; + } + if ( !isDefined( level.zombie_equipment[ equipment ] ) ) + { + return; + } + if ( self has_player_equipment( equipment ) ) + { + return; + } + /* +/# + println( "ZM EQUIPMENT: " + self.name + " got " + equipment + "\n" ); +#/ + */ + curr_weapon = self getcurrentweapon(); + curr_weapon_was_curr_equipment = self is_player_equipment( curr_weapon ); + self equipment_take(); + self set_player_equipment( equipment ); + self giveweapon( equipment ); + self setweaponammoclip( equipment, 1 ); + self thread show_equipment_hint( equipment ); + self notify( equipment + "_given" ); + self set_equipment_invisibility_to_player( equipment, 1 ); + self setactionslot( 1, "weapon", equipment ); + if ( isDefined( level.zombie_equipment[ equipment ].watcher_thread ) ) + { + self thread [[ level.zombie_equipment[ equipment ].watcher_thread ]](); + } + self thread equipment_slot_watcher( equipment ); + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", level.zombie_equipment[ equipment ].vox ); +} + +equipment_slot_watcher( equipment ) +{ + self notify( "kill_equipment_slot_watcher" ); + self endon( "kill_equipment_slot_watcher" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "weapon_change", curr_weapon, prev_weapon ); + self.prev_weapon_before_equipment_change = undefined; + if ( isDefined( prev_weapon ) && prev_weapon != "none" ) + { + prev_weapon_type = weaponinventorytype( prev_weapon ); + if ( prev_weapon_type == "primary" || prev_weapon_type == "altmode" ) + { + self.prev_weapon_before_equipment_change = prev_weapon; + } + } + if ( isDefined( level.zombie_equipment[ equipment ].watcher_thread ) ) + { + if ( curr_weapon == equipment ) + { + if ( self.current_equipment_active[ equipment ] == 1 ) + { + self notify( equipment + "_deactivate" ); + self.current_equipment_active[ equipment ] = 0; + } + else + { + if ( self.current_equipment_active[ equipment ] == 0 ) + { + self notify( equipment + "_activate" ); + self.current_equipment_active[ equipment ] = 1; + } + } + self waittill( "equipment_select_response_done" ); + } + continue; + } + else if ( curr_weapon == equipment && !self.current_equipment_active[ equipment ] ) + { + self notify( equipment + "_activate" ); + self.current_equipment_active[ equipment ] = 1; + continue; + } + else + { + if ( curr_weapon != equipment && self.current_equipment_active[ equipment ] ) + { + self notify( equipment + "_deactivate" ); + self.current_equipment_active[ equipment ] = 0; + } + } + } +} + +is_limited_equipment( equipment ) +{ + while ( isDefined( level._limited_equipment ) ) + { + i = 0; + while ( i < level._limited_equipment.size ) + { + if ( level._limited_equipment[ i ] == equipment ) + { + return 1; + } + i++; + } + } + return 0; +} + +limited_equipment_in_use( equipment ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + current_equipment = players[ i ] get_player_equipment(); + if ( isDefined( current_equipment ) && current_equipment == equipment ) + { + return 1; + } + i++; + } + if ( isDefined( level.dropped_equipment ) && isDefined( level.dropped_equipment[ equipment ] ) ) + { + return 1; + } + return 0; +} + +setup_limited_equipment( equipment ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] set_equipment_invisibility_to_player( equipment, 1 ); + i++; + } + self thread release_limited_equipment_on_disconnect( equipment ); + self thread release_limited_equipment_on_equipment_taken( equipment ); +} + +release_limited_equipment_on_equipment_taken( equipment ) +{ + self endon( "disconnect" ); + self waittill_either( equipment + "_taken", "spawned_spectator" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] set_equipment_invisibility_to_player( equipment, 0 ); + i++; + } +} + +release_limited_equipment_on_disconnect( equipment ) +{ + self endon( equipment + "_taken" ); + self waittill( "disconnect" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isalive( players[ i ] ) ) + { + players[ i ] set_equipment_invisibility_to_player( equipment, 0 ); + } + i++; + } +} + +is_equipment_active( equipment ) +{ + if ( !isDefined( self.current_equipment_active ) || !isDefined( self.current_equipment_active[ equipment ] ) ) + { + return 0; + } + return self.current_equipment_active[ equipment ]; +} + +init_equipment_hint_hudelem( x, y, alignx, aligny, fontscale, alpha ) +{ + self.x = x; + self.y = y; + self.alignx = alignx; + self.aligny = aligny; + self.fontscale = fontscale; + self.alpha = alpha; + self.sort = 20; +} + +setup_equipment_client_hintelem() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( !isDefined( self.hintelem ) ) + { + self.hintelem = newclienthudelem( self ); + } + if ( level.splitscreen ) + { + self.hintelem init_equipment_hint_hudelem( 160, 90, "center", "middle", 1.6, 1 ); + } + else + { + self.hintelem init_equipment_hint_hudelem( 320, 220, "center", "bottom", 1.6, 1 ); + } +} + +show_equipment_hint( equipment ) +{ + self notify( "kill_previous_show_equipment_hint_thread" ); + self endon( "kill_previous_show_equipment_hint_thread" ); + self endon( "death" ); + self endon( "disconnect" ); + if ( isDefined( self.do_not_display_equipment_pickup_hint ) && self.do_not_display_equipment_pickup_hint ) + { + return; + } + wait 0.5; + text = get_equipment_howto_hint( equipment ); + self show_equipment_hint_text( text ); +} + +show_equipment_hint_text( text ) +{ + self notify( "hide_equipment_hint_text" ); + wait 0.05; + self setup_equipment_client_hintelem(); + self.hintelem settext( text ); + self.hintelem.alpha = 1; + self.hintelem.font = "small"; + self.hintelem.fontscale = 1.25; + self.hintelem.hidewheninmenu = 1; + time = self waittill_notify_or_timeout( "hide_equipment_hint_text", 3.2 ); + if ( isDefined( time ) ) + { + self.hintelem fadeovertime( 0.25 ); + self.hintelem.alpha = 0; + self waittill_notify_or_timeout( "hide_equipment_hint_text", 0.25 ); + } + self.hintelem settext( "" ); + self.hintelem destroy(); +} + +equipment_onspawnretrievableweaponobject( watcher, player ) +{ + self.plant_parent = self; + if ( isDefined( level.placeable_equipment_type[ self.name ] ) ) + { + iswallmount = level.placeable_equipment_type[ self.name ] == "wallmount"; + } + if ( !isDefined( player.turret_placement ) || !player.turret_placement[ "result" ] ) + { + if ( iswallmount /*|| !getDvarInt( #"B3416C1D" )*/ ) + { + self waittill( "stationary" ); + waittillframeend; + if ( iswallmount ) + { + if ( isDefined( player.planted_wallmount_on_a_zombie ) && player.planted_wallmount_on_a_zombie ) + { + equip_name = self.name; + thread equipment_disappear_fx( self.origin, undefined, self.angles ); + self delete(); + if ( player hasweapon( equip_name ) ) + { + player setweaponammoclip( equip_name, 1 ); + } + player.planted_wallmount_on_a_zombie = undefined; + return; + } + } + } + else + { + self.plant_parent = player; + self.origin = player.origin; + self.angles = player.angles; + wait_network_frame(); + } + } + equipment = watcher.name + "_zm"; + /* +/# + if ( !isDefined( player.current_equipment ) || player.current_equipment != equipment ) + { + assert( player has_deployed_equipment( equipment ) ); + assert( !isDefined( player.current_equipment ) ); +#/ + } + */ + if ( isDefined( player.current_equipment ) && player.current_equipment == equipment ) + { + player equipment_to_deployed( equipment ); + } + if ( isDefined( level.zombie_equipment[ equipment ].place_fn ) ) + { + if ( isDefined( player.turret_placement ) && player.turret_placement[ "result" ] ) + { + plant_origin = player.turret_placement[ "origin" ]; + plant_angles = player.turret_placement[ "angles" ]; + } + else + { + if ( isDefined( level.placeable_equipment_type[ self.name ] ) && level.placeable_equipment_type[ self.name ] == "wallmount" ) + { + plant_origin = self.origin; + plant_angles = self.angles; + } + else + { + plant_origin = self.origin; + plant_angles = self.angles; + } + } + if ( isDefined( level.check_force_deploy_origin ) ) + { + if ( player [[ level.check_force_deploy_origin ]]( self, plant_origin, plant_angles ) ) + { + plant_origin = player.origin; + plant_angles = player.angles; + self.plant_parent = player; + } + } + else + { + if ( isDefined( level.check_force_deploy_z ) ) + { + if ( player [[ level.check_force_deploy_z ]]( self, plant_origin, plant_angles ) ) + { + plant_origin = ( plant_origin[ 0 ], plant_origin[ 1 ], player.origin[ 2 ] + 10 ); + } + } + } + if ( isDefined( iswallmount ) && iswallmount ) + { + self ghost(); + } + replacement = player [[ level.zombie_equipment[ equipment ].place_fn ]]( plant_origin, plant_angles ); + if ( isDefined( replacement ) ) + { + replacement.owner = player; + replacement.original_owner = player; + replacement.name = self.name; + player notify( "equipment_placed" ); + if ( isDefined( level.equipment_planted ) ) + { + player [[ level.equipment_planted ]]( replacement, equipment, self.plant_parent ); + } + player maps/mp/zombies/_zm_buildables::track_buildables_planted( self ); + } + if ( isDefined( self ) ) + { + self delete(); + } + } +} + +equipment_retrieve( player ) +{ + if ( isDefined( self ) ) + { + self stoploopsound(); + original_owner = self.original_owner; + weaponname = self.name; + if ( !isDefined( original_owner ) ) + { + player equipment_give( weaponname ); + self.owner = player; + } + else + { + if ( player != original_owner ) + { + equipment_transfer( weaponname, original_owner, player ); + self.owner = player; + } + player equipment_from_deployed( weaponname ); + } + if ( isDefined( self.requires_pickup ) && self.requires_pickup ) + { + if ( isDefined( level.zombie_equipment[ weaponname ].pickup_fn ) ) + { + self.owner = player; + if ( isDefined( self.damage ) ) + { + player player_set_equipment_damage( weaponname, self.damage ); + } + player [[ level.zombie_equipment[ weaponname ].pickup_fn ]]( self ); + } + } + self.playdialog = 0; + weaponname = self.name; + self delete(); + if ( !player hasweapon( weaponname ) ) + { + player giveweapon( weaponname ); + clip_ammo = player getweaponammoclip( weaponname ); + clip_max_ammo = weaponclipsize( weaponname ); + if ( clip_ammo < clip_max_ammo ) + { + clip_ammo++; + } + player setweaponammoclip( weaponname, clip_ammo ); + } + player maps/mp/zombies/_zm_buildables::track_planted_buildables_pickedup( weaponname ); + } +} + +equipment_drop_to_planted( equipment, player ) +{ +/* +/# + if ( !isDefined( player.current_equipment ) || player.current_equipment != equipment ) + { + assert( player has_deployed_equipment( equipment ) ); + assert( !isDefined( player.current_equipment ) ); +#/ + } +*/ + if ( isDefined( player.current_equipment ) && player.current_equipment == equipment ) + { + player equipment_to_deployed( equipment ); + } + if ( isDefined( level.zombie_equipment[ equipment ].place_fn ) ) + { + replacement = player [[ level.zombie_equipment[ equipment ].place_fn ]]( player.origin, player.angles ); + if ( isDefined( replacement ) ) + { + replacement.owner = player; + replacement.original_owner = player; + replacement.name = equipment; + if ( isDefined( level.equipment_planted ) ) + { + player [[ level.equipment_planted ]]( replacement, equipment, player ); + } + player notify( "equipment_placed" ); + player maps/mp/zombies/_zm_buildables::track_buildables_planted( replacement ); + } + } +} + +equipment_transfer( weaponname, fromplayer, toplayer ) +{ + if ( is_limited_equipment( weaponname ) ) + { +/* +/# + println( "ZM EQUIPMENT: " + weaponname + " transferred from " + fromplayer.name + " to " + toplayer.name + "\n" ); +#/ +*/ + toplayer equipment_orphaned( weaponname ); + wait 0.05; +/* +/# + assert( !toplayer has_player_equipment( weaponname ) ); +#/ +/# + assert( fromplayer has_player_equipment( weaponname ) ); +#/ +*/ + toplayer equipment_give( weaponname ); + toplayer equipment_to_deployed( weaponname ); + if ( isDefined( level.zombie_equipment[ weaponname ].transfer_fn ) ) + { + [[ level.zombie_equipment[ weaponname ].transfer_fn ]]( fromplayer, toplayer ); + } + fromplayer equipment_release( weaponname ); +/* +/# + assert( toplayer has_player_equipment( weaponname ) ); +#/ +/# + assert( !fromplayer has_player_equipment( weaponname ) ); +#/ +*/ + equipment_damage = 0; + toplayer player_set_equipment_damage( weaponname, fromplayer player_get_equipment_damage( weaponname ) ); + fromplayer player_set_equipment_damage( equipment_damage ); + } + else + { +/* +/# + println( "ZM EQUIPMENT: " + weaponname + " swapped from " + fromplayer.name + " to " + toplayer.name + "\n" ); +#/ +*/ + toplayer equipment_give( weaponname ); + if ( isDefined( toplayer.current_equipment ) && toplayer.current_equipment == weaponname ) + { + toplayer equipment_to_deployed( weaponname ); + } + if ( isDefined( level.zombie_equipment[ weaponname ].transfer_fn ) ) + { + [[ level.zombie_equipment[ weaponname ].transfer_fn ]]( fromplayer, toplayer ); + } + equipment_damage = toplayer player_get_equipment_damage( weaponname ); + toplayer player_set_equipment_damage( weaponname, fromplayer player_get_equipment_damage( weaponname ) ); + fromplayer player_set_equipment_damage( weaponname, equipment_damage ); + } +} + +equipment_release( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " release " + equipment + "\n" ); +#/ +*/ + self equipment_take( equipment ); +} + +equipment_drop( equipment ) +{ + if ( isDefined( level.zombie_equipment[ equipment ].place_fn ) ) + { + equipment_drop_to_planted( equipment, self ); +/* +/# + println( "ZM EQUIPMENT: " + self.name + " drop to planted " + equipment + "\n" ); +#/ +*/ + } + else if ( isDefined( level.zombie_equipment[ equipment ].drop_fn ) ) + { + if ( isDefined( self.current_equipment ) && self.current_equipment == equipment ) + { + self equipment_to_deployed( equipment ); + } + item = self [[ level.zombie_equipment[ equipment ].drop_fn ]](); + if ( isDefined( item ) ) + { + if ( isDefined( level.equipment_planted ) ) + { + self [[ level.equipment_planted ]]( item, equipment, self ); + } + item.owner = undefined; + item.damage = self player_get_equipment_damage( equipment ); + } +/* +/# + println( "ZM EQUIPMENT: " + self.name + " dropped " + equipment + "\n" ); +#/ +*/ + } + else + { + self equipment_take(); + } + self notify( "equipment_dropped" ); +} + +equipment_grab( equipment, item ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " picked up " + equipment + "\n" ); +#/ +*/ + self equipment_give( equipment ); + if ( isDefined( level.zombie_equipment[ equipment ].pickup_fn ) ) + { + item.owner = self; + self player_set_equipment_damage( equipment, item.damage ); + self [[ level.zombie_equipment[ equipment ].pickup_fn ]]( item ); + } +} + +equipment_orphaned( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " orphaned " + equipment + "\n" ); +#/ +*/ + self equipment_take( equipment ); +} + +equipment_to_deployed( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " deployed " + equipment + "\n" ); +#/ +*/ + if ( !isDefined( self.deployed_equipment ) ) + { + self.deployed_equipment = []; + } +/* +/# + assert( self.current_equipment == equipment ); +#/ +*/ + self.deployed_equipment[ self.deployed_equipment.size ] = equipment; + self.current_equipment = undefined; + if ( !isDefined( level.riotshield_name ) || equipment != level.riotshield_name ) + { + self takeweapon( equipment ); + } + self setactionslot( 1, "" ); +} + +equipment_from_deployed( equipment ) +{ + if ( !isDefined( equipment ) ) + { + equipment = "none"; + } +/* +/# + println( "ZM EQUIPMENT: " + self.name + " retrieved " + equipment + "\n" ); +#/ +*/ + if ( isDefined( self.current_equipment ) && equipment != self.current_equipment ) + { + self equipment_drop( self.current_equipment ); + } +/* +/# + assert( self has_deployed_equipment( equipment ) ); +#/ +*/ + self.current_equipment = equipment; + if ( isDefined( level.riotshield_name ) && equipment != level.riotshield_name ) + { + self giveweapon( equipment ); + } + if ( self hasweapon( equipment ) ) + { + self setweaponammoclip( equipment, 1 ); + } + self setactionslot( 1, "weapon", equipment ); + arrayremovevalue( self.deployed_equipment, equipment ); + self notify( equipment + "_pickup" ); +} + +eqstub_get_unitrigger_origin() +{ + if ( isDefined( self.origin_parent ) ) + { + return self.origin_parent.origin; + } + tup = anglesToUp( self.angles ); + eq_unitrigger_offset = 12 * tup; + return self.origin + eq_unitrigger_offset; +} + +eqstub_on_spawn_trigger( trigger ) +{ + if ( isDefined( self.link_parent ) ) + { + trigger enablelinkto(); + trigger linkto( self.link_parent ); + trigger setmovingplatformenabled( 1 ); + } +} + +equipment_buy( equipment ) +{ +/* +/# + println( "ZM EQUIPMENT: " + self.name + " bought " + equipment + "\n" ); +#/ +*/ + if ( isDefined( self.current_equipment ) && equipment != self.current_equipment ) + { + self equipment_drop( self.current_equipment ); + } + if ( equipment != "riotshield_zm" && equipment == "alcatraz_shield_zm" && isDefined( self.player_shield_reset_health ) ) + { + self [[ self.player_shield_reset_health ]](); + } + else + { + self player_set_equipment_damage( equipment, 0 ); + } + self equipment_give( equipment ); +} + +generate_equipment_unitrigger( classname, origin, angles, flags, radius, script_height, hint, icon, think, 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( angles ) ) + { + unitrigger_stub.angles = angles; + } + 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 = hint; + /* + if ( getDvarInt( #"1F0A2129" ) ) + { + unitrigger_stub.cursor_hint = "HINT_WEAPON"; + unitrigger_stub.cursor_hint_weapon = icon; + } + */ + 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_stub.originfunc = ::eqstub_get_unitrigger_origin; + unitrigger_stub.onspawnfunc = ::eqstub_on_spawn_trigger; + if ( isDefined( moving ) && moving ) + { + maps/mp/zombies/_zm_unitrigger::register_unitrigger( unitrigger_stub, think ); + } + else + { + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, think ); + } + return unitrigger_stub; +} + +can_pick_up_equipment( equipment_name, equipment_trigger ) +{ + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || self in_revive_trigger() ) + { + return 0; + } + if ( self isthrowinggrenade() ) + { + return 0; + } + if ( isDefined( self.screecher_weapon ) ) + { + return 0; + } + if ( self is_jumping() ) + { + return 0; + } + if ( self is_player_equipment( equipment_name ) ) + { + return 0; + } + if ( isDefined( self.pickup_equipment ) && self.pickup_equipment ) + { + return 0; + } + if ( isDefined( level.equipment_team_pick_up ) && level.equipment_team_pick_up && !self same_team_placed_equipment( equipment_trigger ) ) + { + return 0; + } + return 1; +} + +same_team_placed_equipment( equipment_trigger ) +{ + if ( isDefined( equipment_trigger ) && isDefined( equipment_trigger.stub ) && isDefined( equipment_trigger.stub.model ) && isDefined( equipment_trigger.stub.model.owner ) ) + { + return equipment_trigger.stub.model.owner.pers[ "team" ] == self.pers[ "team" ]; + } +} + +placed_equipment_think( model, equipname, origin, angles, tradius, toffset ) +{ + pickupmodel = spawn( "script_model", origin ); + if ( isDefined( angles ) ) + { + pickupmodel.angles = angles; + } + pickupmodel setmodel( model ); + if ( isDefined( level.equipment_safe_to_drop ) ) + { + if ( !( self [[ level.equipment_safe_to_drop ]]( pickupmodel ) ) ) + { + equipment_disappear_fx( pickupmodel.origin, undefined, pickupmodel.angles ); + pickupmodel delete(); + self equipment_take( equipname ); + return undefined; + } + } + watchername = getsubstr( equipname, 0, equipname.size - 3 ); + if ( isDefined( level.retrievehints[ watchername ] ) ) + { + hint = level.retrievehints[ watchername ].hint; + } + else + { + hint = &"MP_GENERIC_PICKUP"; + } + icon = get_equipment_icon( equipname ); + if ( !isDefined( tradius ) ) + { + tradius = 32; + } + torigin = origin; + if ( isDefined( toffset ) ) + { + tforward = anglesToForward( angles ); + torigin += toffset * tforward; + } + tup = anglesToUp( angles ); + eq_unitrigger_offset = 12 * tup; + if ( isDefined( pickupmodel.canmove ) ) + { + pickupmodel.stub = generate_equipment_unitrigger( "trigger_radius_use", torigin + eq_unitrigger_offset, angles, 0, tradius, 64, hint, equipname, ::placed_equipment_unitrigger_think, pickupmodel.canmove ); + } + pickupmodel.stub.model = pickupmodel; + pickupmodel.stub.equipname = equipname; + pickupmodel.equipname = equipname; + pickupmodel thread item_attract_zombies(); + pickupmodel thread item_watch_explosions(); + if ( is_limited_equipment( equipname ) ) + { + if ( !isDefined( level.dropped_equipment ) ) + { + level.dropped_equipment = []; + } + if ( isDefined( level.dropped_equipment[ equipname ] ) && isDefined( level.dropped_equipment[ equipname ].model ) ) + { + level.dropped_equipment[ equipname ].model dropped_equipment_destroy( 1 ); + } + level.dropped_equipment[ equipname ] = pickupmodel.stub; + } + destructible_equipment_list_add( pickupmodel ); + return pickupmodel; +} + +watch_player_visibility( equipment ) +{ + self endon( "kill_trigger" ); + self setinvisibletoall(); + while ( isDefined( self ) ) + { + players = getplayers(); + _a1142 = players; + _k1142 = getFirstArrayKey( _a1142 ); + while ( isDefined( _k1142 ) ) + { + player = _a1142[ _k1142 ]; + if ( !isDefined( player ) ) + { + } + else + { + invisible = !player can_pick_up_equipment( equipment, self ); + if ( isDefined( self ) ) + { + self setinvisibletoplayer( player, invisible ); + } + wait 0.05; + } + _k1142 = getNextArrayKey( _a1142, _k1142 ); + } + wait 1; + } +} + +placed_equipment_unitrigger_think() +{ + self endon( "kill_trigger" ); + self thread watch_player_visibility( self.stub.equipname ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( !player can_pick_up_equipment( self.stub.equipname, self ) ) + { + continue; + } + self thread pickup_placed_equipment( player ); + return; + } +} + +pickup_placed_equipment( player ) +{ +/* +/# + if ( isDefined( player.pickup_equipment )assert( !player.pickup_equipment ); +#/ +*/ + player.pickup_equipment = 1; + stub = self.stub; + if ( isDefined( player.current_equipment ) && stub.equipname != player.current_equipment ) + { + player equipment_drop( player.current_equipment ); + } + if ( is_limited_equipment( stub.equipname ) ) + { + if ( isDefined( level.dropped_equipment ) && isDefined( level.dropped_equipment[ stub.equipname ] ) && level.dropped_equipment[ stub.equipname ] == stub ) + { + } + } + if ( isDefined( stub.model ) ) + { + stub.model equipment_retrieve( player ); + } + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( stub ); + wait 3; + player.pickup_equipment = 0; +} + +dropped_equipment_think( model, equipname, origin, angles, tradius, toffset ) +{ + pickupmodel = spawn( "script_model", origin ); + if ( isDefined( angles ) ) + { + pickupmodel.angles = angles; + } + pickupmodel setmodel( model ); + if ( isDefined( level.equipment_safe_to_drop ) ) + { + if ( !( self [[ level.equipment_safe_to_drop ]]( pickupmodel ) ) ) + { + equipment_disappear_fx( pickupmodel.origin, undefined, pickupmodel.angles ); + pickupmodel delete(); + self equipment_take( equipname ); + return; + } + } + watchername = getsubstr( equipname, 0, equipname.size - 3 ); + if ( isDefined( level.retrievehints[ watchername ] ) ) + { + hint = level.retrievehints[ watchername ].hint; + } + else + { + hint = &"MP_GENERIC_PICKUP"; + } + icon = get_equipment_icon( equipname ); + if ( !isDefined( tradius ) ) + { + tradius = 32; + } + torigin = origin; + if ( isDefined( toffset ) ) + { + offset = 64; + tforward = anglesToForward( angles ); + torigin = torigin + ( toffset * tforward ) + vectorScale( ( 0, 0, 0 ), 8 ); + } + if ( isDefined( pickupmodel.canmove ) ) + { + pickupmodel.stub = generate_equipment_unitrigger( "trigger_radius_use", torigin, angles, 0, tradius, 64, hint, equipname, ::dropped_equipment_unitrigger_think, pickupmodel.canmove ); + } + pickupmodel.stub.model = pickupmodel; + pickupmodel.stub.equipname = equipname; + pickupmodel.equipname = equipname; + if ( isDefined( level.equipment_planted ) ) + { + self [[ level.equipment_planted ]]( pickupmodel, equipname, self ); + } + if ( !isDefined( level.dropped_equipment ) ) + { + level.dropped_equipment = []; + } + if ( isDefined( level.dropped_equipment[ equipname ] ) ) + { + level.dropped_equipment[ equipname ].model dropped_equipment_destroy( 1 ); + } + level.dropped_equipment[ equipname ] = pickupmodel.stub; + destructible_equipment_list_add( pickupmodel ); + pickupmodel thread item_attract_zombies(); + return pickupmodel; +} + +dropped_equipment_unitrigger_think() +{ + self endon( "kill_trigger" ); + self thread watch_player_visibility( self.stub.equipname ); + while ( 1 ) + { + self waittill( "trigger", player ); + while ( !player can_pick_up_equipment( self.stub.equipname, self ) ) + { + continue; + } + self thread pickup_dropped_equipment( player ); + return; + } +} + +pickup_dropped_equipment( player ) +{ + player.pickup_equipment = 1; + stub = self.stub; + if ( isDefined( player.current_equipment ) && stub.equipname != player.current_equipment ) + { + player equipment_drop( player.current_equipment ); + } + player equipment_grab( stub.equipname, stub.model ); + stub.model dropped_equipment_destroy(); + wait 3; + player.pickup_equipment = 0; +} + +dropped_equipment_destroy( gusto ) +{ + stub = self.stub; + if ( isDefined( gusto ) && gusto ) + { + equipment_disappear_fx( self.origin, undefined, self.angles ); + } + if ( isDefined( level.dropped_equipment ) ) + { + } + if ( isDefined( stub.model ) ) + { + stub.model delete(); + } + if ( isDefined( self.original_owner ) || is_limited_equipment( stub.equipname ) && maps/mp/zombies/_zm_weapons::is_weapon_included( stub.equipname ) ) + { + self.original_owner equipment_take( stub.equipname ); + } + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( stub ); +} + +add_placeable_equipment( equipment, modelname, destroy_fn, type ) +{ + if ( !isDefined( level.placeable_equipment ) ) + { + level.placeable_equipment = []; + } + level.placeable_equipment[ equipment ] = modelname; + precachemodel( modelname ); + precacheitem( equipment + "_turret" ); + if ( !isDefined( level.placeable_equipment_destroy_fn ) ) + { + level.placeable_equipment_destroy_fn = []; + } + level.placeable_equipment_destroy_fn[ equipment ] = destroy_fn; + if ( !isDefined( level.placeable_equipment_type ) ) + { + level.placeable_equipment_type = []; + } + level.placeable_equipment_type[ equipment ] = type; +} + +is_placeable_equipment( equipment ) +{ + if ( isDefined( level.placeable_equipment ) && isDefined( level.placeable_equipment[ equipment ] ) ) + { + return 1; + } + return 0; +} + +equipment_placement_watcher() +{ + self endon( "death_or_disconnect" ); + for ( ;; ) + { + self waittill( "weapon_change", weapon ); + if ( self.sessionstate != "spectator" && is_placeable_equipment( weapon ) ) + { + self thread equipment_watch_placement( weapon ); + } + } +} + +equipment_watch_placement( equipment ) +{ + self.turret_placement = undefined; + carry_offset = vectorScale( ( 0, 0, 0 ), 22 ); + carry_angles = ( 0, 0, 0 ); + placeturret = spawnturret( "auto_turret", self.origin, equipment + "_turret" ); + placeturret.angles = self.angles; + placeturret setmodel( level.placeable_equipment[ equipment ] ); + placeturret setturretcarried( 1 ); + placeturret setturretowner( self ); + if ( isDefined( level.placeable_equipment_type[ equipment ] ) ) + { + placeturret setturrettype( level.placeable_equipment_type[ equipment ] ); + } + self carryturret( placeturret, carry_offset, carry_angles ); + if ( isDefined( level.use_swipe_protection ) ) + { + self thread watch_melee_swipes( equipment, placeturret ); + } + self notify( "create_equipment_turret" ); + ended = self waittill_any_return( "weapon_change", "grenade_fire", "death_or_disconnect" ); + if ( isDefined( level.use_legacy_equipment_placement ) && !level.use_legacy_equipment_placement ) + { + self.turret_placement = self canplayerplaceturret( /*placeturret*/ ); + } + if ( ended == "weapon_change" ) + { + self.turret_placement = undefined; + if ( self hasweapon( equipment ) ) + { + self setweaponammoclip( equipment, 1 ); + } + } + self notify( "destroy_equipment_turret" ); + self stopcarryturret( placeturret ); + placeturret setturretcarried( 0 ); + placeturret delete(); +} + +watch_melee_swipes( equipment, turret ) +{ + self endon( "weapon_change" ); + self endon( "grenade_fire" ); + self endon( "death" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "melee_swipe", zombie ); + while ( distancesquared( zombie.origin, self.origin ) > ( zombie.meleeattackdist * zombie.meleeattackdist ) ) + { + continue; + } + tpos = turret.origin; + tangles = turret.angles; + self player_damage_equipment( equipment, 200, zombie.origin ); + if ( self.equipment_damage[ equipment ] >= 1500 ) + { + thread equipment_disappear_fx( tpos, undefined, tangles ); + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons[ 0 ] ) ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + if ( isalive( self ) ) + { + self playlocalsound( level.zmb_laugh_alias ); + } + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + self equipment_release( equipment ); + return; + } + } +} + +player_get_equipment_damage( equipment ) +{ + if ( isDefined( self.equipment_damage ) && isDefined( self.equipment_damage[ equipment ] ) ) + { + return self.equipment_damage[ equipment ]; + } + return 0; +} + +player_set_equipment_damage( equipment, damage ) +{ + if ( !isDefined( self.equipment_damage ) ) + { + self.equipment_damage = []; + } + self.equipment_damage[ equipment ] = damage; +} + +player_damage_equipment( equipment, damage, origin ) +{ + if ( !isDefined( self.equipment_damage ) ) + { + self.equipment_damage = []; + } + if ( !isDefined( self.equipment_damage[ equipment ] ) ) + { + self.equipment_damage[ equipment ] = 0; + } + self.equipment_damage[ equipment ] += damage; + if ( self.equipment_damage[ equipment ] > 1500 ) + { + if ( isDefined( level.placeable_equipment_destroy_fn[ equipment ] ) ) + { + self [[ level.placeable_equipment_destroy_fn[ equipment ] ]](); + } + else + { + equipment_disappear_fx( origin ); + } + self equipment_release( equipment ); + } +} + +item_damage( damage ) +{ + if ( isDefined( self.isriotshield ) && self.isriotshield ) + { + if ( isDefined( level.riotshield_damage_callback ) && isDefined( self.owner ) ) + { + self.owner [[ level.riotshield_damage_callback ]]( damage, 0 ); + } + else + { + if ( isDefined( level.deployed_riotshield_damage_callback ) ) + { + self [[ level.deployed_riotshield_damage_callback ]]( damage ); + } + } + } + else + { + if ( isDefined( self.owner ) ) + { + self.owner player_damage_equipment( self.equipname, damage, self.origin ); + return; + } + else + { + if ( !isDefined( self.damage ) ) + { + self.damage = 0; + } + self.damage += damage; + if ( self.damage > 1500 ) + { + self thread dropped_equipment_destroy( 1 ); + } + } + } +} + +item_watch_damage() +{ + self endon( "death" ); + self setcandamage( 1 ); + self.health = 1500; + while ( 1 ) + { + self waittill( "damage", amount ); + self item_damage( amount ); + } +} + +item_watch_explosions() +{ + self endon( "death" ); + while ( 1 ) + { + level waittill( "grenade_exploded", position, radius, idamage, odamage ); + wait randomfloatrange( 0.05, 0.3 ); + distsqrd = distancesquared( self.origin, position ); + if ( distsqrd < ( radius * radius ) ) + { + dist = sqrt( distsqrd ); + dist /= radius; + damage = odamage + ( ( idamage - odamage ) * ( 1 - dist ) ); + self item_damage( damage * 5 ); + } + } +} + +get_item_health() +{ +/* +/# + damage = 0; + if ( isDefined( self.isriotshield ) && self.isriotshield ) + { + damagemax = level.zombie_vars[ "riotshield_hit_points" ]; + if ( isDefined( self.owner ) ) + { + damage = self.owner.shielddamagetaken; + } + else + { + if ( isDefined( level.deployed_riotshield_damage_callback ) ) + { + damage = self.shielddamagetaken; + } + } + } + else + { + if ( isDefined( self.owner ) ) + { + damagemax = 1500; + damage = self.owner player_get_equipment_damage( self.equipname ); + } + else + { + damagemax = 1500; + if ( isDefined( self.damage ) ) + { + damage = self.damage; + } + } + } + return ( damagemax - damage ) / damagemax; +#/ +*/ +} + +debughealth() +{ +/* +/# + self endon( "death" ); + self endon( "stop_attracting_zombies" ); + while ( 1 ) + { + if ( getDvarInt( #"EB512CB7" ) ) + { + health = self get_item_health(); + color = ( 1 - health, health, 0 ); + text = "" + ( health * 100 ) + ""; + print3d( self.origin, text, color, 1, 0,5, 1 ); + } + wait 0.05; +#/ + } +*/ +} + +item_choke() +{ + if ( !isDefined( level.item_choke_count ) ) + { + level.item_choke_count = 0; + } + level.item_choke_count++; + if ( level.item_choke_count >= 10 ) + { + wait 0.05; + level.item_choke_count = 0; + } +} + +is_equipment_ignored( equipname ) +{ + if ( isDefined( level.equipment_ignored_by_zombies ) && isDefined( equipname ) && isDefined( level.equipment_ignored_by_zombies[ equipname ] ) ) + { + return 1; + } + return 0; +} + +enemies_ignore_equipment( equipname ) +{ + if ( !isDefined( level.equipment_ignored_by_zombies ) ) + { + level.equipment_ignored_by_zombies = []; + } + level.equipment_ignored_by_zombies[ equipname ] = equipname; +} + +item_attract_zombies() +{ + self endon( "death" ); + self notify( "stop_attracting_zombies" ); + self endon( "stop_attracting_zombies" ); +/* +/# + self thread debughealth(); +#/ +*/ + if ( is_equipment_ignored( self.equipname ) ) + { + return; + } + while ( 1 ) + { + if ( isDefined( level.vert_equipment_attack_range ) ) + { + vdistmax = level.vert_equipment_attack_range; + } + else + { + vdistmax = 36; + } + if ( isDefined( level.max_equipment_attack_range ) ) + { + distmax = level.max_equipment_attack_range * level.max_equipment_attack_range; + } + else + { + distmax = 4096; + } + if ( isDefined( level.min_equipment_attack_range ) ) + { + distmin = level.min_equipment_attack_range * level.min_equipment_attack_range; + } + else + { + distmin = 2025; + } + ai = getaiarray( level.zombie_team ); + i = 0; + while ( i < ai.size ) + { + if ( !isDefined( ai[ i ] ) ) + { + i++; + continue; + } + else if ( isDefined( ai[ i ].ignore_equipment ) && ai[ i ].ignore_equipment ) + { + i++; + continue; + } + else + { + if ( isDefined( level.ignore_equipment ) ) + { + if ( self [[ level.ignore_equipment ]]( ai[ i ] ) ) + { + i++; + continue; + } + } + else if ( isDefined( ai[ i ].is_inert ) && ai[ i ].is_inert ) + { + i++; + continue; + } + else + { + if ( isDefined( ai[ i ].is_traversing ) && ai[ i ].is_traversing ) + { + i++; + continue; + } + else + { + vdist = abs( ai[ i ].origin[ 2 ] - self.origin[ 2 ] ); + distsqrd = distance2dsquared( ai[ i ].origin, self.origin ); + if ( isDefined( self.equipname ) || self.equipname == "riotshield_zm" && self.equipname == "alcatraz_shield_zm" ) + { + vdistmax = 108; + } + should_attack = 0; + if ( isDefined( level.should_attack_equipment ) ) + { + should_attack = self [[ level.should_attack_equipment ]]( distsqrd ); + } + if ( distsqrd < distmax && distsqrd > distmin || vdist < vdistmax && should_attack ) + { + if ( isDefined( ai[ i ].isscreecher ) && !ai[ i ].isscreecher && !ai[ i ] is_quad() && !ai[ i ] is_leaper() ) + { + ai[ i ] thread attack_item( self ); + item_choke(); + } + } + item_choke(); + } + } + } + i++; + } + wait 0.1; + } +} + +attack_item( item ) +{ + self endon( "death" ); + item endon( "death" ); + self endon( "start_inert" ); + if ( isDefined( self.doing_equipment_attack ) && self.doing_equipment_attack ) + { + return 0; + } + if ( isDefined( self.not_interruptable ) && self.not_interruptable ) + { + return 0; + } + self thread attack_item_stop( item ); + self thread attack_item_interrupt( item ); + if ( getDvar( "zombie_equipment_attack_freq" ) == "" ) + { + setdvar( "zombie_equipment_attack_freq", "15" ); + } + freq = getDvarInt( "zombie_equipment_attack_freq" ); + self.doing_equipment_attack = 1; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 1 - " + getTime() ); + self.item = item; + if ( !isDefined( self ) || !isalive( self ) ) + { + return; + } + if ( isDefined( item.zombie_attack_callback ) ) + { + item [[ item.zombie_attack_callback ]]( self ); + } + self thread maps/mp/zombies/_zm_audio::do_zombies_playvocals( "attack", self.animname ); + if ( isDefined( level.attack_item ) ) + { + self [[ level.attack_item ]](); + } + melee_anim = "zm_window_melee"; + if ( !self.has_legs ) + { + melee_anim = "zm_walk_melee_crawl"; + if ( self.a.gib_ref == "no_legs" ) + { + melee_anim = "zm_stumpy_melee"; + } + else + { + if ( self.zombie_move_speed == "run" || self.zombie_move_speed == "sprint" ) + { + melee_anim = "zm_run_melee_crawl"; + } + } + } + self orientmode( "face point", item.origin ); + self animscripted( self.origin, flat_angle( vectorToAngles( item.origin - self.origin ) ), melee_anim ); + self notify( "item_attack" ); + if ( isDefined( self.custom_item_dmg ) ) + { + item thread item_damage( self.custom_item_dmg ); + } + else + { + item thread item_damage( 100 ); + } + item playsound( "fly_riotshield_zm_impact_flesh" ); + wait ( randomint( 100 ) / 100 ); + self.doing_equipment_attack = 0; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 0 from wait - " + getTime() ); + self orientmode( "face default" ); +} + +attack_item_interrupt( item ) +{ + if ( isDefined( self.has_legs ) && !self.has_legs ) + { + return; + } + self notify( "attack_item_interrupt" ); + self endon( "attack_item_interrupt" ); + self endon( "death" ); + while ( isDefined( self.has_legs ) && self.has_legs ) + { + self waittill( "damage" ); + } + self stopanimscripted(); + self.doing_equipment_attack = 0; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 0 from death - " + getTime() ); + self.item = undefined; +} + +attack_item_stop( item ) +{ + self notify( "attack_item_stop" ); + self endon( "attack_item_stop" ); + self endon( "death" ); + item waittill( "death" ); + self stopanimscripted(); + self.doing_equipment_attack = 0; + self maps/mp/zombies/_zm_spawner::zombie_history( "doing equipment attack 0 from death - " + getTime() ); + self.item = undefined; + if ( isDefined( level.attack_item_stop ) ) + { + self [[ level.attack_item_stop ]](); + } +} + +window_notetracks( msg, equipment ) +{ + self endon( "death" ); + equipment endon( "death" ); + while ( self.doing_equipment_attack ) + { + self waittill( msg, notetrack ); + if ( notetrack == "end" ) + { + return; + } + if ( notetrack == "fire" ) + { + equipment item_damage( 100 ); + } + } +} + +destructible_equipment_list_check() +{ + if ( !isDefined( level.destructible_equipment ) ) + { + level.destructible_equipment = []; + } + i = 0; + while ( i < level.destructible_equipment.size ) + { + if ( !isDefined( level.destructible_equipment[ i ] ) ) + { + arrayremoveindex( level.destructible_equipment, i ); + continue; + } + else + { + i++; + } + } +} + +destructible_equipment_list_add( item ) +{ + destructible_equipment_list_check(); + level.destructible_equipment[ level.destructible_equipment.size ] = item; +} + +get_destructible_equipment_list() +{ + destructible_equipment_list_check(); + return level.destructible_equipment; +} + +equipment_disappear_fx( origin, fx, angles ) +{ + effect = level._equipment_disappear_fx; + if ( isDefined( fx ) ) + { + effect = fx; + } + if ( isDefined( angles ) ) + { + playfx( effect, origin, anglesToForward( angles ) ); + } + else + { + playfx( effect, origin ); + } + wait 1.1; +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_gump.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_gump.gsc new file mode 100644 index 0000000..5aaa735 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_gump.gsc @@ -0,0 +1,81 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( isDefined( level.disable_blackscreen_clientfield ) && !level.disable_blackscreen_clientfield ) + { + registerclientfield( "toplayer", "blackscreen", 1, 1, "int" ); + } + if ( !isDefined( level.uses_gumps ) ) + { + level.uses_gumps = 0; + } + if ( isDefined( level.uses_gumps ) && level.uses_gumps ) + { + onplayerconnect_callback( ::player_connect_gump ); + } +} + +player_teleport_blackscreen_on() +{ + if ( isDefined( level.disable_blackscreen_clientfield ) && level.disable_blackscreen_clientfield ) + { + return; + } + if ( isDefined( level.uses_gumps ) && level.uses_gumps ) + { + self setclientfieldtoplayer( "blackscreen", 1 ); + wait 0.05; + self setclientfieldtoplayer( "blackscreen", 0 ); + } +} + +player_connect_gump() +{ +} + +player_watch_spectate_change() +{ + if ( isDefined( level.disable_blackscreen_clientfield ) && level.disable_blackscreen_clientfield ) + { + return; + } + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "spectator_cycle" ); + self setclientfieldtoplayer( "blackscreen", 1 ); + wait 0.05; + self setclientfieldtoplayer( "blackscreen", 0 ); + } +} + +gump_test() +{ +/* +/# + wait 10; + pos1 = ( -4904, -7657, 4 ); + pos3 = ( 7918, -6506, 177 ); + pos2 = ( 1986, -73, 4 ); + players = get_players(); + if ( isDefined( players[ 0 ] ) ) + { + players[ 0 ] setorigin( pos1 ); + } + wait 0.05; + if ( isDefined( players[ 1 ] ) ) + { + players[ 1 ] setorigin( pos2 ); + } + wait 0.05; + if ( isDefined( players[ 2 ] ) ) + { + players[ 2 ] setorigin( pos3 ); +#/ + } +*/ +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_boards.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_boards.gsc new file mode 100644 index 0000000..88fd512 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_boards.gsc @@ -0,0 +1,131 @@ +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +hack_boards() +{ + windows = getstructarray( "exterior_goal", "targetname" ); + i = 0; + while ( i < windows.size ) + { + window = windows[ i ]; + struct = spawnstruct(); + spot = window; + if ( isDefined( window.trigger_location ) ) + { + spot = window.trigger_location; + } + org = groundpos( spot.origin ) + vectorScale( ( 0, 0, 1 ), 4 ); + r = 96; + h = 96; + if ( isDefined( spot.radius ) ) + { + r = spot.radius; + } + if ( isDefined( spot.height ) ) + { + h = spot.height; + } + struct.origin = org + vectorScale( ( 0, 0, 1 ), 48 ); + struct.radius = r; + struct.height = h; + struct.script_float = 2; + struct.script_int = 0; + struct.window = window; + struct.no_bullet_trace = 1; + struct.no_sight_check = 1; + struct.dot_limit = 0.7; + struct.no_touch_check = 1; + struct.last_hacked_round = 0; + struct.num_hacks = 0; + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( struct, ::board_hack, ::board_qualifier ); + i++; + } +} + +board_hack( hacker ) +{ + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( self ); + num_chunks_checked = 0; + last_repaired_chunk = undefined; + if ( self.last_hacked_round != level.round_number ) + { + self.last_hacked_round = level.round_number; + self.num_hacks = 0; + } + self.num_hacks++; + if ( self.num_hacks < 3 ) + { + hacker maps/mp/zombies/_zm_score::add_to_player_score( 100 ); + } + else + { + cost = int( min( 300, hacker.score ) ); + if ( cost ) + { + hacker maps/mp/zombies/_zm_score::minus_to_player_score( cost ); + } + } + while ( 1 ) + { + if ( all_chunks_intact( self.window, self.window.barrier_chunks ) ) + { + break; + } + else chunk = get_random_destroyed_chunk( self.window, self.window.barrier_chunks ); + if ( !isDefined( chunk ) ) + { + break; + } + else self.window thread maps/mp/zombies/_zm_blockers::replace_chunk( self.window, chunk, undefined, 0, 1 ); + last_repaired_chunk = chunk; + if ( isDefined( self.clip ) ) + { + self.window.clip enable_trigger(); + self.window.clip disconnectpaths(); + } + else + { + blocker_disconnect_paths( self.window.neg_start, self.window.neg_end ); + } + wait_network_frame(); + num_chunks_checked++; + if ( num_chunks_checked >= 20 ) + { + break; + } + else + { + } + } + if ( isDefined( self.window.zbarrier ) ) + { + while ( isDefined( last_repaired_chunk ) ) + { + while ( self.window.zbarrier getzbarrierpiecestate( last_repaired_chunk ) == "closing" ) + { + wait 0.05; + } + } + } + else while ( isDefined( last_repaired_chunk ) && last_repaired_chunk.state == "mid_repair" ) + { + wait 0.05; + } + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( self, ::board_hack, ::board_qualifier ); + self.window notify( "blocker_hacked" ); + self.window notify( "no valid boards" ); +} + +board_qualifier( player ) +{ + if ( all_chunks_intact( self.window, self.window.barrier_chunks ) || no_valid_repairable_boards( self.window, self.window.barrier_chunks ) ) + { + return 0; + } + return 1; +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_box.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_box.gsc new file mode 100644 index 0000000..235fe8b --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_box.gsc @@ -0,0 +1,371 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +box_hacks() +{ + boxes = getstructarray( "treasure_chest_use", "targetname" ); + i = 0; + while ( i < boxes.size ) + { + box = boxes[ i ]; + box.box_hacks[ "respin" ] = ::init_box_respin; + box.box_hacks[ "respin_respin" ] = ::init_box_respin_respin; + box.box_hacks[ "summon_box" ] = ::init_summon_box; + box.last_hacked_round = 0; + i++; + } + level._zombiemode_chest_joker_chance_override_func = ::check_for_free_locations; + level._zombiemode_custom_box_move_logic = ::custom_box_move_logic; + level._zombiemode_check_firesale_loc_valid_func = ::custom_check_firesale_loc_valid_func; + init_summon_hacks(); +} + +custom_check_firesale_loc_valid_func() +{ + if ( isDefined( self.unitrigger_stub ) ) + { + box = self.unitrigger_stub.trigger_target; + } + else + { + if ( isDefined( self.stub ) ) + { + box = self.stub.trigger_target; + } + } + if ( box.last_hacked_round >= level.round_number ) + { + return 0; + } + return 1; +} + +custom_box_move_logic() +{ + num_hacked_locs = 0; + i = 0; + while ( i < level.chests.size ) + { + if ( level.chests[ i ].last_hacked_round >= level.round_number ) + { + num_hacked_locs++; + } + i++; + } + if ( num_hacked_locs == 0 ) + { + maps/mp/zombies/_zm_magicbox::default_box_move_logic(); + return; + } + found_loc = 0; + original_spot = level.chest_index; + while ( !found_loc ) + { + level.chest_index++; + if ( original_spot == level.chest_index ) + { + level.chest_index++; + } + level.chest_index %= level.chests.size; + if ( level.chests[ level.chest_index ].last_hacked_round < level.round_number ) + { + found_loc = 1; + } + } +} + +check_for_free_locations( chance ) +{ + boxes = level.chests; + stored_chance = chance; + chance = -1; + i = 0; + while ( i < boxes.size ) + { + if ( i == level.chest_index ) + { + i++; + continue; + } + else if ( boxes[ i ].last_hacked_round < level.round_number ) + { + chance = stored_chance; + break; + } + else + { + i++; + } + } + return chance; +} + +init_box_respin( chest, player ) +{ + self thread box_respin_think( chest, player ); +} + +box_respin_think( chest, player ) +{ + respin_hack = spawnstruct(); + respin_hack.origin = self.origin + vectorScale( ( 0, 0, 1 ), 24 ); + respin_hack.radius = 48; + respin_hack.height = 72; + respin_hack.script_int = 600; + respin_hack.script_float = 1.5; + respin_hack.player = player; + respin_hack.no_bullet_trace = 1; + respin_hack.chest = chest; + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( respin_hack, ::respin_box, ::hack_box_qualifier ); + self.weapon_model waittill_either( "death", "kill_respin_think_thread" ); + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( respin_hack ); +} + +respin_box_thread( hacker ) +{ + if ( isDefined( self.chest.zbarrier.weapon_model ) ) + { + self.chest.zbarrier.weapon_model notify( "kill_respin_think_thread" ); + } + self.chest.no_fly_away = 1; + self.chest.zbarrier notify( "box_hacked_respin" ); + self.chest disable_trigger(); + play_sound_at_pos( "open_chest", self.chest.zbarrier.origin ); + play_sound_at_pos( "music_chest", self.chest.zbarrier.origin ); + maps/mp/zombies/_zm_weapons::unacquire_weapon_toggle( self.chest.zbarrier.weapon_string ); + self.chest.zbarrier thread maps/mp/zombies/_zm_magicbox::treasure_chest_weapon_spawn( self.chest, hacker, 1 ); + self.chest.zbarrier waittill( "randomization_done" ); + self.chest.no_fly_away = undefined; + if ( !flag( "moving_chest_now" ) ) + { + self.chest enable_trigger(); + self.chest thread maps/mp/zombies/_zm_magicbox::treasure_chest_timeout(); + } +} + +respin_box( hacker ) +{ + self thread respin_box_thread( hacker ); +} + +hack_box_qualifier( player ) +{ + if ( player == self.chest.chest_user && isDefined( self.chest.weapon_out ) ) + { + return 1; + } + return 0; +} + +init_box_respin_respin( chest, player ) +{ + self thread box_respin_respin_think( chest, player ); +} + +box_respin_respin_think( chest, player ) +{ + respin_hack = spawnstruct(); + respin_hack.origin = self.origin + vectorScale( ( 0, 0, 1 ), 24 ); + respin_hack.radius = 48; + respin_hack.height = 72; + respin_hack.script_int = -950; + respin_hack.script_float = 1.5; + respin_hack.player = player; + respin_hack.no_bullet_trace = 1; + respin_hack.chest = chest; + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( respin_hack, ::respin_respin_box, ::hack_box_qualifier ); + self.weapon_model waittill_either( "death", "kill_respin_respin_think_thread" ); + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( respin_hack ); +} + +respin_respin_box( hacker ) +{ + org = self.chest.zbarrier.origin; + if ( isDefined( self.chest.zbarrier.weapon_model ) ) + { + self.chest.zbarrier.weapon_model notify( "kill_respin_respin_think_thread" ); + self.chest.zbarrier.weapon_model notify( "kill_weapon_movement" ); + self.chest.zbarrier.weapon_model moveto( org + vectorScale( ( 0, 0, 1 ), 40 ), 0,5 ); + } + if ( isDefined( self.chest.zbarrier.weapon_model_dw ) ) + { + self.chest.zbarrier.weapon_model_dw notify( "kill_weapon_movement" ); + self.chest.zbarrier.weapon_model_dw moveto( ( org + vectorScale( ( 0, 0, 1 ), 40 ) ) - vectorScale( ( 0, 0, 1 ), 3 ), 0,5 ); + } + self.chest.zbarrier notify( "box_hacked_rerespin" ); + self.chest.box_rerespun = 1; + self thread fake_weapon_powerup_thread( self.chest.zbarrier.weapon_model, self.chest.zbarrier.weapon_model_dw ); +} + +fake_weapon_powerup_thread( weapon1, weapon2 ) +{ + weapon1 endon( "death" ); + playfxontag( level._effect[ "powerup_on_solo" ], weapon1, "tag_origin" ); + playsoundatposition( "zmb_spawn_powerup", weapon1.origin ); + weapon1 playloopsound( "zmb_spawn_powerup_loop" ); + self thread fake_weapon_powerup_timeout( weapon1, weapon2 ); + while ( isDefined( weapon1 ) ) + { + waittime = randomfloatrange( 2.5, 5 ); + yaw = randomint( 360 ); + if ( yaw > 300 ) + { + yaw = 300; + } + else + { + if ( yaw < 60 ) + { + yaw = 60; + } + } + yaw = weapon1.angles[ 1 ] + yaw; + weapon1 rotateto( ( -60 + randomint( 120 ), yaw, -45 + randomint( 90 ) ), waittime, waittime * 0.5, waittime * 0.5 ); + if ( isDefined( weapon2 ) ) + { + weapon2 rotateto( ( -60 + randomint( 120 ), yaw, -45 + randomint( 90 ) ), waittime, waittime * 0.5, waittime * 0.5 ); + } + wait randomfloat( waittime - 0,1 ); + } +} + +fake_weapon_powerup_timeout( weapon1, weapon2 ) +{ + weapon1 endon( "death" ); + wait 15; + i = 0; + while ( i < 40 ) + { + if ( i % 2 ) + { + weapon1 hide(); + if ( isDefined( weapon2 ) ) + { + weapon2 hide(); + } + } + else + { + weapon1 show(); + if ( isDefined( weapon2 ) ) + { + weapon2 hide(); + } + } + if ( i < 15 ) + { + wait 0.5; + i++; + continue; + } + else if ( i < 25 ) + { + wait 0.25; + i++; + continue; + } + else + { + wait 0.1; + } + i++; + } + self.chest notify( "trigger" ); + if ( isDefined( weapon1 ) ) + { + weapon1 delete(); + } + if ( isDefined( weapon2 ) ) + { + weapon2 delete(); + } +} + +init_summon_hacks() +{ + chests = getstructarray( "treasure_chest_use", "targetname" ); + i = 0; + while ( i < chests.size ) + { + chest = chests[ i ]; + chest init_summon_box( chest.hidden ); + i++; + } +} + +init_summon_box( create ) +{ + if ( create ) + { + if ( isDefined( self._summon_hack_struct ) ) + { + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( self._summon_hack_struct ); + self._summon_hack_struct = undefined; + } + struct = spawnstruct(); + struct.origin = self.chest_box.origin + vectorScale( ( 0, 0, 1 ), 24 ); + struct.radius = 48; + struct.height = 72; + struct.script_int = 1200; + struct.script_float = 5; + struct.no_bullet_trace = 1; + struct.chest = self; + self._summon_hack_struct = struct; + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( struct, ::summon_box, ::summon_box_qualifier ); + } + else + { + if ( isDefined( self._summon_hack_struct ) ) + { + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( self._summon_hack_struct ); + self._summon_hack_struct = undefined; + } + } +} + +summon_box_thread( hacker ) +{ + self.chest.last_hacked_round = level.round_number + randomintrange( 2, 5 ); + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( self ); + self.chest thread maps/mp/zombies/_zm_magicbox::show_chest(); + self.chest notify( "kill_chest_think" ); + self.chest.auto_open = 1; + self.chest.no_charge = 1; + self.chest.no_fly_away = 1; + self.chest.forced_user = hacker; + self.chest thread maps/mp/zombies/_zm_magicbox::treasure_chest_think(); + self.chest.zbarrier waittill( "closed" ); + self.chest.forced_user = undefined; + self.chest.auto_open = undefined; + self.chest.no_charge = undefined; + self.chest.no_fly_away = undefined; + self.chest thread maps/mp/zombies/_zm_magicbox::hide_chest(); +} + +summon_box( hacker ) +{ + self thread summon_box_thread( hacker ); + if ( isDefined( hacker ) ) + { + hacker thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "hack_box" ); + } +} + +summon_box_qualifier( player ) +{ + if ( self.chest.last_hacked_round > level.round_number ) + { + return 0; + } + if ( isDefined( self.chest.zbarrier.chest_moving ) && self.chest.zbarrier.chest_moving ) + { + return 0; + } + return 1; +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_doors.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_doors.gsc new file mode 100644 index 0000000..1c632c5 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_doors.gsc @@ -0,0 +1,108 @@ +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +door_struct_debug() +{ + while ( 1 ) + { + wait 0.1; + origin = self.origin; + point = origin; + i = 1; + while ( i < 5 ) + { + point = origin + ( anglesToForward( self.door.angles ) * ( i * 2 ) ); + passed = bullettracepassed( point, origin, 0, undefined ); + color = vectorScale( ( 1, 0, 0 ), 255 ); + if ( !passed ) + { + color = vectorScale( ( 1, 0, 0 ), 255 ); + } +/# + print3d( point, "+", color, 1, 1 ); +#/ + i++; + } + } +} + +hack_doors( targetname, door_activate_func ) +{ + if ( !isDefined( targetname ) ) + { + targetname = "zombie_door"; + } + doors = getentarray( targetname, "targetname" ); + if ( !isDefined( door_activate_func ) ) + { + door_activate_func = ::maps/mp/zombies/_zm_blockers::door_opened; + } + i = 0; + while ( i < doors.size ) + { + door = doors[ i ]; + struct = spawnstruct(); + struct.origin = door.origin + ( anglesToForward( door.angles ) * 2 ); + struct.radius = 48; + struct.height = 72; + struct.script_float = 32.7; + struct.script_int = 200; + struct.door = door; + struct.no_bullet_trace = 1; + struct.door_activate_func = door_activate_func; + trace_passed = 0; + door thread hide_door_buy_when_hacker_active( struct ); + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( struct, ::door_hack ); + door thread watch_door_for_open( struct ); + i++; + } +} + +hide_door_buy_when_hacker_active( door_struct ) +{ + self endon( "death" ); + self endon( "door_hacked" ); + self endon( "door_opened" ); + maps/mp/zombies/_zm_equip_hacker::hide_hint_when_hackers_active(); +} + +watch_door_for_open( door_struct ) +{ + self waittill( "door_opened" ); + self endon( "door_hacked" ); + remove_all_door_hackables_that_target_door( door_struct.door ); +} + +door_hack( hacker ) +{ + self.door notify( "door_hacked" ); + self.door notify( "kill_door_think" ); + remove_all_door_hackables_that_target_door( self.door ); + self.door [[ self.door_activate_func ]](); + self.door._door_open = 1; +} + +remove_all_door_hackables_that_target_door( door ) +{ + candidates = []; + i = 0; + while ( i < level._hackable_objects.size ) + { + obj = level._hackable_objects[ i ]; + if ( isDefined( obj.door ) && obj.door.target == door.target ) + { + candidates[ candidates.size ] = obj; + } + i++; + } + i = 0; + while ( i < candidates.size ) + { + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( candidates[ i ] ); + i++; + } +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_packapunch.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_packapunch.gsc new file mode 100644 index 0000000..c9fba2a --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_packapunch.gsc @@ -0,0 +1,46 @@ +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +hack_packapunch() +{ + vending_weapon_upgrade_trigger = getentarray( "specialty_weapupgrade", "script_noteworthy" ); + perk = getent( vending_weapon_upgrade_trigger[ 0 ].target, "targetname" ); + if ( isDefined( perk ) ) + { + struct = spawnstruct(); + struct.origin = perk.origin + ( anglesToRight( perk.angles ) * 26 ) + vectorScale( ( 0, 0, 1 ), 48 ); + struct.radius = 48; + struct.height = 48; + struct.script_float = 5; + struct.script_int = -1000; + level._pack_hack_struct = struct; + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( level._pack_hack_struct, ::packapunch_hack ); + level._pack_hack_struct pack_trigger_think(); + } +} + +pack_trigger_think() +{ + if ( !flag_exists( "enter_nml" ) ) + { + return; + } + while ( 1 ) + { + flag_wait( "enter_nml" ); + self.script_int = -1000; + while ( flag( "enter_nml" ) ) + { + wait 1; + } + } +} + +packapunch_hack( hacker ) +{ + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( level._pack_hack_struct ); + level._pack_hack_struct.script_int = 0; + level notify( "packapunch_hacked" ); +} diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_perks.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_perks.gsc new file mode 100644 index 0000000..18cd74b --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_perks.gsc @@ -0,0 +1,87 @@ +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +hack_perks() +{ + vending_triggers = getentarray( "zombie_vending", "targetname" ); + i = 0; + while ( i < vending_triggers.size ) + { + struct = spawnstruct(); + if ( isDefined( vending_triggers[ i ].machine ) ) + { + machine[ 0 ] = vending_triggers[ i ].machine; + } + else + { + machine = getentarray( vending_triggers[ i ].target, "targetname" ); + } + struct.origin = machine[ 0 ].origin + ( anglesToRight( machine[ 0 ].angles ) * 18 ) + vectorScale( ( 0, 0, 1 ), 48 ); + struct.radius = 48; + struct.height = 64; + struct.script_float = 5; + while ( !isDefined( vending_triggers[ i ].cost ) ) + { + wait 0.05; + } + struct.script_int = int( vending_triggers[ i ].cost * -1 ); + struct.perk = vending_triggers[ i ]; + if ( isDefined( level._hack_perks_override ) ) + { + struct = struct [[ level._hack_perks_override ]](); + } + vending_triggers[ i ].hackable = struct; + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( struct, ::perk_hack, ::perk_hack_qualifier ); + i++; + } + level._solo_revive_machine_expire_func = ::solo_revive_expire_func; +} + +solo_revive_expire_func() +{ + if ( isDefined( self.hackable ) ) + { + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( self.hackable ); + self.hackable = undefined; + } +} + +perk_hack_qualifier( player ) +{ + if ( isDefined( player._retain_perks ) ) + { + return 0; + } + if ( isDefined( self.perk ) && isDefined( self.perk.script_noteworthy ) ) + { + if ( player hasperk( self.perk.script_noteworthy ) ) + { + return 1; + } + } + return 0; +} + +perk_hack( hacker ) +{ + if ( flag( "solo_game" ) && self.perk.script_noteworthy == "specialty_quickrevive" ) + { + hacker.lives--; + + } + hacker notify( self.perk.script_noteworthy + "_stop" ); + hacker playsoundtoplayer( "evt_perk_throwup", hacker ); + while ( isDefined( hacker.perk_hud ) ) + { + keys = getarraykeys( hacker.perk_hud ); + i = 0; + while ( i < hacker.perk_hud.size ) + { + hacker.perk_hud[ keys[ i ] ].x = i * 30; + i++; + } + } +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_powerups.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_powerups.gsc new file mode 100644 index 0000000..318339f --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_powerups.gsc @@ -0,0 +1,79 @@ +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +unhackable_powerup( name ) +{ + ret = 0; + switch( name ) + { + case "bonus_points_player": + case "bonus_points_team": + case "lose_points_team": + case "random_weapon": + ret = 1; + break; + } + return ret; +} + +hack_powerups() +{ + while ( 1 ) + { + level waittill( "powerup_dropped", powerup ); + if ( !unhackable_powerup( powerup.powerup_name ) ) + { + struct = spawnstruct(); + struct.origin = powerup.origin; + struct.radius = 65; + struct.height = 72; + struct.script_float = 5; + struct.script_int = 5000; + struct.powerup = powerup; + powerup thread powerup_pickup_watcher( struct ); + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( struct, ::powerup_hack ); + } + } +} + +powerup_pickup_watcher( powerup_struct ) +{ + self endon( "hacked" ); + self waittill( "death" ); + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( powerup_struct ); +} + +powerup_hack( hacker ) +{ + self.powerup notify( "hacked" ); + if ( isDefined( self.powerup.zombie_grabbable ) && self.powerup.zombie_grabbable ) + { + self.powerup notify( "powerup_timedout" ); + origin = self.powerup.origin; + self.powerup delete(); + self.powerup = maps/mp/zombies/_zm_net::network_safe_spawn( "powerup", 1, "script_model", origin ); + if ( isDefined( self.powerup ) ) + { + self.powerup maps/mp/zombies/_zm_powerups::powerup_setup( "full_ammo" ); + self.powerup thread maps/mp/zombies/_zm_powerups::powerup_timeout(); + self.powerup thread maps/mp/zombies/_zm_powerups::powerup_wobble(); + self.powerup thread maps/mp/zombies/_zm_powerups::powerup_grab(); + } + } + else + { + if ( self.powerup.powerup_name == "full_ammo" ) + { + self.powerup maps/mp/zombies/_zm_powerups::powerup_setup( "fire_sale" ); + } + else + { + self.powerup maps/mp/zombies/_zm_powerups::powerup_setup( "full_ammo" ); + } + } + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( self ); +} diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_wallbuys.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_wallbuys.gsc new file mode 100644 index 0000000..950a1a5 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_hackables_wallbuys.gsc @@ -0,0 +1,55 @@ +#include maps/mp/zombies/_zm_equip_hacker; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +hack_wallbuys() +{ + weapon_spawns = getstructarray( "weapon_upgrade", "targetname" ); + i = 0; + while ( i < weapon_spawns.size ) + { + if ( weapontype( weapon_spawns[ i ].zombie_weapon_upgrade ) == "grenade" ) + { + i++; + continue; + } + else if ( weapontype( weapon_spawns[ i ].zombie_weapon_upgrade ) == "melee" ) + { + i++; + continue; + } + else if ( weapontype( weapon_spawns[ i ].zombie_weapon_upgrade ) == "mine" ) + { + i++; + continue; + } + else if ( weapontype( weapon_spawns[ i ].zombie_weapon_upgrade ) == "bomb" ) + { + i++; + continue; + } + else + { + struct = spawnstruct(); + struct.origin = weapon_spawns[ i ].origin; + struct.radius = 48; + struct.height = 48; + struct.script_float = 2; + struct.script_int = 3000; + struct.wallbuy = weapon_spawns[ i ]; + maps/mp/zombies/_zm_equip_hacker::register_pooled_hackable_struct( struct, ::wallbuy_hack ); + } + i++; + } + bowie_triggers = getentarray( "bowie_upgrade", "targetname" ); + array_thread( bowie_triggers, ::maps/mp/zombies/_zm_equip_hacker::hide_hint_when_hackers_active ); +} + +wallbuy_hack( hacker ) +{ + self.wallbuy.hacked = 1; + self.clientfieldname = ( self.wallbuy.zombie_weapon_upgrade + "_" ) + self.origin; + level setclientfield( self.clientfieldname, 2 ); + maps/mp/zombies/_zm_equip_hacker::deregister_hackable_struct( self ); +} diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perk_upgrades.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perk_upgrades.gsc new file mode 100644 index 0000000..51249f7 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perk_upgrades.gsc @@ -0,0 +1,685 @@ +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_pers_upgrades; +#include maps/mp/zombies/_zm_pers_upgrades_system; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +pers_upgrade_init() +{ + setup_pers_upgrade_boards(); + setup_pers_upgrade_revive(); + setup_pers_upgrade_multi_kill_headshots(); + setup_pers_upgrade_cash_back(); + setup_pers_upgrade_insta_kill(); + setup_pers_upgrade_jugg(); + setup_pers_upgrade_carpenter(); + setup_pers_upgrade_flopper(); + setup_pers_upgrade_perk_lose(); + setup_pers_upgrade_pistol_points(); + setup_pers_upgrade_double_points(); + setup_pers_upgrade_sniper(); + setup_pers_upgrade_box_weapon(); + setup_pers_upgrade_nube(); + level thread pers_upgrades_monitor(); +} + +pers_abilities_init_globals() +{ + self.successful_revives = 0; + self.failed_revives = 0; + self.failed_cash_back_prones = 0; + self.pers[ "last_headshot_kill_time" ] = getTime(); + self.pers[ "zombies_multikilled" ] = 0; + self.non_headshot_kill_counter = 0; + if ( isDefined( level.pers_upgrade_box_weapon ) && level.pers_upgrade_box_weapon ) + { + self.pers_box_weapon_awarded = undefined; + } + if ( isDefined( level.pers_upgrade_nube ) && level.pers_upgrade_nube ) + { + self thread pers_nube_unlock_watcher(); + } +} + +is_pers_system_active() +{ + if ( !is_classic() ) + { + return 0; + } + if ( is_pers_system_disabled() ) + { + return 0; + } + return 1; +} + +is_pers_system_disabled() +{ + if ( level flag_exists( "sq_minigame_active" ) && flag( "sq_minigame_active" ) ) + { + return 1; + } + return 0; +} + +setup_pers_upgrade_boards() +{ + if ( isDefined( level.pers_upgrade_boards ) && level.pers_upgrade_boards ) + { + level.pers_boarding_round_start = 10; + level.pers_boarding_number_of_boards_required = 74; + pers_register_upgrade( "board", ::pers_upgrade_boards_active, "pers_boarding", level.pers_boarding_number_of_boards_required, 0 ); + } +} + +setup_pers_upgrade_revive() +{ + if ( isDefined( level.pers_upgrade_revive ) && level.pers_upgrade_revive ) + { + level.pers_revivenoperk_number_of_revives_required = 17; + level.pers_revivenoperk_number_of_chances_to_keep = 1; + pers_register_upgrade( "revive", ::pers_upgrade_revive_active, "pers_revivenoperk", level.pers_revivenoperk_number_of_revives_required, 1 ); + } +} + +setup_pers_upgrade_multi_kill_headshots() +{ + if ( isDefined( level.pers_upgrade_multi_kill_headshots ) && level.pers_upgrade_multi_kill_headshots ) + { + level.pers_multikill_headshots_required = 5; + level.pers_multikill_headshots_upgrade_reset_counter = 25; + pers_register_upgrade( "multikill_headshots", ::pers_upgrade_headshot_active, "pers_multikill_headshots", level.pers_multikill_headshots_required, 0 ); + } +} + +setup_pers_upgrade_cash_back() +{ + if ( isDefined( level.pers_upgrade_cash_back ) && level.pers_upgrade_cash_back ) + { + level.pers_cash_back_num_perks_required = 50; + level.pers_cash_back_perk_buys_prone_required = 15; + level.pers_cash_back_failed_prones = 1; + level.pers_cash_back_money_reward = 1000; + pers_register_upgrade( "cash_back", ::pers_upgrade_cash_back_active, "pers_cash_back_bought", level.pers_cash_back_num_perks_required, 0 ); + add_pers_upgrade_stat( "cash_back", "pers_cash_back_prone", level.pers_cash_back_perk_buys_prone_required ); + } +} + +setup_pers_upgrade_insta_kill() +{ + if ( isDefined( level.pers_upgrade_insta_kill ) && level.pers_upgrade_insta_kill ) + { + level.pers_insta_kill_num_required = 2; + level.pers_insta_kill_upgrade_active_time = 18; + pers_register_upgrade( "insta_kill", ::pers_upgrade_insta_kill_active, "pers_insta_kill", level.pers_insta_kill_num_required, 0 ); + } +} + +setup_pers_upgrade_jugg() +{ + if ( isDefined( level.pers_upgrade_jugg ) && level.pers_upgrade_jugg ) + { + level.pers_jugg_hit_and_die_total = 3; + level.pers_jugg_hit_and_die_round_limit = 2; + level.pers_jugg_round_reached_max = 1; + level.pers_jugg_round_lose_target = 15; + level.pers_jugg_upgrade_health_bonus = 90; + pers_register_upgrade( "jugg", ::pers_upgrade_jugg_active, "pers_jugg", level.pers_jugg_hit_and_die_total, 0 ); + } +} + +setup_pers_upgrade_carpenter() +{ + if ( isDefined( level.pers_upgrade_carpenter ) && level.pers_upgrade_carpenter ) + { + level.pers_carpenter_zombie_kills = 1; + pers_register_upgrade( "carpenter", ::pers_upgrade_carpenter_active, "pers_carpenter", level.pers_carpenter_zombie_kills, 0 ); + } +} + +setup_pers_upgrade_flopper() +{ + if ( isDefined( level.pers_upgrade_flopper ) && level.pers_upgrade_flopper ) + { + level.pers_flopper_damage_counter = 6; + level.pers_flopper_counter = 1; + level.pers_flopper_min_fall_damage_activate = 30; + level.pers_flopper_min_fall_damage_deactivate = 50; + pers_register_upgrade( "flopper", ::pers_upgrade_flopper_active, "pers_flopper_counter", level.pers_flopper_counter, 0 ); + } +} + +setup_pers_upgrade_perk_lose() +{ + if ( isDefined( level.pers_upgrade_perk_lose ) && level.pers_upgrade_perk_lose ) + { + level.pers_perk_round_reached_max = 6; + level.pers_perk_lose_counter = 3; + pers_register_upgrade( "perk_lose", ::pers_upgrade_perk_lose_active, "pers_perk_lose_counter", level.pers_perk_lose_counter, 0 ); + } +} + +setup_pers_upgrade_pistol_points() +{ + if ( isDefined( level.pers_upgrade_pistol_points ) && level.pers_upgrade_pistol_points ) + { + level.pers_pistol_points_num_kills_in_game = 8; + level.pers_pistol_points_accuracy = 0.25; + level.pers_pistol_points_counter = 1; + pers_register_upgrade( "pistol_points", ::pers_upgrade_pistol_points_active, "pers_pistol_points_counter", level.pers_pistol_points_counter, 0 ); + } +} + +setup_pers_upgrade_double_points() +{ + if ( isDefined( level.pers_upgrade_double_points ) && level.pers_upgrade_double_points ) + { + level.pers_double_points_score = 2500; + level.pers_double_points_counter = 1; + pers_register_upgrade( "double_points", ::pers_upgrade_double_points_active, "pers_double_points_counter", level.pers_double_points_counter, 0 ); + } +} + +setup_pers_upgrade_sniper() +{ + if ( isDefined( level.pers_upgrade_sniper ) && level.pers_upgrade_sniper ) + { + level.pers_sniper_round_kills_counter = 5; + level.pers_sniper_kill_distance = 800; + level.pers_sniper_counter = 1; + level.pers_sniper_misses = 3; + pers_register_upgrade( "sniper", ::pers_upgrade_sniper_active, "pers_sniper_counter", level.pers_sniper_counter, 0 ); + } +} + +setup_pers_upgrade_box_weapon() +{ + if ( isDefined( level.pers_upgrade_box_weapon ) && level.pers_upgrade_box_weapon ) + { + level.pers_box_weapon_counter = 5; + level.pers_box_weapon_lose_round = 10; + pers_register_upgrade( "box_weapon", ::pers_upgrade_box_weapon_active, "pers_box_weapon_counter", level.pers_box_weapon_counter, 0 ); + } +} + +setup_pers_upgrade_nube() +{ + if ( isDefined( level.pers_upgrade_nube ) && level.pers_upgrade_nube ) + { + level.pers_nube_counter = 1; + level.pers_nube_lose_round = 10; + level.pers_numb_num_kills_unlock = 5; + pers_register_upgrade( "nube", ::pers_upgrade_nube_active, "pers_nube_counter", level.pers_nube_counter, 0 ); + } +} + +pers_upgrade_boards_active() +{ + self endon( "disconnect" ); + last_round_number = level.round_number; + while ( 1 ) + { + self waittill( "pers_stats_end_of_round" ); + if ( level.round_number >= last_round_number ) + { + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( self.rebuild_barrier_reward == 0 ) + { + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_boarding", 0 ); + return; + } + } + } + last_round_number = level.round_number; + } +} + +pers_upgrade_revive_active() +{ + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "player_failed_revive" ); + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( self.failed_revives >= level.pers_revivenoperk_number_of_chances_to_keep ) + { + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_revivenoperk", 0 ); + self.failed_revives = 0; + return; + } + } + } +} + +pers_upgrade_headshot_active() +{ + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "zombie_death_no_headshot" ); + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + self.non_headshot_kill_counter++; + if ( self.non_headshot_kill_counter >= level.pers_multikill_headshots_upgrade_reset_counter ) + { + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_multikill_headshots", 0 ); + self.non_headshot_kill_counter = 0; + return; + } + } + } +} + +pers_upgrade_cash_back_active() +{ + self endon( "disconnect" ); + wait 0.5; + + wait 0.5; + while ( 1 ) + { + self waittill( "cash_back_failed_prone" ); + wait 0.1; + + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + self.failed_cash_back_prones++; + if ( self.failed_cash_back_prones >= level.pers_cash_back_failed_prones ) + { + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_cash_back_bought", 0 ); + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_cash_back_prone", 0 ); + self.failed_cash_back_prones = 0; + wait 0.4; + + return; + } + } + } +} + +pers_upgrade_insta_kill_active() +{ + self endon( "disconnect" ); + wait 0.2; + + wait 0.2; + while ( 1 ) + { + self waittill( "pers_melee_swipe" ); + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( level.pers_melee_swipe_zombie_swiper ) ) + { + e_zombie = level.pers_melee_swipe_zombie_swiper; + if ( isalive( e_zombie ) && isDefined( e_zombie.is_zombie ) && e_zombie.is_zombie ) + { + e_zombie.marked_for_insta_upgraded_death = 1; + e_zombie dodamage( e_zombie.health + 666, e_zombie.origin, self, self, "none", "MOD_PISTOL_BULLET", 0, "knife_zm" ); + } + level.pers_melee_swipe_zombie_swiper = undefined; + } + break; + } + else + { + } + } + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_insta_kill", 0 ); + self kill_insta_kill_upgrade_hud_icon(); + wait 0.4; +} + +is_insta_kill_upgraded_and_active() +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( self maps/mp/zombies/_zm_powerups::is_insta_kill_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "insta_kill" ] ) && self.pers_upgrades_awarded[ "insta_kill" ] ) + { + return 1; + } + } + } + return 0; +} + +pers_upgrade_jugg_active() +{ + self endon( "disconnect" ); + wait 0.5; + + wait 0.5; + self maps/mp/zombies/_zm_perks::perk_set_max_health_if_jugg( "jugg_upgrade", 1, 0 ); + while ( 1 ) + { + level waittill( "start_of_round" ); + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( level.round_number == level.pers_jugg_round_lose_target ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_jugg_downgrade_count", 0 ); + wait 0.5; + if ( self.pers[ "pers_jugg_downgrade_count" ] >= level.pers_jugg_round_reached_max ) + { + break; + } + } + } + else + { + } + } + self maps/mp/zombies/_zm_perks::perk_set_max_health_if_jugg( "jugg_upgrade", 1, 1 ); + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_jugg", 0 ); + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_jugg_downgrade_count", 0 ); +} + +pers_upgrade_carpenter_active() +{ + self endon( "disconnect" ); + wait 0.2; + + wait 0.2; + level waittill( "carpenter_finished" ); + self.pers_carpenter_kill = undefined; + while ( 1 ) + { + self waittill( "carpenter_zombie_killed_check_finished" ); + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( !isDefined( self.pers_carpenter_kill ) ) + { + break; + } + else + { + + } + self.pers_carpenter_kill = undefined; + } + } + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_carpenter", 0 ); + wait 0.4; +} + +persistent_carpenter_ability_check() +{ + if ( isDefined( level.pers_upgrade_carpenter ) && level.pers_upgrade_carpenter ) + { + self endon( "disconnect" ); + + if ( isDefined( self.pers_upgrades_awarded[ "carpenter" ] ) && self.pers_upgrades_awarded[ "carpenter" ] ) + { + level.pers_carpenter_boards_active = 1; + } + self.pers_carpenter_zombie_check_active = 1; + self.pers_carpenter_kill = undefined; + carpenter_extra_time = 3; + carpenter_finished_start_time = undefined; + level.carpenter_finished_start_time = undefined; + while ( 1 ) + { + if ( !is_pers_system_disabled() ) + { + if ( !isDefined( level.carpenter_powerup_active ) ) + { + if ( !isDefined( level.carpenter_finished_start_time ) ) + { + level.carpenter_finished_start_time = getTime(); + } + time = getTime(); + dt = ( time - level.carpenter_finished_start_time ) / 1000; + if ( dt >= carpenter_extra_time ) + { + break; + } + } + else if ( isDefined( self.pers_carpenter_kill ) ) + { + if ( isDefined( self.pers_upgrades_awarded[ "carpenter" ] ) && self.pers_upgrades_awarded[ "carpenter" ] ) + { + break; + } + else self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_carpenter", 0 ); + } + } + wait 0.05; + } + self notify( "carpenter_zombie_killed_check_finished" ); + self.pers_carpenter_zombie_check_active = undefined; + level.pers_carpenter_boards_active = undefined; + } +} + +pers_zombie_death_location_check( attacker, v_pos ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( is_player_valid( attacker ) ) + { + if ( isDefined( attacker.pers_carpenter_zombie_check_active ) ) + { + if ( !check_point_in_playable_area( v_pos ) ) + { + attacker.pers_carpenter_kill = 1; + } + } + } + } +} + +insta_kill_pers_upgrade_icon() +{ + if ( self.zombie_vars[ "zombie_powerup_insta_kill_ug_on" ] ) + { + self.zombie_vars[ "zombie_powerup_insta_kill_ug_time" ] = level.pers_insta_kill_upgrade_active_time; + return; + } + self.zombie_vars[ "zombie_powerup_insta_kill_ug_on" ] = 1; + self._show_solo_hud = 1; + self thread time_remaining_pers_upgrade(); +} + +time_remaining_pers_upgrade() +{ + self endon( "disconnect" ); + self endon( "kill_insta_kill_upgrade_hud_icon" ); + while ( self.zombie_vars[ "zombie_powerup_insta_kill_ug_time" ] >= 0 ) + { + wait 0.05; + self.zombie_vars[ "zombie_powerup_insta_kill_ug_time" ] -= 0.05; + } + self kill_insta_kill_upgrade_hud_icon(); +} + +kill_insta_kill_upgrade_hud_icon() +{ + self.zombie_vars[ "zombie_powerup_insta_kill_ug_on" ] = 0; + self._show_solo_hud = 0; + self.zombie_vars[ "zombie_powerup_insta_kill_ug_time" ] = level.pers_insta_kill_upgrade_active_time; + self notify( "kill_insta_kill_upgrade_hud_icon" ); +} + +pers_upgrade_flopper_active() +{ + self endon( "disconnect" ); + wait 0.5; + /* +/# + iprintlnbold( "*** WE'VE GOT FLOPPER UPGRADED ***" ); +#/ + */ + wait 0.5; + self thread maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_flopper_watcher(); + self waittill( "pers_flopper_lost" ); + /* +/# + iprintlnbold( "*** OH NO: Lost FLOPPER Upgrade ***" ); +#/ + */ + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_flopper_counter", 0 ); + self.pers_num_flopper_damages = 0; +} + +pers_upgrade_perk_lose_active() +{ + self endon( "disconnect" ); + wait 0.5; + /* +/# + iprintlnbold( "*** WE'VE GOT PERK LOSE UPGRADED ***" ); +#/ + */ + wait 0.5; + self.pers_perk_lose_start_round = level.round_number; + self waittill( "pers_perk_lose_lost" ); + /* +/# + iprintlnbold( "*** OH NO: Lost PERK LOSE Upgrade ***" ); +#/ + */ + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_perk_lose_counter", 0 ); +} + +pers_upgrade_pistol_points_active() +{ + self endon( "disconnect" ); + wait 0.5; + /* +/# + iprintlnbold( "*** WE'VE GOT PISTOL POINTS UPGRADED ***" ); +#/ + */ + wait 0.5; + while ( 1 ) + { + self waittill( "pers_pistol_points_kill" ); + accuracy = self maps/mp/zombies/_zm_pers_upgrades_functions::pers_get_player_accuracy(); + if ( accuracy > level.pers_pistol_points_accuracy ) + { + break; + } + else + { + } + } + /* +/# + iprintlnbold( "*** OH NO: Lost PISTOL POINTS Upgrade ***" ); +#/ + */ + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_pistol_points_counter", 0 ); +} + +pers_upgrade_double_points_active() +{ + self endon( "disconnect" ); + wait 0.5; + /* +/# + iprintlnbold( "*** WE'VE GOT DOUBLE POINTS UPGRADED ***" ); +#/ + */ + wait 0.5; + self waittill( "double_points_lost" ); + /* +/# + iprintlnbold( "*** OH NO: Lost DOUBLE POINTS Upgrade ***" ); +#/ + */ + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_double_points_counter", 0 ); +} + +pers_upgrade_sniper_active() +{ + self endon( "disconnect" ); + wait 0.5; + /* +/# + iprintlnbold( "*** WE'VE GOT SNIPER UPGRADED ***" ); +#/ + */ + wait 0.5; + self waittill( "pers_sniper_lost" ); + /* +/# + iprintlnbold( "*** OH NO: Lost SNIPER Upgrade ***" ); +#/ + */ + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_sniper_counter", 0 ); +} + +pers_upgrade_box_weapon_active() +{ + self endon( "disconnect" ); + wait 0.5; + /* +/# + iprintlnbold( "*** WE'VE GOT BOX WEAPON UPGRADED ***" ); +#/ + */ + self thread maps/mp/zombies/_zm_pers_upgrades_functions::pers_magic_box_teddy_bear(); + wait 0.5; + self.pers_box_weapon_awarded = 1; + while ( 1 ) + { + level waittill( "start_of_round" ); + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( level.round_number >= level.pers_box_weapon_lose_round ) + { + break; + } + } + else + { + } + } + /* +/# + iprintlnbold( "*** OH NO: Lost BOX WEAPON Upgrade ***" ); +#/ + */ + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_box_weapon_counter", 0 ); +} + +pers_upgrade_nube_active() +{ + self endon( "disconnect" ); + wait 0.5; + /* +/# + iprintlnbold( "*** WE'VE GOT NUBE UPGRADED ***" ); +#/ + */ + wait 0.5; + while ( 1 ) + { + level waittill( "start_of_round" ); + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( level.round_number >= level.pers_nube_lose_round ) + { + break; + } + } + else + { + } + } + /* +/# + iprintlnbold( "*** OH NO: Lost NUBE Upgrade ***" ); +#/ + */ + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_nube_counter", 0 ); +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perks.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perks.gsc new file mode 100644 index 0000000..5b846fc --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_perks.gsc @@ -0,0 +1,4165 @@ +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_power; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; +#include maps/mp/zombies/_zm_magicbox; + +init() +{ + level.additionalprimaryweapon_limit = 3; + level.perk_purchase_limit = 4; + if ( !level.createfx_enabled ) + { + perks_register_clientfield(); + } + if ( !level.enable_magic ) + { + return; + } + if ( getDvarIntDefault( "_zm_perks_return_early", "0" ) == "1" ) + { + return; + } + initialize_custom_perk_arrays(); + perk_machine_spawn_init(); + vending_weapon_upgrade_trigger = []; + vending_triggers = getentarray( "zombie_vending", "targetname" ); + i = 0; + while ( i < vending_triggers.size ) + { + if ( isDefined( vending_triggers[ i ].script_noteworthy ) && vending_triggers[ i ].script_noteworthy == "specialty_weapupgrade" ) + { + vending_weapon_upgrade_trigger[ vending_weapon_upgrade_trigger.size ] = vending_triggers[ i ]; + arrayremovevalue( vending_triggers, vending_triggers[ i ] ); + } + i++; + } + old_packs = getentarray( "zombie_vending_upgrade", "targetname" ); + i = 0; + while ( i < old_packs.size ) + { + vending_weapon_upgrade_trigger[ vending_weapon_upgrade_trigger.size ] = old_packs[ i ]; + i++; + } + flag_init( "pack_machine_in_use" ); + if ( vending_triggers.size < 1 ) + { + return; + } + if ( vending_weapon_upgrade_trigger.size >= 1 ) + { + array_thread( vending_weapon_upgrade_trigger, ::vending_weapon_upgrade ); + } + level.machine_assets = []; + if ( !isDefined( level.custom_vending_precaching ) ) + { + level.custom_vending_precaching = ::default_vending_precaching; + } + [[ level.custom_vending_precaching ]](); + if ( !isDefined( level.packapunch_timeout ) ) + { + level.packapunch_timeout = 15; + } + set_zombie_var( "zombie_perk_cost", 2000 ); + set_zombie_var( "zombie_perk_juggernaut_health", 160 ); + set_zombie_var( "zombie_perk_juggernaut_health_upgrade", 190 ); + array_thread( vending_triggers, ::vending_trigger_think ); + array_thread( vending_triggers, ::electric_perks_dialog ); + if ( isDefined( level.zombiemode_using_doubletap_perk ) && level.zombiemode_using_doubletap_perk ) + { + level thread turn_doubletap_on(); + } + if ( isDefined( level.zombiemode_using_marathon_perk ) && level.zombiemode_using_marathon_perk ) + { + level thread turn_marathon_on(); + } + if ( isDefined( level.zombiemode_using_juggernaut_perk ) && level.zombiemode_using_juggernaut_perk ) + { + level thread turn_jugger_on(); + } + if ( isDefined( level.zombiemode_using_revive_perk ) && level.zombiemode_using_revive_perk ) + { + level thread turn_revive_on(); + } + if ( isDefined( level.zombiemode_using_sleightofhand_perk ) && level.zombiemode_using_sleightofhand_perk ) + { + level thread turn_sleight_on(); + } + if ( isDefined( level.zombiemode_using_deadshot_perk ) && level.zombiemode_using_deadshot_perk ) + { + level thread turn_deadshot_on(); + } + if ( isDefined( level.zombiemode_using_tombstone_perk ) && level.zombiemode_using_tombstone_perk ) + { + level thread turn_tombstone_on(); + } + if ( isDefined( level.zombiemode_using_additionalprimaryweapon_perk ) && level.zombiemode_using_additionalprimaryweapon_perk ) + { + level thread turn_additionalprimaryweapon_on(); + } + if ( isDefined( level.zombiemode_using_chugabud_perk ) && level.zombiemode_using_chugabud_perk ) + { + level thread turn_chugabud_on(); + } + while ( level._custom_perks.size > 0 ) + { + a_keys = getarraykeys( level._custom_perks ); + i = 0; + while ( i < a_keys.size ) + { + if ( isDefined( level._custom_perks[ a_keys[ i ] ].perk_machine_thread ) ) + { + level thread [[ level._custom_perks[ a_keys[ i ] ].perk_machine_thread ]](); + } + i++; + } + } + if ( isDefined( level._custom_turn_packapunch_on ) ) + { + level thread [[ level._custom_turn_packapunch_on ]](); + } + else + { + level thread turn_packapunch_on(); + } + if ( isDefined( level.quantum_bomb_register_result_func ) ) + { + [[ level.quantum_bomb_register_result_func ]]( "give_nearest_perk", ::quantum_bomb_give_nearest_perk_result, 10, ::quantum_bomb_give_nearest_perk_validation ); + } + level thread perk_hostmigration(); +} + +default_vending_precaching() +{ + if ( isDefined( level.zombiemode_using_pack_a_punch ) && level.zombiemode_using_pack_a_punch ) + { + precacheitem( "zombie_knuckle_crack" ); + precachemodel( "p6_anim_zm_buildable_pap" ); + precachemodel( "p6_anim_zm_buildable_pap_on" ); + precachestring( &"ZOMBIE_PERK_PACKAPUNCH" ); + precachestring( &"ZOMBIE_PERK_PACKAPUNCH_ATT" ); + level._effect[ "packapunch_fx" ] = loadfx( "maps/zombie/fx_zombie_packapunch" ); + level.machine_assets[ "packapunch" ] = spawnstruct(); + level.machine_assets[ "packapunch" ].weapon = "zombie_knuckle_crack"; + level.machine_assets[ "packapunch" ].off_model = "p6_anim_zm_buildable_pap"; + level.machine_assets[ "packapunch" ].on_model = "p6_anim_zm_buildable_pap_on"; + } + if ( isDefined( level.zombiemode_using_additionalprimaryweapon_perk ) && level.zombiemode_using_additionalprimaryweapon_perk ) + { + precacheitem( "zombie_perk_bottle_additionalprimaryweapon" ); + precacheshader( "specialty_additionalprimaryweapon_zombies" ); + precachemodel( "zombie_vending_three_gun" ); + precachemodel( "zombie_vending_three_gun_on" ); + precachestring( &"ZOMBIE_PERK_ADDITIONALWEAPONPERK" ); + level._effect[ "additionalprimaryweapon_light" ] = loadfx( "misc/fx_zombie_cola_arsenal_on" ); + level.machine_assets[ "additionalprimaryweapon" ] = spawnstruct(); + level.machine_assets[ "additionalprimaryweapon" ].weapon = "zombie_perk_bottle_additionalprimaryweapon"; + level.machine_assets[ "additionalprimaryweapon" ].off_model = "zombie_vending_three_gun"; + level.machine_assets[ "additionalprimaryweapon" ].on_model = "zombie_vending_three_gun_on"; + } + if ( isDefined( level.zombiemode_using_deadshot_perk ) && level.zombiemode_using_deadshot_perk ) + { + precacheitem( "zombie_perk_bottle_deadshot" ); + precacheshader( "specialty_ads_zombies" ); + precachemodel( "zombie_vending_ads" ); + precachemodel( "zombie_vending_ads_on" ); + precachestring( &"ZOMBIE_PERK_DEADSHOT" ); + level._effect[ "deadshot_light" ] = loadfx( "misc/fx_zombie_cola_dtap_on" ); + level.machine_assets[ "deadshot" ] = spawnstruct(); + level.machine_assets[ "deadshot" ].weapon = "zombie_perk_bottle_deadshot"; + level.machine_assets[ "deadshot" ].off_model = "zombie_vending_ads"; + level.machine_assets[ "deadshot" ].on_model = "zombie_vending_ads_on"; + } + if ( isDefined( level.zombiemode_using_doubletap_perk ) && level.zombiemode_using_doubletap_perk ) + { + precacheitem( "zombie_perk_bottle_doubletap" ); + precacheshader( "specialty_doubletap_zombies" ); + precachemodel( "zombie_vending_doubletap2" ); + precachemodel( "zombie_vending_doubletap2_on" ); + precachestring( &"ZOMBIE_PERK_DOUBLETAP" ); + level._effect[ "doubletap_light" ] = loadfx( "misc/fx_zombie_cola_dtap_on" ); + level.machine_assets[ "doubletap" ] = spawnstruct(); + level.machine_assets[ "doubletap" ].weapon = "zombie_perk_bottle_doubletap"; + level.machine_assets[ "doubletap" ].off_model = "zombie_vending_doubletap2"; + level.machine_assets[ "doubletap" ].on_model = "zombie_vending_doubletap2_on"; + } + if ( isDefined( level.zombiemode_using_juggernaut_perk ) && level.zombiemode_using_juggernaut_perk ) + { + precacheitem( "zombie_perk_bottle_jugg" ); + precacheshader( "specialty_juggernaut_zombies" ); + precachemodel( "zombie_vending_jugg" ); + precachemodel( "zombie_vending_jugg_on" ); + precachestring( &"ZOMBIE_PERK_JUGGERNAUT" ); + level._effect[ "jugger_light" ] = loadfx( "misc/fx_zombie_cola_jugg_on" ); + level.machine_assets[ "juggernog" ] = spawnstruct(); + level.machine_assets[ "juggernog" ].weapon = "zombie_perk_bottle_jugg"; + level.machine_assets[ "juggernog" ].off_model = "zombie_vending_jugg"; + level.machine_assets[ "juggernog" ].on_model = "zombie_vending_jugg_on"; + } + if ( isDefined( level.zombiemode_using_marathon_perk ) && level.zombiemode_using_marathon_perk ) + { + precacheitem( "zombie_perk_bottle_marathon" ); + precacheshader( "specialty_marathon_zombies" ); + precachemodel( "zombie_vending_marathon" ); + precachemodel( "zombie_vending_marathon_on" ); + precachestring( &"ZOMBIE_PERK_MARATHON" ); + level._effect[ "marathon_light" ] = loadfx( "maps/zombie/fx_zmb_cola_staminup_on" ); + level.machine_assets[ "marathon" ] = spawnstruct(); + level.machine_assets[ "marathon" ].weapon = "zombie_perk_bottle_marathon"; + level.machine_assets[ "marathon" ].off_model = "zombie_vending_marathon"; + level.machine_assets[ "marathon" ].on_model = "zombie_vending_marathon_on"; + } + if ( isDefined( level.zombiemode_using_revive_perk ) && level.zombiemode_using_revive_perk ) + { + precacheitem( "zombie_perk_bottle_revive" ); + precacheshader( "specialty_quickrevive_zombies" ); + precachemodel( "zombie_vending_revive" ); + precachemodel( "zombie_vending_revive_on" ); + precachestring( &"ZOMBIE_PERK_QUICKREVIVE" ); + level._effect[ "revive_light" ] = loadfx( "misc/fx_zombie_cola_revive_on" ); + level._effect[ "revive_light_flicker" ] = loadfx( "maps/zombie/fx_zmb_cola_revive_flicker" ); + level.machine_assets[ "revive" ] = spawnstruct(); + level.machine_assets[ "revive" ].weapon = "zombie_perk_bottle_revive"; + level.machine_assets[ "revive" ].off_model = "zombie_vending_revive"; + level.machine_assets[ "revive" ].on_model = "zombie_vending_revive_on"; + } + if ( isDefined( level.zombiemode_using_sleightofhand_perk ) && level.zombiemode_using_sleightofhand_perk ) + { + precacheitem( "zombie_perk_bottle_sleight" ); + precacheshader( "specialty_fastreload_zombies" ); + precachemodel( "zombie_vending_sleight" ); + precachemodel( "zombie_vending_sleight_on" ); + precachestring( &"ZOMBIE_PERK_FASTRELOAD" ); + level._effect[ "sleight_light" ] = loadfx( "misc/fx_zombie_cola_on" ); + level.machine_assets[ "speedcola" ] = spawnstruct(); + level.machine_assets[ "speedcola" ].weapon = "zombie_perk_bottle_sleight"; + level.machine_assets[ "speedcola" ].off_model = "zombie_vending_sleight"; + level.machine_assets[ "speedcola" ].on_model = "zombie_vending_sleight_on"; + } + if ( isDefined( level.zombiemode_using_tombstone_perk ) && level.zombiemode_using_tombstone_perk ) + { + precacheitem( "zombie_perk_bottle_tombstone" ); + precacheshader( "specialty_tombstone_zombies" ); + precachemodel( "zombie_vending_tombstone" ); + precachemodel( "zombie_vending_tombstone_on" ); + precachemodel( "ch_tombstone1" ); + precachestring( &"ZOMBIE_PERK_TOMBSTONE" ); + level._effect[ "tombstone_light" ] = loadfx( "misc/fx_zombie_cola_on" ); + level.machine_assets[ "tombstone" ] = spawnstruct(); + level.machine_assets[ "tombstone" ].weapon = "zombie_perk_bottle_tombstone"; + level.machine_assets[ "tombstone" ].off_model = "zombie_vending_tombstone"; + level.machine_assets[ "tombstone" ].on_model = "zombie_vending_tombstone_on"; + } + if ( isDefined( level.zombiemode_using_chugabud_perk ) && level.zombiemode_using_chugabud_perk ) + { + precacheitem( "zombie_perk_bottle_whoswho" ); + precacheshader( "specialty_quickrevive_zombies" ); + precachemodel( "p6_zm_vending_chugabud" ); + precachemodel( "p6_zm_vending_chugabud_on" ); + precachemodel( "ch_tombstone1" ); + precachestring( &"ZOMBIE_PERK_TOMBSTONE" ); + level._effect[ "tombstone_light" ] = loadfx( "misc/fx_zombie_cola_on" ); + level.machine_assets[ "whoswho" ] = spawnstruct(); + level.machine_assets[ "whoswho" ].weapon = "zombie_perk_bottle_whoswho"; + level.machine_assets[ "whoswho" ].off_model = "p6_zm_vending_chugabud"; + level.machine_assets[ "whoswho" ].on_model = "p6_zm_vending_chugabud_on"; + } + while ( level._custom_perks.size > 0 ) + { + a_keys = getarraykeys( level._custom_perks ); + i = 0; + while ( i < a_keys.size ) + { + if ( isDefined( level._custom_perks[ a_keys[ i ] ].precache_func ) ) + { + level [[ level._custom_perks[ a_keys[ i ] ].precache_func ]](); + } + i++; + } + } +} + +pap_weapon_move_in( trigger, origin_offset, angles_offset ) +{ + level endon( "Pack_A_Punch_off" ); + trigger endon( "pap_player_disconnected" ); + trigger.worldgun rotateto( self.angles + angles_offset + vectorScale( ( 0, -1, 0 ), 90 ), 0.35, 0, 0 ); + offsetdw = vectorScale( ( 0, -1, 0 ), 3 ); + if ( isDefined( trigger.worldgun.worldgundw ) ) + { + trigger.worldgun.worldgundw rotateto( self.angles + angles_offset + vectorScale( ( 0, -1, 0 ), 90 ), 0.35, 0, 0 ); + } + wait 0.5; + trigger.worldgun moveto( self.origin + origin_offset, 0.5, 0, 0 ); + if ( isDefined( trigger.worldgun.worldgundw ) ) + { + trigger.worldgun.worldgundw moveto( self.origin + origin_offset + offsetdw, 0.5, 0, 0 ); + } +} + +pap_weapon_move_out( trigger, origin_offset, interact_offset ) +{ + level endon( "Pack_A_Punch_off" ); + trigger endon( "pap_player_disconnected" ); + offsetdw = vectorScale( ( 0, -1, 0 ), 3 ); + if ( !isDefined( trigger.worldgun ) ) + { + return; + } + trigger.worldgun moveto( self.origin + interact_offset, 0.5, 0, 0 ); + if ( isDefined( trigger.worldgun.worldgundw ) ) + { + trigger.worldgun.worldgundw moveto( self.origin + interact_offset + offsetdw, 0.5, 0, 0 ); + } + wait 0.5; + if ( !isDefined( trigger.worldgun ) ) + { + return; + } + trigger.worldgun moveto( self.origin + origin_offset, level.packapunch_timeout, 0, 0 ); + if ( isDefined( trigger.worldgun.worldgundw ) ) + { + trigger.worldgun.worldgundw moveto( self.origin + origin_offset + offsetdw, level.packapunch_timeout, 0, 0 ); + } +} + +fx_ent_failsafe() +{ + wait 25; + self delete(); +} + +third_person_weapon_upgrade( current_weapon, upgrade_weapon, packa_rollers, perk_machine, trigger ) +{ + level endon( "Pack_A_Punch_off" ); + trigger endon( "pap_player_disconnected" ); + rel_entity = trigger.perk_machine; + origin_offset = ( 0, -1, 0 ); + angles_offset = ( 0, -1, 0 ); + origin_base = self.origin; + angles_base = self.angles; + if ( isDefined( rel_entity ) ) + { + if ( isDefined( level.pap_interaction_height ) ) + { + origin_offset = ( 0, 0, level.pap_interaction_height ); + } + else + { + origin_offset = vectorScale( ( 0, -1, 0 ), 35 ); + } + angles_offset = vectorScale( ( 0, -1, 0 ), 90 ); + origin_base = rel_entity.origin; + angles_base = rel_entity.angles; + } + else + { + rel_entity = self; + } + forward = anglesToForward( angles_base + angles_offset ); + interact_offset = origin_offset + ( forward * -25 ); + if ( !isDefined( perk_machine.fx_ent ) ) + { + perk_machine.fx_ent = spawn( "script_model", origin_base + origin_offset + ( 0, 1, -34 ) ); + perk_machine.fx_ent.angles = angles_base + angles_offset; + perk_machine.fx_ent setmodel( "tag_origin" ); + perk_machine.fx_ent linkto( perk_machine ); + } + if ( isDefined( level._effect[ "packapunch_fx" ] ) ) + { + fx = playfxontag( level._effect[ "packapunch_fx" ], perk_machine.fx_ent, "tag_origin" ); + } + offsetdw = vectorScale( ( 0, -1, 0 ), 3 ); + weoptions = self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( current_weapon ); + trigger.worldgun = spawn_weapon_model( current_weapon, undefined, origin_base + interact_offset, self.angles, weoptions ); + worldgundw = undefined; + if ( maps/mp/zombies/_zm_magicbox::weapon_is_dual_wield( current_weapon ) ) + { + worldgundw = spawn_weapon_model( current_weapon, maps/mp/zombies/_zm_magicbox::get_left_hand_weapon_model_name( current_weapon ), origin_base + interact_offset + offsetdw, self.angles, weoptions ); + } + trigger.worldgun.worldgundw = worldgundw; + if ( isDefined( level.custom_pap_move_in ) ) + { + perk_machine [[ level.custom_pap_move_in ]]( trigger, origin_offset, angles_offset, perk_machine ); + } + else + { + perk_machine pap_weapon_move_in( trigger, origin_offset, angles_offset ); + } + self playsound( "zmb_perks_packa_upgrade" ); + if ( isDefined( perk_machine.wait_flag ) ) + { + perk_machine.wait_flag rotateto( perk_machine.wait_flag.angles + vectorScale( ( 0, -1, 0 ), 179 ), 0.25, 0, 0 ); + } + wait 0.35; + trigger.worldgun delete(); + if ( isDefined( worldgundw ) ) + { + worldgundw delete(); + } + wait 3; + if ( isDefined( self ) ) + { + self playsound( "zmb_perks_packa_ready" ); + } + else + { + return; + } + upoptions = self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( upgrade_weapon ); + trigger.current_weapon = current_weapon; + trigger.upgrade_name = upgrade_weapon; + trigger.worldgun = spawn_weapon_model( upgrade_weapon, undefined, origin_base + origin_offset, angles_base + angles_offset + vectorScale( ( 0, -1, 0 ), 90 ), upoptions ); + worldgundw = undefined; + if ( maps/mp/zombies/_zm_magicbox::weapon_is_dual_wield( upgrade_weapon ) ) + { + worldgundw = spawn_weapon_model( upgrade_weapon, maps/mp/zombies/_zm_magicbox::get_left_hand_weapon_model_name( upgrade_weapon ), origin_base + origin_offset + offsetdw, angles_base + angles_offset + vectorScale( ( 0, -1, 0 ), 90 ), upoptions ); + } + trigger.worldgun.worldgundw = worldgundw; + if ( isDefined( perk_machine.wait_flag ) ) + { + perk_machine.wait_flag rotateto( perk_machine.wait_flag.angles - vectorScale( ( 0, -1, 0 ), 179 ), 0.25, 0, 0 ); + } + if ( isDefined( level.custom_pap_move_out ) ) + { + rel_entity thread [[ level.custom_pap_move_out ]]( trigger, origin_offset, interact_offset ); + } + else + { + rel_entity thread pap_weapon_move_out( trigger, origin_offset, interact_offset ); + } + return trigger.worldgun; +} + +can_pack_weapon( weaponname ) +{ + if ( weaponname == "riotshield_zm" ) + { + return 0; + } + if ( flag( "pack_machine_in_use" ) ) + { + return 1; + } + weaponname = self get_nonalternate_weapon( weaponname ); + if ( !maps/mp/zombies/_zm_weapons::is_weapon_or_base_included( weaponname ) ) + { + return 0; + } + if ( !self maps/mp/zombies/_zm_weapons::can_upgrade_weapon( weaponname ) ) + { + return 0; + } + return 1; +} + +player_use_can_pack_now() +{ + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( self.intermission ) || self.intermission && self isthrowinggrenade() ) + { + return 0; + } + if ( !self can_buy_weapon() ) + { + return 0; + } + if ( self hacker_active() ) + { + return 0; + } + if ( !self can_pack_weapon( self getcurrentweapon() ) ) + { + return 0; + } + return 1; +} + +vending_machine_trigger_think() +{ + self endon( "death" ); + self endon( "Pack_A_Punch_off" ); + while ( 1 ) + { + players = get_players(); + 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; + } + else + { + self setinvisibletoplayer( players[ i ], 0 ); + } + i++; + } + wait 0.1; + } +} + +vending_weapon_upgrade() +{ + level endon( "Pack_A_Punch_off" ); + wait 0.01; + perk_machine = getent( self.target, "targetname" ); + self.perk_machine = perk_machine; + perk_machine_sound = getentarray( "perksacola", "targetname" ); + packa_rollers = spawn( "script_origin", self.origin ); + packa_timer = spawn( "script_origin", self.origin ); + packa_rollers linkto( self ); + packa_timer linkto( self ); + if ( isDefined( perk_machine.target ) ) + { + perk_machine.wait_flag = getent( perk_machine.target, "targetname" ); + } + pap_is_buildable = self is_buildable(); + if ( pap_is_buildable ) + { + self trigger_off(); + perk_machine hide(); + if ( isDefined( perk_machine.wait_flag ) ) + { + perk_machine.wait_flag hide(); + } + wait_for_buildable( "pap" ); + self trigger_on(); + perk_machine show(); + if ( isDefined( perk_machine.wait_flag ) ) + { + perk_machine.wait_flag show(); + } + } + self usetriggerrequirelookat(); + self sethintstring( &"ZOMBIE_NEED_POWER" ); + self setcursorhint( "HINT_NOICON" ); + power_off = !self maps/mp/zombies/_zm_power::pap_is_on(); + if ( power_off ) + { + pap_array = []; + pap_array[ 0 ] = perk_machine; + level thread do_initial_power_off_callback( pap_array, "packapunch" ); + level waittill( "Pack_A_Punch_on" ); + } + self enable_trigger(); + if ( isDefined( level.machine_assets[ "packapunch" ].power_on_callback ) ) + { + perk_machine thread [[ level.machine_assets[ "packapunch" ].power_on_callback ]](); + } + self thread vending_machine_trigger_think(); + perk_machine playloopsound( "zmb_perks_packa_loop" ); + self thread shutoffpapsounds( perk_machine, packa_rollers, packa_timer ); + self thread vending_weapon_upgrade_cost(); + for ( ;; ) + { + self.pack_player = undefined; + self waittill( "trigger", player ); + index = maps/mp/zombies/_zm_weapons::get_player_index( player ); + current_weapon = player getcurrentweapon(); + if ( current_weapon == "microwavegun_zm" ) + { + current_weapon = "microwavegundw_zm"; + } + current_weapon = player maps/mp/zombies/_zm_weapons::switch_from_alt_weapon( current_weapon ); + if ( isDefined( level.custom_pap_validation ) ) + { + valid = self [[ level.custom_pap_validation ]]( player ); + if ( !valid ) + { + continue; + } + } + else if ( player maps/mp/zombies/_zm_magicbox::can_buy_weapon() && !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( player.intermission ) && !player.intermission || player isthrowinggrenade() && !player maps/mp/zombies/_zm_weapons::can_upgrade_weapon( current_weapon ) ) + { + wait 0.1; + continue; + } + else + { + if ( isDefined( level.pap_moving ) && level.pap_moving ) + { + break; + } + else + { + if ( player isswitchingweapons() ) + { + wait 0.1; + if ( player isswitchingweapons() ) + { + break; + } + } + else if ( !maps/mp/zombies/_zm_weapons::is_weapon_or_base_included( current_weapon ) ) + { + break; + } + else current_cost = self.cost; + player.restore_ammo = undefined; + player.restore_clip = undefined; + player.restore_stock = undefined; + player_restore_clip_size = undefined; + player.restore_max = undefined; + upgrade_as_attachment = will_upgrade_weapon_as_attachment( current_weapon ); + if ( upgrade_as_attachment ) + { + current_cost = self.attachment_cost; + player.restore_ammo = 1; + player.restore_clip = player getweaponammoclip( current_weapon ); + player.restore_clip_size = weaponclipsize( current_weapon ); + player.restore_stock = player getweaponammostock( current_weapon ); + player.restore_max = weaponmaxammo( current_weapon ); + } + if ( player maps/mp/zombies/_zm_pers_upgrades_functions::is_pers_double_points_active() ) + { + current_cost = player maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_double_points_cost( current_cost ); + } + if ( player.score < current_cost ) + { + self playsound( "deny" ); + if ( isDefined( level.custom_pap_deny_vo_func ) ) + { + player [[ level.custom_pap_deny_vo_func ]](); + } + else + { + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "perk_deny", undefined, 0 ); + } + break; + } + else + { + self.pack_player = player; + flag_set( "pack_machine_in_use" ); + maps/mp/_demo::bookmark( "zm_player_use_packapunch", getTime(), player ); + player maps/mp/zombies/_zm_stats::increment_client_stat( "use_pap" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "use_pap" ); + self thread destroy_weapon_in_blackout( player ); + self thread destroy_weapon_on_disconnect( player ); + player maps/mp/zombies/_zm_score::minus_to_player_score( current_cost, 1 ); + sound = "evt_bottle_dispense"; + playsoundatposition( sound, self.origin ); + self thread maps/mp/zombies/_zm_audio::play_jingle_or_stinger( "mus_perks_packa_sting" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", "upgrade_wait" ); + self disable_trigger(); + if ( isDefined( upgrade_as_attachment ) && !upgrade_as_attachment ) + { + player thread do_player_general_vox( "general", "pap_wait", 10, 100 ); + } + else + { + player thread do_player_general_vox( "general", "pap_wait2", 10, 100 ); + } + player thread do_knuckle_crack(); + self.current_weapon = current_weapon; + upgrade_name = maps/mp/zombies/_zm_weapons::get_upgrade_weapon( current_weapon, upgrade_as_attachment ); + player third_person_weapon_upgrade( current_weapon, upgrade_name, packa_rollers, perk_machine, self ); + self enable_trigger(); + self sethintstring( &"ZOMBIE_GET_UPGRADED" ); + if ( isDefined( player ) ) + { + self setinvisibletoall(); + self setvisibletoplayer( player ); + self thread wait_for_player_to_take( player, current_weapon, packa_timer, upgrade_as_attachment ); + } + self thread wait_for_timeout( current_weapon, packa_timer, player ); + self waittill_any( "pap_timeout", "pap_taken", "pap_player_disconnected" ); + self.current_weapon = ""; + if ( isDefined( self.worldgun ) && isDefined( self.worldgun.worldgundw ) ) + { + self.worldgun.worldgundw delete(); + } + if ( isDefined( self.worldgun ) ) + { + self.worldgun delete(); + } + if ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch ) + { + self sethintstring( &"ZOMBIE_PERK_PACKAPUNCH_ATT", self.cost ); + } + else + { + self sethintstring( &"ZOMBIE_PERK_PACKAPUNCH", self.cost ); + } + self setvisibletoall(); + self.pack_player = undefined; + flag_clear( "pack_machine_in_use" ); + } + } + } + } +} + +shutoffpapsounds( ent1, ent2, ent3 ) +{ + while ( 1 ) + { + level waittill( "Pack_A_Punch_off" ); + level thread turnonpapsounds( ent1 ); + ent1 stoploopsound( 0.1 ); + ent2 stoploopsound( 0.1 ); + ent3 stoploopsound( 0.1 ); + } +} + +turnonpapsounds( ent ) +{ + level waittill( "Pack_A_Punch_on" ); + ent playloopsound( "zmb_perks_packa_loop" ); +} + +vending_weapon_upgrade_cost() +{ + level endon( "Pack_A_Punch_off" ); + while ( 1 ) + { + self.cost = 5000; + self.attachment_cost = 2000; + if ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch ) + { + self sethintstring( &"ZOMBIE_PERK_PACKAPUNCH_ATT", self.cost ); + } + else + { + self sethintstring( &"ZOMBIE_PERK_PACKAPUNCH", self.cost ); + } + level waittill( "powerup bonfire sale" ); + self.cost = 1000; + self.attachment_cost = 1000; + if ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch ) + { + self sethintstring( &"ZOMBIE_PERK_PACKAPUNCH_ATT", self.cost ); + } + else + { + self sethintstring( &"ZOMBIE_PERK_PACKAPUNCH", self.cost ); + } + level waittill( "bonfire_sale_off" ); + } +} + +wait_for_player_to_take( player, weapon, packa_timer, upgrade_as_attachment ) +{ + current_weapon = self.current_weapon; + upgrade_name = self.upgrade_name; + /* +/# + assert( isDefined( current_weapon ), "wait_for_player_to_take: weapon does not exist" ); +#/ +/# + assert( isDefined( upgrade_name ), "wait_for_player_to_take: upgrade_weapon does not exist" ); +#/ + */ + upgrade_weapon = upgrade_name; + self endon( "pap_timeout" ); + level endon( "Pack_A_Punch_off" ); + while ( 1 ) + { + packa_timer playloopsound( "zmb_perks_packa_ticktock" ); + self waittill( "trigger", trigger_player ); + if ( isDefined( level.pap_grab_by_anyone ) && level.pap_grab_by_anyone ) + { + player = trigger_player; + } + packa_timer stoploopsound( 0.05 ); + if ( trigger_player == player ) + { + player maps/mp/zombies/_zm_stats::increment_client_stat( "pap_weapon_grabbed" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "pap_weapon_grabbed" ); + current_weapon = player getcurrentweapon(); + /* +/# + if ( current_weapon == "none" ) + { + iprintlnbold( "WEAPON IS NONE, PACKAPUNCH RETRIEVAL DENIED" ); +#/ + } + */ + 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() ) + { + maps/mp/_demo::bookmark( "zm_player_grabbed_packapunch", getTime(), player ); + self notify( "pap_taken" ); + player notify( "pap_taken" ); + player.pap_used = 1; + if ( isDefined( upgrade_as_attachment ) && !upgrade_as_attachment ) + { + player thread do_player_general_vox( "general", "pap_arm", 15, 100 ); + } + else + { + player thread do_player_general_vox( "general", "pap_arm2", 15, 100 ); + } + weapon_limit = get_player_weapon_limit( player ); + player maps/mp/zombies/_zm_weapons::take_fallback_weapon(); + primaries = player getweaponslistprimaries(); + if ( isDefined( primaries ) && primaries.size >= weapon_limit ) + { + player maps/mp/zombies/_zm_weapons::weapon_give( upgrade_weapon ); + } + else + { + player giveweapon( upgrade_weapon, 0, player maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( upgrade_weapon ) ); + player givestartammo( upgrade_weapon ); + } + player switchtoweapon( upgrade_weapon ); + if ( isDefined( player.restore_ammo ) && player.restore_ammo ) + { + new_clip = player.restore_clip + ( weaponclipsize( upgrade_weapon ) - player.restore_clip_size ); + new_stock = player.restore_stock + ( weaponmaxammo( upgrade_weapon ) - player.restore_max ); + player setweaponammostock( upgrade_weapon, new_stock ); + player setweaponammoclip( upgrade_weapon, new_clip ); + } + player.restore_ammo = undefined; + player.restore_clip = undefined; + player.restore_stock = undefined; + player.restore_max = undefined; + player.restore_clip_size = undefined; + player maps/mp/zombies/_zm_weapons::play_weapon_vo( upgrade_weapon ); + return; + } + } + wait 0.05; + } +} + +wait_for_timeout( weapon, packa_timer, player ) +{ + self endon( "pap_taken" ); + self endon( "pap_player_disconnected" ); + self thread wait_for_disconnect( player ); + wait level.packapunch_timeout; + self notify( "pap_timeout" ); + packa_timer stoploopsound( 0.05 ); + packa_timer playsound( "zmb_perks_packa_deny" ); + maps/mp/zombies/_zm_weapons::unacquire_weapon_toggle( weapon ); + if ( isDefined( player ) ) + { + player maps/mp/zombies/_zm_stats::increment_client_stat( "pap_weapon_not_grabbed" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "pap_weapon_not_grabbed" ); + } +} + +wait_for_disconnect( player ) +{ + self endon( "pap_taken" ); + self endon( "pap_timeout" ); + while ( isDefined( player ) ) + { + wait 0.1; + } + /* +/# + println( "*** PAP : User disconnected." ); +#/ + */ + self notify( "pap_player_disconnected" ); +} + +destroy_weapon_on_disconnect( player ) +{ + self endon( "pap_timeout" ); + self endon( "pap_taken" ); + level endon( "Pack_A_Punch_off" ); + player waittill( "disconnect" ); + if ( isDefined( self.worldgun ) ) + { + if ( isDefined( self.worldgun.worldgundw ) ) + { + self.worldgun.worldgundw delete(); + } + self.worldgun delete(); + } +} + +destroy_weapon_in_blackout( player ) +{ + self endon( "pap_timeout" ); + self endon( "pap_taken" ); + self endon( "pap_player_disconnected" ); + level waittill( "Pack_A_Punch_off" ); + if ( isDefined( self.worldgun ) ) + { + self.worldgun rotateto( self.worldgun.angles + ( randomint( 90 ) - 45, 0, randomint( 360 ) - 180 ), 1.5, 0, 0 ); + player playlocalsound( level.zmb_laugh_alias ); + wait 1.5; + if ( isDefined( self.worldgun.worldgundw ) ) + { + self.worldgun.worldgundw delete(); + } + self.worldgun delete(); + } +} + +do_knuckle_crack() +{ + self endon( "disconnect" ); + gun = self upgrade_knuckle_crack_begin(); + self waittill_any( "fake_death", "death", "player_downed", "weapon_change_complete" ); + self upgrade_knuckle_crack_end( gun ); +} + +upgrade_knuckle_crack_begin() +{ + self increment_is_drinking(); + self disable_player_move_states( 1 ); + primaries = self getweaponslistprimaries(); + gun = self getcurrentweapon(); + weapon = level.machine_assets[ "packapunch" ].weapon; + if ( gun != "none" && !is_placeable_mine( gun ) && !is_equipment( gun ) ) + { + self notify( "zmb_lost_knife" ); + self takeweapon( gun ); + } + else + { + return; + } + self giveweapon( weapon ); + self switchtoweapon( weapon ); + return gun; +} + +upgrade_knuckle_crack_end( gun ) +{ +/* +/# + assert( !is_zombie_perk_bottle( gun ) ); +#/ +/# + assert( gun != level.revive_tool ); +#/ +*/ + self enable_player_move_states(); + weapon = level.machine_assets[ "packapunch" ].weapon; + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( self.intermission ) && self.intermission ) + { + self takeweapon( weapon ); + return; + } + self decrement_is_drinking(); + self takeweapon( weapon ); + primaries = self getweaponslistprimaries(); + if ( self.is_drinking > 0 ) + { + return; + } + else if ( isDefined( primaries ) && primaries.size > 0 ) + { + self switchtoweapon( primaries[ 0 ] ); + } + else + { + if ( self hasweapon( level.laststandpistol ) ) + { + self switchtoweapon( level.laststandpistol ); + return; + } + else + { + self maps/mp/zombies/_zm_weapons::give_fallback_weapon(); + } + } +} + +turn_packapunch_on() +{ + vending_weapon_upgrade_trigger = getentarray( "specialty_weapupgrade", "script_noteworthy" ); + level.pap_triggers = vending_weapon_upgrade_trigger; + i = 0; + while ( i < vending_weapon_upgrade_trigger.size ) + { + perk = getent( vending_weapon_upgrade_trigger[ i ].target, "targetname" ); + if ( isDefined( perk ) ) + { + perk setmodel( level.machine_assets[ "packapunch" ].off_model ); + } + i++; + } + for ( ;; ) + { + level waittill( "Pack_A_Punch_on" ); + i = 0; + while ( i < vending_weapon_upgrade_trigger.size ) + { + perk = getent( vending_weapon_upgrade_trigger[ i ].target, "targetname" ); + if ( isDefined( perk ) ) + { + perk thread activate_packapunch(); + } + i++; + } + level waittill( "Pack_A_Punch_off" ); + i = 0; + while ( i < vending_weapon_upgrade_trigger.size ) + { + perk = getent( vending_weapon_upgrade_trigger[ i ].target, "targetname" ); + if ( isDefined( perk ) ) + { + perk thread deactivate_packapunch(); + } + i++; + } + } +} + +activate_packapunch() +{ + self setmodel( level.machine_assets[ "packapunch" ].on_model ); + self playsound( "zmb_perks_power_on" ); + self vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + timer = 0; + duration = 0.05; +} + +deactivate_packapunch() +{ + self setmodel( level.machine_assets[ "packapunch" ].off_model ); +} + +do_initial_power_off_callback( machine_array, perkname ) +{ + if ( !isDefined( level.machine_assets[ perkname ] ) ) + { + /* +/# + println( "Error: doing setup for a machine with no level.machine_assets! Check your perk initialization!" ); +#/ + */ + return; + } + if ( !isDefined( level.machine_assets[ perkname ].power_off_callback ) ) + { + return; + } + wait 0.05; + array_thread( machine_array, level.machine_assets[ perkname ].power_off_callback ); +} + +turn_sleight_on() +{ + while ( 1 ) + { + machine = getentarray( "vending_sleight", "targetname" ); + machine_triggers = getentarray( "vending_sleight", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "speedcola" ].off_model ); + i++; + } + level thread do_initial_power_off_callback( machine, "speedcola" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "sleight_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "speedcola" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "sleight_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "speedcola" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "speedcola" ].power_on_callback ); + } + level notify( "specialty_fastreload_power_on" ); + level waittill( "sleight_off" ); + array_thread( machine, ::turn_perk_off ); + if ( isDefined( level.machine_assets[ "speedcola" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "speedcola" ].power_off_callback ); + } + } +} + +use_solo_revive() +{ + if ( isDefined( level.using_solo_revive ) ) + { + return level.using_solo_revive; + } + players = get_players(); + solo_mode = 0; + if ( players.size == 1 || isDefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive ) + { + solo_mode = 1; + } + level.using_solo_revive = solo_mode; + return solo_mode; +} + +turn_revive_on() +{ + level endon( "stop_quickrevive_logic" ); + machine = getentarray( "vending_revive", "targetname" ); + machine_triggers = getentarray( "vending_revive", "target" ); + machine_model = undefined; + machine_clip = undefined; + if ( isDefined( level.zombiemode_using_revive_perk ) && !level.zombiemode_using_revive_perk ) + { + return; + } + flag_wait( "start_zombie_round_logic" ); + players = get_players(); + solo_mode = 0; + if ( use_solo_revive() ) + { + solo_mode = 1; + } + start_state = 0; + start_state = solo_mode; + while ( 1 ) + { + machine = getentarray( "vending_revive", "targetname" ); + machine_triggers = getentarray( "vending_revive", "target" ); + i = 0; + while ( i < machine.size ) + { + if ( flag_exists( "solo_game" ) && flag_exists( "solo_revive" ) && flag( "solo_game" ) && flag( "solo_revive" ) ) + { + machine[ i ] hide(); + } + machine[ i ] setmodel( level.machine_assets[ "revive" ].off_model ); + if ( isDefined( level.quick_revive_final_pos ) ) + { + level.quick_revive_default_origin = level.quick_revive_final_pos; + } + if ( !isDefined( level.quick_revive_default_origin ) ) + { + level.quick_revive_default_origin = machine[ i ].origin; + level.quick_revive_default_angles = machine[ i ].angles; + } + level.quick_revive_machine = machine[ i ]; + i++; + } + array_thread( machine_triggers, ::set_power_on, 0 ); + if ( isDefined( start_state ) && !start_state ) + { + level waittill( "revive_on" ); + } + start_state = 0; + i = 0; + while ( i < machine.size ) + { + if ( isDefined( machine[ i ].classname ) && machine[ i ].classname == "script_model" ) + { + if ( isDefined( machine[ i ].script_noteworthy ) && machine[ i ].script_noteworthy == "clip" ) + { + machine_clip = machine[ i ]; + i++; + continue; + } + else + { + machine[ i ] setmodel( level.machine_assets[ "revive" ].on_model ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine_model = machine[ i ]; + machine[ i ] thread perk_fx( "revive_light" ); + machine[ i ] notify( "stop_loopsound" ); + machine[ i ] thread play_loop_on_machine(); + if ( isDefined( machine_triggers[ i ] ) ) + { + machine_clip = machine_triggers[ i ].clip; + } + if ( isDefined( machine_triggers[ i ] ) ) + { + blocker_model = machine_triggers[ i ].blocker_model; + } + } + } + i++; + } + wait_network_frame(); + if ( solo_mode && isDefined( machine_model ) && !is_true( machine_model.ishidden ) ) + { + machine_model thread revive_solo_fx( machine_clip, blocker_model ); + } + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "revive" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "revive" ].power_on_callback ); + } + level notify( "specialty_quickrevive_power_on" ); + if ( isDefined( machine_model ) ) + { + machine_model.ishidden = 0; + } + notify_str = level waittill_any_return( "revive_off", "revive_hide" ); + should_hide = 0; + if ( notify_str == "revive_hide" ) + { + should_hide = 1; + } + if ( isDefined( level.machine_assets[ "revive" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "revive" ].power_off_callback ); + } + i = 0; + while ( i < machine.size ) + { + if ( isDefined( machine[ i ].classname ) && machine[ i ].classname == "script_model" ) + { + machine[ i ] turn_perk_off( should_hide ); + } + i++; + } + } +} + +revive_solo_fx( machine_clip, blocker_model ) +{ + if ( level flag_exists( "solo_revive" ) && flag( "solo_revive" ) && !flag( "solo_game" ) ) + { + return; + } + if ( isDefined( machine_clip ) ) + { + level.quick_revive_machine_clip = machine_clip; + } + if ( !isDefined( level.solo_revive_init ) ) + { + level.solo_revive_init = 1; + flag_init( "solo_revive" ); + } + level notify( "revive_solo_fx" ); + level endon( "revive_solo_fx" ); + self endon( "death" ); + flag_wait( "solo_revive" ); + if ( isDefined( level.revive_solo_fx_func ) ) + { + level thread [[ level.revive_solo_fx_func ]](); + } + wait 2; + self playsound( "zmb_box_move" ); + playsoundatposition( "zmb_whoosh", self.origin ); + if ( isDefined( self._linked_ent ) ) + { + self unlink(); + } + self moveto( self.origin + vectorScale( ( 0, -1, 0 ), 40 ), 3 ); + if ( isDefined( level.custom_vibrate_func ) ) + { + [[ level.custom_vibrate_func ]]( self ); + } + else + { + 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, 5 ); + } + self waittill( "movedone" ); + playfx( level._effect[ "poltergeist" ], self.origin ); + playsoundatposition( "zmb_box_poof", self.origin ); + level clientnotify( "drb" ); + if ( isDefined( self.fx ) ) + { + self.fx unlink(); + self.fx delete(); + } + if ( isDefined( machine_clip ) ) + { + machine_clip trigger_off(); + machine_clip connectpaths(); + } + if ( isDefined( blocker_model ) ) + { + blocker_model show(); + } + level notify( "revive_hide" ); +} + +turn_jugger_on() +{ + while ( 1 ) + { + machine = getentarray( "vending_jugg", "targetname" ); + machine_triggers = getentarray( "vending_jugg", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "juggernog" ].off_model ); + i++; + } + level thread do_initial_power_off_callback( machine, "juggernog" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "juggernog_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "juggernog" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "jugger_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_armorvest_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "juggernog" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "juggernog" ].power_on_callback ); + } + level waittill( "juggernog_off" ); + if ( isDefined( level.machine_assets[ "juggernog" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "juggernog" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + } +} + +turn_doubletap_on() +{ + while ( 1 ) + { + machine = getentarray( "vending_doubletap", "targetname" ); + machine_triggers = getentarray( "vending_doubletap", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "doubletap" ].off_model ); + i++; + } + level thread do_initial_power_off_callback( machine, "doubletap" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "doubletap_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "doubletap" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "doubletap_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_rof_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "doubletap" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "doubletap" ].power_on_callback ); + } + level waittill( "doubletap_off" ); + if ( isDefined( level.machine_assets[ "doubletap" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "doubletap" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + } +} + +turn_marathon_on() +{ + while ( 1 ) + { + machine = getentarray( "vending_marathon", "targetname" ); + machine_triggers = getentarray( "vending_marathon", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "marathon" ].off_model ); + i++; + } + array_thread( machine_triggers, ::set_power_on, 0 ); + level thread do_initial_power_off_callback( machine, "marathon" ); + level waittill( "marathon_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "marathon" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "marathon_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_longersprint_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "marathon" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "marathon" ].power_on_callback ); + } + level waittill( "marathon_off" ); + if ( isDefined( level.machine_assets[ "marathon" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "marathon" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + } +} + +turn_deadshot_on() +{ + while ( 1 ) + { + machine = getentarray( "vending_deadshot_model", "targetname" ); + machine_triggers = getentarray( "vending_deadshot", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "deadshot" ].off_model ); + i++; + } + level thread do_initial_power_off_callback( machine, "deadshot" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "deadshot_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "deadshot" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "deadshot_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_deadshot_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "deadshot" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "deadshot" ].power_on_callback ); + } + level waittill( "deadshot_off" ); + if ( isDefined( level.machine_assets[ "deadshot" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "deadshot" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + } +} + +turn_tombstone_on() +{ + level endon( "tombstone_removed" ); + while ( 1 ) + { + machine = getentarray( "vending_tombstone", "targetname" ); + machine_triggers = getentarray( "vending_tombstone", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "tombstone" ].off_model ); + i++; + } + level thread do_initial_power_off_callback( machine, "tombstone" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "tombstone_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "tombstone" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "tombstone_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_scavenger_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "tombstone" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "tombstone" ].power_on_callback ); + } + level waittill( "tombstone_off" ); + if ( isDefined( level.machine_assets[ "tombstone" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "tombstone" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + players = get_players(); + _a1718 = players; + _k1718 = getFirstArrayKey( _a1718 ); + while ( isDefined( _k1718 ) ) + { + player = _a1718[ _k1718 ]; + player.hasperkspecialtytombstone = undefined; + _k1718 = getNextArrayKey( _a1718, _k1718 ); + } + } +} + +turn_additionalprimaryweapon_on() +{ + while ( 1 ) + { + machine = getentarray( "vending_additionalprimaryweapon", "targetname" ); + machine_triggers = getentarray( "vending_additionalprimaryweapon", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "additionalprimaryweapon" ].off_model ); + i++; + } + level thread do_initial_power_off_callback( machine, "additionalprimaryweapon" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "additionalprimaryweapon_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "additionalprimaryweapon" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "additionalprimaryweapon_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_additionalprimaryweapon_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "additionalprimaryweapon" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "additionalprimaryweapon" ].power_on_callback ); + } + level waittill( "additionalprimaryweapon_off" ); + if ( isDefined( level.machine_assets[ "additionalprimaryweapon" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "additionalprimaryweapon" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + } +} + +turn_chugabud_on() +{ + maps/mp/zombies/_zm_chugabud::init(); + if ( isDefined( level.vsmgr_prio_visionset_zm_whos_who ) ) + { + maps/mp/_visionset_mgr::vsmgr_register_info( "visionset", "zm_whos_who", 5000, level.vsmgr_prio_visionset_zm_whos_who, 1, 1 ); + } + while ( 1 ) + { + machine = getentarray( "vending_chugabud", "targetname" ); + machine_triggers = getentarray( "vending_chugabud", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "whoswho" ].off_model ); + i++; + } + level thread do_initial_power_off_callback( machine, "whoswho" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "chugabud_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( level.machine_assets[ "whoswho" ].on_model ); + machine[ i ] vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + machine[ i ] playsound( "zmb_perks_power_on" ); + machine[ i ] thread perk_fx( "tombstone_light" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_finalstand_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + if ( isDefined( level.machine_assets[ "whoswho" ].power_on_callback ) ) + { + array_thread( machine, level.machine_assets[ "whoswho" ].power_on_callback ); + } + level waittill( "chugabud_off" ); + if ( isDefined( level.machine_assets[ "whoswho" ].power_off_callback ) ) + { + array_thread( machine, level.machine_assets[ "whoswho" ].power_off_callback ); + } + array_thread( machine, ::turn_perk_off ); + players = get_players(); + _a1819 = players; + _k1819 = getFirstArrayKey( _a1819 ); + while ( isDefined( _k1819 ) ) + { + player = _a1819[ _k1819 ]; + player.hasperkspecialtychugabud = undefined; + _k1819 = getNextArrayKey( _a1819, _k1819 ); + } + } +} + +set_power_on( state ) +{ + self.power_on = state; +} + +turn_perk_off( ishidden ) +{ + self notify( "stop_loopsound" ); + newmachine = spawn( "script_model", self.origin ); + newmachine.angles = self.angles; + newmachine.targetname = self.targetname; + if ( is_true( ishidden ) ) + { + newmachine.ishidden = 1; + newmachine hide(); + } + self delete(); +} + +play_loop_on_machine() +{ + if ( isDefined( level.sndperksacolaloopoverride ) ) + { + return; + } + sound_ent = spawn( "script_origin", self.origin ); + sound_ent playloopsound( "zmb_perks_machine_loop" ); + sound_ent linkto( self ); + self waittill( "stop_loopsound" ); + sound_ent unlink(); + sound_ent delete(); +} + +perk_fx( fx, turnofffx ) +{ + if ( isDefined( turnofffx ) ) + { + self.perk_fx = 0; + } + else + { + wait 3; + if ( isDefined( self ) && !is_true( self.perk_fx ) ) + { + playfxontag( level._effect[ fx ], self, "tag_origin" ); + self.perk_fx = 1; + } + } +} + +electric_perks_dialog() +{ + self endon( "death" ); + wait 0.01; + flag_wait( "start_zombie_round_logic" ); + players = get_players(); + if ( players.size == 1 ) + { + return; + } + self endon( "warning_dialog" ); + level endon( "switch_flipped" ); + timer = 0; + while ( 1 ) + { + wait 0.5; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( !isDefined( players[ i ] ) ) + { + i++; + continue; + } + else 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 ) + { + if ( !isDefined( players[ i ] ) ) + { + i++; + continue; + } + else + { + players[ i ] thread do_player_vo( "vox_start", 5 ); + wait 3; + self notify( "warning_dialog" ); + /* +/# + iprintlnbold( "warning_given" ); +#/ + */ + } + } + i++; + } + } +} + +reset_vending_hint_string() +{ + perk = self.script_noteworthy; + solo = maps/mp/zombies/_zm_perks::use_solo_revive(); + switch( perk ) + { + case "specialty_armorvest": + case "specialty_armorvest_upgrade": + self sethintstring( &"ZOMBIE_PERK_JUGGERNAUT", self.cost ); + break; + case "specialty_quickrevive": + case "specialty_quickrevive_upgrade": + if ( solo ) + { + self sethintstring( &"ZOMBIE_PERK_QUICKREVIVE_SOLO", self.cost ); + } + else + { + self sethintstring( &"ZOMBIE_PERK_QUICKREVIVE", self.cost ); + } + break; + case "specialty_fastreload": + case "specialty_fastreload_upgrade": + self sethintstring( &"ZOMBIE_PERK_FASTRELOAD", self.cost ); + break; + case "specialty_rof": + case "specialty_rof_upgrade": + self sethintstring( &"ZOMBIE_PERK_DOUBLETAP", self.cost ); + break; + case "specialty_longersprint": + case "specialty_longersprint_upgrade": + self sethintstring( &"ZOMBIE_PERK_MARATHON", self.cost ); + break; + case "specialty_deadshot": + case "specialty_deadshot_upgrade": + self sethintstring( &"ZOMBIE_PERK_DEADSHOT", self.cost ); + break; + case "specialty_additionalprimaryweapon": + case "specialty_additionalprimaryweapon_upgrade": + self sethintstring( &"ZOMBIE_PERK_ADDITIONALPRIMARYWEAPON", self.cost ); + break; + case "specialty_scavenger": + case "specialty_scavenger_upgrade": + self sethintstring( &"ZOMBIE_PERK_TOMBSTONE", self.cost ); + break; + case "specialty_finalstand": + case "specialty_finalstand_upgrade": + self sethintstring( &"ZOMBIE_PERK_CHUGABUD", self.cost ); + break; + default: + self sethintstring( ( perk + " Cost: " ) + level.zombie_vars[ "zombie_perk_cost" ] ); + } + if ( isDefined( level._custom_perks ) ) + { + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].cost ) && isDefined( level._custom_perks[ perk ].hint_string ) ) + { + self sethintstring( level._custom_perks[ perk ].hint_string, level._custom_perks[ perk ].cost ); + } + } +} + +vending_trigger_think() +{ + self endon( "death" ); + wait 0.01; + perk = self.script_noteworthy; + solo = 0; + start_on = 0; + level.revive_machine_is_solo = 0; + if ( isDefined( perk ) || perk == "specialty_quickrevive" && perk == "specialty_quickrevive_upgrade" ) + { + flag_wait( "start_zombie_round_logic" ); + solo = use_solo_revive(); + self endon( "stop_quickrevive_logic" ); + level.quick_revive_trigger = self; + if ( solo ) + { + if ( !is_true( level.revive_machine_is_solo ) ) + { + start_on = 1; + players = get_players(); + _a2045 = players; + _k2045 = getFirstArrayKey( _a2045 ); + while ( isDefined( _k2045 ) ) + { + player = _a2045[ _k2045 ]; + if ( !isDefined( player.lives ) ) + { + player.lives = 0; + } + _k2045 = getNextArrayKey( _a2045, _k2045 ); + } + level maps/mp/zombies/_zm::set_default_laststand_pistol( 1 ); + } + level.revive_machine_is_solo = 1; + } + } + self sethintstring( &"ZOMBIE_NEED_POWER" ); + self setcursorhint( "HINT_NOICON" ); + self usetriggerrequirelookat(); + cost = level.zombie_vars[ "zombie_perk_cost" ]; + switch( perk ) + { + case "specialty_armorvest": + case "specialty_armorvest_upgrade": + cost = 2500; + break; + case "specialty_quickrevive": + case "specialty_quickrevive_upgrade": + if ( solo ) + { + cost = 500; + } + else + { + cost = 1500; + } + break; + case "specialty_fastreload": + case "specialty_fastreload_upgrade": + cost = 3000; + break; + case "specialty_rof": + case "specialty_rof_upgrade": + cost = 2000; + break; + case "specialty_longersprint": + case "specialty_longersprint_upgrade": + cost = 2000; + break; + case "specialty_deadshot": + case "specialty_deadshot_upgrade": + cost = 1500; + break; + case "specialty_additionalprimaryweapon": + case "specialty_additionalprimaryweapon_upgrade": + cost = 4000; + break; + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].cost ) ) + { + cost = level._custom_perks[ perk ].cost; + } + self.cost = cost; + if ( !start_on ) + { + notify_name = perk + "_power_on"; + level waittill( notify_name ); + } + start_on = 0; + if ( !isDefined( level._perkmachinenetworkchoke ) ) + { + level._perkmachinenetworkchoke = 0; + } + else + { + level._perkmachinenetworkchoke++; + } + i = 0; + while ( i < level._perkmachinenetworkchoke ) + { + wait_network_frame(); + i++; + } + self thread maps/mp/zombies/_zm_audio::perks_a_cola_jingle_timer(); + self thread check_player_has_perk( perk ); + switch( perk ) + { + case "specialty_armorvest": + case "specialty_armorvest_upgrade": + self sethintstring( &"ZOMBIE_PERK_JUGGERNAUT", cost ); + break; + case "specialty_quickrevive": + case "specialty_quickrevive_upgrade": + if ( solo ) + { + self sethintstring( &"ZOMBIE_PERK_QUICKREVIVE_SOLO", cost ); + } + else + { + self sethintstring( &"ZOMBIE_PERK_QUICKREVIVE", cost ); + } + break; + case "specialty_fastreload": + case "specialty_fastreload_upgrade": + self sethintstring( &"ZOMBIE_PERK_FASTRELOAD", cost ); + break; + case "specialty_rof": + case "specialty_rof_upgrade": + self sethintstring( &"ZOMBIE_PERK_DOUBLETAP", cost ); + break; + case "specialty_longersprint": + case "specialty_longersprint_upgrade": + self sethintstring( &"ZOMBIE_PERK_MARATHON", cost ); + break; + case "specialty_deadshot": + case "specialty_deadshot_upgrade": + self sethintstring( &"ZOMBIE_PERK_DEADSHOT", cost ); + break; + case "specialty_additionalprimaryweapon": + case "specialty_additionalprimaryweapon_upgrade": + self sethintstring( &"ZOMBIE_PERK_ADDITIONALPRIMARYWEAPON", cost ); + break; + case "specialty_scavenger": + case "specialty_scavenger_upgrade": + self sethintstring( &"ZOMBIE_PERK_TOMBSTONE", cost ); + break; + case "specialty_finalstand": + case "specialty_finalstand_upgrade": + self sethintstring( &"ZOMBIE_PERK_CHUGABUD", cost ); + break; + default: + self sethintstring( ( perk + " Cost: " ) + level.zombie_vars[ "zombie_perk_cost" ] ); + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].hint_string ) ) + { + self sethintstring( level._custom_perks[ perk ].hint_string, cost ); + } + for ( ;; ) + { + self waittill( "trigger", player ); + 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 ) + { + continue; + } + else + { + if ( player in_revive_trigger() ) + { + break; + } + else if ( !player maps/mp/zombies/_zm_magicbox::can_buy_weapon() ) + { + wait 0.1; + break; + } + else if ( player isthrowinggrenade() ) + { + wait 0.1; + break; + } + else if ( player isswitchingweapons() ) + { + wait 0.1; + break; + } + else if ( player.is_drinking > 0 ) + { + wait 0.1; + break; + } + else if ( player hasperk( perk ) || player has_perk_paused( perk ) ) + { + cheat = 0; + /* +/# + if ( getDvarInt( "zombie_cheat" ) >= 5 ) + { + cheat = 1; +#/ + } + */ + if ( cheat != 1 ) + { + self playsound( "deny" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "perk_deny", undefined, 1 ); + break; + } + } + else if ( isDefined( level.custom_perk_validation ) ) + { + valid = self [[ level.custom_perk_validation ]]( player ); + if ( !valid ) + { + break; + } + } + else current_cost = cost; + if ( player maps/mp/zombies/_zm_pers_upgrades_functions::is_pers_double_points_active() ) + { + current_cost = player maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_double_points_cost( current_cost ); + } + if ( player.score < current_cost ) + { + self playsound( "evt_perk_deny" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "perk_deny", undefined, 0 ); + break; + } + else if ( player.num_perks >= player get_player_perk_purchase_limit() ) + { + self playsound( "evt_perk_deny" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "sigh" ); + break; + } + else + { + sound = "evt_bottle_dispense"; + playsoundatposition( sound, self.origin ); + player maps/mp/zombies/_zm_score::minus_to_player_score( current_cost, 1 ); + player.perk_purchased = perk; + self thread maps/mp/zombies/_zm_audio::play_jingle_or_stinger( self.script_label ); + self thread vending_trigger_post_think( player, perk ); + } + } + } +} + +vending_trigger_post_think( player, perk ) +{ + player endon( "disconnect" ); + player endon( "end_game" ); + player endon( "perk_abort_drinking" ); + gun = player perk_give_bottle_begin( perk ); + evt = player waittill_any_return( "fake_death", "death", "player_downed", "weapon_change_complete" ); + if ( evt == "weapon_change_complete" ) + { + player thread wait_give_perk( perk, 1 ); + } + player perk_give_bottle_end( gun, perk ); + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( player.intermission ) && player.intermission ) + { + return; + } + player notify( "burp" ); + if ( isDefined( level.pers_upgrade_cash_back ) && level.pers_upgrade_cash_back ) + { + player maps/mp/zombies/_zm_pers_upgrades_functions::cash_back_player_drinks_perk(); + } + if ( isDefined( level.pers_upgrade_perk_lose ) && level.pers_upgrade_perk_lose ) + { + player thread maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_perk_lose_bought(); + } + if ( isDefined( level.perk_bought_func ) ) + { + player [[ level.perk_bought_func ]]( perk ); + } + player.perk_purchased = undefined; + if ( is_false( self.power_on ) ) + { + wait 1; + perk_pause( self.script_noteworthy ); + } + bbprint( "zombie_uses", "playername %s playerscore %d round %d name %s x %f y %f z %f type %s", player.name, player.score, level.round_number, perk, self.origin, "perk" ); +} + +solo_revive_buy_trigger_move( revive_trigger_noteworthy ) +{ + self endon( "death" ); + revive_perk_triggers = getentarray( revive_trigger_noteworthy, "script_noteworthy" ); + _a2384 = revive_perk_triggers; + _k2384 = getFirstArrayKey( _a2384 ); + while ( isDefined( _k2384 ) ) + { + revive_perk_trigger = _a2384[ _k2384 ]; + self thread solo_revive_buy_trigger_move_trigger( revive_perk_trigger ); + _k2384 = getNextArrayKey( _a2384, _k2384 ); + } +} + +solo_revive_buy_trigger_move_trigger( revive_perk_trigger ) +{ + self endon( "death" ); + revive_perk_trigger setinvisibletoplayer( self ); + if ( level.solo_lives_given >= 3 ) + { + revive_perk_trigger trigger_off(); + if ( isDefined( level._solo_revive_machine_expire_func ) ) + { + revive_perk_trigger [[ level._solo_revive_machine_expire_func ]](); + } + return; + } + while ( self.lives > 0 ) + { + wait 0.1; + } + revive_perk_trigger setvisibletoplayer( self ); +} + +wait_give_perk( perk, bought ) +{ + self endon( "player_downed" ); + self endon( "disconnect" ); + self endon( "end_game" ); + self endon( "perk_abort_drinking" ); + self waittill_notify_or_timeout( "burp", 0.5 ); + self give_perk( perk, bought ); +} + +return_retained_perks() +{ + while ( isDefined( self._retain_perks_array ) ) + { + keys = getarraykeys( self._retain_perks_array ); + _a2445 = keys; + _k2445 = getFirstArrayKey( _a2445 ); + while ( isDefined( _k2445 ) ) + { + perk = _a2445[ _k2445 ]; + if ( isDefined( self._retain_perks_array[ perk ] ) && self._retain_perks_array[ perk ] ) + { + self give_perk( perk, 0 ); + } + _k2445 = getNextArrayKey( _a2445, _k2445 ); + } + } +} + +give_perk( perk, bought ) +{ + self setperk( perk ); + self.num_perks++; + if ( isDefined( bought ) && bought ) + { + self maps/mp/zombies/_zm_audio::playerexert( "burp" ); + if ( isDefined( level.remove_perk_vo_delay ) && level.remove_perk_vo_delay ) + { + self maps/mp/zombies/_zm_audio::perk_vox( perk ); + } + else + { + self delay_thread( 1.5, ::perk_vox, perk ); + } + self setblur( 4, 0.1 ); + wait 0.1; + self setblur( 0, 0.1 ); + self notify( "perk_bought" ); + } + self perk_set_max_health_if_jugg( perk, 1, 0 ); + if ( isDefined( level.disable_deadshot_clientfield ) && !level.disable_deadshot_clientfield ) + { + if ( perk == "specialty_deadshot" ) + { + self setclientfieldtoplayer( "deadshot_perk", 1 ); + } + else + { + if ( perk == "specialty_deadshot_upgrade" ) + { + self setclientfieldtoplayer( "deadshot_perk", 1 ); + } + } + } + if ( perk == "specialty_scavenger" ) + { + self.hasperkspecialtytombstone = 1; + } + players = get_players(); + if ( use_solo_revive() && perk == "specialty_quickrevive" ) + { + self.lives = 1; + if ( !isDefined( level.solo_lives_given ) ) + { + level.solo_lives_given = 0; + } + if ( isDefined( level.solo_game_free_player_quickrevive ) ) + { + level.solo_game_free_player_quickrevive = undefined; + } + else + { + level.solo_lives_given++; + } + if ( level.solo_lives_given >= 3 ) + { + flag_set( "solo_revive" ); + } + self thread solo_revive_buy_trigger_move( perk ); + } + if ( perk == "specialty_finalstand" ) + { + self.lives = 1; + self.hasperkspecialtychugabud = 1; + self notify( "perk_chugabud_activated" ); + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].player_thread_give ) ) + { + self thread [[ level._custom_perks[ perk ].player_thread_give ]](); + } + self set_perk_clientfield( perk, 1 ); + maps/mp/_demo::bookmark( "zm_player_perk", getTime(), self ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "perks_drank" ); + self maps/mp/zombies/_zm_stats::increment_client_stat( perk + "_drank" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( perk + "_drank" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "perks_drank" ); + if ( !isDefined( self.perk_history ) ) + { + self.perk_history = []; + } + self.perk_history = add_to_array( self.perk_history, perk, 0 ); + if ( !isDefined( self.perks_active ) ) + { + self.perks_active = []; + } + self.perks_active[ self.perks_active.size ] = perk; + self notify( "perk_acquired" ); + self thread perk_think( perk ); +} + +perk_set_max_health_if_jugg( perk, set_premaxhealth, clamp_health_to_max_health ) +{ + max_total_health = undefined; + if ( perk == "specialty_armorvest" ) + { + if ( set_premaxhealth ) + { + self.premaxhealth = self.maxhealth; + } + max_total_health = level.zombie_vars[ "zombie_perk_juggernaut_health" ]; + } + else if ( perk == "specialty_armorvest_upgrade" ) + { + if ( set_premaxhealth ) + { + self.premaxhealth = self.maxhealth; + } + max_total_health = level.zombie_vars[ "zombie_perk_juggernaut_health_upgrade" ]; + } + else if ( perk == "jugg_upgrade" ) + { + if ( set_premaxhealth ) + { + self.premaxhealth = self.maxhealth; + } + if ( self hasperk( "specialty_armorvest" ) ) + { + max_total_health = level.zombie_vars[ "zombie_perk_juggernaut_health" ]; + } + else + { + max_total_health = 100; + } + } + else + { + if ( perk == "health_reboot" ) + { + max_total_health = 100; + } + } + if ( isDefined( max_total_health ) ) + { + if ( self maps/mp/zombies/_zm_pers_upgrades_functions::pers_jugg_active() ) + { + max_total_health += level.pers_jugg_upgrade_health_bonus; + } + self setmaxhealth( max_total_health ); + if ( isDefined( clamp_health_to_max_health ) && clamp_health_to_max_health == 1 ) + { + if ( self.health > self.maxhealth ) + { + self.health = self.maxhealth; + } + } + } +} + +check_player_has_perk( perk ) +{ + self endon( "death" ); + /* +/# + if ( getDvarInt( "zombie_cheat" ) >= 5 ) + { + return; +#/ + } + */ + dist = 16384; + while ( 1 ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( distancesquared( players[ i ].origin, self.origin ) < dist ) + { + if ( !players[ i ] hasperk( perk ) && !players[ i ] has_perk_paused( perk ) && !players[ i ] in_revive_trigger() && !is_equipment_that_blocks_purchase( players[ i ] getcurrentweapon() ) && !players[ i ] hacker_active() ) + { + self setinvisibletoplayer( players[ i ], 0 ); + i++; + continue; + } + else + { + self setinvisibletoplayer( players[ i ], 1 ); + } + } + i++; + } + wait 0.1; + } +} + +vending_set_hintstring( perk ) +{ + switch( perk ) + { + case "specialty_armorvest": + case "specialty_armorvest_upgrade": + break; + } +} + +perk_think( perk ) +{ +/* +/# + if ( getDvarInt( "zombie_cheat" ) >= 5 ) + { + if ( isDefined( self.perk_hud[ perk ] ) ) + { + return; +#/ + } + } +*/ + perk_str = perk + "_stop"; + result = self waittill_any_return( "fake_death", "death", "player_downed", perk_str ); + do_retain = 1; + if ( use_solo_revive() && perk == "specialty_quickrevive" ) + { + do_retain = 0; + } + if ( do_retain ) + { + if ( isDefined( self._retain_perks ) && self._retain_perks ) + { + return; + } + else + { + if ( isDefined( self._retain_perks_array ) && isDefined( self._retain_perks_array[ perk ] ) && self._retain_perks_array[ perk ] ) + { + return; + } + } + } + self unsetperk( perk ); + self.num_perks--; + + switch( perk ) + { + case "specialty_armorvest": + self setmaxhealth( 100 ); + break; + case "specialty_additionalprimaryweapon": + if ( result == perk_str ) + { + self maps/mp/zombies/_zm::take_additionalprimaryweapon(); + } + break; + case "specialty_deadshot": + if ( isDefined( level.disable_deadshot_clientfield ) && !level.disable_deadshot_clientfield ) + { + self setclientfieldtoplayer( "deadshot_perk", 0 ); + } + break; + case "specialty_deadshot_upgrade": + if ( isDefined( level.disable_deadshot_clientfield ) && !level.disable_deadshot_clientfield ) + { + self setclientfieldtoplayer( "deadshot_perk", 0 ); + } + break; + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].player_thread_take ) ) + { + self thread [[ level._custom_perks[ perk ].player_thread_take ]](); + } + self set_perk_clientfield( perk, 0 ); + self.perk_purchased = undefined; + if ( isDefined( level.perk_lost_func ) ) + { + self [[ level.perk_lost_func ]]( perk ); + } + if ( isDefined( self.perks_active ) && isinarray( self.perks_active, perk ) ) + { + arrayremovevalue( self.perks_active, perk, 0 ); + } + self notify( "perk_lost" ); +} + +set_perk_clientfield( perk, state ) +{ + switch( perk ) + { + case "specialty_additionalprimaryweapon": + self setclientfieldtoplayer( "perk_additional_primary_weapon", state ); + break; + case "specialty_deadshot": + self setclientfieldtoplayer( "perk_dead_shot", state ); + break; + case "specialty_flakjacket": + self setclientfieldtoplayer( "perk_dive_to_nuke", state ); + break; + case "specialty_rof": + self setclientfieldtoplayer( "perk_double_tap", state ); + break; + case "specialty_armorvest": + self setclientfieldtoplayer( "perk_juggernaut", state ); + break; + case "specialty_longersprint": + self setclientfieldtoplayer( "perk_marathon", state ); + break; + case "specialty_quickrevive": + self setclientfieldtoplayer( "perk_quick_revive", state ); + break; + case "specialty_fastreload": + self setclientfieldtoplayer( "perk_sleight_of_hand", state ); + break; + case "specialty_scavenger": + self setclientfieldtoplayer( "perk_tombstone", state ); + break; + case "specialty_finalstand": + self setclientfieldtoplayer( "perk_chugabud", state ); + break; + case default: + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].clientfield_set ) ) + { + self [[ level._custom_perks[ perk ].clientfield_set ]]( state ); + } + } +} + +perk_hud_destroy( perk ) +{ + self.perk_hud[ perk ] destroy_hud(); +} + +perk_hud_grey( perk, grey_on_off ) +{ + if ( grey_on_off ) + { + self.perk_hud[ perk ].alpha = 0.3; + } + else + { + self.perk_hud[ perk ].alpha = 1; + } +} + +perk_hud_flash() +{ + self endon( "death" ); + self.flash = 1; + self scaleovertime( 0.05, 32, 32 ); + wait 0.3; + self scaleovertime( 0.05, 24, 24 ); + wait 0.3; + self.flash = 0; +} + +perk_flash_audio( perk ) +{ + alias = undefined; + switch( perk ) + { + case "specialty_armorvest": + alias = "zmb_hud_flash_jugga"; + break; + case "specialty_quickrevive": + alias = "zmb_hud_flash_revive"; + break; + case "specialty_fastreload": + alias = "zmb_hud_flash_speed"; + break; + case "specialty_longersprint": + alias = "zmb_hud_flash_stamina"; + break; + case "specialty_flakjacket": + alias = "zmb_hud_flash_phd"; + break; + case "specialty_deadshot": + alias = "zmb_hud_flash_deadshot"; + break; + case "specialty_additionalprimaryweapon": + alias = "zmb_hud_flash_additionalprimaryweapon"; + break; + } + if ( isDefined( alias ) ) + { + self playlocalsound( alias ); + } +} + +perk_hud_start_flash( perk ) +{ + if ( self hasperk( perk ) && isDefined( self.perk_hud ) ) + { + hud = self.perk_hud[ perk ]; + if ( isDefined( hud ) ) + { + if ( isDefined( hud.flash ) && !hud.flash ) + { + hud thread perk_hud_flash(); + self thread perk_flash_audio( perk ); + } + } + } +} + +perk_hud_stop_flash( perk, taken ) +{ + if ( self hasperk( perk ) && isDefined( self.perk_hud ) ) + { + hud = self.perk_hud[ perk ]; + if ( isDefined( hud ) ) + { + hud.flash = undefined; + if ( isDefined( taken ) ) + { + hud notify( "stop_flash_perk" ); + } + } + } +} + +perk_give_bottle_begin( perk ) +{ + self increment_is_drinking(); + self disable_player_move_states( 1 ); + gun = self getcurrentweapon(); + weapon = ""; + switch( perk ) + { + case " _upgrade": + case "specialty_armorvest": + weapon = level.machine_assets[ "juggernog" ].weapon; + break; + case "specialty_quickrevive": + case "specialty_quickrevive_upgrade": + weapon = level.machine_assets[ "revive" ].weapon; + break; + case "specialty_fastreload": + case "specialty_fastreload_upgrade": + weapon = level.machine_assets[ "speedcola" ].weapon; + break; + case "specialty_rof": + case "specialty_rof_upgrade": + weapon = level.machine_assets[ "doubletap" ].weapon; + break; + case "specialty_longersprint": + case "specialty_longersprint_upgrade": + weapon = level.machine_assets[ "marathon" ].weapon; + break; + case "specialty_flakjacket": + case "specialty_flakjacket_upgrade": + weapon = level.machine_assets[ "divetonuke" ].weapon; + break; + case "specialty_deadshot": + case "specialty_deadshot_upgrade": + weapon = level.machine_assets[ "deadshot" ].weapon; + break; + case "specialty_additionalprimaryweapon": + case "specialty_additionalprimaryweapon_upgrade": + weapon = level.machine_assets[ "additionalprimaryweapon" ].weapon; + break; + case "specialty_scavenger": + case "specialty_scavenger_upgrade": + weapon = level.machine_assets[ "tombstone" ].weapon; + break; + case "specialty_finalstand": + case "specialty_finalstand_upgrade": + weapon = level.machine_assets[ "whoswho" ].weapon; + break; + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].perk_bottle ) ) + { + weapon = level._custom_perks[ perk ].perk_bottle; + } + self giveweapon( weapon ); + self switchtoweapon( weapon ); + return gun; +} + +perk_give_bottle_end( gun, perk ) +{ + self endon( "perk_abort_drinking" ); + /* +/# + assert( !is_zombie_perk_bottle( gun ) ); +#/ +/# + assert( gun != level.revive_tool ); +#/ + */ + self enable_player_move_states(); + weapon = ""; + switch( perk ) + { + case "specialty_rof": + case "specialty_rof_upgrade": + weapon = level.machine_assets[ "doubletap" ].weapon; + break; + case "specialty_longersprint": + case "specialty_longersprint_upgrade": + weapon = level.machine_assets[ "marathon" ].weapon; + break; + case "specialty_flakjacket": + case "specialty_flakjacket_upgrade": + weapon = level.machine_assets[ "divetonuke" ].weapon; + break; + case "specialty_armorvest": + case "specialty_armorvest_upgrade": + weapon = level.machine_assets[ "juggernog" ].weapon; + self.jugg_used = 1; + break; + case "specialty_quickrevive": + case "specialty_quickrevive_upgrade": + weapon = level.machine_assets[ "revive" ].weapon; + break; + case "specialty_fastreload": + case "specialty_fastreload_upgrade": + weapon = level.machine_assets[ "speedcola" ].weapon; + self.speed_used = 1; + break; + case "specialty_deadshot": + case "specialty_deadshot_upgrade": + weapon = level.machine_assets[ "deadshot" ].weapon; + break; + case "specialty_additionalprimaryweapon": + case "specialty_additionalprimaryweapon_upgrade": + weapon = level.machine_assets[ "additionalprimaryweapon" ].weapon; + break; + case "specialty_scavenger": + case "specialty_scavenger_upgrade": + weapon = level.machine_assets[ "tombstone" ].weapon; + break; + case "specialty_finalstand": + case "specialty_finalstand_upgrade": + weapon = level.machine_assets[ "whoswho" ].weapon; + break; + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].perk_bottle ) ) + { + weapon = level._custom_perks[ perk ].perk_bottle; + } + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() || isDefined( self.intermission ) && self.intermission ) + { + self takeweapon( weapon ); + return; + } + self takeweapon( weapon ); + if ( self is_multiple_drinking() ) + { + self decrement_is_drinking(); + return; + } + else if ( gun != "none" && !is_placeable_mine( gun ) && !is_equipment_that_blocks_purchase( gun ) ) + { + self switchtoweapon( gun ); + if ( is_melee_weapon( gun ) ) + { + self decrement_is_drinking(); + return; + } + } + else + { + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } + self waittill( "weapon_change_complete" ); + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() && isDefined( self.intermission ) && !self.intermission ) + { + self decrement_is_drinking(); + } +} + +perk_abort_drinking( post_delay ) +{ + if ( self.is_drinking ) + { + self notify( "perk_abort_drinking" ); + self decrement_is_drinking(); + self enable_player_move_states(); + if ( isDefined( post_delay ) ) + { + wait post_delay; + } + } +} + +give_random_perk() +{ + random_perk = undefined; + vending_triggers = getentarray( "zombie_vending", "targetname" ); + perks = []; + i = 0; + while ( i < vending_triggers.size ) + { + perk = vending_triggers[ i ].script_noteworthy; + if ( isDefined( self.perk_purchased ) && self.perk_purchased == perk ) + { + i++; + continue; + } + else + { + if ( perk == "specialty_weapupgrade" ) + { + i++; + continue; + } + else + { + if ( !self hasperk( perk ) && !self has_perk_paused( perk ) ) + { + perks[ perks.size ] = perk; + } + } + } + i++; + } + if ( perks.size > 0 ) + { + perks = array_randomize( perks ); + random_perk = perks[ 0 ]; + self give_perk( random_perk ); + } + else + { + self playsoundtoplayer( level.zmb_laugh_alias, self ); + } + return random_perk; +} + +lose_random_perk() +{ + vending_triggers = getentarray( "zombie_vending", "targetname" ); + perks = []; + i = 0; + while ( i < vending_triggers.size ) + { + perk = vending_triggers[ i ].script_noteworthy; + if ( isDefined( self.perk_purchased ) && self.perk_purchased == perk ) + { + i++; + continue; + } + else + { + if ( self hasperk( perk ) || self has_perk_paused( perk ) ) + { + perks[ perks.size ] = perk; + } + } + i++; + } + if ( perks.size > 0 ) + { + perks = array_randomize( perks ); + perk = perks[ 0 ]; + perk_str = perk + "_stop"; + self notify( perk_str ); + if ( use_solo_revive() && perk == "specialty_quickrevive" ) + { + self.lives--; + + } + } +} + +update_perk_hud() +{ + while ( isDefined( self.perk_hud ) ) + { + keys = getarraykeys( self.perk_hud ); + i = 0; + while ( i < self.perk_hud.size ) + { + self.perk_hud[ keys[ i ] ].x = i * 30; + i++; + } + } +} + +quantum_bomb_give_nearest_perk_validation( position ) +{ + vending_triggers = getentarray( "zombie_vending", "targetname" ); + range_squared = 32400; + i = 0; + while ( i < vending_triggers.size ) + { + if ( distancesquared( vending_triggers[ i ].origin, position ) < range_squared ) + { + return 1; + } + i++; + } + return 0; +} + +quantum_bomb_give_nearest_perk_result( position ) +{ + [[ level.quantum_bomb_play_mystery_effect_func ]]( position ); + vending_triggers = getentarray( "zombie_vending", "targetname" ); + nearest = 0; + i = 1; + while ( i < vending_triggers.size ) + { + if ( distancesquared( vending_triggers[ i ].origin, position ) < distancesquared( vending_triggers[ nearest ].origin, position ) ) + { + nearest = i; + } + i++; + } + players = get_players(); + perk = vending_triggers[ nearest ].script_noteworthy; + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( player.sessionstate == "spectator" || player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + i++; + continue; + } + else + { + if ( !player hasperk( perk ) && isDefined( player.perk_purchased ) && player.perk_purchased != perk && randomint( 5 ) ) + { + if ( player == self ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + } + player give_perk( perk ); + player [[ level.quantum_bomb_play_player_effect_func ]](); + } + } + i++; + } +} + +perk_pause( perk ) +{ + if ( perk == "Pack_A_Punch" || perk == "specialty_weapupgrade" ) + { + return; + } + j = 0; + while ( j < get_players().size ) + { + player = get_players()[ j ]; + if ( !isDefined( player.disabled_perks ) ) + { + player.disabled_perks = []; + } + if ( isDefined( player.disabled_perks[ perk ] ) && !player.disabled_perks[ perk ] ) + { + player.disabled_perks[ perk ] = player hasperk( perk ); + } + if ( player.disabled_perks[ perk ] ) + { + player unsetperk( perk ); + player set_perk_clientfield( perk, 2 ); + if ( perk == "specialty_armorvest" || perk == "specialty_armorvest_upgrade" ) + { + player setmaxhealth( player.premaxhealth ); + if ( player.health > player.maxhealth ) + { + player.health = player.maxhealth; + } + } + if ( perk == "specialty_additionalprimaryweapon" || perk == "specialty_additionalprimaryweapon_upgrade" ) + { + player maps/mp/zombies/_zm::take_additionalprimaryweapon(); + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].player_thread_take ) ) + { + player thread [[ level._custom_perks[ perk ].player_thread_take ]](); + } + /* +/# + println( " ZM PERKS " + player.name + " paused perk " + perk + "\n" ); +#/ + */ + } + j++; + } +} + +perk_unpause( perk ) +{ + if ( !isDefined( perk ) ) + { + return; + } + if ( perk == "Pack_A_Punch" ) + { + return; + } + j = 0; + while ( j < get_players().size ) + { + player = get_players()[ j ]; + if ( isDefined( player.disabled_perks ) && isDefined( player.disabled_perks[ perk ] ) && player.disabled_perks[ perk ] ) + { + player.disabled_perks[ perk ] = 0; + player set_perk_clientfield( perk, 1 ); + player setperk( perk ); + /* +/# + println( " ZM PERKS " + player.name + " unpaused perk " + perk + "\n" ); +#/ + */ + if ( issubstr( perk, "specialty_scavenger" ) ) + { + player.hasperkspecialtytombstone = 1; + } + player perk_set_max_health_if_jugg( perk, 0, 0 ); + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].player_thread_give ) ) + { + player thread [[ level._custom_perks[ perk ].player_thread_give ]](); + } + } + j++; + } +} + +perk_pause_all_perks() +{ + vending_triggers = getentarray( "zombie_vending", "targetname" ); + _a3378 = vending_triggers; + _k3378 = getFirstArrayKey( _a3378 ); + while ( isDefined( _k3378 ) ) + { + trigger = _a3378[ _k3378 ]; + maps/mp/zombies/_zm_perks::perk_pause( trigger.script_noteworthy ); + _k3378 = getNextArrayKey( _a3378, _k3378 ); + } +} + +perk_unpause_all_perks() +{ + vending_triggers = getentarray( "zombie_vending", "targetname" ); + _a3388 = vending_triggers; + _k3388 = getFirstArrayKey( _a3388 ); + while ( isDefined( _k3388 ) ) + { + trigger = _a3388[ _k3388 ]; + maps/mp/zombies/_zm_perks::perk_unpause( trigger.script_noteworthy ); + _k3388 = getNextArrayKey( _a3388, _k3388 ); + } +} + +has_perk_paused( perk ) +{ + if ( isDefined( self.disabled_perks ) && isDefined( self.disabled_perks[ perk ] ) && self.disabled_perks[ perk ] ) + { + return 1; + } + return 0; +} + +getvendingmachinenotify() +{ + if ( !isDefined( self ) ) + { + return ""; + } + switch( self.script_noteworthy ) + { + case "specialty_armorvest": + case "specialty_armorvest_upgrade": + return "juggernog"; + case "specialty_quickrevive": + case "specialty_quickrevive_upgrade": + return "revive"; + case "specialty_fastreload": + case "specialty_fastreload_upgrade": + return "sleight"; + case "specialty_rof": + case "specialty_rof_upgrade": + return "doubletap"; + case "specialty_longersprint": + case "specialty_longersprint_upgrade": + return "marathon"; + case "specialty_flakjacket": + case "specialty_flakjacket_upgrade": + return "divetonuke"; + case "specialty_deadshot": + case "specialty_deadshot_upgrade": + return "deadshot"; + case "specialty_additionalprimaryweapon": + case "specialty_additionalprimaryweapon_upgrade": + return "additionalprimaryweapon"; + case "specialty_scavenger": + case "specialty_scavenger_upgrade": + return "tombstone"; + case "specialty_finalstand": + case "specialty_finalstand_upgrade": + return "chugabud"; + case "specialty_weapupgrade": + return "Pack_A_Punch"; + } + str_perk = undefined; + if ( isDefined( level._custom_perks[ self.script_noteworthy ] ) && isDefined( isDefined( level._custom_perks[ self.script_noteworthy ].alias ) ) ) + { + str_perk = level._custom_perks[ self.script_noteworthy ].alias; + } + return str_perk; +} + +perk_machine_removal( machine, replacement_model ) +{ + if ( !isDefined( machine ) ) + { + return; + } + trig = getent( machine, "script_noteworthy" ); + machine_model = undefined; + if ( isDefined( trig ) ) + { + trig notify( "warning_dialog" ); + while ( isDefined( trig.target ) ) + { + parts = getentarray( trig.target, "targetname" ); + i = 0; + while ( i < parts.size ) + { + if ( isDefined( parts[ i ].classname ) && parts[ i ].classname == "script_model" ) + { + machine_model = parts[ i ]; + i++; + continue; + } + else + { + if ( parts[ i ].script_noteworthy ) + { + if ( isDefined( parts[ i ].script_noteworthy == "clip" ) ) + { + model_clip = parts[ i ]; + } + i++; + continue; + } + else + { + parts[ i ] delete(); + } + } + i++; + } + } + if ( isDefined( replacement_model ) && isDefined( machine_model ) ) + { + machine_model setmodel( replacement_model ); + } + else + { + if ( !isDefined( replacement_model ) && isDefined( machine_model ) ) + { + machine_model delete(); + if ( isDefined( model_clip ) ) + { + model_clip delete(); + } + if ( isDefined( trig.clip ) ) + { + trig.clip delete(); + } + } + } + if ( isDefined( trig.bump ) ) + { + trig.bump delete(); + } + trig delete(); + } +} + +perk_machine_spawn_init() +{ + 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 + "_perks_" ) + location; + pos = []; + if ( isDefined( level.override_perk_targetname ) ) + { + structs = getstructarray( level.override_perk_targetname, "targetname" ); + } + else + { + structs = getstructarray( "zm_perk_machine", "targetname" ); + } + _a3578 = structs; + _k3578 = getFirstArrayKey( _a3578 ); + while ( isDefined( _k3578 ) ) + { + struct = _a3578[ _k3578 ]; + if ( isDefined( struct.script_string ) ) + { + tokens = strtok( struct.script_string, " " ); + _a3583 = tokens; + _k3583 = getFirstArrayKey( _a3583 ); + while ( isDefined( _k3583 ) ) + { + token = _a3583[ _k3583 ]; + if ( token == match_string ) + { + pos[ pos.size ] = struct; + } + _k3583 = getNextArrayKey( _a3583, _k3583 ); + } + } + else pos[ pos.size ] = struct; + _k3578 = getNextArrayKey( _a3578, _k3578 ); + } + if ( !isDefined( pos ) || pos.size == 0 ) + { + return; + } + precachemodel( "zm_collision_perks1" ); + i = 0; + while ( i < pos.size ) + { + perk = pos[ i ].script_noteworthy; + if ( isDefined( perk ) && isDefined( pos[ i ].model ) ) + { + use_trigger = spawn( "trigger_radius_use", pos[ i ].origin + vectorScale( ( 0, -1, 0 ), 30 ), 0, 40, 70 ); + use_trigger.targetname = "zombie_vending"; + use_trigger.script_noteworthy = perk; + use_trigger triggerignoreteam(); + perk_machine = spawn( "script_model", pos[ i ].origin ); + perk_machine.angles = pos[ i ].angles; + perk_machine setmodel( pos[ i ].model ); + if ( isDefined( level._no_vending_machine_bump_trigs ) && level._no_vending_machine_bump_trigs ) + { + bump_trigger = undefined; + } + else + { + bump_trigger = spawn( "trigger_radius", pos[ i ].origin, 0, 35, 64 ); + bump_trigger.script_activated = 1; + bump_trigger.script_sound = "zmb_perks_bump_bottle"; + bump_trigger.targetname = "audio_bump_trigger"; + if ( perk != "specialty_weapupgrade" ) + { + bump_trigger thread thread_bump_trigger(); + } + } + collision = spawn( "script_model", pos[ i ].origin, 1 ); + collision.angles = pos[ i ].angles; + collision setmodel( "zm_collision_perks1" ); + collision.script_noteworthy = "clip"; + collision disconnectpaths(); + use_trigger.clip = collision; + use_trigger.machine = perk_machine; + use_trigger.bump = bump_trigger; + if ( isDefined( pos[ i ].blocker_model ) ) + { + use_trigger.blocker_model = pos[ i ].blocker_model; + } + if ( isDefined( pos[ i ].script_int ) ) + { + perk_machine.script_int = pos[ i ].script_int; + } + if ( isDefined( pos[ i ].turn_on_notify ) ) + { + perk_machine.turn_on_notify = pos[ i ].turn_on_notify; + } + switch( perk ) + { + case "specialty_quickrevive": + case "specialty_quickrevive_upgrade": + use_trigger.script_sound = "mus_perks_revive_jingle"; + use_trigger.script_string = "revive_perk"; + use_trigger.script_label = "mus_perks_revive_sting"; + use_trigger.target = "vending_revive"; + perk_machine.script_string = "revive_perk"; + perk_machine.targetname = "vending_revive"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "revive_perk"; + } + break; + case "specialty_fastreload": + case "specialty_fastreload_upgrade": + use_trigger.script_sound = "mus_perks_speed_jingle"; + use_trigger.script_string = "speedcola_perk"; + use_trigger.script_label = "mus_perks_speed_sting"; + use_trigger.target = "vending_sleight"; + perk_machine.script_string = "speedcola_perk"; + perk_machine.targetname = "vending_sleight"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "speedcola_perk"; + } + break; + case "specialty_longersprint": + case "specialty_longersprint_upgrade": + use_trigger.script_sound = "mus_perks_stamin_jingle"; + use_trigger.script_string = "marathon_perk"; + use_trigger.script_label = "mus_perks_stamin_sting"; + use_trigger.target = "vending_marathon"; + perk_machine.script_string = "marathon_perk"; + perk_machine.targetname = "vending_marathon"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "marathon_perk"; + } + break; + case "specialty_armorvest": + case "specialty_armorvest_upgrade": + use_trigger.script_sound = "mus_perks_jugganog_jingle"; + use_trigger.script_string = "jugg_perk"; + use_trigger.script_label = "mus_perks_jugganog_sting"; + use_trigger.longjinglewait = 1; + use_trigger.target = "vending_jugg"; + perk_machine.script_string = "jugg_perk"; + perk_machine.targetname = "vending_jugg"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "jugg_perk"; + } + break; + case "specialty_scavenger": + case "specialty_scavenger_upgrade": + use_trigger.script_sound = "mus_perks_tombstone_jingle"; + use_trigger.script_string = "tombstone_perk"; + use_trigger.script_label = "mus_perks_tombstone_sting"; + use_trigger.target = "vending_tombstone"; + perk_machine.script_string = "tombstone_perk"; + perk_machine.targetname = "vending_tombstone"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "tombstone_perk"; + } + break; + case "specialty_rof": + case "specialty_rof_upgrade": + use_trigger.script_sound = "mus_perks_doubletap_jingle"; + use_trigger.script_string = "tap_perk"; + use_trigger.script_label = "mus_perks_doubletap_sting"; + use_trigger.target = "vending_doubletap"; + perk_machine.script_string = "tap_perk"; + perk_machine.targetname = "vending_doubletap"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "tap_perk"; + } + break; + case "specialty_finalstand": + case "specialty_finalstand_upgrade": + use_trigger.script_sound = "mus_perks_whoswho_jingle"; + use_trigger.script_string = "tap_perk"; + use_trigger.script_label = "mus_perks_whoswho_sting"; + use_trigger.target = "vending_chugabud"; + perk_machine.script_string = "tap_perk"; + perk_machine.targetname = "vending_chugabud"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "tap_perk"; + } + break; + case "specialty_additionalprimaryweapon": + case "specialty_additionalprimaryweapon_upgrade": + use_trigger.script_sound = "mus_perks_mulekick_jingle"; + use_trigger.script_string = "tap_perk"; + use_trigger.script_label = "mus_perks_mulekick_sting"; + use_trigger.target = "vending_additionalprimaryweapon"; + perk_machine.script_string = "tap_perk"; + perk_machine.targetname = "vending_additionalprimaryweapon"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "tap_perk"; + } + break; + case "specialty_weapupgrade": + use_trigger.target = "vending_packapunch"; + use_trigger.script_sound = "mus_perks_packa_jingle"; + use_trigger.script_label = "mus_perks_packa_sting"; + use_trigger.longjinglewait = 1; + perk_machine.targetname = "vending_packapunch"; + flag_pos = getstruct( pos[ i ].target, "targetname" ); + if ( isDefined( flag_pos ) ) + { + perk_machine_flag = spawn( "script_model", flag_pos.origin ); + perk_machine_flag.angles = flag_pos.angles; + perk_machine_flag setmodel( flag_pos.model ); + perk_machine_flag.targetname = "pack_flag"; + perk_machine.target = "pack_flag"; + } + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "perks_rattle"; + } + break; + case "specialty_deadshot": + case "specialty_deadshot_upgrade": + use_trigger.script_sound = "mus_perks_deadshot_jingle"; + use_trigger.script_string = "deadshot_perk"; + use_trigger.script_label = "mus_perks_deadshot_sting"; + use_trigger.target = "vending_deadshot"; + perk_machine.script_string = "deadshot_vending"; + perk_machine.targetname = "vending_deadshot_model"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "deadshot_vending"; + } + break; + default: + use_trigger.script_sound = "mus_perks_speed_jingle"; + use_trigger.script_string = "speedcola_perk"; + use_trigger.script_label = "mus_perks_speed_sting"; + use_trigger.target = "vending_sleight"; + perk_machine.script_string = "speedcola_perk"; + perk_machine.targetname = "vending_sleight"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "speedcola_perk"; + } + break; + } + 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 ); + } + } + i++; + } +} + +get_perk_machine_start_state( perk ) +{ + if ( isDefined( level.vending_machines_powered_on_at_start ) && level.vending_machines_powered_on_at_start ) + { + return 1; + } + if ( perk == "specialty_quickrevive" || perk == "specialty_quickrevive_upgrade" ) + { + /* +/# + assert( isDefined( level.revive_machine_is_solo ) ); +#/ + */ + return level.revive_machine_is_solo; + } + return 0; +} + +perks_register_clientfield() +{ + if ( isDefined( level.zombiemode_using_additionalprimaryweapon_perk ) && level.zombiemode_using_additionalprimaryweapon_perk ) + { + registerclientfield( "toplayer", "perk_additional_primary_weapon", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_deadshot_perk ) && level.zombiemode_using_deadshot_perk ) + { + registerclientfield( "toplayer", "perk_dead_shot", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_doubletap_perk ) && level.zombiemode_using_doubletap_perk ) + { + registerclientfield( "toplayer", "perk_double_tap", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_juggernaut_perk ) && level.zombiemode_using_juggernaut_perk ) + { + registerclientfield( "toplayer", "perk_juggernaut", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_marathon_perk ) && level.zombiemode_using_marathon_perk ) + { + registerclientfield( "toplayer", "perk_marathon", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_revive_perk ) && level.zombiemode_using_revive_perk ) + { + registerclientfield( "toplayer", "perk_quick_revive", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_sleightofhand_perk ) && level.zombiemode_using_sleightofhand_perk ) + { + registerclientfield( "toplayer", "perk_sleight_of_hand", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_tombstone_perk ) && level.zombiemode_using_tombstone_perk ) + { + registerclientfield( "toplayer", "perk_tombstone", 1, 2, "int" ); + } + if ( isDefined( level.zombiemode_using_perk_intro_fx ) && level.zombiemode_using_perk_intro_fx ) + { + registerclientfield( "scriptmover", "clientfield_perk_intro_fx", 1000, 1, "int" ); + } + if ( isDefined( level.zombiemode_using_chugabud_perk ) && level.zombiemode_using_chugabud_perk ) + { + registerclientfield( "toplayer", "perk_chugabud", 1000, 1, "int" ); + } + while ( isDefined( level._custom_perks ) ) + { + a_keys = getarraykeys( level._custom_perks ); + i = 0; + while ( i < a_keys.size ) + { + if ( isDefined( level._custom_perks[ a_keys[ i ] ].clientfield_register ) ) + { + level [[ level._custom_perks[ a_keys[ i ] ].clientfield_register ]](); + } + i++; + } + } +} + +thread_bump_trigger() +{ + for ( ;; ) + { + self waittill( "trigger", trigplayer ); + trigplayer playsound( self.script_sound ); + while ( is_player_valid( trigplayer ) && trigplayer istouching( self ) ) + { + wait 0.5; + } + } +} + +reenable_quickrevive( machine_clip, solo_mode ) +{ + if ( isDefined( level.revive_machine_spawned ) && !is_true( level.revive_machine_spawned ) ) + { + return; + } + wait 0.1; + power_state = 0; + if ( is_true( solo_mode ) ) + { + power_state = 1; + should_pause = 1; + players = get_players(); + _a3918 = players; + _k3918 = getFirstArrayKey( _a3918 ); + while ( isDefined( _k3918 ) ) + { + player = _a3918[ _k3918 ]; + if ( isDefined( player.lives ) && player.lives > 0 && power_state ) + { + should_pause = 0; + } + else + { + if ( isDefined( player.lives ) && player.lives < 1 ) + { + should_pause = 1; + } + } + _k3918 = getNextArrayKey( _a3918, _k3918 ); + } + if ( should_pause ) + { + perk_pause( "specialty_quickrevive" ); + } + else + { + perk_unpause( "specialty_quickrevive" ); + } + if ( isDefined( level.solo_revive_init ) && level.solo_revive_init && flag( "solo_revive" ) ) + { + disable_quickrevive( machine_clip ); + return; + } + update_quickrevive_power_state( 1 ); + unhide_quickrevive(); + restart_quickrevive(); + level notify( "revive_off" ); + wait 0.1; + level notify( "stop_quickrevive_logic" ); + } + else + { + if ( isDefined( level._dont_unhide_quickervive_on_hotjoin ) && !level._dont_unhide_quickervive_on_hotjoin ) + { + unhide_quickrevive(); + level notify( "revive_off" ); + wait 0.1; + } + level notify( "revive_hide" ); + level notify( "stop_quickrevive_logic" ); + restart_quickrevive(); + if ( flag( "power_on" ) ) + { + power_state = 1; + } + update_quickrevive_power_state( power_state ); + } + level thread turn_revive_on(); + if ( power_state ) + { + perk_unpause( "specialty_quickrevive" ); + level notify( "revive_on" ); + wait 0.1; + level notify( "specialty_quickrevive_power_on" ); + } + else + { + perk_pause( "specialty_quickrevive" ); + } + if ( !is_true( solo_mode ) ) + { + return; + } + should_pause = 1; + players = get_players(); + _a3996 = players; + _k3996 = getFirstArrayKey( _a3996 ); + while ( isDefined( _k3996 ) ) + { + player = _a3996[ _k3996 ]; + if ( !is_player_valid( player ) ) + { + } + else if ( player hasperk( "specialty_quickrevive" ) ) + { + if ( !isDefined( player.lives ) ) + { + player.lives = 0; + } + if ( !isDefined( level.solo_lives_given ) ) + { + level.solo_lives_given = 0; + } + level.solo_lives_given++; + player.lives++; + if ( isDefined( player.lives ) && player.lives > 0 && power_state ) + { + should_pause = 0; + break; + } + else + { + should_pause = 1; + } + } + _k3996 = getNextArrayKey( _a3996, _k3996 ); + } + if ( should_pause ) + { + perk_pause( "specialty_quickrevive" ); + } + else + { + perk_unpause( "specialty_quickrevive" ); + } +} + +update_quickrevive_power_state( poweron ) +{ + _a4034 = level.powered_items; + _k4034 = getFirstArrayKey( _a4034 ); + while ( isDefined( _k4034 ) ) + { + item = _a4034[ _k4034 ]; + if ( isDefined( item.target ) && isDefined( item.target.script_noteworthy ) && item.target.script_noteworthy == "specialty_quickrevive" ) + { + if ( item.power && !poweron ) + { + if ( !isDefined( item.powered_count ) ) + { + item.powered_count = 0; + } + else + { + if ( item.powered_count > 0 ) + { + item.powered_count--; + + } + } + } + else + { + if ( !item.power && poweron ) + { + if ( !isDefined( item.powered_count ) ) + { + item.powered_count = 0; + } + item.powered_count++; + } + } + if ( !isDefined( item.depowered_count ) ) + { + item.depowered_count = 0; + } + item.power = poweron; + } + _k4034 = getNextArrayKey( _a4034, _k4034 ); + } +} + +restart_quickrevive() +{ + triggers = getentarray( "zombie_vending", "targetname" ); + _a4074 = triggers; + _k4074 = getFirstArrayKey( _a4074 ); + while ( isDefined( _k4074 ) ) + { + trigger = _a4074[ _k4074 ]; + if ( !isDefined( trigger.script_noteworthy ) ) + { + } + else + { + if ( trigger.script_noteworthy == "specialty_quickrevive" || trigger.script_noteworthy == "specialty_quickrevive_upgrade" ) + { + trigger notify( "stop_quickrevive_logic" ); + trigger thread vending_trigger_think(); + trigger trigger_on(); + } + } + _k4074 = getNextArrayKey( _a4074, _k4074 ); + } +} + +disable_quickrevive( machine_clip ) +{ + if ( is_true( level.solo_revive_init ) && flag( "solo_revive" ) && isDefined( level.quick_revive_machine ) ) + { + triggers = getentarray( "zombie_vending", "targetname" ); + _a4096 = triggers; + _k4096 = getFirstArrayKey( _a4096 ); + while ( isDefined( _k4096 ) ) + { + trigger = _a4096[ _k4096 ]; + if ( !isDefined( trigger.script_noteworthy ) ) + { + } + else + { + if ( trigger.script_noteworthy == "specialty_quickrevive" || trigger.script_noteworthy == "specialty_quickrevive_upgrade" ) + { + trigger trigger_off(); + } + } + _k4096 = getNextArrayKey( _a4096, _k4096 ); + } + _a4108 = level.powered_items; + _k4108 = getFirstArrayKey( _a4108 ); + while ( isDefined( _k4108 ) ) + { + item = _a4108[ _k4108 ]; + if ( isDefined( item.target ) && isDefined( item.target.script_noteworthy ) && item.target.script_noteworthy == "specialty_quickrevive" ) + { + item.power = 1; + item.self_powered = 1; + } + _k4108 = getNextArrayKey( _a4108, _k4108 ); + } + if ( isDefined( level.quick_revive_machine.original_pos ) ) + { + level.quick_revive_default_origin = level.quick_revive_machine.original_pos; + level.quick_revive_default_angles = level.quick_revive_machine.original_angles; + } + move_org = level.quick_revive_default_origin; + if ( isDefined( level.quick_revive_linked_ent ) ) + { + move_org = level.quick_revive_linked_ent.origin; + if ( isDefined( level.quick_revive_linked_ent_offset ) ) + { + move_org += level.quick_revive_linked_ent_offset; + } + level.quick_revive_machine unlink(); + } + level.quick_revive_machine moveto( move_org + vectorScale( ( 0, -1, 0 ), 40 ), 3 ); + direction = level.quick_revive_machine.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 ); + } + } + level.quick_revive_machine vibrate( direction, 10, 0.5, 4 ); + level.quick_revive_machine waittill( "movedone" ); + level.quick_revive_machine hide(); + level.quick_revive_machine.ishidden = 1; + if ( isDefined( level.quick_revive_machine_clip ) ) + { + level.quick_revive_machine_clip connectpaths(); + level.quick_revive_machine_clip trigger_off(); + } + playfx( level._effect[ "poltergeist" ], level.quick_revive_machine.origin ); + if ( isDefined( level.quick_revive_trigger ) && isDefined( level.quick_revive_trigger.blocker_model ) ) + { + level.quick_revive_trigger.blocker_model show(); + } + level notify( "revive_hide" ); + } +} + +unhide_quickrevive() +{ + while ( players_are_in_perk_area( level.quick_revive_machine ) ) + { + wait 0.1; + } + if ( isDefined( level.quick_revive_machine_clip ) ) + { + level.quick_revive_machine_clip trigger_on(); + level.quick_revive_machine_clip disconnectpaths(); + } + if ( isDefined( level.quick_revive_final_pos ) ) + { + level.quick_revive_machine.origin = level.quick_revive_final_pos; + } + playfx( level._effect[ "poltergeist" ], level.quick_revive_machine.origin ); + if ( isDefined( level.quick_revive_trigger ) && isDefined( level.quick_revive_trigger.blocker_model ) ) + { + level.quick_revive_trigger.blocker_model hide(); + } + level.quick_revive_machine show(); + if ( isDefined( level.quick_revive_machine.original_pos ) ) + { + level.quick_revive_default_origin = level.quick_revive_machine.original_pos; + level.quick_revive_default_angles = level.quick_revive_machine.original_angles; + } + direction = level.quick_revive_machine.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 ); + } + } + org = level.quick_revive_default_origin; + if ( isDefined( level.quick_revive_linked_ent ) ) + { + org = level.quick_revive_linked_ent.origin; + if ( isDefined( level.quick_revive_linked_ent_offset ) ) + { + org += level.quick_revive_linked_ent_offset; + } + } + if ( isDefined( level.quick_revive_linked_ent_moves ) && !level.quick_revive_linked_ent_moves && level.quick_revive_machine.origin != org ) + { + level.quick_revive_machine moveto( org, 3 ); + level.quick_revive_machine vibrate( direction, 10, 0.5, 2.9 ); + level.quick_revive_machine waittill( "movedone" ); + level.quick_revive_machine.angles = level.quick_revive_default_angles; + } + else + { + if ( isDefined( level.quick_revive_linked_ent ) ) + { + org = level.quick_revive_linked_ent.origin; + if ( isDefined( level.quick_revive_linked_ent_offset ) ) + { + org += level.quick_revive_linked_ent_offset; + } + level.quick_revive_machine.origin = org; + } + level.quick_revive_machine vibrate( vectorScale( ( 0, -1, 0 ), 100 ), 0.3, 0.4, 3 ); + } + if ( isDefined( level.quick_revive_linked_ent ) ) + { + level.quick_revive_machine linkto( level.quick_revive_linked_ent ); + } + level.quick_revive_machine.ishidden = 0; +} + +players_are_in_perk_area( perk_machine ) +{ + perk_area_origin = level.quick_revive_default_origin; + if ( isDefined( perk_machine._linked_ent ) ) + { + perk_area_origin = perk_machine._linked_ent.origin; + if ( isDefined( perk_machine._linked_ent_offset ) ) + { + perk_area_origin += perk_machine._linked_ent_offset; + } + } + in_area = 0; + players = get_players(); + dist_check = 9216; + _a4286 = players; + _k4286 = getFirstArrayKey( _a4286 ); + while ( isDefined( _k4286 ) ) + { + player = _a4286[ _k4286 ]; + if ( distancesquared( player.origin, perk_area_origin ) < dist_check ) + { + return 1; + } + _k4286 = getNextArrayKey( _a4286, _k4286 ); + } + return 0; +} + +perk_hostmigration() +{ + level endon( "end_game" ); + level notify( "perk_hostmigration" ); + level endon( "perk_hostmigration" ); + while ( 1 ) + { + level waittill( "host_migration_end" ); + jug = getentarray( "vending_jugg", "targetname" ); + tap = getentarray( "vending_doubletap", "targetname" ); + mar = getentarray( "vending_marathon", "targetname" ); + deadshot = getentarray( "vending_deadshot", "targetname" ); + tomb = getentarray( "vending_tombstone", "targetname" ); + extraweap = getentarray( "vending_additionalprimaryweapon", "targetname" ); + sleight = getentarray( "vending_sleight", "targetname" ); + revive = getentarray( "vending_revive", "targetname" ); + chugabud = getentarray( "vending_chugabud", "targetname" ); + _a4321 = jug; + _k4321 = getFirstArrayKey( _a4321 ); + while ( isDefined( _k4321 ) ) + { + perk = _a4321[ _k4321 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "juggernog" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "jugger_light" ); + } + _k4321 = getNextArrayKey( _a4321, _k4321 ); + } + _a4330 = tap; + _k4330 = getFirstArrayKey( _a4330 ); + while ( isDefined( _k4330 ) ) + { + perk = _a4330[ _k4330 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "doubletap" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "doubletap_light" ); + } + _k4330 = getNextArrayKey( _a4330, _k4330 ); + } + _a4339 = mar; + _k4339 = getFirstArrayKey( _a4339 ); + while ( isDefined( _k4339 ) ) + { + perk = _a4339[ _k4339 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "marathon" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "marathon_light" ); + } + _k4339 = getNextArrayKey( _a4339, _k4339 ); + } + _a4348 = deadshot; + _k4348 = getFirstArrayKey( _a4348 ); + while ( isDefined( _k4348 ) ) + { + perk = _a4348[ _k4348 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "deadshot" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "deadshot_light" ); + } + _k4348 = getNextArrayKey( _a4348, _k4348 ); + } + _a4357 = tomb; + _k4357 = getFirstArrayKey( _a4357 ); + while ( isDefined( _k4357 ) ) + { + perk = _a4357[ _k4357 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "tombstone" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "tombstone_light" ); + } + _k4357 = getNextArrayKey( _a4357, _k4357 ); + } + _a4366 = extraweap; + _k4366 = getFirstArrayKey( _a4366 ); + while ( isDefined( _k4366 ) ) + { + perk = _a4366[ _k4366 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "additionalprimaryweapon" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "additionalprimaryweapon_light" ); + } + _k4366 = getNextArrayKey( _a4366, _k4366 ); + } + _a4375 = sleight; + _k4375 = getFirstArrayKey( _a4375 ); + while ( isDefined( _k4375 ) ) + { + perk = _a4375[ _k4375 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "speedcola" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "sleight_light" ); + } + _k4375 = getNextArrayKey( _a4375, _k4375 ); + } + _a4384 = revive; + _k4384 = getFirstArrayKey( _a4384 ); + while ( isDefined( _k4384 ) ) + { + perk = _a4384[ _k4384 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "revive" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "revive_light" ); + } + _k4384 = getNextArrayKey( _a4384, _k4384 ); + } + _a4393 = chugabud; + _k4393 = getFirstArrayKey( _a4393 ); + while ( isDefined( _k4393 ) ) + { + perk = _a4393[ _k4393 ]; + if ( isDefined( perk.model ) && perk.model == level.machine_assets[ "revive" ].on_model ) + { + perk perk_fx( undefined, 1 ); + perk thread perk_fx( "tombstone_light" ); + } + _k4393 = getNextArrayKey( _a4393, _k4393 ); + } + while ( level._custom_perks.size > 0 ) + { + a_keys = getarraykeys( level._custom_perks ); + i = 0; + while ( i < a_keys.size ) + { + if ( isDefined( level._custom_perks[ a_keys[ i ] ].host_migration_func ) ) + { + level thread [[ level._custom_perks[ a_keys[ i ] ].host_migration_func ]](); + } + i++; + } + } + } +} + +get_perk_array( ignore_chugabud ) +{ + perk_array = []; + if ( self hasperk( "specialty_armorvest" ) ) + { + perk_array[ perk_array.size ] = "specialty_armorvest"; + } + if ( self hasperk( "specialty_deadshot" ) ) + { + perk_array[ perk_array.size ] = "specialty_deadshot"; + } + if ( self hasperk( "specialty_fastreload" ) ) + { + perk_array[ perk_array.size ] = "specialty_fastreload"; + } + if ( self hasperk( "specialty_flakjacket" ) ) + { + perk_array[ perk_array.size ] = "specialty_flakjacket"; + } + if ( self hasperk( "specialty_longersprint" ) ) + { + perk_array[ perk_array.size ] = "specialty_longersprint"; + } + if ( self hasperk( "specialty_quickrevive" ) ) + { + perk_array[ perk_array.size ] = "specialty_quickrevive"; + } + if ( self hasperk( "specialty_rof" ) ) + { + perk_array[ perk_array.size ] = "specialty_rof"; + } + if ( self hasperk( "specialty_additionalprimaryweapon" ) ) + { + perk_array[ perk_array.size ] = "specialty_additionalprimaryweapon"; + } + if ( !isDefined( ignore_chugabud ) || ignore_chugabud == 0 ) + { + if ( self hasperk( "specialty_finalstand" ) ) + { + perk_array[ perk_array.size ] = "specialty_finalstand"; + } + } + while ( level._custom_perks.size > 0 ) + { + a_keys = getarraykeys( level._custom_perks ); + i = 0; + while ( i < a_keys.size ) + { + if ( self hasperk( a_keys[ i ] ) ) + { + perk_array[ perk_array.size ] = a_keys[ i ]; + } + i++; + } + } + return perk_array; +} + +initialize_custom_perk_arrays() +{ + if ( !isDefined( level._custom_perks ) ) + { + level._custom_perks = []; + } +} + +register_perk_basic_info( str_perk, str_alias, n_perk_cost, str_hint_string, str_perk_bottle_weapon ) +{ +/* +/# + assert( isDefined( str_perk ), "str_perk is a required argument for register_perk_basic_info!" ); +#/ +/# + assert( isDefined( str_alias ), "str_alias is a required argument for register_perk_basic_info!" ); +#/ +/# + assert( isDefined( n_perk_cost ), "n_perk_cost is a required argument for register_perk_basic_info!" ); +#/ +/# + assert( isDefined( str_hint_string ), "str_hint_string is a required argument for register_perk_basic_info!" ); +#/ +/# + assert( isDefined( str_perk_bottle_weapon ), "str_perk_bottle_weapon is a required argument for register_perk_basic_info!" ); +#/ +*/ + _register_undefined_perk( str_perk ); + level._custom_perks[ str_perk ].alias = str_perk; + level._custom_perks[ str_perk ].cost = n_perk_cost; + level._custom_perks[ str_perk ].hint_string = str_hint_string; + level._custom_perks[ str_perk ].perk_bottle = str_perk_bottle_weapon; +} + +register_perk_machine( str_perk, func_perk_machine_setup, func_perk_machine_thread ) +{ +/* +/# + assert( isDefined( str_perk ), "str_perk is a required argument for register_perk_machine!" ); +#/ +/# + assert( isDefined( func_perk_machine_setup ), "func_perk_machine_setup is a required argument for register_perk_machine!" ); +#/ +/# + assert( isDefined( func_perk_machine_thread ), "func_perk_machine_thread is a required argument for register_perk_machine!" ); +#/ +*/ + _register_undefined_perk( str_perk ); + if ( !isDefined( level._custom_perks[ str_perk ].perk_machine_set_kvps ) ) + { + level._custom_perks[ str_perk ].perk_machine_set_kvps = func_perk_machine_setup; + } + if ( !isDefined( level._custom_perks[ str_perk ].perk_machine_thread ) ) + { + level._custom_perks[ str_perk ].perk_machine_thread = func_perk_machine_thread; + } +} + +register_perk_precache_func( str_perk, func_precache ) +{ +/* +/# + assert( isDefined( str_perk ), "str_perk is a required argument for register_perk_precache_func!" ); +#/ +/# + assert( isDefined( func_precache ), "func_precache is a required argument for register_perk_precache_func!" ); +#/ +*/ + _register_undefined_perk( str_perk ); + if ( !isDefined( level._custom_perks[ str_perk ].precache_func ) ) + { + level._custom_perks[ str_perk ].precache_func = func_precache; + } +} + +register_perk_threads( str_perk, func_give_player_perk, func_take_player_perk ) +{ +/* +/# + assert( isDefined( str_perk ), "str_perk is a required argument for register_perk_threads!" ); +#/ +/# + assert( isDefined( func_give_player_perk ), "func_give_player_perk is a required argument for register_perk_threads!" ); +#/ +*/ + _register_undefined_perk( str_perk ); + if ( !isDefined( level._custom_perks[ str_perk ].player_thread_give ) ) + { + level._custom_perks[ str_perk ].player_thread_give = func_give_player_perk; + } + if ( isDefined( func_take_player_perk ) ) + { + if ( !isDefined( level._custom_perks[ str_perk ].player_thread_take ) ) + { + level._custom_perks[ str_perk ].player_thread_take = func_take_player_perk; + } + } +} + +register_perk_clientfields( str_perk, func_clientfield_register, func_clientfield_set ) +{ +/* +/# + assert( isDefined( str_perk ), "str_perk is a required argument for register_perk_clientfields!" ); +#/ +/# + assert( isDefined( func_clientfield_register ), "func_clientfield_register is a required argument for register_perk_clientfields!" ); +#/ +/# + assert( isDefined( func_clientfield_set ), "func_clientfield_set is a required argument for register_perk_clientfields!" ); +#/ +*/ + _register_undefined_perk( str_perk ); + if ( !isDefined( level._custom_perks[ str_perk ].clientfield_register ) ) + { + level._custom_perks[ str_perk ].clientfield_register = func_clientfield_register; + } + if ( !isDefined( level._custom_perks[ str_perk ].clientfield_set ) ) + { + level._custom_perks[ str_perk ].clientfield_set = func_clientfield_set; + } +} + +register_perk_host_migration_func( str_perk, func_host_migration ) +{ +/* +/# + assert( isDefined( str_perk ), "str_perk is a required argument for register_perk_host_migration_func!" ); +#/ +/# + assert( isDefined( func_host_migration ), "func_host_migration is a required argument for register_perk_host_migration_func!" ); +#/ +*/ + _register_undefined_perk( str_perk ); + if ( !isDefined( level._custom_perks[ str_perk ].host_migration_func ) ) + { + level._custom_perks[ str_perk ].host_migration_func = func_host_migration; + } +} + +_register_undefined_perk( str_perk ) +{ + if ( !isDefined( level._custom_perks ) ) + { + level._custom_perks = []; + } + if ( !isDefined( level._custom_perks[ str_perk ] ) ) + { + level._custom_perks[ str_perk ] = spawnstruct(); + } +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_functions.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_functions.gsc new file mode 100644 index 0000000..013cbf2 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_functions.gsc @@ -0,0 +1,1445 @@ +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/_visionset_mgr; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_pers_upgrades; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +pers_boards_updated( zbarrier ) +{ + if ( isDefined( level.pers_upgrade_boards ) && level.pers_upgrade_boards ) + { + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "board" ] ) && !self.pers_upgrades_awarded[ "board" ] ) + { + if ( level.round_number >= level.pers_boarding_round_start ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_boarding", 0 ); + if ( self.pers[ "pers_boarding" ] >= level.pers_boarding_number_of_boards_required ) + { + if ( isDefined( zbarrier ) ) + { + self.upgrade_fx_origin = zbarrier.origin; + } + } + } + } + } + } +} + +pers_revive_active() +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "revive" ] ) && self.pers_upgrades_awarded[ "revive" ] ) + { + return 1; + } + } + return 0; +} + +pers_increment_revive_stat( reviver ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + reviver maps/mp/zombies/_zm_stats::increment_client_stat( "pers_revivenoperk", 0 ); + } +} + +pers_mulit_kill_headshot_active() +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "multikill_headshots" ] ) && self.pers_upgrades_awarded[ "multikill_headshots" ] ) + { + return 1; + } + } + return 0; +} + +pers_check_for_pers_headshot( time_of_death, zombie ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( self.pers[ "last_headshot_kill_time" ] == time_of_death ) + { + self.pers[ "zombies_multikilled" ]++; + } + else + { + self.pers[ "zombies_multikilled" ] = 1; + } + self.pers[ "last_headshot_kill_time" ] = time_of_death; + if ( self.pers[ "zombies_multikilled" ] == 2 ) + { + if ( isDefined( zombie ) ) + { + self.upgrade_fx_origin = zombie.origin; + } + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_multikill_headshots", 0 ); + self.non_headshot_kill_counter = 0; + } + } +} + +cash_back_player_drinks_perk() +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( level.pers_upgrade_cash_back ) && level.pers_upgrade_cash_back ) + { + if ( isDefined( self.pers_upgrades_awarded[ "cash_back" ] ) && self.pers_upgrades_awarded[ "cash_back" ] ) + { + self thread cash_back_money_reward(); + self thread cash_back_player_prone_check( 1 ); + return; + } + else + { + if ( self.pers[ "pers_cash_back_bought" ] < level.pers_cash_back_num_perks_required ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_cash_back_bought", 0 ); + return; + } + else + { + self thread cash_back_player_prone_check( 0 ); + } + } + } + } +} + +cash_back_money_reward() +{ + self endon( "death" ); + step = 5; + amount_per_step = int( level.pers_cash_back_money_reward / step ); + i = 0; + while ( i < step ) + { + self maps/mp/zombies/_zm_score::add_to_player_score( amount_per_step ); + wait 0.2; + i++; + } +} + +cash_back_player_prone_check( got_ability ) +{ + self endon( "death" ); + prone_time = 2.5; + start_time = getTime(); + while ( 1 ) + { + time = getTime(); + dt = ( time - start_time ) / 1000; + if ( dt > prone_time ) + { + break; + } + else + { + if ( self getstance() == "prone" ) + { + if ( !got_ability ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_cash_back_prone", 0 ); + wait 0.8; + } + return; + } + wait 0.01; + } + } + if ( got_ability ) + { + self notify( "cash_back_failed_prone" ); + } +} + +pers_upgrade_insta_kill_upgrade_check() +{ + if ( isDefined( level.pers_upgrade_insta_kill ) && level.pers_upgrade_insta_kill ) + { + self endon( "death" ); + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + e_player = players[ i ]; + if ( isDefined( e_player.pers_upgrades_awarded[ "insta_kill" ] ) && e_player.pers_upgrades_awarded[ "insta_kill" ] ) + { + e_player thread insta_kill_upgraded_player_kill_func( level.pers_insta_kill_upgrade_active_time ); + } + i++; + } + if ( isDefined( self.pers_upgrades_awarded[ "insta_kill" ] ) && !self.pers_upgrades_awarded[ "insta_kill" ] ) + { + kills_start = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "kills" ); + self waittill( "insta_kill_over" ); + kills_end = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "kills" ); + num_killed = kills_end - kills_start; + if ( num_killed > 0 ) + { + self maps/mp/zombies/_zm_stats::zero_client_stat( "pers_insta_kill", 0 ); + return; + } + else + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_insta_kill", 0 ); + } + } + } +} + +insta_kill_upgraded_player_kill_func( active_time ) +{ + self endon( "death" ); + wait 0.25; + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_disabled() ) + { + return; + } + self thread maps/mp/zombies/_zm_pers_upgrades::insta_kill_pers_upgrade_icon(); + start_time = getTime(); + zombie_collide_radius = 50; + zombie_player_height_test = 100; + while ( 1 ) + { + time = getTime(); + dt = ( time - start_time ) / 1000; + if ( dt > active_time ) + { + return; + } + else if ( !maps/mp/zombies/_zm_powerups::is_insta_kill_active() ) + { + return; + } + else + { + a_zombies = getaiarray( level.zombie_team ); + e_closest = undefined; + i = 0; + while ( i < a_zombies.size ) + { + e_zombie = a_zombies[ i ]; + if ( isDefined( e_zombie.marked_for_insta_upgraded_death ) ) + { + i++; + continue; + } + else + { + height_diff = abs( self.origin[ 2 ] - e_zombie.origin[ 2 ] ); + if ( height_diff < zombie_player_height_test ) + { + dist = distance2d( self.origin, e_zombie.origin ); + if ( dist < zombie_collide_radius ) + { + dist_max = dist; + e_closest = e_zombie; + } + } + } + i++; + } + if ( isDefined( e_closest ) ) + { + e_closest.marked_for_insta_upgraded_death = 1; + e_closest dodamage( e_closest.health + 666, e_closest.origin, self, self, "none", "MOD_PISTOL_BULLET", 0, "knife_zm" ); + } + wait 0.01; + } + } +} + +pers_insta_kill_melee_swipe( smeansofdeath, eattacker ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( smeansofdeath ) && smeansofdeath == "MOD_MELEE" ) + { + if ( isplayer( self ) && maps/mp/zombies/_zm_pers_upgrades::is_insta_kill_upgraded_and_active() ) + { + self notify( "pers_melee_swipe" ); + level.pers_melee_swipe_zombie_swiper = eattacker; + } + } + } +} + +pers_upgrade_jugg_player_death_stat() +{ + if ( isDefined( level.pers_upgrade_jugg ) && level.pers_upgrade_jugg ) + { + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "jugg" ] ) && !self.pers_upgrades_awarded[ "jugg" ] ) + { + if ( level.round_number <= level.pers_jugg_hit_and_die_round_limit ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_jugg", 0 ); + } + } + } + } +} + +pers_jugg_active() +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "jugg" ] ) && self.pers_upgrades_awarded[ "jugg" ] ) + { + return 1; + } + } + return 0; +} + +pers_upgrade_flopper_damage_check( smeansofdeath, idamage ) +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return 0; + } + if ( !isDefined( smeansofdeath ) || smeansofdeath != "MOD_FALLING" ) + { + return 0; + } + if ( isDefined( self.pers_upgrades_awarded[ "flopper" ] ) && !self.pers_upgrades_awarded[ "flopper" ] ) + { + if ( idamage < level.pers_flopper_min_fall_damage_activate ) + { + return 0; + } + if ( !isDefined( self.pers_num_flopper_damages ) ) + { + self.pers_num_flopper_damages = 0; + } + self.pers_num_flopper_damages++; + if ( self.pers_num_flopper_damages >= level.pers_flopper_damage_counter ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_flopper_counter", 0 ); + /* +/# + iprintlnbold( "FLOPPER STAT: INCREMENTED" ); +#/ + */ + } + } + else + { + if ( isDefined( self.pers_flopper_active ) && !self.pers_flopper_active ) + { + if ( idamage >= level.pers_flopper_min_fall_damage_deactivate ) + { + self notify( "pers_flopper_lost" ); + } + return 0; + } + if ( idamage > 0 ) + { + self notify( "activate_pers_flopper_effect" ); + return 1; + } + } + return 0; +} + +divetonuke_precache_override_func() +{ + precacheshader( "specialty_divetonuke_zombies" ); + level._effect[ "divetonuke_light" ] = loadfx( "misc/fx_zombie_cola_dtap_on" ); +} + +pers_upgrade_flopper_watcher() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "pers_flopper_lost" ); + while ( 1 ) + { + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_disabled() ) + { + wait 0.01; + continue; + } + else + { + self waittill( "dtp_start" ); + self.pers_flopper_active = 1; + self thread pers_flopper_dtn(); + self waittill( "dtp_end" ); + self.pers_flopper_active = undefined; + } + } +} + +pers_flopper_dtn() +{ + self endon( "disconnect" ); + self waittill( "activate_pers_flopper_effect" ); + if ( isDefined( level.pers_flopper_divetonuke_func ) ) + { + self thread [[ level.pers_flopper_divetonuke_func ]]( self, self.origin ); + } +} + +pers_flopper_explode( attacker, origin ) +{ + self endon( "disconnect" ); + radius = level.zombie_vars[ "zombie_perk_divetonuke_radius" ]; + min_damage = level.zombie_vars[ "zombie_perk_divetonuke_min_damage" ]; + max_damage = level.zombie_vars[ "zombie_perk_divetonuke_max_damage" ]; + if ( isDefined( level.pers_flopper_network_optimized ) && level.pers_flopper_network_optimized ) + { + attacker thread pers_flopper_damage_network_optimized( origin, radius, max_damage, min_damage, "MOD_GRENADE_SPLASH" ); + } + else + { + radiusdamage( origin, radius, max_damage, min_damage, attacker, "MOD_GRENADE_SPLASH" ); + } + attacker setclientfield( "phd_flopper_effects", 1 ); + maps/mp/_visionset_mgr::vsmgr_activate( "visionset", "zm_perk_divetonuke", attacker ); + wait 1; + maps/mp/_visionset_mgr::vsmgr_deactivate( "visionset", "zm_perk_divetonuke", attacker ); + attacker setclientfield( "phd_flopper_effects", 0 ); +} + +pers_flopper_damage_network_optimized( origin, radius, max_damage, min_damage, damage_mod ) +{ + self endon( "disconnect" ); + a_zombies = get_array_of_closest( origin, get_round_enemy_array(), undefined, undefined, radius ); + network_stall_counter = 0; + while ( isDefined( a_zombies ) ) + { + i = 0; + while ( i < a_zombies.size ) + { + e_zombie = a_zombies[ i ]; + if ( !isDefined( e_zombie ) || !isalive( e_zombie ) ) + { + i++; + continue; + } + else + { + dist = distance( e_zombie.origin, origin ); + damage = min_damage + ( ( max_damage - min_damage ) * ( 1 - ( dist / radius ) ) ); + e_zombie dodamage( damage, e_zombie.origin, self, self, 0, damage_mod ); + network_stall_counter--; + + if ( network_stall_counter <= 0 ) + { + wait_network_frame(); + network_stall_counter = randomintrange( 1, 3 ); + } + } + i++; + } + } +} + +pers_upgrade_pistol_points_kill() +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + if ( !isDefined( self.pers_num_zombies_killed_in_game ) ) + { + self.pers_num_zombies_killed_in_game = 0; + } + self.pers_num_zombies_killed_in_game++; + if ( isDefined( self.pers_upgrades_awarded[ "pistol_points" ] ) && !self.pers_upgrades_awarded[ "pistol_points" ] ) + { + if ( self.pers_num_zombies_killed_in_game >= level.pers_pistol_points_num_kills_in_game ) + { + accuracy = self pers_get_player_accuracy(); + if ( accuracy <= level.pers_pistol_points_accuracy ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_pistol_points_counter", 0 ); + /* +/# + iprintlnbold( "PISTOL POINTS STAT: INCREMENTED" ); +#/ + */ + } + } + } + else + { + self notify( "pers_pistol_points_kill" ); + } +} + +pers_upgrade_pistol_points_set_score( score, event, mod, damage_weapon ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "pistol_points" ] ) && self.pers_upgrades_awarded[ "pistol_points" ] ) + { + if ( isDefined( event ) ) + { + if ( event == "rebuild_board" ) + { + return score; + } + if ( isDefined( damage_weapon ) ) + { + weapon_class = getweaponclasszm( damage_weapon ); + if ( weapon_class != "weapon_pistol" ) + { + return score; + } + } + if ( isDefined( mod ) && isstring( mod ) && mod == "MOD_PISTOL_BULLET" ) + { + score *= 2; + } + } + } + } + return score; +} + +pers_upgrade_double_points_pickup_start() +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + if ( isDefined( self.double_points_ability_check_active ) && self.double_points_ability_check_active ) + { + self.double_points_ability_start_time = getTime(); + return; + } + self.double_points_ability_check_active = 1; + level.pers_double_points_active = 1; + start_points = self.score; + if ( isDefined( self.account_value ) ) + { + bank_account_value_start = self.account_value; + } + else + { + bank_account_value_start = 0; + } + self.double_points_ability_start_time = getTime(); + last_score = self.score; + ability_lost = 0; + while ( 1 ) + { + if ( self.score > last_score ) + { + ability_lost = 1; + } + last_score = self.score; + time = getTime(); + dt = ( time - self.double_points_ability_start_time ) / 1000; + if ( dt >= 30 ) + { + break; + } + else + { + wait 0.1; + } + } + level.pers_double_points_active = undefined; + if ( isDefined( self.account_value ) ) + { + bank_account_value_end = self.account_value; + } + else + { + bank_account_value_end = 0; + } + if ( bank_account_value_end < bank_account_value_start ) + { + withdrawal_number = bank_account_value_start - bank_account_value_end; + withdrawal_fees = level.ta_vaultfee * withdrawal_number; + withdrawal_amount = level.bank_deposit_ddl_increment_amount * withdrawal_number; + bank_withdrawal_total = withdrawal_amount - withdrawal_fees; + } + else + { + bank_withdrawal_total = 0; + } + if ( isDefined( self.pers_upgrades_awarded[ "double_points" ] ) && self.pers_upgrades_awarded[ "double_points" ] ) + { + if ( ability_lost == 1 ) + { + self notify( "double_points_lost" ); + } + } + else + { + total_points = self.score - start_points; + total_points -= bank_withdrawal_total; + if ( total_points >= level.pers_double_points_score ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_double_points_counter", 0 ); + /* +/# + iprintlnbold( "PISTOL POINTS STAT: INCREMENTED" ); +#/ + */ + } + } + self.double_points_ability_check_active = undefined; +} + +pers_upgrade_double_points_set_score( score ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "double_points" ] ) && self.pers_upgrades_awarded[ "double_points" ] ) + { + if ( isDefined( level.pers_double_points_active ) && level.pers_double_points_active ) + { + score = int( score * 0.5 ); + } + } + } + return score; +} + +pers_upgrade_double_points_cost( current_cost ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.pers_upgrades_awarded[ "double_points" ] ) && self.pers_upgrades_awarded[ "double_points" ] ) + { + current_cost = int( current_cost / 2 ); + } + } + return current_cost; +} + +is_pers_double_points_active() +{ + if ( isDefined( self.pers_upgrades_awarded[ "double_points" ] ) && self.pers_upgrades_awarded[ "double_points" ] ) + { + if ( isDefined( level.pers_double_points_active ) && level.pers_double_points_active ) + { + return 1; + } + } + return 0; +} + +pers_upgrade_perk_lose_bought() +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + wait 1; + if ( isDefined( self.pers_upgrades_awarded[ "perk_lose" ] ) && !self.pers_upgrades_awarded[ "perk_lose" ] ) + { + if ( level.round_number <= level.pers_perk_round_reached_max ) + { + if ( !isDefined( self.bought_all_perks ) ) + { + a_perks = self get_perk_array( 0 ); + if ( isDefined( a_perks ) && a_perks.size == 4 ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_perk_lose_counter", 0 ); + /* +/# + iprintlnbold( "PERK LOSE STAT: INCREMENTED" ); +#/ + */ + self.bought_all_perks = 1; + } + } + } + } + else + { + if ( isDefined( self.pers_perk_lose_start_round ) ) + { + if ( level.round_number > 1 && self.pers_perk_lose_start_round == level.round_number ) + { + self notify( "pers_perk_lose_lost" ); + } + } + } +} + +pers_upgrade_perk_lose_save() +{ + while ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( isDefined( self.perks_active ) ) + { + self.a_saved_perks = []; + self.a_saved_perks = arraycopy( self.perks_active ); + } + else + { + self.a_saved_perks = self get_perk_array( 0 ); + } + self.a_saved_primaries = self getweaponslistprimaries(); + self.a_saved_primaries_weapons = []; + index = 0; + _a1032 = self.a_saved_primaries; + _k1032 = getFirstArrayKey( _a1032 ); + while ( isDefined( _k1032 ) ) + { + weapon = _a1032[ _k1032 ]; + self.a_saved_primaries_weapons[ index ] = maps/mp/zombies/_zm_weapons::get_player_weapondata( self, weapon ); + index++; + _k1032 = getNextArrayKey( _a1032, _k1032 ); + } + } +} + +pers_upgrade_perk_lose_restore() +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + player_has_mule_kick = 0; + discard_quickrevive = 0; + while ( isDefined( self.a_saved_perks ) && self.a_saved_perks.size >= 2 ) + { + i = 0; + while ( i < self.a_saved_perks.size ) + { + perk = self.a_saved_perks[ i ]; + if ( perk == "specialty_quickrevive" ) + { + discard_quickrevive = 1; + } + i++; + } + if ( discard_quickrevive == 1 ) + { + size = self.a_saved_perks.size; + } + else + { + size = self.a_saved_perks.size - 1; + } + i = 0; + while ( i < size ) + { + perk = self.a_saved_perks[ i ]; + if ( discard_quickrevive == 1 && perk == "specialty_quickrevive" ) + { + i++; + continue; + } + else + { + if ( perk == "specialty_additionalprimaryweapon" ) + { + player_has_mule_kick = 1; + } + if ( self hasperk( perk ) ) + { + i++; + continue; + } + else + { + self maps/mp/zombies/_zm_perks::give_perk( perk ); + wait_network_frame(); + } + } + i++; + } + } + while ( player_has_mule_kick ) + { + a_current_weapons = self getweaponslistprimaries(); + i = 0; + while ( i < self.a_saved_primaries_weapons.size ) + { + saved_weapon = self.a_saved_primaries_weapons[ i ]; + found = 0; + j = 0; + while ( j < a_current_weapons.size ) + { + current_weapon = a_current_weapons[ j ]; + if ( current_weapon == saved_weapon[ "name" ] ) + { + found = 1; + break; + } + else + { + j++; + } + } + if ( found == 0 ) + { + self maps/mp/zombies/_zm_weapons::weapondata_give( self.a_saved_primaries_weapons[ i ] ); + self switchtoweapon( a_current_weapons[ 0 ] ); + break; + } + else + { + i++; + } + } + } + self.a_saved_perks = undefined; + self.a_saved_primaries = undefined; + self.a_saved_primaries_weapons = undefined; + } +} + +pers_upgrade_sniper_kill_check( zombie, attacker ) +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + if ( isDefined( zombie ) || !isDefined( attacker ) && !isDefined( zombie.damageweapon ) ) + { + return; + } + if ( isDefined( zombie.marked_for_insta_upgraded_death ) && zombie.marked_for_insta_upgraded_death ) + { + return; + } + weapon = zombie.damageweapon; + if ( !is_sniper_weapon( weapon ) ) + { + return; + } + if ( isDefined( self.pers_upgrades_awarded[ "sniper" ] ) && self.pers_upgrades_awarded[ "sniper" ] ) + { + self thread pers_sniper_score_reward(); + } + else + { + dist = distance( zombie.origin, attacker.origin ); + if ( dist < level.pers_sniper_kill_distance ) + { + return; + } + if ( !isDefined( self.pers_sniper_round ) ) + { + self.pers_sniper_round = level.round_number; + self.pers_sniper_kills = 0; + } + else + { + if ( self.pers_sniper_round != level.round_number ) + { + self.pers_sniper_round = level.round_number; + self.pers_sniper_kills = 0; + } + } + self.pers_sniper_kills++; + /* +/# + iprintlnbold( "Pers: Long range Sniper Kill" ); +#/ + */ + if ( self.pers_sniper_kills >= level.pers_sniper_round_kills_counter ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "pers_sniper_counter", 0 ); + /* +/# + iprintlnbold( "SNIPER STAT: INCREMENTED" ); +#/ + */ + } + } +} + +pers_sniper_score_reward() +{ + self endon( "disconnect" ); + self endon( "death" ); + while ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + total_score = 300; + steps = 10; + score_inc = int( total_score / steps ); + i = 0; + while ( i < steps ) + { + self maps/mp/zombies/_zm_score::add_to_player_score( score_inc ); + wait 0.25; + i++; + } + } +} + +pers_sniper_player_fires( weapon, hit ) +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + if ( isDefined( weapon ) && isDefined( hit ) ) + { + if ( isDefined( self.pers_upgrades_awarded[ "sniper" ] ) && self.pers_upgrades_awarded[ "sniper" ] ) + { + if ( is_sniper_weapon( weapon ) ) + { + if ( !isDefined( self.num_sniper_misses ) ) + { + self.num_sniper_misses = 0; + } + if ( hit ) + { + self.num_sniper_misses = 0; + return; + } + else + { + self.num_sniper_misses++; + if ( self.num_sniper_misses >= level.pers_sniper_misses ) + { + self notify( "pers_sniper_lost" ); + self.num_sniper_misses = 0; + } + } + } + } + } +} + +pers_get_player_accuracy() +{ + accuracy = 1; + total_shots = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "total_shots" ); + total_hits = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "hits" ); + if ( total_shots > 0 ) + { + accuracy = total_hits / total_shots; + } + return accuracy; +} + +is_sniper_weapon( weapon ) +{ + if ( !isDefined( weapon ) ) + { + return 0; + } + if ( !isstring( weapon ) ) + { + return 0; + } + if ( getsubstr( weapon, 0, 4 ) == "svu_" ) + { + return 1; + } + if ( getsubstr( weapon, 0, 6 ) == "dsr50_" ) + { + return 1; + } + if ( getsubstr( weapon, 0, 10 ) == "barretm82_" ) + { + return 1; + } + return 0; +} + +pers_upgrade_box_weapon_used( e_user, e_grabber ) +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + if ( level.round_number >= level.pers_box_weapon_lose_round ) + { + return; + } + if ( isDefined( e_grabber ) && isplayer( e_grabber ) ) + { + if ( is_true( e_grabber.pers_box_weapon_awarded ) ) + { + return; + } + if ( isDefined( e_grabber.pers_upgrades_awarded[ "box_weapon" ] ) && e_grabber.pers_upgrades_awarded[ "box_weapon" ] ) + { + return; + } + e_grabber maps/mp/zombies/_zm_stats::increment_client_stat( "pers_box_weapon_counter", 0 ); + } + else + { + if ( isDefined( e_user ) && isplayer( e_user ) ) + { + if ( isDefined( e_user.pers_upgrades_awarded[ "box_weapon" ] ) && e_user.pers_upgrades_awarded[ "box_weapon" ] ) + { + return; + } + e_user maps/mp/zombies/_zm_stats::zero_client_stat( "pers_box_weapon_counter", 0 ); + } + } +} + +pers_magic_box_teddy_bear() +{ + self endon( "disconnect" ); + if ( isDefined( level.pers_magic_box_firesale ) && level.pers_magic_box_firesale ) + { + self thread pers_magic_box_firesale(); + } + m_bear = spawn( "script_model", self.origin ); + m_bear setmodel( level.chest_joker_model ); + m_bear pers_magic_box_set_teddy_location( level.chest_index ); + self.pers_magix_box_teddy_bear = m_bear; + m_bear setinvisibletoall(); + wait 0.1; + m_bear setvisibletoplayer( self ); + while ( 1 ) + { + box = level.chests[ level.chest_index ]; + if ( level.round_number >= level.pers_box_weapon_lose_round ) + { + break; + } + else + { + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_disabled() ) + { + m_bear setinvisibletoall(); + while ( 1 ) + { + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_disabled() ) + { + break; + } + else + { + wait 0.01; + } + } + m_bear setvisibletoplayer( self ); + } + if ( flag( "moving_chest_now" ) ) + { + m_bear setinvisibletoall(); + while ( flag( "moving_chest_now" ) ) + { + wait 0.1; + } + m_bear pers_magic_box_set_teddy_location( level.chest_index ); + wait 0.1; + m_bear setvisibletoplayer( self ); + } + if ( isDefined( level.sloth_moving_box ) && level.sloth_moving_box ) + { + m_bear setinvisibletoall(); + while ( isDefined( level.sloth_moving_box ) && level.sloth_moving_box ) + { + wait 0.1; + } + m_bear pers_magic_box_set_teddy_location( level.chest_index ); + wait 0.1; + m_bear setvisibletoplayer( self ); + } + if ( isDefined( box._box_open ) && box._box_open ) + { + m_bear setinvisibletoall(); + while ( 1 ) + { + if ( isDefined( box._box_open ) && !box._box_open ) + { + break; + } + else + { + wait 0.01; + } + } + m_bear setvisibletoplayer( self ); + } + wait 0.01; + } + } + m_bear delete(); +} + +pers_magic_box_set_teddy_location( box_index ) +{ + box = level.chests[ box_index ]; + if ( isDefined( box.zbarrier ) ) + { + v_origin = box.zbarrier.origin; + v_angles = box.zbarrier.angles; + } + else + { + v_origin = box.origin; + v_angles = box.angles; + } + v_up = anglesToUp( v_angles ); + height_offset = 22; + self.origin = v_origin + ( v_up * height_offset ); + dp = vectordot( v_up, ( 0, 1, 0 ) ); + if ( dp > 0 ) + { + v_angles_offset = vectorScale( ( 0, 1, 0 ), 90 ); + } + else + { + v_angles_offset = ( 0, -90, -10 ); + } + self.angles = v_angles + v_angles_offset; +} + +pers_treasure_chest_choosespecialweapon( player ) +{ + rval = randomfloat( 1 ); + if ( !isDefined( player.pers_magic_box_weapon_count ) ) + { + player.pers_magic_box_weapon_count = 0; + } + if ( player.pers_magic_box_weapon_count < 2 || player.pers_magic_box_weapon_count == 0 && rval < 0.6 ) + { + player.pers_magic_box_weapon_count++; + if ( isDefined( level.pers_treasure_chest_get_weapons_array_func ) ) + { + [[ level.pers_treasure_chest_get_weapons_array_func ]](); + } + else + { + pers_treasure_chest_get_weapons_array(); + } + keys = array_randomize( level.pers_box_weapons ); + /* +/# + forced_weapon = getDvar( "scr_force_weapon" ); + if ( forced_weapon != "" && isDefined( level.zombie_weapons[ forced_weapon ] ) ) + { + arrayinsert( keys, forced_weapon, 0 ); +#/ + } + */ + pap_triggers = getentarray( "specialty_weapupgrade", "script_noteworthy" ); + i = 0; + while ( i < keys.size ) + { + if ( maps/mp/zombies/_zm_magicbox::treasure_chest_canplayerreceiveweapon( player, keys[ i ], pap_triggers ) ) + { + return keys[ i ]; + } + i++; + } + return keys[ 0 ]; + } + else + { + player.pers_magic_box_weapon_count = 0; + weapon = maps/mp/zombies/_zm_magicbox::treasure_chest_chooseweightedrandomweapon( player ); + return weapon; + } +} + +pers_treasure_chest_get_weapons_array() +{ + if ( !isDefined( level.pers_box_weapons ) ) + { + level.pers_box_weapons = []; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "ray_gun_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "galil_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "knife_ballistic_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "srm1216_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "hamr_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "tar21_zm"; + level.pers_box_weapons[ level.pers_box_weapons.size ] = "raygun_mark2_zm"; + } +} + +pers_magic_box_firesale() +{ + self endon( "disconnect" ); + wait 1; + while ( 1 ) + { + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 ) + { + wait 5; + i = 0; + while ( i < level.chests.size ) + { + if ( i == level.chest_index ) + { + i++; + continue; + } + else + { + box = level.chests[ i ]; + self thread box_firesale_teddy_bear( box, i ); + } + i++; + } + while ( 1 ) + { + if ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 0 ) + { + break; + } + else + { + wait 0.01; + } + } + } + if ( level.round_number >= level.pers_box_weapon_lose_round ) + { + return; + } + wait 0.5; + } +} + +box_firesale_teddy_bear( box, box_index ) +{ + self endon( "disconnect" ); + m_bear = spawn( "script_model", self.origin ); + m_bear setmodel( level.chest_joker_model ); + m_bear pers_magic_box_set_teddy_location( box_index ); + m_bear setinvisibletoall(); + wait 0.1; + m_bear setvisibletoplayer( self ); + while ( 1 ) + { + if ( isDefined( box._box_open ) && box._box_open ) + { + m_bear setinvisibletoall(); + while ( 1 ) + { + if ( isDefined( box._box_open ) && !box._box_open ) + { + break; + } + else + { + wait 0.01; + } + } + m_bear setvisibletoplayer( self ); + } + if ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 0 ) + { + break; + } + else + { + wait 0.01; + } + } + m_bear delete(); +} + +pers_nube_unlock_watcher() +{ + self endon( "disconnect" ); + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return; + } + self.pers_num_nube_kills = 0; + if ( self.pers[ "pers_max_round_reached" ] >= level.pers_nube_lose_round ) + { + return; + } + num_melee_kills = self.pers[ "melee_kills" ]; + num_headshot_kills = self.pers[ "headshots" ]; + num_boards = self.pers[ "boards" ]; + while ( 1 ) + { + self waittill( "pers_player_zombie_kill" ); + if ( self.pers[ "pers_max_round_reached" ] >= level.pers_nube_lose_round ) + { + self.pers_num_nube_kills = 0; + return; + } + if ( num_melee_kills == self.pers[ "melee_kills" ] && num_headshot_kills == self.pers[ "headshots" ] && num_boards == self.pers[ "boards" ] ) + { + self.pers_num_nube_kills++; + continue; + } + else + { + self.pers_num_nube_kills = 0; + num_melee_kills = self.pers[ "melee_kills" ]; + num_headshot_kills = self.pers[ "headshots" ]; + num_boards = self.pers[ "boards" ]; + } + } +} + +pers_nube_player_ranked_as_nube( player ) +{ + if ( player.pers_num_nube_kills >= level.pers_numb_num_kills_unlock ) + { + return 1; + } + return 0; +} + +pers_nube_weapon_upgrade_check( player, str_weapon ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( getsubstr( str_weapon, 0, 11 ) == "rottweil72_" ) + { + if ( isDefined( player.pers_upgrades_awarded[ "nube" ] ) && !player.pers_upgrades_awarded[ "nube" ] ) + { + if ( pers_nube_player_ranked_as_nube( player ) ) + { + player maps/mp/zombies/_zm_stats::increment_client_stat( "pers_nube_counter", 0 ); + str_weapon = "ray_gun_zm"; + fx_org = player.origin; + v_dir = anglesToForward( player getplayerangles() ); + v_up = anglesToUp( player getplayerangles() ); + fx_org = ( fx_org + ( v_dir * 5 ) ) + ( v_up * 12 ); + player.upgrade_fx_origin = fx_org; + } + } + else + { + str_weapon = "ray_gun_zm"; + } + } + } + return str_weapon; +} + +pers_nube_weapon_ammo_check( player, str_weapon ) +{ + if ( maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + if ( getsubstr( str_weapon, 0, 11 ) == "rottweil72_" ) + { + if ( isDefined( player.pers_upgrades_awarded[ "nube" ] ) && player.pers_upgrades_awarded[ "nube" ] ) + { + if ( player hasweapon( "ray_gun_zm" ) ) + { + str_weapon = "ray_gun_zm"; + } + if ( player hasweapon( "ray_gun_upgraded_zm" ) ) + { + str_weapon = "ray_gun_upgraded_zm"; + } + } + } + } + return str_weapon; +} + +pers_nube_should_we_give_raygun( player_has_weapon, player, weapon_buy ) +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return player_has_weapon; + } + if ( player.pers[ "pers_max_round_reached" ] >= level.pers_nube_lose_round ) + { + return player_has_weapon; + } + if ( !pers_nube_player_ranked_as_nube( player ) ) + { + return player_has_weapon; + } + if ( isDefined( weapon_buy ) && getsubstr( weapon_buy, 0, 11 ) != "rottweil72_" ) + { + return player_has_weapon; + } + if ( !player hasweapon( "rottweil72_zm" ) ) + { + player_has_olympia = player hasweapon( "rottweil72_upgraded_zm" ); + } + if ( !player hasweapon( "ray_gun_zm" ) ) + { + player_has_raygun = player hasweapon( "ray_gun_upgraded_zm" ); + } + if ( player_has_olympia && player_has_raygun ) + { + player_has_weapon = 1; + } + else + { + if ( pers_nube_player_ranked_as_nube( player ) && player_has_olympia && player_has_raygun == 0 ) + { + player_has_weapon = 0; + } + else + { + if ( isDefined( player.pers_upgrades_awarded[ "nube" ] ) && player.pers_upgrades_awarded[ "nube" ] && player_has_raygun ) + { + player_has_weapon = 1; + } + } + } + return player_has_weapon; +} + +pers_nube_ammo_hint_string( player, weapon ) +{ + ammo_cost = 0; + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return 0; + } + if ( getsubstr( weapon, 0, 11 ) == "rottweil72_" ) + { + ammo_cost = pers_nube_ammo_cost( player, ammo_cost ); + } + if ( !ammo_cost ) + { + return 0; + } + self.stub.hint_string = &"ZOMBIE_WEAPONAMMOONLY"; + self sethintstring( self.stub.hint_string, ammo_cost ); + return 1; +} + +pers_nube_ammo_cost( player, ammo_cost ) +{ + if ( player hasweapon( "ray_gun_zm" ) ) + { + ammo_cost = 250; + } + if ( player hasweapon( "ray_gun_upgraded_zm" ) ) + { + ammo_cost = 4500; + } + return ammo_cost; +} + +pers_nube_override_ammo_cost( player, weapon, ammo_cost ) +{ + if ( !maps/mp/zombies/_zm_pers_upgrades::is_pers_system_active() ) + { + return ammo_cost; + } + if ( getsubstr( weapon, 0, 11 ) == "rottweil72_" ) + { + ammo_cost = pers_nube_ammo_cost( player, ammo_cost ); + } + return ammo_cost; +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_system.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_system.gsc new file mode 100644 index 0000000..8882282 --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_pers_upgrades_system.gsc @@ -0,0 +1,278 @@ +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +pers_register_upgrade( name, upgrade_active_func, stat_name, stat_desired_value, game_end_reset_if_not_achieved ) +{ + if ( !isDefined( level.pers_upgrades ) ) + { + level.pers_upgrades = []; + level.pers_upgrades_keys = []; + } + if ( isDefined( level.pers_upgrades[ name ] ) ) + { + /* +/# + assert( 0, "A persistent upgrade is already registered for name: " + name ); +#/ + */ + } + level.pers_upgrades_keys[ level.pers_upgrades_keys.size ] = name; + level.pers_upgrades[ name ] = spawnstruct(); + level.pers_upgrades[ name ].stat_names = []; + level.pers_upgrades[ name ].stat_desired_values = []; + level.pers_upgrades[ name ].upgrade_active_func = upgrade_active_func; + level.pers_upgrades[ name ].game_end_reset_if_not_achieved = game_end_reset_if_not_achieved; + add_pers_upgrade_stat( name, stat_name, stat_desired_value ); + /* +/# + if ( isDefined( level.devgui_add_ability ) ) + { + [[ level.devgui_add_ability ]]( name, upgrade_active_func, stat_name, stat_desired_value, game_end_reset_if_not_achieved ); +#/ + } + */ +} + +add_pers_upgrade_stat( name, stat_name, stat_desired_value ) +{ + if ( !isDefined( level.pers_upgrades[ name ] ) ) + { + /* +/# + assert( 0, name + " - Persistent upgrade is not registered yet." ); +#/ + */ + } + stats_size = level.pers_upgrades[ name ].stat_names.size; + level.pers_upgrades[ name ].stat_names[ stats_size ] = stat_name; + level.pers_upgrades[ name ].stat_desired_values[ stats_size ] = stat_desired_value; +} + +pers_upgrades_monitor() +{ + if ( !isDefined( level.pers_upgrades ) ) + { + return; + } + if ( !is_classic() ) + { + return; + } + level thread wait_for_game_end(); + while ( 1 ) + { + waittillframeend; + players = getplayers(); + player_index = 0; + while ( player_index < players.size ) + { + player = players[ player_index ]; + if ( is_player_valid( player ) && isDefined( player.stats_this_frame ) ) + { + if ( !player.stats_this_frame.size && isDefined( player.pers_upgrade_force_test ) && !player.pers_upgrade_force_test ) + { + player_index++; + continue; + } + else + { + pers_upgrade_index = 0; + while ( pers_upgrade_index < level.pers_upgrades_keys.size ) + { + pers_upgrade = level.pers_upgrades[ level.pers_upgrades_keys[ pers_upgrade_index ] ]; + is_stat_updated = player is_any_pers_upgrade_stat_updated( pers_upgrade ); + if ( is_stat_updated ) + { + should_award = player check_pers_upgrade( pers_upgrade ); + if ( should_award ) + { + if ( isDefined( player.pers_upgrades_awarded[ level.pers_upgrades_keys[ pers_upgrade_index ] ] ) && player.pers_upgrades_awarded[ level.pers_upgrades_keys[ pers_upgrade_index ] ] ) + { + //this checks whether the play already has the upgrade + pers_upgrade_index++; + continue; + } + else + { + player.pers_upgrades_awarded[ level.pers_upgrades_keys[ pers_upgrade_index ] ] = 1; + if ( flag( "initial_blackscreen_passed" ) && !is_true( player.is_hotjoining ) ) + { + type = "upgrade"; + if ( isDefined( level.snd_pers_upgrade_force_type ) ) + { + type = level.snd_pers_upgrade_force_type; + } + player playsoundtoplayer( "evt_player_upgrade", player ); + if ( isDefined( level.pers_upgrade_vo_spoken ) && level.pers_upgrade_vo_spoken ) + { + player delay_thread( 1, ::create_and_play_dialog, "general", type, undefined, level.snd_pers_upgrade_force_variant ); + } + else + { + player delay_thread( 1, ::play_vox_to_player, "general", type, level.snd_pers_upgrade_force_variant ); + } + if ( isDefined( player.upgrade_fx_origin ) ) + { + fx_org = player.upgrade_fx_origin; + player.upgrade_fx_origin = undefined; + } + else + { + fx_org = player.origin; + v_dir = anglesToForward( player getplayerangles() ); + v_up = anglesToUp( player getplayerangles() ); + fx_org = ( fx_org + ( v_dir * 30 ) ) + ( v_up * 12 ); + } + playfx( level._effect[ "upgrade_aquired" ], fx_org ); + level thread maps/mp/zombies/_zm::disable_end_game_intermission( 1.5 ); + } +/# + player iprintlnbold( "Upgraded!" ); +#/ + if ( isDefined( pers_upgrade.upgrade_active_func ) ) + { + player thread [[ pers_upgrade.upgrade_active_func ]](); + } + pers_upgrade_index++; + continue; + } + } + else + { + if ( isDefined( player.pers_upgrades_awarded[ level.pers_upgrades_keys[ pers_upgrade_index ] ] ) && player.pers_upgrades_awarded[ level.pers_upgrades_keys[ pers_upgrade_index ] ] ) + { + if ( flag( "initial_blackscreen_passed" ) && !is_true( player.is_hotjoining ) ) + { + player playsoundtoplayer( "evt_player_downgrade", player ); + } + /* +/# + player iprintlnbold( "Downgraded!" ); +#/ + */ + } + player.pers_upgrades_awarded[ level.pers_upgrades_keys[ pers_upgrade_index ] ] = 0; + } + } + pers_upgrade_index++; + } + player.pers_upgrade_force_test = 0; + player.stats_this_frame = []; + } + } + player_index++; + } + wait 0.05; + } +} + +wait_for_game_end() +{ + if ( !is_classic() ) + { + return; + } + level waittill( "end_game" ); + players = getplayers(); + player_index = 0; + while ( player_index < players.size ) + { + player = players[ player_index ]; + index = 0; + while ( index < level.pers_upgrades_keys.size ) + { + str_name = level.pers_upgrades_keys[ index ]; + game_end_reset_if_not_achieved = level.pers_upgrades[ str_name ].game_end_reset_if_not_achieved; + while ( isDefined( game_end_reset_if_not_achieved ) && game_end_reset_if_not_achieved == 1 ) + { + while ( isDefined( player.pers_upgrades_awarded[ str_name ] ) && !player.pers_upgrades_awarded[ str_name ] ) + { + stat_index = 0; + while ( stat_index < level.pers_upgrades[ str_name ].stat_names.size ) + { + player maps/mp/zombies/_zm_stats::zero_client_stat( level.pers_upgrades[ str_name ].stat_names[ stat_index ], 0 ); + stat_index++; + } + } + } + index++; + } + player_index++; + } +} + +check_pers_upgrade( pers_upgrade ) +{ + should_award = 1; + i = 0; + while ( i < pers_upgrade.stat_names.size ) + { + stat_name = pers_upgrade.stat_names[ i ]; + should_award = self check_pers_upgrade_stat( stat_name, pers_upgrade.stat_desired_values[ i ] ); + if ( !should_award ) + { + break; + } + else + { + i++; + } + } + return should_award; +} + +is_any_pers_upgrade_stat_updated( pers_upgrade ) +{ + if ( isDefined( self.pers_upgrade_force_test ) && self.pers_upgrade_force_test ) + { + return 1; + } + result = 0; + i = 0; + while ( i < pers_upgrade.stat_names.size ) + { + stat_name = pers_upgrade.stat_names[ i ]; + if ( isDefined( self.stats_this_frame[ stat_name ] ) ) + { + result = 1; + break; + } + else + { + i++; + } + } + return result; +} + +check_pers_upgrade_stat( stat_name, stat_desired_value ) +{ + should_award = 1; + current_stat_value = self maps/mp/zombies/_zm_stats::get_global_stat( stat_name ); + if ( current_stat_value < stat_desired_value ) + { + should_award = 0; + } + return should_award; +} + +round_end() +{ + if ( !is_classic() ) + { + return; + } + self notify( "pers_stats_end_of_round" ); + if ( isDefined( self.pers[ "pers_max_round_reached" ] ) ) + { + if ( level.round_number > self.pers[ "pers_max_round_reached" ] ) + { + self maps/mp/zombies/_zm_stats::set_client_stat( "pers_max_round_reached", level.round_number, 0 ); + } + } +} + diff --git a/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_score.gsc b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_score.gsc new file mode 100644 index 0000000..6d833af --- /dev/null +++ b/Fixed Zombies GSCs for compiling/patch_zm/maps/mp/zombies/_zm_score.gsc @@ -0,0 +1,397 @@ +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + level.score_cf_info = []; + score_cf_register_info( "damage", 1, 7 ); + score_cf_register_info( "death_normal", 1, 3 ); + score_cf_register_info( "death_torso", 1, 3 ); + score_cf_register_info( "death_neck", 1, 3 ); + score_cf_register_info( "death_head", 1, 3 ); + score_cf_register_info( "death_melee", 1, 3 ); + if ( !level.createfx_enabled ) + { + registerclientfield( "allplayers", "score_cf_double_points_active", 1, 1, "int" ); + } +} + +score_cf_register_info( name, version, max_count ) +{ + if ( level.createfx_enabled ) + { + return; + } + info = spawnstruct(); + info.name = name; + info.cf_field = "score_cf_" + name; + info.version = version; + info.max_count = max_count; + info.bit_count = getminbitcountfornum( max_count ); + info.players = []; + level.score_cf_info[ name ] = info; + registerclientfield( "allplayers", info.cf_field, info.version, info.bit_count, "int" ); +} + +score_cf_increment_info( name ) +{ + info = level.score_cf_info[ name ]; + player_ent_index = self getentitynumber(); + if ( !isDefined( info.players[ player_ent_index ] ) ) + { + info.players[ player_ent_index ] = 0; + } + info.players[ player_ent_index ]++; + if ( info.players[ player_ent_index ] > info.max_count ) + { + info.players[ player_ent_index ] = 0; + } + self setclientfield( info.cf_field, info.players[ player_ent_index ] ); +} + +score_cf_monitor() +{ + if ( level.createfx_enabled ) + { + return; + } + info_keys = getarraykeys( level.score_cf_info ); + while ( 1 ) + { + wait_network_frame(); + players = get_players(); + player_index = 0; + while ( player_index < players.size ) + { + player = players[ player_index ]; + player_ent_index = player getentitynumber(); + info_index = 0; + while ( info_index < info_keys.size ) + { + 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 ) +{ + if ( level.intermission ) + { + return; + } + if ( !is_player_valid( self ) ) + { + return; + } + player_points = 0; + team_points = 0; + multiplier = get_points_multiplier( self ); + switch( event ) + { + case "death": + player_points = get_zombie_death_player_points(); + team_points = get_zombie_death_team_points(); + points = self player_add_points_kill_bonus( mod, hit_location ); + if ( level.zombie_vars[ self.team ][ "zombie_powerup_insta_kill_on" ] == 1 && mod == "MOD_UNKNOWN" ) + { + points *= 2; + } + player_points += points; + if ( team_points > 0 ) + { + team_points += points; + } + if ( mod == "MOD_GRENADE" || mod == "MOD_GRENADE_SPLASH" ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "grenade_kills" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "grenade_kills" ); + } + break; + case "ballistic_knife_death": + player_points = get_zombie_death_player_points() + level.zombie_vars[ "zombie_score_bonus_melee" ]; + self score_cf_increment_info( "death_melee" ); + break; + case "damage_light": + player_points = level.zombie_vars[ "zombie_score_damage_light" ]; + self score_cf_increment_info( "damage" ); + break; + case "damage": + player_points = level.zombie_vars[ "zombie_score_damage_normal" ]; + self score_cf_increment_info( "damage" ); + break; + case "damage_ads": + player_points = int( level.zombie_vars[ "zombie_score_damage_normal" ] * 1.25 ); + self score_cf_increment_info( "damage" ); + break; + case "carpenter_powerup": + case "rebuild_board": + player_points = mod; + break; + case "bonus_points_powerup": + player_points = mod; + break; + case "nuke_powerup": + player_points = mod; + team_points = mod; + break; + case "jetgun_fling": + case "riotshield_fling": + case "thundergun_fling": + player_points = mod; + break; + case "hacker_transfer": + player_points = mod; + break; + case "reviver": + player_points = mod; + break; + case "vulture": + player_points = mod; + break; + case "build_wallbuy": + player_points = mod; + break; + default: + /* +/# + assert( 0, "Unknown point event" ); +#/ + */ + break; + } + 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" ) + { + 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 ); + player_points -= split_player_points; + } + if ( is_true( level.pers_upgrade_pistol_points ) ) + { + player_points = self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_pistol_points_set_score( player_points, event, mod, damage_weapon ); + } + self add_to_player_score( player_points ); + self.pers[ "score" ] = self.score; + if ( isDefined( level._game_module_point_adjustment ) ) + { + level [[ level._game_module_point_adjustment ]]( self, zombie_team, player_points ); + } +} + +get_points_multiplier( player ) +{ + multiplier = level.zombie_vars[ player.team ][ "zombie_point_scalar" ]; + if ( isDefined( level.current_game_module ) && level.current_game_module == 2 ) + { + if ( isDefined( level._race_team_double_points ) && level._race_team_double_points == player._race_team ) + { + return multiplier; + } + else + { + return 1; + } + } + return multiplier; +} + +get_zombie_death_player_points() +{ + players = get_players(); + if ( players.size == 1 ) + { + points = level.zombie_vars[ "zombie_score_kill_1player" ]; + } + else if ( players.size == 2 ) + { + points = level.zombie_vars[ "zombie_score_kill_2player" ]; + } + else if ( players.size == 3 ) + { + points = level.zombie_vars[ "zombie_score_kill_3player" ]; + } + else + { + points = level.zombie_vars[ "zombie_score_kill_4player" ]; + } + return points; +} + +get_zombie_death_team_points() +{ + players = get_players(); + if ( players.size == 1 ) + { + points = level.zombie_vars[ "zombie_score_kill_1p_team" ]; + } + else if ( players.size == 2 ) + { + points = level.zombie_vars[ "zombie_score_kill_2p_team" ]; + } + else if ( players.size == 3 ) + { + points = level.zombie_vars[ "zombie_score_kill_3p_team" ]; + } + else + { + points = level.zombie_vars[ "zombie_score_kill_4p_team" ]; + } + return points; +} + +player_add_points_kill_bonus( mod, hit_location ) +{ + if ( mod == "MOD_MELEE" ) + { + self score_cf_increment_info( "death_melee" ); + return level.zombie_vars[ "zombie_score_bonus_melee" ]; + } + if ( mod == "MOD_BURNED" ) + { + self score_cf_increment_info( "death_torso" ); + return level.zombie_vars[ "zombie_score_bonus_burn" ]; + } + score = 0; + if ( isDefined( hit_location ) ) + { + switch( hit_location ) + { + case "head": + case "helmet": + self score_cf_increment_info( "death_head" ); + score = level.zombie_vars[ "zombie_score_bonus_head" ]; + break; + case "neck": + self score_cf_increment_info( "death_neck" ); + score = level.zombie_vars[ "zombie_score_bonus_neck" ]; + break; + case "torso_lower": + case "torso_upper": + self score_cf_increment_info( "death_torso" ); + score = level.zombie_vars[ "zombie_score_bonus_torso" ]; + break; + default: + self score_cf_increment_info( "death_normal" ); + break; + } + } + return score; +} + +player_reduce_points( event, mod, hit_location ) +{ + if ( level.intermission ) + { + return; + } + points = 0; + switch( event ) + { + case "no_revive_penalty": + percent = level.zombie_vars[ "penalty_no_revive" ]; + points = self.score * percent; + break; + case "died": + percent = level.zombie_vars[ "penalty_died" ]; + points = self.score * percent; + break; + case "downed": + percent = level.zombie_vars[ "penalty_downed" ]; + self notify( "I_am_down" ); + points = self.score * percent; + self.score_lost_when_downed = round_up_to_ten( int( points ) ); + break; + default: + /* +/# + assert( 0, "Unknown point event" ); +#/ + */ + break; + } + points = self.score - round_up_to_ten( int( points ) ); + if ( points < 0 ) + { + points = 0; + } + self.score = points; +} + +add_to_player_score( points, add_to_total ) +{ + if ( !isDefined( add_to_total ) ) + { + add_to_total = 1; + } + if ( !isDefined( points ) || level.intermission ) + { + return; + } + self.score += points; + self.pers[ "score" ] = self.score; + if ( add_to_total ) + { + self.score_total += points; + } + self incrementplayerstat( "score", points ); +} + +minus_to_player_score( points, ignore_double_points_upgrade ) +{ + if ( !isDefined( points ) || level.intermission ) + { + return; + } + if ( !is_true( ignore_double_points_upgrade ) ) + { + if ( is_true( level.pers_upgrade_double_points ) ) + { + points = maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_double_points_set_score( points ); + } + } + self.score -= points; + self.pers[ "score" ] = self.score; + level notify( "spent_points" ); +} + +add_to_team_score( points ) +{ +} + +minus_to_team_score( points ) +{ +} + +player_died_penalty() +{ + players = get_players( self.team ); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] != self && !players[ i ].is_zombie ) + { + players[ i ] player_reduce_points( "no_revive_penalty" ); + } + i++; + } +} + +player_downed_penalty() +{ +/* +/# + println( "ZM >> LAST STAND - player_downed_penalty " ); +#/ +*/ + self player_reduce_points( "downed" ); +} + diff --git a/Fixed Zombies GSCs for compiling/readme.md b/Fixed Zombies GSCs for compiling/readme.md index a670434..c30ba15 100644 --- a/Fixed Zombies GSCs for compiling/readme.md +++ b/Fixed Zombies GSCs for compiling/readme.md @@ -1,25 +1,55 @@ -**The following gscs compile and run successfully with no known errors:** +###The following gscs compile and run successfully with no known errors: +``` +patch_zm/maps/mp/zombies/_zm_ai_basic.gsc patch_zm/maps/mp/zombies/_zm_ai_dogs.gsc -patch_zm/maps/mp/zombies/_zm_tombstone.gsc +patch_zm/maps/mp/zombies/_zm_ai_faller.gsc patch_zm/maps/mp/zombies/_zm_bot.gsc +patch_zm/maps/mp/zombies/_zm_equip_hacker.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 +patch_zm/maps/mp/zombies/_zm_score.gsc +patch_zm/maps/mp/zombies/_zm_tombstone.gsc +``` +``` patch_zm/maps/mp/gametypes_zm/_scoreboard.gsc patch_zm/maps/mp/gametypes_zm/_shellshock.gsc - -zm_transit_patch/maps/mp/zm_transit_utility.gsc - -**The following scripts compile and run successfully with no known errors but required minor changes to run** patch_zm/maps/mp/gametypes_zm/zclassic.gsc - -**The following scripts compile and run successfully with minor errors:** +``` +``` +zm_transit_patch/maps/mp/zm_transit_utility.gsc +``` +###The following scripts compile and run successfully with minor errors: +``` zm_transit_patch/maps/mp/gametypes_zm/zgrief.gsc - -**The following scripts compile and run successfully with major errors:** +``` +###The following scripts compile and run successfully with major errors: +``` zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc - -**The following scripts compile but cause a minidump or other severe error:** +``` +###The following scripts compile and run serverside but clients cannot join due to exe_client_field_mismatch +``` +patch_zm/maps/mp/zombies/_zm_weapons.gsc +patch_zm/maps/mp/zombies/_zm_gump.gsc +patch_zm/maps/mp/zombies/_zm_equipment.gsc +patch_zm/maps/mp/zombies/_zm_perks.gsc +``` +###The following scripts compile but cause a minidump or other severe error: +``` +patch_zm/maps/mp/zombies/_load.gsc patch_zm/maps/mp/zombies/_zm.gsc patch_zm/maps/mp/zombies/_zm_powerups.gsc patch_zm/maps/mp/zombies/_zm_magicbox.gsc +``` -**notes:** +###notes: +``` zm_transit_utility.gsc can be recompiled to fix tombstone +``` \ No newline at end of file