commit 1b9b26edb669c795ede0f8597e296c1ae8b5a7ff Author: JezuzLizard Date: Fri Mar 27 15:23:42 2020 -0700 moved project to its own repo diff --git a/patch_zm/maps/mp/gametypes_zm/_clientids.gsc b/patch_zm/maps/mp/gametypes_zm/_clientids.gsc new file mode 100644 index 0000000..b17e410 --- /dev/null +++ b/patch_zm/maps/mp/gametypes_zm/_clientids.gsc @@ -0,0 +1,16 @@ + +init() +{ + level.clientid = 0; + level thread onplayerconnect(); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player.clientid = level.clientid; + level.clientid++; + } +} diff --git a/patch_zm/maps/mp/gametypes_zm/_globalentities.gsc b/patch_zm/maps/mp/gametypes_zm/_globalentities.gsc new file mode 100644 index 0000000..e69de29 diff --git a/patch_zm/maps/mp/gametypes_zm/_scoreboard.gsc b/patch_zm/maps/mp/gametypes_zm/_scoreboard.gsc new file mode 100644 index 0000000..9c57984 --- /dev/null +++ b/patch_zm/maps/mp/gametypes_zm/_scoreboard.gsc @@ -0,0 +1,25 @@ + +init() +{ + setdvar( "g_ScoresColor_Spectator", ".25 .25 .25" ); + setdvar( "g_ScoresColor_Free", ".76 .78 .10" ); + setdvar( "g_teamColor_MyTeam", ".4 .7 .4" ); + setdvar( "g_teamColor_EnemyTeam", "1 .315 0.35" ); + setdvar( "g_teamColor_MyTeamAlt", ".35 1 1" ); + setdvar( "g_teamColor_EnemyTeamAlt", "1 .5 0" ); + setdvar( "g_teamColor_Squad", ".315 0.35 1" ); + if ( level.createfx_enabled ) + { + return; + } + if ( sessionmodeiszombiesgame() ) + { + setdvar( "g_TeamIcon_Axis", "faction_cia" ); + setdvar( "g_TeamIcon_Allies", "faction_cdc" ); + } + else + { + setdvar( "g_TeamIcon_Axis", game[ "icons" ][ "axis" ] ); + setdvar( "g_TeamIcon_Allies", game[ "icons" ][ "allies" ] ); + } +} diff --git a/patch_zm/maps/mp/gametypes_zm/_shellshock.gsc b/patch_zm/maps/mp/gametypes_zm/_shellshock.gsc new file mode 100644 index 0000000..c718e80 --- /dev/null +++ b/patch_zm/maps/mp/gametypes_zm/_shellshock.gsc @@ -0,0 +1,65 @@ +#include common_scripts/utility; +#include maps/mp/_utility; + +init() +{ + precacheshellshock( "frag_grenade_mp" ); + precacheshellshock( "damage_mp" ); + precacherumble( "artillery_rumble" ); + precacherumble( "grenade_rumble" ); +} + +shellshockondamage( cause, damage ) +{ + if ( cause != "MOD_EXPLOSIVE" && cause != "MOD_GRENADE" && cause != "MOD_GRENADE_SPLASH" || cause == "MOD_PROJECTILE" && cause == "MOD_PROJECTILE_SPLASH" ) + { + time = 0; + if ( damage >= 90 ) + { + time = 4; + } + else if ( damage >= 50 ) + { + time = 3; + } + else if ( damage >= 25 ) + { + time = 2; + } + else + { + if ( damage > 10 ) + { + time = 2; + } + } + if ( time ) + { + if ( self mayapplyscreeneffect() ) + { + self shellshock( "frag_grenade_mp", 0.5 ); + } + } + } +} + +endondeath() +{ + self waittill( "death" ); + waittillframeend; + self notify( "end_explode" ); +} + +endontimer( timer ) +{ + self endon( "disconnect" ); + wait timer; + self notify( "end_on_timer" ); +} + +rcbomb_earthquake( position ) +{ + playrumbleonposition( "grenade_rumble", position ); + earthquake( 0.5, 0.5, self.origin, 512 ); +} + diff --git a/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc b/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc new file mode 100644 index 0000000..b87c304 --- /dev/null +++ b/patch_zm/maps/mp/gametypes_zm/_zm_gametype.gsc @@ -0,0 +1,2076 @@ +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/gametypes_zm/_spawning; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/gametypes_zm/_hud; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/gametypes_zm/_globallogic_ui; +#include maps/mp/gametypes_zm/_hud_message; +#include maps/mp/gametypes_zm/_globallogic_score; +#include maps/mp/gametypes_zm/_globallogic_defaults; +#include maps/mp/gametypes_zm/_gameobjects; +#include maps/mp/gametypes_zm/_weapons; +#include maps/mp/gametypes_zm/_callbacksetup; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; + +main() +{ + //the bare minimum for a zombies game + maps/mp/gametypes_zm/_globallogic::init(); + maps/mp/gametypes_zm/_callbacksetup::setupcallbacks(); + globallogic_setupdefault_zombiecallbacks(); + menu_init(); + //controls several gamemode specific variables non essential + registerroundlimit( 1, 1 ); + registertimelimit( 0, 0 ); + registerscorelimit( 0, 0 ); + registerroundwinlimit( 0, 0 ); + registernumlives( 1, 1 ); + maps/mp/gametypes_zm/_weapons::registergrenadelauncherduddvar( level.gametype, 10, 0, 1440 ); + maps/mp/gametypes_zm/_weapons::registerthrowngrenadeduddvar( level.gametype, 0, 0, 1440 ); + maps/mp/gametypes_zm/_weapons::registerkillstreakdelay( level.gametype, 0, 0, 1440 ); + maps/mp/gametypes_zm/_globallogic::registerfriendlyfiredelay( level.gametype, 15, 0, 1440 ); + + //determines many aspects of the game non essential + level.takelivesondeath = 1; + level.teambased = 1; + level.disableprematchmessages = 1; + level.disablemomentum = 1; + level.overrideteamscore = 0; + level.overrideplayerscore = 0; + level.displayhalftimetext = 0; + level.displayroundendtext = 0; + level.allowannouncer = 0; + level.endgameonscorelimit = 0; + level.endgameontimelimit = 0; + level.resetplayerscoreeveryround = 1; + level.doprematch = 0; + level.nopersistence = 1; + level.scoreroundbased = 0; + level.forceautoassign = 1; + level.dontshowendreason = 1; + level.forceallallies = 0; + level.allow_teamchange = 0; + + //non essential dvars + setdvar( "scr_disable_team_selection", 1 ); + makedvarserverinfo( "scr_disable_team_selection", 1 ); + setmatchflag( "hud_zombie", 1 ); + setdvar( "scr_disable_weapondrop", 1 ); + setdvar( "scr_xpscale", 0 ); + + //all working except onspawnplayerunified + level.onstartgametype = ::onstartgametype; + level.onspawnplayer = ::blank; + + //causes the server to crash when someone joins + level.onspawnplayerunified = ::onspawnplayerunified; + level.onroundendgame = ::onroundendgame; + level.mayspawn = ::mayspawn; + set_game_var( "ZM_roundLimit", 1 ); + set_game_var( "ZM_scoreLimit", 1 ); + set_game_var( "_team1_num", 0 ); + set_game_var( "_team2_num", 0 ); + + //all working non essential + map_name = level.script; + mode = getDvar( "ui_gametype" ); + if ( isDefined( mode ) && mode == "" && isDefined( level.default_game_mode ) ) + { + mode = level.default_game_mode; + } + set_gamemode_var_once( "mode", mode ); + set_game_var_once( "side_selection", 1 ); + location = getDvar( "ui_zm_mapstartlocation" ); + if ( location == "" && isDefined( level.default_start_location ) ) + { + location = level.default_start_location; + } + set_gamemode_var_once( "location", location ); + set_gamemode_var_once( "randomize_mode", getDvarInt( "zm_rand_mode" ) ); + set_gamemode_var_once( "randomize_location", getDvarInt( "zm_rand_loc" ) ); + + //non essential vars + set_gamemode_var_once( "team_1_score", 0 ); + set_gamemode_var_once( "team_2_score", 0 ); + set_gamemode_var_once( "current_round", 0 ); + set_gamemode_var_once( "rules_read", 0 ); + set_game_var_once( "switchedsides", 0 ); + gametype = getDvar( "ui_gametype" ); + game[ "dialog" ][ "gametype" ] = gametype + "_start"; + game[ "dialog" ][ "gametype_hardcore" ] = gametype + "_start"; + game[ "dialog" ][ "offense_obj" ] = "generic_boost"; + game[ "dialog" ][ "defense_obj" ] = "generic_boost"; + set_gamemode_var( "pre_init_zombie_spawn_func", undefined ); + set_gamemode_var( "post_init_zombie_spawn_func", undefined ); + set_gamemode_var( "match_end_notify", undefined ); + set_gamemode_var( "match_end_func", undefined ); + setscoreboardcolumns( "score", "kills", "downs", "revives", "headshots" ); + + //causes no crashes probably fine + onplayerconnect_callback( ::onplayerconnect_check_for_hotjoin ); +} + +game_objects_allowed( mode, location ) +{ + allowed[ 0 ] = mode; + entities = getentarray(); + _a153 = entities; + _k153 = getFirstArrayKey( _a153 ); + while ( isDefined( _k153 ) ) + { + entity = _a153[ _k153 ]; + if ( isDefined( entity.script_gameobjectname ) ) + { + isallowed = maps/mp/gametypes_zm/_gameobjects::entity_is_allowed( entity, allowed ); + isvalidlocation = maps/mp/gametypes_zm/_gameobjects::location_is_allowed( entity, location ); + if ( !isallowed || !isvalidlocation && !is_classic() ) + { + if ( isDefined( entity.spawnflags ) && entity.spawnflags == 1 ) + { + if ( isDefined( entity.classname ) && entity.classname != "trigger_multiple" ) + { + entity connectpaths(); + } + } + entity delete(); + break; + } + else + { + if ( isDefined( entity.script_vector ) ) + { + entity moveto( entity.origin + entity.script_vector, 0,05 ); + entity waittill( "movedone" ); + if ( isDefined( entity.spawnflags ) && entity.spawnflags == 1 ) + { + entity disconnectpaths(); + } + break; + } + else + { + if ( isDefined( entity.spawnflags ) && entity.spawnflags == 1 ) + { + if ( isDefined( entity.classname ) && entity.classname != "trigger_multiple" ) + { + entity connectpaths(); + } + } + } + } + } + _k153 = getNextArrayKey( _a153, _k153 ); + } +} + +post_init_gametype() +{ + if ( isDefined( level.gamemode_map_postinit ) ) + { + if ( isDefined( level.gamemode_map_postinit[ level.scr_zm_ui_gametype ] ) ) + { + [[ level.gamemode_map_postinit[ level.scr_zm_ui_gametype ] ]](); + } + } +} + +post_gametype_main( mode ) +{ + set_game_var( "ZM_roundWinLimit", get_game_var( "ZM_roundLimit" ) * 0.5 ); + level.roundlimit = get_game_var( "ZM_roundLimit" ); + if ( isDefined( level.gamemode_map_preinit ) ) + { + if ( isDefined( level.gamemode_map_preinit[ mode ] ) ) + { + [[ level.gamemode_map_preinit[ mode ] ]](); + } + } +} + +globallogic_setupdefault_zombiecallbacks() +{ + level.spawnplayer = maps/mp/gametypes_zm/_globallogic_spawn::spawnplayer; + level.spawnplayerprediction = maps/mp/gametypes_zm/_globallogic_spawn::spawnplayerprediction; + level.spawnclient = maps/mp/gametypes_zm/_globallogic_spawn::spawnclient; + level.spawnspectator = maps/mp/gametypes_zm/_globallogic_spawn::spawnspectator; + level.spawnintermission = maps/mp/gametypes_zm/_globallogic_spawn::spawnintermission; + level.onplayerscore = ::blank; + level.onteamscore = ::blank; + + //doesn't exist in any dump or any other script no idea what its trying to override to + //level.wavespawntimer = ::wavespawntimer; + level.onspawnplayer = ::blank; + level.onspawnplayerunified = ::blank; + level.onspawnspectator = ::onspawnspectator; + level.onspawnintermission = ::onspawnintermission; + level.onrespawndelay = ::blank; + level.onforfeit = ::blank; + level.ontimelimit = ::blank; + level.onscorelimit = ::blank; + level.ondeadevent = ::ondeadevent; + level.ononeleftevent = ::blank; + level.giveteamscore = ::blank; + level.giveplayerscore = ::blank; + level.gettimelimit = maps/mp/gametypes_zm/_globallogic_defaults::default_gettimelimit; + level.getteamkillpenalty = ::blank; + level.getteamkillscore = ::blank; + level.iskillboosting = ::blank; + level._setteamscore = maps/mp/gametypes_zm/_globallogic_score::_setteamscore; + level._setplayerscore = ::blank; + level._getteamscore = ::blank; + level._getplayerscore = ::blank; + level.onprecachegametype = ::blank; + level.onstartgametype = ::blank; + level.onplayerconnect = ::blank; + level.onplayerdisconnect = ::onplayerdisconnect; + level.onplayerdamage = ::blank; + level.onplayerkilled = ::blank; + level.onplayerkilledextraunthreadedcbs = []; + level.onteamoutcomenotify = maps/mp/gametypes_zm/_hud_message::teamoutcomenotifyzombie; + level.onoutcomenotify = ::blank; + level.onteamwageroutcomenotify = ::blank; + level.onwageroutcomenotify = ::blank; + level.onendgame = ::onendgame; + level.onroundendgame = ::blank; + level.onmedalawarded = ::blank; + level.autoassign = maps/mp/gametypes_zm/_globallogic_ui::menuautoassign; + level.spectator = maps/mp/gametypes_zm/_globallogic_ui::menuspectator; + level.class = maps/mp/gametypes_zm/_globallogic_ui::menuclass; + level.allies = ::menuallieszombies; + level.teammenu = maps/mp/gametypes_zm/_globallogic_ui::menuteam; + level.callbackactorkilled = ::blank; + level.callbackvehicledamage = ::blank; +} + +setup_standard_objects( location ) +{ + structs = getstructarray( "game_mode_object" ); + _a290 = structs; + _k290 = getFirstArrayKey( _a290 ); + while ( isDefined( _k290 ) ) + { + struct = _a290[ _k290 ]; + if ( isDefined( struct.script_noteworthy ) && struct.script_noteworthy != location ) + { + } + else + { + if ( isDefined( struct.script_string ) ) + { + keep = 0; + tokens = strtok( struct.script_string, " " ); + _a300 = tokens; + _k300 = getFirstArrayKey( _a300 ); + while ( isDefined( _k300 ) ) + { + token = _a300[ _k300 ]; + if ( token == level.scr_zm_ui_gametype && token != "zstandard" ) + { + keep = 1; + } + else + { + if ( token == "zstandard" ) + { + keep = 1; + } + } + _k300 = getNextArrayKey( _a300, _k300 ); + } + if ( !keep ) + { + break; + } + } + else + { + barricade = spawn( "script_model", struct.origin ); + barricade.angles = struct.angles; + barricade setmodel( struct.script_parameters ); + } + } + _k290 = getNextArrayKey( _a290, _k290 ); + } + objects = getentarray(); + _a322 = objects; + _k322 = getFirstArrayKey( _a322 ); + while ( isDefined( _k322 ) ) + { + object = _a322[ _k322 ]; + if ( !object is_survival_object() ) + { + } + else + { + if ( isDefined( object.spawnflags ) && object.spawnflags == 1 && object.classname != "trigger_multiple" ) + { + object connectpaths(); + } + object delete(); + } + _k322 = getNextArrayKey( _a322, _k322 ); + } + if ( isDefined( level._classic_setup_func ) ) + { + [[ level._classic_setup_func ]](); + } +} + +is_survival_object() +{ + if ( !isDefined( self.script_parameters ) ) + { + return 0; + } + tokens = strtok( self.script_parameters, " " ); + remove = 0; + _a352 = tokens; + _k352 = getFirstArrayKey( _a352 ); + while ( isDefined( _k352 ) ) + { + token = _a352[ _k352 ]; + if ( token == "survival_remove" ) + { + remove = 1; + } + _k352 = getNextArrayKey( _a352, _k352 ); + } + return remove; +} + +game_module_player_damage_callback( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + self.last_damage_from_zombie_or_player = 0; + if ( isDefined( eattacker ) ) + { + if ( isplayer( eattacker ) && eattacker == self ) + { + return; + } + if ( isDefined( eattacker.is_zombie ) || eattacker.is_zombie && isplayer( eattacker ) ) + { + self.last_damage_from_zombie_or_player = 1; + } + } + if ( isDefined( self._being_shellshocked ) || self._being_shellshocked && self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return; + } + if ( isplayer( eattacker ) && isDefined( eattacker._encounters_team ) && eattacker._encounters_team != self._encounters_team ) + { + if ( isDefined( self.hasriotshield ) && self.hasriotshield && isDefined( vdir ) ) + { + if ( isDefined( self.hasriotshieldequipped ) && self.hasriotshieldequipped ) + { + if ( self maps/mp/zombies/_zm::player_shield_facing_attacker( vdir, 0.2 ) && isDefined( self.player_shield_apply_damage ) ) + { + return; + } + } + else + { + if ( !isDefined( self.riotshieldentity ) ) + { + if ( !self maps/mp/zombies/_zm::player_shield_facing_attacker( vdir, -0.2 ) && isDefined( self.player_shield_apply_damage ) ) + { + return; + } + } + } + } + if ( isDefined( level._game_module_player_damage_grief_callback ) ) + { + self [[ level._game_module_player_damage_grief_callback ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + } + if ( isDefined( level._effect[ "butterflies" ] ) ) + { + if ( isDefined( sweapon ) && weapontype( sweapon ) == "grenade" ) + { + playfx( level._effect[ "butterflies" ], self.origin + vectorScale( ( 1, 1, 1 ), 40 ) ); + } + else + { + playfx( level._effect[ "butterflies" ], vpoint, vdir ); + } + } + self thread do_game_mode_shellshock(); + self playsound( "zmb_player_hit_ding" ); + } +} + +do_game_mode_shellshock() +{ + self endon( "disconnect" ); + self._being_shellshocked = 1; + self shellshock( "grief_stab_zm", 0.75 ); + wait 0.75; + self._being_shellshocked = 0; +} + +add_map_gamemode( mode, preinit_func, precache_func, main_func ) +{ + if ( !isDefined( level.gamemode_map_location_init ) ) + { + level.gamemode_map_location_init = []; + } + if ( !isDefined( level.gamemode_map_location_main ) ) + { + level.gamemode_map_location_main = []; + } + if ( !isDefined( level.gamemode_map_preinit ) ) + { + level.gamemode_map_preinit = []; + } + if ( !isDefined( level.gamemode_map_postinit ) ) + { + level.gamemode_map_postinit = []; + } + if ( !isDefined( level.gamemode_map_precache ) ) + { + level.gamemode_map_precache = []; + } + if ( !isDefined( level.gamemode_map_main ) ) + { + level.gamemode_map_main = []; + } + level.gamemode_map_preinit[ mode ] = preinit_func; + level.gamemode_map_main[ mode ] = main_func; + level.gamemode_map_precache[ mode ] = precache_func; + level.gamemode_map_location_precache[ mode ] = []; + level.gamemode_map_location_main[ mode ] = []; +} + +add_map_location_gamemode( mode, location, precache_func, main_func ) +{ + if ( !isDefined( level.gamemode_map_location_precache[ mode ] ) ) + { + /* +/# + println( "*** ERROR : " + mode + " has not been added to the map using add_map_gamemode." ); +#/ + */ + return; + } + level.gamemode_map_location_precache[ mode ][ location ] = precache_func; + level.gamemode_map_location_main[ mode ][ location ] = main_func; +} + +rungametypeprecache( gamemode ) +{ + if ( !isDefined( level.gamemode_map_location_main ) || !isDefined( level.gamemode_map_location_main[ gamemode ] ) ) + { + return; + } + if ( isDefined( level.gamemode_map_precache ) ) + { + if ( isDefined( level.gamemode_map_precache[ gamemode ] ) ) + { + [[ level.gamemode_map_precache[ gamemode ] ]](); + } + } + if ( isDefined( level.gamemode_map_location_precache ) ) + { + if ( isDefined( level.gamemode_map_location_precache[ gamemode ] ) ) + { + loc = getDvar( "ui_zm_mapstartlocation" ); + if ( loc == "" && isDefined( level.default_start_location ) ) + { + loc = level.default_start_location; + } + if ( isDefined( level.gamemode_map_location_precache[ gamemode ][ loc ] ) ) + { + [[ level.gamemode_map_location_precache[ gamemode ][ loc ] ]](); + } + } + } + if ( isDefined( level.precachecustomcharacters ) ) + { + self [[ level.precachecustomcharacters ]](); + } +} + +rungametypemain( gamemode, mode_main_func, use_round_logic ) +{ + if ( !isDefined( level.gamemode_map_location_main ) || !isDefined( level.gamemode_map_location_main[ gamemode ] ) ) + { + return; + } + level thread game_objects_allowed( get_gamemode_var( "mode" ), get_gamemode_var( "location" ) ); + if ( isDefined( level.gamemode_map_main ) ) + { + if ( isDefined( level.gamemode_map_main[ gamemode ] ) ) + { + level thread [[ level.gamemode_map_main[ gamemode ] ]](); + } + } + if ( isDefined( level.gamemode_map_location_main ) ) + { + if ( isDefined( level.gamemode_map_location_main[ gamemode ] ) ) + { + loc = getDvar( "ui_zm_mapstartlocation" ); + if ( loc == "" && isDefined( level.default_start_location ) ) + { + loc = level.default_start_location; + } + if ( isDefined( level.gamemode_map_location_main[ gamemode ][ loc ] ) ) + { + level thread [[ level.gamemode_map_location_main[ gamemode ][ loc ] ]](); + } + } + } + if ( isDefined( mode_main_func ) ) + { + if ( isDefined( use_round_logic ) && use_round_logic ) + { + level thread round_logic( mode_main_func ); + } + else + { + level thread non_round_logic( mode_main_func ); + } + } + level thread game_end_func(); +} + + +round_logic( mode_logic_func ) +{ + level.skit_vox_override = 1; + if ( isDefined( level.flag[ "start_zombie_round_logic" ] ) ) + { + flag_wait( "start_zombie_round_logic" ); + } + flag_wait( "start_encounters_match_logic" ); + if ( !isDefined( game[ "gamemode_match" ][ "rounds" ] ) ) + { + game[ "gamemode_match" ][ "rounds" ] = []; + } + set_gamemode_var_once( "current_round", 0 ); + set_gamemode_var_once( "team_1_score", 0 ); + set_gamemode_var_once( "team_2_score", 0 ); + if ( isDefined( is_encounter() ) && is_encounter() ) + { + [[ level._setteamscore ]]( "allies", get_gamemode_var( "team_2_score" ) ); + [[ level._setteamscore ]]( "axis", get_gamemode_var( "team_1_score" ) ); + } + flag_set( "pregame" ); + waittillframeend; + level.gameended = 0; + cur_round = get_gamemode_var( "current_round" ); + set_gamemode_var( "current_round", cur_round + 1 ); + game[ "gamemode_match" ][ "rounds" ][ cur_round ] = spawnstruct(); + game[ "gamemode_match" ][ "rounds" ][ cur_round ].mode = getDvar( "ui_gametype" ); + level thread [[ mode_logic_func ]](); + flag_wait( "start_encounters_match_logic" ); + level.gamestarttime = getTime(); + level.gamelengthtime = undefined; + level notify( "clear_hud_elems" ); + level waittill( "game_module_ended", winner ); + game[ "gamemode_match" ][ "rounds" ][ cur_round ].winner = winner; + level thread kill_all_zombies(); + level.gameendtime = getTime(); + level.gamelengthtime = level.gameendtime - level.gamestarttime; + level.gameended = 1; + if ( winner == "A" ) + { + score = get_gamemode_var( "team_1_score" ); + set_gamemode_var( "team_1_score", score + 1 ); + } + else + { + score = get_gamemode_var( "team_2_score" ); + set_gamemode_var( "team_2_score", score + 1 ); + } + if ( isDefined( is_encounter() ) && is_encounter() ) + { + [[ level._setteamscore ]]( "allies", get_gamemode_var( "team_2_score" ) ); + [[ level._setteamscore ]]( "axis", get_gamemode_var( "team_1_score" ) ); + if ( get_gamemode_var( "team_1_score" ) == get_gamemode_var( "team_2_score" ) ) + { + level thread maps/mp/zombies/_zm_audio::zmbvoxcrowdonteam( "win" ); + level thread maps/mp/zombies/_zm_audio_announcer::announceroundwinner( "tied" ); + } + else + { + level thread maps/mp/zombies/_zm_audio::zmbvoxcrowdonteam( "win", winner, "lose" ); + level thread maps/mp/zombies/_zm_audio_announcer::announceroundwinner( winner ); + } + } + level thread delete_corpses(); + level delay_thread( 5, ::revive_laststand_players ); + level notify( "clear_hud_elems" ); + while ( startnextzmround( winner ) ) + { + level clientnotify( "gme" ); + while ( 1 ) + { + wait 1; + } + } + level.match_is_ending = 1; + if ( isDefined( is_encounter() ) && is_encounter() ) + { + matchwonteam = ""; + if ( get_gamemode_var( "team_1_score" ) > get_gamemode_var( "team_2_score" ) ) + { + matchwonteam = "A"; + } + else + { + matchwonteam = "B"; + } + level thread maps/mp/zombies/_zm_audio::zmbvoxcrowdonteam( "win", matchwonteam, "lose" ); + level thread maps/mp/zombies/_zm_audio_announcer::announcematchwinner( matchwonteam ); + level create_final_score(); + track_encounters_win_stats( matchwonteam ); + } + maps/mp/zombies/_zm::intermission(); + level.can_revive_game_module = undefined; + level notify( "end_game" ); +} + +end_rounds_early( winner ) +{ + level.forcedend = 1; + cur_round = get_gamemode_var( "current_round" ); + set_gamemode_var( "ZM_roundLimit", cur_round ); + if ( isDefined( winner ) ) + { + level notify( "game_module_ended" ); + } + else + { + level notify( "end_game" ); + } +} + + +checkzmroundswitch() +{ + if ( !isDefined( level.zm_roundswitch ) || !level.zm_roundswitch ) + { + return 0; + } + + return 1; + return 0; +} + +create_hud_scoreboard( duration, fade ) +{ + level endon( "end_game" ); + level thread module_hud_full_screen_overlay(); + level thread module_hud_team_1_score( duration, fade ); + level thread module_hud_team_2_score( duration, fade ); + level thread module_hud_round_num( duration, fade ); + respawn_spectators_and_freeze_players(); + waittill_any_or_timeout( duration, "clear_hud_elems" ); +} + +respawn_spectators_and_freeze_players() +{ + players = get_players(); + _a785 = players; + _k785 = getFirstArrayKey( _a785 ); + while ( isDefined( _k785 ) ) + { + player = _a785[ _k785 ]; + if ( player.sessionstate == "spectator" ) + { + if ( isDefined( player.spectate_hud ) ) + { + player.spectate_hud destroy(); + } + player [[ level.spawnplayer ]](); + } + player freeze_player_controls( 1 ); + _k785 = getNextArrayKey( _a785, _k785 ); + } +} + +module_hud_team_1_score( duration, fade ) +{ + level._encounters_score_1 = newhudelem(); + level._encounters_score_1.x = 0; + level._encounters_score_1.y = 260; + level._encounters_score_1.alignx = "center"; + level._encounters_score_1.horzalign = "center"; + level._encounters_score_1.vertalign = "top"; + level._encounters_score_1.font = "default"; + level._encounters_score_1.fontscale = 2.3; + level._encounters_score_1.color = ( 1, 1, 1 ); + level._encounters_score_1.foreground = 1; + level._encounters_score_1 settext( "Team CIA: " + get_gamemode_var( "team_1_score" ) ); + level._encounters_score_1.alpha = 0; + level._encounters_score_1.sort = 11; + level._encounters_score_1 fadeovertime( fade ); + level._encounters_score_1.alpha = 1; + level waittill_any_or_timeout( duration, "clear_hud_elems" ); + level._encounters_score_1 fadeovertime( fade ); + level._encounters_score_1.alpha = 0; + wait fade; + level._encounters_score_1 destroy(); +} + +module_hud_team_2_score( duration, fade ) +{ + level._encounters_score_2 = newhudelem(); + level._encounters_score_2.x = 0; + level._encounters_score_2.y = 290; + level._encounters_score_2.alignx = "center"; + level._encounters_score_2.horzalign = "center"; + level._encounters_score_2.vertalign = "top"; + level._encounters_score_2.font = "default"; + level._encounters_score_2.fontscale = 2.3; + level._encounters_score_2.color = ( 1, 1, 1 ); + level._encounters_score_2.foreground = 1; + level._encounters_score_2 settext( "Team CDC: " + get_gamemode_var( "team_2_score" ) ); + level._encounters_score_2.alpha = 0; + level._encounters_score_2.sort = 12; + level._encounters_score_2 fadeovertime( fade ); + level._encounters_score_2.alpha = 1; + level waittill_any_or_timeout( duration, "clear_hud_elems" ); + level._encounters_score_2 fadeovertime( fade ); + level._encounters_score_2.alpha = 0; + wait fade; + level._encounters_score_2 destroy(); +} + +module_hud_round_num( duration, fade ) +{ + level._encounters_round_num = newhudelem(); + level._encounters_round_num.x = 0; + level._encounters_round_num.y = 60; + level._encounters_round_num.alignx = "center"; + level._encounters_round_num.horzalign = "center"; + level._encounters_round_num.vertalign = "top"; + level._encounters_round_num.font = "default"; + level._encounters_round_num.fontscale = 2.3; + level._encounters_round_num.color = ( 1, 1, 1 ); + level._encounters_round_num.foreground = 1; + level._encounters_round_num settext( "Round: ^5" + get_gamemode_var( "current_round" ) + 1 + " / " + get_game_var( "ZM_roundLimit" ) ); + level._encounters_round_num.alpha = 0; + level._encounters_round_num.sort = 13; + level._encounters_round_num fadeovertime( fade ); + level._encounters_round_num.alpha = 1; + level waittill_any_or_timeout( duration, "clear_hud_elems" ); + level._encounters_round_num fadeovertime( fade ); + level._encounters_round_num.alpha = 0; + wait fade; + level._encounters_round_num destroy(); +} + +createtimer() +{ + flag_waitopen( "pregame" ); + elem = newhudelem(); + elem.hidewheninmenu = 1; + elem.horzalign = "center"; + elem.vertalign = "top"; + elem.alignx = "center"; + elem.aligny = "middle"; + elem.x = 0; + elem.y = 0; + elem.foreground = 1; + elem.font = "default"; + elem.fontscale = 1.5; + elem.color = ( 1, 1, 1 ); + elem.alpha = 2; + elem thread maps/mp/gametypes_zm/_hud::fontpulseinit(); + if ( isDefined( level.timercountdown ) && level.timercountdown ) + { + elem settenthstimer( level.timelimit * 60 ); + } + else + { + elem settenthstimerup( 0.1 ); + } + level.game_module_timer = elem; + level waittill( "game_module_ended" ); + elem destroy(); +} + +revive_laststand_players() +{ + if ( isDefined( level.match_is_ending ) && level.match_is_ending ) + { + return; + } + players = get_players(); + _a917 = players; + _k917 = getFirstArrayKey( _a917 ); + while ( isDefined( _k917 ) ) + { + player = _a917[ _k917 ]; + if ( player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + player thread maps/mp/zombies/_zm_laststand::auto_revive( player ); + } + _k917 = getNextArrayKey( _a917, _k917 ); + } +} + +team_icon_winner( elem ) +{ + og_x = elem.x; + og_y = elem.y; + elem.sort = 1; + elem scaleovertime( 0.75, 150, 150 ); + elem moveovertime( 0.75 ); + elem.horzalign = "center"; + elem.vertalign = "middle"; + elem.x = 0; + elem.y = 0; + elem.alpha = 0.7; + wait 0.75; +} + +delete_corpses() +{ + corpses = getcorpsearray(); + x = 0; + while ( x < corpses.size ) + { + corpses[ x ] delete(); + x++; + } +} + +track_encounters_win_stats( matchwonteam ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ]._encounters_team == matchwonteam ) + { + players[ i ] maps/mp/zombies/_zm_stats::increment_client_stat( "wins" ); + players[ i ] maps/mp/zombies/_zm_stats::add_client_stat( "losses", -1 ); + players[ i ] adddstat( "skill_rating", 1 ); + players[ i ] setdstat( "skill_variance", 1 ); + if ( gamemodeismode( level.gamemode_public_match ) ) + { + players[ i ] maps/mp/zombies/_zm_stats::add_location_gametype_stat( level.scr_zm_map_start_location, level.scr_zm_ui_gametype, "wins", 1 ); + players[ i ] maps/mp/zombies/_zm_stats::add_location_gametype_stat( level.scr_zm_map_start_location, level.scr_zm_ui_gametype, "losses", -1 ); + } + } + else + { + players[ i ] setdstat( "skill_rating", 0 ); + players[ i ] setdstat( "skill_variance", 1 ); + } + players[ i ] updatestatratio( "wlratio", "wins", "losses" ); + i++; + } +} + +non_round_logic( mode_logic_func ) +{ + level thread [[ mode_logic_func ]](); +} + +game_end_func() +{ + if ( !isDefined( get_gamemode_var( "match_end_notify" ) ) && !isDefined( get_gamemode_var( "match_end_func" ) ) ) + { + return; + } + level waittill( get_gamemode_var( "match_end_notify" ), winning_team ); + level thread [[ get_gamemode_var( "match_end_func" ) ]]( winning_team ); +} + +setup_classic_gametype() +{ + ents = getentarray(); + _a1004 = ents; + _k1004 = getFirstArrayKey( _a1004 ); + while ( isDefined( _k1004 ) ) + { + ent = _a1004[ _k1004 ]; + if ( isDefined( ent.script_parameters ) ) + { + parameters = strtok( ent.script_parameters, " " ); + should_remove = 0; + _a1010 = parameters; + _k1010 = getFirstArrayKey( _a1010 ); + while ( isDefined( _k1010 ) ) + { + parm = _a1010[ _k1010 ]; + if ( parm == "survival_remove" ) + { + should_remove = 1; + } + _k1010 = getNextArrayKey( _a1010, _k1010 ); + } + if ( should_remove ) + { + ent delete(); + } + } + _k1004 = getNextArrayKey( _a1004, _k1004 ); + } + structs = getstructarray( "game_mode_object" ); + _a1040 = structs; + _k1040 = getFirstArrayKey( _a1040 ); + while ( isDefined( _k1040 ) ) + { + struct = _a1040[ _k1040 ]; + if ( !isDefined( struct.script_string ) ) + { + } + else tokens = strtok( struct.script_string, " " ); + spawn_object = 0; + _a1048 = tokens; + _k1048 = getFirstArrayKey( _a1048 ); + while ( isDefined( _k1048 ) ) + { + parm = _a1048[ _k1048 ]; + if ( parm == "survival" ) + { + spawn_object = 1; + } + _k1048 = getNextArrayKey( _a1048, _k1048 ); + } + if ( !spawn_object ) + { + } + else + { + barricade = spawn( "script_model", struct.origin ); + barricade.angles = struct.angles; + barricade setmodel( struct.script_parameters ); + } + _k1040 = getNextArrayKey( _a1040, _k1040 ); + } + unlink_meat_traversal_nodes(); +} + +zclassic_main() +{ + level thread setup_classic_gametype(); + level thread maps/mp/zombies/_zm::round_start(); +} + +unlink_meat_traversal_nodes() +{ + meat_town_nodes = getnodearray( "meat_town_barrier_traversals", "targetname" ); + meat_tunnel_nodes = getnodearray( "meat_tunnel_barrier_traversals", "targetname" ); + meat_farm_nodes = getnodearray( "meat_farm_barrier_traversals", "targetname" ); + nodes = arraycombine( meat_town_nodes, meat_tunnel_nodes, 1, 0 ); + traversal_nodes = arraycombine( nodes, meat_farm_nodes, 1, 0 ); + _a1086 = traversal_nodes; + _k1086 = getFirstArrayKey( _a1086 ); + while ( isDefined( _k1086 ) ) + { + node = _a1086[ _k1086 ]; + end_node = getnode( node.target, "targetname" ); + unlink_nodes( node, end_node ); + _k1086 = getNextArrayKey( _a1086, _k1086 ); + } +} + +canplayersuicide() +{ + return self hasperk( "specialty_scavenger" ); +} + +onplayerdisconnect() +{ + if ( isDefined( level.game_mode_custom_onplayerdisconnect ) ) + { + level [[ level.game_mode_custom_onplayerdisconnect ]]( self ); + } + level thread maps/mp/zombies/_zm::check_quickrevive_for_hotjoin( 1 ); + self maps/mp/zombies/_zm_laststand::add_weighted_down(); + level maps/mp/zombies/_zm::checkforalldead( self ); +} + +ondeadevent( team ) +{ + thread maps/mp/gametypes_zm/_globallogic::endgame( level.zombie_team, "" ); +} + +onspawnintermission() +{ + spawnpointname = "info_intermission"; + spawnpoints = getentarray( spawnpointname, "classname" ); + if ( spawnpoints.size < 1 ) + { + /* +/# + println( "NO " + spawnpointname + " SPAWNPOINTS IN MAP" ); +#/ + */ + return; + } + spawnpoint = spawnpoints[ randomint( spawnpoints.size ) ]; + if ( isDefined( spawnpoint ) ) + { + self spawn( spawnpoint.origin, spawnpoint.angles ); + } +} + +onspawnspectator( origin, angles ) +{ +} + +mayspawn() +{ + if ( isDefined( level.custommayspawnlogic ) ) + { + return self [[ level.custommayspawnlogic ]](); + } + if ( self.pers[ "lives" ] == 0 ) + { + level notify( "player_eliminated" ); + self notify( "player_eliminated" ); + return 0; + } + return 1; +} + +onstartgametype() +{ + setclientnamemode( "auto_change" ); + level.displayroundendtext = 0; + maps/mp/gametypes_zm/_spawning::create_map_placed_influencers(); + if ( !isoneround() ) + { + level.displayroundendtext = 1; + if ( isscoreroundbased() ) + { + maps/mp/gametypes_zm/_globallogic_score::resetteamscores(); + } + } +} + +module_hud_full_screen_overlay() +{ + fadetoblack = newhudelem(); + fadetoblack.x = 0; + fadetoblack.y = 0; + fadetoblack.horzalign = "fullscreen"; + fadetoblack.vertalign = "fullscreen"; + fadetoblack setshader( "black", 640, 480 ); + fadetoblack.color = ( 1, 1, 1 ); + fadetoblack.alpha = 1; + fadetoblack.foreground = 1; + fadetoblack.sort = 0; + if ( is_encounter() || getDvar( "ui_gametype" ) == "zcleansed" ) + { + level waittill_any_or_timeout( 25, "start_fullscreen_fade_out" ); + } + else + { + level waittill_any_or_timeout( 25, "start_zombie_round_logic" ); + } + fadetoblack fadeovertime( 2 ); + fadetoblack.alpha = 0; + wait 2.1; + fadetoblack destroy(); +} + +create_final_score() +{ + level endon( "end_game" ); + level thread module_hud_team_winer_score(); + wait 2; +} + +module_hud_team_winer_score() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] thread create_module_hud_team_winer_score(); + if ( isDefined( players[ i ]._team_hud ) && isDefined( players[ i ]._team_hud[ "team" ] ) ) + { + players[ i ] thread team_icon_winner( players[ i ]._team_hud[ "team" ] ); + } + if ( isDefined( level.lock_player_on_team_score ) && level.lock_player_on_team_score ) + { + players[ i ] freezecontrols( 1 ); + players[ i ] takeallweapons(); + players[ i ] setclientuivisibilityflag( "hud_visible", 0 ); + players[ i ].sessionstate = "spectator"; + players[ i ].spectatorclient = -1; + players[ i ].maxhealth = players[ i ].health; + players[ i ].shellshocked = 0; + players[ i ].inwater = 0; + players[ i ].friendlydamage = undefined; + players[ i ].hasspawned = 1; + players[ i ].spawntime = getTime(); + players[ i ].afk = 0; + players[ i ] detachall(); + } + i++; + } + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "match_over" ); +} + +create_module_hud_team_winer_score() +{ + self._team_winer_score = newclienthudelem( self ); + self._team_winer_score.x = 0; + self._team_winer_score.y = 70; + self._team_winer_score.alignx = "center"; + self._team_winer_score.horzalign = "center"; + self._team_winer_score.vertalign = "middle"; + self._team_winer_score.font = "default"; + self._team_winer_score.fontscale = 15; + self._team_winer_score.color = ( 1, 1, 1 ); + self._team_winer_score.foreground = 1; + if ( self._encounters_team == "B" && get_gamemode_var( "team_2_score" ) > get_gamemode_var( "team_1_score" ) ) + { + self._team_winer_score settext( &"ZOMBIE_MATCH_WON" ); + } + else + { + if ( self._encounters_team == "B" && get_gamemode_var( "team_2_score" ) < get_gamemode_var( "team_1_score" ) ) + { + self._team_winer_score.color = ( 1, 1, 1 ); + self._team_winer_score settext( &"ZOMBIE_MATCH_LOST" ); + } + } + if ( self._encounters_team == "A" && get_gamemode_var( "team_1_score" ) > get_gamemode_var( "team_2_score" ) ) + { + self._team_winer_score settext( &"ZOMBIE_MATCH_WON" ); + } + else + { + if ( self._encounters_team == "A" && get_gamemode_var( "team_1_score" ) < get_gamemode_var( "team_2_score" ) ) + { + self._team_winer_score.color = ( 1, 1, 1 ); + self._team_winer_score settext( &"ZOMBIE_MATCH_LOST" ); + } + } + self._team_winer_score.alpha = 0; + self._team_winer_score.sort = 12; + self._team_winer_score fadeovertime( 0.25 ); + self._team_winer_score.alpha = 1; + wait 2; + self._team_winer_score fadeovertime( 0.25 ); + self._team_winer_score.alpha = 0; + wait 0.25; + self._team_winer_score destroy(); +} + +displayroundend( round_winner ) +{ + players = get_players(); + _a1336 = players; + _k1336 = getFirstArrayKey( _a1336 ); + while ( isDefined( _k1336 ) ) + { + player = _a1336[ _k1336 ]; + player thread module_hud_round_end( round_winner ); + if ( isDefined( player._team_hud ) && isDefined( player._team_hud[ "team" ] ) ) + { + player thread team_icon_winner( player._team_hud[ "team" ] ); + } + player freeze_player_controls( 1 ); + _k1336 = getNextArrayKey( _a1336, _k1336 ); + } + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "round_end" ); + level thread maps/mp/zombies/_zm_audio::zmbvoxcrowdonteam( "clap" ); + level thread play_sound_2d( "zmb_air_horn" ); + wait 2; +} + +module_hud_round_end( round_winner ) +{ + self endon( "disconnect" ); + self._team_winner_round = newclienthudelem( self ); + self._team_winner_round.x = 0; + self._team_winner_round.y = 50; + self._team_winner_round.alignx = "center"; + self._team_winner_round.horzalign = "center"; + self._team_winner_round.vertalign = "middle"; + self._team_winner_round.font = "default"; + self._team_winner_round.fontscale = 15; + self._team_winner_round.color = ( 1, 1, 1 ); + self._team_winner_round.foreground = 1; + if ( self._encounters_team == round_winner ) + { + self._team_winner_round.color = ( 1, 1, 1 ); + self._team_winner_round settext( "YOU WIN" ); + } + else + { + self._team_winner_round.color = ( 1, 1, 1 ); + self._team_winner_round settext( "YOU LOSE" ); + } + self._team_winner_round.alpha = 0; + self._team_winner_round.sort = 12; + self._team_winner_round fadeovertime( 0.25 ); + self._team_winner_round.alpha = 1; + wait 1.5; + self._team_winner_round fadeovertime( 0.25 ); + self._team_winner_round.alpha = 0; + wait 0.25; + self._team_winner_round destroy(); +} + +displayroundswitch() +{ + level._round_changing_sides = newhudelem(); + level._round_changing_sides.x = 0; + level._round_changing_sides.y = 60; + level._round_changing_sides.alignx = "center"; + level._round_changing_sides.horzalign = "center"; + level._round_changing_sides.vertalign = "middle"; + level._round_changing_sides.font = "default"; + level._round_changing_sides.fontscale = 2.3; + level._round_changing_sides.color = ( 1, 1, 1 ); + level._round_changing_sides.foreground = 1; + level._round_changing_sides.sort = 12; + fadetoblack = newhudelem(); + fadetoblack.x = 0; + fadetoblack.y = 0; + fadetoblack.horzalign = "fullscreen"; + fadetoblack.vertalign = "fullscreen"; + fadetoblack setshader( "black", 640, 480 ); + fadetoblack.color = ( 1, 1, 1 ); + fadetoblack.alpha = 1; + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "side_switch" ); + level._round_changing_sides settext( "CHANGING SIDES" ); + level._round_changing_sides fadeovertime( 0.25 ); + level._round_changing_sides.alpha = 1; + wait 1; + fadetoblack fadeovertime( 1 ); + level._round_changing_sides fadeovertime( 0.25 ); + level._round_changing_sides.alpha = 0; + fadetoblack.alpha = 0; + wait 0.25; + level._round_changing_sides destroy(); + fadetoblack destroy(); +} + +module_hud_create_team_name() +{ + if ( !is_encounter() ) + { + return; + } + if ( !isDefined( self._team_hud ) ) + { + self._team_hud = []; + } + if ( isDefined( self._team_hud[ "team" ] ) ) + { + self._team_hud[ "team" ] destroy(); + } + elem = newclienthudelem( self ); + elem.hidewheninmenu = 1; + elem.alignx = "center"; + elem.aligny = "middle"; + elem.horzalign = "center"; + elem.vertalign = "middle"; + elem.x = 0; + elem.y = 0; + if ( isDefined( level.game_module_team_name_override_og_x ) ) + { + elem.og_x = level.game_module_team_name_override_og_x; + } + else + { + elem.og_x = 85; + } + elem.og_y = -40; + elem.foreground = 1; + elem.font = "default"; + elem.color = ( 1, 1, 1 ); + elem.sort = 1; + elem.alpha = 0.7; + elem setshader( game[ "icons" ][ self.team ], 150, 150 ); + self._team_hud[ "team" ] = elem; +} + +nextzmhud( winner ) +{ + displayroundend( winner ); + create_hud_scoreboard( 1, 0.25 ); + if ( checkzmroundswitch() ) + { + displayroundswitch(); + } +} + +startnextzmround( winner ) +{ + if ( !isonezmround() ) + { + if ( !waslastzmround() ) + { + nextzmhud( winner ); + setmatchtalkflag( "DeadChatWithDead", level.voip.deadchatwithdead ); + setmatchtalkflag( "DeadChatWithTeam", level.voip.deadchatwithteam ); + setmatchtalkflag( "DeadHearTeamLiving", level.voip.deadhearteamliving ); + setmatchtalkflag( "DeadHearAllLiving", level.voip.deadhearallliving ); + setmatchtalkflag( "EveryoneHearsEveryone", level.voip.everyonehearseveryone ); + setmatchtalkflag( "DeadHearKiller", level.voip.deadhearkiller ); + setmatchtalkflag( "KillersHearVictim", level.voip.killershearvictim ); + game[ "state" ] = "playing"; + level.allowbattlechatter = getgametypesetting( "allowBattleChatter" ); + if ( isDefined( level.zm_switchsides_on_roundswitch ) && level.zm_switchsides_on_roundswitch ) + { + set_game_var( "switchedsides", !get_game_var( "switchedsides" ) ); + } + map_restart( 1 ); + return 1; + } + } + return 0; +} + +start_round() +{ + flag_clear( "start_encounters_match_logic" ); + if ( !isDefined( level._module_round_hud ) ) + { + level._module_round_hud = newhudelem(); + level._module_round_hud.x = 0; + level._module_round_hud.y = 70; + level._module_round_hud.alignx = "center"; + level._module_round_hud.horzalign = "center"; + level._module_round_hud.vertalign = "middle"; + level._module_round_hud.font = "default"; + level._module_round_hud.fontscale = 2.3; + level._module_round_hud.color = ( 1, 1, 1 ); + level._module_round_hud.foreground = 1; + level._module_round_hud.sort = 0; + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] freeze_player_controls( 1 ); + i++; + } + level._module_round_hud.alpha = 1; + label = &"Next Round Starting In ^2"; + level._module_round_hud.label = label; + level._module_round_hud settimer( 3 ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "countdown" ); + level thread maps/mp/zombies/_zm_audio::zmbvoxcrowdonteam( "clap" ); + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "round_start" ); + level notify( "start_fullscreen_fade_out" ); + wait 2; + level._module_round_hud fadeovertime( 1 ); + level._module_round_hud.alpha = 0; + wait 1; + level thread play_sound_2d( "zmb_air_horn" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] freeze_player_controls( 0 ); + players[ i ] sprintuprequired(); + i++; + } + flag_set( "start_encounters_match_logic" ); + flag_clear( "pregame" ); + level._module_round_hud destroy(); +} + +isonezmround() +{ + if ( get_game_var( "ZM_roundLimit" ) == 1 ) + { + return 1; + } + return 0; +} + +waslastzmround() +{ + if ( isDefined( level.forcedend ) && level.forcedend ) + { + return 1; + } + if ( !hitzmroundlimit() || hitzmscorelimit() && hitzmroundwinlimit() ) + { + return 1; + } + return 0; +} + +hitzmroundlimit() +{ + if ( get_game_var( "ZM_roundLimit" ) <= 0 ) + { + return 0; + } + return getzmroundsplayed() >= get_game_var( "ZM_roundLimit" ); +} + +hitzmroundwinlimit() +{ + if ( !isDefined( get_game_var( "ZM_roundWinLimit" ) ) || get_game_var( "ZM_roundWinLimit" ) <= 0 ) + { + return 0; + } + if ( get_gamemode_var( "team_1_score" ) >= get_game_var( "ZM_roundWinLimit" ) || get_gamemode_var( "team_2_score" ) >= get_game_var( "ZM_roundWinLimit" ) ) + { + return 1; + } + if ( get_gamemode_var( "team_1_score" ) >= get_game_var( "ZM_roundWinLimit" ) || get_gamemode_var( "team_2_score" ) >= get_game_var( "ZM_roundWinLimit" ) ) + { + if ( get_gamemode_var( "team_1_score" ) != get_gamemode_var( "team_2_score" ) ) + { + return 1; + } + } + return 0; +} + +hitzmscorelimit() +{ + if ( get_game_var( "ZM_scoreLimit" ) <= 0 ) + { + return 0; + } + if ( is_encounter() ) + { + if ( get_gamemode_var( "team_1_score" ) >= get_game_var( "ZM_scoreLimit" ) || get_gamemode_var( "team_2_score" ) >= get_game_var( "ZM_scoreLimit" ) ) + { + return 1; + } + } + return 0; +} + +getzmroundsplayed() +{ + return get_gamemode_var( "current_round" ); +} + +onspawnplayerunified() +{ + onspawnplayer( 0 ); +} + +onspawnplayer( predictedspawn ) +{ + if ( !isDefined( predictedspawn ) ) + { + predictedspawn = 0; + } + pixbeginevent( "ZSURVIVAL:onSpawnPlayer" ); + self.usingobj = undefined; + self.is_zombie = 0; + if ( isDefined( level.custom_spawnplayer ) && isDefined( self.player_initialized ) && self.player_initialized ) + { + self [[ level.custom_spawnplayer ]](); + return; + } + if ( isDefined( level.customspawnlogic ) ) + { + + + spawnpoint = self [[ level.customspawnlogic ]]( predictedspawn ); + if ( predictedspawn ) + { + return; + } + } + else + { + + } + + if ( flag( "begin_spawning" ) ) + { + spawnpoint = maps/mp/zombies/_zm::check_for_valid_spawn_near_team( self, 1 ); + + + } + if ( !isDefined( spawnpoint ) ) + { + match_string = ""; + location = level.scr_zm_map_start_location; + if ( location != "default" && location == "" && isDefined( level.default_start_location ) ) + { + location = level.default_start_location; + } + match_string = ( level.scr_zm_ui_gametype + "_" ) + location; + /* + spawnPoints = []; + structs = getstructarray("initial_spawn", "script_noteworthy"); + if(IsDefined(structs)) + { + foreach(struct in structs) + { + if(IsDefined(struct.script_string) ) + { + + tokens = strtok(struct.script_string," "); + foreach(token in tokens) + { + if(token == match_string ) + { + spawnPoints[spawnPoints.size] = struct; + } + } + } + + } + } + */ + if ( !isDefined( spawnpoints ) || spawnpoints.size == 0 ) + { + spawnpoints = getstructarray( "initial_spawn_points", "targetname" ); + } + + + spawnpoint = maps/mp/zombies/_zm::getfreespawnpoint( spawnpoints, self ); + } + if ( predictedspawn ) + { + self predictspawnpoint( spawnpoint.origin, spawnpoint.angles ); + return; + } + else + { + self spawn( spawnpoint.origin, spawnpoint.angles, "zsurvival" ); + } + self.entity_num = self getentitynumber(); + self thread maps/mp/zombies/_zm::onplayerspawned(); + self thread maps/mp/zombies/_zm::player_revive_monitor(); + self freezecontrols( 1 ); + self.spectator_respawn = spawnpoint; + self.score = self maps/mp/gametypes_zm/_globallogic_score::getpersstat( "score" ); + self.pers[ "participation" ] = 0; + + self.score_total = self.score; + self.old_score = self.score; + self.player_initialized = 0; + self.zombification_time = 0; + self.enabletext = 1; + self thread maps/mp/zombies/_zm_blockers::rebuild_barrier_reward_reset(); + if ( isDefined( level.host_ended_game ) && !level.host_ended_game ) + { + self freeze_player_controls( 0 ); + self enableweapons(); + } + if ( isDefined( level.game_mode_spawn_player_logic ) ) + { + spawn_in_spectate = [[ level.game_mode_spawn_player_logic ]](); + if ( spawn_in_spectate ) + { + self delay_thread( 0.05, maps/mp/zombies/_zm::spawnspectator ); + } + } + pixendevent(); +} + + +get_player_spawns_for_gametype() +{ + match_string = ""; + location = level.scr_zm_map_start_location; + if ( location != "default" && location == "" && isDefined( level.default_start_location ) ) + { + location = level.default_start_location; + } + match_string = ( level.scr_zm_ui_gametype + "_" ) + location; + player_spawns = []; + structs = getstructarray( "player_respawn_point", "targetname" ); + _a1869 = structs; + _k1869 = getFirstArrayKey( _a1869 ); + while ( isDefined( _k1869 ) ) + { + struct = _a1869[ _k1869 ]; + if ( isDefined( struct.script_string ) ) + { + tokens = strtok( struct.script_string, " " ); + _a1874 = tokens; + _k1874 = getFirstArrayKey( _a1874 ); + while ( isDefined( _k1874 ) ) + { + token = _a1874[ _k1874 ]; + if ( token == match_string ) + { + player_spawns[ player_spawns.size ] = struct; + } + _k1874 = getNextArrayKey( _a1874, _k1874 ); + } + } + else player_spawns[ player_spawns.size ] = struct; + _k1869 = getNextArrayKey( _a1869, _k1869 ); + } + return player_spawns; +} + +onendgame( winningteam ) +{ +} + +onroundendgame( roundwinner ) +{ + if ( game[ "roundswon" ][ "allies" ] == game[ "roundswon" ][ "axis" ] ) + { + winner = "tie"; + } + else if ( game[ "roundswon" ][ "axis" ] > game[ "roundswon" ][ "allies" ] ) + { + winner = "axis"; + } + else + { + winner = "allies"; + } + return winner; +} + +menu_init() +{ + game[ "menu_team" ] = "team_marinesopfor"; + game[ "menu_changeclass_allies" ] = "changeclass"; + game[ "menu_initteam_allies" ] = "initteam_marines"; + game[ "menu_changeclass_axis" ] = "changeclass"; + game[ "menu_initteam_axis" ] = "initteam_opfor"; + game[ "menu_class" ] = "class"; + game[ "menu_changeclass" ] = "changeclass"; + game[ "menu_changeclass_offline" ] = "changeclass"; + game[ "menu_wager_side_bet" ] = "sidebet"; + game[ "menu_wager_side_bet_player" ] = "sidebet_player"; + game[ "menu_changeclass_wager" ] = "changeclass_wager"; + game[ "menu_changeclass_custom" ] = "changeclass_custom"; + game[ "menu_changeclass_barebones" ] = "changeclass_barebones"; + game[ "menu_controls" ] = "ingame_controls"; + game[ "menu_options" ] = "ingame_options"; + game[ "menu_leavegame" ] = "popup_leavegame"; + game[ "menu_restartgamepopup" ] = "restartgamepopup"; + precachemenu( game[ "menu_controls" ] ); + precachemenu( game[ "menu_options" ] ); + precachemenu( game[ "menu_leavegame" ] ); + precachemenu( game[ "menu_restartgamepopup" ] ); + precachemenu( "scoreboard" ); + precachemenu( game[ "menu_team" ] ); + precachemenu( game[ "menu_changeclass_allies" ] ); + precachemenu( game[ "menu_initteam_allies" ] ); + precachemenu( game[ "menu_changeclass_axis" ] ); + precachemenu( game[ "menu_class" ] ); + precachemenu( game[ "menu_changeclass" ] ); + precachemenu( game[ "menu_initteam_axis" ] ); + precachemenu( game[ "menu_changeclass_offline" ] ); + precachemenu( game[ "menu_changeclass_wager" ] ); + precachemenu( game[ "menu_changeclass_custom" ] ); + precachemenu( game[ "menu_changeclass_barebones" ] ); + precachemenu( game[ "menu_wager_side_bet" ] ); + precachemenu( game[ "menu_wager_side_bet_player" ] ); + precachestring( &"MP_HOST_ENDED_GAME" ); + precachestring( &"MP_HOST_ENDGAME_RESPONSE" ); + level thread menu_onplayerconnect(); +} + +menu_onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread menu_onmenuresponse(); + } +} + +menu_onmenuresponse() +{ + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "menuresponse", menu, response ); + if ( response == "back" ) + { + self closemenu(); + self closeingamemenu(); + if ( level.console ) + { + if ( game[ "menu_changeclass" ] != menu && game[ "menu_changeclass_offline" ] != menu || menu == game[ "menu_team" ] && menu == game[ "menu_controls" ] ) + { + if ( self.pers[ "team" ] == "allies" ) + { + self openmenu( game[ "menu_class" ] ); + } + if ( self.pers[ "team" ] == "axis" ) + { + self openmenu( game[ "menu_class" ] ); + } + } + } + continue; + } + else if ( response == "changeteam" && level.allow_teamchange == "1" ) + { + self closemenu(); + self closeingamemenu(); + self openmenu( game[ "menu_team" ] ); + } + if ( response == "changeclass_marines" ) + { + self closemenu(); + self closeingamemenu(); + self openmenu( game[ "menu_changeclass_allies" ] ); + continue; + } + else if ( response == "changeclass_opfor" ) + { + self closemenu(); + self closeingamemenu(); + self openmenu( game[ "menu_changeclass_axis" ] ); + continue; + } + else if ( response == "changeclass_wager" ) + { + self closemenu(); + self closeingamemenu(); + self openmenu( game[ "menu_changeclass_wager" ] ); + continue; + } + else if ( response == "changeclass_custom" ) + { + self closemenu(); + self closeingamemenu(); + self openmenu( game[ "menu_changeclass_custom" ] ); + continue; + } + else if ( response == "changeclass_barebones" ) + { + self closemenu(); + self closeingamemenu(); + self openmenu( game[ "menu_changeclass_barebones" ] ); + continue; + } + else if ( response == "changeclass_marines_splitscreen" ) + { + self openmenu( "changeclass_marines_splitscreen" ); + } + if ( response == "changeclass_opfor_splitscreen" ) + { + self openmenu( "changeclass_opfor_splitscreen" ); + } + if ( response == "endgame" ) + { + if ( self issplitscreen() ) + { + level.skipvote = 1; + if ( isDefined( level.gameended ) && !level.gameended ) + { + self maps/mp/zombies/_zm_laststand::add_weighted_down(); + self maps/mp/zombies/_zm_stats::increment_client_stat( "deaths" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "deaths" ); + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_jugg_player_death_stat(); + level.host_ended_game = 1; + maps/mp/zombies/_zm_game_module::freeze_players( 1 ); + level notify( "end_game" ); + } + } + continue; + } + else if ( response == "restart_level_zm" ) + { + self maps/mp/zombies/_zm_laststand::add_weighted_down(); + self maps/mp/zombies/_zm_stats::increment_client_stat( "deaths" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "deaths" ); + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_jugg_player_death_stat(); + missionfailed(); + } + if ( response == "killserverpc" ) + { + level thread maps/mp/gametypes_zm/_globallogic::killserverpc(); + continue; + } + else if ( response == "endround" ) + { + if ( isDefined( level.gameended ) && !level.gameended ) + { + self maps/mp/gametypes_zm/_globallogic::gamehistoryplayerquit(); + self maps/mp/zombies/_zm_laststand::add_weighted_down(); + self closemenu(); + self closeingamemenu(); + level.host_ended_game = 1; + maps/mp/zombies/_zm_game_module::freeze_players( 1 ); + level notify( "end_game" ); + } + else + { + self closemenu(); + self closeingamemenu(); + self iprintln( &"MP_HOST_ENDGAME_RESPONSE" ); + } + continue; + } + else if ( menu == game[ "menu_team" ] && level.allow_teamchange == "1" ) + { + switch( response ) + { + case "allies": + self [[ level.allies ]](); + break; + case "axis": + self [[ level.teammenu ]]( response ); + break; + case "autoassign": + self [[ level.autoassign ]]( 1 ); + break; + case "spectator": + self [[ level.spectator ]](); + break; + } + continue; + } + else + { + if ( game[ "menu_changeclass" ] != menu && game[ "menu_changeclass_offline" ] != menu && game[ "menu_changeclass_wager" ] != menu || menu == game[ "menu_changeclass_custom" ] && menu == game[ "menu_changeclass_barebones" ] ) + { + self closemenu(); + self closeingamemenu(); + if ( level.rankedmatch && issubstr( response, "custom" ) ) + { + } + self.selectedclass = 1; + self [[ level.class ]]( response ); + } + } + } +} + + +menuallieszombies() +{ + self maps/mp/gametypes_zm/_globallogic_ui::closemenus(); + if ( !level.console && level.allow_teamchange == "0" && isDefined( self.hasdonecombat ) && self.hasdonecombat ) + { + return; + } + if ( self.pers[ "team" ] != "allies" ) + { + if ( level.ingraceperiod || !isDefined( self.hasdonecombat ) && !self.hasdonecombat ) + { + self.hasspawned = 0; + } + if ( self.sessionstate == "playing" ) + { + self.switching_teams = 1; + self.joining_team = "allies"; + self.leaving_team = self.pers[ "team" ]; + self suicide(); + } + self.pers[ "team" ] = "allies"; + self.team = "allies"; + self.class = undefined; + self updateobjectivetext(); + if ( level.teambased ) + { + self.sessionteam = "allies"; + } + else + { + self.sessionteam = "none"; + self.ffateam = "allies"; + } + self setclientscriptmainmenu( game[ "menu_class" ] ); + self notify( "joined_team" ); + level notify( "joined_team" ); + self notify( "end_respawn" ); + } +} + + +custom_spawn_init_func() +{ + array_thread( level.zombie_spawners, ::add_spawn_function, maps/mp/zombies/_zm_spawner::zombie_spawn_init ); + array_thread( level.zombie_spawners, ::add_spawn_function, level._zombies_round_spawn_failsafe ); +} + +kill_all_zombies() +{ + ai = getaiarray( level.zombie_team ); + _a2225 = ai; + _k2225 = getFirstArrayKey( _a2225 ); + while ( isDefined( _k2225 ) ) + { + zombie = _a2225[ _k2225 ]; + if ( isDefined( zombie ) ) + { + zombie dodamage( zombie.maxhealth * 2, zombie.origin, zombie, zombie, "none", "MOD_SUICIDE" ); + wait 0.05; + } + _k2225 = getNextArrayKey( _a2225, _k2225 ); + } +} + +init() +{ + + flag_init( "pregame" ); + flag_set( "pregame" ); + level thread onplayerconnect(); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connected", player ); + player thread onplayerspawned(); + if ( isDefined( level.game_module_onplayerconnect ) ) + { + player [[ level.game_module_onplayerconnect ]](); + } + } +} + +onplayerspawned() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill_either( "spawned_player", "fake_spawned_player" ); + if ( isDefined( level.match_is_ending ) && level.match_is_ending ) + { + return; + } + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + self thread maps/mp/zombies/_zm_laststand::auto_revive( self ); + } + if ( isDefined( level.custom_player_fake_death_cleanup ) ) + { + self [[ level.custom_player_fake_death_cleanup ]](); + } + self setstance( "stand" ); + self.zmbdialogqueue = []; + self.zmbdialogactive = 0; + self.zmbdialoggroups = []; + self.zmbdialoggroup = ""; + if ( is_encounter() ) + { + if ( self.team == "axis" ) + { + self.characterindex = 0; + self._encounters_team = "A"; + self._team_name = &"ZOMBIE_RACE_TEAM_1"; + break; + } + else + { + self.characterindex = 1; + self._encounters_team = "B"; + self._team_name = &"ZOMBIE_RACE_TEAM_2"; + } + } + self takeallweapons(); + if ( isDefined( level.givecustomcharacters ) ) + { + self [[ level.givecustomcharacters ]](); + } + self giveweapon( "knife_zm" ); + if ( isDefined( level.onplayerspawned_restore_previous_weapons ) && isDefined( level.isresetting_grief ) && level.isresetting_grief ) + { + weapons_restored = self [[ level.onplayerspawned_restore_previous_weapons ]](); + } + if ( isDefined( weapons_restored ) && !weapons_restored ) + { + self give_start_weapon( 1 ); + } + weapons_restored = 0; + if ( isDefined( level._team_loadout ) ) + { + self giveweapon( level._team_loadout ); + self switchtoweapon( level._team_loadout ); + } + if ( isDefined( level.gamemode_post_spawn_logic ) ) + { + self [[ level.gamemode_post_spawn_logic ]](); + } + } +} + +wait_for_players() +{ + level endon( "end_race" ); + if ( getDvarInt( "party_playerCount" ) == 1 ) + { + flag_wait( "start_zombie_round_logic" ); + return; + } + while ( !flag_exists( "start_zombie_round_logic" ) ) + { + wait 0.05; + } + while ( !flag( "start_zombie_round_logic" ) && isDefined( level._module_connect_hud ) ) + { + level._module_connect_hud.alpha = 0; + level._module_connect_hud.sort = 12; + level._module_connect_hud fadeovertime( 1 ); + level._module_connect_hud.alpha = 1; + wait 1.5; + level._module_connect_hud fadeovertime( 1 ); + level._module_connect_hud.alpha = 0; + wait 1.5; + } + if ( isDefined( level._module_connect_hud ) ) + { + level._module_connect_hud destroy(); + } +} + +onplayerconnect_check_for_hotjoin() +{ +/* +/# + if ( getDvarInt( #"EA6D219A" ) > 0 ) + { + return; +#/ + } +*/ + map_logic_exists = level flag_exists( "start_zombie_round_logic" ); + map_logic_started = flag( "start_zombie_round_logic" ); + if ( map_logic_exists && map_logic_started ) + { + self thread hide_gump_loading_for_hotjoiners(); + } +} + +hide_gump_loading_for_hotjoiners() +{ + self endon( "disconnect" ); + self.rebuild_barrier_reward = 1; + self.is_hotjoining = 1; + num = self getsnapshotackindex(); + while ( num == self getsnapshotackindex() ) + { + wait 0.25; + } + wait 0.5; + self maps/mp/zombies/_zm::spawnspectator(); + self.is_hotjoining = 0; + self.is_hotjoin = 1; + if ( is_true( level.intermission ) || is_true( level.host_ended_game ) ) + { + setclientsysstate( "levelNotify", "zi", self ); + self setclientthirdperson( 0 ); + self resetfov(); + self.health = 100; + self thread [[ level.custom_intermission ]](); + } +} + +blank() +{ + //empty function +} + + diff --git a/patch_zm/maps/mp/gametypes_zm/zclassic.gsc b/patch_zm/maps/mp/gametypes_zm/zclassic.gsc new file mode 100644 index 0000000..50bbe3d --- /dev/null +++ b/patch_zm/maps/mp/gametypes_zm/zclassic.gsc @@ -0,0 +1,31 @@ +#include maps/mp/zombies/_zm_stats; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_stats; + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::main(); + level.onprecachegametype = ::onprecachegametype; + level.onstartgametype = ::onstartgametype; + level._game_module_custom_spawn_init_func = ::custom_spawn_init_func; + level._game_module_stat_update_func = ::survival_classic_custom_stat_update; + maps/mp/gametypes_zm/_zm_gametype::post_gametype_main( "zclassic" ); +} + +onprecachegametype() +{ + level.playersuicideallowed = 1; + level.canplayersuicide = ::canplayersuicide; + level.suicide_weapon = "death_self_zm"; + precacheitem( "death_self_zm" ); + maps/mp/gametypes_zm/_zm_gametype::rungametypeprecache( "zclassic" ); +} + +onstartgametype() +{ + maps/mp/gametypes_zm/_zm_gametype::rungametypemain( "zclassic", ::zclassic_main ); +} + diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_basic.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_basic.gsc new file mode 100644 index 0000000..f5a13ed --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_dogs.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_dogs.gsc new file mode 100644 index 0000000..d59efd8 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_dogs.gsc @@ -0,0 +1,742 @@ +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + level.dogs_enabled = 1; + level.dog_rounds_enabled = 0; + level.dog_round_count = 1; + level.dog_spawners = []; + level.enemy_dog_spawns = []; + level.enemy_dog_locations = []; + flag_init( "dog_clips" ); + precacherumble( "explosion_generic" ); + precacheshellshock( "dog_bite" ); + if ( getDvar( "zombie_dog_animset" ) == "" ) + { + setdvar( "zombie_dog_animset", "zombie" ); + } + if ( getDvar( "scr_dog_health_walk_multiplier" ) == "" ) + { + setdvar( "scr_dog_health_walk_multiplier", "4.0" ); + } + if ( getDvar( "scr_dog_run_distance" ) == "" ) + { + setdvar( "scr_dog_run_distance", "500" ); + } + level.melee_range_sav = getDvar( "ai_meleeRange" ); + level.melee_width_sav = getDvar( "ai_meleeWidth" ); + level.melee_height_sav = getDvar( "ai_meleeHeight" ); + setdvar( "dog_MeleeDamage", "100" ); + set_zombie_var( "dog_fire_trail_percent", 50 ); + level._effect[ "lightning_dog_spawn" ] = loadfx( "maps/zombie/fx_zombie_dog_lightning_buildup" ); + level._effect[ "dog_eye_glow" ] = loadfx( "maps/zombie/fx_zombie_dog_eyes" ); + level._effect[ "dog_gib" ] = loadfx( "maps/zombie/fx_zombie_dog_explosion" ); + level._effect[ "dog_trail_fire" ] = loadfx( "maps/zombie/fx_zombie_dog_fire_trail" ); + level._effect[ "dog_trail_ash" ] = loadfx( "maps/zombie/fx_zombie_dog_ash_trail" ); + dog_spawner_init(); + level thread dog_clip_monitor(); +} + +enable_dog_rounds() +{ + level.dog_rounds_enabled = 1; + if ( !isDefined( level.dog_round_track_override ) ) + { + level.dog_round_track_override = ::dog_round_tracker; + } + level thread [[ level.dog_round_track_override ]](); +} + +dog_spawner_init() +{ + level.dog_spawners = getentarray( "zombie_dog_spawner", "script_noteworthy" ); + later_dogs = getentarray( "later_round_dog_spawners", "script_noteworthy" ); + level.dog_spawners = arraycombine( level.dog_spawners, later_dogs, 1, 0 ); + if ( level.dog_spawners.size == 0 ) + { + return; + } + i = 0; + while ( i < level.dog_spawners.size ) + { + if ( maps/mp/zombies/_zm_spawner::is_spawner_targeted_by_blocker( level.dog_spawners[ i ] ) ) + { + level.dog_spawners[ i ].is_enabled = 0; + i++; + continue; + } + else + { + level.dog_spawners[ i ].is_enabled = 1; + level.dog_spawners[ i ].script_forcespawn = 1; + } + i++; + } + level.dog_health = 100; + array_thread( level.dog_spawners, ::add_spawn_function, ::dog_init ); + level.enemy_dog_spawns = getentarray( "zombie_spawner_dog_init", "targetname" ); +} + +dog_round_spawning() +{ + level endon( "intermission" ); + level.dog_targets = getplayers(); + i = 0; + while ( i < level.dog_targets.size ) + { + level.dog_targets[ i ].hunted_by = 0; + i++; + } + if ( level.intermission ) + { + return; + } + level.dog_intermission = 1; + level thread dog_round_aftermath(); + players = get_players(); + array_thread( players, ::play_dog_round ); + wait 1; + playsoundatposition( "vox_zmba_event_dogstart_0", ( 0, 0, 0 ) ); + wait 6; + if ( level.dog_round_count < 3 ) + { + max = players.size * 6; + } + else + { + max = players.size * 8; + } + level.zombie_total = max; + dog_health_increase(); + count = 0; + while ( count < max ) + { + num_player_valid = get_number_of_valid_players(); + while ( get_current_zombie_count() >= ( num_player_valid * 2 ) ) + { + wait 2; + num_player_valid = get_number_of_valid_players(); + } + players = get_players(); + favorite_enemy = get_favorite_enemy(); + if ( isDefined( level.dog_spawn_func ) ) + { + spawn_loc = [[ level.dog_spawn_func ]]( level.dog_spawners, favorite_enemy ); + ai = spawn_zombie( level.dog_spawners[ 0 ] ); + if ( isDefined( ai ) ) + { + ai.favoriteenemy = favorite_enemy; + spawn_loc thread dog_spawn_fx( ai, spawn_loc ); + level.zombie_total--; + + count++; + } + } + else + { + spawn_point = dog_spawn_factory_logic( level.enemy_dog_spawns, favorite_enemy ); + ai = spawn_zombie( level.dog_spawners[ 0 ] ); + if ( isDefined( ai ) ) + { + ai.favoriteenemy = favorite_enemy; + spawn_point thread dog_spawn_fx( ai, spawn_point ); + level.zombie_total--; + + count++; + flag_set( "dog_clips" ); + } + } + waiting_for_next_dog_spawn( count, max ); + } +} + +waiting_for_next_dog_spawn( count, max ) +{ + default_wait = 1.5; + if ( level.dog_round_count == 1 ) + { + default_wait = 3; + } + else if ( level.dog_round_count == 2 ) + { + default_wait = 2.5; + } + else if ( level.dog_round_count == 3 ) + { + default_wait = 2; + } + else + { + default_wait = 1.5; + } + default_wait -= count / max; + wait default_wait; +} + +dog_round_aftermath() +{ + level waittill( "last_dog_down" ); + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "dog_end" ); + power_up_origin = level.last_dog_origin; + if ( isDefined( power_up_origin ) ) + { + level thread maps/mp/zombies/_zm_powerups::specific_powerup_drop( "full_ammo", power_up_origin ); + } + wait 2; + clientnotify( "dog_stop" ); + wait 6; + level.dog_intermission = 0; +} + +dog_spawn_fx( ai, ent ) +{ + ai endon( "death" ); + ai setfreecameralockonallowed( 0 ); + playfx( level._effect[ "lightning_dog_spawn" ], ent.origin ); + playsoundatposition( "zmb_hellhound_prespawn", ent.origin ); + wait 1.5; + playsoundatposition( "zmb_hellhound_bolt", ent.origin ); + earthquake( 0.5, 0.75, ent.origin, 1000 ); + playrumbleonposition( "explosion_generic", ent.origin ); + playsoundatposition( "zmb_hellhound_spawn", ent.origin ); + angle = vectorToAngles( ai.favoriteenemy.origin - ent.origin ); + angles = ( ai.angles[ 0 ], angle[ 1 ], ai.angles[ 2 ] ); + ai forceteleport( ent.origin, angles ); + ai zombie_setup_attack_properties_dog(); + ai stop_magic_bullet_shield(); + wait 0.1; + ai show(); + ai setfreecameralockonallowed( 1 ); + ai.ignoreme = 0; + ai notify( "visible" ); +} + +dog_spawn_sumpf_logic( dog_array, favorite_enemy ) +{ + dog_array = array_randomize( dog_array ); + i = 0; + while ( i < dog_array.size ) + { + if ( isDefined( level.old_dog_spawn ) && level.old_dog_spawn == dog_array[ i ] ) + { + i++; + continue; + } + else + { + if ( distancesquared( dog_array[ i ].origin, favorite_enemy.origin ) > 160000 && distancesquared( dog_array[ i ].origin, favorite_enemy.origin ) < 640000 ) + { + if ( distancesquared( ( 0, 0, dog_array[ i ].origin[ 2 ] ), ( 0, 0, favorite_enemy.origin[ 2 ] ) ) > 10000 ) + { + i++; + continue; + } + else level.old_dog_spawn = dog_array[ i ]; + return dog_array[ i ]; + } + } + i++; + } + return dog_array[ 0 ]; +} + +dog_spawn_factory_logic( dog_array, favorite_enemy ) +{ + dog_locs = array_randomize( level.enemy_dog_locations ); + i = 0; + while ( i < dog_locs.size ) + { + if ( isDefined( level.old_dog_spawn ) && level.old_dog_spawn == dog_locs[ i ] ) + { + i++; + continue; + } + else + { + dist_squared = distancesquared( dog_locs[ i ].origin, favorite_enemy.origin ); + if ( dist_squared > 160000 && dist_squared < 1000000 ) + { + level.old_dog_spawn = dog_locs[ i ]; + return dog_locs[ i ]; + } + } + i++; + } + return dog_locs[ 0 ]; +} + +get_favorite_enemy() +{ + dog_targets = getplayers(); + least_hunted = dog_targets[ 0 ]; + i = 0; + while ( i < dog_targets.size ) + { + if ( !isDefined( dog_targets[ i ].hunted_by ) ) + { + dog_targets[ i ].hunted_by = 0; + } + if ( !is_player_valid( dog_targets[ i ] ) ) + { + i++; + continue; + } + else + { + if ( !is_player_valid( least_hunted ) ) + { + least_hunted = dog_targets[ i ]; + } + if ( dog_targets[ i ].hunted_by < least_hunted.hunted_by ) + { + least_hunted = dog_targets[ i ]; + } + } + i++; + } + least_hunted.hunted_by += 1; + return least_hunted; +} + +dog_health_increase() +{ + players = getplayers(); + if ( level.dog_round_count == 1 ) + { + level.dog_health = 400; + } + else if ( level.dog_round_count == 2 ) + { + level.dog_health = 900; + } + else if ( level.dog_round_count == 3 ) + { + level.dog_health = 1300; + } + else + { + if ( level.dog_round_count == 4 ) + { + level.dog_health = 1600; + } + } + if ( level.dog_health > 1600 ) + { + level.dog_health = 1600; + } +} + +dog_round_tracker() +{ + level.dog_round_count = 1; + level.next_dog_round = level.round_number + randomintrange( 4, 7 ); + old_spawn_func = level.round_spawn_func; + old_wait_func = level.round_wait_func; + while ( 1 ) + { + level waittill( "between_round_over" ); + if ( level.round_number == level.next_dog_round ) + { + level.music_round_override = 1; + old_spawn_func = level.round_spawn_func; + old_wait_func = level.round_wait_func; + dog_round_start(); + level.round_spawn_func = ::dog_round_spawning; + level.next_dog_round = level.round_number + randomintrange( 4, 6 ); + continue; + } + else + { + if ( flag( "dog_round" ) ) + { + dog_round_stop(); + level.round_spawn_func = old_spawn_func; + level.round_wait_func = old_wait_func; + level.music_round_override = 0; + level.dog_round_count += 1; + } + } + } +} + +dog_round_start() +{ + flag_set( "dog_round" ); + flag_set( "dog_clips" ); + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "dog_start" ); + if ( !isDefined( level.doground_nomusic ) ) + { + level.doground_nomusic = 0; + } + level.doground_nomusic = 1; + level notify( "dog_round_starting" ); + clientnotify( "dog_start" ); + if ( isDefined( level.dog_melee_range ) ) + { + setdvar( "ai_meleeRange", level.dog_melee_range ); + } + else + { + setdvar( "ai_meleeRange", 100 ); + } +} + +dog_round_stop() +{ + flag_clear( "dog_round" ); + flag_clear( "dog_clips" ); + if ( !isDefined( level.doground_nomusic ) ) + { + level.doground_nomusic = 0; + } + level.doground_nomusic = 0; + level notify( "dog_round_ending" ); + clientnotify( "dog_stop" ); + setdvar( "ai_meleeRange", level.melee_range_sav ); + setdvar( "ai_meleeWidth", level.melee_width_sav ); + setdvar( "ai_meleeHeight", level.melee_height_sav ); +} + +play_dog_round() +{ + self playlocalsound( "zmb_dog_round_start" ); + variation_count = 5; + wait 4.5; + players = getplayers(); + num = randomintrange( 0, players.size ); + players[ num ] maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "dog_spawn" ); +} + +dog_init() +{ + self.targetname = "zombie_dog"; + self.script_noteworthy = undefined; + self.animname = "zombie_dog"; + self.ignoreall = 1; + self.ignoreme = 1; + self.allowdeath = 1; + self.allowpain = 0; + self.force_gib = 1; + self.is_zombie = 1; + self.has_legs = 1; + self.gibbed = 0; + self.head_gibbed = 0; + self.default_goalheight = 40; + self.ignore_inert = 1; + self.grenadeawareness = 0; + self.badplaceawareness = 0; + self.ignoresuppression = 1; + self.suppressionthreshold = 1; + self.nododgemove = 1; + self.dontshootwhilemoving = 1; + self.pathenemylookahead = 0; + self.badplaceawareness = 0; + self.chatinitialized = 0; + self.team = level.zombie_team; + health_multiplier = 1; + if ( getDvar( "scr_dog_health_walk_multiplier" ) != "" ) + { + health_multiplier = getDvarFloat( "scr_dog_health_walk_multiplier" ); + } + self.maxhealth = int( level.dog_health * health_multiplier ); + self.health = int( level.dog_health * health_multiplier ); + self.freezegun_damage = 0; + self.zombie_move_speed = "sprint"; + self thread dog_run_think(); + self thread dog_stalk_audio(); + self thread maps/mp/zombies/_zm::round_spawn_failsafe(); + self ghost(); + self thread magic_bullet_shield(); + self dog_fx_eye_glow(); + self dog_fx_trail(); + self thread dog_death(); + level thread maps/mp/zombies/_zm_spawner::zombie_death_event( self ); + self thread maps/mp/zombies/_zm_spawner::enemy_death_detection(); + self.a.disablepain = 1; + self disable_react(); + self clearenemy(); + self cleargoalvolume(); + self.flame_damage_time = 0; + self.meleedamage = 40; + self.thundergun_knockdown_func = ::dog_thundergun_knockdown; + self maps/mp/zombies/_zm_spawner::zombie_history( "zombie_dog_spawn_init -> Spawned = " + self.origin ); + if ( isDefined( level.achievement_monitor_func ) ) + { + self [[ level.achievement_monitor_func ]](); + } +} + +dog_fx_eye_glow() +{ + self.fx_dog_eye = spawn( "script_model", self gettagorigin( "J_EyeBall_LE" ) ); + self.fx_dog_eye.angles = self gettagangles( "J_EyeBall_LE" ); + self.fx_dog_eye setmodel( "tag_origin" ); + self.fx_dog_eye linkto( self, "J_EyeBall_LE" ); +} + +dog_fx_trail() +{ + if ( !is_mature() || randomint( 100 ) > level.zombie_vars[ "dog_fire_trail_percent" ] ) + { + self.fx_dog_trail_type = level._effect[ "dog_trail_ash" ]; + self.fx_dog_trail_sound = "zmb_hellhound_loop_breath"; + } + else + { + self.a.nodeath = 1; + self.fx_dog_trail_type = level._effect[ "dog_trail_fire" ]; + self.fx_dog_trail_sound = "zmb_hellhound_loop_fire"; + } + self.fx_dog_trail = spawn( "script_model", self gettagorigin( "tag_origin" ) ); + self.fx_dog_trail.angles = self gettagangles( "tag_origin" ); + self.fx_dog_trail setmodel( "tag_origin" ); + self.fx_dog_trail linkto( self, "tag_origin" ); +} + +dog_death() +{ + self waittill( "death" ); + if ( get_current_zombie_count() == 0 && level.zombie_total == 0 ) + { + level.last_dog_origin = self.origin; + level notify( "last_dog_down" ); + } + if ( isplayer( self.attacker ) ) + { + event = "death"; + if ( issubstr( self.damageweapon, "knife_ballistic_" ) ) + { + event = "ballistic_knife_death"; + } + self.attacker maps/mp/zombies/_zm_score::player_add_points( event, self.damagemod, self.damagelocation, 1 ); + if ( randomintrange( 0, 100 ) >= 80 ) + { + self.attacker maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "hellhound" ); + } + self.attacker maps/mp/zombies/_zm_stats::increment_client_stat( "zdogs_killed" ); + self.attacker maps/mp/zombies/_zm_stats::increment_player_stat( "zdogs_killed" ); + } + if ( isDefined( self.attacker ) && isai( self.attacker ) ) + { + self.attacker notify( "killed" ); + } + self stoploopsound(); + self.fx_dog_trail delete(); + if ( isDefined( self.a.nodeath ) ) + { + level thread dog_explode_fx( self.origin ); + self delete(); + } + else + { + self playsound( "zmb_hellhound_vocals_death" ); + } +} + +dog_explode_fx( origin ) +{ + playfx( level._effect[ "dog_gib" ], origin ); + playsoundatposition( "zmb_hellhound_explode", origin ); +} + +zombie_setup_attack_properties_dog() +{ + self maps/mp/zombies/_zm_spawner::zombie_history( "zombie_setup_attack_properties()" ); + self thread dog_behind_audio(); + self.ignoreall = 0; + self.pathenemyfightdist = 64; + self.meleeattackdist = 64; + self.disablearrivals = 1; + self.disableexits = 1; +} + +stop_dog_sound_on_death() +{ + self waittill( "death" ); + self stopsounds(); +} + +dog_behind_audio() +{ + self thread stop_dog_sound_on_death(); + self endon( "death" ); + self waittill_any( "dog_running", "dog_combat" ); + self playsound( "zmb_hellhound_vocals_close" ); + wait 3; + while ( 1 ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + vectorAngle = vectorToAngles( self.origin - players[ i ].origin ); + dogangle = AbsAngleClamp180( vectorAngle[ 1 ] - players[ i ].angles[ 1 ] ); + if ( isalive( players[ i ] ) && !isDefined( players[ i ].revivetrigger ) ) + { + if ( Abs( dogangle ) > 90 && distance2d( self.origin, players[ i ].origin ) > 100 ) + { + self playsound( "zmb_hellhound_vocals_close" ); + wait 3; + } + } + i++; + } + wait 0.75; + } +} + +dog_clip_monitor() +{ + clips_on = 0; + level.dog_clips = getentarray( "dog_clips", "targetname" ); + while ( 1 ) + { + i = 0; + while ( i < level.dog_clips.size ) + { + level.dog_clips[ i ] trigger_off(); + level.dog_clips[ i ] connectpaths(); + i++; + } + flag_wait( "dog_clips" ); + if ( isDefined( level.no_dog_clip ) && level.no_dog_clip == 1 ) + { + return; + } + i = 0; + while ( i < level.dog_clips.size ) + { + level.dog_clips[ i ] trigger_on(); + level.dog_clips[ i ] disconnectpaths(); + wait_network_frame(); + i++; + } + dog_is_alive = 1; + while ( dog_is_alive || flag( "dog_round" ) ) + { + dog_is_alive = 0; + dogs = getentarray( "zombie_dog", "targetname" ); + i = 0; + while ( i < dogs.size ) + { + if ( isalive( dogs[ i ] ) ) + { + dog_is_alive = 1; + } + i++; + } + wait 1; + } + flag_clear( "dog_clips" ); + wait 1; + } +} + +special_dog_spawn( spawners, num_to_spawn ) +{ + dogs = getaispeciesarray( "all", "zombie_dog" ); + if ( isDefined( dogs ) && dogs.size >= 9 ) + { + return 0; + } + if ( !isDefined( num_to_spawn ) ) + { + num_to_spawn = 1; + } + spawn_point = undefined; + count = 0; + while ( count < num_to_spawn ) + { + players = get_players(); + favorite_enemy = get_favorite_enemy(); + if ( isDefined( spawners ) ) + { + spawn_point = spawners[ randomint( spawners.size ) ]; + ai = spawn_zombie( spawn_point ); + if ( isDefined( ai ) ) + { + ai.favoriteenemy = favorite_enemy; + spawn_point thread dog_spawn_fx( ai ); + count++; + flag_set( "dog_clips" ); + } + } + else if ( isDefined( level.dog_spawn_func ) ) + { + spawn_loc = [[ level.dog_spawn_func ]]( level.dog_spawners, favorite_enemy ); + ai = spawn_zombie( level.dog_spawners[ 0 ] ); + if ( isDefined( ai ) ) + { + ai.favoriteenemy = favorite_enemy; + spawn_loc thread dog_spawn_fx( ai, spawn_loc ); + count++; + flag_set( "dog_clips" ); + } + } + else + { + spawn_point = dog_spawn_factory_logic( level.enemy_dog_spawns, favorite_enemy ); + ai = spawn_zombie( level.dog_spawners[ 0 ] ); + if ( isDefined( ai ) ) + { + ai.favoriteenemy = favorite_enemy; + spawn_point thread dog_spawn_fx( ai, spawn_point ); + count++; + flag_set( "dog_clips" ); + } + } + waiting_for_next_dog_spawn( count, num_to_spawn ); + } + return 1; +} + +dog_run_think() +{ + self endon( "death" ); + self waittill( "visible" ); + if ( self.health > level.dog_health ) + { + self.maxhealth = level.dog_health; + self.health = level.dog_health; + } + maps/mp/zombies/_zm_net::network_safe_play_fx_on_tag( "dog_fx", 2, self.fx_dog_trail_type, self.fx_dog_trail, "tag_origin" ); + self playloopsound( self.fx_dog_trail_sound ); + while ( 1 ) + { + if ( !is_player_valid( self.favoriteenemy ) ) + { + self.favoriteenemy = get_favorite_enemy(); + } + wait 0.2; + } +} + +dog_stalk_audio() +{ + self endon( "death" ); + self endon( "dog_running" ); + self endon( "dog_combat" ); + while ( 1 ) + { + self playsound( "zmb_hellhound_vocals_amb" ); + wait randomfloatrange( 3, 6 ); + } +} + +dog_thundergun_knockdown( player, gib ) +{ + self endon( "death" ); + damage = int( self.maxhealth * 0.5 ); + self dodamage( damage, player.origin, player ); +} + + diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_faller.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_faller.gsc new file mode 100644 index 0000000..8a3191f --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_bot.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_bot.gsc new file mode 100644 index 0000000..bcef80d --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_bot.gsc @@ -0,0 +1,10 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ +/# + println( "ZM >> Zombiemode Server Scripts Init (_zm_bot.gsc)" ); +#/ +} diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_hacker.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_hacker.gsc new file mode 100644 index 0000000..29bb3d6 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equipment.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equipment.gsc new file mode 100644 index 0000000..a405923 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_boards.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_boards.gsc new file mode 100644 index 0000000..88fd512 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_box.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_box.gsc new file mode 100644 index 0000000..235fe8b --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_doors.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_doors.gsc new file mode 100644 index 0000000..1c632c5 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_packapunch.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_packapunch.gsc new file mode 100644 index 0000000..c9fba2a --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_perks.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_perks.gsc new file mode 100644 index 0000000..18cd74b --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_powerups.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_powerups.gsc new file mode 100644 index 0000000..318339f --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_wallbuys.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_wallbuys.gsc new file mode 100644 index 0000000..950a1a5 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_perk_electric_cherry.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_perk_electric_cherry.gsc new file mode 100644 index 0000000..802beb4 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_perk_electric_cherry.gsc @@ -0,0 +1,400 @@ +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/animscripts/shared; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +enable_electric_cherry_perk_for_level() +{ + register_perk_basic_info( "specialty_grenadepulldeath", "electric_cherry", 2000, &"ZM_PRISON_PERK_CHERRY", "zombie_perk_bottle_cherry" ); + register_perk_precache_func( "specialty_grenadepulldeath", ::electic_cherry_precache ); + register_perk_clientfields( "specialty_grenadepulldeath", ::electric_cherry_register_clientfield, ::electric_cherry_set_clientfield ); + register_perk_threads( "specialty_grenadepulldeath", ::electric_cherry_reload_attack, ::electric_cherry_perk_lost ); + register_perk_machine( "specialty_grenadepulldeath", ::electric_cherry_perk_machine_setup, ::electric_cherry_perk_machine_think ); + register_perk_host_migration_func( "specialty_grenadepulldeath", ::electric_cherry_host_migration_func ); + if ( isDefined( level.custom_electric_cherry_perk_threads ) && level.custom_electric_cherry_perk_threads ) + { + level thread [[ level.custom_electric_cherry_perk_threads ]](); + } +} + +init_electric_cherry() +{ + level.custom_laststand_func = ::electric_cherry_laststand; + set_zombie_var( "tesla_head_gib_chance", 50 ); + registerclientfield( "allplayers", "electric_cherry_reload_fx", 9000, 2, "int" ); +} + +electic_cherry_precache() +{ + precacheitem( "zombie_perk_bottle_cherry" ); + precacheshader( "specialty_fastreload_zombies" ); + precachemodel( "p6_zm_vending_electric_cherry_off" ); + precachemodel( "p6_zm_vending_electric_cherry_on" ); + precachestring( &"ZM_PRISON_PERK_CHERRY" ); + level._effect[ "electriccherry" ] = loadfx( "misc/fx_zombie_cola_on" ); + level._effect[ "electric_cherry_explode" ] = loadfx( "maps/zombie_alcatraz/fx_alcatraz_electric_cherry_down" ); + level._effect[ "electric_cherry_reload_small" ] = loadfx( "maps/zombie_alcatraz/fx_alcatraz_electric_cherry_sm" ); + level._effect[ "electric_cherry_reload_medium" ] = loadfx( "maps/zombie_alcatraz/fx_alcatraz_electric_cherry_player" ); + level._effect[ "electric_cherry_reload_large" ] = loadfx( "maps/zombie_alcatraz/fx_alcatraz_electric_cherry_lg" ); + level._effect[ "tesla_shock" ] = loadfx( "maps/zombie/fx_zombie_tesla_shock" ); + level._effect[ "tesla_shock_secondary" ] = loadfx( "maps/zombie/fx_zombie_tesla_shock_secondary" ); +} + +electric_cherry_register_clientfield() +{ + registerclientfield( "toplayer", "perk_electric_cherry", 9000, 1, "int" ); +} + +electric_cherry_set_clientfield( state ) +{ + self setclientfieldtoplayer( "perk_electric_cherry", state ); +} + +electric_cherry_perk_machine_setup( use_trigger, perk_machine, bump_trigger, collision ) +{ + use_trigger.script_sound = "mus_perks_cherry_jingle"; + use_trigger.script_string = "electric_cherry_perk"; + use_trigger.script_label = "mus_perks_cherry_sting"; + use_trigger.target = "vending_electriccherry"; + perk_machine.script_string = "electriccherry_perk"; + perk_machine.targetname = "vendingelectric_cherry"; + if ( isDefined( bump_trigger ) ) + { + bump_trigger.script_string = "electriccherry_perk"; + } +} + +electric_cherry_perk_machine_think() +{ + init_electric_cherry(); + while ( 1 ) + { + machine = getentarray( "vendingelectric_cherry", "targetname" ); + machine_triggers = getentarray( "vending_electriccherry", "target" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( "p6_zm_vending_electric_cherry_off" ); + i++; + } + level thread do_initial_power_off_callback( machine, "electriccherry" ); + array_thread( machine_triggers, ::set_power_on, 0 ); + level waittill( "electric_cherry_on" ); + i = 0; + while ( i < machine.size ) + { + machine[ i ] setmodel( "p6_zm_vending_electric_cherry_on" ); + 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( "electriccherry" ); + machine[ i ] thread play_loop_on_machine(); + i++; + } + level notify( "specialty_grenadepulldeath_power_on" ); + array_thread( machine_triggers, ::set_power_on, 1 ); + level waittill( "electric_cherry_off" ); + array_thread( machine, ::turn_perk_off ); + } +} + +electric_cherry_host_migration_func() +{ + a_electric_cherry_perk_machines = getentarray( "vending_electriccherry", "targetname" ); + _a130 = a_electric_cherry_perk_machines; + _k130 = getFirstArrayKey( _a130 ); + while ( isDefined( _k130 ) ) + { + perk_machine = _a130[ _k130 ]; + if ( isDefined( perk_machine.model ) && perk_machine.model == "p6_zm_vending_electric_cherry_on" ) + { + perk_machine perk_fx( undefined, 1 ); + perk_machine thread perk_fx( "electriccherry" ); + } + _k130 = getNextArrayKey( _a130, _k130 ); + } +} + +electric_cherry_laststand() +{ + visionsetlaststand( "zombie_last_stand", 1 ); + if ( isDefined( self ) ) + { + playfx( level._effect[ "electric_cherry_explode" ], self.origin ); + self playsound( "zmb_cherry_explode" ); + self notify( "electric_cherry_start" ); + wait 0.05; + a_zombies = get_round_enemy_array(); + a_zombies = get_array_of_closest( self.origin, a_zombies, undefined, undefined, 500 ); + i = 0; + while ( i < a_zombies.size ) + { + if ( isalive( self ) ) + { + + if ( a_zombies[ i ].health <= 1000 ) + { + a_zombies[ i ] thread electric_cherry_death_fx(); + if ( isDefined( self.cherry_kills ) ) + { + self.cherry_kills++; + } + self maps/mp/zombies/_zm_score::add_to_player_score( 40 ); + } + else + { + a_zombies[ i ] thread electric_cherry_stun(); + a_zombies[ i ] thread electric_cherry_shock_fx(); + } + wait 0.1; + a_zombies[ i ] dodamage( 1000, self.origin, self, self, "none" ); + } + i++; + } + self notify( "electric_cherry_end" ); + } +} + +electric_cherry_death_fx() +{ + self endon( "death" ); + tag = "J_SpineUpper"; + fx = "tesla_shock"; + if ( self.isdog ) + { + tag = "J_Spine1"; + } + self playsound( "zmb_elec_jib_zombie" ); + network_safe_play_fx_on_tag( "tesla_death_fx", 2, level._effect[ fx ], self, tag ); + if ( isDefined( self.tesla_head_gib_func ) && !self.head_gibbed ) + { + [[ self.tesla_head_gib_func ]](); + } +} + +electric_cherry_shock_fx() +{ + self endon( "death" ); + tag = "J_SpineUpper"; + fx = "tesla_shock_secondary"; + if ( self.isdog ) + { + tag = "J_Spine1"; + } + self playsound( "zmb_elec_jib_zombie" ); + network_safe_play_fx_on_tag( "tesla_shock_fx", 2, level._effect[ fx ], self, tag ); +} + +electric_cherry_stun() +{ + self endon( "death" ); + self notify( "stun_zombie" ); + self endon( "stun_zombie" ); + if ( self.health <= 0 ) + { +/# + iprintln( "trying to stun a dead zombie" ); +#/ + return; + } + if ( self.ai_state != "find_flesh" ) + { + return; + } + self.forcemovementscriptstate = 1; + self.ignoreall = 1; + i = 0; + while ( i < 2 ) + { + self animscripted( self.origin, self.angles, "zm_afterlife_stun" ); + self maps/mp/animscripts/shared::donotetracks( "stunned" ); + i++; + } + self.forcemovementscriptstate = 0; + self.ignoreall = 0; + self setgoalpos( self.origin ); + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +electric_cherry_reload_attack() +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "stop_electric_cherry_reload_attack" ); + self.wait_on_reload = []; + self.consecutive_electric_cherry_attacks = 0; + while ( 1 ) + { + self waittill( "reload_start" ); + str_current_weapon = self getcurrentweapon(); + while ( isinarray( self.wait_on_reload, str_current_weapon ) ) + { + continue; + } + self.wait_on_reload[ self.wait_on_reload.size ] = str_current_weapon; + self.consecutive_electric_cherry_attacks++; + n_clip_current = self getweaponammoclip( str_current_weapon ); + n_clip_max = weaponclipsize( str_current_weapon ); + n_fraction = n_clip_current / n_clip_max; + perk_radius = linear_map( n_fraction, 1, 0, 32, 128 ); + perk_dmg = linear_map( n_fraction, 1, 0, 1, 1045 ); + self thread check_for_reload_complete( str_current_weapon ); + if ( isDefined( self ) ) + { + switch( self.consecutive_electric_cherry_attacks ) + { + case 0: + case 1: + n_zombie_limit = undefined; + break; + case 2: + n_zombie_limit = 8; + break; + case 3: + n_zombie_limit = 4; + break; + case 4: + n_zombie_limit = 2; + break; + case default: + n_zombie_limit = 0; + } + self thread electric_cherry_cooldown_timer( str_current_weapon ); + if ( isDefined( n_zombie_limit ) && n_zombie_limit == 0 ) + { + continue; + } + self thread electric_cherry_reload_fx( n_fraction ); + self notify( "electric_cherry_start" ); + self playsound( "zmb_cherry_explode" ); + a_zombies = get_round_enemy_array(); + a_zombies = get_array_of_closest( self.origin, a_zombies, undefined, undefined, perk_radius ); + n_zombies_hit = 0; + i = 0; + while ( i < a_zombies.size ) + { + if ( isalive( self ) ) + { + if ( isDefined( n_zombie_limit ) ) + { + if ( n_zombies_hit < n_zombie_limit ) + { + n_zombies_hit++; + } + else + { + break; + } + } + if ( a_zombies[ i ].health <= perk_dmg ) + { + a_zombies[ i ] thread electric_cherry_death_fx(); + if ( isDefined( self.cherry_kills ) ) + { + self.cherry_kills++; + } + self maps/mp/zombies/_zm_score::add_to_player_score( 40 ); + } + else + { + if ( !isDefined( a_zombies[ i ].is_brutus ) ) + { + a_zombies[ i ] thread electric_cherry_stun(); + } + a_zombies[ i ] thread electric_cherry_shock_fx(); + } + wait 0.1; + a_zombies[ i ] dodamage( perk_dmg, self.origin, self, self, "none" ); + } + i++; + } + self notify( "electric_cherry_end" ); + } + } +} + +electric_cherry_cooldown_timer( str_current_weapon ) +{ + self notify( "electric_cherry_cooldown_started" ); + self endon( "electric_cherry_cooldown_started" ); + self endon( "death" ); + self endon( "disconnect" ); + n_reload_time = weaponreloadtime( str_current_weapon ); + if ( self hasperk( "specialty_fastreload" ) ) + { + n_reload_time *= getDvarFloat( "perk_weapReloadMultiplier" ); + } + n_cooldown_time = n_reload_time + 3; + wait n_cooldown_time; + self.consecutive_electric_cherry_attacks = 0; +} + +check_for_reload_complete( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "player_lost_weapon_" + weapon ); + self thread weapon_replaced_monitor( weapon ); + while ( 1 ) + { + self waittill( "reload" ); + str_current_weapon = self getcurrentweapon(); + if ( str_current_weapon == weapon ) + { + arrayremovevalue( self.wait_on_reload, weapon ); + self notify( "weapon_reload_complete_" + weapon ); + return; + } + else + { + } + } +} + +weapon_replaced_monitor( weapon ) +{ + self endon( "death" ); + self endon( "disconnect" ); + self endon( "weapon_reload_complete_" + weapon ); + while ( 1 ) + { + self waittill( "weapon_change" ); + primaryweapons = self getweaponslistprimaries(); + if ( !isinarray( primaryweapons, weapon ) ) + { + self notify( "player_lost_weapon_" + weapon ); + arrayremovevalue( self.wait_on_reload, weapon ); + return; + } + else + { + } + } +} + +electric_cherry_reload_fx( n_fraction ) +{ + if ( n_fraction >= 0.67 ) + { + self setclientfield( "electric_cherry_reload_fx", 1 ); + } + else if ( n_fraction >= 0.33 && n_fraction < 0.67 ) + { + self setclientfield( "electric_cherry_reload_fx", 2 ); + } + else + { + self setclientfield( "electric_cherry_reload_fx", 3 ); + } + wait 1; + self setclientfield( "electric_cherry_reload_fx", 0 ); +} + +electric_cherry_perk_lost() +{ + self notify( "stop_electric_cherry_reload_attack" ); +} + diff --git a/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades.gsc new file mode 100644 index 0000000..51249f7 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_functions.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_functions.gsc new file mode 100644 index 0000000..013cbf2 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_system.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_system.gsc new file mode 100644 index 0000000..8882282 --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_score.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_score.gsc new file mode 100644 index 0000000..6d833af --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_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/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_tombstone.gsc b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_tombstone.gsc new file mode 100644 index 0000000..1833f9b --- /dev/null +++ b/patch_zm/maps/mp/zombies/NoKnownErrors/_zm_tombstone.gsc @@ -0,0 +1,540 @@ +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_weap_cymbal_monkey; +#include maps/mp/zombies/_zm_melee_weapon; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/_utility; + +init() +{ + onplayerconnect_callback( ::tombstone_player_init ); + level.tombstone_laststand_func = ::tombstone_laststand; + level.tombstone_spawn_func = ::tombstone_spawn; + level thread tombstone_hostmigration(); + if ( isDefined( level.zombiemode_using_tombstone_perk ) && level.zombiemode_using_tombstone_perk ) + { + add_custom_limited_weapon_check( ::is_weapon_available_in_tombstone ); + } +} + +tombstone_player_init() +{ + while ( !isDefined( self.tombstone_index ) ) + { + wait 0.1; + } + level.tombstones[ self.tombstone_index ] = spawnstruct(); +} + +tombstone_spawn() +{ + dc = spawn( "script_model", self.origin + vectorScale( ( 0, 0, 1 ), 40 ) ); + dc.angles = self.angles; + dc setmodel( "tag_origin" ); + dc_icon = spawn( "script_model", self.origin + vectorScale( ( 0, 0, 1 ), 40 ) ); + dc_icon.angles = self.angles; + dc_icon setmodel( "ch_tombstone1" ); + dc_icon linkto( dc ); + dc.icon = dc_icon; + dc.script_noteworthy = "player_tombstone_model"; + dc.player = self; + self thread tombstone_clear(); + dc thread tombstone_wobble(); + dc thread tombstone_revived( self ); + result = self waittill_any_return( "player_revived", "spawned_player", "disconnect" ); + if ( result == "player_revived" || result == "disconnect" ) + { + dc notify( "tombstone_timedout" ); + dc_icon unlink(); + dc_icon delete(); + dc delete(); + return; + } + dc thread tombstone_timeout(); + dc thread tombstone_grab(); +} + +tombstone_clear() +{ + result = self waittill_any_return( "tombstone_timedout", "tombstone_grabbed" ); + level.tombstones[ self.tombstone_index ] = spawnstruct(); +} + +tombstone_revived( player ) +{ + self endon( "tombstone_timedout" ); + player endon( "disconnect" ); + shown = 1; + while ( isDefined( self ) && isDefined( player ) ) + { + if ( isDefined( player.revivetrigger ) && isDefined( player.revivetrigger.beingrevived ) && player.revivetrigger.beingrevived ) + { + if ( shown ) + { + shown = 0; + self.icon hide(); + } + } + else + { + if ( !shown ) + { + shown = 1; + self.icon show(); + } + } + wait 0.05; + } +} + +tombstone_laststand() +{ + primaries = self getweaponslistprimaries(); + currentweapon = self getcurrentweapon(); + dc = level.tombstones[ self.tombstone_index ]; + dc.player = self; + dc.weapon = []; + dc.current_weapon = -1; + _a134 = primaries; + index = getFirstArrayKey( _a134 ); + while ( isDefined( index ) ) + { + weapon = _a134[ index ]; + dc.weapon[ index ] = weapon; + dc.stockcount[ index ] = self getweaponammostock( weapon ); + if ( weapon == currentweapon ) + { + dc.current_weapon = index; + } + index = getNextArrayKey( _a134, index ); + } + if ( isDefined( self.hasriotshield ) && self.hasriotshield ) + { + dc.hasriotshield = 1; + } + dc save_weapons_for_tombstone( self ); + if ( self hasweapon( "claymore_zm" ) ) + { + dc.hasclaymore = 1; + dc.claymoreclip = self getweaponammoclip( "claymore_zm" ); + } + if ( self hasweapon( "emp_grenade_zm" ) ) + { + dc.hasemp = 1; + dc.empclip = self getweaponammoclip( "emp_grenade_zm" ); + } + dc.perk = tombstone_save_perks( self ); + lethal_grenade = self get_player_lethal_grenade(); + if ( self hasweapon( lethal_grenade ) ) + { + dc.grenade = self getweaponammoclip( lethal_grenade ); + } + else + { + dc.grenade = 0; + } + if ( maps/mp/zombies/_zm_weap_cymbal_monkey::cymbal_monkey_exists() ) + { + dc.zombie_cymbal_monkey_count = self getweaponammoclip( "cymbal_monkey_zm" ); + } +} + +tombstone_save_perks( ent ) +{ + perk_array = []; + if ( ent hasperk( "specialty_armorvest" ) ) + { + perk_array[ perk_array.size ] = "specialty_armorvest"; + } + if ( ent hasperk( "specialty_deadshot" ) ) + { + perk_array[ perk_array.size ] = "specialty_deadshot"; + } + if ( ent hasperk( "specialty_fastreload" ) ) + { + perk_array[ perk_array.size ] = "specialty_fastreload"; + } + if ( ent hasperk( "specialty_flakjacket" ) ) + { + perk_array[ perk_array.size ] = "specialty_flakjacket"; + } + if ( ent hasperk( "specialty_longersprint" ) ) + { + perk_array[ perk_array.size ] = "specialty_longersprint"; + } + if ( ent hasperk( "specialty_quickrevive" ) ) + { + perk_array[ perk_array.size ] = "specialty_quickrevive"; + } + if ( ent hasperk( "specialty_rof" ) ) + { + perk_array[ perk_array.size ] = "specialty_rof"; + } + return perk_array; +} + +tombstone_grab() +{ + self endon( "tombstone_timedout" ); + wait 1; + while ( isDefined( self ) ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].is_zombie ) + { + i++; + continue; + } + else + { + if ( isDefined( self.player ) && players[ i ] == self.player ) + { + tombstone_machine_triggers = getentarray( "specialty_scavenger", "script_noteworthy" ); + istombstonepowered = 0; + _a258 = tombstone_machine_triggers; + _k258 = getFirstArrayKey( _a258 ); + while ( isDefined( _k258 ) ) + { + trigger = _a258[ _k258 ]; + if ( isDefined( trigger.power_on ) || trigger.power_on && isDefined( trigger.turbine_power_on ) && trigger.turbine_power_on ) + { + istombstonepowered = 1; + } + _k258 = getNextArrayKey( _a258, _k258 ); + } + if ( istombstonepowered ) + { + dist = distance( players[ i ].origin, self.origin ); + if ( dist < 64 ) + { + playfx( level._effect[ "powerup_grabbed" ], self.origin ); + playfx( level._effect[ "powerup_grabbed_wave" ], self.origin ); + players[ i ] tombstone_give(); + wait 0.1; + playsoundatposition( "zmb_tombstone_grab", self.origin ); + self stoploopsound(); + self.icon unlink(); + self.icon delete(); + self delete(); + self notify( "tombstone_grabbed" ); + players[ i ] clientnotify( "dc0" ); + players[ i ] notify( "dance_on_my_grave" ); + } + } + } + } + i++; + } + wait_network_frame(); + } +} + +tombstone_give() +{ + dc = level.tombstones[ self.tombstone_index ]; + while ( !flag( "solo_game" ) ) + { + primaries = self getweaponslistprimaries(); + while ( dc.weapon.size > 1 || primaries.size > 1 ) + { + _a310 = primaries; + _k310 = getFirstArrayKey( _a310 ); + while ( isDefined( _k310 ) ) + { + weapon = _a310[ _k310 ]; + self takeweapon( weapon ); + _k310 = getNextArrayKey( _a310, _k310 ); + } + } + i = 0; + while ( i < dc.weapon.size ) + { + if ( !isDefined( dc.weapon[ i ] ) ) + { + i++; + continue; + } + else if ( dc.weapon[ i ] == "none" ) + { + i++; + continue; + } + else + { + weapon = dc.weapon[ i ]; + stock = dc.stockcount[ i ]; + if ( !self hasweapon( weapon ) ) + { + self giveweapon( weapon, 0, self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); + self setweaponammoclip( weapon, weaponclipsize( weapon ) ); + self setweaponammostock( weapon, stock ); + if ( i == dc.current_weapon ) + { + self switchtoweapon( weapon ); + } + } + } + i++; + } + } + if ( isDefined( dc.hasriotshield ) && dc.hasriotshield ) + { + self maps/mp/zombies/_zm_equipment::equipment_give( "riotshield_zm" ); + if ( isDefined( self.player_shield_reset_health ) ) + { + self [[ self.player_shield_reset_health ]](); + } + } + dc restore_weapons_for_tombstone( self ); + if ( isDefined( dc.hasclaymore ) && dc.hasclaymore && !self hasweapon( "claymore_zm" ) ) + { + self giveweapon( "claymore_zm" ); + self set_player_placeable_mine( "claymore_zm" ); + self setactionslot( 4, "weapon", "claymore_zm" ); + self setweaponammoclip( "claymore_zm", dc.claymoreclip ); + } + if ( isDefined( dc.hasemp ) && dc.hasemp ) + { + self giveweapon( "emp_grenade_zm" ); + self setweaponammoclip( "emp_grenade_zm", dc.empclip ); + } + while ( isDefined( dc.perk ) && dc.perk.size > 0 ) + { + i = 0; + while ( i < dc.perk.size ) + { + if ( self hasperk( dc.perk[ i ] ) ) + { + i++; + continue; + } + else if ( dc.perk[ i ] == "specialty_quickrevive" && flag( "solo_game" ) ) + { + i++; + continue; + } + else + { + maps/mp/zombies/_zm_perks::give_perk( dc.perk[ i ] ); + } + i++; + } + } + if ( dc.grenade > 0 && !flag( "solo_game" ) ) + { + curgrenadecount = 0; + if ( self hasweapon( self get_player_lethal_grenade() ) ) + { + self getweaponammoclip( self get_player_lethal_grenade() ); + } + else + { + self giveweapon( self get_player_lethal_grenade() ); + } + self setweaponammoclip( self get_player_lethal_grenade(), dc.grenade + curgrenadecount ); + } + if ( maps/mp/zombies/_zm_weap_cymbal_monkey::cymbal_monkey_exists() && !flag( "solo_game" ) ) + { + if ( dc.zombie_cymbal_monkey_count ) + { + self maps/mp/zombies/_zm_weap_cymbal_monkey::player_give_cymbal_monkey(); + self setweaponammoclip( "cymbal_monkey_zm", dc.zombie_cymbal_monkey_count ); + } + } +} + +tombstone_wobble() +{ + self endon( "tombstone_grabbed" ); + self endon( "tombstone_timedout" ); + if ( isDefined( self ) ) + { + wait 1; + playfxontag( level._effect[ "powerup_on" ], self, "tag_origin" ); + self playsound( "zmb_tombstone_spawn" ); + self playloopsound( "zmb_tombstone_looper" ); + } + while ( isDefined( self ) ) + { + self rotateyaw( 360, 3 ); + wait 2.9; + } +} + +tombstone_timeout() +{ + self endon( "tombstone_grabbed" ); + self thread playtombstonetimeraudio(); + wait 48.5; + i = 0; + while ( i < 40 ) + { + if ( i % 2 ) + { + self.icon ghost(); + } + else + { + self.icon show(); + } + if ( i < 15 ) + { + wait 0.5; + i++; + continue; + } + else if ( i < 25 ) + { + wait 0.25; + i++; + continue; + } + else + { + wait 0.1; + } + i++; + } + self notify( "tombstone_timedout" ); + self.icon unlink(); + self.icon delete(); + self delete(); +} + +playtombstonetimeraudio() +{ + self endon( "tombstone_grabbed" ); + self endon( "tombstone_timedout" ); + player = self.player; + self thread playtombstonetimerout( player ); + while ( 1 ) + { + player playsoundtoplayer( "zmb_tombstone_timer_count", player ); + wait 1; + } +} + +playtombstonetimerout( player ) +{ + self endon( "tombstone_grabbed" ); + self waittill( "tombstone_timedout" ); + player playsoundtoplayer( "zmb_tombstone_timer_out", player ); +} + +save_weapons_for_tombstone( player ) +{ + self.tombstone_melee_weapons = []; + i = 0; + while ( i < level._melee_weapons.size ) + { + self save_weapon_for_tombstone( player, level._melee_weapons[ i ].weapon_name ); + i++; + } +} + +save_weapon_for_tombstone( player, weapon_name ) +{ + if ( player hasweapon( weapon_name ) ) + { + self.tombstone_melee_weapons[ weapon_name ] = 1; + } +} + +restore_weapons_for_tombstone( player ) +{ + i = 0; + while ( i < level._melee_weapons.size ) + { + self restore_weapon_for_tombstone( player, level._melee_weapons[ i ].weapon_name ); + i++; + } + self.tombstone_melee_weapons = undefined; +} + +restore_weapon_for_tombstone( player, weapon_name ) +{ + if ( isDefined( weapon_name ) || !isDefined( self.tombstone_melee_weapons ) && !isDefined( self.tombstone_melee_weapons[ weapon_name ] ) ) + { + return; + } + if ( isDefined( self.tombstone_melee_weapons[ weapon_name ] ) && self.tombstone_melee_weapons[ weapon_name ] ) + { + player giveweapon( weapon_name ); + player change_melee_weapon( weapon_name, "none" ); + self.tombstone_melee_weapons[ weapon_name ] = 0; + } +} + +tombstone_hostmigration() +{ + level endon( "end_game" ); + level notify( "tombstone_hostmigration" ); + level endon( "tombstone_hostmigration" ); + while ( 1 ) + { + level waittill( "host_migration_end" ); + tombstones = getentarray( "player_tombstone_model", "script_noteworthy" ); + _a580 = tombstones; + _k580 = getFirstArrayKey( _a580 ); + while ( isDefined( _k580 ) ) + { + model = _a580[ _k580 ]; + playfxontag( level._effect[ "powerup_on" ], model, "tag_origin" ); + _k580 = getNextArrayKey( _a580, _k580 ); + } + } +} + +is_weapon_available_in_tombstone( weapon, player_to_check ) +{ + count = 0; + upgradedweapon = weapon; + if ( isDefined( level.zombie_weapons[ weapon ] ) && isDefined( level.zombie_weapons[ weapon ].upgrade_name ) ) + { + upgradedweapon = level.zombie_weapons[ weapon ].upgrade_name; + } + tombstone_index = 0; + while ( tombstone_index < level.tombstones.size ) + { + dc = level.tombstones[ tombstone_index ]; + if ( !isDefined( dc.weapon ) ) + { + tombstone_index++; + continue; + } + else if ( isDefined( player_to_check ) && dc.player != player_to_check ) + { + tombstone_index++; + continue; + } + else + { + weapon_index = 0; + while ( weapon_index < dc.weapon.size ) + { + if ( !isDefined( dc.weapon[ weapon_index ] ) ) + { + weapon_index++; + continue; + } + else + { + tombstone_weapon = dc.weapon[ weapon_index ]; + if ( tombstone_weapon == weapon || tombstone_weapon == upgradedweapon ) + { + count++; + } + } + weapon_index++; + } + } + tombstone_index++; + } + return count; +} + diff --git a/patch_zm/maps/mp/zombies/_load.gsc b/patch_zm/maps/mp/zombies/_load.gsc new file mode 100644 index 0000000..cd154dd --- /dev/null +++ b/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/patch_zm/maps/mp/zombies/_zm.gsc b/patch_zm/maps/mp/zombies/_zm.gsc new file mode 100644 index 0000000..e1a91bc --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm.gsc @@ -0,0 +1,6093 @@ +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/gametypes_zm/_weapons; +#include maps/mp/zombies/_zm_pers_upgrades_system; +#include maps/mp/zombies/_zm_ai_dogs; +#include maps/mp/zombies/_zm_melee_weapon; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/gametypes_zm/_zm_gametype; +#include maps/mp/zombies/_zm_pers_upgrades; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_ffotd; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_blockers; + +init() +{ + + level.player_out_of_playable_area_monitor = 1; + level.player_too_many_weapons_monitor = 1; + level.player_too_many_weapons_monitor_func = ::player_too_many_weapons_monitor; + level.player_too_many_players_check = 1; + level.player_too_many_players_check_func = ::player_too_many_players_check; + level._use_choke_weapon_hints = 1; + level._use_choke_blockers = 1; + level.passed_introscreen = 0; + if ( !isDefined( level.custom_ai_type ) ) + { + level.custom_ai_type = []; + } + level.custom_ai_spawn_check_funcs = []; + level.spawn_funcs = []; + level.spawn_funcs[ "allies" ] = []; + level.spawn_funcs[ "axis" ] = []; + level.spawn_funcs[ "team3" ] = []; + level thread maps/mp/zombies/_zm_ffotd::main_start(); + level.zombiemode = 1; + level.revivefeature = 0; + level.swimmingfeature = 0; + level.calc_closest_player_using_paths = 0; + level.zombie_melee_in_water = 1; + level.put_timed_out_zombies_back_in_queue = 1; + level.use_alternate_poi_positioning = 1; + level.zmb_laugh_alias = "zmb_laugh_richtofen"; + level.sndannouncerisrich = 1; + level.scr_zm_ui_gametype = getDvar( "ui_gametype" ); + level.scr_zm_ui_gametype_group = getDvar( "ui_zm_gamemodegroup" ); + level.scr_zm_map_start_location = getDvar( "ui_zm_mapstartlocation" ); + level.curr_gametype_affects_rank = 0; + gametype = tolower( getDvar( "g_gametype" ) ); + if ( gametype == "zclassic" || gametype == "zstandard" ) + { + level.curr_gametype_affects_rank = 1; + } + level.grenade_multiattack_bookmark_count = 1; + level.rampage_bookmark_kill_times_count = 3; + level.rampage_bookmark_kill_times_msec = 6000; + level.rampage_bookmark_kill_times_delay = 6000; + level thread watch_rampage_bookmark(); + if ( !isDefined( level._zombies_round_spawn_failsafe ) ) + { + level._zombies_round_spawn_failsafe = ::round_spawn_failsafe; + } + level.zombie_visionset = "zombie_neutral"; + if ( getDvar( "anim_intro" ) == "1" ) + { + level.zombie_anim_intro = 1; + } + else + { + level.zombie_anim_intro = 0; + } + precache_shaders(); + precache_models(); + precacherumble( "explosion_generic" ); + precacherumble( "dtp_rumble" ); + precacherumble( "slide_rumble" ); + precache_zombie_leaderboards(); + level._zombie_gib_piece_index_all = 0; + level._zombie_gib_piece_index_right_arm = 1; + level._zombie_gib_piece_index_left_arm = 2; + level._zombie_gib_piece_index_right_leg = 3; + level._zombie_gib_piece_index_left_leg = 4; + level._zombie_gib_piece_index_head = 5; + level._zombie_gib_piece_index_guts = 6; + level._zombie_gib_piece_index_hat = 7; + if ( !isDefined( level.zombie_ai_limit ) ) + { + level.zombie_ai_limit = 24; + } + if ( !isDefined( level.zombie_actor_limit ) ) + { + level.zombie_actor_limit = 31; + } + maps/mp/_visionset_mgr::init(); + init_dvars(); + init_strings(); + init_levelvars(); + init_sounds(); + init_shellshocks(); + init_flags(); + init_client_flags(); + registerclientfield( "world", "zombie_power_on", 1, 1, "int" ); + if ( isDefined( level._no_navcards ) && !level._no_navcards ) + { + if ( level.scr_zm_ui_gametype_group == "zclassic" && !level.createfx_enabled ) + { + registerclientfield( "allplayers", "navcard_held", 1, 4, "int" ); + level.navcards = []; + level.navcards[ 0 ] = "navcard_held_zm_transit"; + level.navcards[ 1 ] = "navcard_held_zm_highrise"; + level.navcards[ 2 ] = "navcard_held_zm_buried"; + level thread setup_player_navcard_hud(); + } + } + register_offhand_weapons_for_level_defaults(); + level thread drive_client_connected_notifies(); + + //not the cause of the minidump + maps/mp/zombies/_zm_zonemgr::init(); + maps/mp/zombies/_zm_unitrigger::init(); + maps/mp/zombies/_zm_audio::init(); + maps/mp/zombies/_zm_blockers::init(); + maps/mp/zombies/_zm_bot::init(); + maps/mp/zombies/_zm_clone::init(); + maps/mp/zombies/_zm_buildables::init(); + maps/mp/zombies/_zm_equipment::init(); + maps/mp/zombies/_zm_laststand::init(); + maps/mp/zombies/_zm_magicbox::init(); + maps/mp/zombies/_zm_perks::init(); + + //causes the server to minidump + //maps/mp/zombies/_zm_playerhealth::init(); + + //ok + maps/mp/zombies/_zm_power::init(); + maps/mp/zombies/_zm_powerups::init(); + maps/mp/zombies/_zm_score::init(); + maps/mp/zombies/_zm_spawner::init(); + maps/mp/zombies/_zm_gump::init(); + + //causes the server to minidump + //maps/mp/zombies/_zm_timer::init(); + + //ok + maps/mp/zombies/_zm_traps::init(); + maps/mp/zombies/_zm_weapons::init(); + + init_function_overrides(); + level thread last_stand_pistol_rank_init(); + level thread maps/mp/zombies/_zm_tombstone::init(); + level thread post_all_players_connected(); + init_utility(); + maps/mp/_utility::registerclientsys( "lsm" ); + maps/mp/zombies/_zm_stats::init(); + initializestattracking(); + if ( get_players().size <= 1 ) + { + incrementcounter( "global_solo_games", 1 ); + } + else if ( level.systemlink ) + { + incrementcounter( "global_systemlink_games", 1 ); + } + else if ( getDvarInt( "splitscreen_playerCount" ) == get_players().size ) + { + incrementcounter( "global_splitscreen_games", 1 ); + } + else + { + incrementcounter( "global_coop_games", 1 ); + } + onplayerconnect_callback( ::zm_on_player_connect ); + maps/mp/zombies/_zm_pers_upgrades::pers_upgrade_init(); + set_demo_intermission_point(); + level thread maps/mp/zombies/_zm_ffotd::main_end(); + level thread track_players_intersection_tracker(); + level thread onallplayersready(); + level thread startunitriggers(); + level thread maps/mp/gametypes_zm/_zm_gametype::post_init_gametype(); + +} + +post_main() +{ + level thread init_custom_ai_type(); +} + +startunitriggers() +{ + flag_wait_any( "start_zombie_round_logic", "start_encounters_match_logic" ); + level thread maps/mp/zombies/_zm_unitrigger::main(); +} + +drive_client_connected_notifies() +{ + while ( 1 ) + { + level waittill( "connected", player ); + player reset_rampage_bookmark_kill_times(); + player callback( "on_player_connect" ); + } +} + +fade_out_intro_screen_zm( hold_black_time, fade_out_time, destroyed_afterwards ) +{ + 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; + if ( isDefined( hold_black_time ) ) + { + wait hold_black_time; + } + else + { + wait 0.2; + } + if ( !isDefined( fade_out_time ) ) + { + fade_out_time = 1.5; + } + level.introscreen fadeovertime( fade_out_time ); + level.introscreen.alpha = 0; + wait 1.6; + level.passed_introscreen = 1; + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] setclientuivisibilityflag( "hud_visible", 1 ); + if ( isDefined( level.host_ended_game ) && !level.host_ended_game ) + { + if ( isDefined( level.player_movement_suppressed ) ) + { + players[ i ] freezecontrols( level.player_movement_suppressed ); + /* +/# + println( " Unfreeze controls 4" ); +#/ + */ + i++; + continue; + } + else + { + if ( isDefined( players[ i ].hostmigrationcontrolsfrozen ) && !players[ i ].hostmigrationcontrolsfrozen ) + { + players[ i ] freezecontrols( 0 ); + /* +/# + println( " Unfreeze controls 5" ); +#/ + */ + } + } + } + i++; + } + if ( destroyed_afterwards == 1 ) + { + level.introscreen destroy(); + } + flag_set( "initial_blackscreen_passed" ); +} + +onallplayersready() +{ + timeout = getTime() + 5000; + while ( getnumexpectedplayers() == 0 && getTime() < timeout ) + { + wait 0.1; + } + /* +/# + println( "ZM >> player_count_expected=" + getnumexpectedplayers() ); +#/ + */ + player_count_actual = 0; + while ( getnumconnectedplayers() < getnumexpectedplayers() || player_count_actual != getnumexpectedplayers() ) + { + players = get_players(); + player_count_actual = 0; + i = 0; + while ( i < players.size ) + { + players[ i ] freezecontrols( 1 ); + if ( players[ i ].sessionstate == "playing" ) + { + player_count_actual++; + } + i++; + } + /* +/# + println( "ZM >> Num Connected =" + getnumconnectedplayers() + " Expected : " + getnumexpectedplayers() ); +#/ + */ + wait 0.1; + } + setinitialplayersconnected(); + /* +/# + println( "ZM >> We have all players - START ZOMBIE LOGIC" ); +#/ + */ + if ( getnumconnectedplayers() == 1 && getDvarInt( "scr_zm_enable_bots" ) == 1 ) + { + level thread add_bots(); + flag_set( "initial_players_connected" ); + } + else + { + players = get_players(); + if ( players.size == 1 ) + { + flag_set( "solo_game" ); + level.solo_lives_given = 0; + _a379 = players; + _k379 = getFirstArrayKey( _a379 ); + while ( isDefined( _k379 ) ) + { + player = _a379[ _k379 ]; + player.lives = 0; + _k379 = getNextArrayKey( _a379, _k379 ); + } + //level maps/mp/zombies/_zm::set_default_laststand_pistol( 1 ); + } + flag_set( "initial_players_connected" ); + while ( !aretexturesloaded() ) + { + wait 0.05; + } + thread start_zombie_logic_in_x_sec( 3 ); + } + fade_out_intro_screen_zm( 5, 1.5, 1 ); +} + +start_zombie_logic_in_x_sec( time_to_wait ) +{ + wait time_to_wait; + flag_set( "start_zombie_round_logic" ); +} + +getallotherplayers() +{ + aliveplayers = []; + i = 0; + while ( i < level.players.size ) + { + if ( !isDefined( level.players[ i ] ) ) + { + i++; + continue; + } + else player = level.players[ i ]; + if ( player.sessionstate != "playing" || player == self ) + { + i++; + continue; + } + else + { + aliveplayers[ aliveplayers.size ] = player; + } + i++; + } + return aliveplayers; +} + +getfreespawnpoint( spawnpoints, player ) +{ + if ( !isDefined( spawnpoints ) ) + { + /* +/# + iprintlnbold( "ZM >> No free spawn points in map" ); +#/ + */ + return undefined; + } + if ( !isDefined( game[ "spawns_randomized" ] ) ) + { + game[ "spawns_randomized" ] = 1; + spawnpoints = array_randomize( spawnpoints ); + random_chance = randomint( 100 ); + if ( random_chance > 50 ) + { + set_game_var( "side_selection", 1 ); + } + else + { + set_game_var( "side_selection", 2 ); + } + } + side_selection = get_game_var( "side_selection" ); + if ( get_game_var( "switchedsides" ) ) + { + if ( side_selection == 2 ) + { + side_selection = 1; + } + else + { + if ( side_selection == 1 ) + { + side_selection = 2; + } + } + } + while ( isDefined( player ) && isDefined( player.team ) ) + { + i = 0; + while ( isDefined( spawnpoints ) && i < spawnpoints.size ) + { + if ( side_selection == 1 ) + { + if ( player.team != "allies" && isDefined( spawnpoints[ i ].script_int ) && spawnpoints[ i ].script_int == 1 ) + { + arrayremovevalue( spawnpoints, spawnpoints[ i ] ); + i = 0; + } + else + { + if ( player.team == "allies" && isDefined( spawnpoints[ i ].script_int ) && spawnpoints[ i ].script_int == 2 ) + { + arrayremovevalue( spawnpoints, spawnpoints[ i ] ); + i = 0; + } + else + { + i++; + } + } + continue; + } + else if ( player.team == "allies" && isDefined( spawnpoints[ i ].script_int ) && spawnpoints[ i ].script_int == 1 ) + { + arrayremovevalue( spawnpoints, spawnpoints[ i ] ); + i = 0; + continue; + } + else + { + if ( player.team != "allies" && isDefined( spawnpoints[ i ].script_int ) && spawnpoints[ i ].script_int == 2 ) + { + arrayremovevalue( spawnpoints, spawnpoints[ i ] ); + i = 0; + } + else + { + i++; + } + } + } + } + if ( !isDefined( self.playernum ) ) + { + if ( self.team == "allies" ) + { + self.playernum = get_game_var( "_team1_num" ); + set_game_var( "_team1_num", self.playernum + 1 ); + } + else + { + self.playernum = get_game_var( "_team2_num" ); + set_game_var( "_team2_num", self.playernum + 1 ); + } + } + j = 0; + while ( j < spawnpoints.size ) + { + while ( !isDefined( spawnpoints[ j ].en_num ) ) + { + m = 0; + while ( m < spawnpoints.size ) + { + spawnpoints[ m ].en_num = m; + m++; + } + } + if ( spawnpoints[ j ].en_num == self.playernum ) + { + return spawnpoints[ j ]; + } + j++; + } + return spawnpoints[ 0 ]; +} + +delete_in_createfx() +{ + exterior_goals = getstructarray( "exterior_goal", "targetname" ); + i = 0; + while ( i < exterior_goals.size ) + { + if ( !isDefined( exterior_goals[ i ].target ) ) + { + i++; + continue; + } + else + { + targets = getentarray( exterior_goals[ i ].target, "targetname" ); + j = 0; + while ( j < targets.size ) + { + targets[ j ] self_delete(); + j++; + } + } + i++; + } + if ( isDefined( level.level_createfx_callback_thread ) ) + { + level thread [[ level.level_createfx_callback_thread ]](); + } +} + +add_bots() +{ + host = gethostplayer(); + while ( !isDefined( host ) ) + { + wait 0.05; + host = gethostplayer(); + } + wait 4; + zbot_spawn(); + setdvar( "bot_AllowMovement", "1" ); + setdvar( "bot_PressAttackBtn", "1" ); + setdvar( "bot_PressMeleeBtn", "1" ); + while ( get_players().size < 2 ) + { + wait 0.05; + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] freezecontrols( 0 ); + /* +/# + println( " Unfreeze controls 6" ); +#/ + */ + i++; + } + level.numberbotsadded = 1; + flag_set( "start_zombie_round_logic" ); +} + +zbot_spawn() +{ + player = gethostplayer(); + spawnpoints = getstructarray( "initial_spawn_points", "targetname" ); + spawnpoint = getfreespawnpoint( spawnpoints ); + bot = addtestclient(); + if ( !isDefined( bot ) ) + { + /* +/# + println( "Could not add test client" ); +#/ + */ + return; + } + bot.pers[ "isBot" ] = 1; + bot.equipment_enabled = 0; + yaw = spawnpoint.angles[ 1 ]; + bot thread zbot_spawn_think( spawnpoint.origin, yaw ); + return bot; +} + +zbot_spawn_think( origin, yaw ) +{ + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "spawned_player" ); + self setorigin( origin ); + angles = ( 0, yaw, 0 ); + self setplayerangles( angles ); + } +} + +post_all_players_connected() +{ + level thread end_game(); + flag_wait( "start_zombie_round_logic" ); + /* +/# + println( "sessions: mapname=", level.script, " gametype zom isserver 1 player_count=", get_players().size ); +#/ + */ + level thread clear_mature_blood(); + level thread round_end_monitor(); + if ( !level.zombie_anim_intro ) + { + if ( isDefined( level._round_start_func ) ) + { + level thread [[ level._round_start_func ]](); + } + } + level thread players_playing(); + disablegrenadesuicide(); + level.startinvulnerabletime = getDvarInt( "player_deathInvulnerableTime" ); + if ( !isDefined( level.music_override ) ) + { + level.music_override = 0; + } +} + +init_custom_ai_type() +{ + while ( isDefined( level.custom_ai_type ) ) + { + i = 0; + while ( i < level.custom_ai_type.size ) + { + [[ level.custom_ai_type[ i ] ]](); + i++; + } + } +} + +zombiemode_melee_miss() +{ + if ( isDefined( self.enemy.curr_pay_turret ) ) + { + self.enemy dodamage( getDvarInt( "ai_meleeDamage" ), self.origin, self, self, "none", "melee" ); + } +} + +player_track_ammo_count() +{ + self notify( "stop_ammo_tracking" ); + self endon( "disconnect" ); + self endon( "stop_ammo_tracking" ); + ammolowcount = 0; + ammooutcount = 0; + while ( 1 ) + { + wait 0.5; + weap = self getcurrentweapon(); + while ( isDefined( weap ) || weap == "none" && !can_track_ammo( weap ) ) + { + continue; + } + while ( self getammocount( weap ) > 5 || self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + ammooutcount = 0; + ammolowcount = 0; + } + if ( self getammocount( weap ) > 0 ) + { + if ( ammolowcount < 1 ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ammo_low" ); + ammolowcount++; + } + } + else + { + if ( ammooutcount < 1 ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "ammo_out" ); + ammooutcount++; + } + } + wait 20; + } +} + +can_track_ammo( weap ) +{ + if ( !isDefined( weap ) ) + { + return 0; + } + switch( weap ) + { + case "alcatraz_shield_zm": + case "chalk_draw_zm": + case "death_throe_zm": + case "equip_dieseldrone_zm": + case "equip_gasmask_zm": + case "humangun_upgraded_zm": + case "humangun_zm": + case "lower_equip_gasmask_zm": + case "no_hands_zm": + case "none": + case "riotshield_zm": + case "screecher_arms_zm": + case "slowgun_upgraded_zm": + case "slowgun_zm": + case "tazer_knuckles_upgraded_zm": + case "tazer_knuckles_zm": + case "time_bomb_detonator_zm": + case "time_bomb_zm": + case "zombie_bowie_flourish": + case "zombie_builder_zm": + case "zombie_fists_zm": + case "zombie_knuckle_crack": + case "zombie_sickle_flourish": + case "zombie_tazer_flourish": + return 0; + default: + if ( !is_zombie_perk_bottle( weap ) && !is_placeable_mine( weap ) && !is_equipment( weap ) && !issubstr( weap, "knife_ballistic_" ) && getsubstr( weap, 0, 3 ) != "gl_" || weaponfuellife( weap ) > 0 && weap == level.revive_tool ) + { + return 0; + } + } + return 1; +} + +spawn_vo() +{ + wait 1; + players = get_players(); + if ( players.size > 1 ) + { + player = random( players ); + index = maps/mp/zombies/_zm_weapons::get_player_index( player ); + player thread spawn_vo_player( index, players.size ); + } +} + +spawn_vo_player( index, num ) +{ + sound = "plr_" + index + "_vox_" + num + "play"; + self playsoundwithnotify( sound, "sound_done" ); + self waittill( "sound_done" ); +} + +precache_shaders() +{ + precacheshader( "hud_chalk_1" ); + precacheshader( "hud_chalk_2" ); + precacheshader( "hud_chalk_3" ); + precacheshader( "hud_chalk_4" ); + precacheshader( "hud_chalk_5" ); + precacheshader( "zom_icon_community_pot" ); + precacheshader( "zom_icon_community_pot_strip" ); + precacheshader( "zom_icon_player_life" ); + precacheshader( "waypoint_revive" ); +} + +precache_models() +{ + precachemodel( "p_zom_win_bars_01_vert04_bend_180" ); + precachemodel( "p_zom_win_bars_01_vert01_bend_180" ); + precachemodel( "p_zom_win_bars_01_vert04_bend" ); + precachemodel( "p_zom_win_bars_01_vert01_bend" ); + precachemodel( "p_zom_win_cell_bars_01_vert04_bent" ); + precachemodel( "p_zom_win_cell_bars_01_vert01_bent" ); + precachemodel( "tag_origin" ); + precachemodel( "zombie_z_money_icon" ); + if ( isDefined( level.precachecustomcharacters ) ) + { + self [[ level.precachecustomcharacters ]](); + } +} + +init_shellshocks() +{ + level.player_killed_shellshock = "zombie_death"; + precacheshellshock( level.player_killed_shellshock ); + precacheshellshock( "pain" ); + precacheshellshock( "explosion" ); +} + +init_strings() +{ + precachestring( &"ZOMBIE_WEAPONCOSTAMMO" ); + precachestring( &"ZOMBIE_ROUND" ); + precachestring( &"SCRIPT_PLUS" ); + precachestring( &"ZOMBIE_GAME_OVER" ); + precachestring( &"ZOMBIE_SURVIVED_ROUND" ); + precachestring( &"ZOMBIE_SURVIVED_ROUNDS" ); + precachestring( &"ZOMBIE_SURVIVED_NOMANS" ); + precachestring( &"ZOMBIE_EXTRA_LIFE" ); + add_zombie_hint( "undefined", &"ZOMBIE_UNDEFINED" ); + add_zombie_hint( "default_treasure_chest", &"ZOMBIE_RANDOM_WEAPON_COST" ); + add_zombie_hint( "default_treasure_chest_950", &"ZOMBIE_RANDOM_WEAPON_950" ); + add_zombie_hint( "powerup_fire_sale_cost", &"ZOMBIE_FIRE_SALE_COST" ); + add_zombie_hint( "default_buy_barrier_piece_10", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_10" ); + add_zombie_hint( "default_buy_barrier_piece_20", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_20" ); + add_zombie_hint( "default_buy_barrier_piece_50", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_50" ); + add_zombie_hint( "default_buy_barrier_piece_100", &"ZOMBIE_BUTTON_BUY_BACK_BARRIER_100" ); + add_zombie_hint( "default_reward_barrier_piece", &"ZOMBIE_BUTTON_REWARD_BARRIER" ); + add_zombie_hint( "default_reward_barrier_piece_10", &"ZOMBIE_BUTTON_REWARD_BARRIER_10" ); + add_zombie_hint( "default_reward_barrier_piece_20", &"ZOMBIE_BUTTON_REWARD_BARRIER_20" ); + add_zombie_hint( "default_reward_barrier_piece_30", &"ZOMBIE_BUTTON_REWARD_BARRIER_30" ); + add_zombie_hint( "default_reward_barrier_piece_40", &"ZOMBIE_BUTTON_REWARD_BARRIER_40" ); + add_zombie_hint( "default_reward_barrier_piece_50", &"ZOMBIE_BUTTON_REWARD_BARRIER_50" ); + add_zombie_hint( "default_buy_debris", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_COST" ); + add_zombie_hint( "default_buy_debris_100", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_100" ); + add_zombie_hint( "default_buy_debris_200", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_200" ); + add_zombie_hint( "default_buy_debris_250", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_250" ); + add_zombie_hint( "default_buy_debris_500", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_500" ); + add_zombie_hint( "default_buy_debris_750", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_750" ); + add_zombie_hint( "default_buy_debris_1000", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_1000" ); + add_zombie_hint( "default_buy_debris_1250", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_1250" ); + add_zombie_hint( "default_buy_debris_1500", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_1500" ); + add_zombie_hint( "default_buy_debris_1750", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_1750" ); + add_zombie_hint( "default_buy_debris_2000", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_2000" ); + add_zombie_hint( "default_buy_debris_3000", &"ZOMBIE_BUTTON_BUY_CLEAR_DEBRIS_3000" ); + add_zombie_hint( "default_buy_door", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_COST" ); + add_zombie_hint( "default_buy_door_close", &"ZOMBIE_BUTTON_BUY_CLOSE_DOOR" ); + add_zombie_hint( "default_buy_door_100", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_100" ); + add_zombie_hint( "default_buy_door_200", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_200" ); + add_zombie_hint( "default_buy_door_250", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_250" ); + add_zombie_hint( "default_buy_door_500", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_500" ); + add_zombie_hint( "default_buy_door_750", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_750" ); + add_zombie_hint( "default_buy_door_1000", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_1000" ); + add_zombie_hint( "default_buy_door_1250", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_1250" ); + add_zombie_hint( "default_buy_door_1500", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_1500" ); + add_zombie_hint( "default_buy_door_1750", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_1750" ); + add_zombie_hint( "default_buy_door_2000", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_2000" ); + add_zombie_hint( "default_buy_door_2500", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_2500" ); + add_zombie_hint( "default_buy_door_3000", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_3000" ); + add_zombie_hint( "default_buy_door_4000", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_4000" ); + add_zombie_hint( "default_buy_door_8000", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_8000" ); + add_zombie_hint( "default_buy_door_16000", &"ZOMBIE_BUTTON_BUY_OPEN_DOOR_16000" ); + add_zombie_hint( "default_buy_area", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_COST" ); + add_zombie_hint( "default_buy_area_100", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_100" ); + add_zombie_hint( "default_buy_area_200", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_200" ); + add_zombie_hint( "default_buy_area_250", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_250" ); + add_zombie_hint( "default_buy_area_500", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_500" ); + add_zombie_hint( "default_buy_area_750", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_750" ); + add_zombie_hint( "default_buy_area_1000", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_1000" ); + add_zombie_hint( "default_buy_area_1250", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_1250" ); + add_zombie_hint( "default_buy_area_1500", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_1500" ); + add_zombie_hint( "default_buy_area_1750", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_1750" ); + add_zombie_hint( "default_buy_area_2000", &"ZOMBIE_BUTTON_BUY_OPEN_AREA_2000" ); +} + +init_sounds() +{ + add_sound( "end_of_round", "mus_zmb_round_over" ); + add_sound( "end_of_game", "mus_zmb_game_over" ); + add_sound( "chalk_one_up", "mus_zmb_chalk" ); + add_sound( "purchase", "zmb_cha_ching" ); + add_sound( "no_purchase", "zmb_no_cha_ching" ); + add_sound( "playerzombie_usebutton_sound", "zmb_zombie_vocals_attack" ); + add_sound( "playerzombie_attackbutton_sound", "zmb_zombie_vocals_attack" ); + add_sound( "playerzombie_adsbutton_sound", "zmb_zombie_vocals_attack" ); + add_sound( "zombie_head_gib", "zmb_zombie_head_gib" ); + add_sound( "rebuild_barrier_piece", "zmb_repair_boards" ); + add_sound( "rebuild_barrier_metal_piece", "zmb_metal_repair" ); + add_sound( "rebuild_barrier_hover", "zmb_boards_float" ); + add_sound( "debris_hover_loop", "zmb_couch_loop" ); + add_sound( "break_barrier_piece", "zmb_break_boards" ); + add_sound( "grab_metal_bar", "zmb_bar_pull" ); + add_sound( "break_metal_bar", "zmb_bar_break" ); + add_sound( "drop_metal_bar", "zmb_bar_drop" ); + add_sound( "blocker_end_move", "zmb_board_slam" ); + add_sound( "barrier_rebuild_slam", "zmb_board_slam" ); + add_sound( "bar_rebuild_slam", "zmb_bar_repair" ); + add_sound( "zmb_rock_fix", "zmb_break_rock_barrier_fix" ); + add_sound( "zmb_vent_fix", "evt_vent_slat_repair" ); + add_sound( "door_slide_open", "zmb_door_slide_open" ); + add_sound( "door_rotate_open", "zmb_door_slide_open" ); + add_sound( "debris_move", "zmb_weap_wall" ); + add_sound( "open_chest", "zmb_lid_open" ); + add_sound( "music_chest", "zmb_music_box" ); + add_sound( "close_chest", "zmb_lid_close" ); + add_sound( "weapon_show", "zmb_weap_wall" ); + add_sound( "break_stone", "break_stone" ); +} + +init_levelvars() +{ + level.is_zombie_level = 1; + level.laststandpistol = "m1911_zm"; + level.default_laststandpistol = "m1911_zm"; + level.default_solo_laststandpistol = "m1911_upgraded_zm"; + level.start_weapon = "m1911_zm"; + level.first_round = 1; + level.start_round = getgametypesetting( "startRound" ); + level.round_number = level.start_round; + level.enable_magic = getgametypesetting( "magic" ); + level.headshots_only = getgametypesetting( "headshotsonly" ); + level.player_starting_points = level.round_number * 500; + level.round_start_time = 0; + level.pro_tips_start_time = 0; + level.intermission = 0; + level.dog_intermission = 0; + level.zombie_total = 0; + level.total_zombies_killed = 0; + level.hudelem_count = 0; + level.zombie_spawn_locations = []; + level.zombie_rise_spawners = []; + level.current_zombie_array = []; + level.current_zombie_count = 0; + level.zombie_total_subtract = 0; + level.destructible_callbacks = []; + level.zombie_vars = []; + _a1039 = level.teams; + _k1039 = getFirstArrayKey( _a1039 ); + while ( isDefined( _k1039 ) ) + { + team = _a1039[ _k1039 ]; + level.zombie_vars[ team ] = []; + _k1039 = getNextArrayKey( _a1039, _k1039 ); + } + difficulty = 1; + column = int( difficulty ) + 1; + set_zombie_var( "zombie_health_increase", 100, 0, column ); + set_zombie_var( "zombie_health_increase_multiplier", 0,1, 1, column ); + set_zombie_var( "zombie_health_start", 150, 0, column ); + set_zombie_var( "zombie_spawn_delay", 2, 1, column ); + set_zombie_var( "zombie_new_runner_interval", 10, 0, column ); + set_zombie_var( "zombie_move_speed_multiplier", 8, 0, column ); + set_zombie_var( "zombie_move_speed_multiplier_easy", 2, 0, column ); + set_zombie_var( "zombie_max_ai", 24, 0, column ); + set_zombie_var( "zombie_ai_per_player", 6, 0, column ); + set_zombie_var( "below_world_check", -1000 ); + set_zombie_var( "spectators_respawn", 1 ); + set_zombie_var( "zombie_use_failsafe", 1 ); + set_zombie_var( "zombie_between_round_time", 10 ); + set_zombie_var( "zombie_intermission_time", 15 ); + set_zombie_var( "game_start_delay", 0, 0, column ); + set_zombie_var( "penalty_no_revive", 0,1, 1, column ); + set_zombie_var( "penalty_died", 0, 1, column ); + set_zombie_var( "penalty_downed", 0,05, 1, column ); + set_zombie_var( "starting_lives", 1, 0, column ); + set_zombie_var( "zombie_score_kill_4player", 50 ); + set_zombie_var( "zombie_score_kill_3player", 50 ); + set_zombie_var( "zombie_score_kill_2player", 50 ); + set_zombie_var( "zombie_score_kill_1player", 50 ); + set_zombie_var( "zombie_score_kill_4p_team", 30 ); + set_zombie_var( "zombie_score_kill_3p_team", 35 ); + set_zombie_var( "zombie_score_kill_2p_team", 45 ); + set_zombie_var( "zombie_score_kill_1p_team", 0 ); + set_zombie_var( "zombie_score_damage_normal", 10 ); + set_zombie_var( "zombie_score_damage_light", 10 ); + set_zombie_var( "zombie_score_bonus_melee", 80 ); + set_zombie_var( "zombie_score_bonus_head", 50 ); + set_zombie_var( "zombie_score_bonus_neck", 20 ); + set_zombie_var( "zombie_score_bonus_torso", 10 ); + set_zombie_var( "zombie_score_bonus_burn", 10 ); + set_zombie_var( "zombie_flame_dmg_point_delay", 500 ); + set_zombie_var( "zombify_player", 0 ); + if ( issplitscreen() ) + { + set_zombie_var( "zombie_timer_offset", 280 ); + } + level thread init_player_levelvars(); + level.gamedifficulty = getgametypesetting( "zmDifficulty" ); + if ( level.gamedifficulty == 0 ) + { + level.zombie_move_speed = level.round_number * level.zombie_vars[ "zombie_move_speed_multiplier_easy" ]; + } + else + { + level.zombie_move_speed = level.round_number * level.zombie_vars[ "zombie_move_speed_multiplier" ]; + } + if ( level.round_number == 1 ) + { + level.zombie_move_speed = 100; + } + else + { + i = 1; + while ( i <= level.round_number ) + { + timer = level.zombie_vars[ "zombie_spawn_delay" ]; + if ( timer > 0.08 ) + { + level.zombie_vars[ "zombie_spawn_delay" ] = timer * 0.95; + i++; + continue; + } + else + { + if ( timer < 0.08 ) + { + level.zombie_vars[ "zombie_spawn_delay" ] = 0.08; + } + } + i++; + } + } + level.speed_change_max = 0; + level.speed_change_num = 0; +} + +init_player_levelvars() +{ + flag_wait( "start_zombie_round_logic" ); + difficulty = 1; + column = int( difficulty ) + 1; + i = 0; + while ( i < 8 ) + { + points = 500; + if ( i > 3 ) + { + points = 3000; + } + points = set_zombie_var( "zombie_score_start_" + ( i + 1 ) + "p", points, 0, column ); + i++; + } +} + +init_dvars() +{ + if ( getDvar( "zombie_debug" ) == "" ) + { + setdvar( "zombie_debug", "0" ); + } + if ( getDvar( "scr_zm_enable_bots" ) == "" ) + { + setdvar( "scr_zm_enable_bots", "0" ); + } + if ( getDvar( "zombie_cheat" ) == "" ) + { + setdvar( "zombie_cheat", "0" ); + } + if ( level.script != "zombie_cod5_prototype" ) + { + setdvar( "magic_chest_movable", "1" ); + } + setdvar( "revive_trigger_radius", "75" ); + setdvar( "player_lastStandBleedoutTime", "45" ); + setdvar( "scr_deleteexplosivesonspawn", "0" ); +} + +init_function_overrides() +{ + level.callbackplayerdamage = ::callback_playerdamage; + level.overrideplayerdamage = ::player_damage_override; + level.callbackplayerkilled = ::player_killed_override; + level.playerlaststand_func = ::player_laststand; + level.callbackplayerlaststand = ::callback_playerlaststand; + level.prevent_player_damage = ::player_prevent_damage; + level.callbackactorkilled = ::actor_killed_override; + level.callbackactordamage = ::actor_damage_override_wrapper; + level.custom_introscreen = ::zombie_intro_screen; + level.custom_intermission = ::player_intermission; + level.global_damage_func = ::zombie_damage; //maps/mp/zombies/_zm_spawner + level.global_damage_func_ads = ::zombie_damage_ads; //maps/mp/zombies/_zm_spawner + level.reset_clientdvars = ::onplayerconnect_clientdvars; + level.zombie_last_stand = ::last_stand_pistol_swap; + level.zombie_last_stand_pistol_memory = ::last_stand_save_pistol_ammo; + level.zombie_last_stand_ammo_return = ::last_stand_restore_pistol_ammo; + level.player_becomes_zombie = ::zombify_player; + level.validate_enemy_path_length = ::default_validate_enemy_path_length; + level.zm_laststand_playerlaststand = ::playerlaststand; //maps/mp/zombies/_zm_laststand +} + +callback_playerlaststand( einflictor, eattacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ + self endon( "disconnect" ); + [[ level.zm_laststand_playerlaststand ]]( einflictor, eattacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ); +} + +codecallback_destructibleevent( event, param1, param2, param3 ) +{ + if ( event == "broken" ) + { + notify_type = param1; + attacker = param2; + weapon = param3; + if ( isDefined( level.destructible_callbacks[ notify_type ] ) ) + { + self thread [[ level.destructible_callbacks[ notify_type ] ]]( notify_type, attacker ); + } + self notify( event ); + } + else + { + if ( event == "breakafter" ) + { + piece = param1; + time = param2; + damage = param3; + self thread breakafter( time, damage, piece ); + } + } +} + +breakafter( time, damage, piece ) +{ + self notify( "breakafter" ); + self endon( "breakafter" ); + wait time; + self dodamage( damage, self.origin, undefined, undefined ); +} + +callback_playerdamage( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ +/* +/# + println( "ZM Callback_PlayerDamage" + idamage + "\n" ); +#/ +*/ + if ( isDefined( eattacker ) && isplayer( eattacker ) && eattacker.sessionteam == self.sessionteam && !eattacker hasperk( "specialty_noname" ) && isDefined( self.is_zombie ) && !self.is_zombie ) + { + self process_friendly_fire_callbacks( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); + if ( self != eattacker ) + { + /* +/# + println( "Exiting - players can't hurt each other." ); +#/ + */ + return; + } + else + { + if ( smeansofdeath != "MOD_GRENADE_SPLASH" && smeansofdeath != "MOD_GRENADE" && smeansofdeath != "MOD_EXPLOSIVE" && smeansofdeath != "MOD_PROJECTILE" && smeansofdeath != "MOD_PROJECTILE_SPLASH" && smeansofdeath != "MOD_BURNED" && smeansofdeath != "MOD_SUICIDE" ) + { + /* +/# + println( "Exiting - damage type verbotten." ); +#/ + */ + return; + } + } + } + if ( isDefined( level.pers_upgrade_insta_kill ) && level.pers_upgrade_insta_kill ) + { + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_insta_kill_melee_swipe( smeansofdeath, eattacker ); + } + if ( isDefined( self.overrideplayerdamage ) ) + { + idamage = self [[ self.overrideplayerdamage ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + } + else + { + if ( isDefined( level.overrideplayerdamage ) ) + { + idamage = self [[ level.overrideplayerdamage ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + } + } + /* +/# + assert( isDefined( idamage ), "You must return a value from a damage override function." ); +#/ + */ + if ( isDefined( self.magic_bullet_shield ) && self.magic_bullet_shield ) + { + maxhealth = self.maxhealth; + self.health += idamage; + self.maxhealth = maxhealth; + } + if ( isDefined( self.divetoprone ) && self.divetoprone == 1 ) + { + if ( smeansofdeath == "MOD_GRENADE_SPLASH" ) + { + dist = distance2d( vpoint, self.origin ); + if ( dist > 32 ) + { + dot_product = vectordot( anglesToForward( self.angles ), vdir ); + if ( dot_product > 0 ) + { + idamage = int( idamage * 0.5 ); + } + } + } + } + /* +/# + println( "CB PD" ); +#/ + */ + if ( isDefined( level.prevent_player_damage ) ) + { + if ( self [[ level.prevent_player_damage ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) ) + { + return; + } + } + idflags |= level.idflags_no_knockback; + if ( idamage > 0 && shitloc == "riotshield" ) + { + shitloc = "torso_upper"; + } + /* +/# + println( "Finishplayerdamage wrapper." ); +#/ + */ + self finishplayerdamagewrapper( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); +} + +finishplayerdamagewrapper( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + self finishplayerdamage( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); +} + +register_player_friendly_fire_callback( callback ) +{ + if ( !isDefined( level.player_friendly_fire_callbacks ) ) + { + level.player_friendly_fire_callbacks = []; + } + level.player_friendly_fire_callbacks[ level.player_friendly_fire_callbacks.size ] = callback; +} + +process_friendly_fire_callbacks( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + while ( isDefined( level.player_friendly_fire_callbacks ) ) + { + _a1421 = level.player_friendly_fire_callbacks; + _k1421 = getFirstArrayKey( _a1421 ); + while ( isDefined( _k1421 ) ) + { + callback = _a1421[ _k1421 ]; + self [[ callback ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); + _k1421 = getNextArrayKey( _a1421, _k1421 ); + } + } +} + +init_flags() +{ + flag_init( "solo_game" ); + flag_init( "start_zombie_round_logic" ); + flag_init( "start_encounters_match_logic" ); + flag_init( "spawn_point_override" ); + flag_init( "power_on" ); + flag_init( "crawler_round" ); + flag_init( "spawn_zombies", 1 ); + flag_init( "dog_round" ); + flag_init( "begin_spawning" ); + flag_init( "end_round_wait" ); + flag_init( "wait_and_revive" ); + flag_init( "instant_revive" ); + flag_init( "initial_blackscreen_passed" ); + flag_init( "initial_players_connected" ); +} + +init_client_flags() +{ + if ( isDefined( level.use_clientside_board_fx ) && level.use_clientside_board_fx ) + { + level._zombie_scriptmover_flag_board_horizontal_fx = 14; + level._zombie_scriptmover_flag_board_vertical_fx = 13; + } + if ( isDefined( level.use_clientside_rock_tearin_fx ) && level.use_clientside_rock_tearin_fx ) + { + level._zombie_scriptmover_flag_rock_fx = 12; + } + level._zombie_player_flag_cloak_weapon = 14; + if ( isDefined( level.disable_deadshot_clientfield ) && !level.disable_deadshot_clientfield ) + { + registerclientfield( "toplayer", "deadshot_perk", 1, 1, "int" ); + } + registerclientfield( "actor", "zombie_riser_fx", 1, 1, "int" ); + if ( isDefined( level._no_water_risers ) && !level._no_water_risers ) + { + registerclientfield( "actor", "zombie_riser_fx_water", 1, 1, "int" ); + } + if ( isDefined( level._foliage_risers ) && level._foliage_risers ) + { + registerclientfield( "actor", "zombie_riser_fx_foliage", 12000, 1, "int" ); + } + if ( isDefined( level.risers_use_low_gravity_fx ) && level.risers_use_low_gravity_fx ) + { + registerclientfield( "actor", "zombie_riser_fx_lowg", 1, 1, "int" ); + } +} + +init_fx() +{ + level.createfx_callback_thread = ::delete_in_createfx; + level._effect[ "wood_chunk_destory" ] = loadfx( "impacts/fx_large_woodhit" ); + level._effect[ "fx_zombie_bar_break" ] = loadfx( "maps/zombie/fx_zombie_bar_break" ); + level._effect[ "fx_zombie_bar_break_lite" ] = loadfx( "maps/zombie/fx_zombie_bar_break_lite" ); + if ( isDefined( level.fx_exclude_edge_fog ) && !level.fx_exclude_edge_fog ) + { + level._effect[ "edge_fog" ] = loadfx( "maps/zombie/fx_fog_zombie_amb" ); + } + level._effect[ "chest_light" ] = loadfx( "maps/zombie/fx_zmb_tranzit_marker_glow" ); + if ( isDefined( level.fx_exclude_default_eye_glow ) && !level.fx_exclude_default_eye_glow ) + { + level._effect[ "eye_glow" ] = loadfx( "misc/fx_zombie_eye_single" ); + } + level._effect[ "headshot" ] = loadfx( "impacts/fx_flesh_hit" ); + level._effect[ "headshot_nochunks" ] = loadfx( "misc/fx_zombie_bloodsplat" ); + level._effect[ "bloodspurt" ] = loadfx( "misc/fx_zombie_bloodspurt" ); + if ( isDefined( level.fx_exclude_tesla_head_light ) && !level.fx_exclude_tesla_head_light ) + { + level._effect[ "tesla_head_light" ] = loadfx( "maps/zombie/fx_zombie_tesla_neck_spurt" ); + } + level._effect[ "zombie_guts_explosion" ] = loadfx( "maps/zombie/fx_zmb_tranzit_torso_explo" ); + level._effect[ "rise_burst_water" ] = loadfx( "maps/zombie/fx_mp_zombie_hand_dirt_burst" ); + level._effect[ "rise_billow_water" ] = loadfx( "maps/zombie/fx_mp_zombie_body_dirt_billowing" ); + level._effect[ "rise_dust_water" ] = loadfx( "maps/zombie/fx_mp_zombie_body_dust_falling" ); + level._effect[ "rise_burst" ] = loadfx( "maps/zombie/fx_mp_zombie_hand_dirt_burst" ); + level._effect[ "rise_billow" ] = loadfx( "maps/zombie/fx_mp_zombie_body_dirt_billowing" ); + level._effect[ "rise_dust" ] = loadfx( "maps/zombie/fx_mp_zombie_body_dust_falling" ); + level._effect[ "fall_burst" ] = loadfx( "maps/zombie/fx_mp_zombie_hand_dirt_burst" ); + level._effect[ "fall_billow" ] = loadfx( "maps/zombie/fx_mp_zombie_body_dirt_billowing" ); + level._effect[ "fall_dust" ] = loadfx( "maps/zombie/fx_mp_zombie_body_dust_falling" ); + level._effect[ "character_fire_death_sm" ] = loadfx( "env/fire/fx_fire_zombie_md" ); + level._effect[ "character_fire_death_torso" ] = loadfx( "env/fire/fx_fire_zombie_torso" ); + if ( isDefined( level.fx_exclude_default_explosion ) && !level.fx_exclude_default_explosion ) + { + level._effect[ "def_explosion" ] = loadfx( "explosions/fx_default_explosion" ); + } + if ( isDefined( level._uses_default_wallbuy_fx ) && level._uses_default_wallbuy_fx ) + { + level._effect[ "870mcs_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_870mcs" ); + level._effect[ "ak74u_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_ak74u" ); + level._effect[ "beretta93r_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_berreta93r" ); + level._effect[ "bowie_knife_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_bowie" ); + level._effect[ "claymore_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_claymore" ); + level._effect[ "m14_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_m14" ); + level._effect[ "m16_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_m16" ); + level._effect[ "mp5k_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_mp5k" ); + level._effect[ "rottweil72_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_olympia" ); + } + if ( isDefined( level._uses_sticky_grenades ) && level._uses_sticky_grenades ) + { + if ( isDefined( level.disable_fx_zmb_wall_buy_semtex ) && !level.disable_fx_zmb_wall_buy_semtex ) + { + level._effect[ "sticky_grenade_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_semtex" ); + } + } + if ( isDefined( level._uses_taser_knuckles ) && level._uses_taser_knuckles ) + { + level._effect[ "tazer_knuckles_zm_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_taseknuck" ); + } + if ( isDefined( level.buildable_wallbuy_weapons ) ) + { + level._effect[ "dynamic_wallbuy_fx" ] = loadfx( "maps/zombie/fx_zmb_wall_buy_question" ); + } + if ( isDefined( level.disable_fx_upgrade_aquired ) && !level.disable_fx_upgrade_aquired ) + { + level._effect[ "upgrade_aquired" ] = loadfx( "maps/zombie/fx_zmb_tanzit_upgrade" ); + } +} + +zombie_intro_screen( string1, string2, string3, string4, string5 ) +{ + flag_wait( "start_zombie_round_logic" ); +} + +players_playing() +{ + players = get_players(); + level.players_playing = players.size; + wait 20; + players = get_players(); + level.players_playing = players.size; +} + +onplayerconnect_clientdvars() +{ + self setclientcompass( 0 ); + self setclientthirdperson( 0 ); + self resetfov(); + self setclientthirdpersonangle( 0 ); + self setclientammocounterhide( 1 ); + self setclientminiscoreboardhide( 1 ); + self setclienthudhardcore( 0 ); + self setclientplayerpushamount( 1 ); + self setdepthoffield( 0, 0, 512, 4000, 4, 0 ); + self setclientaimlockonpitchstrength( 0 ); + self maps/mp/zombies/_zm_laststand::player_getup_setup(); +} + +checkforalldead( excluded_player ) +{ + players = get_players(); + count = 0; + i = 0; + while ( i < players.size ) + { + if ( isDefined( excluded_player ) && excluded_player == players[ i ] ) + { + i++; + continue; + } + else + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) + { + count++; + } + } + i++; + } + if ( count == 0 && isDefined( level.no_end_game_check ) && !level.no_end_game_check ) + { + level notify( "end_game" ); + } +} + +onplayerspawned() +{ + self endon( "disconnect" ); + self notify( "stop_onPlayerSpawned" ); + self endon( "stop_onPlayerSpawned" ); + for ( ;; ) + { + self waittill( "spawned_player" ); + if ( isDefined( level.host_ended_game ) && !level.host_ended_game ) + { + self freezecontrols( 0 ); + /* +/# + println( " Unfreeze controls 7" ); +#/ + */ + } + self.hits = 0; + self init_player_offhand_weapons(); + lethal_grenade = self get_player_lethal_grenade(); + if ( !self hasweapon( lethal_grenade ) ) + { + self giveweapon( lethal_grenade ); + self setweaponammoclip( lethal_grenade, 0 ); + } + self recordplayerrevivezombies( self ); + /* +/# + if ( getDvarInt( "zombie_cheat" ) >= 1 && getDvarInt( "zombie_cheat" ) <= 3 ) + { + self enableinvulnerability(); + + } +#/ + */ + self setactionslot( 3, "altMode" ); + self playerknockback( 0 ); + self setclientthirdperson( 0 ); + self resetfov(); + self setclientthirdpersonangle( 0 ); + self setdepthoffield( 0, 0, 512, 4000, 4, 0 ); + self cameraactivate( 0 ); + self.num_perks = 0; + self.on_lander_last_stand = undefined; + self setblur( 0, 0.1 ); + self.zmbdialogqueue = []; + self.zmbdialogactive = 0; + self.zmbdialoggroups = []; + self.zmbdialoggroup = ""; + + if ( isDefined( level.player_out_of_playable_area_monitor ) && level.player_out_of_playable_area_monitor ) + { + self thread player_out_of_playable_area_monitor(); + } + if ( isDefined( level.player_too_many_weapons_monitor ) && level.player_too_many_weapons_monitor ) + { + self thread [[ level.player_too_many_weapons_monitor_func ]](); + } + if ( isDefined( level.player_too_many_players_check ) && level.player_too_many_players_check ) + { + level thread [[ level.player_too_many_players_check_func ]](); + } + self.disabled_perks = []; + if ( isDefined( self.player_initialized ) ) + { + if ( self.player_initialized == 0 ) + { + self.player_initialized = 1; + self giveweapon( self get_player_lethal_grenade() ); + self setweaponammoclip( self get_player_lethal_grenade(), 0 ); + self setclientammocounterhide( 0 ); + self setclientminiscoreboardhide( 0 ); + self.is_drinking = 0; + self thread player_zombie_breadcrumb(); + self thread player_monitor_travel_dist(); + self thread player_monitor_time_played(); + if ( isDefined( level.custom_player_track_ammo_count ) ) + { + self thread [[ level.custom_player_track_ammo_count ]](); + } + else + { + self thread player_track_ammo_count(); + } + self thread shock_onpain(); + self thread player_grenade_watcher(); + self maps/mp/zombies/_zm_laststand::revive_hud_create(); + if ( isDefined( level.zm_gamemodule_spawn_func ) ) + { + self thread [[ level.zm_gamemodule_spawn_func ]](); + } + self thread player_spawn_protection(); + if ( !isDefined( self.lives ) ) + { + self.lives = 0; + } + } + } + } +} + +player_spawn_protection() +{ + self endon( "disconnect" ); + x = 0; + while ( x < 60 ) + { + self.ignoreme = 1; + x++; + wait 0.05; + } + self.ignoreme = 0; +} + +spawn_life_brush( origin, radius, height ) +{ + life_brush = spawn( "trigger_radius", origin, 0, radius, height ); + life_brush.script_noteworthy = "life_brush"; + return life_brush; +} + +in_life_brush() +{ + life_brushes = getentarray( "life_brush", "script_noteworthy" ); + if ( !isDefined( life_brushes ) ) + { + return 0; + } + i = 0; + while ( i < life_brushes.size ) + { + if ( self istouching( life_brushes[ i ] ) ) + { + return 1; + } + i++; + } + return 0; +} + +spawn_kill_brush( origin, radius, height ) +{ + kill_brush = spawn( "trigger_radius", origin, 0, radius, height ); + kill_brush.script_noteworthy = "kill_brush"; + return kill_brush; +} + +in_kill_brush() +{ + kill_brushes = getentarray( "kill_brush", "script_noteworthy" ); + if ( !isDefined( kill_brushes ) ) + { + return 0; + } + i = 0; + while ( i < kill_brushes.size ) + { + if ( self istouching( kill_brushes[ i ] ) ) + { + return 1; + } + i++; + } + return 0; +} + +in_enabled_playable_area() +{ + playable_area = getentarray( "player_volume", "script_noteworthy" ); + if ( !isDefined( playable_area ) ) + { + return 0; + } + i = 0; + while ( i < playable_area.size ) + { + if ( maps/mp/zombies/_zm_zonemgr::zone_is_enabled( playable_area[ i ].targetname ) && self istouching( playable_area[ i ] ) ) + { + return 1; + } + i++; + } + return 0; +} + +get_player_out_of_playable_area_monitor_wait_time() +{ + +/# + if ( isDefined( level.check_kill_thread_every_frame ) && level.check_kill_thread_every_frame ) + { + return 0.05; +#/ + } + + return 3; +} + +player_out_of_playable_area_monitor() +{ + self notify( "stop_player_out_of_playable_area_monitor" ); + self endon( "stop_player_out_of_playable_area_monitor" ); + self endon( "disconnect" ); + level endon( "end_game" ); + while ( !isDefined( self.characterindex ) ) + { + wait 0.05; + } + wait ( 0.15 * self.characterindex ); + while ( 1 ) + { + while ( self.sessionstate == "spectator" ) + { + wait get_player_out_of_playable_area_monitor_wait_time(); + } + while ( is_true( level.hostmigration_occured ) ) + { + wait get_player_out_of_playable_area_monitor_wait_time(); + } + if ( !self in_life_brush() || self in_kill_brush() && !self in_enabled_playable_area() ) + { + if ( !isDefined( level.player_out_of_playable_area_monitor_callback ) || self [[ level.player_out_of_playable_area_monitor_callback ]]() ) + { + /* +/# + while ( isDefined( level.kill_thread_test_mode ) && level.kill_thread_test_mode ) + { + iprintlnbold( "out of playable" ); + wait get_player_out_of_playable_area_monitor_wait_time(); + } + while ( !self isinmovemode( "ufo", "noclip" ) && isDefined( level.disable_kill_thread ) || level.disable_kill_thread && getDvarInt( "zombie_cheat" ) > 0 ) + { + wait get_player_out_of_playable_area_monitor_wait_time(); +#/ + } + */ + self maps/mp/zombies/_zm_stats::increment_map_cheat_stat( "cheat_out_of_playable" ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_out_of_playable", 0 ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + self playlocalsound( level.zmb_laugh_alias ); + wait 0.5; + if ( get_players().size == 1 && flag( "solo_game" ) && isDefined( self.waiting_to_revive ) && self.waiting_to_revive ) + { + level notify( "end_game" ); + break; + } + else + { + self disableinvulnerability(); + self.lives = 0; + self dodamage( self.health + 1000, self.origin ); + self.bleedout_time = 0; + } + } + } + wait get_player_out_of_playable_area_monitor_wait_time(); + } +} + +get_player_too_many_weapons_monitor_wait_time() +{ + return 3; +} + +player_too_many_weapons_monitor_takeaway_simultaneous( primary_weapons_to_take ) +{ + self endon( "player_too_many_weapons_monitor_takeaway_sequence_done" ); + self waittill_any( "player_downed", "replace_weapon_powerup" ); + i = 0; + while ( i < primary_weapons_to_take.size ) + { + self takeweapon( primary_weapons_to_take[ i ] ); + i++; + } + self maps/mp/zombies/_zm_score::minus_to_player_score( self.score ); + self give_start_weapon( 0 ); + if ( !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + self decrement_is_drinking(); + } + else + { + if ( flag( "solo_game" ) ) + { + self.score_lost_when_downed = 0; + } + } + self notify( "player_too_many_weapons_monitor_takeaway_sequence_done" ); +} + +player_too_many_weapons_monitor_takeaway_sequence( primary_weapons_to_take ) +{ + self thread player_too_many_weapons_monitor_takeaway_simultaneous( primary_weapons_to_take ); + self endon( "player_downed" ); + self endon( "replace_weapon_powerup" ); + self increment_is_drinking(); + score_decrement = round_up_to_ten( int( self.score / ( primary_weapons_to_take.size + 1 ) ) ); + i = 0; + while ( i < primary_weapons_to_take.size ) + { + self playlocalsound( level.zmb_laugh_alias ); + self switchtoweapon( primary_weapons_to_take[ i ] ); + self maps/mp/zombies/_zm_score::minus_to_player_score( score_decrement ); + wait 3; + self takeweapon( primary_weapons_to_take[ i ] ); + i++; + } + self playlocalsound( level.zmb_laugh_alias ); + self maps/mp/zombies/_zm_score::minus_to_player_score( self.score ); + wait 1; + self give_start_weapon( 1 ); + self decrement_is_drinking(); + self notify( "player_too_many_weapons_monitor_takeaway_sequence_done" ); +} + +player_too_many_weapons_monitor() +{ + self notify( "stop_player_too_many_weapons_monitor" ); + self endon( "stop_player_too_many_weapons_monitor" ); + self endon( "disconnect" ); + level endon( "end_game" ); + scalar = self.characterindex; + if ( !isDefined( scalar ) ) + { + scalar = self getentitynumber(); + } + wait ( 0.15 * scalar ); + while ( 1 ) + { + while ( !self has_powerup_weapon() || self maps/mp/zombies/_zm_laststand::player_is_in_laststand() && self.sessionstate == "spectator" ) + { + wait get_player_too_many_weapons_monitor_wait_time(); + } + /* +/# + while ( getDvarInt( "zombie_cheat" ) > 0 ) + { + wait get_player_too_many_weapons_monitor_wait_time(); +#/ + } + */ + weapon_limit = get_player_weapon_limit( self ); + primaryweapons = self getweaponslistprimaries(); + if ( primaryweapons.size > weapon_limit ) + { + self maps/mp/zombies/_zm_weapons::take_fallback_weapon(); + primaryweapons = self getweaponslistprimaries(); + } + primary_weapons_to_take = []; + i = 0; + while ( i < primaryweapons.size ) + { + if ( maps/mp/zombies/_zm_weapons::is_weapon_included( primaryweapons[ i ] ) || maps/mp/zombies/_zm_weapons::is_weapon_upgraded( primaryweapons[ i ] ) ) + { + primary_weapons_to_take[ primary_weapons_to_take.size ] = primaryweapons[ i ]; + } + i++; + } + if ( primary_weapons_to_take.size > weapon_limit ) + { + if ( !isDefined( level.player_too_many_weapons_monitor_callback ) || self [[ level.player_too_many_weapons_monitor_callback ]]( primary_weapons_to_take ) ) + { + self maps/mp/zombies/_zm_stats::increment_map_cheat_stat( "cheat_too_many_weapons" ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_too_many_weapons", 0 ); + self maps/mp/zombies/_zm_stats::increment_client_stat( "cheat_total", 0 ); + self thread player_too_many_weapons_monitor_takeaway_sequence( primary_weapons_to_take ); + self waittill( "player_too_many_weapons_monitor_takeaway_sequence_done" ); + } + } + wait get_player_too_many_weapons_monitor_wait_time(); + } +} + +player_monitor_travel_dist() +{ + self endon( "disconnect" ); + self notify( "stop_player_monitor_travel_dist" ); + self endon( "stop_player_monitor_travel_dist" ); + prevpos = self.origin; + while ( 1 ) + { + wait 0.1; + self.pers[ "distance_traveled" ] += distance( self.origin, prevpos ); + prevpos = self.origin; + } +} + +player_monitor_time_played() +{ + self endon( "disconnect" ); + self notify( "stop_player_monitor_time_played" ); + self endon( "stop_player_monitor_time_played" ); + flag_wait( "start_zombie_round_logic" ); + for ( ;; ) + { + wait 1; + maps/mp/zombies/_zm_stats::increment_client_stat( "time_played_total" ); + } +} + +reset_rampage_bookmark_kill_times() +{ + if ( !isDefined( self.rampage_bookmark_kill_times ) ) + { + self.rampage_bookmark_kill_times = []; + self.ignore_rampage_kill_times = 0; + } + i = 0; + while ( i < level.rampage_bookmark_kill_times_count ) + { + self.rampage_bookmark_kill_times[ i ] = 0; + i++; + } +} + +add_rampage_bookmark_kill_time() +{ + now = getTime(); + if ( now <= self.ignore_rampage_kill_times ) + { + return; + } + oldest_index = 0; + oldest_time = now + 1; + i = 0; + while ( i < level.rampage_bookmark_kill_times_count ) + { + if ( !self.rampage_bookmark_kill_times[ i ] ) + { + oldest_index = i; + break; + } + else if ( oldest_time > self.rampage_bookmark_kill_times[ i ] ) + { + oldest_index = i; + oldest_time = self.rampage_bookmark_kill_times[ i ]; + } + i++; + } + self.rampage_bookmark_kill_times[ oldest_index ] = now; +} + +watch_rampage_bookmark() +{ + while ( 1 ) + { + wait 0.05; + waittillframeend; + now = getTime(); + oldest_allowed = now - level.rampage_bookmark_kill_times_msec; + players = get_players(); + player_index = 0; + while ( player_index < players.size ) + { + player = players[ player_index ]; + + + if ( isDefined( player.pers[ "isBot" ] ) && player.pers[ "isBot" ] ) + { + /* + player_index++; + continue; + */ + } + + else + { + time_index = 0; + while ( time_index < level.rampage_bookmark_kill_times_count ) + { + if ( !player.rampage_bookmark_kill_times[ time_index ] ) + { + break; + } + else if ( oldest_allowed > player.rampage_bookmark_kill_times[ time_index ] ) + { + player.rampage_bookmark_kill_times[ time_index ] = 0; + break; + } + else + { + time_index++; + } + } + if ( time_index >= level.rampage_bookmark_kill_times_count ) + { + maps/mp/_demo::bookmark( "zm_player_rampage", getTime(), player ); + player reset_rampage_bookmark_kill_times(); + player.ignore_rampage_kill_times = now + level.rampage_bookmark_kill_times_delay; + } + } + player_index++; + } + } +} + +player_grenade_multiattack_bookmark_watcher( grenade ) +{ + self endon( "disconnect" ); + waittillframeend; + if ( !isDefined( grenade ) ) + { + return; + } + inflictorentnum = grenade getentitynumber(); + inflictorenttype = grenade getentitytype(); + inflictorbirthtime = 0; + if ( isDefined( grenade.birthtime ) ) + { + inflictorbirthtime = grenade.birthtime; + } + ret_val = grenade waittill_any_timeout( 15, "explode" ); + if ( !isDefined( self ) || isDefined( ret_val ) && ret_val == "timeout" ) + { + return; + } + self.grenade_multiattack_count = 0; + self.grenade_multiattack_ent = undefined; + waittillframeend; + if ( !isDefined( self ) ) + { + return; + } + count = level.grenade_multiattack_bookmark_count; + if ( isDefined( grenade.grenade_multiattack_bookmark_count ) && grenade.grenade_multiattack_bookmark_count ) + { + count = grenade.grenade_multiattack_bookmark_count; + } + bookmark_string = "zm_player_grenade_multiattack"; + if ( isDefined( grenade.use_grenade_special_long_bookmark ) && grenade.use_grenade_special_long_bookmark ) + { + bookmark_string = "zm_player_grenade_special_long"; + } + else + { + if ( isDefined( grenade.use_grenade_special_bookmark ) && grenade.use_grenade_special_bookmark ) + { + bookmark_string = "zm_player_grenade_special"; + } + } + if ( count <= self.grenade_multiattack_count && isDefined( self.grenade_multiattack_ent ) ) + { + adddemobookmark( level.bookmark[ bookmark_string ], getTime(), self getentitynumber(), 255, 0, inflictorentnum, inflictorenttype, inflictorbirthtime, 0, self.grenade_multiattack_ent getentitynumber() ); + } + self.grenade_multiattack_count = 0; +} + +player_grenade_watcher() +{ + self endon( "disconnect" ); + self notify( "stop_player_grenade_watcher" ); + self endon( "stop_player_grenade_watcher" ); + self.grenade_multiattack_count = 0; + while ( 1 ) + { + self waittill( "grenade_fire", grenade, weapname ); + if ( isDefined( grenade ) && isalive( grenade ) ) + { + grenade.team = self.team; + } + self thread player_grenade_multiattack_bookmark_watcher( grenade ); + if ( isDefined( level.grenade_watcher ) ) + { + self [[ level.grenade_watcher ]]( grenade, weapname ); + } + } +} + +player_prevent_damage( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + if ( !isDefined( einflictor ) || !isDefined( eattacker ) ) + { + return 0; + } + if ( einflictor == self || eattacker == self ) + { + return 0; + } + if ( isDefined( einflictor ) && isDefined( einflictor.team ) ) + { + if ( isDefined( einflictor.damage_own_team ) && !einflictor.damage_own_team ) + { + if ( einflictor.team == self.team ) + { + return 1; + } + } + } + return 0; +} + +player_revive_monitor() +{ + self endon( "disconnect" ); + self notify( "stop_player_revive_monitor" ); + self endon( "stop_player_revive_monitor" ); + while ( 1 ) + { + self waittill( "player_revived", reviver ); + self playsoundtoplayer( "zmb_character_revived", self ); + if ( isDefined( level.isresetting_grief ) && level.isresetting_grief ) + { + continue; + } + bbprint( "zombie_playerdeaths", "round %d playername %s deathtype %s x %f y %f z %f", level.round_number, self.name, "revived", self.origin ); + if ( isDefined( reviver ) ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "revive_up" ); + points = self.score_lost_when_downed; + /* +/# + println( "ZM >> LAST STAND - points = " + points ); +#/ + */ + reviver maps/mp/zombies/_zm_score::player_add_points( "reviver", points ); + self.score_lost_when_downed = 0; + } + } +} + +laststand_giveback_player_perks() +{ + while ( isDefined( self.laststand_perks ) ) + { + lost_perk_index = int( -1 ); + if ( self.laststand_perks.size > 1 ) + { + lost_perk_index = randomint( self.laststand_perks.size - 1 ); + } + i = 0; + while ( i < self.laststand_perks.size ) + { + if ( self hasperk( self.laststand_perks[ i ] ) ) + { + i++; + continue; + } + else if ( i == lost_perk_index ) + { + i++; + continue; + } + else + { + maps/mp/zombies/_zm_perks::give_perk( self.laststand_perks[ i ] ); + } + i++; + } + } +} + +remote_revive_watch() +{ + self endon( "death" ); + self endon( "player_revived" ); + keep_checking = 1; + while ( keep_checking ) + { + self waittill( "remote_revive", reviver ); + if ( reviver.team == self.team ) + { + keep_checking = 0; + } + } + self maps/mp/zombies/_zm_laststand::remote_revive( reviver ); +} + +remove_deadshot_bottle() +{ + wait 0.05; + if ( isDefined( self.lastactiveweapon ) && self.lastactiveweapon == "zombie_perk_bottle_deadshot" ) + { + self.lastactiveweapon = "none"; + } +} + +take_additionalprimaryweapon() +{ + weapon_to_take = undefined; + if ( isDefined( self._retain_perks ) || self._retain_perks && isDefined( self._retain_perks_array ) && isDefined( self._retain_perks_array[ "specialty_additionalprimaryweapon" ] ) && self._retain_perks_array[ "specialty_additionalprimaryweapon" ] ) + { + return weapon_to_take; + } + primary_weapons_that_can_be_taken = []; + primaryweapons = self getweaponslistprimaries(); + i = 0; + while ( i < primaryweapons.size ) + { + if ( maps/mp/zombies/_zm_weapons::is_weapon_included( primaryweapons[ i ] ) || maps/mp/zombies/_zm_weapons::is_weapon_upgraded( primaryweapons[ i ] ) ) + { + primary_weapons_that_can_be_taken[ primary_weapons_that_can_be_taken.size ] = primaryweapons[ i ]; + } + i++; + } + pwtcbt = primary_weapons_that_can_be_taken.size; + while ( pwtcbt >= 3 ) + { + weapon_to_take = primary_weapons_that_can_be_taken[ pwtcbt - 1 ]; + pwtcbt--; + + if ( weapon_to_take == self getcurrentweapon() ) + { + self switchtoweapon( primary_weapons_that_can_be_taken[ 0 ] ); + } + self takeweapon( weapon_to_take ); + } + return weapon_to_take; +} + +player_laststand( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ +/* +/# + println( "ZM >> LAST STAND - player_laststand called" ); +#/ +*/ + b_alt_visionset = 0; + self allowjump( 0 ); + currweapon = self getcurrentweapon(); + statweapon = currweapon; + if ( is_alt_weapon( statweapon ) ) + { + statweapon = weaponaltweaponname( statweapon ); + } + self addweaponstat( statweapon, "deathsDuringUse", 1 ); + if ( isDefined( self.hasperkspecialtytombstone ) && self.hasperkspecialtytombstone ) + { + self.laststand_perks = maps/mp/zombies/_zm_tombstone::tombstone_save_perks( self ); + } + if ( isDefined( self.pers_upgrades_awarded[ "perk_lose" ] ) && self.pers_upgrades_awarded[ "perk_lose" ] ) + { + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_perk_lose_save(); + } + players = get_players(); + if ( players.size == 1 && flag( "solo_game" ) ) + { + if ( self.lives > 0 && self hasperk( "specialty_quickrevive" ) ) + { + self thread wait_and_revive(); + } + } + if ( self hasperk( "specialty_additionalprimaryweapon" ) ) + { + self.weapon_taken_by_losing_specialty_additionalprimaryweapon = take_additionalprimaryweapon(); + } + if ( isDefined( self.hasperkspecialtytombstone ) && self.hasperkspecialtytombstone ) + { + self [[ level.tombstone_laststand_func ]](); + self thread [[ level.tombstone_spawn_func ]](); + self.hasperkspecialtytombstone = undefined; + self notify( "specialty_scavenger_stop" ); + } + self clear_is_drinking(); + self thread remove_deadshot_bottle(); + self thread remote_revive_watch(); + self maps/mp/zombies/_zm_score::player_downed_penalty(); + self disableoffhandweapons(); + self thread last_stand_grenade_save_and_return(); + if ( smeansofdeath != "MOD_SUICIDE" && smeansofdeath != "MOD_FALLING" ) + { + if ( isDefined( self.intermission ) && !self.intermission ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "revive_down" ); + } + else + { + if ( isDefined( level.custom_player_death_vo_func ) && !( self [[ level.custom_player_death_vo_func ]]() ) ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "exert_death" ); + } + } + } + bbprint( "zombie_playerdeaths", "round %d playername %s deathtype %s x %f y %f z %f", level.round_number, self.name, "downed", self.origin ); + if ( isDefined( level._zombie_minigun_powerup_last_stand_func ) ) + { + self thread [[ level._zombie_minigun_powerup_last_stand_func ]](); + } + if ( isDefined( level._zombie_tesla_powerup_last_stand_func ) ) + { + self thread [[ level._zombie_tesla_powerup_last_stand_func ]](); + } + if ( self hasperk( "specialty_grenadepulldeath" ) ) + { + b_alt_visionset = 1; + if ( isDefined( level.custom_laststand_func ) ) + { + self thread [[ level.custom_laststand_func ]](); + } + } + if ( isDefined( self.intermission ) && self.intermission ) + { + bbprint( "zombie_playerdeaths", "round %d playername %s deathtype %s x %f y %f z %f", level.round_number, self.name, "died", self.origin ); + wait 0.5; + self stopsounds(); + level waittill( "forever" ); + } + if ( !b_alt_visionset ) + { + visionsetlaststand( "zombie_last_stand", 1 ); + } +} + +failsafe_revive_give_back_weapons( excluded_player ) +{ + i = 0; + while ( i < 10 ) + { + wait 0.05; + players = get_players(); + _a2621 = players; + _k2621 = getFirstArrayKey( _a2621 ); + while ( isDefined( _k2621 ) ) + { + player = _a2621[ _k2621 ]; + if ( excluded_player != player || !isDefined( player.reviveprogressbar ) && player maps/mp/zombies/_zm_laststand::is_reviving_any() ) + { + } + else + { + /* +/# + iprintlnbold( "FAILSAFE CLEANING UP REVIVE HUD AND GUN" ); +#/ + */ + player maps/mp/zombies/_zm_laststand::revive_give_back_weapons( "none" ); + if ( isDefined( player.reviveprogressbar ) ) + { + player.reviveprogressbar maps/mp/gametypes_zm/_hud_util::destroyelem(); + } + if ( isDefined( player.revivetexthud ) ) + { + player.revivetexthud destroy(); + } + } + _k2621 = getNextArrayKey( _a2621, _k2621 ); + } + i++; + } +} + +spawnspectator() +{ + self endon( "disconnect" ); + self endon( "spawned_spectator" ); + self notify( "spawned" ); + self notify( "end_respawn" ); + if ( level.intermission ) + { + return; + } + if ( isDefined( level.no_spectator ) && level.no_spectator ) + { + wait 3; + exitlevel(); + } + self.is_zombie = 1; + level thread failsafe_revive_give_back_weapons( self ); + self notify( "zombified" ); + if ( isDefined( self.revivetrigger ) ) + { + self.revivetrigger delete(); + self.revivetrigger = undefined; + } + self.zombification_time = getTime(); + resettimeout(); + self stopshellshock(); + self stoprumble( "damage_heavy" ); + self.sessionstate = "spectator"; + self.spectatorclient = -1; + self.maxhealth = self.health; + self.shellshocked = 0; + self.inwater = 0; + self.friendlydamage = undefined; + self.hasspawned = 1; + self.spawntime = getTime(); + self.afk = 0; + /* +/# + println( "*************************Zombie Spectator***" ); +#/ + */ + self detachall(); + if ( isDefined( level.custom_spectate_permissions ) ) + { + self [[ level.custom_spectate_permissions ]](); + } + else + { + self setspectatepermissions( 1 ); + } + self thread spectator_thread(); + self spawn( self.origin, self.angles ); + self notify( "spawned_spectator" ); +} + +setspectatepermissions( ison ) +{ + if ( ison ) + { + self allowspectateteam( "allies", self.team == "allies" ); + } + if ( ison ) + { + self allowspectateteam( "axis", self.team == "axis" ); + } + self allowspectateteam( "freelook", 0 ); + self allowspectateteam( "none", 0 ); +} + +spectator_thread() +{ + self endon( "disconnect" ); + self endon( "spawned_player" ); +} + +spectator_toggle_3rd_person() +{ + self endon( "disconnect" ); + self endon( "spawned_player" ); + third_person = 1; + self set_third_person( 1 ); +} + +set_third_person( value ) +{ + if ( value ) + { + self setclientthirdperson( 1 ); + self setclientthirdpersonangle( 354 ); + self setdepthoffield( 0, 128, 512, 4000, 6, 1.8 ); + } + else + { + self setclientthirdperson( 0 ); + self setclientthirdpersonangle( 0 ); + self setdepthoffield( 0, 0, 512, 4000, 4, 0 ); + } + self resetfov(); +} + +last_stand_revive() +{ + level endon( "between_round_over" ); + players = get_players(); + laststand_count = 0; + _a2811 = players; + _k2811 = getFirstArrayKey( _a2811 ); + while ( isDefined( _k2811 ) ) + { + player = _a2811[ _k2811 ]; + if ( !is_player_valid( player ) ) + { + laststand_count++; + } + _k2811 = getNextArrayKey( _a2811, _k2811 ); + } + while ( laststand_count == players.size ) + { + i = 0; + while ( i < players.size ) + { + if ( players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].revivetrigger.beingrevived == 0 ) + { + players[ i ] maps/mp/zombies/_zm_laststand::auto_revive( players[ i ] ); + } + i++; + } + } +} + +last_stand_pistol_rank_init() +{ + level.pistol_values = []; + level.pistol_values[ level.pistol_values.size ] = "m1911_zm"; + level.pistol_values[ level.pistol_values.size ] = "c96_zm"; + level.pistol_values[ level.pistol_values.size ] = "cz75_zm"; + level.pistol_values[ level.pistol_values.size ] = "cz75dw_zm"; + level.pistol_values[ level.pistol_values.size ] = "kard_zm"; + level.pistol_values[ level.pistol_values.size ] = "fiveseven_zm"; + level.pistol_values[ level.pistol_values.size ] = "beretta93r_zm"; + level.pistol_values[ level.pistol_values.size ] = "beretta93r_extclip_zm"; + level.pistol_values[ level.pistol_values.size ] = "fivesevendw_zm"; + level.pistol_values[ level.pistol_values.size ] = "rnma_zm"; + level.pistol_values[ level.pistol_values.size ] = "python_zm"; + level.pistol_values[ level.pistol_values.size ] = "judge_zm"; + level.pistol_values[ level.pistol_values.size ] = "cz75_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "cz75dw_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "kard_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "fiveseven_upgraded_zm"; + level.pistol_value_solo_replace_below = level.pistol_values.size - 1; + level.pistol_values[ level.pistol_values.size ] = "m1911_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "c96_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "beretta93r_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "beretta93r_extclip_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "fivesevendw_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "rnma_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "python_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "judge_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "ray_gun_zm"; + level.pistol_values[ level.pistol_values.size ] = "raygun_mark2_zm"; + level.pistol_values[ level.pistol_values.size ] = "freezegun_zm"; + level.pistol_values[ level.pistol_values.size ] = "ray_gun_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "raygun_mark2_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "freezegun_upgraded_zm"; + level.pistol_values[ level.pistol_values.size ] = "microwavegundw_zm"; + level.pistol_values[ level.pistol_values.size ] = "microwavegundw_upgraded_zm"; +} + +last_stand_pistol_swap() +{ + if ( self has_powerup_weapon() ) + { + self.lastactiveweapon = "none"; + } + if ( !self hasweapon( self.laststandpistol ) ) + { + self giveweapon( self.laststandpistol ); + } + ammoclip = weaponclipsize( self.laststandpistol ); + doubleclip = ammoclip * 2; + if ( isDefined( self._special_solo_pistol_swap ) || self._special_solo_pistol_swap && self.laststandpistol == level.default_solo_laststandpistol && !self.hadpistol ) + { + self._special_solo_pistol_swap = 0; + self.hadpistol = 0; + self setweaponammostock( self.laststandpistol, doubleclip ); + } + else + { + if ( flag( "solo_game" ) && self.laststandpistol == level.default_solo_laststandpistol ) + { + self setweaponammostock( self.laststandpistol, doubleclip ); + } + else + { + if ( self.laststandpistol == level.default_laststandpistol ) + { + self setweaponammostock( self.laststandpistol, doubleclip ); + } + else if ( self.laststandpistol == "ray_gun_zm" || self.laststandpistol == "ray_gun_upgraded_zm" ) + { + if ( self.stored_weapon_info[ self.laststandpistol ].total_amt >= ammoclip ) + { + self setweaponammoclip( self.laststandpistol, ammoclip ); + self.stored_weapon_info[ self.laststandpistol ].given_amt = ammoclip; + } + else + { + self setweaponammoclip( self.laststandpistol, self.stored_weapon_info[ self.laststandpistol ].total_amt ); + self.stored_weapon_info[ self.laststandpistol ].given_amt = self.stored_weapon_info[ self.laststandpistol ].total_amt; + } + self setweaponammostock( self.laststandpistol, 0 ); + } + else + { + if ( self.stored_weapon_info[ self.laststandpistol ].stock_amt >= doubleclip ) + { + self setweaponammostock( self.laststandpistol, doubleclip ); + self.stored_weapon_info[ self.laststandpistol ].given_amt = doubleclip + self.stored_weapon_info[ self.laststandpistol ].clip_amt + self.stored_weapon_info[ self.laststandpistol ].left_clip_amt; + } + else + { + self setweaponammostock( self.laststandpistol, self.stored_weapon_info[ self.laststandpistol ].stock_amt ); + self.stored_weapon_info[ self.laststandpistol ].given_amt = self.stored_weapon_info[ self.laststandpistol ].total_amt; + } + } + } + } + self switchtoweapon( self.laststandpistol ); +} + +last_stand_best_pistol() +{ + pistol_array = []; + current_weapons = self getweaponslistprimaries(); + i = 0; + while ( i < current_weapons.size ) + { + class = weaponclass( current_weapons[ i ] ); + if ( issubstr( current_weapons[ i ], "knife_ballistic_" ) ) + { + class = "knife"; + } + while ( class != "pistol" || class == "pistolspread" && class == "pistol spread" ) + { + if ( current_weapons[ i ] != level.default_laststandpistol || !flag( "solo_game" ) && !flag( "solo_game" ) && current_weapons[ i ] != level.default_solo_laststandpistol ) + { + if ( self getammocount( current_weapons[ i ] ) <= 0 ) + { + i++; + continue; + } + } + else pistol_array_index = pistol_array.size; + pistol_array[ pistol_array_index ] = spawnstruct(); + pistol_array[ pistol_array_index ].gun = current_weapons[ i ]; + pistol_array[ pistol_array_index ].value = 0; + j = 0; + while ( j < level.pistol_values.size ) + { + if ( level.pistol_values[ j ] == current_weapons[ i ] ) + { + pistol_array[ pistol_array_index ].value = j; + i++; + continue; + } + else + { + j++; + } + } + } + i++; + } + self.laststandpistol = last_stand_compare_pistols( pistol_array ); +} + +last_stand_compare_pistols( struct_array ) +{ + if ( !isarray( struct_array ) || struct_array.size <= 0 ) + { + self.hadpistol = 0; + while ( isDefined( self.stored_weapon_info ) ) + { + stored_weapon_info = getarraykeys( self.stored_weapon_info ); + j = 0; + while ( j < stored_weapon_info.size ) + { + if ( stored_weapon_info[ j ] == level.laststandpistol ) + { + self.hadpistol = 1; + } + j++; + } + } + return level.laststandpistol; + } + highest_score_pistol = struct_array[ 0 ]; + i = 1; + while ( i < struct_array.size ) + { + if ( struct_array[ i ].value > highest_score_pistol.value ) + { + highest_score_pistol = struct_array[ i ]; + } + i++; + } + if ( flag( "solo_game" ) ) + { + self._special_solo_pistol_swap = 0; + if ( highest_score_pistol.value <= level.pistol_value_solo_replace_below ) + { + self.hadpistol = 0; + self._special_solo_pistol_swap = 1; + if ( isDefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive && !self hasperk( "specialty_quickrevive" ) && !self hasperk( "specialty_quickrevive" ) ) + { + return highest_score_pistol.gun; + } + else + { + return level.laststandpistol; + } + } + else + { + return highest_score_pistol.gun; + } + } + else + { + return highest_score_pistol.gun; + } +} + +last_stand_save_pistol_ammo() +{ + weapon_inventory = self getweaponslist( 1 ); + self.stored_weapon_info = []; + i = 0; + while ( i < weapon_inventory.size ) + { + weapon = weapon_inventory[ i ]; + class = weaponclass( weapon ); + if ( issubstr( weapon, "knife_ballistic_" ) ) + { + class = "knife"; + } + if ( class != "pistol" || class == "pistolspread" && class == "pistol spread" ) + { + self.stored_weapon_info[ weapon ] = spawnstruct(); + self.stored_weapon_info[ weapon ].clip_amt = self getweaponammoclip( weapon ); + self.stored_weapon_info[ weapon ].left_clip_amt = 0; + dual_wield_name = weapondualwieldweaponname( weapon ); + if ( dual_wield_name != "none" ) + { + self.stored_weapon_info[ weapon ].left_clip_amt = self getweaponammoclip( dual_wield_name ); + } + self.stored_weapon_info[ weapon ].stock_amt = self getweaponammostock( weapon ); + self.stored_weapon_info[ weapon ].total_amt = self.stored_weapon_info[ weapon ].clip_amt + self.stored_weapon_info[ weapon ].left_clip_amt + self.stored_weapon_info[ weapon ].stock_amt; + self.stored_weapon_info[ weapon ].given_amt = 0; + } + i++; + } + self last_stand_best_pistol(); +} + +last_stand_restore_pistol_ammo() +{ + self.weapon_taken_by_losing_specialty_additionalprimaryweapon = undefined; + if ( !isDefined( self.stored_weapon_info ) ) + { + return; + } + weapon_inventory = self getweaponslist( 1 ); + weapon_to_restore = getarraykeys( self.stored_weapon_info ); + i = 0; + while ( i < weapon_inventory.size ) + { + weapon = weapon_inventory[ i ]; + if ( weapon != self.laststandpistol ) + { + i++; + continue; + } + else j = 0; + while ( j < weapon_to_restore.size ) + { + check_weapon = weapon_to_restore[ j ]; + if ( weapon == check_weapon ) + { + dual_wield_name = weapondualwieldweaponname( weapon_to_restore[ j ] ); + if ( weapon != level.default_laststandpistol ) + { + last_clip = self getweaponammoclip( weapon ); + last_left_clip = 0; + if ( dual_wield_name != "none" ) + { + last_left_clip = self getweaponammoclip( dual_wield_name ); + } + last_stock = self getweaponammostock( weapon ); + last_total = last_clip + last_left_clip + last_stock; + used_amt = self.stored_weapon_info[ weapon ].given_amt - last_total; + if ( used_amt >= self.stored_weapon_info[ weapon ].stock_amt ) + { + used_amt -= self.stored_weapon_info[ weapon ].stock_amt; + self.stored_weapon_info[ weapon ].stock_amt = 0; + self.stored_weapon_info[ weapon ].clip_amt -= used_amt; + if ( self.stored_weapon_info[ weapon ].clip_amt < 0 ) + { + self.stored_weapon_info[ weapon ].clip_amt = 0; + } + break; + } + else + { + new_stock_amt = self.stored_weapon_info[ weapon ].stock_amt - used_amt; + if ( new_stock_amt < self.stored_weapon_info[ weapon ].stock_amt ) + { + self.stored_weapon_info[ weapon ].stock_amt = new_stock_amt; + } + } + } + self setweaponammoclip( weapon_to_restore[ j ], self.stored_weapon_info[ weapon_to_restore[ j ] ].clip_amt ); + if ( dual_wield_name != "none" ) + { + self setweaponammoclip( dual_wield_name, self.stored_weapon_info[ weapon_to_restore[ j ] ].left_clip_amt ); + } + self setweaponammostock( weapon_to_restore[ j ], self.stored_weapon_info[ weapon_to_restore[ j ] ].stock_amt ); + i++; + continue; + } + else + { + j++; + } + } + i++; + } +} + +last_stand_take_thrown_grenade() +{ + self endon( "disconnect" ); + self endon( "bled_out" ); + self endon( "player_revived" ); + self waittill( "grenade_fire", grenade, weaponname ); + if ( isDefined( self.lsgsar_lethal ) && weaponname == self.lsgsar_lethal ) + { + self.lsgsar_lethal_nade_amt--; + + } + if ( isDefined( self.lsgsar_tactical ) && weaponname == self.lsgsar_tactical ) + { + self.lsgsar_tactical_nade_amt--; + + } +} + +last_stand_grenade_save_and_return() +{ + if ( isDefined( level.isresetting_grief ) && level.isresetting_grief ) + { + return; + } + self endon( "disconnect" ); + self endon( "bled_out" ); + level endon( "between_round_over" ); + self.lsgsar_lethal_nade_amt = 0; + self.lsgsar_has_lethal_nade = 0; + self.lsgsar_tactical_nade_amt = 0; + self.lsgsar_has_tactical_nade = 0; + self.lsgsar_lethal = undefined; + self.lsgsar_tactical = undefined; + if ( self isthrowinggrenade() ) + { + self thread last_stand_take_thrown_grenade(); + } + weapons_on_player = self getweaponslist( 1 ); + i = 0; + while ( i < weapons_on_player.size ) + { + if ( self is_player_lethal_grenade( weapons_on_player[ i ] ) ) + { + self.lsgsar_has_lethal_nade = 1; + self.lsgsar_lethal = self get_player_lethal_grenade(); + self.lsgsar_lethal_nade_amt = self getweaponammoclip( self get_player_lethal_grenade() ); + self setweaponammoclip( self get_player_lethal_grenade(), 0 ); + self takeweapon( self get_player_lethal_grenade() ); + i++; + continue; + } + else + { + if ( self is_player_tactical_grenade( weapons_on_player[ i ] ) ) + { + self.lsgsar_has_tactical_nade = 1; + self.lsgsar_tactical = self get_player_tactical_grenade(); + self.lsgsar_tactical_nade_amt = self getweaponammoclip( self get_player_tactical_grenade() ); + self setweaponammoclip( self get_player_tactical_grenade(), 0 ); + self takeweapon( self get_player_tactical_grenade() ); + } + } + i++; + } + self waittill( "player_revived" ); + if ( self.lsgsar_has_lethal_nade ) + { + self set_player_lethal_grenade( self.lsgsar_lethal ); + self giveweapon( self.lsgsar_lethal ); + self setweaponammoclip( self.lsgsar_lethal, self.lsgsar_lethal_nade_amt ); + } + if ( self.lsgsar_has_tactical_nade ) + { + self set_player_tactical_grenade( self.lsgsar_tactical ); + self giveweapon( self.lsgsar_tactical ); + self setweaponammoclip( self.lsgsar_tactical, self.lsgsar_tactical_nade_amt ); + } + self.lsgsar_lethal_nade_amt = undefined; + self.lsgsar_has_lethal_nade = undefined; + self.lsgsar_tactical_nade_amt = undefined; + self.lsgsar_has_tactical_nade = undefined; + self.lsgsar_lethal = undefined; + self.lsgsar_tactical = undefined; +} + +spectators_respawn() +{ + level endon( "between_round_over" ); + if ( !isDefined( level.zombie_vars[ "spectators_respawn" ] ) || !level.zombie_vars[ "spectators_respawn" ] ) + { + return; + } + if ( !isDefined( level.custom_spawnplayer ) ) + { + level.custom_spawnplayer = ::spectator_respawn; + } + while ( 1 ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].sessionstate == "spectator" && isDefined( players[ i ].spectator_respawn ) ) + { + players[ i ] [[ level.spawnplayer ]](); + thread refresh_player_navcard_hud(); + if ( isDefined( level.script ) && level.round_number > 6 && players[ i ].score < 1500 ) + { + players[ i ].old_score = players[ i ].score; + if ( isDefined( level.spectator_respawn_custom_score ) ) + { + players[ i ] [[ level.spectator_respawn_custom_score ]](); + } + players[ i ].score = 1500; + } + } + i++; + } + wait 1; + } +} + +spectator_respawn() +{ +/* +/# + println( "*************************Respawn Spectator***" ); +#/ +/# + assert( isDefined( self.spectator_respawn ) ); +#/ +*/ + origin = self.spectator_respawn.origin; + angles = self.spectator_respawn.angles; + self setspectatepermissions( 0 ); + new_origin = undefined; + if ( isDefined( level.check_valid_spawn_override ) ) + { + new_origin = [[ level.check_valid_spawn_override ]]( self ); + } + if ( !isDefined( new_origin ) ) + { + new_origin = check_for_valid_spawn_near_team( self, 1 ); + } + if ( isDefined( new_origin ) ) + { + if ( !isDefined( new_origin.angles ) ) + { + angles = ( 0, 0, -1 ); + } + else + { + angles = new_origin.angles; + } + self spawn( new_origin.origin, angles ); + } + else + { + self spawn( origin, angles ); + } + if ( isDefined( self get_player_placeable_mine() ) ) + { + self takeweapon( self get_player_placeable_mine() ); + self set_player_placeable_mine( undefined ); + } + self maps/mp/zombies/_zm_equipment::equipment_take(); + self.is_burning = undefined; + self.abilities = []; + self.is_zombie = 0; + self.ignoreme = 0; + setclientsysstate( "lsm", "0", self ); + self reviveplayer(); + self notify( "spawned_player" ); + if ( isDefined( level._zombiemode_post_respawn_callback ) ) + { + self thread [[ level._zombiemode_post_respawn_callback ]](); + } + self maps/mp/zombies/_zm_score::player_reduce_points( "died" ); + self maps/mp/zombies/_zm_melee_weapon::spectator_respawn_all(); + claymore_triggers = getentarray( "claymore_purchase", "targetname" ); + i = 0; + while ( i < claymore_triggers.size ) + { + claymore_triggers[ i ] setvisibletoplayer( self ); + claymore_triggers[ i ].claymores_triggered = 0; + i++; + } + self thread player_zombie_breadcrumb(); + self thread return_retained_perks(); + return 1; +} + +check_for_valid_spawn_near_team( revivee, return_struct ) +{ + if ( isDefined( level.check_for_valid_spawn_near_team_callback ) ) + { + spawn_location = [[ level.check_for_valid_spawn_near_team_callback ]]( revivee, return_struct ); + return spawn_location; + } + else + { + players = get_players(); + spawn_points = maps/mp/gametypes_zm/_zm_gametype::get_player_spawns_for_gametype(); + closest_group = undefined; + closest_distance = 100000000; + backup_group = undefined; + backup_distance = 100000000; + if ( spawn_points.size == 0 ) + { + return undefined; + } + i = 0; + while ( i < players.size ) + { + while ( is_player_valid( players[ i ], undefined, 1 ) && players[ i ] != self ) + { + j = 0; + while ( j < spawn_points.size ) + { + if ( isDefined( spawn_points[ j ].script_int ) ) + { + ideal_distance = spawn_points[ j ].script_int; + } + else + { + ideal_distance = 1000; + } + if ( spawn_points[ j ].locked == 0 ) + { + plyr_dist = distancesquared( players[ i ].origin, spawn_points[ j ].origin ); + if ( plyr_dist < ( ideal_distance * ideal_distance ) ) + { + if ( plyr_dist < closest_distance ) + { + closest_distance = plyr_dist; + closest_group = j; + } + j++; + continue; + } + else + { + if ( plyr_dist < backup_distance ) + { + backup_group = j; + backup_distance = plyr_dist; + } + } + } + j++; + } + } + if ( !isDefined( closest_group ) ) + { + closest_group = backup_group; + } + if ( isDefined( closest_group ) ) + { + spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ); + if ( isDefined( spawn_location ) ) + { + return spawn_location; + } + } + i++; + } + return undefined; + } +} + +get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ) +{ + spawn_array = getstructarray( spawn_points[ closest_group ].target, "targetname" ); + spawn_array = array_randomize( spawn_array ); + k = 0; + while ( k < spawn_array.size ) + { + if ( isDefined( spawn_array[ k ].plyr ) && spawn_array[ k ].plyr == revivee getentitynumber() ) + { + if ( positionwouldtelefrag( spawn_array[ k ].origin ) ) + { + spawn_array[ k ].plyr = undefined; + break; + } + else if ( isDefined( return_struct ) && return_struct ) + { + return spawn_array[ k ]; + } + else + { + return spawn_array[ k ].origin; + } + } + k++; + } + k = 0; + while ( k < spawn_array.size ) + { + if ( positionwouldtelefrag( spawn_array[ k ].origin ) ) + { + k++; + continue; + } + else if ( !isDefined( spawn_array[ k ].plyr ) || spawn_array[ k ].plyr == revivee getentitynumber() ) + { + spawn_array[ k ].plyr = revivee getentitynumber(); + if ( isDefined( return_struct ) && return_struct ) + { + return spawn_array[ k ]; + } + else + { + return spawn_array[ k ].origin; + } + } + k++; + } + if ( isDefined( return_struct ) && return_struct ) + { + return spawn_array[ 0 ]; + } + return spawn_array[ 0 ].origin; +} + +check_for_valid_spawn_near_position( revivee, v_position, return_struct ) +{ + spawn_points = maps/mp/gametypes_zm/_zm_gametype::get_player_spawns_for_gametype(); + if ( spawn_points.size == 0 ) + { + return undefined; + } + closest_group = undefined; + closest_distance = 100000000; + backup_group = undefined; + backup_distance = 100000000; + i = 0; + while ( i < spawn_points.size ) + { + if ( isDefined( spawn_points[ i ].script_int ) ) + { + ideal_distance = spawn_points[ i ].script_int; + } + else + { + ideal_distance = 1000; + } + if ( spawn_points[ i ].locked == 0 ) + { + dist = distancesquared( v_position, spawn_points[ i ].origin ); + if ( dist < ( ideal_distance * ideal_distance ) ) + { + if ( dist < closest_distance ) + { + closest_distance = dist; + closest_group = i; + } + break; + } + else + { + if ( dist < backup_distance ) + { + backup_group = i; + backup_distance = dist; + } + } + } + if ( !isDefined( closest_group ) ) + { + closest_group = backup_group; + } + i++; + } + if ( isDefined( closest_group ) ) + { + spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ); + if ( isDefined( spawn_location ) ) + { + return spawn_location; + } + } + return undefined; +} + +check_for_valid_spawn_within_range( revivee, v_position, return_struct, min_distance, max_distance ) +{ + spawn_points = maps/mp/gametypes_zm/_zm_gametype::get_player_spawns_for_gametype(); + if ( spawn_points.size == 0 ) + { + return undefined; + } + closest_group = undefined; + closest_distance = 100000000; + i = 0; + while ( i < spawn_points.size ) + { + if ( spawn_points[ i ].locked == 0 ) + { + dist = distance( v_position, spawn_points[ i ].origin ); + if ( dist >= min_distance && dist <= max_distance ) + { + if ( dist < closest_distance ) + { + closest_distance = dist; + closest_group = i; + } + } + } + i++; + } + if ( isDefined( closest_group ) ) + { + spawn_location = get_valid_spawn_location( revivee, spawn_points, closest_group, return_struct ); + if ( isDefined( spawn_location ) ) + { + return spawn_location; + } + } + return undefined; +} + +get_players_on_team( exclude ) +{ + teammates = []; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].spawn_side == self.spawn_side && !isDefined( players[ i ].revivetrigger ) && players[ i ] != exclude ) + { + teammates[ teammates.size ] = players[ i ]; + } + i++; + } + return teammates; +} + +get_safe_breadcrumb_pos( player ) +{ + players = get_players(); + valid_players = []; + min_dist = 22500; + i = 0; + while ( i < players.size ) + { + if ( !is_player_valid( players[ i ] ) ) + { + i++; + continue; + } + else + { + valid_players[ valid_players.size ] = players[ i ]; + } + i++; + } + i = 0; + while ( i < valid_players.size ) + { + count = 0; + q = 1; + while ( q < player.zombie_breadcrumbs.size ) + { + if ( distancesquared( player.zombie_breadcrumbs[ q ], valid_players[ i ].origin ) < min_dist ) + { + q++; + continue; + } + else + { + count++; + if ( count == valid_players.size ) + { + return player.zombie_breadcrumbs[ q ]; + } + } + q++; + } + i++; + } + return undefined; +} + +default_max_zombie_func( max_num ) +{ + /* +/# + count = getDvarInt( #"CF687B54" ); + if ( count > -1 ) + { + return count; +#/ + } + */ + max = max_num; + if ( level.round_number < 2 ) + { + max = int( max_num * 0.25 ); + } + else if ( level.round_number < 3 ) + { + max = int( max_num * 0.3 ); + } + else if ( level.round_number < 4 ) + { + max = int( max_num * 0.5 ); + } + else if ( level.round_number < 5 ) + { + max = int( max_num * 0.7 ); + } + else + { + if ( level.round_number < 6 ) + { + max = int( max_num * 0.9 ); + } + } + return max; +} + +round_spawning() +{ + level endon( "intermission" ); + level endon( "end_of_round" ); + level endon( "restart_round" ); + /* +/# + level endon( "kill_round" ); +#/ + */ + if ( level.intermission ) + { + return; + } + /* +/# + if ( getDvarInt( "zombie_cheat" ) == 2 || getDvarInt( "zombie_cheat" ) >= 4 ) + { + return; +#/ + } + */ + if ( level.zombie_spawn_locations.size < 1 ) + { + /* +/# + assertmsg( "No active spawners in the map. Check to see if the zone is active and if it's pointing to spawners." ); +#/ + */ + return; + } + ai_calculate_health( level.round_number ); + count = 0; + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ].zombification_time = 0; + i++; + } + max = level.zombie_vars[ "zombie_max_ai" ]; + multiplier = level.round_number / 5; + if ( multiplier < 1 ) + { + multiplier = 1; + } + if ( level.round_number >= 10 ) + { + multiplier *= level.round_number * 0.15; + } + player_num = get_players().size; + if ( player_num == 1 ) + { + max += int( 0.5 * level.zombie_vars[ "zombie_ai_per_player" ] * multiplier ); + } + else + { + max += int( ( player_num - 1 ) * level.zombie_vars[ "zombie_ai_per_player" ] * multiplier ); + } + if ( !isDefined( level.max_zombie_func ) ) + { + level.max_zombie_func = ::default_max_zombie_func; + } + if ( isDefined( level.kill_counter_hud ) && level.zombie_total > 0 ) + { + level.zombie_total = [[ level.max_zombie_func ]]( max ); + level notify( "zombie_total_set" ); + } + if ( isDefined( level.zombie_total_set_func ) ) + { + level thread [[ level.zombie_total_set_func ]](); + } + if ( level.round_number < 10 || level.speed_change_max > 0 ) + { + level thread zombie_speed_up(); + } + mixed_spawns = 0; + old_spawn = undefined; + while ( 1 ) + { + while ( get_current_zombie_count() >= level.zombie_ai_limit || level.zombie_total <= 0 ) + { + wait 0.1; + } + while ( get_current_actor_count() >= level.zombie_actor_limit ) + { + clear_all_corpses(); + wait 0.1; + } + flag_wait( "spawn_zombies" ); + while ( level.zombie_spawn_locations.size <= 0 ) + { + wait 0.1; + } + run_custom_ai_spawn_checks(); + spawn_point = level.zombie_spawn_locations[ randomint( level.zombie_spawn_locations.size ) ]; + if ( !isDefined( old_spawn ) ) + { + old_spawn = spawn_point; + } + else + { + if ( spawn_point == old_spawn ) + { + spawn_point = level.zombie_spawn_locations[ randomint( level.zombie_spawn_locations.size ) ]; + } + } + old_spawn = spawn_point; + while ( isDefined( level.mixed_rounds_enabled ) && level.mixed_rounds_enabled == 1 ) + { + spawn_dog = 0; + if ( level.round_number > 30 ) + { + if ( randomint( 100 ) < 3 ) + { + spawn_dog = 1; + } + } + else if ( level.round_number > 25 && mixed_spawns < 3 ) + { + if ( randomint( 100 ) < 2 ) + { + spawn_dog = 1; + } + } + else + { + if ( level.round_number > 20 && mixed_spawns < 2 ) + { + if ( randomint( 100 ) < 2 ) + { + spawn_dog = 1; + } + break; + } + else + { + if ( level.round_number > 15 && mixed_spawns < 1 ) + { + if ( randomint( 100 ) < 1 ) + { + spawn_dog = 1; + } + } + } + } + while ( spawn_dog ) + { + keys = getarraykeys( level.zones ); + i = 0; + while ( i < keys.size ) + { + while ( level.zones[ keys[ i ] ].is_occupied ) + { + akeys = getarraykeys( level.zones[ keys[ i ] ].adjacent_zones ); + k = 0; + while ( k < akeys.size ) + { + if ( level.zones[ akeys[ k ] ].is_active && !level.zones[ akeys[ k ] ].is_occupied && level.zones[ akeys[ k ] ].dog_locations.size > 0 ) + { + maps/mp/zombies/_zm_ai_dogs::special_dog_spawn( undefined, 1 ); + level.zombie_total--; + + wait_network_frame(); + } + k++; + } + } + i++; + } + } + } + if ( isDefined( level.zombie_spawners ) ) + { + if ( isDefined( level.use_multiple_spawns ) && level.use_multiple_spawns ) + { + if ( isDefined( spawn_point.script_int ) ) + { + if ( isDefined( level.zombie_spawn[ spawn_point.script_int ] ) && level.zombie_spawn[ spawn_point.script_int ].size ) + { + spawner = random( level.zombie_spawn[ spawn_point.script_int ] ); + } + else + { + /* +/# + assertmsg( "Wanting to spawn from zombie group " + spawn_point.script_int + "but it doens't exist" ); +#/ + */ + } + } + else if ( isDefined( level.zones[ spawn_point.zone_name ].script_int ) && level.zones[ spawn_point.zone_name ].script_int ) + { + spawner = random( level.zombie_spawn[ level.zones[ spawn_point.zone_name ].script_int ] ); + } + else + { + if ( isDefined( level.spawner_int ) && isDefined( level.zombie_spawn[ level.spawner_int ].size ) && level.zombie_spawn[ level.spawner_int ].size ) + { + spawner = random( level.zombie_spawn[ level.spawner_int ] ); + break; + } + else + { + spawner = random( level.zombie_spawners ); + } + } + } + else + { + spawner = random( level.zombie_spawners ); + } + ai = spawn_zombie( spawner, spawner.targetname, spawn_point ); + } + if ( isDefined( ai ) ) + { + level.zombie_total--; + + ai thread round_spawn_failsafe(); + count++; + } + wait level.zombie_vars[ "zombie_spawn_delay" ]; + wait_network_frame(); + } +} + +run_custom_ai_spawn_checks() +{ + _a3949 = level.custom_ai_spawn_check_funcs; + str_id = getFirstArrayKey( _a3949 ); + while ( isDefined( str_id ) ) + { + s = _a3949[ str_id ]; + if ( [[ s.func_check ]]() ) + { + a_spawners = [[ s.func_get_spawners ]](); + level.zombie_spawners = arraycombine( level.zombie_spawners, a_spawners, 0, 0 ); + while ( isDefined( level.use_multiple_spawns ) && level.use_multiple_spawns ) + { + _a3958 = a_spawners; + _k3958 = getFirstArrayKey( _a3958 ); + while ( isDefined( _k3958 ) ) + { + sp = _a3958[ _k3958 ]; + if ( isDefined( sp.script_int ) ) + { + if ( !isDefined( level.zombie_spawn[ sp.script_int ] ) ) + { + level.zombie_spawn[ sp.script_int ] = []; + } + if ( !isinarray( level.zombie_spawn[ sp.script_int ], sp ) ) + { + level.zombie_spawn[ sp.script_int ][ level.zombie_spawn[ sp.script_int ].size ] = sp; + } + } + _k3958 = getNextArrayKey( _a3958, _k3958 ); + } + } + if ( isDefined( s.func_get_locations ) ) + { + a_locations = [[ s.func_get_locations ]](); + level.zombie_spawn_locations = arraycombine( level.zombie_spawn_locations, a_locations, 0, 0 ); + } + } + else + { + a_spawners = [[ s.func_get_spawners ]](); + _a3985 = a_spawners; + _k3985 = getFirstArrayKey( _a3985 ); + while ( isDefined( _k3985 ) ) + { + sp = _a3985[ _k3985 ]; + arrayremovevalue( level.zombie_spawners, sp ); + _k3985 = getNextArrayKey( _a3985, _k3985 ); + } + while ( isDefined( level.use_multiple_spawns ) && level.use_multiple_spawns ) + { + _a3992 = a_spawners; + _k3992 = getFirstArrayKey( _a3992 ); + while ( isDefined( _k3992 ) ) + { + sp = _a3992[ _k3992 ]; + if ( isDefined( sp.script_int ) && isDefined( level.zombie_spawn[ sp.script_int ] ) ) + { + arrayremovevalue( level.zombie_spawn[ sp.script_int ], sp ); + } + _k3992 = getNextArrayKey( _a3992, _k3992 ); + } + } + while ( isDefined( s.func_get_locations ) ) + { + a_locations = [[ s.func_get_locations ]](); + _a4005 = a_locations; + _k4005 = getFirstArrayKey( _a4005 ); + while ( isDefined( _k4005 ) ) + { + s_loc = _a4005[ _k4005 ]; + arrayremovevalue( level.zombie_spawn_locations, s_loc ); + _k4005 = getNextArrayKey( _a4005, _k4005 ); + } + } + } + str_id = getNextArrayKey( _a3949, str_id ); + } +} + +register_custom_ai_spawn_check( str_id, func_check, func_get_spawners, func_get_locations ) +{ + if ( !isDefined( level.custom_ai_spawn_check_funcs[ str_id ] ) ) + { + level.custom_ai_spawn_check_funcs[ str_id ] = spawnstruct(); + } + level.custom_ai_spawn_check_funcs[ str_id ].func_check = func_check; + level.custom_ai_spawn_check_funcs[ str_id ].func_get_spawners = func_get_spawners; + level.custom_ai_spawn_check_funcs[ str_id ].func_get_locations = func_get_locations; +} + +zombie_speed_up() +{ + if ( level.round_number <= 3 ) + { + return; + } + level endon( "intermission" ); + level endon( "end_of_round" ); + level endon( "restart_round" ); + /* +/# + level endon( "kill_round" ); +#/ + */ + while ( level.zombie_total > 4 ) + { + wait 2; + } + num_zombies = get_current_zombie_count(); + while ( num_zombies > 3 ) + { + wait 2; + num_zombies = get_current_zombie_count(); + } + zombies = get_round_enemy_array(); + while ( zombies.size > 0 ) + { + if ( zombies.size == 1 && isDefined( zombies[ 0 ].has_legs ) && zombies[ 0 ].has_legs ) + { + if ( isDefined( level.zombie_speed_up ) ) + { + zombies[ 0 ] thread [[ level.zombie_speed_up ]](); + break; + } + else + { + if ( zombies[ 0 ].zombie_move_speed != "sprint" ) + { + zombies[ 0 ] set_zombie_run_cycle( "sprint" ); + zombies[ 0 ].zombie_move_speed_original = zombies[ 0 ].zombie_move_speed; + } + } + } + wait 0.5; + zombies = get_round_enemy_array(); + } +} + +round_spawning_test() +{ + while ( 1 ) + { + spawn_point = level.zombie_spawn_locations[ randomint( level.zombie_spawn_locations.size ) ]; + spawner = random( level.zombie_spawners ); + ai = spawn_zombie( spawner, spawner.targetname, spawn_point ); + ai waittill( "death" ); + wait 5; + } +} + +round_pause( delay ) +{ + if ( !isDefined( delay ) ) + { + delay = 30; + } + level.countdown_hud = create_counter_hud(); + level.countdown_hud setvalue( delay ); + level.countdown_hud.color = ( 0, 0, -1 ); + level.countdown_hud.alpha = 1; + level.countdown_hud fadeovertime( 2 ); + wait 2; + level.countdown_hud.color = vectorScale( ( 0, 0, -1 ), 0,21 ); + level.countdown_hud fadeovertime( 3 ); + wait 3; + while ( delay >= 1 ) + { + wait 1; + delay--; + + level.countdown_hud setvalue( delay ); + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] playlocalsound( "zmb_perks_packa_ready" ); + i++; + } + level.countdown_hud fadeovertime( 1 ); + level.countdown_hud.color = ( 0, 0, -1 ); + level.countdown_hud.alpha = 0; + wait 1; + level.countdown_hud destroy_hud(); +} + +round_start() +{ +/* +/# + println( "ZM >> round_start start" ); +#/ +*/ + if ( isDefined( level.round_prestart_func ) ) + { + [[ level.round_prestart_func ]](); + } + else + { + n_delay = 2; + if ( isDefined( level.zombie_round_start_delay ) ) + { + n_delay = level.zombie_round_start_delay; + } + wait n_delay; + } + level.zombie_health = level.zombie_vars[ "zombie_health_start" ]; + if ( getDvarInt( "scr_writeConfigStrings" ) == 1 ) + { + wait 5; + exitlevel(); + return; + } + if ( level.zombie_vars[ "game_start_delay" ] > 0 ) + { + round_pause( level.zombie_vars[ "game_start_delay" ] ); + } + flag_set( "begin_spawning" ); + if ( !isDefined( level.round_spawn_func ) ) + { + level.round_spawn_func = ::round_spawning; + } + /* +/# + if ( getDvarInt( #"7688603C" ) ) + { + level.round_spawn_func = ::round_spawning_test; +#/ + } + */ + if ( !isDefined( level.round_wait_func ) ) + { + level.round_wait_func = ::round_wait; + } + if ( !isDefined( level.round_think_func ) ) + { + level.round_think_func = ::round_think; + } + level thread [[ level.round_think_func ]](); +} + +play_door_dialog() +{ + level endon( "power_on" ); + self endon( "warning_dialog" ); + timer = 0; + while ( 1 ) + { + wait 0.05; + players = get_players(); + i = 0; + while ( i < players.size ) + { + dist = distancesquared( players[ i ].origin, self.origin ); + if ( dist > 4900 ) + { + timer = 0; + i++; + continue; + } + else + { + while ( dist < 4900 && timer < 3 ) + { + wait 0.5; + timer++; + } + if ( dist > 4900 && timer >= 3 ) + { + self playsound( "door_deny" ); + players[ i ] maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "door_deny" ); + wait 3; + self notify( "warning_dialog" ); + } + } + i++; + } + } +} + +wait_until_first_player() +{ + players = get_players(); + if ( !isDefined( players[ 0 ] ) ) + { + level waittill( "first_player_ready" ); + } +} + +round_one_up() +{ + level endon( "end_game" ); + if ( isDefined( level.noroundnumber ) && level.noroundnumber == 1 ) + { + return; + } + if ( !isDefined( level.doground_nomusic ) ) + { + level.doground_nomusic = 0; + } + if ( level.first_round ) + { + intro = 1; + if ( isDefined( level._custom_intro_vox ) ) + { + level thread [[ level._custom_intro_vox ]](); + } + else + { + level thread play_level_start_vox_delayed(); + } + } + else + { + intro = 0; + } + if ( level.round_number != 5 && level.round_number != 10 && level.round_number != 20 || level.round_number == 35 && level.round_number == 50 ) + { + players = get_players(); + rand = randomintrange( 0, players.size ); + players[ rand ] thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "round_" + level.round_number ); + } + if ( intro ) + { + if ( isDefined( level.host_ended_game ) && level.host_ended_game ) + { + return; + } + wait 6.25; + level notify( "intro_hud_done" ); + wait 2; + } + else + { + wait 2.5; + } + reportmtu( level.round_number ); +} + +round_over() +{ + if ( isDefined( level.noroundnumber ) && level.noroundnumber == 1 ) + { + return; + } + time = level.zombie_vars[ "zombie_between_round_time" ]; + players = getplayers(); + player_index = 0; + while ( player_index < players.size ) + { + if ( !isDefined( players[ player_index ].pers[ "previous_distance_traveled" ] ) ) + { + players[ player_index ].pers[ "previous_distance_traveled" ] = 0; + } + distancethisround = int( players[ player_index ].pers[ "distance_traveled" ] - players[ player_index ].pers[ "previous_distance_traveled" ] ); + players[ player_index ].pers[ "previous_distance_traveled" ] = players[ player_index ].pers[ "distance_traveled" ]; + players[ player_index ] incrementplayerstat( "distance_traveled", distancethisround ); + if ( players[ player_index ].pers[ "team" ] != "spectator" ) + { + zonename = players[ player_index ] get_current_zone(); + if ( isDefined( zonename ) ) + { + players[ player_index ] recordzombiezone( "endingZone", zonename ); + } + } + player_index++; + } + recordzombieroundend(); + wait time; +} + +round_think( restart ) +{ + if ( !isDefined( restart ) ) + { + restart = 0; + } + /* +/# + println( "ZM >> round_think start" ); +#/ + */ + level endon( "end_round_think" ); + while ( isDefined( restart ) && !restart ) + { + if ( isDefined( level.initial_round_wait_func ) ) + { + [[ level.initial_round_wait_func ]](); + } + while ( isDefined( level.host_ended_game ) && !level.host_ended_game ) + { + players = get_players(); + _a4430 = players; + _k4430 = getFirstArrayKey( _a4430 ); + while ( isDefined( _k4430 ) ) + { + player = _a4430[ _k4430 ]; + if ( isDefined( player.hostmigrationcontrolsfrozen ) && !player.hostmigrationcontrolsfrozen ) + { + player freezecontrols( 0 ); + /* +/# + println( " Unfreeze controls 8" ); +#/ + */ + } + player maps/mp/zombies/_zm_stats::set_global_stat( "rounds", level.round_number ); + _k4430 = getNextArrayKey( _a4430, _k4430 ); + } + } + } + setroundsplayed( level.round_number ); + for ( ;; ) + { + maxreward = 50 * level.round_number; + if ( maxreward > 500 ) + { + maxreward = 500; + } + level.zombie_vars[ "rebuild_barrier_cap_per_round" ] = maxreward; + level.pro_tips_start_time = getTime(); + level.zombie_last_run_time = getTime(); + if ( isDefined( level.zombie_round_change_custom ) ) + { + [[ level.zombie_round_change_custom ]](); + } + else + { + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "round_start" ); + round_one_up(); + } + maps/mp/zombies/_zm_powerups::powerup_round_start(); + players = get_players(); + array_thread( players, ::rebuild_barrier_reward_reset ); + if ( isDefined( level.headshots_only ) && !level.headshots_only && !restart ) + { + level thread award_grenades_for_survivors(); + } + /* + bbprint( "zombie_rounds", "round %d player_count %d", level.round_number, players.size ); +/# + println( "ZM >> round_think, round=" + level.round_number + ", player_count=" + players.size ); +#/ + */ + level.round_start_time = getTime(); + while ( level.zombie_spawn_locations.size <= 0 ) + { + wait 0.1; + } + level thread [[ level.round_spawn_func ]](); + level notify( "start_of_round" ); + recordzombieroundstart(); + players = getplayers(); + index = 0; + while ( index < players.size ) + { + zonename = players[ index ] get_current_zone(); + if ( isDefined( zonename ) ) + { + players[ index ] recordzombiezone( "startingZone", zonename ); + } + index++; + } + if ( isDefined( level.round_start_custom_func ) ) + { + [[ level.round_start_custom_func ]](); + } + [[ level.round_wait_func ]](); + level.first_round = 0; + level notify( "end_of_round" ); + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "round_end" ); + uploadstats(); + if ( isDefined( level.round_end_custom_logic ) ) + { + [[ level.round_end_custom_logic ]](); + } + players = get_players(); + if ( isDefined( level.no_end_game_check ) && level.no_end_game_check ) + { + level thread last_stand_revive(); + level thread spectators_respawn(); + } + else + { + if ( players.size != 1 ) + { + level thread spectators_respawn(); + } + } + players = get_players(); + array_thread( players, ::round_end ); + timer = level.zombie_vars[ "zombie_spawn_delay" ]; + if ( timer > 0.08 ) + { + level.zombie_vars[ "zombie_spawn_delay" ] = timer * 0.95; + } + else + { + if ( timer < 0.08 ) + { + level.zombie_vars[ "zombie_spawn_delay" ] = 0.08; + } + } + if ( level.gamedifficulty == 0 ) + { + level.zombie_move_speed = level.round_number * level.zombie_vars[ "zombie_move_speed_multiplier_easy" ]; + } + else + { + level.zombie_move_speed = level.round_number * level.zombie_vars[ "zombie_move_speed_multiplier" ]; + } + level.round_number++; + if ( level.round_number >= 255 ) + { + level.round_number = 255; + } + setroundsplayed( level.round_number ); + matchutctime = getutc(); + players = get_players(); + _a4579 = players; + _k4579 = getFirstArrayKey( _a4579 ); + while ( isDefined( _k4579 ) ) + { + player = _a4579[ _k4579 ]; + if ( level.curr_gametype_affects_rank && level.round_number > ( 3 + level.start_round ) ) + { + player maps/mp/zombies/_zm_stats::add_client_stat( "weighted_rounds_played", level.round_number ); + } + player maps/mp/zombies/_zm_stats::set_global_stat( "rounds", level.round_number ); + player maps/mp/zombies/_zm_stats::update_playing_utc_time( matchutctime ); + _k4579 = getNextArrayKey( _a4579, _k4579 ); + } + //check_quickrevive_for_hotjoin(); + level round_over(); + level notify( "between_round_over" ); + restart = 0; + } +} + +award_grenades_for_survivors() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( !players[ i ].is_zombie ) + { + lethal_grenade = players[ i ] get_player_lethal_grenade(); + if ( !players[ i ] hasweapon( lethal_grenade ) ) + { + players[ i ] giveweapon( lethal_grenade ); + players[ i ] setweaponammoclip( lethal_grenade, 0 ); + } + if ( players[ i ] getfractionmaxammo( lethal_grenade ) < 0.25 ) + { + players[ i ] setweaponammoclip( lethal_grenade, 2 ); + i++; + continue; + } + else if ( players[ i ] getfractionmaxammo( lethal_grenade ) < 0.5 ) + { + players[ i ] setweaponammoclip( lethal_grenade, 3 ); + i++; + continue; + } + else + { + players[ i ] setweaponammoclip( lethal_grenade, 4 ); + } + } + i++; + } +} + +ai_calculate_health( round_number ) +{ + level.zombie_health = level.zombie_vars[ "zombie_health_start" ]; + i = 2; + while ( i <= round_number ) + { + if ( i >= 10 ) + { + old_health = level.zombie_health; + level.zombie_health += int( level.zombie_health * level.zombie_vars[ "zombie_health_increase_multiplier" ] ); + if ( level.zombie_health < old_health ) + { + level.zombie_health = old_health; + return; + } + i++; + continue; + } + else + { + level.zombie_health = int( level.zombie_health + level.zombie_vars[ "zombie_health_increase" ] ); + } + i++; + } +} + +ai_zombie_health( round_number ) +{ + zombie_health = level.zombie_vars[ "zombie_health_start" ]; + i = 2; + while ( i <= round_number ) + { + if ( i >= 10 ) + { + old_health = zombie_health; + zombie_health += int( zombie_health * level.zombie_vars[ "zombie_health_increase_multiplier" ] ); + if ( zombie_health < old_health ) + { + return old_health; + } + } + else + { + zombie_health = int( zombie_health + level.zombie_vars[ "zombie_health_increase" ] ); + } + i++; + } + return zombie_health; +} + +round_spawn_failsafe_debug() +{ +/* +/# + level notify( "failsafe_debug_stop" ); + level endon( "failsafe_debug_stop" ); + start = getTime(); + level.chunk_time = 0; + while ( 1 ) + { + level.failsafe_time = getTime() - start; + if ( isDefined( self.lastchunk_destroy_time ) ) + { + level.chunk_time = getTime() - self.lastchunk_destroy_time; + } + wait_network_frame(); +#/ + } +*/ +} + +round_spawn_failsafe() +{ + self endon( "death" ); + prevorigin = self.origin; + while ( 1 ) + { + if ( !level.zombie_vars[ "zombie_use_failsafe" ] ) + { + return; + } + if ( isDefined( self.ignore_round_spawn_failsafe ) && self.ignore_round_spawn_failsafe ) + { + return; + } + wait 30; + if ( !self.has_legs ) + { + wait 10; + } + if ( isDefined( self.is_inert ) && self.is_inert ) + { + continue; + } + while ( isDefined( self.lastchunk_destroy_time ) ) + { + while ( ( getTime() - self.lastchunk_destroy_time ) < 8000 ) + { + continue; + } + } + if ( self.origin[ 2 ] < level.zombie_vars[ "below_world_check" ] ) + { + if ( isDefined( level.put_timed_out_zombies_back_in_queue ) && level.put_timed_out_zombies_back_in_queue && !flag( "dog_round" ) && isDefined( self.isscreecher ) && !self.isscreecher ) + { + level.zombie_total++; + level.zombie_total_subtract++; + } + /* +/# +#/ + */ + self dodamage( self.health + 100, ( 0, 0, -1 ) ); + return; + } + else if ( distancesquared( self.origin, prevorigin ) < 576 ) + { + if ( isDefined( level.put_timed_out_zombies_back_in_queue ) && level.put_timed_out_zombies_back_in_queue && !flag( "dog_round" ) ) + { + if ( !self.ignoreall && isDefined( self.nuked ) && !self.nuked && isDefined( self.marked_for_death ) && !self.marked_for_death && isDefined( self.isscreecher ) && !self.isscreecher && isDefined( self.has_legs ) && self.has_legs ) + { + level.zombie_total++; + level.zombie_total_subtract++; + } + } + level.zombies_timeout_playspace++; + /* +/# +#/ + */ + self dodamage( self.health + 100, ( 0, 0, -1 ) ); + return; + } + else + { + prevorigin = self.origin; + } + } +} + +round_wait() +{ + level endon( "restart_round" ); + /* +/# + if ( getDvarInt( #"7688603C" ) ) + { + level waittill( "forever" ); +#/ + } +/# + if ( getDvarInt( "zombie_cheat" ) == 2 || getDvarInt( "zombie_cheat" ) >= 4 ) + { + level waittill( "forever" ); +#/ + } + */ + wait 1; + if ( flag( "dog_round" ) ) + { + wait 7; + while ( level.dog_intermission ) + { + wait 0.5; + } + increment_dog_round_stat( "finished" ); + } + else + { + while ( 1 ) + { + should_wait = 0; + if ( isDefined( level.is_ghost_round_started ) && [[ level.is_ghost_round_started ]]() ) + { + should_wait = 1; + } + else + { + if ( get_current_zombie_count() > 0 && level.zombie_total > 0 ) + { + should_wait = level.intermission; + } + } + if ( !should_wait ) + { + return; + } + if ( flag( "end_round_wait" ) ) + { + return; + } + wait 1; + } + } +} + +zombify_player() +{ + self maps/mp/zombies/_zm_score::player_died_penalty(); + bbprint( "zombie_playerdeaths", "round %d playername %s deathtype %s x %f y %f z %f", level.round_number, self.name, "died", self.origin ); + self recordplayerdeathzombies(); + if ( isDefined( level.deathcard_spawn_func ) ) + { + self [[ level.deathcard_spawn_func ]](); + } + if ( !isDefined( level.zombie_vars[ "zombify_player" ] ) || !level.zombie_vars[ "zombify_player" ] ) + { + self thread spawnspectator(); + return; + } + self.ignoreme = 1; + self.is_zombie = 1; + self.zombification_time = getTime(); + self.team = level.zombie_team; + self notify( "zombified" ); + if ( isDefined( self.revivetrigger ) ) + { + self.revivetrigger delete(); + } + self.revivetrigger = undefined; + self setmovespeedscale( 0.3 ); + self reviveplayer(); + self takeallweapons(); + self giveweapon( "zombie_melee", 0 ); + self switchtoweapon( "zombie_melee" ); + self disableweaponcycling(); + self disableoffhandweapons(); + setclientsysstate( "zombify", 1, self ); + self thread maps/mp/zombies/_zm_spawner::zombie_eye_glow(); + self thread playerzombie_player_damage(); + self thread playerzombie_soundboard(); +} + +playerzombie_player_damage() +{ + self endon( "death" ); + self endon( "disconnect" ); + self thread playerzombie_infinite_health(); + self.zombiehealth = level.zombie_health; + while ( 1 ) + { + self waittill( "damage", amount, attacker, directionvec, point, type ); + while ( !isDefined( attacker ) || !isplayer( attacker ) ) + { + wait 0.05; + } + self.zombiehealth -= amount; + if ( self.zombiehealth <= 0 ) + { + self thread playerzombie_downed_state(); + self waittill( "playerzombie_downed_state_done" ); + self.zombiehealth = level.zombie_health; + } + } +} + +playerzombie_downed_state() +{ + self endon( "death" ); + self endon( "disconnect" ); + downtime = 15; + starttime = getTime(); + endtime = starttime + ( downtime * 1000 ); + self thread playerzombie_downed_hud(); + self.playerzombie_soundboard_disable = 1; + self thread maps/mp/zombies/_zm_spawner::zombie_eye_glow_stop(); + self disableweapons(); + self allowstand( 0 ); + self allowcrouch( 0 ); + self allowprone( 1 ); + while ( getTime() < endtime ) + { + wait 0.05; + } + self.playerzombie_soundboard_disable = 0; + self thread maps/mp/zombies/_zm_spawner::zombie_eye_glow(); + self enableweapons(); + self allowstand( 1 ); + self allowcrouch( 0 ); + self allowprone( 0 ); + self notify( "playerzombie_downed_state_done" ); +} + +playerzombie_downed_hud() +{ + self endon( "death" ); + self endon( "disconnect" ); + text = newclienthudelem( self ); + text.alignx = "center"; + text.aligny = "middle"; + text.horzalign = "user_center"; + text.vertalign = "user_bottom"; + text.foreground = 1; + text.font = "default"; + text.fontscale = 1.8; + text.alpha = 0; + text.color = ( 0, 0, -1 ); + text settext( &"ZOMBIE_PLAYERZOMBIE_DOWNED" ); + text.y = -113; + if ( self issplitscreen() ) + { + text.y = -137; + } + text fadeovertime( 0.1 ); + text.alpha = 1; + self waittill( "playerzombie_downed_state_done" ); + text fadeovertime( 0.1 ); + text.alpha = 0; +} + +playerzombie_infinite_health() +{ + self endon( "death" ); + self endon( "disconnect" ); + bighealth = 100000; + while ( 1 ) + { + if ( self.health < bighealth ) + { + self.health = bighealth; + } + wait 0.1; + } +} + +playerzombie_soundboard() +{ + self endon( "death" ); + self endon( "disconnect" ); + self.playerzombie_soundboard_disable = 0; + self.buttonpressed_use = 0; + self.buttonpressed_attack = 0; + self.buttonpressed_ads = 0; + self.usesound_waittime = 3000; + self.usesound_nexttime = getTime(); + usesound = "playerzombie_usebutton_sound"; + self.attacksound_waittime = 3000; + self.attacksound_nexttime = getTime(); + attacksound = "playerzombie_attackbutton_sound"; + self.adssound_waittime = 3000; + self.adssound_nexttime = getTime(); + adssound = "playerzombie_adsbutton_sound"; + self.inputsound_nexttime = getTime(); + while ( 1 ) + { + while ( self.playerzombie_soundboard_disable ) + { + wait 0.05; + } + if ( self usebuttonpressed() ) + { + if ( self can_do_input( "use" ) ) + { + self thread playerzombie_play_sound( usesound ); + self thread playerzombie_waitfor_buttonrelease( "use" ); + self.usesound_nexttime = getTime() + self.usesound_waittime; + } + } + else if ( self attackbuttonpressed() ) + { + if ( self can_do_input( "attack" ) ) + { + self thread playerzombie_play_sound( attacksound ); + self thread playerzombie_waitfor_buttonrelease( "attack" ); + self.attacksound_nexttime = getTime() + self.attacksound_waittime; + } + } + else + { + if ( self adsbuttonpressed() ) + { + if ( self can_do_input( "ads" ) ) + { + self thread playerzombie_play_sound( adssound ); + self thread playerzombie_waitfor_buttonrelease( "ads" ); + self.adssound_nexttime = getTime() + self.adssound_waittime; + } + } + } + wait 0.05; + } +} + +can_do_input( inputtype ) +{ + if ( getTime() < self.inputsound_nexttime ) + { + return 0; + } + cando = 0; + switch( inputtype ) + { + case "use": + if ( getTime() >= self.usesound_nexttime && !self.buttonpressed_use ) + { + cando = 1; + } + break; + case "attack": + if ( getTime() >= self.attacksound_nexttime && !self.buttonpressed_attack ) + { + cando = 1; + } + break; + case "ads": + if ( getTime() >= self.usesound_nexttime && !self.buttonpressed_ads ) + { + cando = 1; + } + break; + default: + /* +/# + assertmsg( "can_do_input(): didn't recognize inputType of " + inputtype ); +#/ + */ + break; + } + return cando; +} + +playerzombie_play_sound( alias ) +{ + self play_sound_on_ent( alias ); +} + +playerzombie_waitfor_buttonrelease( inputtype ) +{ + if ( inputtype != "use" && inputtype != "attack" && inputtype != "ads" ) + { + /* +/# + assertmsg( "playerzombie_waitfor_buttonrelease(): inputType of " + inputtype + " is not recognized." ); +#/ + */ + return; + } + notifystring = "waitfor_buttonrelease_" + inputtype; + self notify( notifystring ); + self endon( notifystring ); + if ( inputtype == "use" ) + { + self.buttonpressed_use = 1; + while ( self usebuttonpressed() ) + { + wait 0.05; + } + self.buttonpressed_use = 0; + } + else if ( inputtype == "attack" ) + { + self.buttonpressed_attack = 1; + while ( self attackbuttonpressed() ) + { + wait 0.05; + } + self.buttonpressed_attack = 0; + } + else + { + if ( inputtype == "ads" ) + { + self.buttonpressed_ads = 1; + while ( self adsbuttonpressed() ) + { + wait 0.05; + } + self.buttonpressed_ads = 0; + } + } +} + +remove_ignore_attacker() +{ + self notify( "new_ignore_attacker" ); + self endon( "new_ignore_attacker" ); + self endon( "disconnect" ); + if ( !isDefined( level.ignore_enemy_timer ) ) + { + level.ignore_enemy_timer = 0.4; + } + wait level.ignore_enemy_timer; + self.ignoreattacker = undefined; +} + +player_shield_facing_attacker( vdir, limit ) +{ + orientation = self getplayerangles(); + forwardvec = anglesToForward( orientation ); + forwardvec2d = ( forwardvec[ 0 ], forwardvec[ 1 ], 0 ); + unitforwardvec2d = vectornormalize( forwardvec2d ); + tofaceevec = vdir * -1; + tofaceevec2d = ( tofaceevec[ 0 ], tofaceevec[ 1 ], 0 ); + unittofaceevec2d = vectornormalize( tofaceevec2d ); + dotproduct = vectordot( unitforwardvec2d, unittofaceevec2d ); + return dotproduct > limit; +} + +player_damage_override_cheat( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + player_damage_override( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + return 0; +} + +player_damage_override( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + if ( isDefined( level._game_module_player_damage_callback ) ) + { + self [[ level._game_module_player_damage_callback ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + } + idamage = self check_player_damage_callbacks( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + if ( isDefined( self.use_adjusted_grenade_damage ) && self.use_adjusted_grenade_damage ) + { + self.use_adjusted_grenade_damage = undefined; + if ( self.health > idamage ) + { + return idamage; + } + } + if ( !idamage ) + { + return 0; + } + if ( self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return 0; + } + if ( isDefined( einflictor ) ) + { + if ( isDefined( einflictor.water_damage ) && einflictor.water_damage ) + { + return 0; + } + } + if ( isDefined( eattacker ) && isDefined( eattacker.is_zombie ) || eattacker.is_zombie && isplayer( eattacker ) ) + { + if ( isDefined( self.hasriotshield ) && self.hasriotshield && isDefined( vdir ) ) + { + if ( isDefined( self.hasriotshieldequipped ) && self.hasriotshieldequipped ) + { + if ( self player_shield_facing_attacker( vdir, 0.2 ) && isDefined( self.player_shield_apply_damage ) ) + { + self [[ self.player_shield_apply_damage ]]( 100, 0 ); + return 0; + } + } + else + { + if ( !isDefined( self.riotshieldentity ) ) + { + if ( !self player_shield_facing_attacker( vdir, -0.2 ) && isDefined( self.player_shield_apply_damage ) ) + { + self [[ self.player_shield_apply_damage ]]( 100, 0 ); + return 0; + } + } + } + } + } + if ( isDefined( eattacker ) ) + { + if ( isDefined( self.ignoreattacker ) && self.ignoreattacker == eattacker ) + { + return 0; + } + if ( isDefined( self.is_zombie ) && self.is_zombie && isDefined( eattacker.is_zombie ) && eattacker.is_zombie ) + { + return 0; + } + if ( isDefined( eattacker.is_zombie ) && eattacker.is_zombie ) + { + self.ignoreattacker = eattacker; + self thread remove_ignore_attacker(); + if ( isDefined( eattacker.custom_damage_func ) ) + { + idamage = eattacker [[ eattacker.custom_damage_func ]]( self ); + } + else if ( isDefined( eattacker.meleedamage ) ) + { + idamage = eattacker.meleedamage; + } + else + { + idamage = 50; + } + } + eattacker notify( "hit_player" ); + if ( smeansofdeath != "MOD_FALLING" ) + { + self thread playswipesound( smeansofdeath, eattacker ); + if ( isDefined( eattacker.is_zombie ) || eattacker.is_zombie && isplayer( eattacker ) ) + { + self playrumbleonentity( "damage_heavy" ); + } + canexert = 1; + if ( isDefined( level.pers_upgrade_flopper ) && level.pers_upgrade_flopper ) + { + if ( isDefined( self.pers_upgrades_awarded[ "flopper" ] ) && self.pers_upgrades_awarded[ "flopper" ] ) + { + if ( smeansofdeath != "MOD_PROJECTILE_SPLASH" && smeansofdeath != "MOD_GRENADE" ) + { + canexert = smeansofdeath != "MOD_GRENADE_SPLASH"; + } + } + } + if ( isDefined( canexert ) && canexert ) + { + if ( randomintrange( 0, 1 ) == 0 ) + { + self thread maps/mp/zombies/_zm_audio::playerexert( "hitmed" ); + } + else + { + self thread maps/mp/zombies/_zm_audio::playerexert( "hitlrg" ); + } + } + } + } + finaldamage = idamage; + if ( !is_placeable_mine( sweapon ) || sweapon == "freezegun_zm" && sweapon == "freezegun_upgraded_zm" ) + { + return 0; + } + if ( isDefined( self.player_damage_override ) ) + { + self thread [[ self.player_damage_override ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + } + if ( smeansofdeath == "MOD_FALLING" ) + { + if ( self hasperk( "specialty_flakjacket" ) && isDefined( self.divetoprone ) && self.divetoprone == 1 ) + { + if ( isDefined( level.zombiemode_divetonuke_perk_func ) ) + { + [[ level.zombiemode_divetonuke_perk_func ]]( self, self.origin ); + } + return 0; + } + if ( isDefined( level.pers_upgrade_flopper ) && level.pers_upgrade_flopper ) + { + if ( self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_flopper_damage_check( smeansofdeath, idamage ) ) + { + return 0; + } + } + } + if ( smeansofdeath != "MOD_PROJECTILE" && smeansofdeath != "MOD_PROJECTILE_SPLASH" || smeansofdeath == "MOD_GRENADE" && smeansofdeath == "MOD_GRENADE_SPLASH" ) + { + if ( self hasperk( "specialty_flakjacket" ) ) + { + return 0; + } + if ( isDefined( level.pers_upgrade_flopper ) && level.pers_upgrade_flopper ) + { + if ( isDefined( self.pers_upgrades_awarded[ "flopper" ] ) && self.pers_upgrades_awarded[ "flopper" ] ) + { + return 0; + } + } + if ( self.health > 75 && isDefined( self.is_zombie ) && !self.is_zombie ) + { + return 75; + } + } + if ( idamage < self.health ) + { + if ( isDefined( eattacker ) ) + { + if ( isDefined( level.custom_kill_damaged_vo ) ) + { + eattacker thread [[ level.custom_kill_damaged_vo ]]( self ); + } + else + { + eattacker.sound_damage_player = self; + } + if ( isDefined( eattacker.has_legs ) && !eattacker.has_legs ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "crawl_hit" ); + } + else + { + if ( isDefined( eattacker.animname ) && eattacker.animname == "monkey_zombie" ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "monkey_hit" ); + } + } + } + return finaldamage; + } + if ( isDefined( eattacker ) ) + { + if ( isDefined( eattacker.animname ) && eattacker.animname == "zombie_dog" ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "killed_by_zdog" ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "killed_by_zdog" ); + } + else + { + if ( isDefined( eattacker.is_avogadro ) && eattacker.is_avogadro ) + { + self maps/mp/zombies/_zm_stats::increment_client_stat( "killed_by_avogadro", 0 ); + self maps/mp/zombies/_zm_stats::increment_player_stat( "killed_by_avogadro" ); + } + } + } + self thread clear_path_timers(); + if ( level.intermission ) + { + level waittill( "forever" ); + } + if ( level.scr_zm_ui_gametype == "zcleansed" && idamage > 0 ) + { + if ( isDefined( eattacker ) && isplayer( eattacker ) && eattacker.team != self.team && isDefined( self.laststand ) && !self.laststand || !self maps/mp/zombies/_zm_laststand::player_is_in_laststand() && !isDefined( self.last_player_attacker ) ) + { + if ( isDefined( eattacker.maxhealth ) && isDefined( eattacker.is_zombie ) && eattacker.is_zombie ) + { + eattacker.health = eattacker.maxhealth; + } + if ( isDefined( level.player_kills_player ) ) + { + self thread [[ level.player_kills_player ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + } + } + } + if ( self.lives > 0 && self hasperk( "specialty_finalstand" ) ) + { + self.lives--; + + if ( isDefined( level.chugabud_laststand_func ) ) + { + self thread [[ level.chugabud_laststand_func ]](); + return 0; + } + } + players = get_players(); + count = 0; + i = 0; + while ( i < players.size ) + { + if ( self != players[ i ] && !players[ i ].is_zombie || players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate == "spectator" ) + { + count++; + } + i++; + } + if ( count < players.size || isDefined( level._game_module_game_end_check ) && !( [[ level._game_module_game_end_check ]]() ) ) + { + if ( isDefined( self.lives ) && self.lives > 0 && isDefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive && self hasperk( "specialty_quickrevive" ) ) + { + self thread wait_and_revive(); + } + return finaldamage; + } + if ( players.size == 1 && flag( "solo_game" ) ) + { + if ( self.lives == 0 || !self hasperk( "specialty_quickrevive" ) ) + { + self.intermission = 1; + } + } + if ( players.size == 1 && flag( "solo_game" ) ) + { + if ( self.lives != 0 ) + { + solo_death = !self hasperk( "specialty_quickrevive" ); + } + } + if ( count > 1 ) + { + if ( players.size == 1 ) + { + non_solo_death = !flag( "solo_game" ); + } + } + if ( !solo_death && non_solo_death && isDefined( level.no_end_game_check ) && !level.no_end_game_check ) + { + level notify( "stop_suicide_trigger" ); + self thread maps/mp/zombies/_zm_laststand::playerlaststand( einflictor, eattacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime ); + if ( !isDefined( vdir ) ) + { + vdir = ( 0, 0, -1 ); + } + self fakedamagefrom( vdir ); + if ( isDefined( level.custom_player_fake_death ) ) + { + self thread [[ level.custom_player_fake_death ]]( vdir, smeansofdeath ); + } + else + { + self thread player_fake_death(); + } + } + if ( count == players.size && isDefined( level.no_end_game_check ) && !level.no_end_game_check ) + { + if ( players.size == 1 && flag( "solo_game" ) ) + { + if ( self.lives == 0 || !self hasperk( "specialty_quickrevive" ) ) + { + self.lives = 0; + level notify( "pre_end_game" ); + wait_network_frame(); + if ( flag( "dog_round" ) ) + { + increment_dog_round_stat( "lost" ); + } + level notify( "end_game" ); + } + else + { + return finaldamage; + } + } + else + { + level notify( "pre_end_game" ); + wait_network_frame(); + if ( flag( "dog_round" ) ) + { + increment_dog_round_stat( "lost" ); + } + level notify( "end_game" ); + } + return 0; + } + else + { + surface = "flesh"; + return finaldamage; + } +} + +clear_path_timers() +{ + zombies = getaiarray( level.zombie_team ); + _a5596 = zombies; + _k5596 = getFirstArrayKey( _a5596 ); + while ( isDefined( _k5596 ) ) + { + zombie = _a5596[ _k5596 ]; + if ( isDefined( zombie.favoriteenemy ) && zombie.favoriteenemy == self ) + { + zombie.zombie_path_timer = 0; + } + _k5596 = getNextArrayKey( _a5596, _k5596 ); + } +} + +check_player_damage_callbacks( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + if ( !isDefined( level.player_damage_callbacks ) ) + { + return idamage; + } + i = 0; + while ( i < level.player_damage_callbacks.size ) + { + newdamage = self [[ level.player_damage_callbacks[ i ] ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + if ( newdamage != -1 ) + { + return newdamage; + } + i++; + } + return idamage; +} + +register_player_damage_callback( func ) +{ + if ( !isDefined( level.player_damage_callbacks ) ) + { + level.player_damage_callbacks = []; + } + level.player_damage_callbacks[ level.player_damage_callbacks.size ] = func; +} + +wait_and_revive() +{ + flag_set( "wait_and_revive" ); + if ( isDefined( self.waiting_to_revive ) && self.waiting_to_revive == 1 ) + { + return; + } + if ( isDefined( self.pers_upgrades_awarded[ "perk_lose" ] ) && self.pers_upgrades_awarded[ "perk_lose" ] ) + { + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_perk_lose_save(); + } + self.waiting_to_revive = 1; + if ( isDefined( level.exit_level_func ) ) + { + self thread [[ level.exit_level_func ]](); + } + else + { + if ( get_players().size == 1 ) + { + self thread default_exit_level(); + } + } + solo_revive_time = 10; + self.revive_hud settext( &"ZOMBIE_REVIVING_SOLO", self ); + self maps/mp/zombies/_zm_laststand::revive_hud_show_n_fade( solo_revive_time ); + flag_wait_or_timeout( "instant_revive", solo_revive_time ); + if ( flag( "instant_revive" ) ) + { + self maps/mp/zombies/_zm_laststand::revive_hud_show_n_fade( 1 ); + } + flag_clear( "wait_and_revive" ); + self maps/mp/zombies/_zm_laststand::auto_revive( self ); + self.lives--; + + self.waiting_to_revive = 0; + if ( isDefined( self.pers_upgrades_awarded[ "perk_lose" ] ) && self.pers_upgrades_awarded[ "perk_lose" ] ) + { + self thread maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_perk_lose_restore(); + } +} + +actor_damage_override( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + if ( !isDefined( self ) || !isDefined( attacker ) ) + { + return damage; + } + if ( weapon == "tazer_knuckles_zm" || weapon == "jetgun_zm" ) + { + self.knuckles_extinguish_flames = 1; + } + else + { + if ( weapon != "none" ) + { + self.knuckles_extinguish_flames = undefined; + } + } + if ( isDefined( attacker.animname ) && attacker.animname == "quad_zombie" ) + { + if ( isDefined( self.animname ) && self.animname == "quad_zombie" ) + { + return 0; + } + } + if ( !isplayer( attacker ) && isDefined( self.non_attacker_func ) ) + { + if ( isDefined( self.non_attack_func_takes_attacker ) && self.non_attack_func_takes_attacker ) + { + return self [[ self.non_attacker_func ]]( damage, weapon, attacker ); + } + else + { + return self [[ self.non_attacker_func ]]( damage, weapon ); + } + } + if ( !isplayer( attacker ) && !isplayer( self ) ) + { + return damage; + } + if ( !isDefined( damage ) || !isDefined( meansofdeath ) ) + { + return damage; + } + if ( meansofdeath == "" ) + { + return damage; + } + old_damage = damage; + final_damage = damage; + if ( isDefined( self.actor_damage_func ) ) + { + final_damage = [[ self.actor_damage_func ]]( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); + } + /* +/# + if ( getDvarInt( #"5ABA6445" ) ) + { + println( "Perk/> Damage Factor: " + ( final_damage / old_damage ) + " - Pre Damage: " + old_damage + " - Post Damage: " + final_damage ); +#/ + } + */ + if ( attacker.classname == "script_vehicle" && isDefined( attacker.owner ) ) + { + attacker = attacker.owner; + } + if ( isDefined( self.in_water ) && self.in_water ) + { + if ( int( final_damage ) >= self.health ) + { + self.water_damage = 1; + } + } + attacker thread maps/mp/gametypes_zm/_weapons::checkhit( weapon ); + if ( attacker maps/mp/zombies/_zm_pers_upgrades_functions::pers_mulit_kill_headshot_active() && is_headshot( weapon, shitloc, meansofdeath ) ) + { + final_damage *= 2; + } + if ( isDefined( level.headshots_only ) && level.headshots_only && isDefined( attacker ) && isplayer( attacker ) ) + { + if ( meansofdeath == "MOD_MELEE" || shitloc == "head" && shitloc == "helmet" ) + { + return int( final_damage ); + } + if ( is_explosive_damage( meansofdeath ) ) + { + return int( final_damage ); + } + else + { + if ( !is_headshot( weapon, shitloc, meansofdeath ) ) + { + return 0; + } + } + } + return int( final_damage ); +} + +actor_damage_override_wrapper( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ) +{ + damage_override = self actor_damage_override( inflictor, attacker, damage, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); + if ( damage_override < self.health || isDefined( self.dont_die_on_me ) && !self.dont_die_on_me ) + { + self finishactordamage( inflictor, attacker, damage_override, flags, meansofdeath, weapon, vpoint, vdir, shitloc, psoffsettime, boneindex ); + } +} + +actor_killed_override( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime ) +{ + if ( game[ "state" ] == "postgame" ) + { + return; + } + if ( isai( attacker ) && isDefined( attacker.script_owner ) ) + { + if ( attacker.script_owner.team != self.aiteam ) + { + attacker = attacker.script_owner; + } + } + if ( attacker.classname == "script_vehicle" && isDefined( attacker.owner ) ) + { + attacker = attacker.owner; + } + if ( isDefined( attacker ) && isplayer( attacker ) ) + { + multiplier = 1; + if ( is_headshot( sweapon, shitloc, smeansofdeath ) ) + { + multiplier = 1.5; + } + type = undefined; + if ( isDefined( self.animname ) ) + { + switch( self.animname ) + { + case "quad_zombie": + type = "quadkill"; + break; + case "ape_zombie": + type = "apekill"; + break; + case "zombie": + type = "zombiekill"; + break; + case "zombie_dog": + type = "dogkill"; + break; + } + } + } + if ( isDefined( self.is_ziplining ) && self.is_ziplining ) + { + self.deathanim = undefined; + } + if ( isDefined( self.actor_killed_override ) ) + { + self [[ self.actor_killed_override ]]( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime ); + } +} + +round_end_monitor() +{ + while ( 1 ) + { + level waittill( "end_of_round" ); + maps/mp/_demo::bookmark( "zm_round_end", getTime(), undefined, undefined, 1 ); + bbpostdemostreamstatsforround( level.round_number ); + wait 0.05; + } +} + +end_game() +{ + level waittill( "end_game" ); + check_end_game_intermission_delay(); + /* +/# + println( "end_game TRIGGERED " ); +#/ + */ + clientnotify( "zesn" ); + if ( isDefined( level.sndgameovermusicoverride ) ) + { + level thread maps/mp/zombies/_zm_audio::change_zombie_music( level.sndgameovermusicoverride ); + } + else + { + level thread maps/mp/zombies/_zm_audio::change_zombie_music( "game_over" ); + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + setclientsysstate( "lsm", "0", players[ i ] ); + i++; + } + i = 0; + while ( i < players.size ) + { + if ( players[ i ] player_is_in_laststand() ) + { + players[ i ] recordplayerdeathzombies(); + players[ i ] maps/mp/zombies/_zm_stats::increment_player_stat( "deaths" ); + players[ i ] maps/mp/zombies/_zm_stats::increment_client_stat( "deaths" ); + players[ i ] maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_jugg_player_death_stat(); + } + if ( isDefined( players[ i ].revivetexthud ) ) + { + players[ i ].revivetexthud destroy(); + } + i++; + } + stopallrumbles(); + level.intermission = 1; + level.zombie_vars[ "zombie_powerup_insta_kill_time" ] = 0; + level.zombie_vars[ "zombie_powerup_fire_sale_time" ] = 0; + level.zombie_vars[ "zombie_powerup_point_doubler_time" ] = 0; + wait 0.1; + game_over = []; + survived = []; + players = get_players(); + setmatchflag( "disableIngameMenu", 1 ); + _a5934 = players; + _k5934 = getFirstArrayKey( _a5934 ); + while ( isDefined( _k5934 ) ) + { + player = _a5934[ _k5934 ]; + player closemenu(); + player closeingamemenu(); + _k5934 = getNextArrayKey( _a5934, _k5934 ); + } + while ( !isDefined( level._supress_survived_screen ) ) + { + i = 0; + while ( i < players.size ) + { + if ( isDefined( level.custom_game_over_hud_elem ) ) + { + game_over[ i ] = [[ level.custom_game_over_hud_elem ]]( players[ i ] ); + } + else + { + game_over[ i ] = newclienthudelem( players[ i ] ); + game_over[ i ].alignx = "center"; + game_over[ i ].aligny = "middle"; + game_over[ i ].horzalign = "center"; + game_over[ i ].vertalign = "middle"; + game_over[ i ].y -= 130; + game_over[ i ].foreground = 1; + game_over[ i ].fontscale = 3; + game_over[ i ].alpha = 0; + game_over[ i ].color = ( 0, 0, -1 ); + game_over[ i ].hidewheninmenu = 1; + game_over[ i ] settext( &"ZOMBIE_GAME_OVER" ); + game_over[ i ] fadeovertime( 1 ); + game_over[ i ].alpha = 1; + if ( players[ i ] issplitscreen() ) + { + game_over[ i ].fontscale = 2; + game_over[ i ].y += 40; + } + } + survived[ i ] = newclienthudelem( players[ i ] ); + survived[ i ].alignx = "center"; + survived[ i ].aligny = "middle"; + survived[ i ].horzalign = "center"; + survived[ i ].vertalign = "middle"; + survived[ i ].y -= 100; + survived[ i ].foreground = 1; + survived[ i ].fontscale = 2; + survived[ i ].alpha = 0; + survived[ i ].color = ( 0, 0, -1 ); + survived[ i ].hidewheninmenu = 1; + if ( players[ i ] issplitscreen() ) + { + survived[ i ].fontscale = 1.5; + survived[ i ].y += 40; + } + if ( level.round_number < 2 ) + { + if ( level.script == "zombie_moon" ) + { + if ( !isDefined( level.left_nomans_land ) ) + { + nomanslandtime = level.nml_best_time; + player_survival_time = int( nomanslandtime / 1000 ); + player_survival_time_in_mins = maps/mp/zombies/_zm::to_mins( player_survival_time ); + survived[ i ] settext( &"ZOMBIE_SURVIVED_NOMANS", player_survival_time_in_mins ); + } + else + { + if ( level.left_nomans_land == 2 ) + { + survived[ i ] settext( &"ZOMBIE_SURVIVED_ROUND" ); + } + } + } + else + { + survived[ i ] settext( &"ZOMBIE_SURVIVED_ROUND" ); + } + } + else + { + survived[ i ] settext( &"ZOMBIE_SURVIVED_ROUNDS", level.round_number ); + } + survived[ i ] fadeovertime( 1 ); + survived[ i ].alpha = 1; + i++; + } + } + if ( isDefined( level.custom_end_screen ) ) + { + level [[ level.custom_end_screen ]](); + } + i = 0; + while ( i < players.size ) + { + players[ i ] setclientammocounterhide( 1 ); + players[ i ] setclientminiscoreboardhide( 1 ); + i++; + } + uploadstats(); + maps/mp/zombies/_zm_stats::update_players_stats_at_match_end( players ); + maps/mp/zombies/_zm_stats::update_global_counters_on_match_end(); + wait 1; + wait 3.95; + players = get_players(); + _a6045 = players; + _k6045 = getFirstArrayKey( _a6045 ); + while ( isDefined( _k6045 ) ) + { + player = _a6045[ _k6045 ]; + if ( isDefined( player.sessionstate ) && player.sessionstate == "spectator" ) + { + player.sessionstate = "playing"; + } + _k6045 = getNextArrayKey( _a6045, _k6045 ); + } + wait 0.05; + players = get_players(); + if ( !isDefined( level._supress_survived_screen ) ) + { + i = 0; + while ( i < players.size ) + { + survived[ i ] destroy(); + game_over[ i ] destroy(); + i++; + } + } + else i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ].survived_hud ) ) + { + players[ i ].survived_hud destroy(); + } + if ( isDefined( players[ i ].game_over_hud ) ) + { + players[ i ].game_over_hud destroy(); + } + i++; + } + intermission(); + wait level.zombie_vars[ "zombie_intermission_time" ]; + level notify( "stop_intermission" ); + array_thread( get_players(), ::player_exit_level ); + bbprint( "zombie_epilogs", "rounds %d", level.round_number ); + wait 1.5; + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] cameraactivate( 0 ); + i++; + } + exitlevel( 0 ); + wait 666; +} + +disable_end_game_intermission( delay ) +{ + level.disable_intermission = 1; + wait delay; + level.disable_intermission = undefined; +} + +check_end_game_intermission_delay() +{ + while ( isDefined( level.disable_intermission ) ) + { + while ( 1 ) + { + if ( !isDefined( level.disable_intermission ) ) + { + return; + } + else + { + wait 0.01; + } + } + } +} + +upload_leaderboards() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] uploadleaderboards(); + i++; + } +} + +initializestattracking() +{ + level.global_zombies_killed = 0; + level.zombies_timeout_spawn = 0; + level.zombies_timeout_playspace = 0; + level.zombies_timeout_undamaged = 0; + level.zombie_player_killed_count = 0; + level.zombie_trap_killed_count = 0; + level.zombie_pathing_failed = 0; + level.zombie_breadcrumb_failed = 0; +} + +uploadglobalstatcounters() +{ + incrementcounter( "global_zombies_killed", level.global_zombies_killed ); + incrementcounter( "global_zombies_killed_by_players", level.zombie_player_killed_count ); + incrementcounter( "global_zombies_killed_by_traps", level.zombie_trap_killed_count ); +} + +player_fake_death() +{ + level notify( "fake_death" ); + self notify( "fake_death" ); + self takeallweapons(); + self allowstand( 0 ); + self allowcrouch( 0 ); + self allowprone( 1 ); + self.ignoreme = 1; + self enableinvulnerability(); + wait 1; + self freezecontrols( 1 ); +} + +player_exit_level() +{ + self allowstand( 1 ); + self allowcrouch( 0 ); + self allowprone( 0 ); + if ( isDefined( self.game_over_bg ) ) + { + self.game_over_bg.foreground = 1; + self.game_over_bg.sort = 100; + self.game_over_bg fadeovertime( 1 ); + self.game_over_bg.alpha = 1; + } +} + +player_killed_override( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ + level waittill( "forever" ); +} + +player_zombie_breadcrumb() +{ + self notify( "stop_player_zombie_breadcrumb" ); + self endon( "stop_player_zombie_breadcrumb" ); + self endon( "disconnect" ); + self endon( "spawned_spectator" ); + level endon( "intermission" ); + self.zombie_breadcrumbs = []; + self.zombie_breadcrumb_distance = 576; + self.zombie_breadcrumb_area_num = 3; + self.zombie_breadcrumb_area_distance = 16; + self store_crumb( self.origin ); + last_crumb = self.origin; + self thread debug_breadcrumbs(); + while ( 1 ) + { + wait_time = 0.1; + while ( self.ignoreme ) + { + wait wait_time; + } + store_crumb = 1; + airborne = 0; + crumb = self.origin; + if ( !self isonground() && self isinvehicle() ) + { + trace = bullettrace( self.origin + vectorScale( ( 0, 0, -1 ), 10 ), self.origin, 0, undefined ); + crumb = trace[ "position" ]; + } + if ( !airborne && distancesquared( crumb, last_crumb ) < self.zombie_breadcrumb_distance ) + { + store_crumb = 0; + } + if ( airborne && self isonground() ) + { + store_crumb = 1; + airborne = 0; + } + if ( isDefined( level.custom_breadcrumb_store_func ) ) + { + store_crumb = self [[ level.custom_breadcrumb_store_func ]]( store_crumb ); + } + if ( isDefined( level.custom_airborne_func ) ) + { + airborne = self [[ level.custom_airborne_func ]]( airborne ); + } + if ( store_crumb ) + { + debug_print( "Player is storing breadcrumb " + crumb ); + if ( isDefined( self.node ) ) + { + debug_print( "has closest node " ); + } + last_crumb = crumb; + self store_crumb( crumb ); + } + wait wait_time; + } +} + +store_crumb( origin ) +{ + offsets = []; + height_offset = 32; + index = 0; + j = 1; + while ( j <= self.zombie_breadcrumb_area_num ) + { + offset = j * self.zombie_breadcrumb_area_distance; + offsets[ 0 ] = ( origin[ 0 ] - offset, origin[ 1 ], origin[ 2 ] ); + offsets[ 1 ] = ( origin[ 0 ] + offset, origin[ 1 ], origin[ 2 ] ); + offsets[ 2 ] = ( origin[ 0 ], origin[ 1 ] - offset, origin[ 2 ] ); + offsets[ 3 ] = ( origin[ 0 ], origin[ 1 ] + offset, origin[ 2 ] ); + offsets[ 4 ] = ( origin[ 0 ] - offset, origin[ 1 ], origin[ 2 ] + height_offset ); + offsets[ 5 ] = ( origin[ 0 ] + offset, origin[ 1 ], origin[ 2 ] + height_offset ); + offsets[ 6 ] = ( origin[ 0 ], origin[ 1 ] - offset, origin[ 2 ] + height_offset ); + offsets[ 7 ] = ( origin[ 0 ], origin[ 1 ] + offset, origin[ 2 ] + height_offset ); + i = 0; + while ( i < offsets.size ) + { + self.zombie_breadcrumbs[ index ] = offsets[ i ]; + index++; + i++; + } + j++; + } +} + +to_mins( seconds ) +{ + hours = 0; + minutes = 0; + if ( seconds > 59 ) + { + minutes = int( seconds / 60 ); + seconds = int( seconds * 1000 ) % 60000; + seconds *= 0.001; + if ( minutes > 59 ) + { + hours = int( minutes / 60 ); + minutes = int( minutes * 1000 ) % 60000; + minutes *= 0.001; + } + } + if ( hours < 10 ) + { + hours = "0" + hours; + } + if ( minutes < 10 ) + { + minutes = "0" + minutes; + } + seconds = int( seconds ); + if ( seconds < 10 ) + { + seconds = "0" + seconds; + } + combined = "" + hours + ":" + minutes + ":" + seconds; + return combined; +} + +intermission() +{ + level.intermission = 1; + level notify( "intermission" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + setclientsysstate( "levelNotify", "zi", players[ i ] ); + players[ i ] setclientthirdperson( 0 ); + players[ i ] resetfov(); + players[ i ].health = 100; + players[ i ] thread [[ level.custom_intermission ]](); + players[ i ] stopsounds(); + i++; + } + wait 0.25; + players = get_players(); + i = 0; + while ( i < players.size ) + { + setclientsysstate( "lsm", "0", players[ i ] ); + i++; + } + level thread zombie_game_over_death(); +} + +zombie_game_over_death() +{ + zombies = getaiarray( level.zombie_team ); + i = 0; + while ( i < zombies.size ) + { + if ( !isalive( zombies[ i ] ) ) + { + i++; + continue; + } + else + { + zombies[ i ] setgoalpos( zombies[ i ].origin ); + } + i++; + } + i = 0; + while ( i < zombies.size ) + { + if ( !isalive( zombies[ i ] ) ) + { + i++; + continue; + } + else if ( isDefined( zombies[ i ].ignore_game_over_death ) && zombies[ i ].ignore_game_over_death ) + { + i++; + continue; + } + else + { + wait ( 0.5 + randomfloat( 2 ) ); + if ( isDefined( zombies[ i ] ) ) + { + zombies[ i ] maps/mp/zombies/_zm_spawner::zombie_head_gib(); + zombies[ i ] dodamage( zombies[ i ].health + 666, zombies[ i ].origin ); + } + } + i++; + } +} + +player_intermission() +{ + self closemenu(); + self closeingamemenu(); + level endon( "stop_intermission" ); + self endon( "disconnect" ); + self endon( "death" ); + self notify( "_zombie_game_over" ); + self.score = self.score_total; + self.sessionstate = "intermission"; + self.spectatorclient = -1; + self.killcamentity = -1; + self.archivetime = 0; + self.psoffsettime = 0; + self.friendlydamage = undefined; + points = getstructarray( "intermission", "targetname" ); + if ( !isDefined( points ) || points.size == 0 ) + { + points = getentarray( "info_intermission", "classname" ); + if ( points.size < 1 ) + { + /* +/# + println( "NO info_intermission POINTS IN MAP" ); +#/ + */ + return; + } + } + self.game_over_bg = newclienthudelem( self ); + self.game_over_bg.horzalign = "fullscreen"; + self.game_over_bg.vertalign = "fullscreen"; + self.game_over_bg setshader( "black", 640, 480 ); + self.game_over_bg.alpha = 1; + org = undefined; + while ( 1 ) + { + points = array_randomize( points ); + i = 0; + while ( i < points.size ) + { + point = points[ i ]; + if ( !isDefined( org ) ) + { + self spawn( point.origin, point.angles ); + } + if ( isDefined( points[ i ].target ) ) + { + if ( !isDefined( org ) ) + { + org = spawn( "script_model", self.origin + vectorScale( ( 0, 0, -1 ), 60 ) ); + org setmodel( "tag_origin" ); + } + org.origin = points[ i ].origin; + org.angles = points[ i ].angles; + j = 0; + while ( j < get_players().size ) + { + player = get_players()[ j ]; + player camerasetposition( org ); + player camerasetlookat(); + player cameraactivate( 1 ); + j++; + } + speed = 20; + if ( isDefined( points[ i ].speed ) ) + { + speed = points[ i ].speed; + } + target_point = getstruct( points[ i ].target, "targetname" ); + dist = distance( points[ i ].origin, target_point.origin ); + time = dist / speed; + q_time = time * 0.25; + if ( q_time > 1 ) + { + q_time = 1; + } + self.game_over_bg fadeovertime( q_time ); + self.game_over_bg.alpha = 0; + org moveto( target_point.origin, time, q_time, q_time ); + org rotateto( target_point.angles, time, q_time, q_time ); + wait ( time - q_time ); + self.game_over_bg fadeovertime( q_time ); + self.game_over_bg.alpha = 1; + wait q_time; + i++; + continue; + } + else + { + self.game_over_bg fadeovertime( 1 ); + self.game_over_bg.alpha = 0; + wait 5; + self.game_over_bg thread fade_up_over_time( 1 ); + } + i++; + } + } +} + +fade_up_over_time( t ) +{ + self fadeovertime( t ); + self.alpha = 1; +} + +default_exit_level() +{ + zombies = getaiarray( level.zombie_team ); + i = 0; + while ( i < zombies.size ) + { + if ( isDefined( zombies[ i ].ignore_solo_last_stand ) && zombies[ i ].ignore_solo_last_stand ) + { + i++; + continue; + } + else + { + if ( isDefined( zombies[ i ].find_exit_point ) ) + { + zombies[ i ] thread [[ zombies[ i ].find_exit_point ]](); + i++; + continue; + } + else if ( zombies[ i ].ignoreme ) + { + zombies[ i ] thread default_delayed_exit(); + i++; + continue; + } + else + { + zombies[ i ] thread default_find_exit_point(); + } + } + i++; + } +} + +default_delayed_exit() +{ + self endon( "death" ); + while ( 1 ) + { + if ( !flag( "wait_and_revive" ) ) + { + return; + } + if ( !self.ignoreme ) + { + break; + } + else + { + wait 0.1; + } + } + self thread default_find_exit_point(); +} + +default_find_exit_point() +{ + self endon( "death" ); + player = get_players()[ 0 ]; + dist_zombie = 0; + dist_player = 0; + dest = 0; + away = vectornormalize( self.origin - player.origin ); + endpos = self.origin + vectorScale( away, 600 ); + locs = array_randomize( level.enemy_dog_locations ); + i = 0; + while ( i < locs.size ) + { + dist_zombie = distancesquared( locs[ i ].origin, endpos ); + dist_player = distancesquared( locs[ i ].origin, player.origin ); + if ( dist_zombie < dist_player ) + { + dest = i; + break; + } + else + { + i++; + } + } + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + if ( isDefined( locs[ dest ] ) ) + { + self setgoalpos( locs[ dest ].origin ); + } + while ( 1 ) + { + b_passed_override = 1; + if ( isDefined( level.default_find_exit_position_override ) ) + { + b_passed_override = [[ level.default_find_exit_position_override ]](); + } + if ( !flag( "wait_and_revive" ) && b_passed_override ) + { + break; + } + else + { + wait 0.1; + } + } + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); +} + +play_level_start_vox_delayed() +{ + wait 3; + players = get_players(); + num = randomintrange( 0, players.size ); + players[ num ] maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "intro" ); +} + +register_sidequest( id, sidequest_stat ) +{ + if ( !isDefined( level.zombie_sidequest_stat ) ) + { + level.zombie_sidequest_previously_completed = []; + level.zombie_sidequest_stat = []; + } + level.zombie_sidequest_stat[ id ] = sidequest_stat; + flag_wait( "start_zombie_round_logic" ); + level.zombie_sidequest_previously_completed[ id ] = 0; + if ( level.systemlink || getDvarInt( "splitscreen_playerCount" ) == get_players().size ) + { + return; + } + if ( isDefined( level.zm_disable_recording_stats ) && level.zm_disable_recording_stats ) + { + return; + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] maps/mp/zombies/_zm_stats::get_global_stat( level.zombie_sidequest_stat[ id ] ) ) + { + level.zombie_sidequest_previously_completed[ id ] = 1; + return; + } + i++; + } +} + +is_sidequest_previously_completed( id ) +{ + if ( isDefined( level.zombie_sidequest_previously_completed[ id ] ) ) + { + return level.zombie_sidequest_previously_completed[ id ]; + } +} + +set_sidequest_completed( id ) +{ + level notify( "zombie_sidequest_completed" ); + level.zombie_sidequest_previously_completed[ id ] = 1; + if ( level.systemlink ) + { + return; + } + if ( getDvarInt( "splitscreen_playerCount" ) == get_players().size ) + { + return; + } + if ( isDefined( level.zm_disable_recording_stats ) && level.zm_disable_recording_stats ) + { + return; + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( isDefined( level.zombie_sidequest_stat[ id ] ) ) + { + players[ i ] maps/mp/zombies/_zm_stats::add_global_stat( level.zombie_sidequest_stat[ id ], 1 ); + } + i++; + } +} + +playswipesound( mod, attacker ) +{ + if ( isDefined( attacker.is_zombie ) && attacker.is_zombie ) + { + self playsoundtoplayer( "evt_player_swiped", self ); + return; + } +} + +precache_zombie_leaderboards() +{ + if ( sessionmodeissystemlink() ) + { + return; + } + globalleaderboards = "LB_ZM_GB_BULLETS_FIRED_AT "; + globalleaderboards += "LB_ZM_GB_BULLETS_HIT_AT "; + globalleaderboards += "LB_ZM_GB_DEATHS_AT "; + globalleaderboards += "LB_ZM_GB_DISTANCE_TRAVELED_AT "; + globalleaderboards += "LB_ZM_GB_DOORS_PURCHASED_AT "; + globalleaderboards += "LB_ZM_GB_DOWNS_AT "; + globalleaderboards += "LB_ZM_GB_GIBS_AT "; + globalleaderboards += "LB_ZM_GB_GRENADE_KILLS_AT "; + globalleaderboards += "LB_ZM_GB_HEADSHOTS_AT "; + globalleaderboards += "LB_ZM_GB_KILLS_AT "; + globalleaderboards += "LB_ZM_GB_PERKS_DRANK_AT "; + globalleaderboards += "LB_ZM_GB_REVIVES_AT "; + if ( sessionmodeisprivateonlinegame() ) + { + precacheleaderboards( globalleaderboards ); + return; + } + maplocationname = level.scr_zm_map_start_location; + if ( maplocationname != "default" && maplocationname == "" && isDefined( level.default_start_location ) ) + { + maplocationname = level.default_start_location; + } + if ( level.scr_zm_ui_gametype_group != "zclassic" && level.scr_zm_ui_gametype_group == "zsurvival" && level.scr_zm_ui_gametype != "zcleansed" ) + { + expectedplayernum = getnumexpectedplayers(); + if ( expectedplayernum == 1 ) + { + gamemodeleaderboard = "LB_ZM_GM_" + level.scr_zm_ui_gametype + "_" + maplocationname + "_" + expectedplayernum + "PLAYER"; + } + else + { + gamemodeleaderboard = "LB_ZM_GM_" + level.scr_zm_ui_gametype + "_" + maplocationname + "_" + expectedplayernum + "PLAYERS"; + } + } + else + { + gamemodeleaderboard = "LB_ZM_GM_" + level.scr_zm_ui_gametype + "_" + maplocationname; + } + precacheleaderboards( globalleaderboards + gamemodeleaderboard ); +} + +zm_on_player_connect() +{ + if ( level.passed_introscreen ) + { + self setclientuivisibilityflag( "hud_visible", 1 ); + } + thread refresh_player_navcard_hud(); + self thread watchdisconnect(); +} + +zm_on_player_disconnect() +{ + thread refresh_player_navcard_hud(); +} + +watchdisconnect() +{ + self notify( "watchDisconnect" ); + self endon( "watchDisconnect" ); + self waittill( "disconnect" ); + zm_on_player_disconnect(); +} + +increment_dog_round_stat( stat ) +{ + players = get_players(); + _a6853 = players; + _k6853 = getFirstArrayKey( _a6853 ); + while ( isDefined( _k6853 ) ) + { + player = _a6853[ _k6853 ]; + player maps/mp/zombies/_zm_stats::increment_client_stat( "zdog_rounds_" + stat ); + _k6853 = getNextArrayKey( _a6853, _k6853 ); + } +} + +setup_player_navcard_hud() +{ + flag_wait( "start_zombie_round_logic" ); + thread refresh_player_navcard_hud(); +} + +refresh_player_navcard_hud() +{ + if ( !isDefined( level.navcards ) ) + { + return; + } + players = get_players(); + _a6871 = players; + _k6871 = getFirstArrayKey( _a6871 ); + while ( isDefined( _k6871 ) ) + { + player = _a6871[ _k6871 ]; + navcard_bits = 0; + i = 0; + while ( i < level.navcards.size ) + { + hasit = player maps/mp/zombies/_zm_stats::get_global_stat( level.navcards[ i ] ); + if ( isDefined( player.navcard_grabbed ) && player.navcard_grabbed == level.navcards[ i ] ) + { + hasit = 1; + } + if ( hasit ) + { + //navcard_bits +=( 1 << i ); + } + i++; + } + wait_network_frame(); + player setclientfield( "navcard_held", 0 ); + if ( navcard_bits > 0 ) + { + wait_network_frame(); + player setclientfield( "navcard_held", navcard_bits ); + } + _k6871 = getNextArrayKey( _a6871, _k6871 ); + } +} + + +check_quickrevive_for_hotjoin( disconnecting_player ) +{ + solo_mode = 0; + subtract_num = 0; + should_update = 0; + if ( isDefined( disconnecting_player ) ) + { + subtract_num = 1; + } + players = get_players(); + if ( ( players.size - subtract_num ) == 1 || isDefined( level.force_solo_quick_revive ) && level.force_solo_quick_revive ) + { + solo_mode = 1; + if ( !flag( "solo_game" ) ) + { + should_update = 1; + } + flag_set( "solo_game" ); + } + else + { + if ( flag( "solo_game" ) ) + { + should_update = 1; + } + flag_clear( "solo_game" ); + } + level.using_solo_revive = solo_mode; + level.revive_machine_is_solo = solo_mode; + set_default_laststand_pistol( solo_mode ); + if ( should_update && isDefined( level.quick_revive_machine ) ) + { + update_quick_revive( solo_mode ); + } +} + +set_default_laststand_pistol( solo_mode ) +{ + if ( !solo_mode ) + { + level.laststandpistol = level.default_laststandpistol; + } + else + { + level.laststandpistol = level.default_solo_laststandpistol; + } +} + +update_quick_revive( solo_mode ) +{ + if ( !isDefined( solo_mode ) ) + { + solo_mode = 0; + } + clip = undefined; + if ( isDefined( level.quick_revive_machine_clip ) ) + { + clip = level.quick_revive_machine_clip; + } + level.quick_revive_machine thread maps/mp/zombies/_zm_perks::reenable_quickrevive( clip, solo_mode ); +} + + +player_too_many_players_check() +{ + max_players = 4; + if ( level.scr_zm_ui_gametype == "zgrief" || level.scr_zm_ui_gametype == "zmeat" ) + { + max_players = 8; + } + if ( get_players().size > max_players ) + { + maps/mp/zombies/_zm_game_module::freeze_players( 1 ); + level notify( "end_game" ); + } +} + + + + diff --git a/patch_zm/maps/mp/zombies/_zm_gump.gsc b/patch_zm/maps/mp/zombies/_zm_gump.gsc new file mode 100644 index 0000000..5aaa735 --- /dev/null +++ b/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/patch_zm/maps/mp/zombies/_zm_magicbox.gsc b/patch_zm/maps/mp/zombies/_zm_magicbox.gsc new file mode 100644 index 0000000..2ab30df --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_magicbox.gsc @@ -0,0 +1,1656 @@ +#include maps/mp/zombies/_zm_stats; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm_unitrigger; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !isDefined( level.chest_joker_model ) ) + { + level.chest_joker_model = "zombie_teddybear"; + precachemodel( level.chest_joker_model ); + } + if ( !isDefined( level.magic_box_zbarrier_state_func ) ) + { + level.magic_box_zbarrier_state_func = ::process_magic_box_zbarrier_state; + } + if ( isDefined( level.using_locked_magicbox ) && level.using_locked_magicbox ) + { + maps/mp/zombies/_zm_magicbox_lock::init(); + } + if ( is_classic() ) + { + level.chests = getstructarray( "treasure_chest_use", "targetname" ); + treasure_chest_init( "start_chest" ); + } + if ( level.createfx_enabled ) + { + return; + } + registerclientfield( "zbarrier", "magicbox_glow", 1000, 1, "int" ); + registerclientfield( "zbarrier", "zbarrier_show_sounds", 9000, 1, "int" ); + registerclientfield( "zbarrier", "zbarrier_leave_sounds", 9000, 1, "int" ); + if ( !isDefined( level.magic_box_check_equipment ) ) + { + level.magic_box_check_equipment = ::default_magic_box_check_equipment; + } + level thread magicbox_host_migration(); +} + +treasure_chest_init( start_chest_name ) +{ + flag_init( "moving_chest_enabled" ); + flag_init( "moving_chest_now" ); + flag_init( "chest_has_been_used" ); + level.chest_moves = 0; + level.chest_level = 0; + if ( level.chests.size == 0 ) + { + return; + } + i = 0; + while ( i < level.chests.size ) + { + level.chests[ i ].box_hacks = []; + level.chests[ i ].orig_origin = level.chests[ i ].origin; + level.chests[ i ] get_chest_pieces(); + if ( isDefined( level.chests[ i ].zombie_cost ) ) + { + level.chests[ i ].old_cost = level.chests[ i ].zombie_cost; + i++; + continue; + } + else + { + level.chests[ i ].old_cost = 950; + } + i++; + } + if ( !level.enable_magic ) + { + _a102 = level.chests; + _k102 = getFirstArrayKey( _a102 ); + while ( isDefined( _k102 ) ) + { + chest = _a102[ _k102 ]; + chest hide_chest(); + _k102 = getNextArrayKey( _a102, _k102 ); + } + return; + } + level.chest_accessed = 0; + if ( level.chests.size > 1 ) + { + flag_set( "moving_chest_enabled" ); + level.chests = array_randomize( level.chests ); + } + else + { + level.chest_index = 0; + level.chests[ 0 ].no_fly_away = 1; + } + init_starting_chest_location( start_chest_name ); + array_thread( level.chests, ::treasure_chest_think ); +} + +init_starting_chest_location( start_chest_name ) +{ + level.chest_index = 0; + start_chest_found = 0; + if ( level.chests.size == 1 ) + { + start_chest_found = 1; + if ( isDefined( level.chests[ level.chest_index ].zbarrier ) ) + { + level.chests[ level.chest_index ].zbarrier set_magic_box_zbarrier_state( "initial" ); + } + } + else + { + i = 0; + while ( i < level.chests.size ) + { + if ( isDefined( level.random_pandora_box_start ) && level.random_pandora_box_start == 1 ) + { + if ( start_chest_found || isDefined( level.chests[ i ].start_exclude ) && level.chests[ i ].start_exclude == 1 ) + { + level.chests[ i ] hide_chest(); + } + else + { + level.chest_index = i; + level.chests[ level.chest_index ].hidden = 0; + if ( isDefined( level.chests[ level.chest_index ].zbarrier ) ) + { + level.chests[ level.chest_index ].zbarrier set_magic_box_zbarrier_state( "initial" ); + } + start_chest_found = 1; + } + i++; + continue; + } + else + { + if ( !start_chest_found || !isDefined( level.chests[ i ].script_noteworthy ) && !issubstr( level.chests[ i ].script_noteworthy, start_chest_name ) ) + { + level.chests[ i ] hide_chest(); + i++; + continue; + } + else + { + level.chest_index = i; + level.chests[ level.chest_index ].hidden = 0; + if ( isDefined( level.chests[ level.chest_index ].zbarrier ) ) + { + level.chests[ level.chest_index ].zbarrier set_magic_box_zbarrier_state( "initial" ); + } + start_chest_found = 1; + } + } + i++; + } + } + if ( !isDefined( level.pandora_show_func ) ) + { + level.pandora_show_func = ::default_pandora_show_func; + } + level.chests[ level.chest_index ] thread [[ level.pandora_show_func ]](); +} + +set_treasure_chest_cost( cost ) +{ + level.zombie_treasure_chest_cost = cost; +} + +get_chest_pieces() +{ + self.chest_box = getent( self.script_noteworthy + "_zbarrier", "script_noteworthy" ); + self.chest_rubble = []; + rubble = getentarray( self.script_noteworthy + "_rubble", "script_noteworthy" ); + i = 0; + while ( i < rubble.size ) + { + if ( distancesquared( self.origin, rubble[ i ].origin ) < 10000 ) + { + self.chest_rubble[ self.chest_rubble.size ] = rubble[ i ]; + } + i++; + } + self.zbarrier = getent( self.script_noteworthy + "_zbarrier", "script_noteworthy" ); + if ( isDefined( self.zbarrier ) ) + { + self.zbarrier zbarrierpieceuseboxriselogic( 3 ); + self.zbarrier zbarrierpieceuseboxriselogic( 4 ); + } + self.unitrigger_stub = spawnstruct(); + self.unitrigger_stub.origin = self.origin + ( anglesToRight( self.angles ) * -22.5 ); + self.unitrigger_stub.angles = self.angles; + self.unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + self.unitrigger_stub.script_width = 104; + self.unitrigger_stub.script_height = 50; + self.unitrigger_stub.script_length = 45; + self.unitrigger_stub.trigger_target = self; + unitrigger_force_per_player_triggers( self.unitrigger_stub, 1 ); + self.unitrigger_stub.prompt_and_visibility_func = ::boxtrigger_update_prompt; + self.zbarrier.owner = self; +} + +boxtrigger_update_prompt( player ) +{ + can_use = self boxstub_update_prompt( player ); + if ( isDefined( self.hint_string ) ) + { + if ( isDefined( self.hint_parm1 ) ) + { + self sethintstring( self.hint_string, self.hint_parm1 ); + } + else + { + self sethintstring( self.hint_string ); + } + } + return can_use; +} + +boxstub_update_prompt( player ) +{ + self setcursorhint( "HINT_NOICON" ); + if ( !self trigger_visible_to_player( player ) ) + { + return 0; + } + self.hint_parm1 = undefined; + if ( isDefined( self.stub.trigger_target.grab_weapon_hint ) && self.stub.trigger_target.grab_weapon_hint ) + { + if ( isDefined( level.magic_box_check_equipment ) && [[ level.magic_box_check_equipment ]]( self.stub.trigger_target.grab_weapon_name ) ) + { + self.hint_string = &"ZOMBIE_TRADE_EQUIP"; + } + else + { + self.hint_string = &"ZOMBIE_TRADE_WEAPON"; + } + } + else + { + if ( isDefined( level.using_locked_magicbox ) && level.using_locked_magicbox && isDefined( self.stub.trigger_target.is_locked ) && self.stub.trigger_target.is_locked ) + { + self.hint_string = get_hint_string( self, "locked_magic_box_cost" ); + } + else + { + self.hint_parm1 = self.stub.trigger_target.zombie_cost; + self.hint_string = get_hint_string( self, "default_treasure_chest" ); + } + } + return 1; +} + +default_magic_box_check_equipment( weapon ) +{ + return is_offhand_weapon( weapon ); +} + +trigger_visible_to_player( player ) +{ + self setinvisibletoplayer( player ); + visible = 1; + if ( isDefined( self.stub.trigger_target.chest_user ) && !isDefined( self.stub.trigger_target.box_rerespun ) ) + { + if ( player != self.stub.trigger_target.chest_user || is_placeable_mine( self.stub.trigger_target.chest_user getcurrentweapon() ) && self.stub.trigger_target.chest_user hacker_active() ) + { + visible = 0; + } + } + else + { + if ( !player can_buy_weapon() ) + { + visible = 0; + } + } + if ( !visible ) + { + return 0; + } + self setvisibletoplayer( player ); + return 1; +} + +magicbox_unitrigger_think() +{ + self endon( "kill_trigger" ); + while ( 1 ) + { + self waittill( "trigger", player ); + self.stub.trigger_target notify( "trigger" ); + } +} + +play_crazi_sound() +{ + self playlocalsound( level.zmb_laugh_alias ); +} + +show_chest_sound_thread() +{ + self.zbarrier setclientfield( "zbarrier_show_sounds", 1 ); + wait 1; + self.zbarrier setclientfield( "zbarrier_show_sounds", 0 ); +} + +show_chest() +{ + self.zbarrier set_magic_box_zbarrier_state( "arriving" ); + self.zbarrier waittill( "arrived" ); + self thread [[ level.pandora_show_func ]](); + thread maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.unitrigger_stub, ::magicbox_unitrigger_think ); + self thread show_chest_sound_thread(); + self.hidden = 0; + if ( isDefined( self.box_hacks[ "summon_box" ] ) ) + { + self [[ self.box_hacks[ "summon_box" ] ]]( 0 ); + } +} + +hide_chest_sound_thread() +{ + self.zbarrier setclientfield( "zbarrier_leave_sounds", 1 ); + wait 1; + self.zbarrier setclientfield( "zbarrier_leave_sounds", 0 ); +} + +hide_chest( doboxleave ) +{ + if ( isDefined( self.unitrigger_stub ) ) + { + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger_stub ); + } + if ( isDefined( self.pandora_light ) ) + { + self.pandora_light delete(); + } + self.hidden = 1; + if ( isDefined( self.box_hacks ) && isDefined( self.box_hacks[ "summon_box" ] ) ) + { + self [[ self.box_hacks[ "summon_box" ] ]]( 1 ); + } + if ( isDefined( self.zbarrier ) ) + { + if ( isDefined( doboxleave ) && doboxleave ) + { + self thread hide_chest_sound_thread(); + level thread leaderdialog( "boxmove" ); + self.zbarrier thread magic_box_zbarrier_leave(); + self.zbarrier waittill( "left" ); + playfx( level._effect[ "poltergeist" ], self.zbarrier.origin, anglesToUp( self.angles ), anglesToForward( self.angles ) ); + playsoundatposition( "zmb_box_poof", self.zbarrier.origin ); + return; + } + else + { + self.zbarrier thread set_magic_box_zbarrier_state( "away" ); + } + } +} + +magic_box_zbarrier_leave() +{ + self set_magic_box_zbarrier_state( "leaving" ); + self waittill( "left" ); + self set_magic_box_zbarrier_state( "away" ); +} + +default_pandora_fx_func() +{ + self endon( "death" ); + self.pandora_light = spawn( "script_model", self.zbarrier.origin ); + self.pandora_light.angles = self.zbarrier.angles + vectorScale( ( 0, 1, 0 ), 90 ); + self.pandora_light setmodel( "tag_origin" ); + if ( isDefined( level._box_initialized ) && !level._box_initialized ) + { + flag_wait( "start_zombie_round_logic" ); + level._box_initialized = 1; + } + wait 1; + if ( isDefined( self ) && isDefined( self.pandora_light ) ) + { + playfxontag( level._effect[ "lght_marker" ], self.pandora_light, "tag_origin" ); + } +} + +default_pandora_show_func( anchor, anchortarget, pieces ) +{ + if ( !isDefined( self.pandora_light ) ) + { + if ( !isDefined( level.pandora_fx_func ) ) + { + level.pandora_fx_func = ::default_pandora_fx_func; + } + self thread [[ level.pandora_fx_func ]](); + } + playfx( level._effect[ "lght_marker_flare" ], self.pandora_light.origin ); +} + +unregister_unitrigger_on_kill_think() +{ + self notify( "unregister_unitrigger_on_kill_think" ); + self endon( "unregister_unitrigger_on_kill_think" ); + self waittill( "kill_chest_think" ); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger_stub ); +} + +treasure_chest_think() +{ + self endon( "kill_chest_think" ); + user = undefined; + user_cost = undefined; + self.box_rerespun = undefined; + self.weapon_out = undefined; + self thread unregister_unitrigger_on_kill_think(); + for ( ;; ) + { + while ( 1 ) + { + if ( !isDefined( self.forced_user ) ) + { + self waittill( "trigger", user ); + while ( user == level ) + { + continue; + } + } + else user = self.forced_user; + while ( user in_revive_trigger() ) + { + wait 0.1; + } + while ( user.is_drinking > 0 ) + { + wait 0.1; + } + while ( isDefined( self.disabled ) && self.disabled ) + { + wait 0.1; + } + while ( user getcurrentweapon() == "none" ) + { + wait 0.1; + } + reduced_cost = undefined; + if ( is_player_valid( user ) && user maps/mp/zombies/_zm_pers_upgrades_functions::is_pers_double_points_active() ) + { + reduced_cost = int( self.zombie_cost / 2 ); + } + if ( isDefined( level.using_locked_magicbox ) && level.using_locked_magicbox && isDefined( self.is_locked ) && self.is_locked ) + { + if ( user.score >= level.locked_magic_box_cost ) + { + user maps/mp/zombies/_zm_score::minus_to_player_score( level.locked_magic_box_cost ); + self.zbarrier set_magic_box_zbarrier_state( "unlocking" ); + self.unitrigger_stub run_visibility_function_for_all_triggers(); + } + else + { + user create_and_play_dialog( "general", "no_money_box" ); + } + wait 0.1; + } + } + if ( isDefined( self.auto_open ) && is_player_valid( user ) ) + { + if ( !isDefined( self.no_charge ) ) + { + user maps/mp/zombies/_zm_score::minus_to_player_score( self.zombie_cost ); + user_cost = self.zombie_cost; + } + else + { + user_cost = 0; + } + self.chest_user = user; + break; + } + else if ( is_player_valid( user ) && user.score >= self.zombie_cost ) + { + user maps/mp/zombies/_zm_score::minus_to_player_score( self.zombie_cost ); + user_cost = self.zombie_cost; + self.chest_user = user; + break; + } + else if ( isDefined( reduced_cost ) && user.score >= reduced_cost ) + { + user maps/mp/zombies/_zm_score::minus_to_player_score( reduced_cost ); + user_cost = reduced_cost; + self.chest_user = user; + break; + } + else while ( user.score < self.zombie_cost ) + { + play_sound_at_pos( "no_purchase", self.origin ); + user create_and_play_dialog( "general", "no_money_box" ); + } + wait 0.05; + } + flag_set( "chest_has_been_used" ); + maps/mp/_demo::bookmark( "zm_player_use_magicbox", getTime(), user ); + user maps/mp/zombies/_zm_stats::increment_client_stat( "use_magicbox" ); + user maps/mp/zombies/_zm_stats::increment_player_stat( "use_magicbox" ); + if ( isDefined( level._magic_box_used_vo ) ) + { + user thread [[ level._magic_box_used_vo ]](); + } + self thread watch_for_emp_close(); + if ( isDefined( level.using_locked_magicbox ) && level.using_locked_magicbox ) + { + self thread maps/mp/zombies/_zm_magicbox_lock::watch_for_lock(); + } + self._box_open = 1; + self._box_opened_by_fire_sale = 0; + if ( isDefined( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) && level.zombie_vars[ "zombie_powerup_fire_sale_on" ] && !isDefined( self.auto_open ) && self [[ level._zombiemode_check_firesale_loc_valid_func ]]() ) + { + self._box_opened_by_fire_sale = 1; + } + if ( isDefined( self.chest_lid ) ) + { + self.chest_lid thread treasure_chest_lid_open(); + } + if ( isDefined( self.zbarrier ) ) + { + play_sound_at_pos( "open_chest", self.origin ); + play_sound_at_pos( "music_chest", self.origin ); + self.zbarrier set_magic_box_zbarrier_state( "open" ); + } + self.timedout = 0; + self.weapon_out = 1; + self.zbarrier thread treasure_chest_weapon_spawn( self, user ); + self.zbarrier thread treasure_chest_glowfx(); + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger_stub ); + self.zbarrier waittill_any( "randomization_done", "box_hacked_respin" ); + if ( flag( "moving_chest_now" ) && !self._box_opened_by_fire_sale && isDefined( user_cost ) ) + { + user maps/mp/zombies/_zm_score::add_to_player_score( user_cost, 0 ); + } + if ( flag( "moving_chest_now" ) && !level.zombie_vars[ "zombie_powerup_fire_sale_on" ] && !self._box_opened_by_fire_sale ) + { + self thread treasure_chest_move( self.chest_user ); + } + else + { + self.grab_weapon_hint = 1; + self.grab_weapon_name = self.zbarrier.weapon_string; + self.chest_user = user; + thread maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.unitrigger_stub, ::magicbox_unitrigger_think ); + if ( isDefined( self.zbarrier ) && !is_true( self.zbarrier.closed_by_emp ) ) + { + self thread treasure_chest_timeout(); + } + while ( isDefined( self.closed_by_emp ) && !self.closed_by_emp ) + { + self waittill( "trigger", grabber ); + self.weapon_out = undefined; + if ( isDefined( level.magic_box_grab_by_anyone ) && level.magic_box_grab_by_anyone ) + { + if ( isplayer( grabber ) ) + { + user = grabber; + } + } + if ( isDefined( level.pers_upgrade_box_weapon ) && level.pers_upgrade_box_weapon ) + { + self maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_box_weapon_used( user, grabber ); + } + while ( isDefined( grabber.is_drinking ) && grabber.is_drinking > 0 ) + { + wait 0.1; + } + while ( grabber == user && user getcurrentweapon() == "none" ) + { + wait 0.1; + } + if ( grabber != level && isDefined( self.box_rerespun ) && self.box_rerespun ) + { + user = grabber; + } + if ( grabber == user || grabber == level ) + { + self.box_rerespun = undefined; + current_weapon = "none"; + if ( is_player_valid( user ) ) + { + current_weapon = user getcurrentweapon(); + } + if ( grabber == user && is_player_valid( user ) && user.is_drinking > 0 && !is_placeable_mine( current_weapon ) && !is_equipment( current_weapon ) && level.revive_tool != current_weapon ) + { + bbprint( "zombie_uses", "playername %s playerscore %d round %d cost %d name %s x %f y %f z %f type %s", user.name, user.score, level.round_number, self.zombie_cost, self.zbarrier.weapon_string, self.origin, "magic_accept" ); + self notify( "user_grabbed_weapon" ); + user notify( "user_grabbed_weapon" ); + user thread treasure_chest_give_weapon( self.zbarrier.weapon_string ); + maps/mp/_demo::bookmark( "zm_player_grabbed_magicbox", getTime(), user ); + user maps/mp/zombies/_zm_stats::increment_client_stat( "grabbed_from_magicbox" ); + user maps/mp/zombies/_zm_stats::increment_player_stat( "grabbed_from_magicbox" ); + } + else if ( grabber == level ) + { + unacquire_weapon_toggle( self.zbarrier.weapon_string ); + self.timedout = 1; + if ( is_player_valid( user ) ) + { + bbprint( "zombie_uses", "playername %s playerscore %d round %d cost %d name %s x %f y %f z %f type %S", user.name, user.score, level.round_number, self.zombie_cost, self.zbarrier.weapon_string, self.origin, "magic_reject" ); + } + } + } + else + { + wait 0.05; + } + } + self.grab_weapon_hint = 0; + self.zbarrier notify( "weapon_grabbed" ); + if ( isDefined( self._box_opened_by_fire_sale ) && !self._box_opened_by_fire_sale ) + { + level.chest_accessed += 1; + } + if ( level.chest_moves > 0 && isDefined( level.pulls_since_last_ray_gun ) ) + { + level.pulls_since_last_ray_gun += 1; + } + if ( isDefined( level.pulls_since_last_tesla_gun ) ) + { + level.pulls_since_last_tesla_gun += 1; + } + thread maps/mp/zombies/_zm_unitrigger::unregister_unitrigger( self.unitrigger_stub ); + if ( isDefined( self.chest_lid ) ) + { + self.chest_lid thread treasure_chest_lid_close( self.timedout ); + } + if ( isDefined( self.zbarrier ) ) + { + self.zbarrier set_magic_box_zbarrier_state( "close" ); + play_sound_at_pos( "close_chest", self.origin ); + self.zbarrier waittill( "closed" ); + wait 1; + } + else + { + wait 3; + } + if ( isDefined( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) && level.zombie_vars[ "zombie_powerup_fire_sale_on" ] || self [[ level._zombiemode_check_firesale_loc_valid_func ]]() && self == level.chests[ level.chest_index ] ) + { + thread maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.unitrigger_stub, ::magicbox_unitrigger_think ); + } + } + self._box_open = 0; + self._box_opened_by_fire_sale = 0; + self.chest_user = undefined; + self notify( "chest_accessed" ); + self thread treasure_chest_think(); +} + +watch_for_emp_close() +{ + self endon( "chest_accessed" ); + self.closed_by_emp = 0; + if ( !should_watch_for_emp() ) + { + return; + } + if ( isDefined( self.zbarrier ) ) + { + self.zbarrier.closed_by_emp = 0; + } + while ( 1 ) + { + level waittill( "emp_detonate", origin, radius ); + if ( distancesquared( origin, self.origin ) < ( radius * radius ) ) + { + break; + } + else + { + } + } + if ( flag( "moving_chest_now" ) ) + { + return; + } + self.closed_by_emp = 1; + if ( isDefined( self.zbarrier ) ) + { + self.zbarrier.closed_by_emp = 1; + self.zbarrier notify( "box_hacked_respin" ); + if ( isDefined( self.zbarrier.weapon_model ) ) + { + self.zbarrier.weapon_model notify( "kill_weapon_movement" ); + } + if ( isDefined( self.zbarrier.weapon_model_dw ) ) + { + self.zbarrier.weapon_model_dw notify( "kill_weapon_movement" ); + } + } + wait 0.1; + self notify( "trigger" ); +} + +can_buy_weapon() +{ + if ( isDefined( self.is_drinking ) && self.is_drinking > 0 ) + { + return 0; + } + if ( self hacker_active() ) + { + return 0; + } + current_weapon = self getcurrentweapon(); + if ( is_placeable_mine( current_weapon ) || is_equipment_that_blocks_purchase( current_weapon ) ) + { + return 0; + } + if ( self in_revive_trigger() ) + { + return 0; + } + if ( current_weapon == "none" ) + { + return 0; + } + return 1; +} + +default_box_move_logic() +{ + index = -1; + i = 0; + while ( i < level.chests.size ) + { + if ( issubstr( level.chests[ i ].script_noteworthy, "move" + ( level.chest_moves + 1 ) ) && i != level.chest_index ) + { + index = i; + break; + } + else + { + i++; + } + } + if ( index != -1 ) + { + level.chest_index = index; + } + else + { + level.chest_index++; + } + if ( level.chest_index >= level.chests.size ) + { + temp_chest_name = level.chests[ level.chest_index - 1 ].script_noteworthy; + level.chest_index = 0; + level.chests = array_randomize( level.chests ); + if ( temp_chest_name == level.chests[ level.chest_index ].script_noteworthy ) + { + level.chest_index++; + } + } +} + +treasure_chest_move( player_vox ) +{ + level waittill( "weapon_fly_away_start" ); + players = get_players(); + array_thread( players, ::play_crazi_sound ); + if ( isDefined( player_vox ) ) + { + player_vox delay_thread( randomintrange( 2, 7 ), ::create_and_play_dialog, "general", "box_move" ); + } + level waittill( "weapon_fly_away_end" ); + if ( isDefined( self.zbarrier ) ) + { + self hide_chest( 1 ); + } + wait 0.1; + post_selection_wait_duration = 7; + if ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 && self [[ level._zombiemode_check_firesale_loc_valid_func ]]() ) + { + current_sale_time = level.zombie_vars[ "zombie_powerup_fire_sale_time" ]; + wait_network_frame(); + self thread fire_sale_fix(); + level.zombie_vars[ "zombie_powerup_fire_sale_time" ] = current_sale_time; + while ( level.zombie_vars[ "zombie_powerup_fire_sale_time" ] > 0 ) + { + wait 0.1; + } + } + else post_selection_wait_duration += 5; + level.verify_chest = 0; + if ( isDefined( level._zombiemode_custom_box_move_logic ) ) + { + [[ level._zombiemode_custom_box_move_logic ]](); + } + else + { + default_box_move_logic(); + } + if ( isDefined( level.chests[ level.chest_index ].box_hacks[ "summon_box" ] ) ) + { + level.chests[ level.chest_index ] [[ level.chests[ level.chest_index ].box_hacks[ "summon_box" ] ]]( 0 ); + } + wait post_selection_wait_duration; + playfx( level._effect[ "poltergeist" ], level.chests[ level.chest_index ].zbarrier.origin ); + level.chests[ level.chest_index ] show_chest(); + flag_clear( "moving_chest_now" ); + self.zbarrier.chest_moving = 0; +} + +fire_sale_fix() +{ + if ( !isDefined( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) ) + { + return; + } + if ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) + { + self.old_cost = 950; + self thread show_chest(); + self.zombie_cost = 10; + self.unitrigger_stub unitrigger_set_hint_string( self, "default_treasure_chest", self.zombie_cost ); + wait_network_frame(); + level waittill( "fire_sale_off" ); + while ( isDefined( self._box_open ) && self._box_open ) + { + wait 0.1; + } + self hide_chest( 1 ); + self.zombie_cost = self.old_cost; + } +} + +check_for_desirable_chest_location() +{ + if ( !isDefined( level.desirable_chest_location ) ) + { + return level.chest_index; + } + if ( level.chests[ level.chest_index ].script_noteworthy == level.desirable_chest_location ) + { + level.desirable_chest_location = undefined; + return level.chest_index; + } + i = 0; + while ( i < level.chests.size ) + { + if ( level.chests[ i ].script_noteworthy == level.desirable_chest_location ) + { + level.desirable_chest_location = undefined; + return i; + } + i++; + } + /* +/# + iprintln( level.desirable_chest_location + " is an invalid box location!" ); +#/ + */ + level.desirable_chest_location = undefined; + return level.chest_index; +} + +rotateroll_box() +{ + angles = 40; + angles2 = 0; + while ( isDefined( self ) ) + { + self rotateroll( angles + angles2, 0.5 ); + wait 0.7; + angles2 = 40; + self rotateroll( angles * -2, 0.5 ); + wait 0.7; + } +} + +verify_chest_is_open() +{ + i = 0; + while ( i < level.open_chest_location.size ) + { + if ( isDefined( level.open_chest_location[ i ] ) ) + { + if ( level.open_chest_location[ i ] == level.chests[ level.chest_index ].script_noteworthy ) + { + level.verify_chest = 1; + return; + } + } + i++; + } + level.verify_chest = 0; +} + +treasure_chest_timeout() +{ + self endon( "user_grabbed_weapon" ); + self.zbarrier endon( "box_hacked_respin" ); + self.zbarrier endon( "box_hacked_rerespin" ); + wait 12; + self notify( "trigger" ); +} + +treasure_chest_lid_open() +{ + openroll = 105; + opentime = 0.5; + self rotateroll( 105, opentime, opentime * 0,5 ); + play_sound_at_pos( "open_chest", self.origin ); + play_sound_at_pos( "music_chest", self.origin ); +} + +treasure_chest_lid_close( timedout ) +{ + closeroll = -105; + closetime = 0.5; + self rotateroll( closeroll, closetime, closetime * 0,5 ); + play_sound_at_pos( "close_chest", self.origin ); + self notify( "lid_closed" ); +} + +treasure_chest_chooserandomweapon( player ) +{ + keys = getarraykeys( level.zombie_weapons ); + return keys[ randomint( keys.size ) ]; +} + +treasure_chest_canplayerreceiveweapon( player, weapon, pap_triggers ) +{ + if ( !get_is_in_box( weapon ) ) + { + return 0; + } + if ( isDefined( player ) && player has_weapon_or_upgrade( weapon ) ) + { + return 0; + } + if ( !limited_weapon_below_quota( weapon, player, pap_triggers ) ) + { + return 0; + } + if ( !player player_can_use_content( weapon ) ) + { + return 0; + } + if ( isDefined( level.custom_magic_box_selection_logic ) ) + { + if ( !( [[ level.custom_magic_box_selection_logic ]]( weapon, player, pap_triggers ) ) ) + { + return 0; + } + } + if ( isDefined( player ) && isDefined( level.special_weapon_magicbox_check ) ) + { + return player [[ level.special_weapon_magicbox_check ]]( weapon ); + } + return 1; +} + +treasure_chest_chooseweightedrandomweapon( player ) +{ + keys = array_randomize( getarraykeys( level.zombie_weapons ) ); + if ( isDefined( level.customrandomweaponweights ) ) + { + keys = player [[ level.customrandomweaponweights ]]( keys ); + } + /* +/# + 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 ( treasure_chest_canplayerreceiveweapon( player, keys[ i ], pap_triggers ) ) + { + return keys[ i ]; + } + i++; + } + return keys[ 0 ]; +} + +weapon_is_dual_wield( name ) +{ + switch( name ) + { + case "cz75dw_upgraded_zm": + case "cz75dw_zm": + case "fivesevendw_upgraded_zm": + case "fivesevendw_zm": + case "hs10_upgraded_zm": + case "m1911_upgraded_zm": + case "microwavegundw_upgraded_zm": + case "microwavegundw_zm": + case "pm63_upgraded_zm": + return 1; + default: + return 0; + } +} + +weapon_show_hint_choke() +{ + level._weapon_show_hint_choke = 0; + while ( 1 ) + { + wait 0.05; + level._weapon_show_hint_choke = 0; + } +} + +decide_hide_show_hint( endon_notify, second_endon_notify, onlyplayer ) +{ + self endon( "death" ); + if ( isDefined( endon_notify ) ) + { + self endon( endon_notify ); + } + if ( isDefined( second_endon_notify ) ) + { + self endon( second_endon_notify ); + } + if ( !isDefined( level._weapon_show_hint_choke ) ) + { + level thread weapon_show_hint_choke(); + } + use_choke = 0; + if ( isDefined( level._use_choke_weapon_hints ) && level._use_choke_weapon_hints == 1 ) + { + use_choke = 1; + } + while ( 1 ) + { + last_update = getTime(); + if ( isDefined( self.chest_user ) && !isDefined( self.box_rerespun ) ) + { + if ( is_placeable_mine( self.chest_user getcurrentweapon() ) || self.chest_user hacker_active() ) + { + self setinvisibletoplayer( self.chest_user ); + } + else + { + self setvisibletoplayer( self.chest_user ); + } + } + else + { + if ( isDefined( onlyplayer ) ) + { + if ( onlyplayer can_buy_weapon() ) + { + self setinvisibletoplayer( onlyplayer, 0 ); + } + else + { + self setinvisibletoplayer( onlyplayer, 1 ); + } + break; + } + else + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ] can_buy_weapon() ) + { + self setinvisibletoplayer( players[ i ], 0 ); + i++; + continue; + } + else + { + self setinvisibletoplayer( players[ i ], 1 ); + } + i++; + } + } + } + if ( use_choke ) + { + while ( level._weapon_show_hint_choke > 4 && getTime() < ( last_update + 150 ) ) + { + wait 0.05; + } + } + else wait 0.1; + level._weapon_show_hint_choke++; + } +} + +get_left_hand_weapon_model_name( name ) +{ + switch( name ) + { + case "microwavegundw_zm": + return getweaponmodel( "microwavegunlh_zm" ); + case "microwavegundw_upgraded_zm": + return getweaponmodel( "microwavegunlh_upgraded_zm" ); + default: + return getweaponmodel( name ); + } +} + +clean_up_hacked_box() +{ + self waittill( "box_hacked_respin" ); + self endon( "box_spin_done" ); + if ( isDefined( self.weapon_model ) ) + { + self.weapon_model delete(); + self.weapon_model = undefined; + } + if ( isDefined( self.weapon_model_dw ) ) + { + self.weapon_model_dw delete(); + self.weapon_model_dw = undefined; + } + self hidezbarrierpiece( 3 ); + self hidezbarrierpiece( 4 ); + self setzbarrierpiecestate( 3, "closed" ); + self setzbarrierpiecestate( 4, "closed" ); +} + +treasure_chest_weapon_spawn( chest, player, respin ) +{ + if ( isDefined( level.using_locked_magicbox ) && level.using_locked_magicbox ) + { + self.owner endon( "box_locked" ); + self thread maps/mp/zombies/_zm_magicbox_lock::clean_up_locked_box(); + } + self endon( "box_hacked_respin" ); + self thread clean_up_hacked_box(); + /* +/# + assert( isDefined( player ) ); +#/ + */ + self.weapon_string = undefined; + modelname = undefined; + rand = undefined; + number_cycles = 40; + if ( isDefined( chest.zbarrier ) ) + { + if ( isDefined( level.custom_magic_box_do_weapon_rise ) ) + { + chest.zbarrier thread [[ level.custom_magic_box_do_weapon_rise ]](); + } + else + { + chest.zbarrier thread magic_box_do_weapon_rise(); + } + } + i = 0; + while ( i < number_cycles ) + { + if ( i < 20 ) + { + wait 0.05; + i++; + continue; + } + else if ( i < 30 ) + { + wait 0.1; + i++; + continue; + } + else if ( i < 35 ) + { + wait 0.2; + i++; + continue; + } + else + { + if ( i < 38 ) + { + wait 0.3; + } + } + i++; + } + if ( isDefined( level.custom_magic_box_weapon_wait ) ) + { + [[ level.custom_magic_box_weapon_wait ]](); + } + if ( isDefined( player.pers_upgrades_awarded[ "box_weapon" ] ) && player.pers_upgrades_awarded[ "box_weapon" ] ) + { + rand = maps/mp/zombies/_zm_pers_upgrades_functions::pers_treasure_chest_choosespecialweapon( player ); + } + else + { + rand = treasure_chest_chooseweightedrandomweapon( player ); + } + self.weapon_string = rand; + wait 0.1; + if ( isDefined( level.custom_magicbox_float_height ) ) + { + v_float = anglesToUp( self.angles ) * level.custom_magicbox_float_height; + } + else + { + v_float = anglesToUp( self.angles ) * 40; + } + self.model_dw = undefined; + self.weapon_model = spawn_weapon_model( rand, undefined, self.origin + v_float, self.angles + vectorScale( ( 0, 1, 0 ), 180 ) ); + if ( weapon_is_dual_wield( rand ) ) + { + self.weapon_model_dw = spawn_weapon_model( rand, get_left_hand_weapon_model_name( rand ), self.weapon_model.origin - vectorScale( ( 0, 1, 0 ), 3 ), self.weapon_model.angles ); + } + if ( getDvar( "magic_chest_movable" ) == "1" && isDefined( chest._box_opened_by_fire_sale ) && !chest._box_opened_by_fire_sale && isDefined( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) && level.zombie_vars[ "zombie_powerup_fire_sale_on" ] && !( self [[ level._zombiemode_check_firesale_loc_valid_func ]]() ) ) + { + random = randomint( 100 ); + if ( !isDefined( level.chest_min_move_usage ) ) + { + level.chest_min_move_usage = 4; + } + if ( level.chest_accessed < level.chest_min_move_usage ) + { + chance_of_joker = -1; + } + else chance_of_joker = level.chest_accessed + 20; + if ( level.chest_moves == 0 && level.chest_accessed >= 8 ) + { + chance_of_joker = 100; + } + if ( level.chest_accessed >= 4 && level.chest_accessed < 8 ) + { + if ( random < 15 ) + { + chance_of_joker = 100; + } + else + { + chance_of_joker = -1; + } + } + if ( level.chest_moves > 0 ) + { + if ( level.chest_accessed >= 8 && level.chest_accessed < 13 ) + { + if ( random < 30 ) + { + chance_of_joker = 100; + } + else + { + chance_of_joker = -1; + } + } + if ( level.chest_accessed >= 13 ) + { + if ( random < 50 ) + { + chance_of_joker = 100; + } + else + { + chance_of_joker = -1; + } + } + } + if ( isDefined( chest.no_fly_away ) ) + { + chance_of_joker = -1; + } + if ( isDefined( level._zombiemode_chest_joker_chance_override_func ) ) + { + chance_of_joker = [[ level._zombiemode_chest_joker_chance_override_func ]]( chance_of_joker ); + } + if ( chance_of_joker > random ) + { + self.weapon_string = undefined; + self.weapon_model setmodel( level.chest_joker_model ); + self.weapon_model.angles = self.angles + vectorScale( ( 0, 1, 0 ), 90 ); + if ( isDefined( self.weapon_model_dw ) ) + { + self.weapon_model_dw delete(); + self.weapon_model_dw = undefined; + } + self.chest_moving = 1; + flag_set( "moving_chest_now" ); + level.chest_accessed = 0; + level.chest_moves++; + } + } + self notify( "randomization_done" ); + if ( flag( "moving_chest_now" ) && level.zombie_vars[ "zombie_powerup_fire_sale_on" ] && !( self [[ level._zombiemode_check_firesale_loc_valid_func ]]() ) ) + { + if ( isDefined( level.chest_joker_custom_movement ) ) + { + self [[ level.chest_joker_custom_movement ]](); + } + else + { + wait 0.5; + level notify( "weapon_fly_away_start" ); + wait 2; + if ( isDefined( self.weapon_model ) ) + { + v_fly_away = self.origin + ( anglesToUp( self.angles ) * 500 ); + self.weapon_model moveto( v_fly_away, 4, 3 ); + } + if ( isDefined( self.weapon_model_dw ) ) + { + v_fly_away = self.origin + ( anglesToUp( self.angles ) * 500 ); + self.weapon_model_dw moveto( v_fly_away, 4, 3 ); + } + self.weapon_model waittill( "movedone" ); + self.weapon_model delete(); + if ( isDefined( self.weapon_model_dw ) ) + { + self.weapon_model_dw delete(); + self.weapon_model_dw = undefined; + } + self notify( "box_moving" ); + level notify( "weapon_fly_away_end" ); + } + } + else + { + acquire_weapon_toggle( rand, player ); + if ( rand == "tesla_gun_zm" || rand == "ray_gun_zm" ) + { + if ( rand == "ray_gun_zm" ) + { + level.pulls_since_last_ray_gun = 0; + } + if ( rand == "tesla_gun_zm" ) + { + level.pulls_since_last_tesla_gun = 0; + level.player_seen_tesla_gun = 1; + } + } + if ( !isDefined( respin ) ) + { + if ( isDefined( chest.box_hacks[ "respin" ] ) ) + { + self [[ chest.box_hacks[ "respin" ] ]]( chest, player ); + } + } + else + { + if ( isDefined( chest.box_hacks[ "respin_respin" ] ) ) + { + self [[ chest.box_hacks[ "respin_respin" ] ]]( chest, player ); + } + } + if ( isDefined( level.custom_magic_box_timer_til_despawn ) ) + { + self.weapon_model thread [[ level.custom_magic_box_timer_til_despawn ]]( self ); + } + else + { + self.weapon_model thread timer_til_despawn( v_float ); + } + if ( isDefined( self.weapon_model_dw ) ) + { + if ( isDefined( level.custom_magic_box_timer_til_despawn ) ) + { + self.weapon_model_dw thread [[ level.custom_magic_box_timer_til_despawn ]]( self ); + } + else + { + self.weapon_model_dw thread timer_til_despawn( v_float ); + } + } + self waittill( "weapon_grabbed" ); + if ( !chest.timedout ) + { + if ( isDefined( self.weapon_model ) ) + { + self.weapon_model delete(); + } + if ( isDefined( self.weapon_model_dw ) ) + { + self.weapon_model_dw delete(); + } + } + } + self.weapon_string = undefined; + self notify( "box_spin_done" ); +} + +chest_get_min_usage() +{ + min_usage = 4; + return min_usage; +} + +chest_get_max_usage() +{ + max_usage = 6; + players = get_players(); + if ( level.chest_moves == 0 ) + { + if ( players.size == 1 ) + { + max_usage = 3; + } + else if ( players.size == 2 ) + { + max_usage = 4; + } + else if ( players.size == 3 ) + { + max_usage = 5; + } + else + { + max_usage = 6; + } + } + else if ( players.size == 1 ) + { + max_usage = 4; + } + else if ( players.size == 2 ) + { + max_usage = 4; + } + else if ( players.size == 3 ) + { + max_usage = 5; + } + else + { + max_usage = 7; + } + return max_usage; +} + +timer_til_despawn( v_float ) +{ + self endon( "kill_weapon_movement" ); + putbacktime = 12; + self moveto( self.origin - ( v_float * 0.85 ), putbacktime, putbacktime * 0.5 ); + wait putbacktime; + if ( isDefined( self ) ) + { + self delete(); + } +} + +treasure_chest_glowfx() +{ + self setclientfield( "magicbox_glow", 1 ); + self waittill_any( "weapon_grabbed", "box_moving" ); + self setclientfield( "magicbox_glow", 0 ); +} + +treasure_chest_give_weapon( weapon_string ) +{ + self.last_box_weapon = getTime(); + self maps/mp/zombies/_zm_weapons::weapon_give( weapon_string, 0, 1 ); +} + +magic_box_teddy_twitches() +{ + self endon( "zbarrier_state_change" ); + self setzbarrierpiecestate( 0, "closed" ); + while ( 1 ) + { + wait randomfloatrange( 180, 1800 ); + self setzbarrierpiecestate( 0, "opening" ); + wait randomfloatrange( 180, 1800 ); + self setzbarrierpiecestate( 0, "closing" ); + } +} + +magic_box_initial() +{ + self setzbarrierpiecestate( 1, "open" ); +} + +magic_box_arrives() +{ + self setzbarrierpiecestate( 1, "opening" ); + while ( self getzbarrierpiecestate( 1 ) == "opening" ) + { + wait 0.05; + } + self notify( "arrived" ); +} + +magic_box_leaves() +{ + self setzbarrierpiecestate( 1, "closing" ); + while ( self getzbarrierpiecestate( 1 ) == "closing" ) + { + wait 0.1; + } + self notify( "left" ); +} + +magic_box_opens() +{ + self setzbarrierpiecestate( 2, "opening" ); + while ( self getzbarrierpiecestate( 2 ) == "opening" ) + { + wait 0.1; + } + self notify( "opened" ); +} + +magic_box_closes() +{ + self setzbarrierpiecestate( 2, "closing" ); + while ( self getzbarrierpiecestate( 2 ) == "closing" ) + { + wait 0.1; + } + self notify( "closed" ); +} + +magic_box_do_weapon_rise() +{ + self endon( "box_hacked_respin" ); + self setzbarrierpiecestate( 3, "closed" ); + self setzbarrierpiecestate( 4, "closed" ); + wait_network_frame(); + self zbarrierpieceuseboxriselogic( 3 ); + self zbarrierpieceuseboxriselogic( 4 ); + self showzbarrierpiece( 3 ); + self showzbarrierpiece( 4 ); + self setzbarrierpiecestate( 3, "opening" ); + self setzbarrierpiecestate( 4, "opening" ); + while ( self getzbarrierpiecestate( 3 ) != "open" ) + { + wait 0.5; + } + self hidezbarrierpiece( 3 ); + self hidezbarrierpiece( 4 ); +} + +magic_box_do_teddy_flyaway() +{ + self showzbarrierpiece( 3 ); + self setzbarrierpiecestate( 3, "closing" ); +} + +is_chest_active() +{ + curr_state = self.zbarrier get_magic_box_zbarrier_state(); + if ( flag( "moving_chest_now" ) ) + { + return 0; + } + if ( curr_state == "open" || curr_state == "close" ) + { + return 1; + } + return 0; +} + +get_magic_box_zbarrier_state() +{ + return self.state; +} + +set_magic_box_zbarrier_state( state ) +{ + i = 0; + while ( i < self getnumzbarrierpieces() ) + { + self hidezbarrierpiece( i ); + i++; + } + self notify( "zbarrier_state_change" ); + self [[ level.magic_box_zbarrier_state_func ]]( state ); +} + +process_magic_box_zbarrier_state( state ) +{ + switch( state ) + { + case "away": + self showzbarrierpiece( 0 ); + self thread magic_box_teddy_twitches(); + self.state = "away"; + break; + case "arriving": + self showzbarrierpiece( 1 ); + self thread magic_box_arrives(); + self.state = "arriving"; + break; + case "initial": + self showzbarrierpiece( 1 ); + self thread magic_box_initial(); + thread maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( self.owner.unitrigger_stub, ::magicbox_unitrigger_think ); + self.state = "initial"; + break; + case "open": + self showzbarrierpiece( 2 ); + self thread magic_box_opens(); + self.state = "open"; + break; + case "close": + self showzbarrierpiece( 2 ); + self thread magic_box_closes(); + self.state = "close"; + break; + case "leaving": + self showzbarrierpiece( 1 ); + self thread magic_box_leaves(); + self.state = "leaving"; + break; + default: + if ( isDefined( level.custom_magicbox_state_handler ) ) + { + self [[ level.custom_magicbox_state_handler ]]( state ); + } + break; + } +} + +magicbox_host_migration() +{ + level endon( "end_game" ); + level notify( "mb_hostmigration" ); + level endon( "mb_hostmigration" ); + while ( 1 ) + { + level waittill( "host_migration_end" ); + while ( !isDefined( level.chests ) ) + { + continue; + } + _a2101 = level.chests; + _k2101 = getFirstArrayKey( _a2101 ); + while ( isDefined( _k2101 ) ) + { + chest = _a2101[ _k2101 ]; + if ( !is_true( chest.hidden ) ) + { + if ( isDefined( chest ) && isDefined( chest.pandora_light ) ) + { + playfxontag( level._effect[ "lght_marker" ], chest.pandora_light, "tag_origin" ); + } + } + wait_network_frame(); + _k2101 = getNextArrayKey( _a2101, _k2101 ); + } + } +} + diff --git a/patch_zm/maps/mp/zombies/_zm_perks.gsc b/patch_zm/maps/mp/zombies/_zm_perks.gsc new file mode 100644 index 0000000..105c5cf --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_perks.gsc @@ -0,0 +1,4163 @@ +#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; + } + 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"); + for(i = 0; i < pos.size; i++) + { + perk = pos[i].script_noteworthy; + if(isdefined(perk) && isdefined(pos[i].model)) + { + use_trigger = spawn("trigger_radius_use", pos[i].origin + VectorScale( 0, 0, 1, 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; + case 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); + } + } + } +} + +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/patch_zm/maps/mp/zombies/_zm_powerups.gsc b/patch_zm/maps/mp/zombies/_zm_powerups.gsc new file mode 100644 index 0000000..0c23f2c --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_powerups.gsc @@ -0,0 +1,2965 @@ +#include maps/mp/zombies/_zm_melee_weapon; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_blockers; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_pers_upgrades; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + precacheshader( "specialty_doublepoints_zombies" ); + precacheshader( "specialty_instakill_zombies" ); + precacheshader( "specialty_firesale_zombies" ); + precacheshader( "zom_icon_bonfire" ); + precacheshader( "zom_icon_minigun" ); + precacheshader( "black" ); + set_zombie_var( "zombie_insta_kill", 0, undefined, undefined, 1 ); + set_zombie_var( "zombie_point_scalar", 1, undefined, undefined, 1 ); + set_zombie_var( "zombie_drop_item", 0 ); + set_zombie_var( "zombie_timer_offset", 350 ); + set_zombie_var( "zombie_timer_offset_interval", 30 ); + set_zombie_var( "zombie_powerup_fire_sale_on", 0 ); + set_zombie_var( "zombie_powerup_fire_sale_time", 30 ); + set_zombie_var( "zombie_powerup_bonfire_sale_on", 0 ); + set_zombie_var( "zombie_powerup_bonfire_sale_time", 30 ); + set_zombie_var( "zombie_powerup_insta_kill_on", 0, undefined, undefined, 1 ); + set_zombie_var( "zombie_powerup_insta_kill_time", 30, undefined, undefined, 1 ); + set_zombie_var( "zombie_powerup_point_doubler_on", 0, undefined, undefined, 1 ); + set_zombie_var( "zombie_powerup_point_doubler_time", 30, undefined, undefined, 1 ); + set_zombie_var( "zombie_powerup_drop_increment", 2000 ); + set_zombie_var( "zombie_powerup_drop_max_per_round", 4 ); + onplayerconnect_callback( ::init_player_zombie_vars ); + level._effect[ "powerup_on" ] = loadfx( "misc/fx_zombie_powerup_on" ); + level._effect[ "powerup_off" ] = loadfx( "misc/fx_zombie_powerup_off" ); + level._effect[ "powerup_grabbed" ] = loadfx( "misc/fx_zombie_powerup_grab" ); + level._effect[ "powerup_grabbed_wave" ] = loadfx( "misc/fx_zombie_powerup_wave" ); + if ( isDefined( level.using_zombie_powerups ) && level.using_zombie_powerups ) + { + level._effect[ "powerup_on_red" ] = loadfx( "misc/fx_zombie_powerup_on_red" ); + level._effect[ "powerup_grabbed_red" ] = loadfx( "misc/fx_zombie_powerup_red_grab" ); + level._effect[ "powerup_grabbed_wave_red" ] = loadfx( "misc/fx_zombie_powerup_red_wave" ); + } + level._effect[ "powerup_on_solo" ] = loadfx( "misc/fx_zombie_powerup_solo_on" ); + level._effect[ "powerup_grabbed_solo" ] = loadfx( "misc/fx_zombie_powerup_solo_grab" ); + level._effect[ "powerup_grabbed_wave_solo" ] = loadfx( "misc/fx_zombie_powerup_solo_wave" ); + level._effect[ "powerup_on_caution" ] = loadfx( "misc/fx_zombie_powerup_caution_on" ); + level._effect[ "powerup_grabbed_caution" ] = loadfx( "misc/fx_zombie_powerup_caution_grab" ); + level._effect[ "powerup_grabbed_wave_caution" ] = loadfx( "misc/fx_zombie_powerup_caution_wave" ); + init_powerups(); + if ( !level.enable_magic ) + { + return; + } + thread watch_for_drop(); + thread setup_firesale_audio(); + thread setup_bonfiresale_audio(); + level.use_new_carpenter_func = ::start_carpenter_new; + level.board_repair_distance_squared = 562500; +} + +init_powerups() +{ + flag_init( "zombie_drop_powerups" ); + if ( isDefined( level.enable_magic ) && level.enable_magic ) + { + flag_set( "zombie_drop_powerups" ); + } + if ( !isDefined( level.active_powerups ) ) + { + level.active_powerups = []; + } + if ( !isDefined( level.zombie_powerup_array ) ) + { + level.zombie_powerup_array = []; + } + if ( !isDefined( level.zombie_special_drop_array ) ) + { + level.zombie_special_drop_array = []; + } + add_zombie_powerup( "nuke", "zombie_bomb", &"ZOMBIE_POWERUP_NUKE", ::func_should_always_drop, 0, 0, 0, "misc/fx_zombie_mini_nuke_hotness" ); + add_zombie_powerup( "insta_kill", "zombie_skull", &"ZOMBIE_POWERUP_INSTA_KILL", ::func_should_always_drop, 0, 0, 0, undefined, "powerup_instant_kill", "zombie_powerup_insta_kill_time", "zombie_powerup_insta_kill_on" ); + add_zombie_powerup( "full_ammo", "zombie_ammocan", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_always_drop, 0, 0, 0 ); + add_zombie_powerup( "double_points", "zombie_x2_icon", &"ZOMBIE_POWERUP_DOUBLE_POINTS", ::func_should_always_drop, 0, 0, 0, undefined, "powerup_double_points", "zombie_powerup_point_doubler_time", "zombie_powerup_point_doubler_on" ); + add_zombie_powerup( "carpenter", "zombie_carpenter", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_drop_carpenter, 0, 0, 0 ); + add_zombie_powerup( "fire_sale", "zombie_firesale", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_drop_fire_sale, 0, 0, 0, undefined, "powerup_fire_sale", "zombie_powerup_fire_sale_time", "zombie_powerup_fire_sale_on" ); + add_zombie_powerup( "bonfire_sale", "zombie_pickup_bonfire", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_never_drop, 0, 0, 0, undefined, "powerup_bon_fire", "zombie_powerup_bonfire_sale_time", "zombie_powerup_bonfire_sale_on" ); + add_zombie_powerup( "minigun", "zombie_pickup_minigun", &"ZOMBIE_POWERUP_MINIGUN", ::func_should_drop_minigun, 1, 0, 0, undefined, "powerup_mini_gun", "zombie_powerup_minigun_time", "zombie_powerup_minigun_on" ); + add_zombie_powerup( "free_perk", "zombie_pickup_perk_bottle", &"ZOMBIE_POWERUP_FREE_PERK", ::func_should_never_drop, 0, 0, 0 ); + add_zombie_powerup( "tesla", "zombie_pickup_minigun", &"ZOMBIE_POWERUP_MINIGUN", ::func_should_never_drop, 1, 0, 0, undefined, "powerup_tesla", "zombie_powerup_tesla_time", "zombie_powerup_tesla_on" ); + add_zombie_powerup( "random_weapon", "zombie_pickup_minigun", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_never_drop, 1, 0, 0 ); + add_zombie_powerup( "bonus_points_player", "zombie_z_money_icon", &"ZOMBIE_POWERUP_BONUS_POINTS", ::func_should_never_drop, 1, 0, 0 ); + add_zombie_powerup( "bonus_points_team", "zombie_z_money_icon", &"ZOMBIE_POWERUP_BONUS_POINTS", ::func_should_never_drop, 0, 0, 0 ); + add_zombie_powerup( "lose_points_team", "zombie_z_money_icon", &"ZOMBIE_POWERUP_LOSE_POINTS", ::func_should_never_drop, 0, 0, 1 ); + add_zombie_powerup( "lose_perk", "zombie_pickup_perk_bottle", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_never_drop, 0, 0, 1 ); + add_zombie_powerup( "empty_clip", "zombie_ammocan", &"ZOMBIE_POWERUP_MAX_AMMO", ::func_should_never_drop, 0, 0, 1 ); + add_zombie_powerup( "insta_kill_ug", "zombie_skull", &"ZOMBIE_POWERUP_INSTA_KILL", ::func_should_never_drop, 1, 0, 0, undefined, "powerup_instant_kill_ug", "zombie_powerup_insta_kill_ug_time", "zombie_powerup_insta_kill_ug_on", 5000 ); + if ( isDefined( level.level_specific_init_powerups ) ) + { + [[ level.level_specific_init_powerups ]](); + } + randomize_powerups(); + level.zombie_powerup_index = 0; + randomize_powerups(); + level.rare_powerups_active = 0; + level.firesale_vox_firstime = 0; + level thread powerup_hud_monitor(); + if ( isDefined( level.quantum_bomb_register_result_func ) ) + { + [[ level.quantum_bomb_register_result_func ]]( "random_powerup", ::quantum_bomb_random_powerup_result, 5, level.quantum_bomb_in_playable_area_validation_func ); + [[ level.quantum_bomb_register_result_func ]]( "random_zombie_grab_powerup", ::quantum_bomb_random_zombie_grab_powerup_result, 5, level.quantum_bomb_in_playable_area_validation_func ); + [[ level.quantum_bomb_register_result_func ]]( "random_weapon_powerup", ::quantum_bomb_random_weapon_powerup_result, 60, level.quantum_bomb_in_playable_area_validation_func ); + [[ level.quantum_bomb_register_result_func ]]( "random_bonus_or_lose_points_powerup", ::quantum_bomb_random_bonus_or_lose_points_powerup_result, 25, level.quantum_bomb_in_playable_area_validation_func ); + } + registerclientfield( "scriptmover", "powerup_fx", 1000, 3, "int" ); +} + +init_player_zombie_vars() +{ + self.zombie_vars[ "zombie_powerup_minigun_on" ] = 0; + self.zombie_vars[ "zombie_powerup_minigun_time" ] = 0; + self.zombie_vars[ "zombie_powerup_tesla_on" ] = 0; + self.zombie_vars[ "zombie_powerup_tesla_time" ] = 0; + self.zombie_vars[ "zombie_powerup_insta_kill_ug_on" ] = 0; + self.zombie_vars[ "zombie_powerup_insta_kill_ug_time" ] = 18; +} + +set_weapon_ignore_max_ammo( str_weapon ) +{ + if ( !isDefined( level.zombie_weapons_no_max_ammo ) ) + { + level.zombie_weapons_no_max_ammo = []; + } + level.zombie_weapons_no_max_ammo[ str_weapon ] = 1; +} + +powerup_hud_monitor() +{ + flag_wait( "start_zombie_round_logic" ); + if ( isDefined( level.current_game_module ) && level.current_game_module == 2 ) + { + return; + } + flashing_timers = []; + flashing_values = []; + flashing_timer = 10; + flashing_delta_time = 0; + flashing_is_on = 0; + flashing_value = 3; + flashing_min_timer = 0.15; + while ( flashing_timer >= flashing_min_timer ) + { + if ( flashing_timer < 5 ) + { + flashing_delta_time = 0.1; + } + else + { + flashing_delta_time = 0.2; + } + if ( flashing_is_on ) + { + flashing_timer = flashing_timer - flashing_delta_time - 0.05; + flashing_value = 2; + } + else + { + flashing_timer -= flashing_delta_time; + flashing_value = 3; + } + flashing_timers[ flashing_timers.size ] = flashing_timer; + flashing_values[ flashing_values.size ] = flashing_value; + flashing_is_on = !flashing_is_on; + } + client_fields = []; + powerup_keys = getarraykeys( level.zombie_powerups ); + powerup_key_index = 0; + while ( powerup_key_index < powerup_keys.size ) + { + if ( isDefined( level.zombie_powerups[ powerup_keys[ powerup_key_index ] ].client_field_name ) ) + { + powerup_name = powerup_keys[ powerup_key_index ]; + client_fields[ powerup_name ] = spawnstruct(); + client_fields[ powerup_name ].client_field_name = level.zombie_powerups[ powerup_name ].client_field_name; + client_fields[ powerup_name ].solo = level.zombie_powerups[ powerup_name ].solo; + client_fields[ powerup_name ].time_name = level.zombie_powerups[ powerup_name ].time_name; + client_fields[ powerup_name ].on_name = level.zombie_powerups[ powerup_name ].on_name; + } + powerup_key_index++; + } + if ( getDvar( "_zm_powerupsReturnEarly" ) ) + { + return; + } + client_field_keys = getarraykeys( client_fields ); + + while ( 1 ) + { + wait 0.05; + waittillframeend; + players = get_players(); + playerindex = 0; + while ( playerindex < players.size ) + { + client_field_key_index = 0; + while ( client_field_key_index < client_field_keys.size ) + { + player = players[ playerindex ]; + if ( isDefined( level.powerup_player_valid ) ) + { + if ( !( [[ level.powerup_player_valid ]]( player ) ) ) + { + client_field_key_index++; + continue; + } + } + client_field_name_array = client_field_keys[client_field_key_index]; + client_field_name = client_fields[client_field_name_array].client_field_name; + time_name = client_fields[client_field_name_array].time_name; + on_name = client_fields[client_field_name_array].on_name; + powerup_timer = undefined; + powerup_on = undefined; + if ( client_fields[ client_field_keys[ client_field_key_index ] ].solo ) + { + if ( isDefined( player._show_solo_hud ) && player._show_solo_hud == 1 ) + { + powerup_timer = player.zombie_vars[ time_name ]; + powerup_on = player.zombie_vars[ on_name ]; + } + } + else if ( isDefined( level.zombie_vars[ player.team ][ time_name ] ) ) + { + powerup_timer = level.zombie_vars[ player.team ][ time_name ]; + powerup_on = level.zombie_vars[ player.team ][ on_name ]; + } + else + { + if ( isDefined( level.zombie_vars[ time_name ] ) ) + { + powerup_timer = level.zombie_vars[ time_name ]; + powerup_on = level.zombie_vars[ on_name ]; + } + } + if ( isDefined( powerup_timer ) && isDefined( powerup_on ) ) + { + player set_clientfield_powerups( client_field_name, powerup_timer, powerup_on, flashing_timers, flashing_values ); + client_field_key_index++; + continue; + } + else + { + player setclientfieldtoplayer( client_field_name, 0 ); + } + client_field_key_index++; + } + playerindex++; + } + } +} + +set_clientfield_powerups( clientfield_name, powerup_timer, powerup_on, flashing_timers, flashing_values ) +{ + if ( powerup_on ) + { + if ( powerup_timer < 10 ) + { + flashing_value = 3; + i = flashing_timers.size - 1; + while ( i > 0 ) + { + if ( powerup_timer < flashing_timers[ i ] ) + { + flashing_value = flashing_values[ i ]; + break; + } + else + { + i--; + + } + } + self setclientfieldtoplayer( clientfield_name, flashing_value ); + } + else + { + self setclientfieldtoplayer( clientfield_name, 1 ); + } + } + else + { + self setclientfieldtoplayer( clientfield_name, 0 ); + } +} + +randomize_powerups() +{ + level.zombie_powerup_array = array_randomize( level.zombie_powerup_array ); +} + +get_next_powerup() +{ + powerup = level.zombie_powerup_array[ level.zombie_powerup_index ]; + level.zombie_powerup_index++; + if ( level.zombie_powerup_index >= level.zombie_powerup_array.size ) + { + level.zombie_powerup_index = 0; + randomize_powerups(); + } + return powerup; +} + +get_valid_powerup() +{ + if ( isDefined( level.zombie_powerup_boss ) ) + { + i = level.zombie_powerup_boss; + level.zombie_powerup_boss = undefined; + return level.zombie_powerup_array[ i ]; + } + if ( isDefined( level.zombie_powerup_ape ) ) + { + powerup = level.zombie_powerup_ape; + level.zombie_powerup_ape = undefined; + return powerup; + } + powerup = get_next_powerup(); + while ( 1 ) + { + while ( !( [[ level.zombie_powerups[ powerup ].func_should_drop_with_regular_powerups ]]() ) ) + { + powerup = get_next_powerup(); + } + return powerup; + } +} + +minigun_no_drop() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].zombie_vars[ "zombie_powerup_minigun_on" ] == 1 ) + { + return 1; + } + i++; + } + if ( !flag( "power_on" ) ) + { + if ( flag( "solo_game" ) ) + { + if ( level.solo_lives_given == 0 ) + { + return 1; + } + } + else + { + return 1; + } + } + return 0; +} + +get_num_window_destroyed() +{ + num = 0; + i = 0; + while ( i < level.exterior_goals.size ) + { + if ( all_chunks_destroyed( level.exterior_goals[ i ], level.exterior_goals[ i ].barrier_chunks ) ) + { + num += 1; + } + i++; + } + return num; +} + +watch_for_drop() +{ + flag_wait( "start_zombie_round_logic" ); + flag_wait( "begin_spawning" ); + players = get_players(); + score_to_drop = ( players.size * level.zombie_vars[ "zombie_score_start_" + players.size + "p" ] ) + level.zombie_vars[ "zombie_powerup_drop_increment" ]; + while ( 1 ) + { + flag_wait( "zombie_drop_powerups" ); + players = get_players(); + curr_total_score = 0; + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ].score_total ) ) + { + curr_total_score += players[ i ].score_total; + } + i++; + } + if ( curr_total_score > score_to_drop ) + { + level.zombie_vars[ "zombie_powerup_drop_increment" ] *= 1.14; + score_to_drop = curr_total_score + level.zombie_vars[ "zombie_powerup_drop_increment" ]; + level.zombie_vars[ "zombie_drop_item" ] = 1; + } + wait 0.5; + } + +} + +add_zombie_powerup( powerup_name, model_name, hint, func_should_drop_with_regular_powerups, solo, caution, zombie_grabbable, fx, client_field_name, time_name, on_name, clientfield_version ) +{ + if ( !isDefined( clientfield_version ) ) + { + clientfield_version = 1; + } + if ( isDefined( level.zombie_include_powerups ) && !isDefined( level.zombie_include_powerups[ powerup_name ] ) ) + { + return; + } + precachemodel( model_name ); + precachestring( hint ); + struct = spawnstruct(); + if ( !isDefined( level.zombie_powerups ) ) + { + level.zombie_powerups = []; + } + struct.powerup_name = powerup_name; + struct.model_name = model_name; + struct.weapon_classname = "script_model"; + struct.hint = hint; + struct.func_should_drop_with_regular_powerups = func_should_drop_with_regular_powerups; + struct.solo = solo; + struct.caution = caution; + struct.zombie_grabbable = zombie_grabbable; + if ( isDefined( fx ) ) + { + struct.fx = loadfx( fx ); + } + level.zombie_powerups[ powerup_name ] = struct; + level.zombie_powerup_array[ level.zombie_powerup_array.size ] = powerup_name; + add_zombie_special_drop( powerup_name ); + if ( !level.createfx_enabled ) + { + if ( isDefined( client_field_name ) ) + { + registerclientfield( "toplayer", client_field_name, clientfield_version, 2, "int" ); + struct.client_field_name = client_field_name; + struct.time_name = time_name; + struct.on_name = on_name; + } + } +} + +powerup_set_can_pick_up_in_last_stand( powerup_name, b_can_pick_up ) +{ + level.zombie_powerups[ powerup_name ].can_pick_up_in_last_stand = b_can_pick_up; +} + +add_zombie_special_drop( powerup_name ) +{ + level.zombie_special_drop_array[ level.zombie_special_drop_array.size ] = powerup_name; +} + +include_zombie_powerup( powerup_name ) +{ + if ( !isDefined( level.zombie_include_powerups ) ) + { + level.zombie_include_powerups = []; + } + level.zombie_include_powerups[ powerup_name ] = 1; +} + +powerup_round_start() +{ + level.powerup_drop_count = 0; +} + +powerup_drop( drop_point ) +{ + if ( level.powerup_drop_count >= level.zombie_vars[ "zombie_powerup_drop_max_per_round" ] ) + { + return; + } + if ( !isDefined( level.zombie_include_powerups ) || level.zombie_include_powerups.size == 0 ) + { + return; + } + rand_drop = randomint( 100 ); + if ( rand_drop > 2 ) + { + if ( !level.zombie_vars[ "zombie_drop_item" ] ) + { + return; + } + debug = "score"; + } + else + { + debug = "random"; + } + playable_area = getentarray( "player_volume", "script_noteworthy" ); + level.powerup_drop_count++; + powerup = maps/mp/zombies/_zm_net::network_safe_spawn( "powerup", 1, "script_model", drop_point + vectorScale( ( 0, 0, 0 ), 40 ) ); + valid_drop = 0; + i = 0; + while ( i < playable_area.size ) + { + if ( powerup istouching( playable_area[ i ] ) ) + { + valid_drop = 1; + } + i++; + } + if ( valid_drop && level.rare_powerups_active ) + { + pos = ( drop_point[ 0 ], drop_point[ 1 ], drop_point[ 2 ] + 42 ); + if ( check_for_rare_drop_override( pos ) ) + { + level.zombie_vars[ "zombie_drop_item" ] = 0; + valid_drop = 0; + } + } + if ( !valid_drop ) + { + level.powerup_drop_count--; + + powerup delete(); + return; + } + powerup powerup_setup(); + print_powerup_drop( powerup.powerup_name, debug ); + powerup thread powerup_timeout(); + powerup thread powerup_wobble(); + powerup thread powerup_grab(); + powerup thread powerup_move(); + powerup thread powerup_emp(); + level.zombie_vars[ "zombie_drop_item" ] = 0; + level notify( "powerup_dropped" ); +} + +specific_powerup_drop( powerup_name, drop_spot, powerup_team, powerup_location ) +{ + powerup = maps/mp/zombies/_zm_net::network_safe_spawn( "powerup", 1, "script_model", drop_spot + vectorScale( ( 0, 0, 0 ), 40 ) ); + level notify( "powerup_dropped" ); + if ( isDefined( powerup ) ) + { + powerup powerup_setup( powerup_name, powerup_team, powerup_location ); + powerup thread powerup_timeout(); + powerup thread powerup_wobble(); + powerup thread powerup_grab( powerup_team ); + powerup thread powerup_move(); + powerup thread powerup_emp(); + return powerup; + } +} + +quantum_bomb_random_powerup_result( position ) +{ + if ( !isDefined( level.zombie_include_powerups ) || !level.zombie_include_powerups.size ) + { + return; + } + keys = getarraykeys( level.zombie_include_powerups ); + while ( keys.size ) + { + index = randomint( keys.size ); + if ( !level.zombie_powerups[ keys[ index ] ].zombie_grabbable ) + { + skip = 0; + switch( keys[ index ] ) + { + case "bonus_points_player": + case "bonus_points_team": + case "random_weapon": + skip = 1; + break; + case "fire_sale": + case "full_ammo": + case "insta_kill": + case "minigun": + if ( randomint( 4 ) ) + { + skip = 1; + } + break; + case "bonfire_sale": + case "free_perk": + case "tesla": + if ( randomint( 20 ) ) + { + skip = 1; + } + break; + default: + } + while ( skip ) + { + arrayremovevalue( keys, keys[ index ] ); + } + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); + level specific_powerup_drop( keys[ index ], position ); + return; + continue; + } + else + { + arrayremovevalue( keys, keys[ index ] ); + } + } +} + +quantum_bomb_random_zombie_grab_powerup_result( position ) +{ + if ( !isDefined( level.zombie_include_powerups ) || !level.zombie_include_powerups.size ) + { + return; + } + keys = getarraykeys( level.zombie_include_powerups ); + while ( keys.size ) + { + index = randomint( keys.size ); + if ( level.zombie_powerups[ keys[ index ] ].zombie_grabbable ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_bad" ); + [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); + level specific_powerup_drop( keys[ index ], position ); + return; + continue; + } + else + { + arrayremovevalue( keys, keys[ index ] ); + } + } +} + +quantum_bomb_random_weapon_powerup_result( position ) +{ + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); + level specific_powerup_drop( "random_weapon", position ); +} + +quantum_bomb_random_bonus_or_lose_points_powerup_result( position ) +{ + rand = randomint( 10 ); + powerup = "bonus_points_team"; + switch( rand ) + { + case 0: + case 1: + powerup = "lose_points_team"; + if ( isDefined( level.zombie_include_powerups[ powerup ] ) ) + { + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_bad" ); + break; + } + case 2: + case 3: + case 4: + powerup = "bonus_points_player"; + if ( isDefined( level.zombie_include_powerups[ powerup ] ) ) + { + break; + } + default: + powerup = "bonus_points_team"; + break; + } + [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); + level specific_powerup_drop( powerup, position ); +} + +special_powerup_drop( drop_point ) +{ + if ( !isDefined( level.zombie_include_powerups ) || level.zombie_include_powerups.size == 0 ) + { + return; + } + powerup = spawn( "script_model", drop_point + vectorScale( ( 0, 0, 0 ), 40 ) ); + playable_area = getentarray( "player_volume", "script_noteworthy" ); + valid_drop = 0; + i = 0; + while ( i < playable_area.size ) + { + if ( powerup istouching( playable_area[ i ] ) ) + { + valid_drop = 1; + break; + } + else + { + i++; + } + } + if ( !valid_drop ) + { + powerup delete(); + return; + } + powerup special_drop_setup(); +} + +cleanup_random_weapon_list() +{ + self waittill( "death" ); + arrayremovevalue( level.random_weapon_powerups, self ); +} + +powerup_setup( powerup_override, powerup_team, powerup_location ) +{ + powerup = undefined; + if ( !isDefined( powerup_override ) ) + { + powerup = get_valid_powerup(); + } + else + { + powerup = powerup_override; + if ( powerup == "tesla" && tesla_powerup_active() ) + { + powerup = "minigun"; + } + } + struct = level.zombie_powerups[ powerup ]; + if ( powerup == "random_weapon" ) + { + players = get_players(); + self.weapon = maps/mp/zombies/_zm_magicbox::treasure_chest_chooseweightedrandomweapon( players[ 0 ] ); + self.base_weapon = self.weapon; + if ( !isDefined( level.random_weapon_powerups ) ) + { + level.random_weapon_powerups = []; + } + level.random_weapon_powerups[ level.random_weapon_powerups.size ] = self; + self thread cleanup_random_weapon_list(); + if ( isDefined( level.zombie_weapons[ self.weapon ].upgrade_name ) && !randomint( 4 ) ) + { + self.weapon = level.zombie_weapons[ self.weapon ].upgrade_name; + } + self setmodel( getweaponmodel( self.weapon ) ); + self useweaponhidetags( self.weapon ); + offsetdw = vectorScale( ( 0, 0, 0 ), 3 ); + self.worldgundw = undefined; + if ( maps/mp/zombies/_zm_magicbox::weapon_is_dual_wield( self.weapon ) ) + { + self.worldgundw = spawn( "script_model", self.origin + offsetdw ); + self.worldgundw.angles = self.angles; + self.worldgundw setmodel( maps/mp/zombies/_zm_magicbox::get_left_hand_weapon_model_name( self.weapon ) ); + self.worldgundw useweaponhidetags( self.weapon ); + self.worldgundw linkto( self, "tag_weapon", offsetdw, ( 0, 0, 0 ) ); + } + } + else + { + self setmodel( struct.model_name ); + } + maps/mp/_demo::bookmark( "zm_powerup_dropped", getTime(), undefined, undefined, 1 ); + playsoundatposition( "zmb_spawn_powerup", self.origin ); + if ( isDefined( powerup_team ) ) + { + self.powerup_team = powerup_team; + } + if ( isDefined( powerup_location ) ) + { + self.powerup_location = powerup_location; + } + self.powerup_name = struct.powerup_name; + self.hint = struct.hint; + self.solo = struct.solo; + self.caution = struct.caution; + self.zombie_grabbable = struct.zombie_grabbable; + self.func_should_drop_with_regular_powerups = struct.func_should_drop_with_regular_powerups; + if ( isDefined( struct.fx ) ) + { + self.fx = struct.fx; + } + if ( isDefined( struct.can_pick_up_in_last_stand ) ) + { + self.can_pick_up_in_last_stand = struct.can_pick_up_in_last_stand; + } + self playloopsound( "zmb_spawn_powerup_loop" ); + level.active_powerups[ level.active_powerups.size ] = self; +} + +special_drop_setup() +{ + powerup = undefined; + is_powerup = 1; + if ( level.round_number <= 10 ) + { + powerup = get_valid_powerup(); + } + else + { + powerup = level.zombie_special_drop_array[ randomint( level.zombie_special_drop_array.size ) ]; + if ( level.round_number > 15 && randomint( 100 ) < ( ( level.round_number - 15 ) * 5 ) ) + { + powerup = "nothing"; + } + } + switch( powerup ) + { + case "all_revive": + case "bonfire_sale": + case "bonus_points_player": + case "bonus_points_team": + case "carpenter": + case "double_points": + case "empty_clip": + case "fire_sale": + case "free_perk": + case "insta_kill": + case "lose_perk": + case "lose_points_team": + case "minigun": + case "nuke": + case "random_weapon": + case "tesla": + case "zombie_blood": + break; + case "full_ammo": + if ( level.round_number > 10 && randomint( 100 ) < ( ( level.round_number - 10 ) * 5 ) ) + { + powerup = level.zombie_powerup_array[ randomint( level.zombie_powerup_array.size ) ]; + } + break; + case "dog": + if ( level.round_number >= 15 ) + { + is_powerup = 0; + dog_spawners = getentarray( "special_dog_spawner", "targetname" ); + thread play_sound_2d( "sam_nospawn" ); + } + else + { + powerup = get_valid_powerup(); + } + break; + default: + if ( isDefined( level._zombiemode_special_drop_setup ) ) + { + is_powerup = [[ level._zombiemode_special_drop_setup ]]( powerup ); + } + else + { + is_powerup = 0; + playfx( level._effect[ "lightning_dog_spawn" ], self.origin ); + playsoundatposition( "pre_spawn", self.origin ); + wait 1.5; + playsoundatposition( "zmb_bolt", self.origin ); + earthquake( 0.5, 0.75, self.origin, 1000 ); + playrumbleonposition( "explosion_generic", self.origin ); + playsoundatposition( "spawn", self.origin ); + wait 1; + thread play_sound_2d( "sam_nospawn" ); + self delete(); + } + } + if ( is_powerup ) + { + playfx( level._effect[ "lightning_dog_spawn" ], self.origin ); + playsoundatposition( "pre_spawn", self.origin ); + wait 1.5; + playsoundatposition( "zmb_bolt", self.origin ); + earthquake( 0.5, 0.75, self.origin, 1000 ); + playrumbleonposition( "explosion_generic", self.origin ); + playsoundatposition( "spawn", self.origin ); + self powerup_setup( powerup ); + self thread powerup_timeout(); + self thread powerup_wobble(); + self thread powerup_grab(); + self thread powerup_move(); + self thread powerup_emp(); + } +} + +powerup_zombie_grab_trigger_cleanup( trigger ) +{ + self waittill_any( "powerup_timedout", "powerup_grabbed", "hacked" ); + trigger delete(); +} + +powerup_zombie_grab( powerup_team ) +{ + self endon( "powerup_timedout" ); + self endon( "powerup_grabbed" ); + self endon( "hacked" ); + zombie_grab_trigger = spawn( "trigger_radius", self.origin - vectorScale( ( 0, 0, 0 ), 40 ), 4, 32, 72 ); + zombie_grab_trigger enablelinkto(); + zombie_grab_trigger linkto( self ); + zombie_grab_trigger setteamfortrigger( level.zombie_team ); + self thread powerup_zombie_grab_trigger_cleanup( zombie_grab_trigger ); + poi_dist = 300; + if ( isDefined( level._zombie_grabbable_poi_distance_override ) ) + { + poi_dist = level._zombie_grabbable_poi_distance_override; + } + zombie_grab_trigger create_zombie_point_of_interest( poi_dist, 2, 0, 1, undefined, undefined, powerup_team ); + while ( isDefined( self ) ) + { + zombie_grab_trigger waittill( "trigger", who ); + if ( isDefined( level._powerup_grab_check ) ) + { + while ( !( self [[ level._powerup_grab_check ]]( who ) ) ) + { + continue; + } + } + else if ( !isDefined( who ) || !isai( who ) ) + { + continue; + } + playfx( level._effect[ "powerup_grabbed_red" ], self.origin ); + playfx( level._effect[ "powerup_grabbed_wave_red" ], self.origin ); + switch( self.powerup_name ) + { + case "lose_points_team": + level thread lose_points_team_powerup( self ); + players = get_players(); + players[ randomintrange( 0, players.size ) ] thread powerup_vo( "lose_points" ); + break; + case "lose_perk": + level thread lose_perk_powerup( self ); + break; + case "empty_clip": + level thread empty_clip_powerup( self ); + break; + default: + if ( isDefined( level._zombiemode_powerup_zombie_grab ) ) + { + level thread [[ level._zombiemode_powerup_zombie_grab ]]( self ); + } + if ( isDefined( level._game_mode_powerup_zombie_grab ) ) + { + level thread [[ level._game_mode_powerup_zombie_grab ]]( self, who ); + } + else + { + } + break; + } + level thread maps/mp/zombies/_zm_audio::do_announcer_playvox( "powerup", self.powerup_name ); + wait 0.1; + playsoundatposition( "zmb_powerup_grabbed", self.origin ); + self stoploopsound(); + self powerup_delete(); + self notify( "powerup_grabbed" ); + } +} + +powerup_grab(powerup_team) +{ + if ( isdefined( self ) && self.zombie_grabbable ) + { + self thread powerup_zombie_grab(powerup_team); + return; + } + + self endon ("powerup_timedout"); + self endon ("powerup_grabbed"); + + range_squared = 64 * 64; + while (isdefined(self)) + { + players = GET_PLAYERS(); + + for (i = 0; i < players.size; i++) + { + // Don't let them grab the minigun, tesla, or random weapon if they're downed or reviving + // due to weapon switching issues. + if ( self.powerup_name != "minigun" && self.powerup_name != "tesla" && self.powerup_name != "random_weapon" && self.powerup_name == "meat_stink" || players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ] usebuttonpressed() && players[ i ] in_revive_trigger() ) + { + continue; + } + + if ( DistanceSquared( players[i].origin, self.origin ) < range_squared ) + { + if( IsDefined( level.zombie_powerup_grab_func ) ) + { + level thread [[level.zombie_powerup_grab_func]](); + } + else + { + switch (self.powerup_name) + { + case "nuke": + level thread nuke_powerup( self, players[i].team ); + + //chrisp - adding powerup VO sounds + players[i] thread powerup_vo("nuke"); + zombies = getaiarray( level.zombie_team ); + //players[i].zombie_nuked = get_array_of_closest( self.origin, zombies ); + players[i].zombie_nuked = ArraySort( zombies, self.origin ); + players[i] notify("nuke_triggered"); + + break; + case "full_ammo": + level thread full_ammo_powerup( self ,players[i] ); + players[i] thread powerup_vo("full_ammo"); + break; + case "double_points": + level thread double_points_powerup( self, players[i] ); + players[i] thread powerup_vo("double_points"); + break; + case "insta_kill": + level thread insta_kill_powerup( self,players[i] ); + players[i] thread powerup_vo("insta_kill"); + break; + case "carpenter": + if(isDefined(level.use_new_carpenter_func)) + { + level thread [[level.use_new_carpenter_func]](self.origin); + } + else + { + level thread start_carpenter( self.origin ); + } + players[i] thread powerup_vo("carpenter"); + break; + + case "fire_sale": + level thread start_fire_sale( self ); + players[i] thread powerup_vo("firesale"); + break; + + case "bonfire_sale": + level thread start_bonfire_sale( self ); + players[i] thread powerup_vo("firesale"); + break; + + case "minigun": + level thread minigun_weapon_powerup( players[i] ); + players[i] thread powerup_vo( "minigun" ); + break; + + case "free_perk": + level thread free_perk_powerup( self ); + //players[i] thread powerup_vo( "insta_kill" ); + break; + + case "tesla": + level thread tesla_weapon_powerup( players[i] ); + players[i] thread powerup_vo( "tesla" ); // TODO: Audio should uncomment this once the sounds have been set up + break; + + case "random_weapon": + if ( !level random_weapon_powerup( self, players[i] ) ) + { + continue; + } + // players[i] thread powerup_vo( "random_weapon" ); // TODO: Audio should uncomment this once the sounds have been set up + break; + + case "bonus_points_player": + level thread bonus_points_player_powerup( self, players[i] ); + players[i] thread powerup_vo( "bonus_points_solo" ); // TODO: Audio should uncomment this once the sounds have been set up + break; + + case "bonus_points_team": + level thread bonus_points_team_powerup( self ); + players[i] thread powerup_vo( "bonus_points_team" ); // TODO: Audio should uncomment this once the sounds have been set up + break; + + case "teller_withdrawl": + level thread teller_withdrawl(self ,players[i]); + //TODO - play some sound/vo stuff here? + break; + + default: + // RAVEN BEGIN bhackbarth: callback for level specific powerups + if ( IsDefined( level._zombiemode_powerup_grab ) ) + { + level thread [[ level._zombiemode_powerup_grab ]]( self, players[i] ); + } + // RAVEN END + else + { + } + + break; + + } + } + + maps\mp\_demo::bookmark( "zm_player_powerup_grabbed", gettime(), players[i] ); + + if( should_award_stat ( self.powerup_name )) //don't do this for things that aren't really a powerup + { + //track # of picked up powerups/drops for the player + players[i] maps\mp\zombies\_zm_stats::increment_client_stat( "drops" ); + players[i] maps\mp\zombies\_zm_stats::increment_client_stat( self.powerup_name + "_pickedup" ); + } + + if ( self.solo ) + { + playfx( level._effect["powerup_grabbed_solo"], self.origin ); + playfx( level._effect["powerup_grabbed_wave_solo"], self.origin ); + } + else if ( self.caution ) + { + playfx( level._effect["powerup_grabbed_caution"], self.origin ); + playfx( level._effect["powerup_grabbed_wave_caution"], self.origin ); + } + else + { + playfx( level._effect["powerup_grabbed"], self.origin ); + playfx( level._effect["powerup_grabbed_wave"], self.origin ); + } + + if ( is_true( self.stolen ) ) + { + level notify( "monkey_see_monkey_dont_achieved" ); + } + + // RAVEN BEGIN bhackbarth: since there is a wait here, flag the powerup as being taken + self.claimed = true; + self.power_up_grab_player = players[i]; //Player who grabbed the power up + // RAVEN END + + wait( 0.1 ); + + playsoundatposition("zmb_powerup_grabbed", self.origin); + self stoploopsound(); + self hide(); + + //Preventing the line from playing AGAIN if fire sale becomes active before it runs out + if( self.powerup_name != "fire_sale" ) + { + if( isdefined( self.power_up_grab_player ) ) + { + if(isDefined(level.powerup_intro_vox)) + { + level thread [[level.powerup_intro_vox]](self); + } + else + { + if(isDefined(level.powerup_vo_available) ) + { + can_say_vo = [[level.powerup_vo_available]](); + if(!can_say_vo) + { + self powerup_delete(); + self notify ("powerup_grabbed"); + return; + } + } + level thread maps\mp\zombies\_zm_audio_announcer::leaderDialog( self.powerup_name, self.power_up_grab_player.pers["team"] ); + self powerup_delete(); + self notify ("powerup_grabbed"); + } + } + } + } + } + wait 0.1; + } +} + +start_fire_sale( item ) +{ + if ( level.zombie_vars[ "zombie_powerup_fire_sale_time" ] > 0 && is_true( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) ) + { + level.zombie_vars[ "zombie_powerup_fire_sale_time" ] += 30; + return; + } + level notify( "powerup fire sale" ); + level endon( "powerup fire sale" ); + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "fire_sale" ); + level.zombie_vars[ "zombie_powerup_fire_sale_on" ] = 1; + level thread toggle_fire_sale_on(); + level.zombie_vars[ "zombie_powerup_fire_sale_time" ] = 30; + while ( level.zombie_vars[ "zombie_powerup_fire_sale_time" ] > 0 ) + { + wait 0.05; + level.zombie_vars[ "zombie_powerup_fire_sale_time" ] -= 0.05; + } + level.zombie_vars[ "zombie_powerup_fire_sale_on" ] = 0; + level notify( "fire_sale_off" ); +} + +start_bonfire_sale( item ) +{ + level notify( "powerup bonfire sale" ); + level endon( "powerup bonfire sale" ); + temp_ent = spawn( "script_origin", ( 0, 0, 0 ) ); + temp_ent playloopsound( "zmb_double_point_loop" ); + level.zombie_vars[ "zombie_powerup_bonfire_sale_on" ] = 1; + level thread toggle_bonfire_sale_on(); + level.zombie_vars[ "zombie_powerup_bonfire_sale_time" ] = 30; + while ( level.zombie_vars[ "zombie_powerup_bonfire_sale_time" ] > 0 ) + { + wait 0.05; + level.zombie_vars[ "zombie_powerup_bonfire_sale_time" ] -= 0.05; + } + level.zombie_vars[ "zombie_powerup_bonfire_sale_on" ] = 0; + level notify( "bonfire_sale_off" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] playsound( "zmb_points_loop_off" ); + i++; + } + temp_ent delete(); +} + +start_carpenter( origin ) +{ + window_boards = getstructarray( "exterior_goal", "targetname" ); + total = level.exterior_goals.size; + carp_ent = spawn( "script_origin", ( 0, 0, 0 ) ); + carp_ent playloopsound( "evt_carpenter" ); + while ( 1 ) + { + windows = get_closest_window_repair( window_boards, origin ); + if ( !isDefined( windows ) ) + { + carp_ent stoploopsound( 1 ); + carp_ent playsoundwithnotify( "evt_carpenter_end", "sound_done" ); + carp_ent waittill( "sound_done" ); + break; + } + else arrayremovevalue( window_boards, windows ); + while ( 1 ) + { + if ( all_chunks_intact( windows, windows.barrier_chunks ) ) + { + break; + } + else chunk = get_random_destroyed_chunk( windows, windows.barrier_chunks ); + if ( !isDefined( chunk ) ) + { + break; + } + else + { + windows thread maps/mp/zombies/_zm_blockers::replace_chunk( windows, chunk, undefined, maps/mp/zombies/_zm_powerups::is_carpenter_boards_upgraded(), 1 ); + if ( isDefined( windows.clip ) ) + { + windows.clip enable_trigger(); + windows.clip disconnectpaths(); + } + else + { + blocker_disconnect_paths( windows.neg_start, windows.neg_end ); + } + wait_network_frame(); + wait 0.05; + } + } + wait_network_frame(); + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] maps/mp/zombies/_zm_score::player_add_points( "carpenter_powerup", 200 ); + i++; + } + carp_ent delete(); +} + +get_closest_window_repair( windows, origin ) +{ + current_window = undefined; + shortest_distance = undefined; + i = 0; + while ( i < windows.size ) + { + if ( all_chunks_intact( windows, windows[ i ].barrier_chunks ) ) + { + i++; + continue; + } + else if ( !isDefined( current_window ) ) + { + current_window = windows[ i ]; + shortest_distance = distancesquared( current_window.origin, origin ); + i++; + continue; + } + else + { + if ( distancesquared( windows[ i ].origin, origin ) < shortest_distance ) + { + current_window = windows[ i ]; + shortest_distance = distancesquared( windows[ i ].origin, origin ); + } + } + i++; + } + return current_window; +} + +powerup_vo( type ) +{ + self endon( "death" ); + self endon( "disconnect" ); + if ( isDefined( level.powerup_vo_available ) ) + { + if ( !( [[ level.powerup_vo_available ]]() ) ) + { + return; + } + } + wait randomfloatrange( 2, 2.5 ); + if ( type == "tesla" ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", type ); + } + else + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "powerup", type ); + } + if ( isDefined( level.custom_powerup_vo_response ) ) + { + level [[ level.custom_powerup_vo_response ]]( self, type ); + } +} + +powerup_wobble_fx() +{ + self endon( "death" ); + if ( !isDefined( self ) ) + { + return; + } + if ( isDefined( level.powerup_fx_func ) ) + { + self thread [[ level.powerup_fx_func ]](); + return; + } + if ( self.solo ) + { + self setclientfield( "powerup_fx", 2 ); + } + else if ( self.caution ) + { + self setclientfield( "powerup_fx", 4 ); + } + else if ( self.zombie_grabbable ) + { + self setclientfield( "powerup_fx", 3 ); + } + else + { + self setclientfield( "powerup_fx", 1 ); + } +} + +powerup_wobble() +{ + self endon( "powerup_grabbed" ); + self endon( "powerup_timedout" ); + self thread powerup_wobble_fx(); + while ( isDefined( self ) ) + { + waittime = randomfloatrange( 2.5, 5 ); + yaw = randomint( 360 ); + if ( yaw > 300 ) + { + yaw = 300; + } + else + { + if ( yaw < 60 ) + { + yaw = 60; + } + } + yaw = self.angles[ 1 ] + yaw; + new_angles = ( -60 + randomint( 120 ), yaw, -45 + randomint( 90 ) ); + self rotateto( new_angles, waittime, waittime * 0.5, waittime * 0.5 ); + if ( isDefined( self.worldgundw ) ) + { + self.worldgundw rotateto( new_angles, waittime, waittime * 0.5, waittime * 0.5 ); + } + wait randomfloat( waittime - 0,1 ); + } +} + +powerup_timeout() +{ + if ( isDefined( level._powerup_timeout_override ) && !isDefined( self.powerup_team ) ) + { + self thread [[ level._powerup_timeout_override ]](); + return; + } + self endon( "powerup_grabbed" ); + self endon( "death" ); + self endon( "powerup_reset" ); + self show(); + wait_time = 15; + if ( isDefined( level._powerup_timeout_custom_time ) ) + { + time = [[ level._powerup_timeout_custom_time ]]( self ); + if ( time == 0 ) + { + return; + } + wait_time = time; + } + wait wait_time; + i = 0; + while ( i < 40 ) + { + if ( i % 2 ) + { + self ghost(); + if ( isDefined( self.worldgundw ) ) + { + self.worldgundw ghost(); + } + } + else + { + self show(); + if ( isDefined( self.worldgundw ) ) + { + self.worldgundw show(); + } + } + if ( i < 15 ) + { + wait 0.5; + i++; + continue; + } + else if ( i < 25 ) + { + wait 0.25; + i++; + continue; + } + else + { + wait 0.1; + } + i++; + } + self notify( "powerup_timedout" ); + self powerup_delete(); +} + +powerup_delete() +{ + arrayremovevalue( level.active_powerups, self, 0 ); + if ( isDefined( self.worldgundw ) ) + { + self.worldgundw delete(); + } + self delete(); +} + +powerup_delete_delayed( time ) +{ + if ( isDefined( time ) ) + { + wait time; + } + else + { + wait 0.01; + } + self powerup_delete(); +} + +nuke_powerup( drop_item, player_team ) +{ + location = drop_item.origin; + playfx( drop_item.fx, location ); + level thread nuke_flash( player_team ); + wait 0.5; + zombies = getaiarray( level.zombie_team ); + zombies = arraysort( zombies, location ); + zombies_nuked = []; + i = 0; + while ( i < zombies.size ) + { + if ( isDefined( zombies[ i ].ignore_nuke ) && zombies[ i ].ignore_nuke ) + { + i++; + continue; + } + else + { + if ( isDefined( zombies[ i ].marked_for_death ) && zombies[ i ].marked_for_death ) + { + i++; + continue; + } + else + { + if ( isDefined( zombies[ i ].nuke_damage_func ) ) + { + zombies[ i ] thread [[ zombies[ i ].nuke_damage_func ]](); + i++; + continue; + } + else if ( is_magic_bullet_shield_enabled( zombies[ i ] ) ) + { + i++; + continue; + } + else + { + zombies[ i ].marked_for_death = 1; + zombies[ i ].nuked = 1; + zombies_nuked[ zombies_nuked.size ] = zombies[ i ]; + } + } + } + i++; + } + i = 0; + while ( i < zombies_nuked.size ) + { + wait randomfloatrange( 0.1, 0.7 ); + if ( !isDefined( zombies_nuked[ i ] ) ) + { + i++; + continue; + } + else if ( is_magic_bullet_shield_enabled( zombies_nuked[ i ] ) ) + { + i++; + continue; + } + else + { + if ( i < 5 && !zombies_nuked[ i ].isdog ) + { + zombies_nuked[ i ] thread maps/mp/animscripts/zm_death::flame_death_fx(); + } + if ( !zombies_nuked[ i ].isdog ) + { + if ( isDefined( zombies_nuked[ i ].no_gib ) && !zombies_nuked[ i ].no_gib ) + { + zombies_nuked[ i ] maps/mp/zombies/_zm_spawner::zombie_head_gib(); + } + zombies_nuked[ i ] playsound( "evt_nuked" ); + } + zombies_nuked[ i ] dodamage( zombies_nuked[ i ].health + 666, zombies_nuked[ i ].origin ); + } + i++; + } + players = get_players( player_team ); + i = 0; + while ( i < players.size ) + { + players[ i ] maps/mp/zombies/_zm_score::player_add_points( "nuke_powerup", 400 ); + i++; + } +} + +nuke_flash( team ) +{ + if ( isDefined( team ) ) + { + get_players()[ 0 ] playsoundtoteam( "evt_nuke_flash", team ); + } + else + { + get_players()[ 0 ] playsound( "evt_nuke_flash" ); + } + fadetowhite = newhudelem(); + fadetowhite.x = 0; + fadetowhite.y = 0; + fadetowhite.alpha = 0; + fadetowhite.horzalign = "fullscreen"; + fadetowhite.vertalign = "fullscreen"; + fadetowhite.foreground = 1; + fadetowhite setshader( "white", 640, 480 ); + fadetowhite fadeovertime( 0,2 ); + fadetowhite.alpha = 0.8; + wait 0.5; + fadetowhite fadeovertime( 1 ); + fadetowhite.alpha = 0; + wait 1.1; + fadetowhite destroy(); +} + +double_points_powerup( drop_item, player ) +{ + level notify( "powerup points scaled_" + player.team ); + level endon( "powerup points scaled_" + player.team ); + team = player.team; + level thread point_doubler_on_hud( drop_item, team ); + if ( isDefined( level.pers_upgrade_double_points ) && level.pers_upgrade_double_points ) + { + player thread maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_double_points_pickup_start(); + } + if ( isDefined( level.current_game_module ) && level.current_game_module == 2 ) + { + if ( isDefined( player._race_team ) ) + { + if ( player._race_team == 1 ) + { + level._race_team_double_points = 1; + } + else + { + level._race_team_double_points = 2; + } + } + } + level.zombie_vars[ team ][ "zombie_point_scalar" ] = 2; + players = get_players(); + player_index = 0; + while ( player_index < players.size ) + { + if ( team == players[ player_index ].team ) + { + players[ player_index ] setclientfield( "score_cf_double_points_active", 1 ); + } + player_index++; + } + wait 30; + level.zombie_vars[ team ][ "zombie_point_scalar" ] = 1; + level._race_team_double_points = undefined; + players = get_players(); + player_index = 0; + while ( player_index < players.size ) + { + if ( team == players[ player_index ].team ) + { + players[ player_index ] setclientfield( "score_cf_double_points_active", 0 ); + } + player_index++; + } +} + +full_ammo_powerup( drop_item, player ) +{ + players = get_players( player.team ); + if ( isDefined( level._get_game_module_players ) ) + { + players = [[ level._get_game_module_players ]]( player ); + } + i = 0; + while ( i < players.size ) + { + if ( players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + i++; + continue; + } + else + { + primary_weapons = players[ i ] getweaponslist( 1 ); + players[ i ] notify( "zmb_max_ammo" ); + players[ i ] notify( "zmb_lost_knife" ); + players[ i ] notify( "zmb_disable_claymore_prompt" ); + players[ i ] notify( "zmb_disable_spikemore_prompt" ); + x = 0; + while ( x < primary_weapons.size ) + { + if ( level.headshots_only && is_lethal_grenade( primary_weapons[ x ] ) ) + { + x++; + continue; + } + else + { + if ( isDefined( level.zombie_include_equipment ) && isDefined( level.zombie_include_equipment[ primary_weapons[ x ] ] ) ) + { + x++; + continue; + } + else + { + if ( isDefined( level.zombie_weapons_no_max_ammo ) && isDefined( level.zombie_weapons_no_max_ammo[ primary_weapons[ x ] ] ) ) + { + x++; + continue; + } + else + { + if ( players[ i ] hasweapon( primary_weapons[ x ] ) ) + { + players[ i ] givemaxammo( primary_weapons[ x ] ); + } + } + } + } + x++; + } + } + i++; + } + level thread full_ammo_on_hud( drop_item, player.team ); +} + +insta_kill_powerup( drop_item, player ) +{ + level notify( "powerup instakill_" + player.team ); + level endon( "powerup instakill_" + player.team ); + if ( isDefined( level.insta_kill_powerup_override ) ) + { + level thread [[ level.insta_kill_powerup_override ]]( drop_item, player ); + return; + } + if ( is_classic() ) + { + player thread maps/mp/zombies/_zm_pers_upgrades_functions::pers_upgrade_insta_kill_upgrade_check(); + } + team = player.team; + level thread insta_kill_on_hud( drop_item, team ); + level.zombie_vars[ team ][ "zombie_insta_kill" ] = 1; + wait 30; + level.zombie_vars[ team ][ "zombie_insta_kill" ] = 0; + players = get_players( team ); + i = 0; + while ( i < players.size ) + { + if ( isDefined( players[ i ] ) ) + { + players[ i ] notify( "insta_kill_over" ); + } + i++; + } +} + +is_insta_kill_active() +{ + return level.zombie_vars[ self.team ][ "zombie_insta_kill" ]; +} + +check_for_instakill( player, mod, hit_location ) +{ + if ( isDefined( player ) && isalive( player ) && isDefined( level.check_for_instakill_override ) ) + { + if ( !( self [[ level.check_for_instakill_override ]]( player ) ) ) + { + return; + } + if ( player.use_weapon_type == "MOD_MELEE" ) + { + player.last_kill_method = "MOD_MELEE"; + } + else + { + player.last_kill_method = "MOD_UNKNOWN"; + } + modname = remove_mod_from_methodofdeath( mod ); + if ( isDefined( self.no_gib ) && !self.no_gib ) + { + self maps/mp/zombies/_zm_spawner::zombie_head_gib(); + } + self.health = 1; + self dodamage( self.health + 666, self.origin, player, self, hit_location, modname ); + player notify( "zombie_killed" ); + } + if ( isDefined( player ) && isalive( player ) || level.zombie_vars[ player.team ][ "zombie_insta_kill" ] && isDefined( player.personal_instakill ) && player.personal_instakill ) + { + if ( is_magic_bullet_shield_enabled( self ) ) + { + return; + } + if ( isDefined( self.instakill_func ) ) + { + self thread [[ self.instakill_func ]](); + return; + } + if ( player.use_weapon_type == "MOD_MELEE" ) + { + player.last_kill_method = "MOD_MELEE"; + } + else + { + player.last_kill_method = "MOD_UNKNOWN"; + } + modname = remove_mod_from_methodofdeath( mod ); + if ( flag( "dog_round" ) ) + { + self.health = 1; + self dodamage( self.health + 666, self.origin, player, self, hit_location, modname ); + player notify( "zombie_killed" ); + return; + } + else + { + if ( isDefined( self.no_gib ) && !self.no_gib ) + { + self maps/mp/zombies/_zm_spawner::zombie_head_gib(); + } + self.health = 1; + self dodamage( self.health + 666, self.origin, player, self, hit_location, modname ); + player notify( "zombie_killed" ); + } + } +} + +insta_kill_on_hud( drop_item, player_team ) +{ + if ( level.zombie_vars[ player_team ][ "zombie_powerup_insta_kill_on" ] ) + { + level.zombie_vars[ player_team ][ "zombie_powerup_insta_kill_time" ] = 30; + return; + } + level.zombie_vars[ player_team ][ "zombie_powerup_insta_kill_on" ] = 1; + level thread time_remaning_on_insta_kill_powerup( player_team ); +} + +time_remaning_on_insta_kill_powerup( player_team ) +{ + temp_enta = spawn( "script_origin", ( 0, 0, 0 ) ); + temp_enta playloopsound( "zmb_insta_kill_loop" ); + while ( level.zombie_vars[ player_team ][ "zombie_powerup_insta_kill_time" ] >= 0 ) + { + wait 0.05; + level.zombie_vars[ player_team ][ "zombie_powerup_insta_kill_time" ] -= 0.05; + } + get_players()[ 0 ] playsoundtoteam( "zmb_insta_kill", player_team ); + temp_enta stoploopsound( 2 ); + level.zombie_vars[ player_team ][ "zombie_powerup_insta_kill_on" ] = 0; + level.zombie_vars[ player_team ][ "zombie_powerup_insta_kill_time" ] = 30; + temp_enta delete(); +} + +point_doubler_on_hud( drop_item, player_team ) +{ + self endon( "disconnect" ); + if ( level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_on" ] ) + { + level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_time" ] = 30; + return; + } + level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_on" ] = 1; + level thread time_remaining_on_point_doubler_powerup( player_team ); +} + +time_remaining_on_point_doubler_powerup( player_team ) +{ + temp_ent = spawn( "script_origin", ( 0, 0, 0 ) ); + temp_ent playloopsound( "zmb_double_point_loop" ); + while ( level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_time" ] >= 0 ) + { + wait 0.05; + level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_time" ] -= 0.05; + } + level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_on" ] = 0; + players = get_players( player_team ); + i = 0; + while ( i < players.size ) + { + players[ i ] playsound( "zmb_points_loop_off" ); + i++; + } + temp_ent stoploopsound( 2 ); + level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_time" ] = 30; + temp_ent delete(); +} + +toggle_bonfire_sale_on() +{ + level endon( "powerup bonfire sale" ); + if ( !isDefined( level.zombie_vars[ "zombie_powerup_bonfire_sale_on" ] ) ) + { + return; + } + if ( level.zombie_vars[ "zombie_powerup_bonfire_sale_on" ] ) + { + if ( isDefined( level.bonfire_init_func ) ) + { + level thread [[ level.bonfire_init_func ]](); + } + level waittill( "bonfire_sale_off" ); + } +} + +toggle_fire_sale_on() +{ + level endon( "powerup fire sale" ); + if ( !isDefined( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) ) + { + return; + } + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) + { + i = 0; + while ( i < level.chests.size ) + { + show_firesale_box = level.chests[ i ] [[ level._zombiemode_check_firesale_loc_valid_func ]](); + if ( show_firesale_box ) + { + level.chests[ i ].zombie_cost = 10; + if ( level.chest_index != i ) + { + level.chests[ i ].was_temp = 1; + if ( is_true( level.chests[ i ].hidden ) ) + { + level.chests[ i ] thread maps/mp/zombies/_zm_magicbox::show_chest(); + } + wait_network_frame(); + } + } + i++; + } + level waittill( "fire_sale_off" ); + waittillframeend; + i = 0; + while ( i < level.chests.size ) + { + show_firesale_box = level.chests[ i ] [[ level._zombiemode_check_firesale_loc_valid_func ]](); + if ( show_firesale_box ) + { + if ( level.chest_index != i && isDefined( level.chests[ i ].was_temp ) ) + { + level.chests[ i ].was_temp = undefined; + level thread remove_temp_chest( i ); + } + level.chests[ i ].zombie_cost = level.chests[ i ].old_cost; + } + i++; + } + } +} + +fire_sale_weapon_wait() +{ + self.zombie_cost = self.old_cost; + while ( isDefined( self.chest_user ) ) + { + wait_network_frame(); + } + self set_hint_string( self, "default_treasure_chest", self.zombie_cost ); +} + +remove_temp_chest( chest_index ) +{ + while ( isDefined( level.chests[ chest_index ].chest_user ) || isDefined( level.chests[ chest_index ]._box_open ) && level.chests[ chest_index ]._box_open == 1 ) + { + wait_network_frame(); + } + if ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] ) + { + level.chests[ chest_index ].was_temp = 1; + level.chests[ chest_index ].zombie_cost = 10; + return; + } + i = 0; + while ( i < chest_index ) + { + wait_network_frame(); + i++; + } + playfx( level._effect[ "poltergeist" ], level.chests[ chest_index ].orig_origin ); + level.chests[ chest_index ].zbarrier playsound( "zmb_box_poof_land" ); + level.chests[ chest_index ].zbarrier playsound( "zmb_couch_slam" ); + wait_network_frame(); + level.chests[ chest_index ] maps/mp/zombies/_zm_magicbox::hide_chest(); +} + +devil_dialog_delay() +{ + wait 1; +} + +full_ammo_on_hud( drop_item, player_team ) +{ + self endon( "disconnect" ); + hudelem = maps/mp/gametypes_zm/_hud_util::createserverfontstring( "objective", 2, player_team ); + hudelem maps/mp/gametypes_zm/_hud_util::setpoint( "TOP", undefined, 0, level.zombie_vars[ "zombie_timer_offset" ] - ( level.zombie_vars[ "zombie_timer_offset_interval" ] * 2 ) ); + hudelem.sort = 0.5; + hudelem.alpha = 0; + hudelem fadeovertime( 0.5 ); + hudelem.alpha = 1; + if ( isDefined( drop_item ) ) + { + hudelem.label = drop_item.hint; + } + hudelem thread full_ammo_move_hud( player_team ); +} + +full_ammo_move_hud( player_team ) +{ + players = get_players( player_team ); + players[ 0 ] playsoundtoteam( "zmb_full_ammo", player_team ); + wait 0.5; + move_fade_time = 1.5; + self fadeovertime( move_fade_time ); + self moveovertime( move_fade_time ); + self.y = 270; + self.alpha = 0; + wait move_fade_time; + self destroy(); +} + +check_for_rare_drop_override( pos ) +{ + if ( isDefined( flag( "ape_round" ) ) && flag( "ape_round" ) ) + { + return 0; + } + return 0; +} + +setup_firesale_audio() +{ + wait 2; + intercom = getentarray( "intercom", "targetname" ); + while ( 1 ) + { + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 0 ) + { + wait 0.2; + } + i = 0; + while ( i < intercom.size ) + { + intercom[ i ] thread play_firesale_audio(); + i++; + } + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 ) + { + wait 0.1; + } + level notify( "firesale_over" ); + } +} + +play_firesale_audio() +{ + if ( isDefined( level.sndfiresalemusoff ) && level.sndfiresalemusoff ) + { + return; + } + if ( isDefined( level.sndannouncerisrich ) && level.sndannouncerisrich ) + { + self playloopsound( "mus_fire_sale_rich" ); + } + else + { + self playloopsound( "mus_fire_sale" ); + } + level waittill( "firesale_over" ); + self stoploopsound(); +} + +setup_bonfiresale_audio() +{ + wait 2; + intercom = getentarray( "intercom", "targetname" ); + while ( 1 ) + { + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 0 ) + { + wait 0.2; + } + i = 0; + while ( i < intercom.size ) + { + intercom[ i ] thread play_bonfiresale_audio(); + i++; + } + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 ) + { + wait 0.1; + } + level notify( "firesale_over" ); + } +} + +play_bonfiresale_audio() +{ + if ( isDefined( level.sndfiresalemusoff ) && level.sndfiresalemusoff ) + { + return; + } + if ( isDefined( level.sndannouncerisrich ) && level.sndannouncerisrich ) + { + self playloopsound( "mus_fire_sale_rich" ); + } + else + { + self playloopsound( "mus_fire_sale" ); + } + level waittill( "firesale_over" ); + self stoploopsound(); +} + +free_perk_powerup( item ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) + { + player = players[ i ]; + if ( isDefined( item.ghost_powerup ) ) + { + player maps/mp/zombies/_zm_stats::increment_client_stat( "buried_ghost_perk_acquired", 0 ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "buried_ghost_perk_acquired" ); + player notify( "player_received_ghost_round_free_perk" ); + } + free_perk = player maps/mp/zombies/_zm_perks::give_random_perk(); + if ( isDefined( level.disable_free_perks_before_power ) && level.disable_free_perks_before_power ) + { + player thread disable_perk_before_power( free_perk ); + } + } + i++; + } +} + +disable_perk_before_power( perk ) +{ + self endon( "disconnect" ); + if ( isDefined( perk ) ) + { + wait 0.1; + if ( !flag( "power_on" ) ) + { + a_players = get_players(); + if ( isDefined( a_players ) && a_players.size == 1 && perk == "specialty_quickrevive" ) + { + return; + } + self perk_pause( perk ); + flag_wait( "power_on" ); + self perk_unpause( perk ); + } + } +} + +random_weapon_powerup_throttle() +{ + self.random_weapon_powerup_throttle = 1; + wait 0.25; + self.random_weapon_powerup_throttle = 0; +} + +random_weapon_powerup( item, player ) +{ + if ( player.sessionstate == "spectator" || player maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return 0; + } + if ( isDefined( player.random_weapon_powerup_throttle ) && !player.random_weapon_powerup_throttle || player isswitchingweapons() && player.is_drinking > 0 ) + { + return 0; + } + current_weapon = player getcurrentweapon(); + current_weapon_type = weaponinventorytype( current_weapon ); + if ( !is_tactical_grenade( item.weapon ) ) + { + if ( current_weapon_type != "primary" && current_weapon_type != "altmode" ) + { + return 0; + } + if ( !isDefined( level.zombie_weapons[ current_weapon ] ) && !maps/mp/zombies/_zm_weapons::is_weapon_upgraded( current_weapon ) && current_weapon_type != "altmode" ) + { + return 0; + } + } + player thread random_weapon_powerup_throttle(); + weapon_string = item.weapon; + if ( weapon_string == "knife_ballistic_zm" ) + { + weapon = player maps/mp/zombies/_zm_melee_weapon::give_ballistic_knife( weapon_string, 0 ); + } + else + { + if ( weapon_string == "knife_ballistic_upgraded_zm" ) + { + weapon = player maps/mp/zombies/_zm_melee_weapon::give_ballistic_knife( weapon_string, 1 ); + } + } + player thread maps/mp/zombies/_zm_weapons::weapon_give( weapon_string ); + return 1; +} + +bonus_points_player_powerup( item, player ) +{ + points = randomintrange( 1, 25 ) * 100; + if ( isDefined( level.bonus_points_powerup_override ) ) + { + points = [[ level.bonus_points_powerup_override ]](); + } + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && player.sessionstate != "spectator" ) + { + player maps/mp/zombies/_zm_score::player_add_points( "bonus_points_powerup", points ); + } +} + +bonus_points_team_powerup( item ) +{ + points = randomintrange( 1, 25 ) * 100; + if ( isDefined( level.bonus_points_powerup_override ) ) + { + points = [[ level.bonus_points_powerup_override ]](); + } + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) + { + players[ i ] maps/mp/zombies/_zm_score::player_add_points( "bonus_points_powerup", points ); + } + i++; + } +} + +lose_points_team_powerup( item ) +{ + points = randomintrange( 1, 25 ) * 100; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) + { + if ( ( players[ i ].score - points ) <= 0 ) + { + players[ i ] maps/mp/zombies/_zm_score::minus_to_player_score( players[ i ].score ); + i++; + continue; + } + else + { + players[ i ] maps/mp/zombies/_zm_score::minus_to_player_score( points ); + } + } + i++; + } +} + +lose_perk_powerup( item ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && player.sessionstate != "spectator" ) + { + player maps/mp/zombies/_zm_perks::lose_random_perk(); + } + i++; + } +} + +empty_clip_powerup( item ) +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + player = players[ i ]; + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && player.sessionstate != "spectator" ) + { + weapon = player getcurrentweapon(); + player setweaponammoclip( weapon, 0 ); + } + i++; + } +} + +minigun_weapon_powerup( ent_player, time ) +{ + ent_player endon( "disconnect" ); + ent_player endon( "death" ); + ent_player endon( "player_downed" ); + if ( !isDefined( time ) ) + { + time = 30; + } + if ( isDefined( level._minigun_time_override ) ) + { + time = level._minigun_time_override; + } + if ( ent_player.zombie_vars[ "zombie_powerup_minigun_on" ] || ent_player getcurrentweapon() == "minigun_zm" && isDefined( ent_player.has_minigun ) && ent_player.has_minigun ) + { + if ( ent_player.zombie_vars[ "zombie_powerup_minigun_time" ] < time ) + { + ent_player.zombie_vars[ "zombie_powerup_minigun_time" ] = time; + } + return; + } + ent_player notify( "replace_weapon_powerup" ); + ent_player._show_solo_hud = 1; + level._zombie_minigun_powerup_last_stand_func = ::minigun_watch_gunner_downed; + ent_player.has_minigun = 1; + ent_player.has_powerup_weapon = 1; + ent_player increment_is_drinking(); + ent_player._zombie_gun_before_minigun = ent_player getcurrentweapon(); + ent_player giveweapon( "minigun_zm" ); + ent_player switchtoweapon( "minigun_zm" ); + ent_player.zombie_vars[ "zombie_powerup_minigun_on" ] = 1; + level thread minigun_weapon_powerup_countdown( ent_player, "minigun_time_over", time ); + level thread minigun_weapon_powerup_replace( ent_player, "minigun_time_over" ); +} + +minigun_weapon_powerup_countdown( ent_player, str_gun_return_notify, time ) +{ + ent_player endon( "death" ); + ent_player endon( "disconnect" ); + ent_player endon( "player_downed" ); + ent_player endon( str_gun_return_notify ); + ent_player endon( "replace_weapon_powerup" ); + setclientsysstate( "levelNotify", "minis", ent_player ); + ent_player.zombie_vars[ "zombie_powerup_minigun_time" ] = time; + while ( ent_player.zombie_vars[ "zombie_powerup_minigun_time" ] > 0 ) + { + wait 0.05; + ent_player.zombie_vars[ "zombie_powerup_minigun_time" ] -= 0.05; + } + setclientsysstate( "levelNotify", "minie", ent_player ); + level thread minigun_weapon_powerup_remove( ent_player, str_gun_return_notify ); +} + +minigun_weapon_powerup_replace( ent_player, str_gun_return_notify ) +{ + ent_player endon( "death" ); + ent_player endon( "disconnect" ); + ent_player endon( "player_downed" ); + ent_player endon( str_gun_return_notify ); + ent_player waittill( "replace_weapon_powerup" ); + ent_player takeweapon( "minigun_zm" ); + ent_player.zombie_vars[ "zombie_powerup_minigun_on" ] = 0; + ent_player.has_minigun = 0; + ent_player decrement_is_drinking(); +} + +minigun_weapon_powerup_remove( ent_player, str_gun_return_notify ) +{ + ent_player endon( "death" ); + ent_player endon( "player_downed" ); + ent_player takeweapon( "minigun_zm" ); + ent_player.zombie_vars[ "zombie_powerup_minigun_on" ] = 0; + ent_player._show_solo_hud = 0; + ent_player.has_minigun = 0; + ent_player.has_powerup_weapon = 0; + ent_player notify( str_gun_return_notify ); + ent_player decrement_is_drinking(); + while ( isDefined( ent_player._zombie_gun_before_minigun ) ) + { + player_weapons = ent_player getweaponslistprimaries(); + i = 0; + while ( i < player_weapons.size ) + { + if ( player_weapons[ i ] == ent_player._zombie_gun_before_minigun ) + { + ent_player switchtoweapon( ent_player._zombie_gun_before_minigun ); + return; + } + i++; + } + } + primaryweapons = ent_player getweaponslistprimaries(); + if ( primaryweapons.size > 0 ) + { + ent_player switchtoweapon( primaryweapons[ 0 ] ); + } + else + { + allweapons = ent_player getweaponslist( 1 ); + i = 0; + while ( i < allweapons.size ) + { + if ( is_melee_weapon( allweapons[ i ] ) ) + { + ent_player switchtoweapon( allweapons[ i ] ); + return; + } + i++; + } + } +} + +minigun_weapon_powerup_off() +{ + self.zombie_vars[ "zombie_powerup_minigun_time" ] = 0; +} + +minigun_watch_gunner_downed() +{ + if ( isDefined( self.has_minigun ) && !self.has_minigun ) + { + return; + } + primaryweapons = self getweaponslistprimaries(); + i = 0; + while ( i < primaryweapons.size ) + { + if ( primaryweapons[ i ] == "minigun_zm" ) + { + self takeweapon( "minigun_zm" ); + } + i++; + } + self notify( "minigun_time_over" ); + self.zombie_vars[ "zombie_powerup_minigun_on" ] = 0; + self._show_solo_hud = 0; + wait 0.05; + self.has_minigun = 0; + self.has_powerup_weapon = 0; +} + +tesla_weapon_powerup( ent_player, time ) +{ + ent_player endon( "disconnect" ); + ent_player endon( "death" ); + ent_player endon( "player_downed" ); + if ( !isDefined( time ) ) + { + time = 11; + } + if ( ent_player.zombie_vars[ "zombie_powerup_tesla_on" ] || ent_player getcurrentweapon() == "tesla_gun_zm" && isDefined( ent_player.has_tesla ) && ent_player.has_tesla ) + { + ent_player givemaxammo( "tesla_gun_zm" ); + if ( ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] < time ) + { + ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = time; + } + return; + } + ent_player notify( "replace_weapon_powerup" ); + ent_player._show_solo_hud = 1; + level._zombie_tesla_powerup_last_stand_func = ::tesla_watch_gunner_downed; + ent_player.has_tesla = 1; + ent_player.has_powerup_weapon = 1; + ent_player increment_is_drinking(); + ent_player._zombie_gun_before_tesla = ent_player getcurrentweapon(); + ent_player giveweapon( "tesla_gun_zm" ); + ent_player givemaxammo( "tesla_gun_zm" ); + ent_player switchtoweapon( "tesla_gun_zm" ); + ent_player.zombie_vars[ "zombie_powerup_tesla_on" ] = 1; + level thread tesla_weapon_powerup_countdown( ent_player, "tesla_time_over", time ); + level thread tesla_weapon_powerup_replace( ent_player, "tesla_time_over" ); +} + +tesla_weapon_powerup_countdown( ent_player, str_gun_return_notify, time ) +{ + ent_player endon( "death" ); + ent_player endon( "player_downed" ); + ent_player endon( str_gun_return_notify ); + ent_player endon( "replace_weapon_powerup" ); + setclientsysstate( "levelNotify", "minis", ent_player ); + ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = time; + while ( 1 ) + { + ent_player waittill_any( "weapon_fired", "reload", "zmb_max_ammo" ); + if ( !ent_player getweaponammostock( "tesla_gun_zm" ) ) + { + clip_count = ent_player getweaponammoclip( "tesla_gun_zm" ); + if ( !clip_count ) + { + break; + } + else if ( clip_count == 1 ) + { + ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = 1; + } + else + { + if ( clip_count == 3 ) + { + ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = 6; + } + } + continue; + } + else + { + ent_player.zombie_vars[ "zombie_powerup_tesla_time" ] = 11; + } + } + setclientsysstate( "levelNotify", "minie", ent_player ); + level thread tesla_weapon_powerup_remove( ent_player, str_gun_return_notify ); +} + +tesla_weapon_powerup_replace( ent_player, str_gun_return_notify ) +{ + ent_player endon( "death" ); + ent_player endon( "disconnect" ); + ent_player endon( "player_downed" ); + ent_player endon( str_gun_return_notify ); + ent_player waittill( "replace_weapon_powerup" ); + ent_player takeweapon( "tesla_gun_zm" ); + ent_player.zombie_vars[ "zombie_powerup_tesla_on" ] = 0; + ent_player.has_tesla = 0; + ent_player decrement_is_drinking(); +} + +tesla_weapon_powerup_remove( ent_player, str_gun_return_notify ) +{ + ent_player endon( "death" ); + ent_player endon( "player_downed" ); + ent_player takeweapon( "tesla_gun_zm" ); + ent_player.zombie_vars[ "zombie_powerup_tesla_on" ] = 0; + ent_player._show_solo_hud = 0; + ent_player.has_tesla = 0; + ent_player.has_powerup_weapon = 0; + ent_player notify( str_gun_return_notify ); + ent_player decrement_is_drinking(); + while ( isDefined( ent_player._zombie_gun_before_tesla ) ) + { + player_weapons = ent_player getweaponslistprimaries(); + i = 0; + while ( i < player_weapons.size ) + { + if ( player_weapons[ i ] == ent_player._zombie_gun_before_tesla ) + { + ent_player switchtoweapon( ent_player._zombie_gun_before_tesla ); + return; + } + i++; + } + } + primaryweapons = ent_player getweaponslistprimaries(); + if ( primaryweapons.size > 0 ) + { + ent_player switchtoweapon( primaryweapons[ 0 ] ); + } + else + { + allweapons = ent_player getweaponslist( 1 ); + i = 0; + while ( i < allweapons.size ) + { + if ( is_melee_weapon( allweapons[ i ] ) ) + { + ent_player switchtoweapon( allweapons[ i ] ); + return; + } + i++; + } + } +} + +tesla_weapon_powerup_off() +{ + self.zombie_vars[ "zombie_powerup_tesla_time" ] = 0; +} + +tesla_watch_gunner_downed() +{ + if ( isDefined( self.has_tesla ) && !self.has_tesla ) + { + return; + } + primaryweapons = self getweaponslistprimaries(); + i = 0; + while ( i < primaryweapons.size ) + { + if ( primaryweapons[ i ] == "tesla_gun_zm" ) + { + self takeweapon( "tesla_gun_zm" ); + } + i++; + } + self notify( "tesla_time_over" ); + self.zombie_vars[ "zombie_powerup_tesla_on" ] = 0; + self._show_solo_hud = 0; + wait 0.05; + self.has_tesla = 0; + self.has_powerup_weapon = 0; +} + +tesla_powerup_active() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].zombie_vars[ "zombie_powerup_tesla_on" ] ) + { + return 1; + } + i++; + } + return 0; +} + +print_powerup_drop( powerup, type ) +{ +} + +register_carpenter_node( node, callback ) +{ + if ( !isDefined( level._additional_carpenter_nodes ) ) + { + level._additional_carpenter_nodes = []; + } + node._post_carpenter_callback = callback; + level._additional_carpenter_nodes[ level._additional_carpenter_nodes.size ] = node; +} + +start_carpenter_new( origin ) +{ + level.carpenter_powerup_active = 1; + window_boards = getstructarray( "exterior_goal", "targetname" ); + if ( isDefined( level._additional_carpenter_nodes ) ) + { + window_boards = arraycombine( window_boards, level._additional_carpenter_nodes, 0, 0 ); + } + carp_ent = spawn( "script_origin", ( 0, 0, 0 ) ); + carp_ent playloopsound( "evt_carpenter" ); + boards_near_players = get_near_boards( window_boards ); + boards_far_from_players = get_far_boards( window_boards ); + level repair_far_boards( boards_far_from_players, maps/mp/zombies/_zm_powerups::is_carpenter_boards_upgraded() ); + i = 0; + while ( i < boards_near_players.size ) + { + window = boards_near_players[ i ]; + num_chunks_checked = 0; + last_repaired_chunk = undefined; + while ( 1 ) + { + if ( all_chunks_intact( window, window.barrier_chunks ) ) + { + break; + } + else chunk = get_random_destroyed_chunk( window, window.barrier_chunks ); + if ( !isDefined( chunk ) ) + { + break; + } + else window thread maps/mp/zombies/_zm_blockers::replace_chunk( window, chunk, undefined, maps/mp/zombies/_zm_powerups::is_carpenter_boards_upgraded(), 1 ); + last_repaired_chunk = chunk; + if ( isDefined( window.clip ) ) + { + window.clip enable_trigger(); + window.clip disconnectpaths(); + } + else + { + blocker_disconnect_paths( window.neg_start, window.neg_end ); + } + wait_network_frame(); + num_chunks_checked++; + if ( num_chunks_checked >= 20 ) + { + break; + } + else + { + } + } + if ( isDefined( window.zbarrier ) ) + { + if ( isDefined( last_repaired_chunk ) ) + { + while ( window.zbarrier getzbarrierpiecestate( last_repaired_chunk ) == "closing" ) + { + wait 0.05; + } + if ( isDefined( window._post_carpenter_callback ) ) + { + window [[ window._post_carpenter_callback ]](); + } + } + i++; + continue; + } + else while ( isDefined( last_repaired_chunk ) && last_repaired_chunk.state == "mid_repair" ) + { + wait 0.05; + } + i++; + } + carp_ent stoploopsound( 1 ); + carp_ent playsoundwithnotify( "evt_carpenter_end", "sound_done" ); + carp_ent waittill( "sound_done" ); + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ] maps/mp/zombies/_zm_score::player_add_points( "carpenter_powerup", 200 ); + i++; + } + carp_ent delete(); + level notify( "carpenter_finished" ); + level.carpenter_powerup_active = undefined; +} + +is_carpenter_boards_upgraded() +{ + if ( isDefined( level.pers_carpenter_boards_active ) && level.pers_carpenter_boards_active == 1 ) + { + return 1; + } + return 0; +} + +get_near_boards( windows ) +{ + players = get_players(); + boards_near_players = []; + j = 0; + while ( j < windows.size ) + { + close = 0; + i = 0; + while ( i < players.size ) + { + origin = undefined; + if ( isDefined( windows[ j ].zbarrier ) ) + { + origin = windows[ j ].zbarrier.origin; + } + else + { + origin = windows[ j ].origin; + } + if ( distancesquared( players[ i ].origin, origin ) <= level.board_repair_distance_squared ) + { + close = 1; + break; + } + else + { + i++; + } + } + if ( close ) + { + boards_near_players[ boards_near_players.size ] = windows[ j ]; + } + j++; + } + return boards_near_players; +} + +get_far_boards( windows ) +{ + players = get_players(); + boards_far_from_players = []; + j = 0; + while ( j < windows.size ) + { + close = 0; + i = 0; + while ( i < players.size ) + { + origin = undefined; + if ( isDefined( windows[ j ].zbarrier ) ) + { + origin = windows[ j ].zbarrier.origin; + } + else + { + origin = windows[ j ].origin; + } + if ( distancesquared( players[ i ].origin, origin ) >= level.board_repair_distance_squared ) + { + close = 1; + break; + } + else + { + i++; + } + } + if ( close ) + { + boards_far_from_players[ boards_far_from_players.size ] = windows[ j ]; + } + j++; + } + return boards_far_from_players; +} + +repair_far_boards( barriers, upgrade ) +{ + i = 0; + while ( i < barriers.size ) + { + barrier = barriers[ i ]; + if ( all_chunks_intact( barrier, barrier.barrier_chunks ) ) + { + i++; + continue; + } + else + { + while ( isDefined( barrier.zbarrier ) ) + { + a_pieces = barrier.zbarrier getzbarrierpieceindicesinstate( "open" ); + while ( isDefined( a_pieces ) ) + { + xx = 0; + while ( xx < a_pieces.size ) + { + chunk = a_pieces[ xx ]; + if ( upgrade ) + { + barrier.zbarrier zbarrierpieceuseupgradedmodel( chunk ); + barrier.zbarrier.chunk_health[ chunk ] = barrier.zbarrier getupgradedpiecenumlives( chunk ); + xx++; + continue; + } + else + { + barrier.zbarrier zbarrierpieceusedefaultmodel( chunk ); + barrier.zbarrier.chunk_health[ chunk ] = 0; + } + xx++; + } + } + x = 0; + while ( x < barrier.zbarrier getnumzbarrierpieces() ) + { + barrier.zbarrier setzbarrierpiecestate( x, "closed" ); + barrier.zbarrier showzbarrierpiece( x ); + x++; + } + } + if ( isDefined( barrier.clip ) ) + { + barrier.clip enable_trigger(); + barrier.clip disconnectpaths(); + } + else + { + blocker_disconnect_paths( barrier.neg_start, barrier.neg_end ); + } + if ( ( i % 4 ) == 0 ) + { + wait_network_frame(); + } + } + i++; + } +} + +func_should_never_drop() +{ + return 0; +} + +func_should_always_drop() +{ + return 1; +} + +func_should_drop_minigun() +{ + if ( minigun_no_drop() ) + { + return 0; + } + return 1; +} + +func_should_drop_carpenter() +{ + if ( get_num_window_destroyed() < 5 ) + { + return 0; + } + return 1; +} + +func_should_drop_fire_sale() +{ + if ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] != 1 || level.chest_moves < 1 && isDefined( level.disable_firesale_drop ) && level.disable_firesale_drop ) + { + return 0; + } + return 1; +} + +powerup_move() +{ + self endon( "powerup_timedout" ); + self endon( "powerup_grabbed" ); + drag_speed = 75; + while ( 1 ) + { + self waittill( "move_powerup", moveto, distance ); + drag_vector = moveto - self.origin; + range_squared = lengthsquared( drag_vector ); + if ( range_squared > ( distance * distance ) ) + { + drag_vector = vectornormalize( drag_vector ); + drag_vector = distance * drag_vector; + moveto = self.origin + drag_vector; + } + self.origin = moveto; + } +} + +powerup_emp() +{ + self endon( "powerup_timedout" ); + self endon( "powerup_grabbed" ); + if ( !should_watch_for_emp() ) + { + return; + } + while ( 1 ) + { + level waittill( "emp_detonate", origin, radius ); + if ( distancesquared( origin, self.origin ) < ( radius * radius ) ) + { + playfx( level._effect[ "powerup_off" ], self.origin ); + self thread powerup_delete_delayed(); + self notify( "powerup_timedout" ); + } + } +} + +get_powerups( origin, radius ) +{ + if ( isDefined( origin ) && isDefined( radius ) ) + { + powerups = []; + _a3603 = level.active_powerups; + _k3603 = getFirstArrayKey( _a3603 ); + while ( isDefined( _k3603 ) ) + { + powerup = _a3603[ _k3603 ]; + if ( distancesquared( origin, powerup.origin ) < ( radius * radius ) ) + { + powerups[ powerups.size ] = powerup; + } + _k3603 = getNextArrayKey( _a3603, _k3603 ); + } + return powerups; + } + return level.active_powerups; +} + +should_award_stat( powerup_name ) +{ + if ( powerup_name != "teller_withdrawl" && powerup_name != "blue_monkey" || powerup_name == "free_perk" && powerup_name == "bonus_points_player" ) + { + return 0; + } + if ( isDefined( level.statless_powerups ) && isDefined( level.statless_powerups[ powerup_name ] ) ) + { + return 0; + } + return 1; +} + +teller_withdrawl( powerup, player ) +{ + player maps/mp/zombies/_zm_score::add_to_player_score( powerup.value ); +} + + + diff --git a/patch_zm/maps/mp/zombies/_zm_timer.gsc b/patch_zm/maps/mp/zombies/_zm_timer.gsc new file mode 100644 index 0000000..4dfc9b7 --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_timer.gsc @@ -0,0 +1,80 @@ +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + precacheshader( "zombie_stopwatchneedle" ); + precacheshader( "zombie_stopwatch" ); + precacheshader( "zombie_stopwatch_glass" ); + if ( !isDefined( level.stopwatch_length_width ) ) + { + level.stopwatch_length_width = 96; + } +} + +start_timer( time, stop_notify ) +{ + self notify( "stop_prev_timer" ); + self endon( "stop_prev_timer" ); + if ( !isDefined( self.stopwatch_elem ) ) + { + self.stopwatch_elem = newclienthudelem( self ); + self.stopwatch_elem.horzalign = "left"; + self.stopwatch_elem.vertalign = "top"; + self.stopwatch_elem.alignx = "left"; + self.stopwatch_elem.aligny = "top"; + self.stopwatch_elem.x = 10; + self.stopwatch_elem.alpha = 0; + self.stopwatch_elem.sort = 2; + self.stopwatch_elem_glass = newclienthudelem( self ); + self.stopwatch_elem_glass.horzalign = "left"; + self.stopwatch_elem_glass.vertalign = "top"; + self.stopwatch_elem_glass.alignx = "left"; + self.stopwatch_elem_glass.aligny = "top"; + self.stopwatch_elem_glass.x = 10; + self.stopwatch_elem_glass.alpha = 0; + self.stopwatch_elem_glass.sort = 3; + self.stopwatch_elem_glass setshader( "zombie_stopwatch_glass", level.stopwatch_length_width, level.stopwatch_length_width ); + } + self thread update_hud_position(); + if ( isDefined( stop_notify ) ) + { + self thread wait_for_stop_notify( stop_notify ); + } + if ( time > 60 ) + { + time = 0; + } + self.stopwatch_elem setclock( time, 60, "zombie_stopwatch", level.stopwatch_length_width, level.stopwatch_length_width ); + self.stopwatch_elem.alpha = 1; + self.stopwatch_elem_glass.alpha = 1; + wait time; + self notify( "countdown_finished" ); + wait 1; + self.stopwatch_elem.alpha = 0; + self.stopwatch_elem_glass.alpha = 0; +} + +wait_for_stop_notify( stop_notify ) +{ + self endon( "stop_prev_timer" ); + self endon( "countdown_finished" ); + self waittill( stop_notify ); + self.stopwatch_elem.alpha = 0; + self.stopwatch_elem_glass.alpha = 0; +} + +update_hud_position() +{ + self endon( "disconnect" ); + self endon( "stop_prev_timer" ); + self endon( "countdown_finished" ); + while ( 1 ) + { + self.stopwatch_elem.y = 20; + self.stopwatch_elem_glass.y = 20; + wait 0.05; + } +} + diff --git a/patch_zm/maps/mp/zombies/_zm_weapons.gsc b/patch_zm/maps/mp/zombies/_zm_weapons.gsc new file mode 100644 index 0000000..3be55fc --- /dev/null +++ b/patch_zm/maps/mp/zombies/_zm_weapons.gsc @@ -0,0 +1,3058 @@ +#include maps/mp/zombies/_zm_weap_cymbal_monkey; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_pers_upgrades_functions; +#include maps/mp/zombies/_zm_melee_weapon; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/gametypes_zm/_weapons; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; +#include maps/mp/zombies/_zm_weap_claymore; +#include maps/mp/zombies/_zm_weap_ballistic_knife; + + +init() +{ +/* +/# + println( "ZM >> init (_zm_weapons.gsc)" ); +#/ +*/ + + init_weapons(); + init_weapon_upgrade(); + init_weapon_toggle(); + precacheshader( "minimap_icon_mystery_box" ); + precacheshader( "specialty_instakill_zombies" ); + precacheshader( "specialty_firesale_zombies" ); + precacheitem( "zombie_fists_zm" ); + level._weaponobjects_on_player_connect_override = ::weaponobjects_on_player_connect_override; + level._zombiemode_check_firesale_loc_valid_func = ::default_check_firesale_loc_valid_func; + level.missileentities = []; + setupretrievablehintstrings(); + level thread onplayerconnect(); + +} + +setupretrievablehintstrings() +{ + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "claymore", &"ZOMBIE_CLAYMORE_PICKUP" ); +} + +onplayerconnect() +{ + for ( ;; ) + { + level waittill( "connecting", player ); + player thread onplayerspawned(); + } +} + +onplayerspawned() +{ + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "spawned_player" ); + self thread watchforgrenadeduds(); + self thread watchforgrenadelauncherduds(); + self.staticweaponsstarttime = getTime(); + } +} + +watchforgrenadeduds() +{ + self endon( "spawned_player" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "grenade_fire", grenade, weapname ); + if ( !is_equipment( weapname ) && weapname != "claymore_zm" ) + { + grenade thread checkgrenadefordud( weapname, 1, self ); + grenade thread watchforscriptexplosion( weapname, 1, self ); + } + } +} + +watchforgrenadelauncherduds() +{ + self endon( "spawned_player" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "grenade_launcher_fire", grenade, weapname ); + grenade thread checkgrenadefordud( weapname, 0, self ); + grenade thread watchforscriptexplosion( weapname, 0, self ); + } +} + +grenade_safe_to_throw( player, weapname ) +{ + if ( isDefined( level.grenade_safe_to_throw ) ) + { + return self [[ level.grenade_safe_to_throw ]]( player, weapname ); + } + return 1; +} + +grenade_safe_to_bounce( player, weapname ) +{ + if ( isDefined( level.grenade_safe_to_bounce ) ) + { + return self [[ level.grenade_safe_to_bounce ]]( player, weapname ); + } + return 1; +} + +makegrenadedudanddestroy() +{ + self endon( "death" ); + self notify( "grenade_dud" ); + self makegrenadedud(); + wait 3; + if ( isDefined( self ) ) + { + self delete(); + } +} + +checkgrenadefordud( weapname, isthrowngrenade, player ) +{ + self endon( "death" ); + player endon( "zombify" ); + if ( !self grenade_safe_to_throw( player, weapname ) ) + { + self thread makegrenadedudanddestroy(); + return; + } + for ( ;; ) + { + self waittill_any_timeout( 0.25, "grenade_bounce", "stationary" ); + if ( !self grenade_safe_to_bounce( player, weapname ) ) + { + self thread makegrenadedudanddestroy(); + return; + } + } +} + +wait_explode() +{ + self endon( "grenade_dud" ); + self endon( "done" ); + self waittill( "explode", position ); + level.explode_position = position; + level.explode_position_valid = 1; + self notify( "done" ); +} + +wait_timeout( time ) +{ + self endon( "grenade_dud" ); + self endon( "done" ); + wait time; + self notify( "done" ); +} + +wait_for_explosion( time ) +{ + level.explode_position = ( 0, 0, 0 ); + level.explode_position_valid = 0; + self thread wait_explode(); + self thread wait_timeout( time ); + self waittill( "done" ); + self notify( "death_or_explode" ); +} + +watchforscriptexplosion( weapname, isthrowngrenade, player ) +{ + self endon( "grenade_dud" ); + if ( is_lethal_grenade( weapname ) || is_grenade_launcher( weapname ) ) + { + self thread wait_for_explosion( 20 ); + self waittill( "death_or_explode", exploded, position ); + if ( exploded ) + { + level notify( "grenade_exploded" ); + } + } +} + +get_nonalternate_weapon( altweapon ) +{ + if ( is_alt_weapon( altweapon ) ) + { + alt = weaponaltweaponname( altweapon ); + while ( alt == "none" ) + { + primaryweapons = self getweaponslistprimaries(); + alt = primaryweapons[ 0 ]; + _a201 = primaryweapons; + _k201 = getFirstArrayKey( _a201 ); + while ( isDefined( _k201 ) ) + { + weapon = _a201[ _k201 ]; + if ( weaponaltweaponname( weapon ) == altweapon ) + { + alt = weapon; + break; + } + else + { + _k201 = getNextArrayKey( _a201, _k201 ); + } + } + } + return alt; + } + return altweapon; +} + +switch_from_alt_weapon( current_weapon ) +{ + if ( is_alt_weapon( current_weapon ) ) + { + alt = weaponaltweaponname( current_weapon ); + while ( alt == "none" ) + { + primaryweapons = self getweaponslistprimaries(); + alt = primaryweapons[ 0 ]; + _a227 = primaryweapons; + _k227 = getFirstArrayKey( _a227 ); + while ( isDefined( _k227 ) ) + { + weapon = _a227[ _k227 ]; + if ( weaponaltweaponname( weapon ) == current_weapon ) + { + alt = weapon; + break; + } + else + { + _k227 = getNextArrayKey( _a227, _k227 ); + } + } + } + self switchtoweaponimmediate( alt ); + self waittill_notify_or_timeout( "weapon_change_complete", 1 ); + return alt; + } + return current_weapon; +} + +give_fallback_weapon() +{ + self giveweapon( "zombie_fists_zm" ); + self switchtoweapon( "zombie_fists_zm" ); +} + +take_fallback_weapon() +{ + if ( self hasweapon( "zombie_fists_zm" ) ) + { + self takeweapon( "zombie_fists_zm" ); + } +} + +switch_back_primary_weapon( oldprimary ) +{ + if ( isDefined( self.laststand ) && self.laststand ) + { + return; + } + primaryweapons = self getweaponslistprimaries(); + if ( isDefined( oldprimary ) && isinarray( primaryweapons, oldprimary ) ) + { + self switchtoweapon( oldprimary ); + } + else + { + if ( isDefined( primaryweapons ) && primaryweapons.size > 0 ) + { + self switchtoweapon( primaryweapons[ 0 ] ); + } + } +} + +add_retrievable_knife_init_name( name ) +{ + if ( !isDefined( level.retrievable_knife_init_names ) ) + { + level.retrievable_knife_init_names = []; + } + level.retrievable_knife_init_names[ level.retrievable_knife_init_names.size ] = name; +} + +watchweaponusagezm() +{ + self endon( "death" ); + self endon( "disconnect" ); + level endon( "game_ended" ); + for ( ;; ) + { + self waittill( "weapon_fired", curweapon ); + self.lastfiretime = getTime(); + self.hasdonecombat = 1; + if ( isDefined( self.hitsthismag[ curweapon ] ) ) + { + self thread updatemagshots( curweapon ); + } + switch( weaponclass( curweapon ) ) + { + case "rifle": + if ( curweapon == "crossbow_explosive_mp" ) + { + level.globalcrossbowfired++; + self addweaponstat( curweapon, "shots", 1 ); + self thread begingrenadetracking(); + break; + } + case "pistol": + case "pistol spread": + case "pistolspread": + case "mg": + case "smg": + case "spread": + self trackweaponfire( curweapon ); + level.globalshotsfired++; + break; + case "grenade": + case "rocketlauncher": + if ( is_alt_weapon( curweapon ) ) + { + curweapon = weaponaltweaponname( curweapon ); + } + self addweaponstat( curweapon, "shots", 1 ); + break; + default: + + switch( curweapon ) + { + case "m202_flash_mp": + case "m220_tow_mp": + case "m32_mp": + case "minigun_mp": + case "mp40_blinged_mp": + self.usedkillstreakweapon[ curweapon ] = 1; + break; + continue; + default: + + } + } + } +} + +trackweaponzm() +{ + self.currentweapon = self getcurrentweapon(); + self.currenttime = getTime(); + spawnid = getplayerspawnid( self ); + while ( 1 ) + { + event = self waittill_any_return( "weapon_change", "death", "disconnect", "bled_out" ); + newtime = getTime(); + if ( event == "weapon_change" ) + { + newweapon = self getcurrentweapon(); + if ( newweapon != "none" && newweapon != self.currentweapon ) + { + updatelastheldweapontimingszm( newtime ); + self.currentweapon = newweapon; + self.currenttime = newtime; + } + continue; + } + else + { + if ( event != "disconnect" ) + { + updateweapontimingszm( newtime ); + } + return; + } + } +} + +updatelastheldweapontimingszm( newtime ) +{ + if ( isDefined( self.currentweapon ) && isDefined( self.currenttime ) ) + { + curweapon = self.currentweapon; + totaltime = int( ( newtime - self.currenttime ) / 1000 ); + if ( totaltime > 0 ) + { + if ( is_alt_weapon( curweapon ) ) + { + curweapon = weaponaltweaponname( curweapon ); + } + self addweaponstat( curweapon, "timeUsed", totaltime ); + } + } +} + +updateweapontimingszm( newtime ) +{ + if ( self is_bot() ) + { + return; + } + updatelastheldweapontimingszm( newtime ); + if ( !isDefined( self.staticweaponsstarttime ) ) + { + return; + } + totaltime = int( ( newtime - self.staticweaponsstarttime ) / 1000 ); + if ( totaltime < 0 ) + { + return; + } + self.staticweaponsstarttime = newtime; +} + +watchweaponchangezm() +{ + self endon( "death" ); + self endon( "disconnect" ); + self.lastdroppableweapon = self getcurrentweapon(); + self.hitsthismag = []; + weapon = self getcurrentweapon(); + if ( isDefined( weapon ) && weapon != "none" && !isDefined( self.hitsthismag[ weapon ] ) ) + { + self.hitsthismag[ weapon ] = weaponclipsize( weapon ); + } + while ( 1 ) + { + previous_weapon = self getcurrentweapon(); + self waittill( "weapon_change", newweapon ); + if ( maydropweapon( newweapon ) ) + { + self.lastdroppableweapon = newweapon; + } + if ( newweapon != "none" ) + { + if ( !isDefined( self.hitsthismag[ newweapon ] ) ) + { + self.hitsthismag[ newweapon ] = weaponclipsize( newweapon ); + } + } + } +} + +weaponobjects_on_player_connect_override_internal() +{ + self maps/mp/gametypes_zm/_weaponobjects::createbasewatchers(); + self createclaymorewatcher_zm(); + i = 0; + while ( i < level.retrievable_knife_init_names.size ) + { + self createballisticknifewatcher_zm( level.retrievable_knife_init_names[ i ], level.retrievable_knife_init_names[ i ] + "_zm" ); + i++; + } + self maps/mp/gametypes_zm/_weaponobjects::setupretrievablewatcher(); + if ( !isDefined( self.weaponobjectwatcherarray ) ) + { + self.weaponobjectwatcherarray = []; + } + self thread maps/mp/gametypes_zm/_weaponobjects::watchweaponobjectspawn(); + self thread maps/mp/gametypes_zm/_weaponobjects::watchweaponprojectileobjectspawn(); + self thread maps/mp/gametypes_zm/_weaponobjects::deleteweaponobjectson(); + self.concussionendtime = 0; + self.hasdonecombat = 0; + self.lastfiretime = 0; + self thread watchweaponusagezm(); + self thread maps/mp/gametypes_zm/_weapons::watchgrenadeusage(); + self thread maps/mp/gametypes_zm/_weapons::watchmissileusage(); + self thread watchweaponchangezm(); + self thread maps/mp/gametypes_zm/_weapons::watchturretuse(); + self thread trackweaponzm(); + self notify( "weapon_watchers_created" ); +} + +weaponobjects_on_player_connect_override() +{ + add_retrievable_knife_init_name( "knife_ballistic" ); + add_retrievable_knife_init_name( "knife_ballistic_upgraded" ); + onplayerconnect_callback( ::weaponobjects_on_player_connect_override_internal ); +} + +createclaymorewatcher_zm() +{ + watcher = self maps/mp/gametypes_zm/_weaponobjects::createuseweaponobjectwatcher( "claymore", "claymore_zm", self.team ); + watcher.onspawnretrievetriggers = ::on_spawn_retrieve_trigger; + watcher.adjusttriggerorigin = ::adjust_trigger_origin; + watcher.pickup = level.pickup_claymores; + watcher.pickup_trigger_listener = level.pickup_claymores_trigger_listener; + watcher.skip_weapon_object_damage = 1; + watcher.headicon = 0; + watcher.watchforfire = 1; + watcher.detonate = ::claymoredetonate; + watcher.ondamage = level.claymores_on_damage; +} + +createballisticknifewatcher_zm( name, weapon ) +{ + watcher = self maps/mp/gametypes_zm/_weaponobjects::createuseweaponobjectwatcher( name, weapon, self.team ); + watcher.onspawn = ::on_spawn; + watcher.onspawnretrievetriggers = ::on_spawn_retrieve_trigger; + watcher.storedifferentobject = 1; + watcher.headicon = 0; +} + +isempweapon( weaponname ) +{ + if ( isDefined( weaponname ) && weaponname != "emp_mp" || weaponname == "emp_grenade_mp" && weaponname == "emp_grenade_zm" ) + { + return 1; + } + return 0; +} + +claymoredetonate( attacker, weaponname ) +{ + from_emp = isempweapon( weaponname ); + if ( from_emp ) + { + self delete(); + return; + } + if ( isDefined( attacker ) ) + { + self detonate( attacker ); + } + else if ( isDefined( self.owner ) && isplayer( self.owner ) ) + { + self detonate( self.owner ); + } + else + { + self detonate(); + } +} + +default_check_firesale_loc_valid_func() +{ + return 1; +} + +add_zombie_weapon( weapon_name, upgrade_name, hint, cost, weaponvo, weaponvoresp, ammo_cost, create_vox ) +{ + if ( isDefined( level.zombie_include_weapons ) && !isDefined( level.zombie_include_weapons[ weapon_name ] ) ) + { + return; + } + table = "mp/zombiemode.csv"; + table_cost = tablelookup( table, 0, weapon_name, 1 ); + table_ammo_cost = tablelookup( table, 0, weapon_name, 2 ); + if ( isDefined( table_cost ) && table_cost != "" ) + { + cost = round_up_to_ten( int( table_cost ) ); + } + if ( isDefined( table_ammo_cost ) && table_ammo_cost != "" ) + { + ammo_cost = round_up_to_ten( int( table_ammo_cost ) ); + } + precachestring( hint ); + struct = spawnstruct(); + if ( !isDefined( level.zombie_weapons ) ) + { + level.zombie_weapons = []; + } + if ( !isDefined( level.zombie_weapons_upgraded ) ) + { + level.zombie_weapons_upgraded = []; + } + if ( isDefined( upgrade_name ) ) + { + level.zombie_weapons_upgraded[ upgrade_name ] = weapon_name; + } + struct.weapon_name = weapon_name; + struct.upgrade_name = upgrade_name; + struct.weapon_classname = "weapon_" + weapon_name; + struct.hint = hint; + struct.cost = cost; + struct.vox = weaponvo; + struct.vox_response = weaponvoresp; + /* +/# + println( "ZM >> Looking for weapon - " + weapon_name ); +#/ + */ + struct.is_in_box = level.zombie_include_weapons[ weapon_name ]; + if ( !isDefined( ammo_cost ) ) + { + ammo_cost = round_up_to_ten( int( cost * 0.5 ) ); + } + struct.ammo_cost = ammo_cost; + level.zombie_weapons[ weapon_name ] = struct; + if ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch && isDefined( upgrade_name ) ) + { + add_attachments( weapon_name, upgrade_name ); + } + if ( isDefined( create_vox ) ) + { + level.vox maps/mp/zombies/_zm_audio::zmbvoxadd( "player", "weapon_pickup", weapon_name, weaponvo, undefined ); + } + /* +/# + if ( isDefined( level.devgui_add_weapon ) ) + { + [[ level.devgui_add_weapon ]]( weapon_name, upgrade_name, hint, cost, weaponvo, weaponvoresp, ammo_cost ); +#/ + } + */ +} + +add_attachments( weapon_name, upgrade_name ) +{ + table = "zm/pap_attach.csv"; + if ( isDefined( level.weapon_attachment_table ) ) + { + table = level.weapon_attachment_table; + } + row = tablelookuprownum( table, 0, upgrade_name ); + while ( row > -1 ) + { + level.zombie_weapons[ weapon_name ].default_attachment = tablelookup( table, 0, upgrade_name, 1 ); + level.zombie_weapons[ weapon_name ].addon_attachments = []; + index = 2; + next_addon = tablelookup( table, 0, upgrade_name, index ); + while ( isDefined( next_addon ) && next_addon.size > 0 ) + { + level.zombie_weapons[ weapon_name ].addon_attachments[ level.zombie_weapons[ weapon_name ].addon_attachments.size ] = next_addon; + index++; + next_addon = tablelookup( table, 0, upgrade_name, index ); + } + } +} + +default_weighting_func() +{ + return 1; +} + +default_tesla_weighting_func() +{ + num_to_add = 1; + if ( isDefined( level.pulls_since_last_tesla_gun ) ) + { + if ( isDefined( level.player_drops_tesla_gun ) && level.player_drops_tesla_gun == 1 ) + { + num_to_add += int( 0.2 * level.zombie_include_weapons.size ); + } + if ( !isDefined( level.player_seen_tesla_gun ) || level.player_seen_tesla_gun == 0 ) + { + if ( level.round_number > 10 ) + { + num_to_add += int( 0.2 * level.zombie_include_weapons.size ); + } + else + { + if ( level.round_number > 5 ) + { + num_to_add += int( 0.15 * level.zombie_include_weapons.size ); + } + } + } + } + return num_to_add; +} + +default_1st_move_weighting_func() +{ + if ( level.chest_moves > 0 ) + { + num_to_add = 1; + return num_to_add; + } + else + { + return 0; + } +} + +default_upgrade_weapon_weighting_func() +{ + if ( level.chest_moves > 1 ) + { + return 1; + } + else + { + return 0; + } +} + +default_cymbal_monkey_weighting_func() +{ + players = get_players(); + count = 0; + i = 0; + while ( i < players.size ) + { + if ( players[ i ] has_weapon_or_upgrade( "cymbal_monkey_zm" ) ) + { + count++; + } + i++; + } + if ( count > 0 ) + { + return 1; + } + else + { + if ( level.round_number < 10 ) + { + return 3; + } + else + { + return 5; + } + } +} + +is_weapon_included( weapon_name ) +{ + if ( !isDefined( level.zombie_weapons ) ) + { + return 0; + } + return isDefined( level.zombie_weapons[ weapon_name ] ); +} + +is_weapon_or_base_included( weapon_name ) +{ + if ( !isDefined( level.zombie_weapons ) ) + { + return 0; + } + if ( isDefined( level.zombie_weapons[ weapon_name ] ) ) + { + return 1; + } + base = get_base_weapon_name( weapon_name, 1 ); + if ( isDefined( level.zombie_weapons[ base ] ) ) + { + return 1; + } + return 0; +} + +include_zombie_weapon( weapon_name, in_box, collector, weighting_func ) +{ + if ( !isDefined( level.zombie_include_weapons ) ) + { + level.zombie_include_weapons = []; + } + if ( !isDefined( in_box ) ) + { + in_box = 1; + } + /* +/# + println( "ZM >> Including weapon - " + weapon_name ); +#/ + */ + level.zombie_include_weapons[ weapon_name ] = in_box; + precacheitem( weapon_name ); + if ( !isDefined( weighting_func ) ) + { + level.weapon_weighting_funcs[ weapon_name ] = ::default_weighting_func; + } + else + { + level.weapon_weighting_funcs[ weapon_name ] = weighting_func; + } +} + +init_weapons() +{ + //throws exe_client_field_mismatch on join + //or the server won't rotate to the map + if ( isDefined( level._zombie_custom_add_weapons ) ) + { + //[[ level._zombie_custom_add_weapons ]](); + } + precachemodel( "zombie_teddybear" ); +} + +add_limited_weapon( weapon_name, amount ) +{ + if ( !isDefined( level.limited_weapons ) ) + { + level.limited_weapons = []; + } + level.limited_weapons[ weapon_name ] = amount; +} + +limited_weapon_below_quota( weapon, ignore_player, pap_triggers ) +{ + while ( isDefined( level.limited_weapons[ weapon ] ) ) + { + if ( !isDefined( pap_triggers ) ) + { + if ( !isDefined( level.pap_triggers ) ) + { + pap_triggers = getentarray( "specialty_weapupgrade", "script_noteworthy" ); + break; + } + else + { + pap_triggers = level.pap_triggers; + } + } + if ( is_true( level.no_limited_weapons ) ) + { + return 0; + } + upgradedweapon = weapon; + if ( isDefined( level.zombie_weapons[ weapon ] ) && isDefined( level.zombie_weapons[ weapon ].upgrade_name ) ) + { + upgradedweapon = level.zombie_weapons[ weapon ].upgrade_name; + } + players = get_players(); + count = 0; + limit = level.limited_weapons[ weapon ]; + i = 0; + while ( i < players.size ) + { + if ( isDefined( ignore_player ) && ignore_player == players[ i ] ) + { + i++; + continue; + } + else + { + if ( players[ i ] has_weapon_or_upgrade( weapon ) ) + { + count++; + if ( count >= limit ) + { + return 0; + } + } + } + i++; + } + k = 0; + while ( k < pap_triggers.size ) + { + if ( isDefined( pap_triggers[ k ].current_weapon ) || pap_triggers[ k ].current_weapon == weapon && pap_triggers[ k ].current_weapon == upgradedweapon ) + { + count++; + if ( count >= limit ) + { + return 0; + } + } + k++; + } + chestindex = 0; + while ( chestindex < level.chests.size ) + { + if ( isDefined( level.chests[ chestindex ].zbarrier.weapon_string ) && level.chests[ chestindex ].zbarrier.weapon_string == weapon ) + { + count++; + if ( count >= limit ) + { + return 0; + } + } + chestindex++; + } + if ( isDefined( level.custom_limited_weapon_checks ) ) + { + _a952 = level.custom_limited_weapon_checks; + _k952 = getFirstArrayKey( _a952 ); + while ( isDefined( _k952 ) ) + { + check = _a952[ _k952 ]; + count += [[ check ]]( weapon ); + _k952 = getNextArrayKey( _a952, _k952 ); + } + if ( count >= limit ) + { + return 0; + } + } + while ( isDefined( level.random_weapon_powerups ) ) + { + powerupindex = 0; + while ( powerupindex < level.random_weapon_powerups.size ) + { + if ( isDefined( level.random_weapon_powerups[ powerupindex ] ) && level.random_weapon_powerups[ powerupindex ].base_weapon == weapon ) + { + count++; + if ( count >= limit ) + { + return 0; + } + } + powerupindex++; + } + } + } + return 1; +} + +add_custom_limited_weapon_check( callback ) +{ + if ( !isDefined( level.custom_limited_weapon_checks ) ) + { + level.custom_limited_weapon_checks = []; + } + level.custom_limited_weapon_checks[ level.custom_limited_weapon_checks.size ] = callback; +} + +add_weapon_to_content( weapon_name, package ) +{ + if ( !isDefined( level.content_weapons ) ) + { + level.content_weapons = []; + } + level.content_weapons[ weapon_name ] = package; +} + +player_can_use_content( weapon ) +{ + if ( isDefined( level.content_weapons ) ) + { + if ( isDefined( level.content_weapons[ weapon ] ) ) + { + return self hasdlcavailable( level.content_weapons[ weapon ] ); + } + } + return 1; +} + +init_spawnable_weapon_upgrade() +{ + spawn_list = []; + spawnable_weapon_spawns = getstructarray( "weapon_upgrade", "targetname" ); + spawnable_weapon_spawns = arraycombine( spawnable_weapon_spawns, getstructarray( "bowie_upgrade", "targetname" ), 1, 0 ); + spawnable_weapon_spawns = arraycombine( spawnable_weapon_spawns, getstructarray( "sickle_upgrade", "targetname" ), 1, 0 ); + spawnable_weapon_spawns = arraycombine( spawnable_weapon_spawns, getstructarray( "tazer_upgrade", "targetname" ), 1, 0 ); + spawnable_weapon_spawns = arraycombine( spawnable_weapon_spawns, getstructarray( "buildable_wallbuy", "targetname" ), 1, 0 ); + if ( !is_true( level.headshots_only ) ) + { + spawnable_weapon_spawns = arraycombine( spawnable_weapon_spawns, getstructarray( "claymore_purchase", "targetname" ), 1, 0 ); + } + match_string = ""; + location = level.scr_zm_map_start_location; + if ( location != "default" && location == "" && isDefined( level.default_start_location ) ) + { + location = level.default_start_location; + } + match_string = level.scr_zm_ui_gametype; + if ( location != "" ) + { + match_string = ( match_string + "_" ) + location; + } + match_string_plus_space = " " + match_string; + i = 0; + while ( i < spawnable_weapon_spawns.size ) + { + spawnable_weapon = spawnable_weapon_spawns[ i ]; + if ( isDefined( spawnable_weapon.zombie_weapon_upgrade ) && spawnable_weapon.zombie_weapon_upgrade == "sticky_grenade_zm" && is_true( level.headshots_only ) ) + { + i++; + continue; + } + else + { + if ( !isDefined( spawnable_weapon.script_noteworthy ) || spawnable_weapon.script_noteworthy == "" ) + { + spawn_list[ spawn_list.size ] = spawnable_weapon; + i++; + continue; + } + else + { + matches = strtok( spawnable_weapon.script_noteworthy, "," ); + j = 0; + while ( j < matches.size ) + { + if ( matches[ j ] == match_string || matches[ j ] == match_string_plus_space ) + { + spawn_list[ spawn_list.size ] = spawnable_weapon; + } + j++; + } + } + } + i++; + } + tempmodel = spawn( "script_model", ( 0, 0, 0 ) ); + i = 0; + while ( i < spawn_list.size ) + { + clientfieldname = ( spawn_list[ i ].zombie_weapon_upgrade + "_" ) + spawn_list[ i ].origin; + numbits = 2; + if ( isDefined( level._wallbuy_override_num_bits ) ) + { + numbits = level._wallbuy_override_num_bits; + } + registerclientfield( "world", clientfieldname, 1, numbits, "int" ); + target_struct = getstruct( spawn_list[ i ].target, "targetname" ); + if ( spawn_list[ i ].targetname == "buildable_wallbuy" ) + { + bits = 4; + if ( isDefined( level.buildable_wallbuy_weapons ) ) + { + bits = getminbitcountfornum( level.buildable_wallbuy_weapons.size + 1 ); + } + registerclientfield( "world", clientfieldname + "_idx", 12000, bits, "int" ); + spawn_list[ i ].clientfieldname = clientfieldname; + i++; + continue; + } + else + { + precachemodel( target_struct.model ); + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = spawn_list[ i ].origin; + unitrigger_stub.angles = spawn_list[ i ].angles; + tempmodel.origin = spawn_list[ i ].origin; + tempmodel.angles = spawn_list[ i ].angles; + mins = undefined; + maxs = undefined; + absmins = undefined; + absmaxs = undefined; + tempmodel setmodel( target_struct.model ); + tempmodel useweaponhidetags( spawn_list[ i ].zombie_weapon_upgrade ); + mins = tempmodel getmins(); + maxs = tempmodel getmaxs(); + absmins = tempmodel getabsmins(); + absmaxs = tempmodel getabsmaxs(); + bounds = absmaxs - absmins; + unitrigger_stub.script_length = bounds[ 0 ] * 0.25; + unitrigger_stub.script_width = bounds[ 1 ]; + unitrigger_stub.script_height = bounds[ 2 ]; + unitrigger_stub.origin -= anglesToRight( unitrigger_stub.angles ) * ( unitrigger_stub.script_length * 0.4 ); + unitrigger_stub.target = spawn_list[ i ].target; + unitrigger_stub.targetname = spawn_list[ i ].targetname; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + if ( spawn_list[ i ].targetname == "weapon_upgrade" ) + { + unitrigger_stub.cost = get_weapon_cost( spawn_list[ i ].zombie_weapon_upgrade ); + if ( isDefined( level.monolingustic_prompt_format ) && !level.monolingustic_prompt_format ) + { + unitrigger_stub.hint_string = get_weapon_hint( spawn_list[ i ].zombie_weapon_upgrade ); + unitrigger_stub.hint_parm1 = unitrigger_stub.cost; + break; + } + else + { + unitrigger_stub.hint_parm1 = get_weapon_display_name( spawn_list[ i ].zombie_weapon_upgrade ); + if ( isDefined( unitrigger_stub.hint_parm1 ) || unitrigger_stub.hint_parm1 == "" && unitrigger_stub.hint_parm1 == "none" ) + { + unitrigger_stub.hint_parm1 = "missing weapon name " + spawn_list[ i ].zombie_weapon_upgrade; + } + unitrigger_stub.hint_parm2 = unitrigger_stub.cost; + unitrigger_stub.hint_string = &"ZOMBIE_WEAPONCOSTONLY"; + } + } + unitrigger_stub.weapon_upgrade = spawn_list[ i ].zombie_weapon_upgrade; + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + unitrigger_stub.require_look_at = 1; + if ( isDefined( spawn_list[ i ].require_look_from ) && spawn_list[ i ].require_look_from ) + { + unitrigger_stub.require_look_from = 1; + } + unitrigger_stub.zombie_weapon_upgrade = spawn_list[ i ].zombie_weapon_upgrade; + unitrigger_stub.clientfieldname = clientfieldname; + maps/mp/zombies/_zm_unitrigger::unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + if ( is_melee_weapon( unitrigger_stub.zombie_weapon_upgrade ) ) + { + if ( unitrigger_stub.zombie_weapon_upgrade == "tazer_knuckles_zm" && isDefined( level.taser_trig_adjustment ) ) + { + unitrigger_stub.origin += level.taser_trig_adjustment; + } + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::weapon_spawn_think ); + } + else if ( unitrigger_stub.zombie_weapon_upgrade == "claymore_zm" ) + { + unitrigger_stub.prompt_and_visibility_func = ::claymore_unitrigger_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::buy_claymores ); + } + else + { + unitrigger_stub.prompt_and_visibility_func = ::wall_weapon_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::weapon_spawn_think ); + } + spawn_list[ i ].trigger_stub = unitrigger_stub; + } + i++; + } + level._spawned_wallbuys = spawn_list; + tempmodel delete(); +} + +add_dynamic_wallbuy( weapon, wallbuy, pristine ) +{ + spawned_wallbuy = undefined; + i = 0; + while ( i < level._spawned_wallbuys.size ) + { + if ( level._spawned_wallbuys[ i ].target == wallbuy ) + { + spawned_wallbuy = level._spawned_wallbuys[ i ]; + break; + } + else + { + i++; + } + } + if ( !isDefined( spawned_wallbuy ) ) + { + /* +/# + assertmsg( "Cannot find dynamic wallbuy" ); +#/ + */ + return; + } + if ( isDefined( spawned_wallbuy.trigger_stub ) ) + { + /* +/# + assertmsg( "Dynamic wallbuy already added" ); +#/ + */ + return; + } + target_struct = getstruct( wallbuy, "targetname" ); + wallmodel = spawn_weapon_model( weapon, undefined, target_struct.origin, target_struct.angles ); + clientfieldname = spawned_wallbuy.clientfieldname; + model = getweaponmodel( weapon ); + unitrigger_stub = spawnstruct(); + unitrigger_stub.origin = target_struct.origin; + unitrigger_stub.angles = target_struct.angles; + wallmodel.origin = target_struct.origin; + wallmodel.angles = target_struct.angles; + mins = undefined; + maxs = undefined; + absmins = undefined; + absmaxs = undefined; + wallmodel setmodel( model ); + wallmodel useweaponhidetags( weapon ); + mins = wallmodel getmins(); + maxs = wallmodel getmaxs(); + absmins = wallmodel getabsmins(); + absmaxs = wallmodel getabsmaxs(); + bounds = absmaxs - absmins; + unitrigger_stub.script_length = bounds[ 0 ] * 0.25; + unitrigger_stub.script_width = bounds[ 1 ]; + unitrigger_stub.script_height = bounds[ 2 ]; + unitrigger_stub.origin -= anglesToRight( unitrigger_stub.angles ) * ( unitrigger_stub.script_length * 0.4 ); + unitrigger_stub.target = spawned_wallbuy.target; + unitrigger_stub.targetname = "weapon_upgrade"; + unitrigger_stub.cursor_hint = "HINT_NOICON"; + unitrigger_stub.first_time_triggered = !pristine; + if ( !is_melee_weapon( weapon ) ) + { + if ( pristine || weapon == "claymore_zm" ) + { + unitrigger_stub.hint_string = get_weapon_hint( weapon ); + } + else + { + unitrigger_stub.hint_string = get_weapon_hint_ammo(); + } + unitrigger_stub.cost = get_weapon_cost( weapon ); + unitrigger_stub.hint_parm1 = unitrigger_stub.cost; + } + unitrigger_stub.weapon_upgrade = weapon; + unitrigger_stub.script_unitrigger_type = "unitrigger_box_use"; + unitrigger_stub.require_look_at = 1; + unitrigger_stub.zombie_weapon_upgrade = weapon; + unitrigger_stub.clientfieldname = clientfieldname; + maps/mp/zombies/_zm_unitrigger::unitrigger_force_per_player_triggers( unitrigger_stub, 1 ); + if ( is_melee_weapon( weapon ) ) + { + if ( weapon == "tazer_knuckles_zm" && isDefined( level.taser_trig_adjustment ) ) + { + unitrigger_stub.origin += level.taser_trig_adjustment; + } + maps/mp/zombies/_zm_melee_weapon::add_stub( unitrigger_stub, weapon ); + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::melee_weapon_think ); + } + else if ( weapon == "claymore_zm" ) + { + unitrigger_stub.prompt_and_visibility_func = ::claymore_unitrigger_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::buy_claymores ); + } + else + { + unitrigger_stub.prompt_and_visibility_func = ::wall_weapon_update_prompt; + maps/mp/zombies/_zm_unitrigger::register_static_unitrigger( unitrigger_stub, ::weapon_spawn_think ); + } + spawned_wallbuy.trigger_stub = unitrigger_stub; + weaponidx = undefined; + while ( isDefined( level.buildable_wallbuy_weapons ) ) + { + i = 0; + while ( i < level.buildable_wallbuy_weapons.size ) + { + if ( weapon == level.buildable_wallbuy_weapons[ i ] ) + { + weaponidx = i; + break; + } + else + { + i++; + } + } + } + if ( isDefined( weaponidx ) ) + { + level setclientfield( clientfieldname + "_idx", weaponidx + 1 ); + wallmodel delete(); + if ( !pristine ) + { + level setclientfield( clientfieldname, 1 ); + } + } + else + { + level setclientfield( clientfieldname, 1 ); + wallmodel show(); + } +} + +wall_weapon_update_prompt( player ) +{ + weapon = self.stub.zombie_weapon_upgrade; + if ( isDefined( level.monolingustic_prompt_format ) && !level.monolingustic_prompt_format ) + { + player_has_weapon = player has_weapon_or_upgrade( weapon ); + if ( !player_has_weapon && isDefined( level.weapons_using_ammo_sharing ) && level.weapons_using_ammo_sharing ) + { + shared_ammo_weapon = player get_shared_ammo_weapon( self.zombie_weapon_upgrade ); + if ( isDefined( shared_ammo_weapon ) ) + { + weapon = shared_ammo_weapon; + player_has_weapon = 1; + } + } + if ( !player_has_weapon ) + { + cost = get_weapon_cost( weapon ); + self.stub.hint_string = get_weapon_hint( weapon ); + self sethintstring( self.stub.hint_string, cost ); + } + else if ( isDefined( level.use_legacy_weapon_prompt_format ) && level.use_legacy_weapon_prompt_format ) + { + cost = get_weapon_cost( weapon ); + ammo_cost = get_ammo_cost( weapon ); + self.stub.hint_string = get_weapon_hint_ammo(); + self sethintstring( self.stub.hint_string, cost, ammo_cost ); + } + else + { + if ( player has_upgrade( weapon ) ) + { + ammo_cost = get_upgraded_ammo_cost( weapon ); + } + else + { + ammo_cost = get_ammo_cost( weapon ); + } + self.stub.hint_string = &"ZOMBIE_WEAPONAMMOONLY"; + self sethintstring( self.stub.hint_string, ammo_cost ); + } + } + else + { + if ( !player has_weapon_or_upgrade( weapon ) ) + { + string_override = 0; + if ( isDefined( player.pers_upgrades_awarded[ "nube" ] ) && player.pers_upgrades_awarded[ "nube" ] ) + { + string_override = maps/mp/zombies/_zm_pers_upgrades_functions::pers_nube_ammo_hint_string( player, weapon ); + } + if ( !string_override ) + { + cost = get_weapon_cost( weapon ); + weapon_display = get_weapon_display_name( weapon ); + if ( isDefined( weapon_display ) || weapon_display == "" && weapon_display == "none" ) + { + weapon_display = "missing weapon name " + weapon; + } + self.stub.hint_string = &"ZOMBIE_WEAPONCOSTONLY"; + self sethintstring( self.stub.hint_string, weapon_display, cost ); + } + } + else + { + if ( player has_upgrade( weapon ) ) + { + ammo_cost = get_upgraded_ammo_cost( weapon ); + } + else + { + ammo_cost = get_ammo_cost( weapon ); + } + self.stub.hint_string = &"ZOMBIE_WEAPONAMMOONLY"; + self sethintstring( self.stub.hint_string, ammo_cost ); + } + } + if ( getDvarInt( #"1F0A2129" ) ) + { + self.stub.cursor_hint = "HINT_WEAPON"; + self.stub.cursor_hint_weapon = weapon; + self setcursorhint( self.stub.cursor_hint, self.stub.cursor_hint_weapon ); + } + else + { + self.stub.cursor_hint = "HINT_NOICON"; + self.stub.cursor_hint_weapon = undefined; + self setcursorhint( self.stub.cursor_hint ); + } + return 1; +} + +reset_wallbuy_internal( set_hint_string ) +{ + if ( isDefined( self.first_time_triggered ) && self.first_time_triggered == 1 ) + { + self.first_time_triggered = 0; + if ( isDefined( self.clientfieldname ) ) + { + level setclientfield( self.clientfieldname, 0 ); + } + if ( set_hint_string ) + { + hint_string = get_weapon_hint( self.zombie_weapon_upgrade ); + cost = get_weapon_cost( self.zombie_weapon_upgrade ); + self sethintstring( hint_string, cost ); + } + } +} + +reset_wallbuys() +{ + weapon_spawns = []; + weapon_spawns = getentarray( "weapon_upgrade", "targetname" ); + melee_and_grenade_spawns = []; + melee_and_grenade_spawns = getentarray( "bowie_upgrade", "targetname" ); + melee_and_grenade_spawns = arraycombine( melee_and_grenade_spawns, getentarray( "sickle_upgrade", "targetname" ), 1, 0 ); + melee_and_grenade_spawns = arraycombine( melee_and_grenade_spawns, getentarray( "tazer_upgrade", "targetname" ), 1, 0 ); + if ( !is_true( level.headshots_only ) ) + { + melee_and_grenade_spawns = arraycombine( melee_and_grenade_spawns, getentarray( "claymore_purchase", "targetname" ), 1, 0 ); + } + i = 0; + while ( i < weapon_spawns.size ) + { + weapon_spawns[ i ] reset_wallbuy_internal( 1 ); + i++; + } + i = 0; + while ( i < melee_and_grenade_spawns.size ) + { + melee_and_grenade_spawns[ i ] reset_wallbuy_internal( 0 ); + i++; + } + while ( isDefined( level._unitriggers ) ) + { + candidates = []; + i = 0; + while ( i < level._unitriggers.trigger_stubs.size ) + { + stub = level._unitriggers.trigger_stubs[ i ]; + tn = stub.targetname; + if ( tn != "weapon_upgrade" && tn != "bowie_upgrade" && tn != "sickle_upgrade" || tn == "tazer_upgrade" && tn == "claymore_purchase" ) + { + stub.first_time_triggered = 0; + if ( isDefined( stub.clientfieldname ) ) + { + level setclientfield( stub.clientfieldname, 0 ); + } + if ( tn == "weapon_upgrade" ) + { + stub.hint_string = get_weapon_hint( stub.zombie_weapon_upgrade ); + stub.cost = get_weapon_cost( stub.zombie_weapon_upgrade ); + stub.hint_parm1 = stub.cost; + } + } + i++; + } + } +} + +init_weapon_upgrade() +{ + init_spawnable_weapon_upgrade(); + weapon_spawns = []; + weapon_spawns = getentarray( "weapon_upgrade", "targetname" ); + i = 0; + while ( i < weapon_spawns.size ) + { + if ( isDefined( level.monolingustic_prompt_format ) && !level.monolingustic_prompt_format ) + { + hint_string = get_weapon_hint( weapon_spawns[ i ].zombie_weapon_upgrade ); + cost = get_weapon_cost( weapon_spawns[ i ].zombie_weapon_upgrade ); + weapon_spawns[ i ] sethintstring( hint_string, cost ); + weapon_spawns[ i ] setcursorhint( "HINT_NOICON" ); + } + else + { + cost = get_weapon_cost( weapon_spawns[ i ].zombie_weapon_upgrade ); + weapon_display = get_weapon_display_name( weapon_spawns[ i ].zombie_weapon_upgrade ); + if ( isDefined( weapon_display ) || weapon_display == "" && weapon_display == "none" ) + { + weapon_display = "missing weapon name " + weapon_spawns[ i ].zombie_weapon_upgrade; + } + hint_string = &"ZOMBIE_WEAPONCOSTONLY"; + weapon_spawns[ i ] sethintstring( hint_string, weapon_display, cost ); + } + weapon_spawns[ i ] usetriggerrequirelookat(); + weapon_spawns[ i ] thread weapon_spawn_think(); + model = getent( weapon_spawns[ i ].target, "targetname" ); + if ( isDefined( model ) ) + { + model useweaponhidetags( weapon_spawns[ i ].zombie_weapon_upgrade ); + model hide(); + } + i++; + } +} + +init_weapon_toggle() +{ + if ( !isDefined( level.magic_box_weapon_toggle_init_callback ) ) + { + return; + } + level.zombie_weapon_toggles = []; + level.zombie_weapon_toggle_max_active_count = 0; + level.zombie_weapon_toggle_active_count = 0; + precachestring( &"ZOMBIE_WEAPON_TOGGLE_DISABLED" ); + precachestring( &"ZOMBIE_WEAPON_TOGGLE_ACTIVATE" ); + precachestring( &"ZOMBIE_WEAPON_TOGGLE_DEACTIVATE" ); + precachestring( &"ZOMBIE_WEAPON_TOGGLE_ACQUIRED" ); + level.zombie_weapon_toggle_disabled_hint = &"ZOMBIE_WEAPON_TOGGLE_DISABLED"; + level.zombie_weapon_toggle_activate_hint = &"ZOMBIE_WEAPON_TOGGLE_ACTIVATE"; + level.zombie_weapon_toggle_deactivate_hint = &"ZOMBIE_WEAPON_TOGGLE_DEACTIVATE"; + level.zombie_weapon_toggle_acquired_hint = &"ZOMBIE_WEAPON_TOGGLE_ACQUIRED"; + precachemodel( "zombie_zapper_cagelight" ); + precachemodel( "zombie_zapper_cagelight_green" ); + precachemodel( "zombie_zapper_cagelight_red" ); + precachemodel( "zombie_zapper_cagelight_on" ); + level.zombie_weapon_toggle_disabled_light = "zombie_zapper_cagelight"; + level.zombie_weapon_toggle_active_light = "zombie_zapper_cagelight_green"; + level.zombie_weapon_toggle_inactive_light = "zombie_zapper_cagelight_red"; + level.zombie_weapon_toggle_acquired_light = "zombie_zapper_cagelight_on"; + weapon_toggle_ents = []; + weapon_toggle_ents = getentarray( "magic_box_weapon_toggle", "targetname" ); + i = 0; + while ( i < weapon_toggle_ents.size ) + { + struct = spawnstruct(); + struct.trigger = weapon_toggle_ents[ i ]; + struct.weapon_name = struct.trigger.script_string; + struct.upgrade_name = level.zombie_weapons[ struct.trigger.script_string ].upgrade_name; + struct.enabled = 0; + struct.active = 0; + struct.acquired = 0; + target_array = []; + target_array = getentarray( struct.trigger.target, "targetname" ); + j = 0; + while ( j < target_array.size ) + { + switch( target_array[ j ].script_string ) + { + case "light": + struct.light = target_array[ j ]; + struct.light setmodel( level.zombie_weapon_toggle_disabled_light ); + break; + j++; + continue; + case "weapon": + struct.weapon_model = target_array[ j ]; + struct.weapon_model hide(); + break; + j++; + continue; + } + j++; + } + struct.trigger sethintstring( level.zombie_weapon_toggle_disabled_hint ); + struct.trigger setcursorhint( "HINT_NOICON" ); + struct.trigger usetriggerrequirelookat(); + struct thread weapon_toggle_think(); + level.zombie_weapon_toggles[ struct.weapon_name ] = struct; + i++; + } + level thread [[ level.magic_box_weapon_toggle_init_callback ]](); +} + +get_weapon_toggle( weapon_name ) +{ + if ( !isDefined( level.zombie_weapon_toggles ) ) + { + return undefined; + } + if ( isDefined( level.zombie_weapon_toggles[ weapon_name ] ) ) + { + return level.zombie_weapon_toggles[ weapon_name ]; + } + keys = getarraykeys( level.zombie_weapon_toggles ); + i = 0; + while ( i < keys.size ) + { + if ( weapon_name == level.zombie_weapon_toggles[ keys[ i ] ].upgrade_name ) + { + return level.zombie_weapon_toggles[ keys[ i ] ]; + } + i++; + } + return undefined; +} + +is_weapon_toggle( weapon_name ) +{ + return isDefined( get_weapon_toggle( weapon_name ) ); +} + +disable_weapon_toggle( weapon_name ) +{ + toggle = get_weapon_toggle( weapon_name ); + if ( !isDefined( toggle ) ) + { + return; + } + if ( toggle.active ) + { + level.zombie_weapon_toggle_active_count--; + + } + toggle.enabled = 0; + toggle.active = 0; + toggle.light setmodel( level.zombie_weapon_toggle_disabled_light ); + toggle.weapon_model hide(); + toggle.trigger sethintstring( level.zombie_weapon_toggle_disabled_hint ); +} + +enable_weapon_toggle( weapon_name ) +{ + toggle = get_weapon_toggle( weapon_name ); + if ( !isDefined( toggle ) ) + { + return; + } + toggle.enabled = 1; + toggle.weapon_model show(); + toggle.weapon_model useweaponhidetags( weapon_name ); + deactivate_weapon_toggle( weapon_name ); +} + +activate_weapon_toggle( weapon_name, trig_for_vox ) +{ + if ( level.zombie_weapon_toggle_active_count >= level.zombie_weapon_toggle_max_active_count ) + { + if ( isDefined( trig_for_vox ) ) + { + trig_for_vox thread maps/mp/zombies/_zm_audio::weapon_toggle_vox( "max" ); + } + return; + } + toggle = get_weapon_toggle( weapon_name ); + if ( !isDefined( toggle ) ) + { + return; + } + if ( isDefined( trig_for_vox ) ) + { + trig_for_vox thread maps/mp/zombies/_zm_audio::weapon_toggle_vox( "activate", weapon_name ); + } + level.zombie_weapon_toggle_active_count++; + toggle.active = 1; + toggle.light setmodel( level.zombie_weapon_toggle_active_light ); + toggle.trigger sethintstring( level.zombie_weapon_toggle_deactivate_hint ); +} + +deactivate_weapon_toggle( weapon_name, trig_for_vox ) +{ + toggle = get_weapon_toggle( weapon_name ); + if ( !isDefined( toggle ) ) + { + return; + } + if ( isDefined( trig_for_vox ) ) + { + trig_for_vox thread maps/mp/zombies/_zm_audio::weapon_toggle_vox( "deactivate", weapon_name ); + } + if ( toggle.active ) + { + level.zombie_weapon_toggle_active_count--; + + } + toggle.active = 0; + toggle.light setmodel( level.zombie_weapon_toggle_inactive_light ); + toggle.trigger sethintstring( level.zombie_weapon_toggle_activate_hint ); +} + +acquire_weapon_toggle( weapon_name, player ) +{ + toggle = get_weapon_toggle( weapon_name ); + if ( !isDefined( toggle ) ) + { + return; + } + if ( !toggle.active || toggle.acquired ) + { + return; + } + toggle.acquired = 1; + toggle.light setmodel( level.zombie_weapon_toggle_acquired_light ); + toggle.trigger sethintstring( level.zombie_weapon_toggle_acquired_hint ); + toggle thread unacquire_weapon_toggle_on_death_or_disconnect_thread( player ); +} + +unacquire_weapon_toggle_on_death_or_disconnect_thread( player ) +{ + self notify( "end_unacquire_weapon_thread" ); + self endon( "end_unacquire_weapon_thread" ); + player waittill_any( "spawned_spectator", "disconnect" ); + unacquire_weapon_toggle( self.weapon_name ); +} + +unacquire_weapon_toggle( weapon_name ) +{ + toggle = get_weapon_toggle( weapon_name ); + if ( !isDefined( toggle ) ) + { + return; + } + if ( !toggle.active || !toggle.acquired ) + { + return; + } + toggle.acquired = 0; + toggle.light setmodel( level.zombie_weapon_toggle_active_light ); + toggle.trigger sethintstring( level.zombie_weapon_toggle_deactivate_hint ); + toggle notify( "end_unacquire_weapon_thread" ); +} + +weapon_toggle_think() +{ + for ( ;; ) + { + self.trigger waittill( "trigger", player ); + if ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0.5 ); + continue; + } + else if ( !self.enabled || self.acquired ) + { + self.trigger thread maps/mp/zombies/_zm_audio::weapon_toggle_vox( "max" ); + continue; + } + else + { + if ( !self.active ) + { + activate_weapon_toggle( self.weapon_name, self.trigger ); + break; + } + else + { + deactivate_weapon_toggle( self.weapon_name, self.trigger ); + } + } + } +} + +get_weapon_hint( weapon_name ) +{ +/* +/# + assert( isDefined( level.zombie_weapons[ weapon_name ] ), weapon_name + " was not included or is not part of the zombie weapon list." ); +#/ +*/ + return level.zombie_weapons[ weapon_name ].hint; +} + +get_weapon_cost( weapon_name ) +{ +/* +/# + assert( isDefined( level.zombie_weapons[ weapon_name ] ), weapon_name + " was not included or is not part of the zombie weapon list." ); +#/ +*/ + return level.zombie_weapons[ weapon_name ].cost; +} + +get_ammo_cost( weapon_name ) +{ +/* +/# + assert( isDefined( level.zombie_weapons[ weapon_name ] ), weapon_name + " was not included or is not part of the zombie weapon list." ); +#/ +*/ + return level.zombie_weapons[ weapon_name ].ammo_cost; +} + +get_upgraded_ammo_cost( weapon_name ) +{ +/* +/# + assert( isDefined( level.zombie_weapons[ weapon_name ] ), weapon_name + " was not included or is not part of the zombie weapon list." ); +#/ +*/ + if ( isDefined( level.zombie_weapons[ weapon_name ].upgraded_ammo_cost ) ) + { + return level.zombie_weapons[ weapon_name ].upgraded_ammo_cost; + } + return 4500; +} + +get_weapon_display_name( weapon_name ) +{ + weapon_display = getweapondisplayname( weapon_name ); + if ( isDefined( weapon_display ) || weapon_display == "" && weapon_display == "none" ) + { + weapon_display = &"MPUI_NONE"; +/* +/# + weapon_display = "missing weapon name " + weapon_name; +#/ +*/ + } + return weapon_display; +} + +get_is_in_box( weapon_name ) +{ +/* +/# + assert( isDefined( level.zombie_weapons[ weapon_name ] ), weapon_name + " was not included or is not part of the zombie weapon list." ); +#/ +*/ + return level.zombie_weapons[ weapon_name ].is_in_box; +} + +weapon_supports_default_attachment( weaponname ) +{ + weaponname = get_base_weapon_name( weaponname ); + if ( isDefined( weaponname ) ) + { + attachment = level.zombie_weapons[ weaponname ].default_attachment; + } + return isDefined( attachment ); +} + +default_attachment( weaponname ) +{ + weaponname = get_base_weapon_name( weaponname ); + if ( isDefined( weaponname ) ) + { + attachment = level.zombie_weapons[ weaponname ].default_attachment; + } + if ( isDefined( attachment ) ) + { + return attachment; + } + else + { + return "none"; + } +} + +weapon_supports_attachments( weaponname ) +{ + weaponname = get_base_weapon_name( weaponname ); + if ( isDefined( weaponname ) ) + { + attachments = level.zombie_weapons[ weaponname ].addon_attachments; + } + if ( isDefined( attachments ) ) + { + return attachments.size > 1; + } +} + +random_attachment( weaponname, exclude ) +{ + lo = 0; + if ( isDefined( level.zombie_weapons[ weaponname ].addon_attachments ) && level.zombie_weapons[ weaponname ].addon_attachments.size > 0 ) + { + attachments = level.zombie_weapons[ weaponname ].addon_attachments; + } + else + { + attachments = getweaponsupportedattachments( weaponname ); + lo = 1; + } + minatt = lo; + if ( isDefined( exclude ) && exclude != "none" ) + { + minatt = lo + 1; + } + while ( attachments.size > minatt ) + { + while ( 1 ) + { + idx = randomint( attachments.size - lo ) + lo; + if ( !isDefined( exclude ) || attachments[ idx ] != exclude ) + { + return attachments[ idx ]; + } + } + } + return "none"; +} + +get_base_name( weaponname ) +{ + split = strtok( weaponname, "+" ); + if ( split.size > 1 ) + { + return split[ 0 ]; + } + return weaponname; +} + +get_attachment_name( weaponname, att_id ) +{ + split = strtok( weaponname, "+" ); + if ( isDefined( att_id ) ) + { + attachment = att_id + 1; + if ( split.size > attachment ) + { + return split[ attachment ]; + } + } + else + { + if ( split.size > 1 ) + { + att = split[ 1 ]; + idx = 2; + while ( split.size > idx ) + { + att = ( att + "+" ) + split[ idx ]; + idx++; + } + return att; + } + } + return undefined; +} + +get_attachment_index( weapon ) +{ + att = get_attachment_name( weapon ); + if ( att == "none" ) + { + return -1; + } + base = get_base_name( weapon ); + if ( att == level.zombie_weapons[ base ].default_attachment ) + { + return 0; + } + while ( isDefined( level.zombie_weapons[ base ].addon_attachments ) ) + { + i = 0; + while ( i < level.zombie_weapons[ base ].addon_attachments.size ) + { + if ( level.zombie_weapons[ base ].addon_attachments[ i ] == att ) + { + return i + 1; + } + i++; + } + } +/* +/# + println( "ZM WEAPON ERROR: Unrecognized attachment in weapon " + weapon ); +#/ +*/ + return -1; +} + +weapon_supports_this_attachment( weapon, att ) +{ + base = get_base_name( weapon ); + if ( att == level.zombie_weapons[ base ].default_attachment ) + { + return 1; + } + while ( isDefined( level.zombie_weapons[ base ].addon_attachments ) ) + { + i = 0; + while ( i < level.zombie_weapons[ base ].addon_attachments.size ) + { + if ( level.zombie_weapons[ base ].addon_attachments[ i ] == att ) + { + return 1; + } + i++; + } + } + return 0; +} + +has_attachment( weaponname, att ) +{ + split = strtok( weaponname, "+" ); + idx = 1; + while ( split.size > idx ) + { + if ( att == split[ idx ] ) + { + return 1; + } + } + return 0; +} + +get_base_weapon_name( upgradedweaponname, base_if_not_upgraded ) +{ + if ( !isDefined( upgradedweaponname ) || upgradedweaponname == "" ) + { + return undefined; + } + upgradedweaponname = tolower( upgradedweaponname ); + upgradedweaponname = get_base_name( upgradedweaponname ); + if ( isDefined( level.zombie_weapons_upgraded[ upgradedweaponname ] ) ) + { + return level.zombie_weapons_upgraded[ upgradedweaponname ]; + } + if ( isDefined( base_if_not_upgraded ) && base_if_not_upgraded ) + { + return upgradedweaponname; + } + return undefined; +} + +get_upgrade_weapon( weaponname, add_attachment ) +{ + rootweaponname = tolower( weaponname ); + rootweaponname = get_base_name( rootweaponname ); + baseweaponname = get_base_weapon_name( rootweaponname, 1 ); + newweapon = rootweaponname; + if ( !is_weapon_upgraded( rootweaponname ) ) + { + newweapon = level.zombie_weapons[ rootweaponname ].upgrade_name; + } + if ( isDefined( add_attachment ) && add_attachment && isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch ) + { + oldatt = get_attachment_name( weaponname ); + att = random_attachment( baseweaponname, oldatt ); + newweapon = ( newweapon + "+" ) + att; + } + else + { + if ( isDefined( level.zombie_weapons[ rootweaponname ] ) && isDefined( level.zombie_weapons[ rootweaponname ].default_attachment ) ) + { + att = level.zombie_weapons[ rootweaponname ].default_attachment; + newweapon = ( newweapon + "+" ) + att; + } + } + return newweapon; +} + +can_upgrade_weapon( weaponname ) +{ + if ( isDefined( weaponname ) || weaponname == "" && weaponname == "zombie_fists_zm" ) + { + return 0; + } + weaponname = tolower( weaponname ); + weaponname = get_base_name( weaponname ); + if ( !is_weapon_upgraded( weaponname ) ) + { + return isDefined( level.zombie_weapons[ weaponname ].upgrade_name ); + } + if ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch && weapon_supports_attachments( weaponname ) ) + { + return 1; + } + return 0; +} + +will_upgrade_weapon_as_attachment( weaponname ) +{ + if ( isDefined( weaponname ) || weaponname == "" && weaponname == "zombie_fists_zm" ) + { + return 0; + } + weaponname = tolower( weaponname ); + weaponname = get_base_name( weaponname ); + if ( !is_weapon_upgraded( weaponname ) ) + { + return 0; + } + if ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch && weapon_supports_attachments( weaponname ) ) + { + return 1; + } + return 0; +} + +is_weapon_upgraded( weaponname ) +{ + if ( isDefined( weaponname ) || weaponname == "" && weaponname == "zombie_fists_zm" ) + { + return 0; + } + weaponname = tolower( weaponname ); + weaponname = get_base_name( weaponname ); + if ( isDefined( level.zombie_weapons_upgraded[ weaponname ] ) ) + { + return 1; + } + return 0; +} + +get_weapon_with_attachments( weaponname ) +{ + if ( self hasweapon( weaponname ) ) + { + return weaponname; + } + while ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch ) + { + weaponname = tolower( weaponname ); + weaponname = get_base_name( weaponname ); + weapons = self getweaponslist( 1 ); + _a2245 = weapons; + _k2245 = getFirstArrayKey( _a2245 ); + while ( isDefined( _k2245 ) ) + { + weapon = _a2245[ _k2245 ]; + weapon = tolower( weapon ); + weapon_base = get_base_name( weapon ); + if ( weaponname == weapon_base ) + { + return weapon; + } + _k2245 = getNextArrayKey( _a2245, _k2245 ); + } + } + return undefined; +} + +has_weapon_or_attachments( weaponname ) +{ + if ( self hasweapon( weaponname ) ) + { + return 1; + } + while ( isDefined( level.zombiemode_reusing_pack_a_punch ) && level.zombiemode_reusing_pack_a_punch ) + { + weaponname = tolower( weaponname ); + weaponname = get_base_name( weaponname ); + weapons = self getweaponslist( 1 ); + _a2267 = weapons; + _k2267 = getFirstArrayKey( _a2267 ); + while ( isDefined( _k2267 ) ) + { + weapon = _a2267[ _k2267 ]; + weapon = tolower( weapon ); + weapon = get_base_name( weapon ); + if ( weaponname == weapon ) + { + return 1; + } + _k2267 = getNextArrayKey( _a2267, _k2267 ); + } + } + return 0; +} + +has_upgrade( weaponname ) +{ + weaponname = get_base_name( weaponname ); + has_upgrade = 0; + if ( isDefined( level.zombie_weapons[ weaponname ] ) && isDefined( level.zombie_weapons[ weaponname ].upgrade_name ) ) + { + has_upgrade = self has_weapon_or_attachments( level.zombie_weapons[ weaponname ].upgrade_name ); + } + if ( !has_upgrade && weaponname == "knife_ballistic_zm" ) + { + has_weapon = self maps/mp/zombies/_zm_melee_weapon::has_upgraded_ballistic_knife(); + } + return has_upgrade; +} + +has_weapon_or_upgrade( weaponname ) +{ + weaponname = get_base_name( weaponname ); + upgradedweaponname = weaponname; + if ( isDefined( level.zombie_weapons[ weaponname ] ) && isDefined( level.zombie_weapons[ weaponname ].upgrade_name ) ) + { + upgradedweaponname = level.zombie_weapons[ weaponname ].upgrade_name; + } + has_weapon = 0; + if ( isDefined( level.zombie_weapons[ weaponname ] ) ) + { + if ( !self has_weapon_or_attachments( weaponname ) ) + { + has_weapon = self has_upgrade( weaponname ); + } + } + if ( !has_weapon && weaponname == "knife_ballistic_zm" ) + { + has_weapon = self maps/mp/zombies/_zm_melee_weapon::has_any_ballistic_knife(); + } + if ( !has_weapon && is_equipment( weaponname ) ) + { + has_weapon = self is_equipment_active( weaponname ); + } + return has_weapon; +} + +add_shared_ammo_weapon( str_weapon, str_base_weapon ) +{ + level.zombie_weapons[ str_weapon ].shared_ammo_weapon = str_base_weapon; +} + +get_shared_ammo_weapon( base_weapon ) +{ + base_weapon = get_base_name( base_weapon ); + weapons = self getweaponslist( 1 ); + _a2355 = weapons; + _k2355 = getFirstArrayKey( _a2355 ); + while ( isDefined( _k2355 ) ) + { + weapon = _a2355[ _k2355 ]; + weapon = tolower( weapon ); + weapon = get_base_name( weapon ); + if ( !isDefined( level.zombie_weapons[ weapon ] ) && isDefined( level.zombie_weapons_upgraded[ weapon ] ) ) + { + weapon = level.zombie_weapons_upgraded[ weapon ]; + } + if ( isDefined( level.zombie_weapons[ weapon ] ) && isDefined( level.zombie_weapons[ weapon ].shared_ammo_weapon ) && level.zombie_weapons[ weapon ].shared_ammo_weapon == base_weapon ) + { + return weapon; + } + _k2355 = getNextArrayKey( _a2355, _k2355 ); + } + return undefined; +} + +get_player_weapon_with_same_base( weaponname ) +{ + weaponname = tolower( weaponname ); + weaponname = get_base_name( weaponname ); + retweapon = get_weapon_with_attachments( weaponname ); + if ( !isDefined( retweapon ) ) + { + if ( isDefined( level.zombie_weapons[ weaponname ] ) ) + { + retweapon = get_weapon_with_attachments( level.zombie_weapons[ weaponname ].upgrade_name ); + } + else + { + if ( isDefined( level.zombie_weapons_upgraded[ weaponname ] ) ) + { + return get_weapon_with_attachments( level.zombie_weapons_upgraded[ weaponname ] ); + } + } + } + return retweapon; +} + +get_weapon_hint_ammo() +{ + if ( isDefined( level.has_pack_a_punch ) && !level.has_pack_a_punch ) + { + return &"ZOMBIE_WEAPONCOSTAMMO"; + } + else + { + return &"ZOMBIE_WEAPONCOSTAMMO_UPGRADE"; + } +} + +weapon_set_first_time_hint( cost, ammo_cost ) +{ + self sethintstring( get_weapon_hint_ammo(), cost, ammo_cost ); +} + +weapon_spawn_think() +{ + cost = get_weapon_cost( self.zombie_weapon_upgrade ); + ammo_cost = get_ammo_cost( self.zombie_weapon_upgrade ); + is_grenade = weapontype( self.zombie_weapon_upgrade ) == "grenade"; + shared_ammo_weapon = undefined; + second_endon = undefined; + if ( isDefined( self.stub ) ) + { + second_endon = "kill_trigger"; + self.first_time_triggered = self.stub.first_time_triggered; + } + if ( isDefined( self.stub ) && isDefined( self.stub.trigger_per_player ) && self.stub.trigger_per_player ) + { + self thread decide_hide_show_hint( "stop_hint_logic", second_endon, self.parent_player ); + } + else + { + self thread decide_hide_show_hint( "stop_hint_logic", second_endon ); + } + if ( is_grenade ) + { + self.first_time_triggered = 0; + hint = get_weapon_hint( self.zombie_weapon_upgrade ); + self sethintstring( hint, cost ); + } + else if ( !isDefined( self.first_time_triggered ) ) + { + self.first_time_triggered = 0; + if ( isDefined( self.stub ) ) + { + self.stub.first_time_triggered = 0; + } + } + else + { + if ( self.first_time_triggered ) + { + if ( isDefined( level.use_legacy_weapon_prompt_format ) && level.use_legacy_weapon_prompt_format ) + { + self weapon_set_first_time_hint( cost, get_ammo_cost( self.zombie_weapon_upgrade ) ); + } + } + } + for ( ;; ) + { + self waittill( "trigger", player ); + if ( !is_player_valid( player ) ) + { + player thread ignore_triggers( 0.5 ); + continue; + } + else if ( !player can_buy_weapon() ) + { + wait 0.1; + continue; + } + else if ( isDefined( self.stub ) && isDefined( self.stub.require_look_from ) && self.stub.require_look_from ) + { + toplayer = player get_eye() - self.origin; + forward = -1 * anglesToRight( self.angles ); + dot = vectordot( toplayer, forward ); + if ( dot < 0 ) + { + continue; + } + } + else if ( player has_powerup_weapon() ) + { + wait 0.1; + continue; + } + else + { + player_has_weapon = player has_weapon_or_upgrade( self.zombie_weapon_upgrade ); + if ( !player_has_weapon && isDefined( level.weapons_using_ammo_sharing ) && level.weapons_using_ammo_sharing ) + { + shared_ammo_weapon = player get_shared_ammo_weapon( self.zombie_weapon_upgrade ); + if ( isDefined( shared_ammo_weapon ) ) + { + player_has_weapon = 1; + } + } + if ( isDefined( level.pers_upgrade_nube ) && level.pers_upgrade_nube ) + { + player_has_weapon = maps/mp/zombies/_zm_pers_upgrades_functions::pers_nube_should_we_give_raygun( player_has_weapon, player, self.zombie_weapon_upgrade ); + } + cost = get_weapon_cost( self.zombie_weapon_upgrade ); + if ( player maps/mp/zombies/_zm_pers_upgrades_functions::is_pers_double_points_active() ) + { + cost = int( cost / 2 ); + } + if ( !player_has_weapon ) + { + if ( player.score >= cost ) + { + if ( self.first_time_triggered == 0 ) + { + self show_all_weapon_buys( player, cost, ammo_cost, is_grenade ); + } + player maps/mp/zombies/_zm_score::minus_to_player_score( cost, 1 ); + bbprint( "zombie_uses", "playername %s playerscore %d round %d cost %d name %s x %f y %f z %f type %s", player.name, player.score, level.round_number, cost, self.zombie_weapon_upgrade, self.origin, "weapon" ); + level notify( "weapon_bought" ); + if ( self.zombie_weapon_upgrade == "riotshield_zm" ) + { + player maps/mp/zombies/_zm_equipment::equipment_give( "riotshield_zm" ); + if ( isDefined( player.player_shield_reset_health ) ) + { + player [[ player.player_shield_reset_health ]](); + } + } + else if ( self.zombie_weapon_upgrade == "jetgun_zm" ) + { + player maps/mp/zombies/_zm_equipment::equipment_give( "jetgun_zm" ); + } + else + { + if ( is_lethal_grenade( self.zombie_weapon_upgrade ) ) + { + player takeweapon( player get_player_lethal_grenade() ); + player set_player_lethal_grenade( self.zombie_weapon_upgrade ); + } + str_weapon = self.zombie_weapon_upgrade; + if ( isDefined( level.pers_upgrade_nube ) && level.pers_upgrade_nube ) + { + str_weapon = maps/mp/zombies/_zm_pers_upgrades_functions::pers_nube_weapon_upgrade_check( player, str_weapon ); + } + player weapon_give( str_weapon ); + } + player maps/mp/zombies/_zm_stats::increment_client_stat( "wallbuy_weapons_purchased" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "wallbuy_weapons_purchased" ); + } + else + { + play_sound_on_ent( "no_purchase" ); + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "no_money_weapon" ); + } + } + else str_weapon = self.zombie_weapon_upgrade; + if ( isDefined( shared_ammo_weapon ) ) + { + str_weapon = shared_ammo_weapon; + } + if ( isDefined( level.pers_upgrade_nube ) && level.pers_upgrade_nube ) + { + str_weapon = maps/mp/zombies/_zm_pers_upgrades_functions::pers_nube_weapon_ammo_check( player, str_weapon ); + } + if ( isDefined( self.hacked ) && self.hacked ) + { + if ( !player has_upgrade( str_weapon ) ) + { + ammo_cost = 4500; + } + else + { + ammo_cost = get_ammo_cost( str_weapon ); + } + } + else + { + if ( player has_upgrade( str_weapon ) ) + { + ammo_cost = 4500; + break; + } + else + { + ammo_cost = get_ammo_cost( str_weapon ); + } + } + if ( isDefined( player.pers_upgrades_awarded[ "nube" ] ) && player.pers_upgrades_awarded[ "nube" ] ) + { + ammo_cost = maps/mp/zombies/_zm_pers_upgrades_functions::pers_nube_override_ammo_cost( player, self.zombie_weapon_upgrade, ammo_cost ); + } + if ( player maps/mp/zombies/_zm_pers_upgrades_functions::is_pers_double_points_active() ) + { + ammo_cost = int( ammo_cost / 2 ); + } + if ( str_weapon == "riotshield_zm" ) + { + play_sound_on_ent( "no_purchase" ); + } + else if ( player.score >= ammo_cost ) + { + if ( self.first_time_triggered == 0 ) + { + self show_all_weapon_buys( player, cost, ammo_cost, is_grenade ); + } + if ( player has_upgrade( str_weapon ) ) + { + player maps/mp/zombies/_zm_stats::increment_client_stat( "upgraded_ammo_purchased" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "upgraded_ammo_purchased" ); + } + else + { + player maps/mp/zombies/_zm_stats::increment_client_stat( "ammo_purchased" ); + player maps/mp/zombies/_zm_stats::increment_player_stat( "ammo_purchased" ); + } + if ( str_weapon == "riotshield_zm" ) + { + if ( isDefined( player.player_shield_reset_health ) ) + { + ammo_given = player [[ player.player_shield_reset_health ]](); + } + else + { + ammo_given = 0; + } + } + else if ( player has_upgrade( str_weapon ) ) + { + ammo_given = player ammo_give( level.zombie_weapons[ str_weapon ].upgrade_name ); + } + else + { + ammo_given = player ammo_give( str_weapon ); + } + if ( ammo_given ) + { + player maps/mp/zombies/_zm_score::minus_to_player_score( ammo_cost, 1 ); + bbprint( "zombie_uses", "playername %s playerscore %d round %d cost %d name %s x %f y %f z %f type %s", player.name, player.score, level.round_number, ammo_cost, str_weapon, self.origin, "ammo" ); + } + } + else play_sound_on_ent( "no_purchase" ); + if ( isDefined( level.custom_generic_deny_vo_func ) ) + { + player [[ level.custom_generic_deny_vo_func ]](); + } + else + { + player maps/mp/zombies/_zm_audio::create_and_play_dialog( "general", "no_money_weapon" ); + } + if ( isDefined( self.stub ) && isDefined( self.stub.prompt_and_visibility_func ) ) + { + self [[ self.stub.prompt_and_visibility_func ]]( player ); + } + } + } +} + +show_all_weapon_buys( player, cost, ammo_cost, is_grenade ) +{ + model = getent( self.target, "targetname" ); + if ( isDefined( model ) ) + { + model thread weapon_show( player ); + } + else + { + if ( isDefined( self.clientfieldname ) ) + { + level setclientfield( self.clientfieldname, 1 ); + } + } + self.first_time_triggered = 1; + if ( isDefined( self.stub ) ) + { + self.stub.first_time_triggered = 1; + } + if ( !is_grenade ) + { + self weapon_set_first_time_hint( cost, ammo_cost ); + } + if ( isDefined( level.dont_link_common_wallbuys ) && !level.dont_link_common_wallbuys && isDefined( level._spawned_wallbuys ) ) + { + i = 0; + while ( i < level._spawned_wallbuys.size ) + { + wallbuy = level._spawned_wallbuys[ i ]; + if ( isDefined( self.stub ) && isDefined( wallbuy.trigger_stub ) && self.stub.clientfieldname == wallbuy.trigger_stub.clientfieldname ) + { + i++; + continue; + } + else + { + if ( self.zombie_weapon_upgrade == wallbuy.zombie_weapon_upgrade ) + { + if ( isDefined( wallbuy.trigger_stub ) && isDefined( wallbuy.trigger_stub.clientfieldname ) ) + { + level setclientfield( wallbuy.trigger_stub.clientfieldname, 1 ); + } + else + { + if ( isDefined( wallbuy.target ) ) + { + model = getent( wallbuy.target, "targetname" ); + if ( isDefined( model ) ) + { + model thread weapon_show( player ); + } + } + } + if ( isDefined( wallbuy.trigger_stub ) ) + { + wallbuy.trigger_stub.first_time_triggered = 1; + if ( isDefined( wallbuy.trigger_stub.trigger ) ) + { + wallbuy.trigger_stub.trigger.first_time_triggered = 1; + if ( !is_grenade ) + { + wallbuy.trigger_stub.trigger weapon_set_first_time_hint( cost, ammo_cost ); + } + } + i++; + continue; + } + else + { + if ( !is_grenade ) + { + wallbuy weapon_set_first_time_hint( cost, ammo_cost ); + } + } + } + } + i++; + } + } +} + +weapon_show( player ) +{ + player_angles = vectorToAngles( player.origin - self.origin ); + player_yaw = player_angles[ 1 ]; + weapon_yaw = self.angles[ 1 ]; + if ( isDefined( self.script_int ) ) + { + weapon_yaw -= self.script_int; + } + yaw_diff = absAngleClamp180( player_yaw - weapon_yaw ); + if ( yaw_diff > 0 ) + { + yaw = weapon_yaw - 90; + } + else + { + yaw = weapon_yaw + 90; + } + self.og_origin = self.origin; + self.origin += anglesToForward( ( 0, yaw, 0 ) ) * 8; + wait 0.05; + self show(); + play_sound_at_pos( "weapon_show", self.origin, self ); + time = 1; + if ( !isDefined( self._linked_ent ) ) + { + self moveto( self.og_origin, time ); + } +} + +get_pack_a_punch_weapon_options( weapon ) +{ + if ( !isDefined( self.pack_a_punch_weapon_options ) ) + { + self.pack_a_punch_weapon_options = []; + } + if ( !is_weapon_upgraded( weapon ) ) + { + return self calcweaponoptions( 0, 0, 0, 0, 0 ); + } + if ( isDefined( self.pack_a_punch_weapon_options[ weapon ] ) ) + { + return self.pack_a_punch_weapon_options[ weapon ]; + } + smiley_face_reticle_index = 1; + base = get_base_name( weapon ); + camo_index = 39; + if ( level.script == "zm_prison" ) + { + camo_index = 40; + } + else + { + if ( level.script == "zm_tomb" ) + { + camo_index = 45; + } + } + lens_index = randomintrange( 0, 6 ); + reticle_index = randomintrange( 0, 16 ); + reticle_color_index = randomintrange( 0, 6 ); + plain_reticle_index = 16; + r = randomint( 10 ); + use_plain = r < 3; + if ( base == "saritch_upgraded_zm" ) + { + reticle_index = smiley_face_reticle_index; + } + else + { + if ( use_plain ) + { + reticle_index = plain_reticle_index; + } + } +/* +/# + if ( getDvarInt( #"471F9AB9" ) >= 0 ) + { + reticle_index = getDvarInt( #"471F9AB9" ); +#/ + } +*/ + scary_eyes_reticle_index = 8; + purple_reticle_color_index = 3; + if ( reticle_index == scary_eyes_reticle_index ) + { + reticle_color_index = purple_reticle_color_index; + } + letter_a_reticle_index = 2; + pink_reticle_color_index = 6; + if ( reticle_index == letter_a_reticle_index ) + { + reticle_color_index = pink_reticle_color_index; + } + letter_e_reticle_index = 7; + green_reticle_color_index = 1; + if ( reticle_index == letter_e_reticle_index ) + { + reticle_color_index = green_reticle_color_index; + } + self.pack_a_punch_weapon_options[ weapon ] = self calcweaponoptions( camo_index, lens_index, reticle_index, reticle_color_index ); + return self.pack_a_punch_weapon_options[ weapon ]; +} + +weapon_give( weapon, is_upgrade, magic_box, nosound ) +{ + primaryweapons = self getweaponslistprimaries(); + current_weapon = self getcurrentweapon(); + current_weapon = self maps/mp/zombies/_zm_weapons::switch_from_alt_weapon( current_weapon ); + /* +/# + assert( self player_can_use_content( weapon ) ); +#/ + */ + if ( !isDefined( is_upgrade ) ) + { + is_upgrade = 0; + } + weapon_limit = get_player_weapon_limit( self ); + if ( is_equipment( weapon ) ) + { + self maps/mp/zombies/_zm_equipment::equipment_give( weapon ); + } + if ( weapon == "riotshield_zm" ) + { + if ( isDefined( self.player_shield_reset_health ) ) + { + self [[ self.player_shield_reset_health ]](); + } + } + if ( self hasweapon( weapon ) ) + { + if ( issubstr( weapon, "knife_ballistic_" ) ) + { + self notify( "zmb_lost_knife" ); + } + self givestartammo( weapon ); + if ( !is_offhand_weapon( weapon ) ) + { + self switchtoweapon( weapon ); + } + return; + } + if ( is_melee_weapon( weapon ) ) + { + current_weapon = maps/mp/zombies/_zm_melee_weapon::change_melee_weapon( weapon, current_weapon ); + } + else if ( is_lethal_grenade( weapon ) ) + { + old_lethal = self get_player_lethal_grenade(); + if ( isDefined( old_lethal ) && old_lethal != "" ) + { + self takeweapon( old_lethal ); + unacquire_weapon_toggle( old_lethal ); + } + self set_player_lethal_grenade( weapon ); + } + else if ( is_tactical_grenade( weapon ) ) + { + old_tactical = self get_player_tactical_grenade(); + if ( isDefined( old_tactical ) && old_tactical != "" ) + { + self takeweapon( old_tactical ); + unacquire_weapon_toggle( old_tactical ); + } + self set_player_tactical_grenade( weapon ); + } + else + { + if ( is_placeable_mine( weapon ) ) + { + old_mine = self get_player_placeable_mine(); + if ( isDefined( old_mine ) ) + { + self takeweapon( old_mine ); + unacquire_weapon_toggle( old_mine ); + } + self set_player_placeable_mine( weapon ); + } + } + if ( !is_offhand_weapon( weapon ) ) + { + self maps/mp/zombies/_zm_weapons::take_fallback_weapon(); + } + if ( primaryweapons.size >= weapon_limit ) + { + if ( is_placeable_mine( current_weapon ) || is_equipment( current_weapon ) ) + { + current_weapon = undefined; + } + if ( isDefined( current_weapon ) ) + { + if ( !is_offhand_weapon( weapon ) ) + { + if ( current_weapon == "tesla_gun_zm" ) + { + level.player_drops_tesla_gun = 1; + } + if ( issubstr( current_weapon, "knife_ballistic_" ) ) + { + self notify( "zmb_lost_knife" ); + } + self takeweapon( current_weapon ); + unacquire_weapon_toggle( current_weapon ); + } + } + } + if ( isDefined( level.zombiemode_offhand_weapon_give_override ) ) + { + if ( self [[ level.zombiemode_offhand_weapon_give_override ]]( weapon ) ) + { + return; + } + } + if ( weapon == "cymbal_monkey_zm" ) + { + self maps/mp/zombies/_zm_weap_cymbal_monkey::player_give_cymbal_monkey(); + self play_weapon_vo( weapon, magic_box ); + return; + } + else if ( issubstr( weapon, "knife_ballistic_" ) ) + { + weapon = self maps/mp/zombies/_zm_melee_weapon::give_ballistic_knife( weapon, issubstr( weapon, "upgraded" ) ); + } + else + { + if ( weapon == "claymore_zm" ) + { + self thread maps/mp/zombies/_zm_weap_claymore::claymore_setup(); + self play_weapon_vo( weapon, magic_box ); + return; + } + } + if ( isDefined( level.zombie_weapons_callbacks ) && isDefined( level.zombie_weapons_callbacks[ weapon ] ) ) + { + self thread [[ level.zombie_weapons_callbacks[ weapon ] ]](); + play_weapon_vo( weapon, magic_box ); + return; + } + if ( isDefined( nosound ) && !nosound ) + { + self play_sound_on_ent( "purchase" ); + } + if ( weapon == "ray_gun_zm" ) + { + playsoundatposition( "mus_raygun_stinger", ( 0, 0, 0 ) ); + } + if ( !is_weapon_upgraded( weapon ) ) + { + self giveweapon( weapon ); + } + else + { + self giveweapon( weapon, 0, self get_pack_a_punch_weapon_options( weapon ) ); + } + acquire_weapon_toggle( weapon, self ); + self givestartammo( weapon ); + if ( !is_offhand_weapon( weapon ) ) + { + if ( !is_melee_weapon( weapon ) ) + { + self switchtoweapon( weapon ); + } + else + { + self switchtoweapon( current_weapon ); + } + } + self play_weapon_vo( weapon, magic_box ); +} + +play_weapon_vo( weapon, magic_box ) +{ + if ( isDefined( level._audio_custom_weapon_check ) ) + { + type = self [[ level._audio_custom_weapon_check ]]( weapon, magic_box ); + } + else + { + type = self weapon_type_check( weapon ); + } + if ( type == "crappy" ) + { + return; + } + if ( type != "favorite" && type != "upgrade" ) + { + type = weapon; + } + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "weapon_pickup", type ); +} + +weapon_type_check( weapon ) +{ + if ( !isDefined( self.entity_num ) ) + { + return "crappy"; + } + weapon = get_base_name( weapon ); + if ( self is_favorite_weapon( weapon ) ) + { + return "favorite"; + } + if ( issubstr( weapon, "upgraded" ) ) + { + return "upgrade"; + } + else + { + return level.zombie_weapons[ weapon ].vox; + } +} + +get_player_index( player ) +{ +/* +/# + assert( isplayer( player ) ); +#/ +/# + assert( isDefined( player.characterindex ) ); +#/ +/# + if ( player.entity_num == 0 && getDvar( #"2222BA21" ) != "" ) + { + new_vo_index = getDvarInt( #"2222BA21" ); + return new_vo_index; +#/ + } + */ + return player.characterindex; +} + +ammo_give( weapon ) +{ + give_ammo = 0; + if ( !is_offhand_weapon( weapon ) ) + { + weapon = get_weapon_with_attachments( weapon ); + if ( isDefined( weapon ) ) + { + stockmax = 0; + stockmax = weaponstartammo( weapon ); + clipcount = self getweaponammoclip( weapon ); + currstock = self getammocount( weapon ); + if ( ( currstock - clipcount ) >= stockmax ) + { + give_ammo = 0; + } + else + { + give_ammo = 1; + } + } + } + else + { + if ( self has_weapon_or_upgrade( weapon ) ) + { + if ( self getammocount( weapon ) < weaponmaxammo( weapon ) ) + { + give_ammo = 1; + } + } + } + if ( give_ammo ) + { + self play_sound_on_ent( "purchase" ); + self givemaxammo( weapon ); + alt_weap = weaponaltweaponname( weapon ); + if ( alt_weap != "none" ) + { + self givemaxammo( alt_weap ); + } + return 1; + } + if ( !give_ammo ) + { + return 0; + } +} + +get_player_weapondata( player, weapon ) +{ + weapondata = []; + if ( !isDefined( weapon ) ) + { + weapondata[ "name" ] = player getcurrentweapon(); + } + else + { + weapondata[ "name" ] = weapon; + } + weapondata[ "dw_name" ] = weapondualwieldweaponname( weapondata[ "name" ] ); + weapondata[ "alt_name" ] = weaponaltweaponname( weapondata[ "name" ] ); + if ( weapondata[ "name" ] != "none" ) + { + weapondata[ "clip" ] = player getweaponammoclip( weapondata[ "name" ] ); + weapondata[ "stock" ] = player getweaponammostock( weapondata[ "name" ] ); + weapondata[ "fuel" ] = player getweaponammofuel( weapondata[ "name" ] ); + weapondata[ "heat" ] = player isweaponoverheating( 1, weapondata[ "name" ] ); + weapondata[ "overheat" ] = player isweaponoverheating( 0, weapondata[ "name" ] ); + } + else + { + weapondata[ "clip" ] = 0; + weapondata[ "stock" ] = 0; + weapondata[ "fuel" ] = 0; + weapondata[ "heat" ] = 0; + weapondata[ "overheat" ] = 0; + } + if ( weapondata[ "dw_name" ] != "none" ) + { + weapondata[ "lh_clip" ] = player getweaponammoclip( weapondata[ "dw_name" ] ); + } + else + { + weapondata[ "lh_clip" ] = 0; + } + if ( weapondata[ "alt_name" ] != "none" ) + { + weapondata[ "alt_clip" ] = player getweaponammoclip( weapondata[ "alt_name" ] ); + weapondata[ "alt_stock" ] = player getweaponammostock( weapondata[ "alt_name" ] ); + } + else + { + weapondata[ "alt_clip" ] = 0; + weapondata[ "alt_stock" ] = 0; + } + return weapondata; +} + +weapon_is_better( left, right ) +{ + if ( left != right ) + { + left_upgraded = !isDefined( level.zombie_weapons[ left ] ); + right_upgraded = !isDefined( level.zombie_weapons[ right ] ); + if ( left_upgraded && right_upgraded ) + { + leftatt = get_attachment_index( left ); + rightatt = get_attachment_index( right ); + return leftatt > rightatt; + } + else + { + if ( left_upgraded ) + { + return 1; + } + } + } + return 0; +} + +merge_weapons( oldweapondata, newweapondata ) +{ + weapondata = []; + weapondata[ "name" ] = "none"; + if ( weapon_is_better( oldweapondata[ "name" ], newweapondata[ "name" ] ) ) + { + weapondata[ "name" ] = oldweapondata[ "name" ]; + } + else + { + weapondata[ "name" ] = newweapondata[ "name" ]; + } + name = weapondata[ "name" ]; + dw_name = weapondualwieldweaponname( name ); + alt_name = weaponaltweaponname( name ); + if ( name != "none" ) + { + weapondata[ "clip" ] = newweapondata[ "clip" ] + oldweapondata[ "clip" ]; + weapondata[ "clip" ] = int( min( weapondata[ "clip" ], weaponclipsize( name ) ) ); + weapondata[ "stock" ] = newweapondata[ "stock" ] + oldweapondata[ "stock" ]; + weapondata[ "stock" ] = int( min( weapondata[ "stock" ], weaponmaxammo( name ) ) ); + weapondata[ "fuel" ] = newweapondata[ "fuel" ] + oldweapondata[ "fuel" ]; + weapondata[ "fuel" ] = int( min( weapondata[ "fuel" ], weaponfuellife( name ) ) ); + weapondata[ "heat" ] = int( min( newweapondata[ "heat" ], oldweapondata[ "heat" ] ) ); + weapondata[ "overheat" ] = int( min( newweapondata[ "overheat" ], oldweapondata[ "overheat" ] ) ); + } + if ( dw_name != "none" ) + { + weapondata[ "lh_clip" ] = newweapondata[ "lh_clip" ] + oldweapondata[ "lh_clip" ]; + weapondata[ "lh_clip" ] = int( min( weapondata[ "lh_clip" ], weaponclipsize( dw_name ) ) ); + } + if ( alt_name != "none" ) + { + weapondata[ "alt_clip" ] = newweapondata[ "alt_clip" ] + oldweapondata[ "alt_clip" ]; + weapondata[ "alt_clip" ] = int( min( weapondata[ "alt_clip" ], weaponclipsize( alt_name ) ) ); + weapondata[ "alt_stock" ] = newweapondata[ "alt_stock" ] + oldweapondata[ "alt_stock" ]; + weapondata[ "alt_stock" ] = int( min( weapondata[ "alt_stock" ], weaponmaxammo( alt_name ) ) ); + } + return weapondata; +} + +weapondata_give( weapondata ) +{ + current = get_player_weapon_with_same_base( weapondata[ "name" ] ); + if ( isDefined( current ) ) + { + curweapondata = get_player_weapondata( self, current ); + self takeweapon( current ); + weapondata = merge_weapons( curweapondata, weapondata ); + } + name = weapondata[ "name" ]; + weapon_give( name, undefined, undefined, 1 ); + dw_name = weapondualwieldweaponname( name ); + alt_name = weaponaltweaponname( name ); + if ( name != "none" ) + { + self setweaponammoclip( name, weapondata[ "clip" ] ); + self setweaponammostock( name, weapondata[ "stock" ] ); + if ( isDefined( weapondata[ "fuel" ] ) ) + { + self setweaponammofuel( name, weapondata[ "fuel" ] ); + } + if ( isDefined( weapondata[ "heat" ] ) && isDefined( weapondata[ "overheat" ] ) ) + { + self setweaponoverheating( weapondata[ "overheat" ], weapondata[ "heat" ], name ); + } + } + if ( dw_name != "none" ) + { + self setweaponammoclip( dw_name, weapondata[ "lh_clip" ] ); + } + if ( alt_name != "none" ) + { + self setweaponammoclip( alt_name, weapondata[ "alt_clip" ] ); + self setweaponammostock( alt_name, weapondata[ "alt_stock" ] ); + } +} + +register_zombie_weapon_callback( str_weapon, func ) +{ + if ( !isDefined( level.zombie_weapons_callbacks ) ) + { + level.zombie_weapons_callbacks = []; + } + if ( !isDefined( level.zombie_weapons_callbacks[ str_weapon ] ) ) + { + level.zombie_weapons_callbacks[ str_weapon ] = func; + } +} + + + diff --git a/patch_zm/readme.md b/patch_zm/readme.md new file mode 100644 index 0000000..fb1a72b --- /dev/null +++ b/patch_zm/readme.md @@ -0,0 +1,51 @@ +### The following gscs compile and run successfully with no known errors: +``` +patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_scoreboard.gsc +patch_zm/maps/mp/gametypes_zm/NoKnownErrors/_shellshock.gsc +patch_zm/maps/mp/gametypes_zm/NoKnownErrors/zclassic.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_basic.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_dogs.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_ai_faller.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_bot.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_equip_hacker.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_boards.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_box.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_doors.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_packapunch.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_perks.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_powerups.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_hackables_wallbuys.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_perk_electric_cherry.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_functions.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_pers_upgrades_system.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_score.gsc +patch_zm/maps/mp/zombies/NoKnownErrors/_zm_tombstone.gsc +``` +### The following scripts compile and run successfully with minor errors: +``` +patch_zm/maps/mp/zombies/MinorErorrs/_zm_timer.gsc +``` +### The following scripts compile and run successfully with major errors: +``` +patch_zm/maps/mp/gametypes_zm/MajorErrors/_zm_gametype.gsc +patch_zm/maps/mp/zombies/MajorErrors/_zm_magicbox.gsc +patch_zm/maps/mp/zombies/MajorErrors/_zm_perks.gsc +patch_zm/maps/mp/zombies/MajorErrors/_zm_powerups.gsc +patch_zm/maps/mp/zombies/MajorErrors/_zm_weapons.gsc +``` +### The following scripts compile and run serverside but clients cannot join due to exe_client_field_mismatch +``` +patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm.gsc +patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm_gump.gsc +patch_zm/maps/mp/zombies/exe_client_field_mismatch/_zm_equipment.gsc +``` +### The following scripts compile but cause a minidump or other severe error: +``` +patch_zm/maps/mp/zombies/SevereErrors/_load.gsc +``` + +### notes: +``` +The shaders that _zm_timer.gsc relies on do not exist. +``` diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e21d89f --- /dev/null +++ b/readme.md @@ -0,0 +1,25 @@ +### About this project + +The way scripts are categorized is based on their current functionality. +The objective of this project is to get as many scripts in the No Known Erorrs category. +Eventually, once scripts have been tested even more thoroughly there will be a new category for scripts that have parity with the original scripts. + +The categories are: + +No Known Errors: This means that during a short gameplay test no errors are observed. +It can also mean that the script is unused such as the _hackables series meaning that while they are being parsed nothing is calling them. + +Minor Errors: Indicates that the scripts are functional but perhaps there is a typo in text shown on screen or other ui error. +It means that while the script doesn't have 100% parity with the base script it nears 100% and all the expected core functionality of the script works. + +Major Errors: The scripts' core functionality is missing or broken so that anything from crashes occur during gameplay or perks not working. +Any script categorized as having major errors is not yet in a playable state unlike scripts with only Minor or No Known Errors. + +exe_client_field_mismatch: This is a specific error that doesn't have a specific cause. +Scripts that cause this error will run serverside but clients cannot join due to this error. + +Severe Errors: Minidump, hang on map_rotate, crash, or other error that prevents the server from starting up is in this category. +This type of error can be caused by many different things + +Each script will be sorted by its location e.g. patch_zm/maps/mp/zombies and then sorted by error type so it would look like this: +patch_zm/maps/mp/zombies/MinorErrors/_zm_timer.gsc \ No newline at end of file diff --git a/zm_highrise_patch/maps/mp/zombies/_zm_weap_slipgun.gsc b/zm_highrise_patch/maps/mp/zombies/_zm_weap_slipgun.gsc new file mode 100644 index 0000000..8fda028 --- /dev/null +++ b/zm_highrise_patch/maps/mp/zombies/_zm_weap_slipgun.gsc @@ -0,0 +1,891 @@ +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_ai_basic; +#include maps/mp/animscripts/zm_shared; +#include maps/mp/animscripts/zm_utility; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_spawner; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +set_zombie_var_once( var, value, is_float, column, is_team_based ) +{ + if ( !isDefined( level.zombie_vars ) || !isDefined( level.zombie_vars[ var ] ) ) + { + set_zombie_var( var, value, is_float, column, is_team_based ); + } +} + +init() +{ + if ( !maps/mp/zombies/_zm_weapons::is_weapon_included( "slipgun_zm" ) ) + { + return; + } + precachemodel( "t5_weapon_crossbow_bolt" ); + precacheitem( "slip_bolt_zm" ); + precacheitem( "slip_bolt_upgraded_zm" ); + if ( is_true( level.slipgun_as_equipment ) ) + { + maps/mp/zombies/_zm_equipment::register_equipment( "slipgun_zm", &"ZM_HIGHRISE_EQUIP_SLIPGUN_PICKUP_HINT_STRING", &"ZM_HIGHRISE_EQUIP_SLIPGUN_HOWTO", "jetgun_zm_icon", "slipgun", ::slipgun_activation_watcher_thread, ::transferslipgun, ::dropslipgun, ::pickupslipgun ); + maps/mp/zombies/_zm_equipment::enemies_ignore_equipment( "slipgun_zm" ); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "slipgun", &"ZM_HIGHRISE_EQUIP_SLIPGUN_PICKUP_HINT_STRING" ); + } + set_zombie_var_once( "slipgun_reslip_max_spots", 8 ); + set_zombie_var_once( "slipgun_reslip_rate", 6 ); + set_zombie_var_once( "slipgun_max_kill_chain_depth", 16 ); + set_zombie_var_once( "slipgun_max_kill_round", 100 ); + set_zombie_var_once( "slipgun_chain_radius", 120 ); + set_zombie_var_once( "slipgun_chain_wait_min", 0.75, 1 ); + set_zombie_var_once( "slipgun_chain_wait_max", 1.5, 1 ); + level.slippery_spot_count = 0; + level.sliquifier_distance_checks = 0; + maps/mp/zombies/_zm_spawner::register_zombie_damage_callback( ::slipgun_zombie_damage_response ); + maps/mp/zombies/_zm_spawner::register_zombie_death_animscript_callback( ::slipgun_zombie_death_response ); + level._effect[ "slipgun_explode" ] = loadfx( "weapon/liquifier/fx_liquifier_goo_explo" ); + level._effect[ "slipgun_splatter" ] = loadfx( "maps/zombie/fx_zmb_goo_splat" ); + level._effect[ "slipgun_simmer" ] = loadfx( "weapon/liquifier/fx_liquifier_goo_sizzle" ); + level._effect[ "slipgun_viewmodel_eject" ] = loadfx( "weapon/liquifier/fx_liquifier_clip_eject" ); + level._effect[ "slipgun_viewmodel_reload" ] = loadfx( "weapon/liquifier/fx_liquifier_reload_steam" ); + onplayerconnect_callback( ::slipgun_player_connect ); + thread wait_init_damage(); +} + +wait_init_damage() +{ + while ( !isDefined( level.zombie_vars ) || !isDefined( level.zombie_vars[ "zombie_health_start" ] ) ) + { + wait 1; + } + wait 1; + level.slipgun_damage = maps/mp/zombies/_zm::ai_zombie_health( level.zombie_vars[ "slipgun_max_kill_round" ] ); + level.slipgun_damage_mod = "MOD_PROJECTILE_SPLASH"; +} + +slipgun_player_connect() +{ + self thread watch_for_slip_bolt(); +} + +watch_for_slip_bolt() +{ + self endon( "death" ); + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "grenade_fire", grenade, weaponname, parent ); + self.num_sliquifier_kills = 0; + switch( weaponname ) + { + case "slip_bolt_zm": + grenade thread slip_bolt( self, 0 ); + break; + continue; + case "slip_bolt_upgraded_zm": + grenade thread slip_bolt( self, 1 ); + break; + continue; + } + } +} + +slip_bolt( player, upgraded ) +{ + startpos = player getweaponmuzzlepoint(); + self waittill( "explode", position ); + duration = 24; + if ( upgraded ) + { + duration = 36; + } + thread add_slippery_spot( position, duration, startpos ); +} + +dropslipgun() +{ + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "t6_wpn_zmb_slipgun_world", "slipgun_zm", self.origin + vectorScale( ( 0, 0, 1 ), 30 ), self.angles ); + if ( isDefined( item ) ) + { + item.original_owner = self; + item.owner = undefined; + item.name = "slipgun_zm"; + item.requires_pickup = 1; + item.clipammo = self getweaponammoclip( item.name ); + item.stockammo = self getweaponammostock( item.name ); + } + self takeweapon( "slipgun_zm" ); + return item; +} + +pickupslipgun( item ) +{ + item.owner = self; + self giveweapon( item.name ); + if ( isDefined( item.clipammo ) && isDefined( item.stockammo ) ) + { + self setweaponammoclip( item.name, item.clipammo ); + self setweaponammostock( item.name, item.stockammo ); + item.clipammo = undefined; + item.stockammo = undefined; + } +} + +transferslipgun( fromplayer, toplayer ) +{ + toplayer notify( "slipgun_zm_taken" ); + fromplayer notify( "slipgun_zm_taken" ); +} + +slipgun_activation_watcher_thread() +{ + self endon( "zombified" ); + self endon( "disconnect" ); + self endon( "slipgun_zm_taken" ); + while ( 1 ) + { + self waittill_either( "slipgun_zm_activate", "slipgun_zm_deactivate" ); + } +} + +slipgun_debug_circle( origin, radius, seconds, onslope, parent, start ) +{ +/* +/# + if ( getDvarInt( #"6136A815" ) ) + { + frames = int( 20 * seconds ); + if ( isDefined( parent ) ) + { + time = seconds; + frames = 1; + while ( time > 0 ) + { + morigin = origin + ( parent.origin - start ); + if ( isDefined( onslope ) && onslope ) + { + circle( morigin, radius, ( 0, 0, 1 ), 0, 1, frames ); + } + else + { + circle( morigin, radius, ( 0, 0, 1 ), 0, 1, frames ); + } + time -= 0,05; + wait 0,05; + } + } + else if ( isDefined( onslope ) && onslope ) + { + circle( origin, radius, ( 0, 0, 1 ), 0, 1, frames ); + return; + } + else + { + circle( origin, radius, ( 0, 0, 1 ), 0, 1, frames ); +#/ + } + } +*/ +} + +slipgun_debug_line( start, end, color, seconds ) +{ +/* +/# + if ( getDvarInt( #"6136A815" ) ) + { + frames = int( 20 * seconds ); + line( start, end, color, 1, 0, frames ); +#/ + } +*/ +} + +canzombieongoofall() +{ + if ( is_true( self.is_inert ) ) + { + return 0; + } + if ( is_true( self.is_traversing ) ) + { + return 0; + } + if ( is_true( self.barricade_enter ) ) + { + return 0; + } + if ( randomint( 100 ) < 20 ) + { + trace = groundtrace( self.origin + vectorScale( ( 0, 0, 1 ), 5 ), self.origin + vectorScale( ( 0, 0, 1 ), 300 ), 0, undefined ); + origin = trace[ "position" ]; + groundnormal = trace[ "normal" ]; + if ( distancesquared( self.origin, origin ) > 256 ) + { + return 0; + } + dot = vectordot( ( 0, 0, 1 ), groundnormal ); + if ( dot < 0.9 ) + { + return 0; + } + trace_origin = self.origin + vectorScale( anglesToForward( self.angles ), 200 ); + trace = groundtrace( trace_origin + vectorScale( ( 0, 0, 1 ), 5 ), self.origin + vectorScale( ( 0, 0, 1 ), 300 ), 0, undefined ); + origin = trace[ "position" ]; + groundnormal = trace[ "normal" ]; + if ( distancesquared( trace_origin, origin ) > 256 ) + { + return 0; + } + dot = vectordot( ( 0, 0, 1 ), groundnormal ); + if ( dot < 0.9 ) + { + return 0; + } + return 1; + } + return 0; +} + +zombiemoveongoo() +{ + self endon( "death" ); + self endon( "removed" ); + level endon( "intermission" ); + if ( is_true( self.sliding_on_goo ) ) + { + return; + } + self notify( "endOnGoo" ); + self endon( "endOnGoo" ); + self notify( "stop_zombie_goto_entrance" ); + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self.goo_last_vel = self getvelocity(); + self.goo_last_pos = self.origin; + slide_direction = anglesToForward( self.angles ); + self animmode( "slide" ); + self orientmode( "face enemy" ); + self.forcemovementscriptstate = 1; + self.ai_state = "zombieMoveOnGoo"; + self maps/mp/zombies/_zm_spawner::zombie_history( "zombieMoveOnGoo " + getTime() ); + self.sliding_on_goo = 0; + self thread zombiemoveongoo_on_killanimscript(); + for ( ;; ) + { + while ( 1 ) + { + if ( isDefined( self.is_on_goo ) ) + { + self_on_goo = self.is_on_goo; + } + velocity = self getvelocity(); + velocitylength = length( self getvelocity() ); + if ( isDefined( self.has_legs ) ) + { + iscrawler = !self.has_legs; + } + isleaper = self is_leaper(); + while ( is_true( self.is_leaping ) ) + { + wait 0.1; + } + if ( !self_on_goo ) + { + self animcustom( ::zombie_moveongoo_animcustom_recover ); + self waittill( "zombie_MoveOnGoo_animCustom_recover_done" ); + break; + } + else + { + if ( velocitylength <= 0.2 ) + { + self animmode( "normal" ); + wait 0.1; + self animmode( "slide" ); + } + if ( !self.sliding_on_goo || !issubstr( self.zombie_move_speed, "slide" ) ) + { + if ( !iscrawler && !isleaper && !isDefined( self.fell_while_sliding ) && canzombieongoofall() ) + { + self animcustom( ::zombie_moveongoo_animcustom_fall ); + self waittill( "zombie_MoveOnGoo_animCustom_fall_done" ); + } + } + else self.sliding_on_goo = 1; + if ( velocitylength <= 0.2 ) + { + wait 0.1; + } + self animmode( "slide" ); + self orientmode( "face enemy" ); + if ( self.zombie_move_speed == "sprint" ) + { + if ( !isDefined( self.zombie_move_speed ) || isDefined( self.zombie_move_speed ) && self.zombie_move_speed != "sprint_slide" ) + { + animstatedef = self maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "sprint_slide" ); + self set_zombie_run_cycle( animstatedef ); + } + break; + } + else if ( self.zombie_move_speed == "run" ) + { + if ( !isDefined( self.zombie_move_speed ) || isDefined( self.zombie_move_speed ) && self.zombie_move_speed != "run_slide" ) + { + animstatedef = self maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "run_slide" ); + self set_zombie_run_cycle( animstatedef ); + } + break; + } + else + { + if ( !isDefined( self.zombie_move_speed ) || isDefined( self.zombie_move_speed ) && self.zombie_move_speed != "walk_slide" ) + { + animstatedef = self maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "walk_slide" ); + self set_zombie_run_cycle( animstatedef ); + } + } + } + wait 0.05; + } + } + zombiemoveongoo_gobacktonormal(); +} + +zombie_moveongoo_animcustom_fall() +{ + self endon( "death" ); + self endon( "removed" ); + level endon( "intermission" ); + self.fell_while_sliding = 1; + self animmode( "normal" ); + self orientmode( "face angle", self.angles[ 1 ] ); + fallanimstatedef = "zm_move_slide_fall"; + self setanimstatefromasd( fallanimstatedef ); + maps/mp/animscripts/zm_shared::donotetracks( "slide_fall_anim" ); + self notify( "zombie_MoveOnGoo_animCustom_fall_done" ); +} + +zombie_moveongoo_animcustom_recover() +{ + self endon( "death" ); + self endon( "removed" ); + level endon( "intermission" ); + self.recovering_from_goo = 1; + if ( randomint( 100 ) < 50 ) + { + animstatedef = maps/mp/animscripts/zm_utility::append_missing_legs_suffix( "zm_move_slide_recover" ); + self setanimstatefromasd( animstatedef ); + maps/mp/animscripts/zm_shared::donotetracks( "slide_recover_anim" ); + } + self.recovering_from_goo = 0; + zombiemoveongoo_gobacktonormal(); + self notify( "zombie_MoveOnGoo_animCustom_recover_done" ); +} + +zombiemoveongoo_on_killanimscript() +{ + self endon( "death" ); + self endon( "removed" ); + level endon( "intermission" ); + self notify( "zombieMoveOnGoo_on_killAnimScript_thread" ); + self endon( "zombieMoveOnGoo_on_killAnimScript_thread" ); + self waittill_any( "endOnGoo", "killanimscript" ); + zombiemoveongoo_gobacktonormal(); +} + +zombiemoveongoo_gobacktonormal() +{ + self animmode( "normal" ); + self set_zombie_run_cycle(); + self.sliding_on_goo = 0; + self.fell_while_sliding = undefined; + self notify( "zombieMoveOnGoo_on_killAnimScript_thread" ); + self notify( "endOnGoo" ); + self.forcemovementscriptstate = 0; + if ( !is_true( self.completed_emerging_into_playable_area ) ) + { + /* +/# + assert( isDefined( self.first_node ) ); +#/ + */ + self maps/mp/zombies/_zm_spawner::reset_attack_spot(); + self orientmode( "face default" ); + self thread maps/mp/zombies/_zm_spawner::zombie_goto_entrance( self.first_node ); + } + else + { + self orientmode( "face enemy" ); + self thread maps/mp/zombies/_zm_ai_basic::find_flesh(); + } +} + +zombie_can_slip() +{ + if ( is_true( self.barricade_enter ) ) + { + return 0; + } + if ( is_true( self.is_traversing ) ) + { + return 0; + } + if ( !is_true( self.completed_emerging_into_playable_area ) && !isDefined( self.first_node ) ) + { + return 0; + } + if ( is_true( self.is_leaping ) ) + { + return 0; + } + return 1; +} + +zombie_set_slipping( onoff ) +{ + if ( isDefined( self ) ) + { + self.is_on_goo = onoff; + if ( onoff ) + { + self thread zombiemoveongoo(); + } + } +} + +slippery_spot_choke( lifetime ) +{ + level.sliquifier_distance_checks++; + if ( level.sliquifier_distance_checks >= 32 ) + { + level.sliquifier_distance_checks = 0; + lifetime -= 0.05; + wait 0.05; + } + return lifetime; +} + +add_slippery_spot( origin, duration, startpos ) +{ + wait 0.5; + level.slippery_spot_count++; + hit_norm = vectornormalize( startpos - origin ); + hit_from = 6 * hit_norm; + trace_height = 120; + trace = bullettrace( origin + hit_from, origin + hit_from + ( 0, 0, trace_height * -1 ), 0, undefined ); + if ( isDefined( trace[ "entity" ] ) ) + { + parent = trace[ "entity" ]; + if ( is_true( parent.can_move ) ) + { + return; + } + } + fxorigin = origin + hit_from; + /* +/# + red = ( 0, 0, 1 ); + green = ( 0, 0, 1 ); + dkgreen = vectorScale( ( 0, 0, 1 ), 0,15 ); + blue = ( 0, 0, 1 ); + grey = vectorScale( ( 0, 0, 1 ), 0,3 ); + black = ( 0, 0, 1 ); + slipgun_debug_line( origin, origin + hit_from, red, duration ); + if ( trace[ "fraction" ] == 1 ) + { + slipgun_debug_line( origin + hit_from, origin + hit_from + ( 0, 0, trace_height * -1 ), grey, duration ); + } + else + { + slipgun_debug_line( origin + hit_from, trace[ "position" ], green, duration ); + slipgun_debug_line( trace[ "position" ], origin + hit_from + ( 0, 0, trace_height * -1 ), dkgreen, duration ); +#/ + } + */ + if ( trace[ "fraction" ] == 1 ) + { + return; + } + moving_parent = undefined; + moving_parent_start = ( 0, 0, 1 ); + if ( isDefined( trace[ "entity" ] ) ) + { + parent = trace[ "entity" ]; + if ( is_true( parent.can_move ) ) + { + return; + } + } + origin = trace[ "position" ]; + thread pool_of_goo( fxorigin, duration ); + if ( !isDefined( level.slippery_spots ) ) + { + level.slippery_spots = []; + } + level.slippery_spots[ level.slippery_spots.size ] = origin; + radius = 60; + height = 48; + /* +/# + thread slipgun_debug_circle( origin, radius, duration, 0, moving_parent, moving_parent_start ); +#/ + */ + slicked_players = []; + slicked_zombies = []; + lifetime = duration; + radius2 = radius * radius; + while ( lifetime > 0 ) + { + oldlifetime = lifetime; + _a612 = get_players(); + _k612 = getFirstArrayKey( _a612 ); + while ( isDefined( _k612 ) ) + { + player = _a612[ _k612 ]; + num = player getentitynumber(); + morigin = origin; + if ( isDefined( moving_parent ) ) + { + morigin = origin + ( moving_parent.origin - moving_parent_start ); + } + if ( distance2dsquared( player.origin, morigin ) < radius2 ) + { + should_be_slick = abs( player.origin[ 2 ] - morigin[ 2 ] ) < height; + } + is_slick = isDefined( slicked_players[ num ] ); + if ( should_be_slick != is_slick ) + { + if ( !isDefined( player.slick_count ) ) + { + player.slick_count = 0; + } + if ( should_be_slick ) + { + player.slick_count++; + slicked_players[ num ] = player; + } + else + { + player.slick_count--; +/* +/# + assert( player.slick_count >= 0 ); +#/ +*/ + } + player forceslick( player.slick_count ); + } + lifetime = slippery_spot_choke( lifetime ); + _k612 = getNextArrayKey( _a612, _k612 ); + } + zombies = get_round_enemy_array(); + while ( isDefined( zombies ) ) + { + _a645 = zombies; + _k645 = getFirstArrayKey( _a645 ); + while ( isDefined( _k645 ) ) + { + zombie = _a645[ _k645 ]; + if ( isDefined( zombie ) ) + { + num = zombie getentitynumber(); + morigin = origin; + if ( isDefined( moving_parent ) ) + { + morigin = origin + ( moving_parent.origin - moving_parent_start ); + } + if ( distance2dsquared( zombie.origin, morigin ) < radius2 ) + { + should_be_slick = abs( zombie.origin[ 2 ] - morigin[ 2 ] ) < height; + } + if ( should_be_slick && !zombie zombie_can_slip() ) + { + should_be_slick = 0; + } + is_slick = isDefined( slicked_zombies[ num ] ); + if ( should_be_slick != is_slick ) + { + if ( !isDefined( zombie.slick_count ) ) + { + zombie.slick_count = 0; + } + if ( should_be_slick ) + { + zombie.slick_count++; + slicked_zombies[ num ] = zombie; + } + else + { + if ( zombie.slick_count > 0 ) + { + zombie.slick_count--; + + } + } + zombie zombie_set_slipping( zombie.slick_count > 0 ); + } + lifetime = slippery_spot_choke( lifetime ); + } + _k645 = getNextArrayKey( _a645, _k645 ); + } + } + if ( oldlifetime == lifetime ) + { + lifetime -= 0.05; + wait 0.05; + } + } + _a684 = slicked_players; + _k684 = getFirstArrayKey( _a684 ); + while ( isDefined( _k684 ) ) + { + player = _a684[ _k684 ]; + player.slick_count--; + /* + +/# + assert( player.slick_count >= 0 ); +#/ + */ + player forceslick( player.slick_count ); + _k684 = getNextArrayKey( _a684, _k684 ); + } + _a690 = slicked_zombies; + _k690 = getFirstArrayKey( _a690 ); + while ( isDefined( _k690 ) ) + { + zombie = _a690[ _k690 ]; + if ( isDefined( zombie ) ) + { + if ( zombie.slick_count > 0 ) + { + zombie.slick_count--; + + } + zombie zombie_set_slipping( zombie.slick_count > 0 ); + } + _k690 = getNextArrayKey( _a690, _k690 ); + } + arrayremovevalue( level.slippery_spots, origin, 0 ); + level.slippery_spot_count--; + +} + +pool_of_goo( origin, duration ) +{ + effect_life = 24; + if ( duration > effect_life ) + { + pool_of_goo( origin, duration - effect_life ); + duration = effect_life; + } + if ( isDefined( level._effect[ "slipgun_splatter" ] ) ) + { + playfx( level._effect[ "slipgun_splatter" ], origin ); + } + wait duration; +} + +explode_into_goo( player, chain_depth ) +{ + if ( isDefined( self.marked_for_insta_upgraded_death ) ) + { + return; + } + tag = "J_SpineLower"; + if ( is_true( self.isdog ) ) + { + tag = "tag_origin"; + } + self.guts_explosion = 1; + self playsound( "wpn_slipgun_zombie_explode" ); + if ( isDefined( level._effect[ "slipgun_explode" ] ) ) + { + playfx( level._effect[ "slipgun_explode" ], self gettagorigin( tag ) ); + } + if ( !is_true( self.isdog ) ) + { + wait 0.1; + } + self ghost(); + if ( !isDefined( self.goo_chain_depth ) ) + { + self.goo_chain_depth = chain_depth; + } + chain_radius = level.zombie_vars[ "slipgun_chain_radius" ]; + level thread explode_to_near_zombies( player, self.origin, chain_radius, self.goo_chain_depth ); +} + +explode_to_near_zombies( player, origin, radius, chain_depth ) +{ + if ( level.zombie_vars[ "slipgun_max_kill_chain_depth" ] > 0 && chain_depth > level.zombie_vars[ "slipgun_max_kill_chain_depth" ] ) + { + return; + } + enemies = get_round_enemy_array(); + enemies = get_array_of_closest( origin, enemies ); + minchainwait = level.zombie_vars[ "slipgun_chain_wait_min" ]; + maxchainwait = level.zombie_vars[ "slipgun_chain_wait_max" ]; + rsquared = radius * radius; + tag = "J_Head"; + marked_zombies = []; + while ( isDefined( enemies ) && enemies.size ) + { + index = 0; + enemy = enemies[ index ]; + while ( distancesquared( enemy.origin, origin ) < rsquared ) + { + if ( isalive( enemy ) && !is_true( enemy.guts_explosion ) && !is_true( enemy.nuked ) && !isDefined( enemy.slipgun_sizzle ) ) + { + trace = bullettrace( origin + vectorScale( ( 0, 0, 1 ), 50 ), enemy.origin + vectorScale( ( 0, 0, 1 ), 50 ), 0, undefined, 1 ); + if ( isDefined( trace[ "fraction" ] ) && trace[ "fraction" ] == 1 ) + { + enemy.slipgun_sizzle = playfxontag( level._effect[ "slipgun_simmer" ], enemy, tag ); + marked_zombies[ marked_zombies.size ] = enemy; + } + } + index++; + if ( index >= enemies.size ) + { + break; + } + else + { + enemy = enemies[ index ]; + } + } + } + while ( isDefined( marked_zombies ) && marked_zombies.size ) + { + _a799 = marked_zombies; + _k799 = getFirstArrayKey( _a799 ); + while ( isDefined( _k799 ) ) + { + enemy = _a799[ _k799 ]; + if ( isalive( enemy ) && !is_true( enemy.guts_explosion ) && !is_true( enemy.nuked ) ) + { + wait randomfloatrange( minchainwait, maxchainwait ); + if ( isalive( enemy ) && !is_true( enemy.guts_explosion ) && !is_true( enemy.nuked ) ) + { + if ( !isDefined( enemy.goo_chain_depth ) ) + { + enemy.goo_chain_depth = chain_depth; + } + if ( enemy.health > 0 ) + { + if ( player maps/mp/zombies/_zm_powerups::is_insta_kill_active() ) + { + enemy.health = 1; + } + enemy dodamage( level.slipgun_damage, origin, player, player, "none", level.slipgun_damage_mod, 0, "slip_goo_zm" ); + } + if ( level.slippery_spot_count < level.zombie_vars[ "slipgun_reslip_max_spots" ] ) + { + if ( isDefined( enemy.slick_count ) && enemy.slick_count == 0 && enemy.health <= 0 ) + { + if ( level.zombie_vars[ "slipgun_reslip_rate" ] > 0 && randomint( level.zombie_vars[ "slipgun_reslip_rate" ] ) == 0 ) + { + startpos = origin; + duration = 24; + thread add_slippery_spot( enemy.origin, duration, startpos ); + } + } + } + } + } + _k799 = getNextArrayKey( _a799, _k799 ); + } + } +} + +slipgun_zombie_1st_hit_response( upgraded, player ) +{ + self notify( "stop_find_flesh" ); + self notify( "zombie_acquire_enemy" ); + self orientmode( "face default" ); + self.ignoreall = 1; + self.gibbed = 1; + if ( isalive( self ) ) + { + if ( !isDefined( self.goo_chain_depth ) ) + { + self.goo_chain_depth = 0; + } + if ( self.health > 0 ) + { + if ( player maps/mp/zombies/_zm_powerups::is_insta_kill_active() ) + { + self.health = 1; + } + self dodamage( level.slipgun_damage, self.origin, player, player, "none", level.slipgun_damage_mod, 0, "slip_goo_zm" ); + } + } +} + +slipgun_zombie_hit_response_internal( mod, damageweapon, player ) +{ + if ( !self is_slipgun_damage( mod, damageweapon ) && !is_slipgun_explosive_damage( mod, damageweapon ) ) + { + return 0; + } + self playsound( "wpn_slipgun_zombie_impact" ); + upgraded = damageweapon == "slipgun_upgraded_zm"; + self thread slipgun_zombie_1st_hit_response( upgraded, player ); + if ( isDefined( player ) && isplayer( player ) ) + { + player thread slipgun_play_zombie_hit_vox(); + } + return 1; +} + +slipgun_zombie_damage_response( mod, hit_location, hit_origin, player, amount ) +{ + return slipgun_zombie_hit_response_internal( mod, self.damageweapon, player ); +} + +slipgun_zombie_death_response() +{ + if ( !self is_slipgun_damage( self.damagemod, self.damageweapon ) && !is_slipgun_explosive_damage( self.damagemod, self.damageweapon ) ) + { + return 0; + } + level maps/mp/zombies/_zm_spawner::zombie_death_points( self.origin, self.damagemod, self.damagelocation, self.attacker, self ); + self explode_into_goo( self.attacker, 0 ); + return 1; +} + +is_slipgun_explosive_damage( mod, weapon ) +{ + if ( isDefined( weapon ) ) + { + if ( weapon != "slip_goo_zm" && weapon != "slip_bolt_zm" ) + { + return weapon == "slip_bolt_upgraded_zm"; + } + } +} + +is_slipgun_damage( mod, weapon ) +{ + if ( isDefined( weapon ) ) + { + if ( weapon != "slipgun_zm" ) + { + return weapon == "slipgun_upgraded_zm"; + } + } +} + +slipgun_play_zombie_hit_vox() +{ + rand = randomintrange( 0, 101 ); + if ( rand >= 20 ) + { + self maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "human" ); + } +} + diff --git a/zm_highrise_patch/readme.md b/zm_highrise_patch/readme.md new file mode 100644 index 0000000..3c3b11f --- /dev/null +++ b/zm_highrise_patch/readme.md @@ -0,0 +1,14 @@ +### The following gscs compile and run successfully with no known errors: + +### The following scripts compile and run successfully with minor errors: + +### The following scripts compile and run successfully with major errors: +``` +zm_highrise_patch/maps/mp/zombies/_zm_weap_slipgun.gsc +``` +### The following scripts compile and run serverside but clients cannot join due to exe_client_field_mismatch + +### The following scripts compile but cause a minidump or other severe error: + +### notes: + diff --git a/zm_transit_patch/maps/mp/gametypes_zm/zgrief.gsc b/zm_transit_patch/maps/mp/gametypes_zm/zgrief.gsc new file mode 100644 index 0000000..4f993f4 --- /dev/null +++ b/zm_transit_patch/maps/mp/gametypes_zm/zgrief.gsc @@ -0,0 +1,730 @@ +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_audio_announcer; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/_demo; +#include maps/mp/zombies/_zm_laststand; +#include maps/mp/zombies/_zm_weap_cymbal_monkey; +#include maps/mp/zombies/_zm_magicbox; +#include maps/mp/zombies/_zm_game_module; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_game_module_meat_utility; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/gametypes_zm/zmeat; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/zombies/_zm_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/_utility; +#include maps/mp/zombies/_zm_spawner; + +main() +{ + maps/mp/gametypes_zm/_zm_gametype::main(); + level.onprecachegametype = ::onprecachegametype; + level.onstartgametype = ::onstartgametype; + level.custom_spectate_permissions = ::setspectatepermissionsgrief; + level._game_module_custom_spawn_init_func = ::custom_spawn_init_func; + //level._game_module_stat_update_func = ::maps/mp/zombies/_zm_stats::grief_custom_stat_update; + level._game_module_player_damage_callback = ::game_module_player_damage_callback; + level.custom_end_screen = ::custom_end_screen; + level.gamemode_map_postinit[ "zgrief" ] = ::postinit_func; + level._supress_survived_screen = 1; + level.game_module_team_name_override_og_x = 155; + level.prevent_player_damage = ::player_prevent_damage; + level._game_module_player_damage_grief_callback = ::game_module_player_damage_grief_callback; + level._grief_reset_message = ::grief_reset_message; + level._game_module_player_laststand_callback = ::grief_laststand_weapon_save; + level.onplayerspawned_restore_previous_weapons = ::grief_laststand_weapons_return; + level.game_module_onplayerconnect = ::grief_onplayerconnect; + level.game_mode_spawn_player_logic = ::game_mode_spawn_player_logic; + level.game_mode_custom_onplayerdisconnect = ::grief_onplayerdisconnect; + maps/mp/gametypes_zm/_zm_gametype::post_gametype_main( "zgrief" ); +} + +grief_onplayerconnect() +{ + self thread move_team_icons(); + self thread zgrief_player_bled_out_msg(); +} + +grief_onplayerdisconnect( disconnecting_player ) +{ + level thread update_players_on_bleedout_or_disconnect( disconnecting_player ); +} + +setspectatepermissionsgrief() +{ + self allowspectateteam( "allies", 1 ); + self allowspectateteam( "axis", 1 ); + self allowspectateteam( "freelook", 0 ); + self allowspectateteam( "none", 1 ); +} + +custom_end_screen() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + players[ i ].game_over_hud = newclienthudelem( players[ i ] ); + players[ i ].game_over_hud.alignx = "center"; + players[ i ].game_over_hud.aligny = "middle"; + players[ i ].game_over_hud.horzalign = "center"; + players[ i ].game_over_hud.vertalign = "middle"; + players[ i ].game_over_hud.y -= 130; + players[ i ].game_over_hud.foreground = 1; + players[ i ].game_over_hud.fontscale = 3; + players[ i ].game_over_hud.alpha = 0; + players[ i ].game_over_hud.color = ( 1, 1, 1 ); + players[ i ].game_over_hud.hidewheninmenu = 1; + players[ i ].game_over_hud settext( &"ZOMBIE_GAME_OVER" ); + players[ i ].game_over_hud fadeovertime( 1 ); + players[ i ].game_over_hud.alpha = 1; + if ( players[ i ] issplitscreen() ) + { + players[ i ].game_over_hud.fontscale = 2; + players[ i ].game_over_hud.y += 40; + } + players[ i ].survived_hud = newclienthudelem( players[ i ] ); + players[ i ].survived_hud.alignx = "center"; + players[ i ].survived_hud.aligny = "middle"; + players[ i ].survived_hud.horzalign = "center"; + players[ i ].survived_hud.vertalign = "middle"; + players[ i ].survived_hud.y -= 100; + players[ i ].survived_hud.foreground = 1; + players[ i ].survived_hud.fontscale = 2; + players[ i ].survived_hud.alpha = 0; + players[ i ].survived_hud.color = ( 1, 1, 1 ); + players[ i ].survived_hud.hidewheninmenu = 1; + if ( players[ i ] issplitscreen() ) + { + players[ i ].survived_hud.fontscale = 1.5; + players[ i ].survived_hud.y += 40; + } + winner_text = &"ZOMBIE_GRIEF_WIN"; + loser_text = &"ZOMBIE_GRIEF_LOSE"; + if ( level.round_number < 2 ) + { + winner_text = &"ZOMBIE_GRIEF_WIN_SINGLE"; + loser_text = &"ZOMBIE_GRIEF_LOSE_SINGLE"; + } + if ( isDefined( level.host_ended_game ) && level.host_ended_game ) + { + players[ i ].survived_hud settext( &"MP_HOST_ENDED_GAME" ); + } + else + { + if ( isDefined( level.gamemodulewinningteam ) && players[ i ]._encounters_team == level.gamemodulewinningteam ) + { + players[ i ].survived_hud settext( winner_text, level.round_number ); + break; + } + else + { + players[ i ].survived_hud settext( loser_text, level.round_number ); + } + } + players[ i ].survived_hud fadeovertime( 1 ); + players[ i ].survived_hud.alpha = 1; + i++; + } +} + +postinit_func() +{ + level.min_humans = 1; + level.zombie_ai_limit = 24; + level.prevent_player_damage = ::player_prevent_damage; + level.lock_player_on_team_score = 1; + level._zombie_spawning = 0; + level._get_game_module_players = undefined; + level.powerup_drop_count = 0; + level.is_zombie_level = 1; + setmatchtalkflag( "DeadChatWithDead", 1 ); + setmatchtalkflag( "DeadChatWithTeam", 1 ); + setmatchtalkflag( "DeadHearTeamLiving", 1 ); + setmatchtalkflag( "DeadHearAllLiving", 1 ); + setmatchtalkflag( "EveryoneHearsEveryone", 1 ); +} + +grief_game_end_check_func() +{ + return 0; +} + +player_prevent_damage( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + if ( isDefined( eattacker ) && isplayer( eattacker ) && self != eattacker && !eattacker hasperk( "specialty_noname" ) && isDefined( self.is_zombie ) && !self.is_zombie ) + { + return 1; + } + return 0; +} + +game_module_player_damage_grief_callback( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + penalty = 10; + if ( isDefined( eattacker ) && isplayer( eattacker ) && eattacker != self && eattacker.team != self.team && smeansofdeath == "MOD_MELEE" ) + { + self applyknockback( idamage, vdir ); + } +} + +onprecachegametype() +{ + level.playersuicideallowed = 1; + level.suicide_weapon = "death_self_zm"; + precacheitem( "death_self_zm" ); + precacheshellshock( "grief_stab_zm" ); + precacheshader( "faction_cdc" ); + precacheshader( "faction_cia" ); + precacheshader( "waypoint_revive_cdc_zm" ); + precacheshader( "waypoint_revive_cia_zm" ); + level._effect[ "butterflies" ] = loadfx( "maps/zombie/fx_zmb_impact_noharm" ); + level thread maps/mp/gametypes_zm/_zm_gametype::init(); + maps/mp/gametypes_zm/_zm_gametype::rungametypeprecache( "zgrief" ); +} + +onstartgametype() +{ + level.no_end_game_check = 1; + level._game_module_game_end_check = ::grief_game_end_check_func; + level.round_end_custom_logic = ::grief_round_end_custom_logic; + maps/mp/gametypes_zm/_zm_gametype::setup_classic_gametype(); + maps/mp/gametypes_zm/_zm_gametype::rungametypemain( "zgrief", ::zgrief_main ); +} + +zgrief_main() +{ + level thread maps/mp/zombies/_zm::round_start(); + level thread maps/mp/gametypes_zm/_zm_gametype::kill_all_zombies(); + flag_wait( "initial_blackscreen_passed" ); + level thread maps/mp/zombies/_zm_game_module::wait_for_team_death_and_round_end(); + players = get_players(); + _a302 = players; + _k302 = getFirstArrayKey( _a302 ); + while ( isDefined( _k302 ) ) + { + player = _a302[ _k302 ]; + player.is_hotjoin = 0; + _k302 = getNextArrayKey( _a302, _k302 ); + } + wait 1; + playsoundatposition( "vox_zmba_grief_intro_0", ( 1, 1, 1 ) ); +} + +move_team_icons() +{ + self endon( "disconnect" ); + flag_wait( "initial_blackscreen_passed" ); + wait 0.5; +} + +kill_start_chest() +{ + flag_wait( "initial_blackscreen_passed" ); + wait 2; + start_chest = getstruct( "start_chest", "script_noteworthy" ); + start_chest maps/mp/zombies/_zm_magicbox::hide_chest(); +} + +door_close_zombie_think() +{ + self endon( "death" ); + while ( isalive( self ) ) + { + if ( isDefined( self.enemy ) && isplayer( self.enemy ) ) + { + insamezone = 0; + keys = getarraykeys( level.zones ); + i = 0; + while ( i < keys.size ) + { + if ( self maps/mp/zombies/_zm_zonemgr::entity_in_zone( keys[ i ] ) && self.enemy maps/mp/zombies/_zm_zonemgr::entity_in_zone( keys[ i ] ) ) + { + insamezone = 1; + } + i++; + } + while ( insamezone ) + { + wait 3; + } + nearestzombienode = getnearestnode( self.origin ); + nearestplayernode = getnearestnode( self.enemy.origin ); + if ( isDefined( nearestzombienode ) && isDefined( nearestplayernode ) ) + { + if ( !nodesvisible( nearestzombienode, nearestplayernode ) && !nodescanpath( nearestzombienode, nearestplayernode ) ) + { + self silentlyremovezombie(); + } + } + } + wait 1; + } +} + +silentlyremovezombie() +{ + level.zombie_total++; + playfx( level._effect[ "spawn_cloud" ], self.origin ); + self.skip_death_notetracks = 1; + self.nodeathragdoll = 1; + self dodamage( self.maxhealth * 2, self.origin, self, self, "none", "MOD_SUICIDE" ); + self self_delete(); +} + +zgrief_player_bled_out_msg() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "bled_out" ); + level thread update_players_on_bleedout_or_disconnect( self ); + } +} + +show_grief_hud_msg( msg, msg_parm, offset, cleanup_end_game ) +{ + self endon( "disconnect" ); + while ( isDefined( level.hostmigrationtimer ) ) + { + wait 0.05; + } + zgrief_hudmsg = newclienthudelem( self ); + zgrief_hudmsg.alignx = "center"; + zgrief_hudmsg.aligny = "middle"; + zgrief_hudmsg.horzalign = "center"; + zgrief_hudmsg.vertalign = "middle"; + zgrief_hudmsg.y -= 130; + if ( self issplitscreen() ) + { + zgrief_hudmsg.y += 70; + } + if ( isDefined( offset ) ) + { + zgrief_hudmsg.y += offset; + } + zgrief_hudmsg.foreground = 1; + zgrief_hudmsg.fontscale = 5; + zgrief_hudmsg.alpha = 0; + zgrief_hudmsg.color = ( 1, 1, 1 ); + zgrief_hudmsg.hidewheninmenu = 1; + zgrief_hudmsg.font = "default"; + if ( isDefined( cleanup_end_game ) && cleanup_end_game ) + { + level endon( "end_game" ); + zgrief_hudmsg thread show_grief_hud_msg_cleanup(); + } + if ( isDefined( msg_parm ) ) + { + zgrief_hudmsg settext( msg, msg_parm ); + } + else + { + zgrief_hudmsg settext( msg ); + } + zgrief_hudmsg changefontscaleovertime( 0.25 ); + zgrief_hudmsg fadeovertime( 0.25 ); + zgrief_hudmsg.alpha = 1; + zgrief_hudmsg.fontscale = 2; + wait 3.25; + zgrief_hudmsg changefontscaleovertime( 1 ); + zgrief_hudmsg fadeovertime( 1 ); + zgrief_hudmsg.alpha = 0; + zgrief_hudmsg.fontscale = 5; + wait 1; + zgrief_hudmsg notify( "death" ); + if ( isDefined( zgrief_hudmsg ) ) + { + zgrief_hudmsg destroy(); + } +} + +show_grief_hud_msg_cleanup() +{ + self endon( "death" ); + level waittill( "end_game" ); + if ( isDefined( self ) ) + { + self destroy(); + } +} + +grief_reset_message() +{ + msg = &"ZOMBIE_GRIEF_RESET"; + players = get_players(); + if ( isDefined( level.hostmigrationtimer ) ) + { + while ( isDefined( level.hostmigrationtimer ) ) + { + wait 0.05; + } + wait 4; + } + _a697 = players; + _k697 = getFirstArrayKey( _a697 ); + while ( isDefined( _k697 ) ) + { + player = _a697[ _k697 ]; + player thread show_grief_hud_msg( msg ); + _k697 = getNextArrayKey( _a697, _k697 ); + } + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "grief_restarted" ); +} + +grief_laststand_weapon_save( einflictor, attacker, idamage, smeansofdeath, sweapon, vdir, shitloc, psoffsettime, deathanimduration ) +{ + self.grief_savedweapon_weapons = self getweaponslist(); + self.grief_savedweapon_weaponsammo_stock = []; + self.grief_savedweapon_weaponsammo_clip = []; + self.grief_savedweapon_currentweapon = self getcurrentweapon(); + self.grief_savedweapon_grenades = self get_player_lethal_grenade(); + if ( isDefined( self.grief_savedweapon_grenades ) ) + { + self.grief_savedweapon_grenades_clip = self getweaponammoclip( self.grief_savedweapon_grenades ); + } + self.grief_savedweapon_tactical = self get_player_tactical_grenade(); + if ( isDefined( self.grief_savedweapon_tactical ) ) + { + self.grief_savedweapon_tactical_clip = self getweaponammoclip( self.grief_savedweapon_tactical ); + } + i = 0; + while ( i < self.grief_savedweapon_weapons.size ) + { + self.grief_savedweapon_weaponsammo_clip[ i ] = self getweaponammoclip( self.grief_savedweapon_weapons[ i ] ); + self.grief_savedweapon_weaponsammo_stock[ i ] = self getweaponammostock( self.grief_savedweapon_weapons[ i ] ); + i++; + } + if ( isDefined( self.hasriotshield ) && self.hasriotshield ) + { + self.grief_hasriotshield = 1; + } + if ( self hasweapon( "claymore_zm" ) ) + { + self.grief_savedweapon_claymore = 1; + self.grief_savedweapon_claymore_clip = self getweaponammoclip( "claymore_zm" ); + } + if ( isDefined( self.current_equipment ) ) + { + self.grief_savedweapon_equipment = self.current_equipment; + } +} + +grief_laststand_weapons_return() +{ + if ( isDefined( level.isresetting_grief ) && !level.isresetting_grief ) + { + return 0; + } + if ( !isDefined( self.grief_savedweapon_weapons ) ) + { + return 0; + } + primary_weapons_returned = 0; + _a766 = self.grief_savedweapon_weapons; + index = getFirstArrayKey( _a766 ); + while ( isDefined( index ) ) + { + weapon = _a766[ index ]; + if ( isDefined( self.grief_savedweapon_grenades ) || weapon == self.grief_savedweapon_grenades && isDefined( self.grief_savedweapon_tactical ) && weapon == self.grief_savedweapon_tactical ) + { + } + else + { + if ( isweaponprimary( weapon ) ) + { + if ( primary_weapons_returned >= 2 ) + { + break; + } + else primary_weapons_returned++; + } + if ( weapon == "item_meat_zm" ) + { + break; + } + else + { + self giveweapon( weapon, 0, self maps/mp/zombies/_zm_weapons::get_pack_a_punch_weapon_options( weapon ) ); + if ( isDefined( self.grief_savedweapon_weaponsammo_clip[ index ] ) ) + { + self setweaponammoclip( weapon, self.grief_savedweapon_weaponsammo_clip[ index ] ); + } + if ( isDefined( self.grief_savedweapon_weaponsammo_stock[ index ] ) ) + { + self setweaponammostock( weapon, self.grief_savedweapon_weaponsammo_stock[ index ] ); + } + } + } + index = getNextArrayKey( _a766, index ); + } + if ( isDefined( self.grief_savedweapon_grenades ) ) + { + self giveweapon( self.grief_savedweapon_grenades ); + if ( isDefined( self.grief_savedweapon_grenades_clip ) ) + { + self setweaponammoclip( self.grief_savedweapon_grenades, self.grief_savedweapon_grenades_clip ); + } + } + if ( isDefined( self.grief_savedweapon_tactical ) ) + { + self giveweapon( self.grief_savedweapon_tactical ); + if ( isDefined( self.grief_savedweapon_tactical_clip ) ) + { + self setweaponammoclip( self.grief_savedweapon_tactical, self.grief_savedweapon_tactical_clip ); + } + } + if ( isDefined( self.current_equipment ) ) + { + self maps/mp/zombies/_zm_equipment::equipment_take( self.current_equipment ); + } + if ( isDefined( self.grief_savedweapon_equipment ) ) + { + self.do_not_display_equipment_pickup_hint = 1; + self maps/mp/zombies/_zm_equipment::equipment_give( self.grief_savedweapon_equipment ); + self.do_not_display_equipment_pickup_hint = undefined; + } + if ( isDefined( self.grief_hasriotshield ) && self.grief_hasriotshield ) + { + if ( isDefined( self.player_shield_reset_health ) ) + { + self [[ self.player_shield_reset_health ]](); + } + } + if ( isDefined( self.grief_savedweapon_claymore ) && self.grief_savedweapon_claymore ) + { + self giveweapon( "claymore_zm" ); + self set_player_placeable_mine( "claymore_zm" ); + self setactionslot( 4, "weapon", "claymore_zm" ); + self setweaponammoclip( "claymore_zm", self.grief_savedweapon_claymore_clip ); + } + primaries = self getweaponslistprimaries(); + _a859 = primaries; + _k859 = getFirstArrayKey( _a859 ); + while ( isDefined( _k859 ) ) + { + weapon = _a859[ _k859 ]; + if ( isDefined( self.grief_savedweapon_currentweapon ) && self.grief_savedweapon_currentweapon == weapon ) + { + self switchtoweapon( weapon ); + return 1; + } + _k859 = getNextArrayKey( _a859, _k859 ); + } + if ( primaries.size > 0 ) + { + self switchtoweapon( primaries[ 0 ] ); + return 1; + } + return 0; +} + +grief_store_player_scores() +{ + players = get_players(); + _a883 = players; + _k883 = getFirstArrayKey( _a883 ); + while ( isDefined( _k883 ) ) + { + player = _a883[ _k883 ]; + player._pre_round_score = player.score; + _k883 = getNextArrayKey( _a883, _k883 ); + } +} + +grief_restore_player_score() +{ + if ( !isDefined( self._pre_round_score ) ) + { + self._pre_round_score = self.score; + } + if ( isDefined( self._pre_round_score ) ) + { + self.score = self._pre_round_score; + self.pers[ "score" ] = self._pre_round_score; + } +} + +game_mode_spawn_player_logic() +{ + if ( flag( "start_zombie_round_logic" ) && !isDefined( self.is_hotjoin ) ) + { + self.is_hotjoin = 1; + return 1; + } + return 0; +} + +update_players_on_bleedout_or_disconnect( excluded_player ) +{ + other_team = undefined; + players = get_players(); + players_remaining = 0; + _a920 = players; + _k920 = getFirstArrayKey( _a920 ); + while ( isDefined( _k920 ) ) + { + player = _a920[ _k920 ]; + if ( player == excluded_player ) + { + } + else if ( player.team == excluded_player.team ) + { + if ( is_player_valid( player ) ) + { + players_remaining++; + } + break; + } + _k920 = getNextArrayKey( _a920, _k920 ); + } + _a937 = players; + _k937 = getFirstArrayKey( _a937 ); + while ( isDefined( _k937 ) ) + { + player = _a937[ _k937 ]; + if ( player == excluded_player ) + { + } + else if ( player.team != excluded_player.team ) + { + other_team = player.team; + if ( players_remaining < 1 ) + { + player thread show_grief_hud_msg( &"ZOMBIE_ZGRIEF_ALL_PLAYERS_DOWN", undefined, undefined, 1 ); + player delay_thread_watch_host_migrate( 2, ::show_grief_hud_msg, &"ZOMBIE_ZGRIEF_SURVIVE", undefined, 30, 1 ); + break; + } + else + { + player thread show_grief_hud_msg( &"ZOMBIE_ZGRIEF_PLAYER_BLED_OUT", players_remaining ); + } + } + _k937 = getNextArrayKey( _a937, _k937 ); + } + if ( players_remaining == 1 ) + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "last_player", excluded_player.team ); + } + if ( !isDefined( other_team ) ) + { + return; + } + if ( players_remaining < 1 ) + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( "4_player_down", other_team ); + } + else + { + level thread maps/mp/zombies/_zm_audio_announcer::leaderdialog( players_remaining + "_player_left", other_team ); + } +} + +delay_thread_watch_host_migrate( timer, func, param1, param2, param3, param4, param5, param6 ) +{ + self thread _delay_thread_watch_host_migrate_proc( func, timer, param1, param2, param3, param4, param5, param6 ); +} + +_delay_thread_watch_host_migrate_proc( func, timer, param1, param2, param3, param4, param5, param6 ) +{ + self endon( "death" ); + self endon( "disconnect" ); + wait timer; + if ( isDefined( level.hostmigrationtimer ) ) + { + while ( isDefined( level.hostmigrationtimer ) ) + { + wait 0.05; + } + wait timer; + } + single_thread( self, func, param1, param2, param3, param4, param5, param6 ); +} + +grief_round_end_custom_logic() +{ + waittillframeend; + if ( isDefined( level.gamemodulewinningteam ) ) + { + level notify( "end_round_think" ); + } +} + +custom_spawn_init_func() +{ + array_thread( level.zombie_spawners, ::add_spawn_function, ::zombie_spawn_init ); + array_thread( level.zombie_spawners, ::add_spawn_function, level._zombies_round_spawn_failsafe ); +} + +game_module_player_damage_callback( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ) +{ + self.last_damage_from_zombie_or_player = 0; + if ( isDefined( eattacker ) ) + { + if ( isplayer( eattacker ) && eattacker == self ) + { + return; + } + if ( isDefined( eattacker.is_zombie ) || eattacker.is_zombie && isplayer( eattacker ) ) + { + self.last_damage_from_zombie_or_player = 1; + } + } + if ( isDefined( self._being_shellshocked ) || self._being_shellshocked && self maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + return; + } + if ( isplayer( eattacker ) && isDefined( eattacker._encounters_team ) && eattacker._encounters_team != self._encounters_team ) + { + if ( isDefined( self.hasriotshield ) && self.hasriotshield && isDefined( vdir ) ) + { + if ( isDefined( self.hasriotshieldequipped ) && self.hasriotshieldequipped ) + { + if ( self maps/mp/zombies/_zm::player_shield_facing_attacker( vdir, 0.2 ) && isDefined( self.player_shield_apply_damage ) ) + { + return; + } + } + else + { + if ( !isDefined( self.riotshieldentity ) ) + { + if ( !self maps/mp/zombies/_zm::player_shield_facing_attacker( vdir, -0.2 ) && isDefined( self.player_shield_apply_damage ) ) + { + return; + } + } + } + } + if ( isDefined( level._game_module_player_damage_grief_callback ) ) + { + self [[ level._game_module_player_damage_grief_callback ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, psoffsettime ); + } + if ( isDefined( level._effect[ "butterflies" ] ) ) + { + if ( isDefined( sweapon ) && weapontype( sweapon ) == "grenade" ) + { + playfx( level._effect[ "butterflies" ], self.origin + vectorScale( ( 1, 1, 1 ), 40 ) ); + } + else + { + playfx( level._effect[ "butterflies" ], vpoint, vdir ); + } + } + self thread do_game_mode_shellshock(); + self playsound( "zmb_player_hit_ding" ); + } +} + +do_game_mode_shellshock() +{ + self endon( "disconnect" ); + self._being_shellshocked = 1; + self shellshock( "grief_stab_zm", 0,75 ); + wait 0.75; + self._being_shellshocked = 0; +} diff --git a/zm_transit_patch/maps/mp/zm_transit_utility.gsc b/zm_transit_patch/maps/mp/zm_transit_utility.gsc new file mode 100644 index 0000000..375f18f --- /dev/null +++ b/zm_transit_patch/maps/mp/zm_transit_utility.gsc @@ -0,0 +1,279 @@ +#include maps/mp/_compass; +#include maps/mp/zombies/_zm_zonemgr; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_score; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +playercanafford( player, cost ) +{ + if ( !player usebuttonpressed() ) + { + return 0; + } + if ( player in_revive_trigger() ) + { + return 0; + } + if ( isDefined( cost ) ) + { + if ( player.score < cost ) + { + return 0; + } + player maps/mp/zombies/_zm_score::minus_to_player_score( cost ); + } + return 1; +} + +setinvisibletoall() +{ + players = get_players(); + playerindex = 0; + while ( playerindex < players.size ) + { + self setinvisibletoplayer( players[ playerindex ] ); + playerindex++; + } +} + +spawnandlinkfxtotag( effect, ent, tag ) +{ + fxent = spawn( "script_model", ent gettagorigin( tag ) ); + fxent setmodel( "tag_origin" ); + fxent linkto( ent, tag ); + wait_network_frame(); + playfxontag( effect, fxent, "tag_origin" ); + return fxent; +} + +spawnandlinkfxtooffset( effect, ent, offsetorigin, offsetangles ) +{ + fxent = spawn( "script_model", ( 0, 0, 0 ) ); + fxent setmodel( "tag_origin" ); + fxent linkto( ent, "", offsetorigin, offsetangles ); + wait_network_frame(); + playfxontag( effect, fxent, "tag_origin" ); + return fxent; +} + +custom_weapon_wall_prices() +{ + if ( !isDefined( level.zombie_include_weapons ) ) + { + return; + } + weapon_spawns = []; + weapon_spawns = getentarray( "weapon_upgrade", "targetname" ); + i = 0; + while ( i < weapon_spawns.size ) + { + if ( !isDefined( level.zombie_weapons[ weapon_spawns[ i ].zombie_weapon_upgrade ] ) ) + { + i++; + continue; + } + else + { + if ( isDefined( weapon_spawns[ i ].script_int ) ) + { + cost = weapon_spawns[ i ].script_int; + level.zombie_weapons[ weapon_spawns[ i ].zombie_weapon_upgrade ].cost = cost; + } + } + i++; + } +} + +pause_zombie_spawning() +{ + if ( !isDefined( level.spawnpausecount ) ) + { + level.spawnpausecount = 0; + } + level.spawnpausecount++; + flag_clear( "spawn_zombies" ); +} + +try_resume_zombie_spawning() +{ + if ( !isDefined( level.spawnpausecount ) ) + { + level.spawnpausecount = 0; + } + level.spawnpausecount--; + + if ( level.spawnpausecount <= 0 ) + { + level.spawnpausecount = 0; + flag_set( "spawn_zombies" ); + } +} + +automatonspeak( category, type, response, force_variant, override ) +{ + if ( isDefined( level.automaton ) && !is_true( level.automaton.disabled_by_emp ) ) + { + if ( type != "leaving" && type != "leaving_warning" ) + { + level.automaton notify( "want_to_be_speaking" ); + level.automaton waittill( "startspeaking" ); + } + level.automaton maps/mp/zombies/_zm_audio::create_and_play_dialog( category, type, response, force_variant, override ); + } +} + +is_thedouche() +{ + return self.characterindex == 0; +} + +is_theconspiracytheorist() +{ + return self.characterindex == 1; +} + +is_thefarmersdaughter() +{ + return self.characterindex == 2; +} + +is_theelectricalengineer() +{ + return self.characterindex == 3; +} + +get_random_encounter_match( location ) +{ + match_pool = []; + return random( match_pool ); +} + +transit_breakable_glass_init() +{ + glass = getentarray( "transit_glass", "targetname" ); + if ( level.splitscreen && getDvarInt( "splitscreen_playerCount" ) > 2 ) + { + array_delete( glass ); + return; + } + array_thread( glass, ::transit_breakable_glass ); +} + +transit_breakable_glass() +{ + level endon( "intermission" ); + self.health = 99999; + self setcandamage( 1 ); + self.damage_state = 0; + while ( 1 ) + { + self waittill( "damage", amount, attacker, direction, point, dmg_type ); + if ( isplayer( attacker ) ) + { + if ( self.damage_state == 0 ) + { + self glass_gets_destroyed(); + self.damage_state = 1; + self playsound( "fly_glass_break" ); + } + } + } +} + +glass_gets_destroyed() +{ + if ( isDefined( level._effect[ "glass_impact" ] ) ) + { + playfx( level._effect[ "glass_impact" ], self.origin, anglesToForward( self.angles ) ); + } + wait 0.1; + if ( isDefined( self.model ) && self.damage_state == 0 ) + { + self setmodel( self.model + "_broken" ); + self.damage_state = 1; + return; + } + else + { + self delete(); + return; + } +} + +solo_tombstone_removal() +{ + if ( getnumexpectedplayers() > 1 ) + { + return; + } + level notify( "tombstone_removed" ); + level thread maps/mp/zombies/_zm_perks::perk_machine_removal( "specialty_scavenger" ); +} + +sparking_power_lines() +{ + lines = getentarray( "power_line_sparking", "targetname" ); +} + +disconnect_door_zones( zone_a, zone_b, flag_name ) +{ + level endon( "intermission" ); + level endon( "end_game" ); + while ( 1 ) + { + flag_wait( flag_name ); + azone = level.zones[ zone_a ].adjacent_zones[ zone_b ]; + azone maps/mp/zombies/_zm_zonemgr::door_close_disconnect( flag_name ); + } +} + +enable_morse_code() +{ + level clientnotify( "mc1" ); +} + +disable_morse_code() +{ + level clientnotify( "mc0" ); +} + +transit_pathnode_spawning() +{ + precachemodel( "collision_wall_128x128x10_standard" ); + precachemodel( "collision_wall_256x256x10_standard" ); + precachemodel( "collision_clip_64x64x256" ); + minimap_upperl = spawn( "script_origin", ( -12248, 9496, 552 ) ); + minimap_upperl.targetname = "minimap_corner"; + minimap_lowerr = spawn( "script_origin", ( 14472, -8496, -776 ) ); + minimap_lowerr.targetname = "minimap_corner"; + maps/mp/_compass::setupminimap( "compass_map_zm_transit" ); + flag_wait( "start_zombie_round_logic" ); + collision1 = spawn( "script_model", ( 2273, -126, 143 ) ); + collision1 setmodel( "collision_wall_128x128x10_standard" ); + collision1.angles = ( 0, 0, 0 ); + collision1 ghost(); + collision2 = spawn( "script_model", ( 2096, -126, 143 ) ); + collision2 setmodel( "collision_wall_128x128x10_standard" ); + collision2.angles = ( 0, 0, 0 ); + collision2 ghost(); + collision3 = spawn( "script_model", ( 1959, -126, 143 ) ); + collision3 setmodel( "collision_wall_128x128x10_standard" ); + collision3.angles = ( 0, 0, 0 ); + collision3 ghost(); + collision4 = spawn( "script_model", ( 12239, 8509, -688 ) ); + collision4 setmodel( "collision_wall_128x128x10_standard" ); + collision4.angles = ( 0, 0, 0 ); + collision4 ghost(); + collision5 = spawn( "script_model", ( 8320, -6679, 362 ) ); + collision5 setmodel( "collision_wall_256x256x10_standard" ); + collision5.angles = vectorScale( ( 0, 0, 0 ), 300 ); + collision5 ghost(); + collision5 = spawn( "script_model", ( 10068, 7272, -67 ) ); + collision5 setmodel( "collision_clip_64x64x256" ); + collision5.angles = ( 0, 0, 0 ); + collision5 ghost(); +} + diff --git a/zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc b/zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc new file mode 100644 index 0000000..23554ea --- /dev/null +++ b/zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc @@ -0,0 +1,935 @@ +#include maps/mp/animscripts/zm_run; +#include maps/mp/animscripts/zm_death; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_buildables; +#include maps/mp/gametypes_zm/_weaponobjects; +#include maps/mp/zombies/_zm_equipment; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_net; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/_utility; +#include common_scripts/utility; + +init() +{ + if ( !maps/mp/zombies/_zm_weapons::is_weapon_included( "jetgun_zm" ) ) + { + return; + } + maps/mp/zombies/_zm_equipment::register_equipment( "jetgun_zm", &"ZOMBIE_EQUIP_JETGUN_PICKUP_HINT_STRING", &"ZOMBIE_EQUIP_JETGUN_HOWTO", "jetgun_zm_icon", "jetgun", ::jetgun_activation_watcher_thread, undefined, ::dropjetgun, ::pickupjetgun ); + maps/mp/gametypes_zm/_weaponobjects::createretrievablehint( "jetgun", &"ZOMBIE_EQUIP_JETGUN_PICKUP_HINT_STRING" ); + level._effect[ "jetgun_smoke_cloud" ] = loadfx( "weapon/thunder_gun/fx_thundergun_smoke_cloud" ); + level._effect[ "jetgun_overheat" ] = loadfx( "weapon/jet_gun/fx_jetgun_overheat" ); + level._effect[ "jetgun_vortex" ] = loadfx( "weapon/jet_gun/fx_jetgun_on" ); + level._effect[ "jetgun_meat_grinder" ] = loadfx( "weapon/jet_gun/fx_jetgun_kill" ); + set_zombie_var( "jetgun_cylinder_radius", 1024 ); + set_zombie_var( "jetgun_grind_range", 128 ); + set_zombie_var( "jetgun_gib_range", 256 ); + set_zombie_var( "jetgun_gib_damage", 50 ); + set_zombie_var( "jetgun_knockdown_range", 256 ); + set_zombie_var( "jetgun_drag_range", 2048 ); + set_zombie_var( "jetgun_knockdown_damage", 15 ); + set_zombie_var( "powerup_move_dist", 50 ); + set_zombie_var( "powerup_drag_range", 500 ); + level.jetgun_pulled_in_range = int( level.zombie_vars[ "jetgun_drag_range" ] / 8 ) * ( level.zombie_vars[ "jetgun_drag_range" ] / 8 ); + level.jetgun_pulling_in_range = int( level.zombie_vars[ "jetgun_drag_range" ] / 4 ) * ( level.zombie_vars[ "jetgun_drag_range" ] / 4 ); + level.jetgun_inner_range = int( level.zombie_vars[ "jetgun_drag_range" ] / 2 ) * ( level.zombie_vars[ "jetgun_drag_range" ] / 2 ); + level.jetgun_outer_edge = int( level.zombie_vars[ "jetgun_drag_range" ] * level.zombie_vars[ "jetgun_drag_range" ] ); + level.jetgun_gib_refs = []; + level.jetgun_gib_refs[ level.jetgun_gib_refs.size ] = "guts"; + level.jetgun_gib_refs[ level.jetgun_gib_refs.size ] = "right_arm"; + level.jetgun_gib_refs[ level.jetgun_gib_refs.size ] = "left_arm"; + level.jetgun_gib_refs[ level.jetgun_gib_refs.size ] = "right_leg"; + level.jetgun_gib_refs[ level.jetgun_gib_refs.size ] = "left_leg"; + level.jetgun_gib_refs[ level.jetgun_gib_refs.size ] = "no_legs"; + /* +/# + level thread jetgun_devgui_dvar_think(); + level.zm_devgui_jetgun_never_overheat = ::never_overheat; +#/ + */ + onplayerconnect_callback( ::jetgun_on_player_connect ); +} + +dropjetgun() +{ + item = self maps/mp/zombies/_zm_equipment::placed_equipment_think( "t6_wpn_zmb_jet_gun_world", "jetgun_zm", self.origin + vectorScale( ( 1, 0, 1 ), 30 ), self.angles ); + if ( isDefined( item ) ) + { + item.overheating = self.jetgun_overheating; + item.heatval = self.jetgun_heatval; + item.original_owner = self; + item.owner = undefined; + item.name = "jetgun_zm"; + item.requires_pickup = 1; + } + self.jetgun_overheating = undefined; + self.jetgun_heatval = undefined; + self takeweapon( "jetgun_zm" ); + return item; +} + +pickupjetgun( item ) +{ + item.owner = self; + if ( isDefined( item.overheating ) && isDefined( item.heatval ) ) + { + self.jetgun_overheating = item.overheating; + self.jetgun_heatval = item.heatval; + } + item.overheating = undefined; + item.heatval = undefined; + self setcurrentweaponspinlerp( 0 ); +} + +jetgun_activation_watcher_thread() +{ + self endon( "zombified" ); + self endon( "disconnect" ); + self endon( "jetgun_zm_taken" ); + while ( 1 ) + { + self waittill_either( "jetgun_zm_activate", "jetgun_zm_deactivate" ); + } +} + +jetgun_devgui_dvar_think() +{ +/* +/# + if ( !maps/mp/zombies/_zm_weapons::is_weapon_included( "jetgun_zm" ) ) + { + return; + } + setdvar( "scr_jetgun_cylinder_radius", level.zombie_vars[ "jetgun_cylinder_radius" ] ); + setdvar( "scr_jetgun_grind_range", level.zombie_vars[ "jetgun_grind_range" ] ); + setdvar( "scr_jetgun_drag_range", level.zombie_vars[ "jetgun_drag_range" ] ); + setdvar( "scr_jetgun_gib_range", level.zombie_vars[ "jetgun_gib_range" ] ); + setdvar( "scr_jetgun_gib_damage", level.zombie_vars[ "jetgun_gib_damage" ] ); + setdvar( "scr_jetgun_knockdown_range", level.zombie_vars[ "jetgun_knockdown_range" ] ); + setdvar( "scr_jetgun_knockdown_damage", level.zombie_vars[ "jetgun_knockdown_damage" ] ); + for ( ;; ) + { + level.zombie_vars[ "jetgun_cylinder_radius" ] = getDvarInt( "scr_jetgun_cylinder_radius" ); + level.zombie_vars[ "jetgun_grind_range" ] = getDvarInt( "scr_jetgun_grind_range" ); + level.zombie_vars[ "jetgun_drag_range" ] = getDvarInt( "scr_jetgun_drag_range" ); + level.zombie_vars[ "jetgun_gib_range" ] = getDvarInt( "scr_jetgun_gib_range" ); + level.zombie_vars[ "jetgun_gib_damage" ] = getDvarInt( "scr_jetgun_gib_damage" ); + level.zombie_vars[ "jetgun_knockdown_range" ] = getDvarInt( "scr_jetgun_knockdown_range" ); + level.zombie_vars[ "jetgun_knockdown_damage" ] = getDvarInt( "scr_jetgun_knockdown_damage" ); + wait 0.5; + } +#/ +*/ +} + +jetgun_on_player_connect() +{ + self thread wait_for_jetgun_fired(); + self thread watch_weapon_changes(); + self thread handle_overheated_jetgun(); +} + +get_jetgun_engine_direction() +{ + return self getcurrentweaponspinlerp(); +} + +set_jetgun_engine_direction( nv ) +{ + self setcurrentweaponspinlerp( nv ); +} + +never_overheat() +{ +/* +/# + self notify( "never_overheat" ); + self endon( "never_overheat" ); + self endon( "death_or_disconnect" ); + while ( 1 ) + { + if ( self getcurrentweapon() == "jetgun_zm" ) + { + self setweaponoverheating( 0, 0 ); + } + wait 0.05; + + } +#/ +*/ +} + +watch_overheat() +{ + self endon( "death_or_disconnect" ); + self endon( "weapon_change" ); + if ( self getcurrentweapon() == "jetgun_zm" && isDefined( self.jetgun_overheating ) && isDefined( self.jetgun_heatval ) ) + { + self setweaponoverheating( self.jetgun_overheating, self.jetgun_heatval ); + } + while ( 1 ) + { + if ( self getcurrentweapon() == "jetgun_zm" ) + { + overheating = self isweaponoverheating( 0 ); + heat = self isweaponoverheating( 1 ); + self.jetgun_overheating = overheating; + self.jetgun_heatval = heat; + if ( overheating ) + { + self notify( "jetgun_overheated" ); + } + if ( heat > 75 ) + { + self thread play_overheat_fx(); + } + } + wait 0.05; + } +} + +play_overheat_fx() +{ + if ( isDefined( self.overheat_fx_playing ) && !self.overheat_fx_playing ) + { + self.overheat_fx_playing = 1; + playfxontag( level._effect[ "jetgun_overheat" ], self, "tag_flash" ); + wait 5; + if ( isDefined( self ) ) + { + self.overheat_fx_playing = 0; + } + } +} + +handle_overheated_jetgun() +{ + self endon( "disconnect" ); + while ( 1 ) + { + self waittill( "jetgun_overheated" ); + if ( self getcurrentweapon() == "jetgun_zm" ) + { + if ( isDefined( level.explode_overheated_jetgun ) && level.explode_overheated_jetgun ) + { + self thread maps/mp/zombies/_zm_equipment::equipment_release( "jetgun_zm" ); + weapon_org = self gettagorigin( "tag_weapon" ); + pcount = get_players().size; + pickup_time = 360 / pcount; + maps/mp/zombies/_zm_buildables::player_explode_buildable( "jetgun_zm", weapon_org, 250, 1, pickup_time ); + self.jetgun_overheating = undefined; + self.jetgun_heatval = undefined; + self playsound( "wpn_jetgun_explo" ); + break; + } + else + { + if ( isDefined( level.unbuild_overheated_jetgun ) && level.unbuild_overheated_jetgun ) + { + self thread maps/mp/zombies/_zm_equipment::equipment_release( "jetgun_zm" ); + maps/mp/zombies/_zm_buildables::unbuild_buildable( "jetgun_zm", 1 ); + self.jetgun_overheating = undefined; + self.jetgun_heatval = undefined; + break; + } + else + { + if ( isDefined( level.take_overheated_jetgun ) && level.take_overheated_jetgun ) + { + self thread maps/mp/zombies/_zm_equipment::equipment_release( "jetgun_zm" ); + self.jetgun_overheating = undefined; + self.jetgun_heatval = undefined; + } + } + } + } + } +} + +watch_weapon_changes() +{ + self endon( "disconnect" ); + for ( ;; ) + { + self waittill( "weapon_change", weapon ); + if ( weapon == "jetgun_zm" ) + { + /* +/# + if ( getDvarInt( #"BCDDAAFF" ) > 0 ) + { + self thread zombie_drag_radius(); + + } +#/ + */ + self thread watch_overheat(); + } + } +} + +wait_for_jetgun_fired() +{ + self endon( "disconnect" ); + self waittill( "spawned_player" ); + for ( ;; ) + { + self waittill( "weapon_fired" ); + currentweapon = self getcurrentweapon(); + if ( currentweapon == "jetgun_zm" || currentweapon == "jetgun_upgraded_zm" ) + { + self jetgun_firing(); + } + } +} + +jetgun_network_choke() +{ + level.jetgun_network_choke_count++; + if ( level.jetgun_network_choke_count % 10 ) + { + wait_network_frame(); + wait_network_frame(); + wait_network_frame(); + } +} + +is_jetgun_firing() +{ + return abs( self get_jetgun_engine_direction() ) > 0.2; +} + +jetgun_firing() +{ + if ( !isDefined( self.jetsound_ent ) ) + { + self.jetsound_ent = spawn( "script_origin", self.origin ); + self.jetsound_ent linkto( self, "tag_origin" ); + } + jetgun_fired = 0; + if ( self is_jetgun_firing() && jetgun_fired == 0 ) + { + self.jetsound_ent playloopsound( "wpn_jetgun_effect_plr_loop", 0.8 ); + self.jetsound_ent playsound( "wpn_jetgun_effect_plr_start" ); + self notify( "jgun_snd" ); + } + while ( self is_jetgun_firing() ) + { + jetgun_fired = 1; + self thread jetgun_fired(); + view_pos = self gettagorigin( "tag_flash" ); + view_angles = self gettagangles( "tag_flash" ); + if ( self get_jetgun_engine_direction() < 0 ) + { + playfx( level._effect[ "jetgun_smoke_cloud" ], view_pos - self getplayerviewheight(), anglesToForward( view_angles ), anglesToUp( view_angles ) ); + } + else + { + playfx( level._effect[ "jetgun_smoke_cloud" ], view_pos - self getplayerviewheight(), anglesToForward( view_angles ) * -1, anglesToUp( view_angles ) ); + } + wait 0.25; + } + if ( jetgun_fired == 1 ) + { + self.jetsound_ent stoploopsound( 0.5 ); + self.jetsound_ent playsound( "wpn_jetgun_effect_plr_end" ); + self.jetsound_ent thread sound_ent_cleanup(); + jetgun_fired = 0; + } +} + +sound_ent_cleanup() +{ + self endon( "jgun_snd" ); + wait 4; + if ( isDefined( self.jetsound_ent ) ) + { + self delete(); + } +} + +jetgun_fired() +{ + if ( !self is_jetgun_firing() ) + { + return; + } + origin = self getweaponmuzzlepoint(); + physicsjetthrust( origin, self getweaponforwarddir() * -1, level.zombie_vars[ "jetgun_grind_range" ], self get_jetgun_engine_direction(), 0.85 ); + if ( !isDefined( level.jetgun_knockdown_enemies ) ) + { + level.jetgun_knockdown_enemies = []; + level.jetgun_knockdown_gib = []; + level.jetgun_drag_enemies = []; + level.jetgun_fling_enemies = []; + level.jetgun_grind_enemies = []; + } + powerups = maps/mp/zombies/_zm_powerups::get_powerups(); + if ( isDefined( powerups ) && powerups.size ) + { + self thread try_pull_powerups( powerups ); + } + self jetgun_get_enemies_in_range( self get_jetgun_engine_direction() ); + level.jetgun_network_choke_count = 0; + _a408 = level.jetgun_fling_enemies; + index = getFirstArrayKey( _a408 ); + while ( isDefined( index ) ) + { + zombie = _a408[ index ]; + jetgun_network_choke(); + if ( isDefined( zombie ) ) + { + zombie thread jetgun_fling_zombie( self, index ); + } + index = getNextArrayKey( _a408, index ); + } + _a418 = level.jetgun_drag_enemies; + _k418 = getFirstArrayKey( _a418 ); + while ( isDefined( _k418 ) ) + { + zombie = _a418[ _k418 ]; + jetgun_network_choke(); + if ( isDefined( zombie ) ) + { + zombie.jetgun_owner = self; + zombie thread jetgun_drag_zombie( origin, -1 * self get_jetgun_engine_direction() ); + } + _k418 = getNextArrayKey( _a418, _k418 ); + } + level.jetgun_knockdown_enemies = []; + level.jetgun_knockdown_gib = []; + level.jetgun_drag_enemies = []; + level.jetgun_fling_enemies = []; + level.jetgun_grind_enemies = []; +} + +try_pull_powerups( powerups ) +{ + powerup_move_dist = level.zombie_vars[ "powerup_move_dist" ] * -1 * self get_jetgun_engine_direction(); + powerup_range_squared = level.zombie_vars[ "powerup_drag_range" ] * level.zombie_vars[ "powerup_drag_range" ]; + view_pos = self getweaponmuzzlepoint(); + forward_view_angles = self getweaponforwarddir(); + _a453 = powerups; + _k453 = getFirstArrayKey( _a453 ); + while ( isDefined( _k453 ) ) + { + powerup = _a453[ _k453 ]; + if ( distancesquared( view_pos, powerup.origin ) > powerup_range_squared ) + { + } + else normal = vectornormalize( powerup.origin - view_pos ); + dot = vectordot( forward_view_angles, normal ); + if ( abs( dot ) < 0.7 ) + { + } + else + { + powerup notify( "move_powerup" ); + } + _k453 = getNextArrayKey( _a453, _k453 ); + } +} + +jetgun_get_enemies_in_range( invert ) +{ + view_pos = self getweaponmuzzlepoint(); + zombies = get_array_of_closest( view_pos, get_round_enemy_array(), undefined, 3, level.zombie_vars[ "jetgun_drag_range" ] ); + if ( !isDefined( zombies ) ) + { + } + knockdown_range_squared = level.zombie_vars[ "jetgun_knockdown_range" ] * level.zombie_vars[ "jetgun_knockdown_range" ]; + drag_range_squared = level.zombie_vars[ "jetgun_drag_range" ] * level.zombie_vars[ "jetgun_drag_range" ]; + gib_range_squared = level.zombie_vars[ "jetgun_gib_range" ] * level.zombie_vars[ "jetgun_gib_range" ]; + grind_range_squared = level.zombie_vars[ "jetgun_grind_range" ] * level.zombie_vars[ "jetgun_grind_range" ]; + cylinder_radius_squared = level.zombie_vars[ "jetgun_cylinder_radius" ] * level.zombie_vars[ "jetgun_cylinder_radius" ]; + forward_view_angles = self getweaponforwarddir(); + end_pos = view_pos + vectorScale( forward_view_angles, level.zombie_vars[ "jetgun_knockdown_range" ] ); + /* +/# + if ( getDvarInt( #"BCDDAAFF" ) == 2 ) + { + near_circle_pos = view_pos + vectorScale( forward_view_angles, 2 ); + circle( near_circle_pos, level.zombie_vars[ "jetgun_cylinder_radius" ], ( 1, 0, 1 ), 0, 0, 100 ); + line( near_circle_pos, end_pos, ( 1, 0, 1 ), 1, 0, 100 ); + circle( end_pos, level.zombie_vars[ "jetgun_cylinder_radius" ], ( 1, 0, 1 ), 0, 0, 100 ); + + } +#/ + */ + i = 0; + while ( i < zombies.size ) + { + self jetgun_check_enemies_in_range( zombies[ i ], view_pos, drag_range_squared, gib_range_squared, grind_range_squared, cylinder_radius_squared, forward_view_angles, end_pos, invert ); + i++; + } +} + +jetgun_check_enemies_in_range( zombie, view_pos, drag_range_squared, gib_range_squared, grind_range_squared, cylinder_radius_squared, forward_view_angles, end_pos, invert ) +{ + if ( !isDefined( zombie ) ) + { + return; + } + if ( !isDefined( zombie ) ) + { + return; + } + if ( zombie enemy_killed_by_jetgun() ) + { + return; + } + if ( !isDefined( zombie.ai_state ) || zombie.ai_state != "find_flesh" && zombie.ai_state != "zombieMoveOnBus" ) + { + return; + } + if ( isDefined( zombie.in_the_ground ) && zombie.in_the_ground ) + { + return; + } + if ( isDefined( zombie.is_avogadro ) && zombie.is_avogadro ) + { + return; + } + if ( isDefined( zombie.isdog ) && zombie.isdog ) + { + return; + } + if ( isDefined( zombie.isscreecher ) && zombie.isscreecher ) + { + return; + } + if ( isDefined( self.animname ) && self.animname == "quad_zombie" ) + { + return; + } + test_origin = zombie getcentroid(); + test_range_squared = distancesquared( view_pos, test_origin ); + if ( test_range_squared > drag_range_squared ) + { + zombie jetgun_debug_print( "range", ( 1, 0, 1 ) ); + return; + } + normal = vectornormalize( test_origin - view_pos ); + dot = vectordot( forward_view_angles, normal ); + if ( abs( dot ) < 0.7 ) + { + zombie jetgun_debug_print( "dot", ( 1, 0, 1 ) ); + return; + } + radial_origin = pointonsegmentnearesttopoint( view_pos, end_pos, test_origin ); + if ( distancesquared( test_origin, radial_origin ) > cylinder_radius_squared ) + { + zombie jetgun_debug_print( "cylinder", ( 1, 0, 1 ) ); + return; + } + if ( zombie damageconetrace( view_pos, self ) == 0 ) + { + zombie jetgun_debug_print( "cone", ( 1, 0, 1 ) ); + return; + } + jetgun_blow_suck = invert; + if ( dot <= 0 ) + { + jetgun_blow_suck *= -1; + } + if ( test_range_squared < grind_range_squared ) + { + level.jetgun_fling_enemies[ level.jetgun_fling_enemies.size ] = zombie; + level.jetgun_grind_enemies[ level.jetgun_grind_enemies.size ] = dot < 0; + } + else + { + if ( test_range_squared < drag_range_squared && dot > 0 ) + { + level.jetgun_drag_enemies[ level.jetgun_drag_enemies.size ] = zombie; + } + } +} + +jetgun_debug_print( msg, color ) +{ +/* +/# + if ( !getDvarInt( #"BCDDAAFF" ) ) + { + return; + } + if ( !isDefined( color ) ) + { + color = ( 1, 0, 1 ); + } + print3d( self.origin + vectorScale( ( 1, 0, 1 ), 60 ), msg, color, 1, 1, 40 ); +#/ +*/ +} + +jetgun_debug_print_on_ent( msg, color ) +{ +/* +/# + if ( !getDvarInt( #"BCDDAAFF" ) ) + { + return; + } + if ( !isDefined( color ) ) + { + color = ( 1, 0, 1 ); + } + self notify( "new_jetgun_debug_print_on_ent" ); + self endon( "death" ); + self endon( "jetgun_end_drag_state" ); + self endon( "new_jetgun_debug_print_on_ent" ); + while ( 1 ) + { + print3d( self.origin + vectorScale( ( 1, 0, 1 ), 60 ), msg, color, 1, 1 ); + wait 0.05; + + } +#/ +*/ +} + +try_gibbing() +{ + if ( isDefined( self ) && isDefined( self.a ) && isDefined( self.isscreecher ) && !self.isscreecher ) + { + self.a.gib_ref = random( level.jetgun_gib_refs ); + self thread maps/mp/animscripts/zm_death::do_gib(); + } +} + +jetgun_handle_death_notetracks( note ) +{ + if ( note == "jetgunned" ) + { + self thread jetgun_grind_death_ending(); + } +} + +jetgun_grind_death_ending() +{ + if ( !isDefined( self ) ) + { + return; + } + self hide(); + wait 0.1; + self self_delete(); +} + +jetgun_grind_zombie( player ) +{ + player endon( "death" ); + player endon( "disconnect" ); + self endon( "death" ); + if ( !isDefined( self.jetgun_grind ) ) + { + self.jetgun_grind = 1; + self notify( "grinding" ); + player set_jetgun_engine_direction( 0.5 * player get_jetgun_engine_direction() ); + if ( is_mature() ) + { + if ( isDefined( level._effect[ "zombie_guts_explosion" ] ) ) + { + playfx( level._effect[ "zombie_guts_explosion" ], self gettagorigin( "J_SpineLower" ) ); + } + } + self.nodeathragdoll = 1; + self.handle_death_notetracks = ::jetgun_handle_death_notetracks; + self dodamage( self.health + 666, player.origin, player ); + } +} + +jetgun_fling_zombie( player, index ) +{ + if ( !isDefined( self ) ) + { + return; + } + if ( isDefined( self.jetgun_fling_func ) ) + { + self [[ self.jetgun_fling_func ]]( player ); + return; + } + was_alive = isalive( self ); + if ( was_alive ) + { + self.jetgun_fling = 1; + self notify( "flinging" ); + deathanim = undefined; + if ( is_mature() ) + { + player weaponplayejectbrass(); + } + if ( isDefined( self.has_legs ) && self.has_legs ) + { + if ( isDefined( self.jetgun_drag_state ) && self.jetgun_drag_state == "jetgun_sprint" ) + { + deathanim = "zm_jetgun_sprint_death"; + } + else + { + deathanim = "zm_jetgun_death"; + } + } + else + { + deathanim = "zm_jetgun_death_crawl"; + } + self.deathanim = deathanim; + player playsound( "evt_jetgun_zmb_suck" ); + } + self thread jetgun_grind_zombie( player ); +} + +jetgun_drag_zombie( vdir, speed ) +{ + if ( isDefined( self.jetgun_drag_func ) ) + { + self [[ self.jetgun_drag_func ]]( vdir, speed ); + return; + } + self zombie_do_drag( vdir, speed ); +} + +jetgun_knockdown_zombie( player, gib ) +{ + self endon( "death" ); + return; + if ( isDefined( self.jetgun_knockdown_func ) ) + { + self [[ self.jetgun_knockdown_func ]]( player, gib ); + } + else + { + self dodamage( level.zombie_vars[ "jetgun_knockdown_damage" ], player.origin, player ); + } + if ( gib ) + { + self.a.gib_ref = random( level.jetgun_gib_refs ); + self thread maps/mp/animscripts/zm_death::do_gib(); + } + self.jetgun_handle_pain_notetracks = ::handle_jetgun_pain_notetracks; + self dodamage( level.zombie_vars[ "jetgun_knockdown_damage" ], player.origin, player ); +} + +handle_jetgun_pain_notetracks( note ) +{ + if ( note == "zombie_knockdown_ground_impact" ) + { + playfx( level._effect[ "jetgun_knockdown_ground" ], self.origin, anglesToForward( self.angles ), anglesToUp( self.angles ) ); + } +} + +is_jetgun_damage() +{ + if ( isDefined( self.damageweapon ) && self.damageweapon != "jetgun_zm" && self.damageweapon == "jetgun_upgraded_zm" ) + { + if ( self.damagemod != "MOD_GRENADE" ) + { + return self.damagemod != "MOD_GRENADE_SPLASH"; + } + } +} + +enemy_killed_by_jetgun() +{ + if ( isDefined( self.jetgun_fling ) && !self.jetgun_fling ) + { + if ( isDefined( self.jetgun_grind ) ) + { + return self.jetgun_grind; + } + } +} + +zombie_do_drag( vdir, speed ) +{ + if ( !self zombie_is_in_drag_state() ) + { + self zombie_enter_drag_state( vdir, speed ); + self thread zombie_drag_think(); + } + else + { + self zombie_keep_in_drag_state( vdir, speed ); + } +} + +zombie_is_in_drag_state() +{ + if ( isDefined( self.drag_state ) ) + { + return self.drag_state; + } +} + +zombie_should_stay_in_drag_state() +{ + if ( !isDefined( self ) || !isalive( self ) ) + { + return 0; + } + if ( isDefined( self.jetgun_owner ) || self.jetgun_owner getcurrentweapon() != "jetgun_zm" && !self.jetgun_owner is_jetgun_firing() ) + { + return 0; + } + if ( isDefined( self.drag_state ) && self.drag_state ) + { + return 1; + } + return 0; +} + +zombie_keep_in_drag_state( vdir, speed ) +{ + self.drag_start_time = getTime(); + self.drag_target = vdir; +} + +zombie_enter_drag_state( vdir, speed ) +{ + self.drag_state = 1; + self.jetgun_drag_state = "unaffected"; + if ( isDefined( self.is_traversing ) ) + { + self.was_traversing = self.is_traversing; + } + self notify( "killanimscript" ); + self zombie_keep_in_drag_state( vdir, speed ); + self.zombie_move_speed_pre_jetgun_drag = self.zombie_move_speed; +} + +zombie_exit_drag_state() +{ + self notify( "jetgun_end_drag_state" ); + self.drag_state = 0; + self.jetgun_drag_state = "unaffected"; + self.needs_run_update = 1; + if ( isDefined( self.zombie_move_speed_pre_jetgun_drag ) ) + { + self set_zombie_run_cycle( self.zombie_move_speed_pre_jetgun_drag ); + self.zombie_move_speed_pre_jetgun_drag = undefined; + } + else + { + self set_zombie_run_cycle(); + } + if ( isDefined( self.isdog ) && !self.isdog ) + { + self maps/mp/animscripts/zm_run::moverun(); + } + if ( isDefined( self.was_traversing ) && self.was_traversing ) + { + self traversemode( "gravity" ); + self.a.nodeath = 0; + self maps/mp/animscripts/zm_run::needsupdate(); + if ( !self.isdog ) + { + self maps/mp/animscripts/zm_run::moverun(); + } + self.is_traversing = 0; + self notify( "zombie_end_traverse" ); + if ( is_mature() ) + { + if ( isDefined( level._effect[ "zombie_guts_explosion" ] ) ) + { + playfx( level._effect[ "zombie_guts_explosion" ], self gettagorigin( "J_SpineLower" ) ); + } + } + self.nodeathragdoll = 1; + self dodamage( self.health + 666, self.origin, self ); + } +} + +aiphysicstrace( start, end ) +{ + result = physicstrace( start, end, ( 1, 0, 1 ), ( 1, 0, 1 ), self ); + return result[ "position" ]; +} + +zombie_drag_think() +{ + self endon( "death" ); + self endon( "flinging" ); + self endon( "grinding" ); + while ( self zombie_should_stay_in_drag_state() ) + { + self._distance_to_jetgun_owner = distancesquared( self.origin, self.jetgun_owner.origin ); + jetgun_network_choke(); + if ( self.zombie_move_speed == "sprint" || self._distance_to_jetgun_owner < level.jetgun_pulled_in_range ) + { + self jetgun_drag_set( "jetgun_sprint", "jetgun_walk_fast_crawl" ); + } + else + { + if ( self._distance_to_jetgun_owner < level.jetgun_pulling_in_range ) + { + self jetgun_drag_set( "jetgun_walk_fast", "jetgun_walk_fast" ); + break; + } + else if ( self._distance_to_jetgun_owner < level.jetgun_inner_range ) + { + self jetgun_drag_set( "jetgun_walk", "jetgun_walk_slow_crawl" ); + break; + } + else + { + if ( self._distance_to_jetgun_owner < level.jetgun_outer_edge ) + { + self jetgun_drag_set( "jetgun_walk_slow", "jetgun_walk_slow_crawl" ); + } + } + } + wait 0.1; + } + self thread zombie_exit_drag_state(); +} + +jetgun_drag_set( legsanim, crawlanim ) +{ + self endon( "death" ); + self.needs_run_update = 1; + if ( self.has_legs ) + { + self._had_legs = 1; + self set_zombie_run_cycle( legsanim ); + } + else + { + self._had_legs = 0; + self set_zombie_run_cycle( crawlanim ); + } +/* +/# + if ( self.jetgun_drag_state != legsanim ) + { + self thread jetgun_debug_print_on_ent( legsanim, ( 1, 0, 1 ) ); + + } + self.jetgun_drag_state = legsanim; +#/ +*/ +} + +zombie_drag_radius() +{ +/* +/# + self endon( "death_or_disconnect" ); + self endon( "weapon_change" ); + while ( 1 ) + { + circle( self.origin, level.zombie_vars[ "jetgun_grind_range" ], vectorScale( ( 1, 0, 1 ), 0.5 ) ); + circle( self.origin, level.zombie_vars[ "jetgun_drag_range" ] / 8, ( 1, 0, 1 ) ); + circle( self.origin, level.zombie_vars[ "jetgun_drag_range" ] / 4, ( 1, 0, 1 ) ); + circle( self.origin, level.zombie_vars[ "jetgun_drag_range" ] / 2, ( 1, 0, 1 ) ); + circle( self.origin, level.zombie_vars[ "jetgun_drag_range" ], ( 1, 0, 1 ) ); + wait 0.05; + + } +#/ +*/ +} + diff --git a/zm_transit_patch/readme.md b/zm_transit_patch/readme.md new file mode 100644 index 0000000..752a19a --- /dev/null +++ b/zm_transit_patch/readme.md @@ -0,0 +1,24 @@ +### The following gscs compile and run successfully with no known 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: + +``` +zm_transit_patch/maps/mp/zombies/_zm_weap_jetgun.gsc +``` + +### The following scripts compile and run serverside but clients cannot join due to exe_client_field_mismatch + +### The following scripts compile but cause a minidump or other severe error: + +### notes: +``` +zm_transit_utility.gsc can be recompiled to fix tombstone +```