From 5ef4f751e566f7b99e1053ed907a35c8335bc0ec Mon Sep 17 00:00:00 2001 From: Cahz Date: Sat, 8 Aug 2020 09:44:29 -0700 Subject: [PATCH] Updated Github --- .../MW3 Styled Infection/README.md | 3 + .../MW3 Styled Infection/_clientids.gsc | 280 ++ Multiplayer Mods/Vote Kick System/README.md | 6 + .../Vote Kick System/_clientids.gsc | 322 ++ Zombies Mods/Grenade Cluster/README.md | 6 + Zombies Mods/Grenade Cluster/_clientids.gsc | 49 + Zombies Mods/Vote Kick System/README.md | 6 + Zombies Mods/Vote Kick System/_clientids.gsc | 328 ++ .../maps/mp/gametypes_zm/_clientids.gsc | Bin 0 -> 29212 bytes .../maps/mp/zombies/_zm_powerups.gsc | Bin 0 -> 52324 bytes Zombies Mods/Zombies++ v1.2/README.md | 16 + .../Zombies++ v1.2/Source Code/_clientids.gsc | 1157 ++++++ .../Source Code/_zm_powerups.gsc | 3124 +++++++++++++++++ Zombies Mods/Zombies++ v1.2/dedicated_zm.cfg | 249 ++ 14 files changed, 5546 insertions(+) create mode 100644 Multiplayer Mods/MW3 Styled Infection/README.md create mode 100644 Multiplayer Mods/MW3 Styled Infection/_clientids.gsc create mode 100644 Multiplayer Mods/Vote Kick System/README.md create mode 100644 Multiplayer Mods/Vote Kick System/_clientids.gsc create mode 100644 Zombies Mods/Grenade Cluster/README.md create mode 100644 Zombies Mods/Grenade Cluster/_clientids.gsc create mode 100644 Zombies Mods/Vote Kick System/README.md create mode 100644 Zombies Mods/Vote Kick System/_clientids.gsc create mode 100644 Zombies Mods/Zombies++ v1.2/Precompiled/maps/mp/gametypes_zm/_clientids.gsc create mode 100644 Zombies Mods/Zombies++ v1.2/Precompiled/maps/mp/zombies/_zm_powerups.gsc create mode 100644 Zombies Mods/Zombies++ v1.2/README.md create mode 100644 Zombies Mods/Zombies++ v1.2/Source Code/_clientids.gsc create mode 100644 Zombies Mods/Zombies++ v1.2/Source Code/_zm_powerups.gsc create mode 100644 Zombies Mods/Zombies++ v1.2/dedicated_zm.cfg diff --git a/Multiplayer Mods/MW3 Styled Infection/README.md b/Multiplayer Mods/MW3 Styled Infection/README.md new file mode 100644 index 0000000..79b478b --- /dev/null +++ b/Multiplayer Mods/MW3 Styled Infection/README.md @@ -0,0 +1,3 @@ +# MW3 STYLED INFECTED +## DIRECTIONS +- Compile _**_clientids.gsc**_ as _**_clientids.gsc**_ and place it in the directory _**maps/mp/gametypes_zm/_clientids.gsc**_ diff --git a/Multiplayer Mods/MW3 Styled Infection/_clientids.gsc b/Multiplayer Mods/MW3 Styled Infection/_clientids.gsc new file mode 100644 index 0000000..9f4519f --- /dev/null +++ b/Multiplayer Mods/MW3 Styled Infection/_clientids.gsc @@ -0,0 +1,280 @@ +/*////////////////// +//MOD INFORMATION// +////////////////// + +MW3 STYLE INFECTION GAMEMODE +DEVELOPED BY @ItsCahz + +Free for use to the public +Released on plutonium forums by Cahz + +This mod runs best with Team Deathmatch as the gamemode +The goal of Infected is to stay alive as long as possible + +SURVIVORS +Random Primary (mtar, msmc, m27, or remmington) +Secondary (fiveseven) + +INFECTED +First Infected gets survivor loadout until there is more than one person infected +Knife and Tomahawk only afterwards +*/ + +#include maps/mp/_utility; +#include common_scripts/utility; +#include maps/mp/gametypes/_hud_util; +#include maps/mp/gametypes/_hud_message; +#include maps/mp/gametypes/_globallogic; + +init() +{ + level thread onPlayerConnect(); + level thread StartInfected(); + level thread EndInfected(); + //wait 1; + //level thread spawnBot(10); +} + +onPlayerConnect() +{ + for(;;) + { + level waittill("connected", player); + player thread onPlayerSpawned(); + player thread checkName(player.name); + player maps\mp\teams\_teams::changeteam("axis"); + player thread onScreenText(); + } +} + +onPlayerSpawned() +{ + self endon("disconnect"); + level endon("game_ended"); + for(;;) + { + self waittill("spawned_player"); + level notify("update_text"); + + self givePerks(); + + if(!isDefined(self.isFirstSpawn)) + { + self.isFirstSpawn = true; + self iprintln("Welcome to MW3 Style Infection!"); + self iprintln("Developed by: ^5@ItsCahz"); + } + if(self.pers["team"] == "axis") + { + if(isDefined(self.infected)) + self maps\mp\teams\_teams::changeteam("allies"); + else + { + self iprintlnbold("^5You Are Not Infected! Stay Alive!"); + + self thread giveWeapons("Survivor"); + self thread monitorWeapons(); + self thread waitForDeath(); + + level.totalAlive += 1; + } + } + if(self.pers["team"] == "allies") + { + if(!isDefined(self.infected)) + self maps\mp\teams\_teams::changeteam("axis"); + else + { + self iprintlnbold("^1You Are Infected! Kill the Survivors!"); + + if(level.infectedCount == 1) + self thread giveWeapons("Survivors"); + else + self thread giveWeapons("Infected"); + + self thread monitorWeapons(); + } + } + } +} + +checkName(text) +{ + if(IsInArray(level.infectedtable, text)) + self.infected = true; +} + +saveName(text) +{ + if(!IsInArray(level.infectedtable, text)) + level.infectedtable[level.infectedtable.size] = text; +} + +StartInfected() +{ + level.totalAlive = 0; + level.infectedCount = 0; + level.firstinfected = ""; + level.infectedtable = []; + + level.survivorWeapons = strTok("insas_mp,870mcs_mp,hk416_mp,tar21_mp", ","); + + level.survivorPrimary = RandomInt(level.survivorWeapons.size); + level.survivorSecondary = "fiveseven_mp"; + + level.infectedPrimary = "knife_mp"; + level.infectedSecondary = "hatchet_mp"; + level.infectedTactical = "tactical_insertion_mp"; + + level thread updateText(); + + level waittill("prematch_over"); + + wait 3; + iPrintlnBold("^1Picking First Infected!"); + wait 5; + + level.firstinfected = pickRandomPlayer(); + level.firstinfected.infected = true; + level.firstinfected suicide(); + level.firstinfected maps\mp\teams\_teams::changeteam("allies"); + + level.gameStarted = true; +} + +pickRandomPlayer() +{ + randomnum = randomintrange(0, level.players.size); + infected = level.players[randomnum]; + + if (isAlive(infected)) + return infected; + else + return pickRandomPlayer(); +} + +giveWeapons(Team) +{ + self takeallweapons(); + if(Team == "Infected") + { + self giveWeapon(level.infectedPrimary); + self giveWeapon(level.infectedSecondary); + self giveWeapon(level.infectedTactical); + self switchToWeapon(level.infectedPrimary); + } + else + { + self giveWeapon(level.survivorWeapons[level.survivorPrimary]); + self giveWeapon(level.survivorSecondary); + self switchToWeapon(level.survivorWeapons[level.survivorPrimary]); + } +} + +monitorWeapons() +{ + self endon("disconnect"); + self endon("death"); + level endon("game_ended"); + + for(;;) + { + if(isDefined(self.infected)) + { + if(level.infectedCount == 1) + { + if(self getCurrentWeapon() != (level.survivorWeapons[level.survivorPrimary]) && self getCurrentWeapon() != level.survivorSecondary && self getCurrentWeapon() != "none") + self thread giveWeapons("Survivor"); + } + else + { + if(self getCurrentWeapon() != level.infectedPrimary && self getCurrentWeapon() != level.infectedSecondary && self getCurrentWeapon() != level.infectedTactical && self getCurrentWeapon() != "none") + self thread giveWeapons("Infected"); + } + } + else + { + if(self getCurrentWeapon() != (level.survivorWeapons[level.survivorPrimary]) && self getCurrentWeapon() != level.survivorSecondary && self getCurrentWeapon() != "none") + self thread giveWeapons("Survivor"); + } + wait 0.05; + } +} + +waitForDeath() +{ + self endon("disconnect"); + self endon("first_infected"); + + for(;;) + { + self waittill("death"); + + self.infected = true; + level.totalAlive -=1; + level.infectedCount += 1; + level notify("update_text"); + self maps\mp\teams\_teams::changeteam("allies"); + self thread saveName(self.name); + break; + } +} + +givePerks() +{ + self ClearPerks(); + self setperk("specialty_additionalprimaryweapon"); + self setperk("specialty_fallheight"); + self setperk("specialty_fastequipmentuse"); + self setperk("specialty_fastladderclimb"); + self setperk("specialty_fastmantle"); + self setperk("specialty_fastmeleerecovery"); + self setperk("specialty_fasttoss"); + self setperk("specialty_fastweaponswitch"); + self setperk("specialty_longersprint"); + self setperk("specialty_sprintrecovery"); + self setperk("specialty_twogrenades"); + self setperk("specialty_twoprimaries"); + self setperk("specialty_unlimitedsprint"); +} + +EndInfected() +{ + level endon("game_ended"); + for(;;) + { + wait 0.05; + if(level.totalAlive == 0 && isDefined(level.gameStarted)) + thread endgame( "allies", "^7The Infected Win!" ); + } +} + +onScreenText() +{ + self.onScreenText = self createFontString("objective", 1.75); + self.onScreenText setPoint("CENTER", "CENTER", -355, 150); + self.onScreenText setText( "Survivors Left: ^5"+level.totalAlive); +} + +updateText() +{ + for(;;) + { + level waittill("update_text"); + foreach(player in level.players) + { + if(level.totalAlive == 1 || level.totalAlive == 0) + player.onScreenText setText( "Survivors Left: ^1"+level.totalAlive); + else + player.onScreenText setText( "Survivors Left: ^5"+level.totalAlive); + } + } +} + +spawnBot(value) +{ + for(i = 0; i < value; i++) + { + self thread maps\mp\bots\_bot::spawn_bot( "axis" ); + } +} \ No newline at end of file diff --git a/Multiplayer Mods/Vote Kick System/README.md b/Multiplayer Mods/Vote Kick System/README.md new file mode 100644 index 0000000..36abec4 --- /dev/null +++ b/Multiplayer Mods/Vote Kick System/README.md @@ -0,0 +1,6 @@ +# VOTEKICK SYSTEM + +## DIRECTIONS +- Compile _**_clientids.gsc**_ as _**_clientids.gsc**_ and place it in the directory _**maps/mp/gametypes/_clientids.gsc**_ + +**DOES NOT INCLUDE OVERFLOW FIX** \ No newline at end of file diff --git a/Multiplayer Mods/Vote Kick System/_clientids.gsc b/Multiplayer Mods/Vote Kick System/_clientids.gsc new file mode 100644 index 0000000..8370545 --- /dev/null +++ b/Multiplayer Mods/Vote Kick System/_clientids.gsc @@ -0,0 +1,322 @@ +/*///////////////////////////////// +// SIMPLE VOTE KICK SYSTEM BO2 // +// DEVELOPED BY @ITSCAHZ // +//////////////////////////////// + +THANKS @THEHIDDENHOUR FOR THE HELP AND ANSWERING QUESTIONS WHEN I HAD THEM + + VERSION 1.1 ADDED A DVAR FOR BANNING TO PREVENT SOMEONE FROM REJOINING AFTER BEING VOTEKICKED + ADDED VOTE KICK LIMIT: ONE VOTE KICK PER PERSON, PER MAP*/ + +#include maps\mp\_utility; +#include common_scripts\utility; +#include maps\mp\gametypes\_hud_util; +#include maps\mp\gametypes\_hud_message; + +init() +{ + level thread onPlayerConnect(); +} + +onPlayerConnect() +{ + for(;;) + { + level waittill("connected", player); + player thread activateVoteKickSystem(); + } +} + +activateVoteKickSystem() +{ + if(getPlayerDvar(self, "banned") == "") + {} + else if(getPlayerDvar(self, "banned") == true) + { + kick(self getEntityNumber(),"EXE_PLAYERKICKED"); + } + self endon("disconnect"); + level endon("game_ended"); + for(;;) + { + if(self adsbuttonpressed() && self actionslottwobuttonpressed() && !isDefined(level.voting) && !isDefined(self.checkingToVote)) + { + self thread votekickText(); + self thread func_whotokick(); + } + wait 0.05; + } +} + +func_whotokick() +{ + self endon("disconnect"); + self endon("close_voting"); + level endon("game_ended"); + + self.checkingToVote = true; + level thread recountPlayers(); + + i = 0; + player = level.players[i]; + + self.VoteKickTopString setText("Vote Kick Who?"); + self.VoteKickBottomString setText("[{+actionslot 3}] << ^1"+player.name+"^7 >> [{+actionslot 4}]"); + self.VoteKickInfoString setText("^5Press [{+gostand}] to Select, [{+melee}] to Close"); + + for(;;) + { + if(self actionslotfourbuttonpressed()) + { + if(i != (level.players.size - 1)) + { + i++; + player = level.players[i]; + self.VoteKickBottomString setText("[{+actionslot 3}] << ^1"+player.name+"^7 >> [{+actionslot 4}]"); + } + else + { + i = 0; + player = level.players[i]; + self.VoteKickBottomString setText("[{+actionslot 3}] << ^1"+player.name+"^7 >> [{+actionslot 4}]"); + } + } + if(self actionslotthreebuttonpressed()) + { + if(i == 0) + { + i = (level.players.size - 1); + player = level.players[i]; + self.VoteKickBottomString setText("[{+actionslot 3}] << ^1"+player.name+"^7 >> [{+actionslot 4}]"); + } + else + { + i--; + player = level.players[i]; + self.VoteKickBottomString setText("[{+actionslot 3}] << ^1"+player.name+"^7 >> [{+actionslot 4}]"); + } + } + if(self meleebuttonpressed()) + { + self.checkingToVote = undefined; + self.VoteKickTopString destroy(); + self.VoteKickBottomString destroy(); + self.VoteKickInfoString destroy(); + self notify("close_voting"); + } + if(self jumpbuttonpressed()) + self thread CheckIfCanVoteKick(player); + wait 0.05; + } +} + +CheckIfCanVoteKick(badplayer) +{ + if(!isDefined(level.voting)) + { + + if(isDefined(self.VoteKickedAlready)) //only lets a player votekick once per game to prevent abuse + self iprintln("^1You cannot vote kick more than once a game!"); + /* + ----------------------------------------------- + | *USE THIS IF USING A VERFICATION SYSTEM* | + | TO STOP VERIFIED USERS FROM BEING VOTEKICKED | + ----------------------------------------------- + else if(badplayer isVerified()) + { + self iprintln("^1Cannot vote kick verified users!"); + } + */ + else + { + level.voting = true; + self.VoteKickedAlready = true; + foreach(player in level.players) + { + player.VoteKickTopString destroy(); + player.VoteKickBottomString destroy(); + player.VoteKickInfoString destroy(); + } + level thread StartVoteKick(badplayer); + self.checkingToVote = undefined; + self notify("close_voting"); + } + } + else + self iprintln("^1Voting taking place! Please wait until it has finished!"); +} + +StartVoteKick(badplayer) +{ + level endon("voting_ended"); + level endon("game_ended"); + + level thread StartVoteKickTimeLimit(badplayer); + level thread KickIfVotesAreEnough(badplayer); + + level.votesneeded = ceil(level.numberOfPlayers / 2); + level.votestokick = 0; + + foreach(player in level.players) + { + player thread votekickText(); + if(player.name == badplayer.name) + { + player freezeControls(true); + player.VoteKickTopString setText("^1Vote Kicking "+badplayer.name); + player.VoteKickBottomString setText("^1( "+level.votestokick+" / "+level.votesneeded+" ) ^7votes needed!"); + player.VoteKickInfoString setText("The lobby is vote kicking you please wait"); + } + else + { + player thread VotingButtonMonitor(badplayer); + player.VoteKickTopString setText("^1Vote Kicking "+badplayer.name); + player.VoteKickBottomString setText("^1( "+level.votestokick+" / "+level.votesneeded+" ) ^7votes needed!"); + player.VoteKickInfoString setText("^5Prone [{+actionslot 1}] ^1Vote to Kick\n^5Prone [{+actionslot 2}] ^2Vote to Stay"); + } + } +} + +VotingButtonMonitor(badplayer) +{ + self endon("disconnect"); + level endon("voting_ended"); + level endon("game_ended"); + + for(;;) + { + if(self getStance() == "prone" && self actionslotonebuttonpressed() && !isDefined(self.menu.open) && !isDefined(self.voted)) + { + self.voted = true; + level.votestokick += 1; + level notify("update_vote_text"); + self iprintln("^1You voted for ^5"+badplayer.name+" to get kicked!"); + self.VoteKickInfoString destroy(); + } + if(self getStance() == "prone" && self actionslottwobuttonpressed() && !isDefined(self.menu.open) && !isDefined(self.voted)) + { + self.voted = true; + self iprintln("^2You voted for ^5"+badplayer.name+" to stay!"); + self.VoteKickInfoString destroy(); + } + wait 0.05; + } +} + +KickIfVotesAreEnough(badplayer) +{ + level endon("voting_ended"); + level endon("game_ended"); + + for(;;) + { + wait 0.05; + if(level.votestokick >= level.votesneeded) + { + foreach(player in level.players) + { + player iprintln("^5Vote Passed! ^1"+badplayer.name+" got Kicked!"); + player.voted = undefined; + player.checkingToVote = undefined; + } + setPlayerDvar(badplayer, "banned", true); //this dvar is sticky, and will "ban" the player until + //the server is reset + kick(badplayer getentitynumber()); + level.votestokick = undefined; + level.voting = undefined; + level notify("voting_ended"); + } + } +} + +StartVoteKickTimeLimit(badplayer) +{ + level endon("voting_ended"); + level endon("game_ended"); + + level thread updateText(); + level thread removeText(); + level.votesneeded = ceil(level.numberOfPlayers / 2); + level.votestokick = 0; + wait 15; + if(level.votestokick < level.votesneeded) + { + foreach(player in level.players) + { + player.voted = undefined; + player.checkingToVote = undefined; + if(player.name == badplayer.name) + { + player iprintln("^1Not Enough votes to kick you!"); + player freezeControls(false); + } + else + player iprintln("^1Not Enough Votes to Kick ^5"+badplayer.name+"!"); + } + } + level.votestokick = undefined; + level.voting = undefined; + level notify("voting_ended"); +} + +updateText() +{ + level endon("voting_ended"); + + for(;;) + { + level waittill("update_vote_text"); + foreach(player in level.players) + player.VoteKickBottomString setText("^1( "+level.votestokick+" / "+level.votesneeded+" ) ^7votes needed!"); + } +} + +removeText() +{ + for(;;) + { + level waittill("voting_ended"); + foreach(player in level.players) + { + player.VoteKickTopString destroy(); + player.VoteKickBottomString destroy(); + player.VoteKickInfoString destroy(); + } + } +} + +votekickText() +{ + self.VoteKickTopString = self createFontString("objective", 1.2); + self.VoteKickTopString setPoint("CENTER", "CENTER", -345, -100); + self.VoteKickBottomString = self createFontString("objective", 1.2); + self.VoteKickBottomString setPoint("CENTER", "CENTER", -345, -85); + self.VoteKickInfoString = self createFontString("objective", 1); + self.VoteKickInfoString setPoint("CENTER", "CENTER", -345, -70); +} + +recountPlayers() +{ + level.numberOfBots = 0; + level.numberOfPlayers = 0; + foreach(player in level.players) + { + if(isDefined(player.pers["isBot"])&& player.pers["isBot"]) + level.numberOfBots += 1; + else + level.numberOfPlayers += 1; + } +} + +setPlayerDvar(player, dvar, value) +{ + thedvar = player getXUID() + "_" + dvar; + setDvar(thedvar, value); +} + +getPlayerDvar(player, dvar) +{ + thedvar = player getXUID() + "_" + dvar; + + return getDvar(thedvar); +} \ No newline at end of file diff --git a/Zombies Mods/Grenade Cluster/README.md b/Zombies Mods/Grenade Cluster/README.md new file mode 100644 index 0000000..8d75282 --- /dev/null +++ b/Zombies Mods/Grenade Cluster/README.md @@ -0,0 +1,6 @@ +# GRENADE CLUSTER + +## DIRECTIONS +- Compile _**_clientids.gsc**_ as _**_clientids.gsc**_ and place it in the directory _**maps/mp/gametypes_zm/_clientids.gsc**_ + +To add to your own script, copy **watch_for_grenade_throw** and **multiply_grenades**, then thread **watch_for_grenade_throw** inside your onPlayerConnect function \ No newline at end of file diff --git a/Zombies Mods/Grenade Cluster/_clientids.gsc b/Zombies Mods/Grenade Cluster/_clientids.gsc new file mode 100644 index 0000000..0f3bbc0 --- /dev/null +++ b/Zombies Mods/Grenade Cluster/_clientids.gsc @@ -0,0 +1,49 @@ +#include maps/mp/_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_utility; + +init() +{ + level thread onplayerconnected(); +} + +onplayerconnected() +{ + for ( ;; ) + { + level waittill( "connected", player ); + player thread watch_for_grenade_throw(); + } +} + +watch_for_grenade_throw() +{ + self endon ( "disconnect" ); + level endon ( "end_game" ); + for ( ;; ) + { + self waittill ("grenade_fire", grenade, weapname); + if ( weapname == "frag_grenade_zm" ) + { + grenade thread multiply_grenades(); + } + wait 0.1; + } +} + +multiply_grenades() +{ + self endon ( "death" ); + wait 1.25; + self magicgrenadetype( "frag_grenade_zm", self.origin + ( 20, 0, 0 ), ( 50, 0, 400 ), 2.5 ); + wait 0.25; + self magicgrenadetype( "frag_grenade_zm", self.origin + ( -20, 0, 0 ), ( -50, 0, 400 ), 2.5 ); + wait 0.25; + self magicgrenadetype( "frag_grenade_zm", self.origin + ( 0, 20, 0 ), ( 0, 50, 400 ), 2.5 ); + wait 0.25; + self magicgrenadetype( "frag_grenade_zm", self.origin + ( 0, -20, 0 ), ( 0, -50, 400 ), 2.5 ); + wait 0.25; + self magicgrenadetype( "frag_grenade_zm", self.origin, ( 0, 0, 400 ), 2.5 ); +} \ No newline at end of file diff --git a/Zombies Mods/Vote Kick System/README.md b/Zombies Mods/Vote Kick System/README.md new file mode 100644 index 0000000..43474c2 --- /dev/null +++ b/Zombies Mods/Vote Kick System/README.md @@ -0,0 +1,6 @@ +# VOTEKICK SYSTEM + +## DIRECTIONS +- Compile _**_clientids.gsc**_ as _**_clientids.gsc**_ and place it in the directory _**maps/mp/gametypes_zm/_clientids.gsc**_ + +**DOES NOT INCLUDE OVERFLOW FIX** \ No newline at end of file diff --git a/Zombies Mods/Vote Kick System/_clientids.gsc b/Zombies Mods/Vote Kick System/_clientids.gsc new file mode 100644 index 0000000..7926abc --- /dev/null +++ b/Zombies Mods/Vote Kick System/_clientids.gsc @@ -0,0 +1,328 @@ +/*///////////////////////////////// +// SIMPLE VOTE KICK SYSTEM BO2 // +// DEVELOPED BY @ITSCAHZ // +//////////////////////////////// + + VERSION 1.1 ( ZOMBIES ) + +THANKS @THEHIDDENHOUR FOR THE HELP AND ANSWERING QUESTIONS WHEN I HAD THEM + + VERSION 1.1 ADDED A DVAR FOR BANNING TO PREVENT SOMEONE FROM REJOINING AFTER BEING VOTEKICKED + ADDED VOTE KICK LIMIT: ONE VOTE KICK PER PERSON, PER MAP*/ + +#include maps/mp/_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_utility; + +init() +{ + level thread onPlayerConnect(); +} + +onPlayerConnect() +{ + for( ;; ) + { + level waittill( "connected", player ); + player thread activateVoteKick(); + } +} + +activateVoteKick() +{ + if( getPlayerDvar( player, "banned" ) == "" ) + {} + else if( getPlayerDvar( player, "banned" ) == true ) + { + kick( player getEntityNumber(), "EXE_PLAYERKICKED" ); + } + self endon( "disconnect" ); + level endon( "end_game" ); + for(;;) + { + if( self adsbuttonpressed() && self actionslottwobuttonpressed() && !isDefined( level.voting ) && !isDefined( self.checkingToVote ) && level.players.size >= 3 ) + { + self thread votekickText(); + self thread func_whotokick(); + } + wait 0.05; + } +} + +func_whotokick() +{ + self endon( "disconnect" ); + self endon( "close_voting" ); + level endon( "end_game" ); + + self.checkingToVote = true; + level thread recountPlayers(); + + i = 0; + player = level.players[i]; + + self.VoteKickTopString setText( "Vote Kick Who?" ); + self.VoteKickBottomString setText( "[{+actionslot 3}] << ^1"+player.name+"^7 >> [{+actionslot 4}]" ); + self.VoteKickInfoString setText( "^5Press [{+gostand}] to Select, [{+melee}] to Close" ); + + for( ;; ) + { + if( self actionslotfourbuttonpressed() ) + { + if( i != ( level.players.size - 1) ) + { + i++; + player = level.players[i]; + self.VoteKickBottomString setText( "[{+actionslot 3}] << ^1" + player.name + "^7 >> [{+actionslot 4}]" ); + } + else + { + i = 0; + player = level.players[i]; + self.VoteKickBottomString setText( "[{+actionslot 3}] << ^1" + player.name + "^7 >> [{+actionslot 4}]" ); + } + } + if( self actionslotthreebuttonpressed() ) + { + if( i == 0 ) + { + i = (level.players.size - 1); + player = level.players[i]; + self.VoteKickBottomString setText( "[{+actionslot 3}] << ^1" + player.name + "^7 >> [{+actionslot 4}]" ); + } + else + { + i--; + player = level.players[i]; + self.VoteKickBottomString setText( "[{+actionslot 3}] << ^1" + player.name + "^7 >> [{+actionslot 4}]" ); + } + } + if( self meleebuttonpressed() ) + { + self.checkingToVote = undefined; + self.VoteKickTopString destroy(); + self.VoteKickBottomString destroy(); + self.VoteKickInfoString destroy(); + self notify("close_voting"); + } + if( self jumpbuttonpressed() ) + { + self thread CheckIfCanVoteKick( player ); + } + wait 0.05; + } +} + +CheckIfCanVoteKick( badplayer ) +{ + if( !isDefined( level.voting ) ) + { + + if( isDefined( self.VoteKickedAlready ) ) + { + self iprintln( "^1You cannot vote kick more than once a game!" ); + } + else + { + level.voting = true; + self.VoteKickedAlready = true; + foreach( player in level.players ) + { + player.VoteKickTopString destroy(); + player.VoteKickBottomString destroy(); + player.VoteKickInfoString destroy(); + } + level thread StartVoteKick( badplayer ); + self.checkingToVote = undefined; + self notify( "close_voting" ); + } + } + else + { + self iprintln( "^1Voting taking place! Please wait until it has finished!" ); + } +} + +StartVoteKick( badplayer ) +{ + level endon( "voting_ended" ); + level endon( "end_game" ); + + level thread StartVoteKickTimeLimit( badplayer ); + level thread KickIfVotesAreEnough( badplayer ); + + level.votesneeded = ceil( level.numberOfPlayers / 2 ); + level.votestokick = 0; + + foreach( player in level.players ) + { + player thread votekickText(); + if( player.name == badplayer.name ) + { + player freezeControls( true ); + player.VoteKickTopString setText( "^1Vote Kicking " + badplayer.name ); + player.VoteKickBottomString setText( "^1( " + level.votestokick + " / " + level.votesneeded + " ) ^7votes needed!" ); + player.VoteKickInfoString setText( "The lobby is vote kicking you please wait" ); + } + else + { + player thread VotingButtonMonitor( badplayer ); + player.VoteKickTopString setText( "^1Vote Kicking " + badplayer.name ); + player.VoteKickBottomString setText( "^1( " + level.votestokick + " / " + level.votesneeded + " ) ^7votes needed!" ); + player.VoteKickInfoString setText( "^5Prone [{+actionslot 1}] ^1Vote to Kick\n^5Prone [{+actionslot 2}] ^2Vote to Stay" ); + } + } +} + +VotingButtonMonitor( badplayer ) +{ + self endon( "disconnect" ); + level endon( "voting_ended" ); + level endon( "end_game" ); + + for( ;; ) + { + if( self getStance() == "prone" && self actionslotonebuttonpressed() && !isDefined( self.menu.open ) && !isDefined( self.voted ) ) + { + self.voted = true; + level.votestokick += 1; + level notify( "update_vote_text" ); + self iprintln("^1You voted for ^5"+badplayer.name+" to get kicked!" ); + self.VoteKickInfoString destroy(); + } + if( self getStance() == "prone" && self actionslottwobuttonpressed() && !isDefined( self.menu.open ) && !isDefined( self.voted ) ) + { + self.voted = true; + self iprintln( "^2You voted for ^5"+badplayer.name+" to stay!" ); + self.VoteKickInfoString destroy(); + } + wait 0.05; + } +} + +KickIfVotesAreEnough( badplayer ) +{ + level endon( "voting_ended" ); + level endon( "end_game" ); + + for( ;; ) + { + if( level.votestokick >= level.votesneeded ) + { + foreach( player in level.players ) + { + player iprintln( "^5Vote Passed! ^1" + badplayer.name + " got Kicked!" ); + player.voted = undefined; + player.checkingToVote = undefined; + } + setPlayerDvar( badplayer, "banned", true ); //this dvar is sticky, and will "ban" the player until + //the server is reset + kick( badplayer getentitynumber() ); + level.votestokick = undefined; + level.voting = undefined; + level notify( "voting_ended" ); + } + wait 0.05; + } +} + +StartVoteKickTimeLimit( badplayer ) +{ + level endon( "voting_ended" ); + level endon( "end_game" ); + + level thread updateText(); + level thread removeText(); + level.votesneeded = ceil( level.numberOfPlayers / 2 ); + level.votestokick = 0; + wait 15; + if( level.votestokick < level.votesneeded ) + { + foreach( player in level.players ) + { + player.voted = undefined; + player.checkingToVote = undefined; + if( player.name == badplayer.name ) + { + player iprintln( "^1Not Enough votes to kick you!" ); + } + else + { + player iprintln("^1Not Enough Votes to Kick ^5" + badplayer.name + "!"); + } + } + } + level.votestokick = undefined; + level.voting = undefined; + level notify( "voting_ended" ); +} + +updateText() +{ + level endon( "voting_ended" ); + + for( ;; ) + { + level waittill( "update_vote_text" ); + foreach( player in level.players ) + { + player.VoteKickBottomString setText( "^1( " + level.votestokick + " / " + level.votesneeded + " ) ^7votes needed!" ); + } + } +} + +removeText() +{ + for(;;) + { + level waittill( "voting_ended" ); + foreach( player in level.players ) + { + player.VoteKickTopString destroy(); + player.VoteKickBottomString destroy(); + player.VoteKickInfoString destroy(); + } + } +} + +votekickText() +{ + self.VoteKickTopString = self createFontString( "objective", 1.2 ); + self.VoteKickTopString setPoint( "CENTER", "CENTER", -345, -100 ); + self.VoteKickBottomString = self createFontString( "objective", 1.2 ); + self.VoteKickBottomString setPoint( "CENTER", "CENTER", -345, -85 ); + self.VoteKickInfoString = self createFontString( "objective", 1 ); + self.VoteKickInfoString setPoint( "CENTER", "CENTER", -345, -70 ); +} + +recountPlayers() +{ + level.numberOfBots = 0; + level.numberOfPlayers = 0; + foreach( player in level.players ) + { + if( isDefined( player.pers[ "isBot" ] ) && player.pers[ "isBot" ] ) + { + level.numberOfBots += 1; + } + else + { + level.numberOfPlayers += 1; + } + } +} + +setPlayerDvar( player, dvar, value ) +{ + thedvar = player getXUID() + "_" + dvar; + setDvar( thedvar, value ); +} + +getPlayerDvar( player, dvar ) +{ + thedvar = player getXUID() + "_" + dvar; + + return getDvar( thedvar ); +} \ No newline at end of file diff --git a/Zombies Mods/Zombies++ v1.2/Precompiled/maps/mp/gametypes_zm/_clientids.gsc b/Zombies Mods/Zombies++ v1.2/Precompiled/maps/mp/gametypes_zm/_clientids.gsc new file mode 100644 index 0000000000000000000000000000000000000000..656a64266f9cc962390e45e2a031eca0ace77f34 GIT binary patch literal 29212 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 literal 0 HcmV?d00001 diff --git a/Zombies Mods/Zombies++ v1.2/README.md b/Zombies Mods/Zombies++ v1.2/README.md new file mode 100644 index 0000000..c4b5ff1 --- /dev/null +++ b/Zombies Mods/Zombies++ v1.2/README.md @@ -0,0 +1,16 @@ +# ZOMBIES++ +If you want to just run the mod, use the precompiled version of the files to save time. If you want to change anything about Z++, you need to edit the open source code. +## DIRECTIONS +###### PRECOMPILED +- Take the **maps** folder containing the precompiled files and directories and place it in your **t6r/data** folder +- Make sure to replace your _**dedicated_zm.cfg**_ file with the one for Z++ +###### EDITING SOURCE CODE +- Compile _**_clientids.gsc**_ as _**_clientids.gsc**_ and place it in the directory _**maps/mp/gametypes_zm/_clientids.gsc**_ +- Compile _**_zm_powerups.gsc**_ as _**_zm_powerups.gsc**_ and place it in the directory _**map/mp/zombies/_zm_powerups.gsc**_ +- Make sure to replace your _**dedicated_zm.cfg**_ file with the one for Z++ +###### UPDATES V1.2 +- _**_zm_powerups.gsc**_ now holds all functions for custom powerups +- _**_clientids.gsc**_ now holds all other functions for Z++ +- Fixed Zombie Blood +- Fixed Zombie Counter +- Optimized Code for Stability diff --git a/Zombies Mods/Zombies++ v1.2/Source Code/_clientids.gsc b/Zombies Mods/Zombies++ v1.2/Source Code/_clientids.gsc new file mode 100644 index 0000000..5a85be0 --- /dev/null +++ b/Zombies Mods/Zombies++ v1.2/Source Code/_clientids.gsc @@ -0,0 +1,1157 @@ +#include maps/mp/_utility; +#include common_scripts/utility; +#include maps/mp/gametypes_zm/_hud_util; +#include maps/mp/zombies/_zm; +#include maps/mp/zombies/_zm_utility; +#include maps/mp/zombies/_zm_weapons; +#include maps/mp/zombies/_zm_stats; +#include maps/mp/gametypes_zm/_hud_message; +#include maps/mp/zombies/_zm_powerups; +#include maps/mp/zombies/_zm_perks; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_score; + +init() +{ + startInit(); //precaching models + level thread onPlayerConnect(); //on connect + thread initServerDvars(); //initilize server dvars (credit JezuzLizard) + thread startCustomPerkMachines(); //custom perk machines + level.playerDamageStub = level.callbackplayerdamage; //damage callback for phd flopper + level.callbackplayerdamage = ::phd_flopper_dmg_check; //more damage callback stuff. everybody do the flop + //level.using_solo_revive = 0; //disables solo revive, fixing only 3 revives per game. + //level.is_forever_solo_game = 0; //changes afterlives on motd from 3 to 1 + isTown(); //jezuzlizard's fix for tombstone :) +} + +onPlayerConnect() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + for (;;) + { + level waittill( "connected", player ); + + player thread [[level.givecustomcharacters]](); + player thread doPHDdive(); + player thread onPlayerSpawned(); + player thread onPlayerDowned(); + player thread spawnIfRoundOne(); //force spawns if round 1. no more spectating one player on round 1 + } +} + +onPlayerSpawned() +{ + level endon( "end_game" ); + self endon( "disconnect" ); + for(;;) + { + self waittill( "spawned_player" ); + } +} + +startCustomPerkMachines() +{ + if(level.disableAllCustomPerks == 0) + { + if(getDvar("mapname") == "zm_prison") //mob of the dead + { + if(level.enablePHDFlopper == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_deadshot", "p6_zm_al_vending_nuke_on", "PHD Flopper", 3000, (2427.45, 10048.4, 1704.13), "PHD_FLOPPER", (0, 0, 0) ); + if(level.enableStaminUp == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_deadshot", "p6_zm_al_vending_doubletap2_on", "Stamin-Up", 2000, (-339.642, -3915.84, -8447.88), "specialty_longersprint", (0, 270, 0) ); + } + else if(getDvar("mapname") == "zm_highrise") //die rise + { + if(level.enablePHDFlopper == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_whoswho", "zombie_vending_nuke_on_lo", "PHD Flopper", 3000, (1260.3, 2736.36, 3047.49), "PHD_FLOPPER", (0, 0, 0) ); + if(level.enableDeadshot == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_whoswho", "zombie_vending_revive", "Deadshot Daiquiri", 1500, (3690.54, 1932.36, 1420), "specialty_deadshot", (-15, 0, 0) ); + if(level.enableStaminUp == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_revive", "zombie_vending_doubletap2", "Stamin-Up", 2000, (1704, -35, 1120.13), "specialty_longersprint", (0, -30, 0) ); + } + else if(getDvar("mapname") == "zm_buried") //buried + { + if(level.enablePHDFlopper == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_marathon", "zombie_vending_jugg", "PHD Flopper", 3000, (2631.73, 304.165, 240.125), "PHD_FLOPPER", (5, 0, 0) ); + if(level.enableDeadshot == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_marathon", "zombie_vending_revive", "Deadshot Daiquiri", 1500, (1055.18, -1055.55, 201), "specialty_deadshot", (3, 270, 0) ); + } + else if(getDvar("mapname") == "zm_nuked") //nuketown + { + if(level.enablePHDFlopper == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_revive", "zombie_vending_jugg", "PHD Flopper", 3000, (683, 727, -56), "PHD_FLOPPER", (5, 250, 0) ); + if(level.enableDeadshot == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_jugg", "zombie_vending_revive", "Deadshot Daiquiri", 1500, (747, 356, 91), "specialty_deadshot", (0, 330, 0) ); + if(level.enableStaminUp == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_revive", "zombie_vending_doubletap2", "Stamin-Up", 2000, (-638, 268, -54), "specialty_longersprint", (0, 165, 0) ); + if(level.enableMuleKick == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_jugg", "zombie_vending_sleight", "Mule Kick", 3000, (-953, 715, 83), "specialty_additionalprimaryweapon", (0, 75, 0) ); + } + else if(getDvar("mapname") == "zm_transit") //transit + { + if(level.enablePHDFlopper == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_revive", "zombie_vending_jugg", "PHD Flopper", 3000, (-6304, 5430, -55), "PHD_FLOPPER", (0, 90, 0) ); + if(level.enableDeadshot == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_jugg", "zombie_vending_revive", "Deadshot Daiquiri", 1500, (-6088, -7419, 0), "specialty_deadshot", (0, 90, 0) ); + if(level.enableMuleKick == 1) + level thread CustomPerkMachine( "zombie_perk_bottle_jugg", "zombie_vending_sleight", "Mule Kick", 3000, (1149, -215, -304), "specialty_additionalprimaryweapon", (0, 180, 0) ); + } + } +} + +onPlayerDowned() +{ + self endon("disconnect"); + level endon("end_game"); + + for(;;) + { + self waittill( "player_downed" ); + self unsetperk( "specialty_additionalprimaryweapon" ); //removes the mulekick perk functionality + self unsetperk( "specialty_longersprint" ); //removes the staminup perk functionality + self unsetperk( "specialty_deadshot" ); //removes the deadshot perk functionality + self.hasPHD = undefined; //resets the flopper variable + self.hasMuleKick = undefined; //resets the mule kick variable + self.hasStaminUp = undefined; //resets the staminup variable + self.hasDeadshot = undefined; //resets the deadshot variable + self.icon1 Destroy();self.icon1 = undefined; //deletes the perk icons and resets the variable + self.icon2 Destroy();self.icon2 = undefined; //deletes the perk icons and resets the variable + self.icon3 Destroy();self.icon3 = undefined; //deletes the perk icons and resets the variable + self.icon4 Destroy();self.icon4 = undefined; //deletes the perk icons and resets the variable + } +} + +doPHDdive() //credit to extinct. just edited to add self.hasPHD variable +{ + self endon("disconnect"); + level endon("end_game"); + + for(;;) + { + if(isDefined(self.divetoprone) && self.divetoprone) + { + if(self isOnGround() && isDefined(self.hasPHD)) + { + if(level.script == "zm_tomb" || level.script == "zm_buried") + explosionfx = level._effect["divetonuke_groundhit"]; + else + explosionfx = loadfx("explosions/fx_default_explosion"); + self playSound("zmb_phdflop_explo"); + playfx(explosionfx, self.origin); + self damageZombiesInRange(310, self, "kill"); + wait .3; + } + } + wait .05; + } +} + +damageZombiesInRange(range, what, amount) //damage zombies for phd flopper +{ + enemy = getAiArray(level.zombie_team); + foreach(zombie in enemy) + { + if(distance(zombie.origin, what.origin) < range) + { + if(amount == "kill") + zombie doDamage(zombie.health * 2, zombie.origin, self); + else + zombie doDamage(amount, zombie.origin, self); + } + } +} + +phd_flopper_dmg_check( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, timeoffset, boneindex ) //phdflopdmgchecker lmao +{ + if ( smeansofdeath == "MOD_SUICIDE" || smeansofdeath == "MOD_FALLING" || smeansofdeath == "MOD_PROJECTILE" || smeansofdeath == "MOD_PROJECTILE_SPLASH" || smeansofdeath == "MOD_GRENADE" || smeansofdeath == "MOD_GRENADE_SPLASH" || smeansofdeath == "MOD_EXPLOSIVE" ) + { + if(isDefined(self.hasPHD)) //if player has phd flopper, dont damage the player + return; + } + [[ level.playerDamageStub ]]( einflictor, eattacker, idamage, idflags, smeansofdeath, sweapon, vpoint, vdir, shitloc, timeoffset, boneindex ); +} + +CustomPerkMachine( bottle, model, perkname, cost, origin, perk, angles ) //custom perk system. orginal code from ZeiiKeN. edited to work for all maps and custom phd perk +{ + level endon( "end_game" ); + if(!isDefined(level.customPerkNum)) + level.customPerkNum = 1; + else + level.customPerkNum += 1; + collision = spawn("script_model", origin); + collision setModel("collision_geo_cylinder_32x128_standard"); + collision rotateTo(angles, .1); + RPerks = spawn( "script_model", origin ); + RPerks setModel( model ); + RPerks rotateTo(angles, .1); + level thread LowerMessage( "Custom Perks", "Hold ^3F ^7for "+perkname+" [Cost: "+cost+"]" ); + trig = spawn("trigger_radius", origin, 1, 25, 25); + trig SetCursorHint( "HINT_NOICON" ); + trig setLowerMessage( trig, "Custom Perks" ); + for(;;) + { + trig waittill("trigger", player); + if(player useButtonPressed() && player.score >= cost) + { + wait .25; + if(player useButtonPressed()) + { + if(perk != "PHD_FLOPPER" && !player hasPerk(perk) || perk == "PHD_FLOPPER" && !isDefined(player.hasPHD)) + { + player playsound( "zmb_cha_ching" ); //money shot + player.score -= cost; //take points + level.trig hide(); + player thread GivePerk( bottle, perk, perkname ); //give perk + wait 2; + level.trig show(); + } + else + player iprintln("You Already Have "+perkname+"!"); + } + } + } +} + +GivePerk( model, perk, perkname ) +{ + self DisableOffhandWeapons(); + self DisableWeaponCycling(); + weaponA = self getCurrentWeapon(); + weaponB = model; + self GiveWeapon( weaponB ); + self SwitchToWeapon( weaponB ); + self waittill( "weapon_change_complete" ); + self EnableOffhandWeapons(); + self EnableWeaponCycling(); + self TakeWeapon( weaponB ); + self SwitchToWeapon( weaponA ); + self setperk( perk ); + self maps/mp/zombies/_zm_audio::playerexert( "burp" ); + self setblur( 4, 0.1 ); + wait 0.1; + self setblur( 0, 0.1 ); + if(perk == "PHD_FLOPPER") + { + self.hasPHD = true; + self thread drawCustomPerkHUD("specialty_doubletap_zombies", 0, (1, 0.25, 1)); + } + else if(perk == "specialty_additionalprimaryweapon") + { + self.hasMuleKick = true; + self thread drawCustomPerkHUD("specialty_fastreload_zombies", 0, (0, 0.7, 0)); + } + else if(perk == "specialty_longersprint") + { + self.hasStaminUp = true; + self thread drawCustomPerkHUD("specialty_juggernaut_zombies", 0, (1, 1, 0)); + } + else if(perk == "specialty_deadshot") + { + self.hasDeadshot = true; + self thread drawCustomPerkHUD("specialty_quickrevive_zombies", 0, (0.125, 0.125, 0.125)); + } +} + +LowerMessage( ref, text ) +{ + if( !IsDefined( level.zombie_hints ) ) + level.zombie_hints = []; + PrecacheString( text ); + level.zombie_hints[ref] = text; +} + +setLowerMessage( ent, default_ref ) +{ + if( IsDefined( ent.script_hint ) ) + self SetHintString( get_zombie_hint( ent.script_hint ) ); + else + self SetHintString( get_zombie_hint( default_ref ) ); +} + +drawshader( shader, x, y, width, height, color, alpha, sort ) +{ + hud = newclienthudelem( self ); + hud.elemtype = "icon"; + hud.color = color; + hud.alpha = alpha; + hud.sort = sort; + hud.children = []; + hud setparent( level.uiparent ); + hud setshader( shader, width, height ); + hud.x = x; + hud.y = y; + return hud; +} + +drawCustomPerkHUD(perk, x, color, perkname) //perk hud thinking or whatever. probably not the best method but whatever lol +{ + if(!isDefined(self.icon1)) + { + x = -408; + if(getDvar("mapname") == "zm_buried") + self.icon1 = self drawshader( perk, x, 293, 24, 25, color, 100, 0 ); + else + self.icon1 = self drawshader( perk, x, 320, 24, 25, color, 100, 0 ); + } + else if(!isDefined(self.icon2)) + { + x = -378; + if(getDvar("mapname") == "zm_buried") + self.icon2 = self drawshader( perk, x, 293, 24, 25, color, 100, 0 ); + else + self.icon2 = self drawshader( perk, x, 320, 24, 25, color, 100, 0 ); + } + else if(!isDefined(self.icon3)) + { + x = -348; + if(getDvar("mapname") == "zm_buried") + self.icon3 = self drawshader( perk, x, 293, 24, 25, color, 100, 0 ); + else + self.icon3 = self drawshader( perk, x, 320, 24, 25, color, 100, 0 ); + } + else if(!isDefined(self.icon4)) + { + x = -318; + if(getDvar("mapname") == "zm_buried") + self.icon4 = self drawshader( perk, x, 293, 24, 25, color, 100, 0 ); + else + self.icon4 = self drawshader( perk, x, 320, 24, 25, color, 100, 0 ); + } +} + +LowerMessage( ref, text ) +{ + if( !IsDefined( level.zombie_hints ) ) + level.zombie_hints = []; + PrecacheString( text ); + level.zombie_hints[ref] = text; +} + +setLowerMessage( ent, default_ref ) +{ + if( IsDefined( ent.script_hint ) ) + self SetHintString( get_zombie_hint( ent.script_hint ) ); + else + self SetHintString( get_zombie_hint( default_ref ) ); +} + +startInit() +{ + PrecacheModel("collision_geo_cylinder_32x128_standard"); + PrecacheModel("zombie_vending_jugg"); + PrecacheModel("zombie_perk_bottle_marathon"); + PrecacheModel("zombie_perk_bottle_whoswho"); + PrecacheModel("zombie_vending_nuke_on_lo"); + PrecacheModel("p6_zm_al_vending_pap_on"); + PrecacheModel("p6_anim_zm_buildable_pap"); + PrecacheModel("p6_zm_al_vending_pap_on"); + PrecacheModel("p6_zm_al_vending_jugg_on"); + PrecacheModel("p6_zm_al_vending_sleight_on"); + PrecacheModel("p6_zm_al_vending_doubletap2_on"); + PrecacheModel("p6_zm_al_vending_ads_on"); + PrecacheModel("p6_zm_al_vending_nuke_on"); + PrecacheModel("p6_zm_al_vending_three_gun_on"); + PrecacheModel("zombie_vending_revive"); + PrecacheModel("zombie_vending_doubletap2"); + PrecacheModel("zombie_x2_icon"); + PrecacheModel("zombie_bomb"); + PrecacheModel("zombie_ammocan"); + PrecacheModel("zombie_x2_icon"); + PrecacheModel("zombie_skull"); + PrecacheShader("specialty_deadshot_zombies"); + if(isDefined(level.player_out_of_playable_area_monitor)) + level.player_out_of_playable_area_monitor = false; + level.pers_sniper_misses = 9999; //sniper perma perk! never lose it hahahahahahahahaha + thread gscRestart(); //JezuzLizard fix sound stuff + thread setPlayersToSpectator(); //JezuzLizard fix sound stuff +} + +initServerDvars() //credits to JezuzLizard!!! This is a huge help in making this happen +{ + level.player_starting_points = getDvarIntDefault( "playerStartingPoints", 500 ); + //sets the perk limit for all players + level.perk_purchase_limit = getDvarIntDefault( "perkLimit", 4 ); + //sets the maximum number of zombies that can be on the map at once 32 max + level.zombie_ai_limit = getDvarIntDefault( "zombieAiLimit", 24 ); + //sets the number of zombie bodies that can be on the map at once + level.zombie_actor_limit = getDvarIntDefault( "zombieActorLimit", 32 ); + //enables midround hellhounds WARNING: causes permanent round pauses on maps that aren't bus depot, town or farm + level.mixed_rounds_enabled = getDvarIntDefault( "midroundDogs", 0 ); + //disables the end game check WARNING: make sure to include a spectator respawner and auto revive function + level.no_end_game_check = getDvarIntDefault( "noEndGameCheck", 0 ); + //sets the solo laststand pistol + level.default_solo_laststandpistol = getDvar( "soloLaststandWeapon" ); + //the default laststand pistol + level.default_laststandpistol = getDvar( "coopLaststandWeapon" ); + //set the starting weapon + level.start_weapon = getDvar( "startWeaponZm" ); + //sets all zombies to this speed lower values result in walkers higher values sprinters + level.zombie_move_speed = getDvarIntDefault( "zombieMoveSpeed", 1 ); + //locks the zombie movespeed to the above value + level.zombieMoveSpeedLocked = getDvarIntDefault( "zombieMoveSpeedLocked", 0 ); + //sets whether there is a cap to the zombie movespeed active + level.zombieMoveSpeedCap = getDvarIntDefault( "zombieMoveSpeedCap", 0 ); + //sets the value to the zombie movespeed cap + level.zombieMoveSpeedCapValue = getDvarIntDefault( "zombieMoveSpeedCapValue", 1 ); + //sets the round number any value between 1-255 + level.round_number = getDvarIntDefault( "roundNumber", 1 ); + //enables the override for zombies per round + level.overrideZombieTotalPermanently = getDvarIntDefault( "overrideZombieTotalPermanently", 0 ); + //sets the number of zombies per round to the value indicated + level.overrideZombieTotalPermanentlyValue = getDvarIntDefault( "overrideZombieTotalPermanentlyValue", 6 ); + //enables the override for zombie health + level.overrideZombieHealthPermanently = getDvarIntDefault( "overrideZombieHealthPermanently", 0 ); + //sets the health of zombies every round to the value indicated + level.overrideZombieHealthPermanentlyValue = getDvarIntDefault( "overrideZombieHealthPermanentlyValue", 150 ); + //enables the health cap override so zombies health won't grow beyond the value indicated + level.overrideZombieMaxHealth = getDvarIntDefault( "overrideZombieMaxHealth", 0 ); + //sets the maximum health zombie health will increase to + level.overrideZombieMaxHealthValue = getDvarIntDefault( "overrideZombieMaxHealthValue" , 150 ); + + //disables walkers + level.disableWalkers = getDvarIntDefault( "disableWalkers", 0 ); + if ( level.disableWalkers ) + { + level.speed_change_round = undefined; + } + //set afterlives on mob to 1 like a normal coop match and sets the prices of doors on origins to be higher + level.disableSoloMode = getDvarIntDefault( "disableSoloMode", 0 ); + if ( level.disableSoloMode ) + { + level.is_forever_solo_game = undefined; + } + //disables all drops + level.zmPowerupsNoPowerupDrops = getDvarIntDefault( "zmPowerupsNoPowerupDrops", 0 ); + + //Zombie_Vars: + //The reason zombie_vars are first set to a var is because they don't reliably set when set directly to the value of a dvar + //sets the maximum number of drops per round + level.maxPowerupsPerRound = getDvarIntDefault( "maxPowerupsPerRound", 4 ); + level.zombie_vars["zombie_powerup_drop_max_per_round"] = level.maxPowerupsPerRound; + //sets the powerup drop rate lower is better + level.powerupDropRate = getDvarIntDefault( "powerupDropRate", 2000 ); + level.zombie_vars["zombie_powerup_drop_increment"] = level.powerupDropRate; + //makes every zombie drop a powerup + level.zombiesAlwaysDropPowerups = getDvarIntDefault( "zombiesAlwaysDropPowerups", 0 ); + level.zombie_vars[ "zombie_drop_item" ] = level.zombiesAlwaysDropPowerups; + //increase these below vars to increase drop rate + //points to the powerup increment to a powerup drop related to level.zombie_vars["zombie_powerup_drop_increment"] + level.fourPlayerPowerupScore = getDvarIntDefault( "fourPlayerPowerupScore", 50 ); + level.zombie_vars[ "zombie_score_kill_4p_team" ] = level.fourPlayerPowerupScore; + //points to the powerup increment to a powerup drop related to level.zombie_vars["zombie_powerup_drop_increment"] + level.threePlayerPowerupScore = getDvarIntDefault( "threePlayerPowerupScore", 50 ); + level.zombie_vars[ "zombie_score_kill_3p_team" ] = level.threePlayerPowerupScore; + //points to the powerup increment to a powerup drop related to level.zombie_vars["zombie_powerup_drop_increment"] + level.twoPlayerPowerupScore = getDvarIntDefault( "twoPlayerPowerupScore", 50 ); + level.zombie_vars[ "zombie_score_kill_2p_team" ] = level.twoPlayerPowerupScore; + //points to the powerup increment to a powerup drop related to level.zombie_vars["zombie_powerup_drop_increment"] + level.onePlayerPowerupScore = getDvarIntDefault( "onePlayerPowerupScore", 50 ); + level.zombie_vars[ "zombie_score_kill_1p_team" ] = level.onePlayerPowerupScore; + //points for melee kills to the powerup increment to a powerup drop + level.powerupScoreMeleeKill = getDvarIntDefault( "powerupScoreMeleeKill", 80 ); + level.zombie_vars[ "zombie_score_bonus_melee" ] = level.powerupScoreMeleeKill; + //points for headshot kills to the powerup increment to a powerup drop + level.powerupScoreHeadshotKill = getDvarIntDefault( "powerupScoreHeadshotKill", 50 ); + level.zombie_vars[ "zombie_score_bonus_head" ] = level.powerupScoreHeadshotKill; + //points for neck kills to the powerup increment to a powerup drop + level.powerupScoreNeckKill = getDvarIntDefault( "powerupScoreNeckKill", 20 ); + level.zombie_vars[ "zombie_score_bonus_neck" ] = level.powerupScoreNeckKill; + //points for torso kills to the powerup increment to a powerup drop + level.powerupScoreTorsoKill = getDvarIntDefault( "powerupScoreTorsoKill", 10 ); + level.zombie_vars[ "zombie_score_bonus_torso" ] = level.powerupScoreTorsoKill; + //sets the zombie spawnrate; max is 0.08 + level.zombieSpawnRate = getDvarFloatDefault( "zombieSpawnRate", 2 ); + level.zombie_vars[ "zombie_spawn_delay" ] = level.zombieSpawnRate; + //sets the zombie spawnrate multiplier increase + level.zombieSpawnRateMultiplier = getDvarFloatDefault( "zombieSpawnRateMultiplier", 0.95 ); + //locks the spawnrate so it does not change throughout gameplay + level.zombieSpawnRateLocked = getDvarIntDefault( "zombieSpawnRateLocked", 0 ); + //alters the number of zombies per round formula amount of zombies per round is roughly correlated to this value + //ie half as many zombies per player is half as many zombies per round + level.zombiesPerPlayer = getDvarIntDefault( "zombiesPerPlayer", 6 ); + level.zombie_vars["zombie_ai_per_player"] = level.zombiesPerPlayer; + //sets the flat amount of hp the zombies gain per round not used after round 10 + level.zombieHealthIncreaseFlat = getDvarIntDefault( "zombieHealthIncreaseFlat", 100 ); + level.zombie_vars[ "zombie_health_increase" ] = level.zombieHealthIncreaseFlat; + //multiplies zombie health by this value every round after round 10 + level.zombieHealthIncreaseMultiplier = getDvarFloatDefault( "zombieHealthIncreaseMultiplier", 0.1 ); + level.zombie_vars[ "zombie_health_increase_multiplier" ] = level.zombieHealthIncreaseMultiplier; + //base zombie health before any multipliers or additions + level.zombieHealthStart = getDvarIntDefault( "zombieHealthStart", 150 ); + level.zombie_vars[ "zombie_health_start" ] = level.zombieHealthStart; + //time before new runners spawn on early rounds + level.zombieNewRunnerInterval = getDvarIntDefault( "zombieNewRunnerInterval", 10 ); + level.zombie_vars[ "zombie_new_runner_interval" ] = level.zombieNewRunnerInterval; + //determines level.zombie_move_speed on original + level.zombieMoveSpeedMultiplier = getDvarIntDefault( "zombieMoveSpeedMultiplier", 10 ); + level.zombie_vars[ "zombie_move_speed_multiplier" ] = level.zombieMoveSpeedMultiplier; + //determines level.zombie_move_speed on easy + level.zombieMoveSpeedMultiplierEasy = getDvarIntDefault( "zombieMoveSpeedMultiplierEasy", 8 ); + level.zombie_vars[ "zombie_move_speed_multiplier_easy"] = level.zombieMoveSpeedMultiplierEasy; + //affects the number of zombies per round formula + level.zombieMaxAi = getDvarIntDefault( "zombieMaxAi", 24 ); + level.zombie_vars[ "zombie_max_ai" ] = level.zombieMaxAi; + //affects the check for zombies that have fallen thru the map + level.belowWorldCheck = getDvarIntDefault( "belowWorldCheck", -1000 ); + level.zombie_vars[ "below_world_check" ] = level.belowWorldCheck; + //sets whether spectators respawn at the end of the round + level.customSpectatorsRespawn = getDvarIntDefault( "customSpectatorsRespawn", 1 ); + level.zombie_vars[ "spectators_respawn" ] = level.customSpectatorsRespawn; + //sets the time that the game takes during the end game intermission + level.zombieIntermissionTime = getDvarIntDefault( "zombieIntermissionTime", 20 ); + level.zombie_vars["zombie_intermission_time"] = level.zombieIntermissionTime; + //the time between rounds + level.zombieBetweenRoundTime = getDvarIntDefault( "zombieBetweenRoundTime", 15 ); + level.zombie_vars["zombie_between_round_time"] = level.zombieBetweenRoundTime; + //time before the game starts + level.roundStartDelay = getDvarIntDefault( "roundStartDelay", 0 ); + level.zombie_vars[ "game_start_delay" ] = level.roundStartDelay; + //points all players lose when a player bleeds out %10 default + level.bleedoutPointsLostAllPlayers = getDvarFloatDefault( "bleedoutPointsLostAllPlayers", 0.1 ); + level.zombie_vars[ "penalty_no_revive" ] = level.bleedoutPointsLostAllPlayers; + //penalty to the player who died 10% of points by default + level.bleedoutPointsLostSelf = getDvarFloatDefault( "bleedoutPointsLostSelf", 0.1 ); + level.zombie_vars[ "penalty_died" ] = level.bleedoutPointsLostSelf; + //points players lose on down %5 by default + level.downedPointsLostSelf = getDvarFloatDefault( "downedPointsLostSelf", 0.05 ); + level.zombie_vars[ "penalty_downed" ] = level.downedPointsLostSelf; + //unknown + level.playerStartingLives = getDvarIntDefault( "playerStartingLives", 1 ); + level.zombie_vars[ "starting_lives" ] = level.playerStartingLives; + //points earned per zombie kill in a 4 player game + level.fourPlayerScorePerZombieKill = getDvarIntDefault( "fourPlayerScorePerZombieKill", 50 ); + level.zombie_vars[ "zombie_score_kill_4player" ] = level.fourPlayerScorePerZombieKill; + //points earned per zombie kill in a 3 player game + level.threePlayerScorePerZombieKill = getDvarIntDefault( "threePlayerScorePerZombieKill", 50 ); + level.zombie_vars[ "zombie_score_kill_3player" ] = level.threePlayerScorePerZombieKill; + //points earned per zombie kill in a 2 player game + level.twoPlayerScorePerZombieKill = getDvarIntDefault( "twoPlayerScorePerZombieKill", 50 ); + level.zombie_vars[ "zombie_score_kill_2player" ] = level.twoPlayerScorePerZombieKill; + //points earned per zombie kill in a 1 player game + level.onePlayerScorePerZombieKill = getDvarIntDefault( "onePlayerScorePerZombieKill", 50 ); + level.zombie_vars[ "zombie_score_kill_1player" ] = level.onePlayerScorePerZombieKill; + //points given for a normal attack + level.pointsPerNormalAttack = getDvarIntDefault( "pointsPerNormalAttack", 10 ); + level.zombie_vars[ "zombie_score_damage_normal" ] = level.pointsPerNormalAttack; + //points given for a light attack + level.pointsPerLightAttack = getDvarIntDefault( "pointsPerLightAttack", 10 ); + level.zombie_vars[ "zombie_score_damage_light" ] = level.pointsPerLightAttack; + //players turn into a zombie on death WARNING: buggy as can be and is missing assets + level.shouldZombifyPlayer = getDvarIntDefault( "shouldZombifyPlayer", 0 ); + level.zombie_vars[ "zombify_player" ] = level.shouldZombifyPlayer; + //points scalar for allies team + level.alliesPointsMultiplier = getDvarIntDefault( "alliesPointsMultiplier", 1 ); + level.zombie_vars[ "allies" ][ "zombie_point_scalar" ] = level.alliesPointsMultiplier; + //points scalar for axis team + level.axisPointsMultiplier = getDvarIntDefault( "axisPointsMultiplier", 1 ); + level.zombie_vars[ "axis" ][ "zombie_point_scalar" ] = level.axisPointsMultiplier; + //sets the radius of emps explosion lower this to 1 to render emps useless + level.empPerkExplosionRadius = getDvarIntDefault( "empPerkExplosionRadius", 420 ); + level.zombie_vars[ "emp_perk_off_range" ] = level.empPerkExplosionRadius; + //sets the duration of emps on perks set to 0 for infiinite emps + level.empPerkOffDuration = getDvarIntDefault( "empPerkOffDuration", 90 ); + level.zombie_vars[ "emp_perk_off_time" ] = level.empPerkOffDuration; + //riotshield health + level.riotshieldHitPoints = getDvarIntDefault( "riotshieldHitPoints", 2250 ); + level.zombie_vars[ "riotshield_hit_points" ] = level.riotshieldHitPoints; + //jugg health bonus + level.juggHealthBonus = getDvarIntDefault( "juggHealthBonus", 160 ); + level.zombie_vars[ "zombie_perk_juggernaut_health" ] = level.juggHealthBonus; + //perma jugg health bonus + level.permaJuggHealthBonus = getDvarIntDefault( "permaJuggHealthBonus", 190 ); + level.zombie_vars[ "zombie_perk_juggernaut_health_upgrade" ] = level.permaJuggHealthBonus; + //phd min explosion damage + level.minPhdExplosionDamage = getDvarIntDefault( "minPhdExplosionDamage", 1000 ); + level.zombie_vars[ "zombie_perk_divetonuke_min_damage" ] = level.minPhdExplosionDamage; + //phd max explosion damage + level.maxPhdExplosionDamage = getDvarIntDefault( "maxPhdExplosionDamage", 5000 ); + level.zombie_vars[ "zombie_perk_divetonuke_max_damage" ] = level.maxPhdExplosionDamage; + //phd explosion radius + level.phdDamageRadius = getDvarIntDefault( "phdDamageRadius", 300 ); + level.zombie_vars[ "zombie_perk_divetonuke_radius" ] = level.phdDamageRadius; + //zombie counter onscreen + level.enableZombieCounter = getDvarIntDefault( "enableZombieCounter", 1 ); + level.zombie_vars[ "enableZombieCounter" ] = level.enableZombieCounter; + //change mystery box price + level.customMysteryBoxPriceEnabled = getDvarIntDefault( "customMysteryBoxPriceEnabled", 0 ); + level.zombie_vars[ "customMysteryBoxPriceEnabled" ] = level.customMysteryBoxPriceEnabled; + //set mystery box price + level.customMysteryBoxPrice = getDvarIntDefault( "customMysteryBoxPrice", 500 ); + level.zombie_vars[ "customMysteryBoxPrice" ] = level.customMysteryBoxPrice; + //disable custom perks + level.disableAllCustomPerks = getDvarIntDefault( "disableAllCustomPerks", 0 ); + level.zombie_vars[ "disableAllCustomPerks" ] = level.disableAllCustomPerks; + //enable custom phdflopper + level.enablePHDFlopper = getDvarIntDefault( "enablePHDFlopper", 1 ); + level.zombie_vars[ "enablePHDFlopper" ] = level.enablePHDFlopper; + //enable custom staminup + level.enableStaminUp = getDvarIntDefault( "enableStaminUp", 1 ); + level.zombie_vars[ "enableStaminUp" ] = level.enableStaminUp; + //enable custom deadshot + level.enableDeadshot = getDvarIntDefault( "enableDeadshot", 1 ); + level.zombie_vars[ "enableDeadshot" ] = level.enableDeadshot; + //enable custom mule kick + level.enableMuleKick = getDvarIntDefault( "enableMuleKick", 1 ); + level.zombie_vars[ "enableMuleKick" ] = level.enableMuleKick; + disable_specific_powerups(); + checks(); + thread zombies_always_drop_powerups(); + thread zombies_per_round_override(); + thread zombie_health_override(); + thread zombie_health_cap_override(); + thread zombie_spawn_delay_fix(); + thread zombie_speed_fix(); +} + +trackPackAPunchDrops() +{ + level endon("end_game"); + level.rounds_since_last_pack_a_punch = 0; + for(;;) + { + level waittill("start_of_round"); + level.rounds_since_last_pack_a_punch_drop += 1; + wait 0.5; + } +} + +gscRestart() +{ + level waittill( "end_game" ); + wait 15; + map_restart( false ); +} + +setPlayersToSpectator() +{ + level.no_end_game_check = 1; + wait 3; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( i == 0 ) + { + i++; + } + players[ i ] setToSpectator(); + i++; + } + wait 5; + spawnAllPlayers(); +} + +setToSpectator() +{ + self.sessionstate = "spectator"; + if (isDefined(self.is_playing)) + { + self.is_playing = false; + } +} + +spawnAllPlayers() +{ + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( players[ i ].sessionstate == "spectator" && isDefined( players[ i ].spectator_respawn ) ) + { + players[ i ] [[ level.spawnplayer ]](); + if ( level.script != "zm_tomb" || level.script != "zm_prison" || !is_classic() ) + { + thread maps\mp\zombies\_zm::refresh_player_navcard_hud(); + } + } + i++; + } + level.no_end_game_check = 0; +} + +disable_all_powerups() +{ + if ( level.zmPowerupsNoPowerupDrops ) + { + flag_clear( "zombie_drop_powerups" ); + } +} + +zombies_always_drop_powerups() +{ + if ( !level.zombiesAlwaysDropPowerups ) + { + return; + } + while ( 1 ) + { + level.zombie_vars[ "zombie_drop_item" ] = level.zombiesAlwaysDropPowerups; + wait 0.05; + } +} + +zombies_per_round_override() +{ + if ( !level.overrideZombieTotalPermanently ) + { + return; + } + while ( 1 ) + { + level waittill( "start_of_round" ); + level.zombie_total = getDvarIntDefault( "overrideZombieTotalPermanentlyValue", 6 ); + } +} + +zombie_health_override() +{ + if ( !level.overrideZombieHealthPermanently ) + { + return; + } + while ( 1 ) + { + level waittill( "start_of_round" ); + level.zombie_health = getDvarIntDefault( "overrideZombieHealthPermanentlyValue", 150 ); + } +} + +zombie_health_cap_override() +{ + if ( !level.overrideZombieMaxHealth ) + { + return; + } + while ( 1 ) + { + level waittill( "start_of_round" ); + if ( level.zombie_health > level.overrideZombieMaxHealthValue ) + { + level.zombie_health = getDvarIntDefault( "overrideZombieHealthMaxHealthValue", 150 ); + } + } +} + +zombie_spawn_delay_fix() +{ + if ( level.zombieSpawnRateLocked ) + { + return; + } + i = 1; + while ( i <= level.round_number ) + { + timer = level.zombieSpawnRate; + if ( timer > 0.08 ) + { + level.zombieSpawnRate = timer * level.zombieSpawnRateMultiplier; + i++; + continue; + } + else if ( timer < 0.08 ) + { + level.zombieSpawnRate = 0.08; + break; + } + i++; + } + while ( 1 ) + { + level waittill( "start_of_round" ); + if ( level.zombieSpawnRate > 0.08 ) + { + level.zombieSpawnRate = level.zombieSpawnRate * level.zombieSpawnRateMultiplier; + } + level.zombie_vars[ "zombie_spawn_delay" ] = level.zombieSpawnRate; + } +} + +zombie_speed_fix() +{ + if ( level.zombieMoveSpeedLocked ) + { + return; + } + 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" ]; + } +} + +zombie_speed_override() +{ + if ( !level.zombieMoveSpeedLocked ) + { + return; + } + while ( 1 ) + { + level waittill( "start_of_round" ); + level.zombie_move_speed = getDvarIntDefault( "zombieMoveSpeed", 1 ); + } +} + +zombie_speed_cap_override() +{ + if ( !level.zombieMoveSpeedCap ) + { + return; + } + while ( 1 ) + { + level waittill( "start_of_round" ); + if ( level.zombie_move_speed > level.zombieMoveSpeedCapValue ) + { + level.zombie_move_speed = level.zombieMoveSpeedCapValue; + } + } +} + +checks() +{ + if( level.customMysteryBoxPriceEnabled == 1) //custom mystery box price + { + level thread setMysteryBoxPrice(); + } + if( level.enableZombieCounter == 1 ) //draw zombie counter + { + level thread drawZombiesCounter(); //credit carbonmodding + } + if ( level.mixed_rounds_enabled ) + { + if ( level.script != "zm_transit" || is_classic() || level.scr_zm_ui_gametype == "zgrief" ) + { + level.mixed_rounds_enabled = 0; + } + } + + if ( level.start_weapon == "" || level.start_weapon== "m1911_zm" ) + { + level.start_weapon = "m1911_zm"; + if ( level.script == "zm_tomb" ) + { + level.start_weapon = "c96_zm"; + } + } + if ( level.default_laststandpistol == "" || level.default_laststandpistol == "m1911_zm" ) + { + level.default_laststandpistol = "m1911_zm"; + if ( level.script == "zm_tomb" ) + { + level.default_laststandpistol = "c96_zm"; + } + } + if ( level.default_solo_laststandpistol == "" || level.default_solo_laststandpistol == "m1911_upgraded_zm" ) + { + level.default_solo_laststandpistol = "m1911_upgraded_zm"; + if ( level.script == "zm_tomb" ) + { + level.default_solo_laststandpistol = "c96_upgraded_zm"; + } + } + +} + +disable_specific_powerups() +{ + level.powerupNames = array( "fast_feet", "unlimited_ammo", "pack_a_punch", "money_drop", "nuke", "insta_kill", "full_ammo", "double_points", "fire_sale", "free_perk", "carpenter" ); + array = level.powerupNames; + //custom powerups and regular powerups + level.zmPowerupsEnabled = []; + //fast feet custom drop + level.zmPowerupsEnabled[ "fast_feet" ] = spawnstruct(); + level.zmPowerupsEnabled[ "fast_feet" ].name = "fast_feet"; + level.zmPowerupsEnabled[ "fast_feet" ].active = getDvarIntDefault( "zmPowerupsFastFeetEnabled", 1 ); + //custom unlimited ammo drop + level.zmPowerupsEnabled[ "unlimited_ammo" ] = spawnstruct(); + level.zmPowerupsEnabled[ "unlimited_ammo" ].name = "unlimited_ammo"; + level.zmPowerupsEnabled[ "unlimited_ammo" ].active = getDvarIntDefault( "zmPowerupsUnlimitedAmmoEnabled", 1 ); + //custom pack a punch drop + level.zmPowerupsEnabled[ "pack_a_punch" ] = spawnstruct(); + level.zmPowerupsEnabled[ "pack_a_punch" ].name = "pack_a_punch"; + level.zmPowerupsEnabled[ "pack_a_punch" ].active = getDvarIntDefault( "zmPowerupsPackAPunchEnabled", 1 ); + //custom money drop + level.zmPowerupsEnabled[ "money_drop" ] = spawnstruct(); + level.zmPowerupsEnabled[ "money_drop" ].name = "money_drop"; + level.zmPowerupsEnabled[ "money_drop" ].active = getDvarIntDefault( "zmPowerupsMoneyDropEnabled", 1 ); + //nuke + level.zmPowerupsEnabled[ "nuke" ] = spawnstruct(); + level.zmPowerupsEnabled[ "nuke" ].name = "nuke"; + level.zmPowerupsEnabled[ "nuke" ].active = getDvarIntDefault( "zmPowerupsNukeEnabled", 1 ); + //remove insta kills from the drop cycle and special drops + level.zmPowerupsEnabled[ "insta_kill" ] = spawnstruct(); + level.zmPowerupsEnabled[ "insta_kill" ].name = "insta_kill"; + level.zmPowerupsEnabled[ "insta_kill" ].active = getDvarIntDefault( "zmPowerupsInstaKillEnabled", 1 ); + //remove max ammos from the drop cycle and special drops + level.zmPowerupsEnabled[ "full_ammo" ] = spawnstruct(); + level.zmPowerupsEnabled[ "full_ammo" ].name = "full_ammo"; + level.zmPowerupsEnabled[ "full_ammo" ].active = getDvarIntDefault( "zmPowerupsMaxAmmoEnabled", 1 ); + //remove carpenter from the drop cycle and special drops + level.zmPowerupsEnabled[ "double_points" ] = spawnstruct(); + level.zmPowerupsEnabled[ "double_points" ].name = "double_points"; + level.zmPowerupsEnabled[ "double_points" ].active = getDvarIntDefault( "zmPowerupsDoublePointsEnabled", 1 ); + //remove fire sale from the drop cycle and special drops NOTE: fire sale isn't on all maps already this being enabled won't make it spawn + level.zmPowerupsEnabled[ "fire_sale" ] = spawnstruct(); + level.zmPowerupsEnabled[ "fire_sale" ].name = "fire_sale"; + level.zmPowerupsEnabled[ "fire_sale" ].active = getDvarIntDefault( "zmPowerupsFireSaleEnabled", 1 ); + //remove the perk bottle from the drop cycle and special drops + level.zmPowerupsEnabled[ "free_perk" ] = spawnstruct(); + level.zmPowerupsEnabled[ "free_perk" ].name = "free_perk"; + level.zmPowerupsEnabled[ "free_perk" ].active = getDvarIntDefault( "zmPowerupsPerkBottleEnabled", 1 ); + //removes carpenter from the drop cycle and special drops + level.zmPowerupsEnabled[ "carpenter" ] = spawnstruct(); + level.zmPowerupsEnabled[ "carpenter" ].name = "carpenter"; + level.zmPowerupsEnabled[ "carpenter" ].active = getDvarIntDefault( "zmPowerupsCarpenterEnabled", 1 ); + //removes zombie blood from the drop cycle and special drops + level.zmPowerupsEnabled[ "zombie_blood" ] = spawnstruct(); + level.zmPowerupsEnabled[ "zombie_blood" ].name = "zombie_blood"; + level.zmPowerupsEnabled[ "zombie_blood" ].active = getDvarIntDefault( "zmPowerupsZombieBloodEnabled", 1 ); + + //you can expand this list with custom powerups if you'd like just add a new spawnstruct() and add to the array at the top + + for ( i = 0; i < array.size; i++ ) + { + if ( !level.zmPowerupsEnabled[ array[ i ] ].active ) + { + name = level.zmPowerupsEnabled[ array[ i ] ].name; + if ( isInArray( level.zombie_include_powerups, name ) ) + { + arrayremovevalue( level.zombie_include_powerups, name ); + } + if ( isInArray( level.zombie_powerups, name ) ) + { + arrayremovevalue( level.zombie_powerups, name ); + } + if ( isInArray( level.zombie_powerup_array, name ) ) + { + arrayremovevalue( level.zombie_powerup_array, name ); + } + } + } +} + +drawZombiesCounter() +{ + level.zombiesCounter = createServerFontString("hudsmall" , 1.9); + level.zombiesCounter setPoint("CENTER", "CENTER", "CENTER", 190); + while(true) + { + enemies = get_round_enemy_array().size + level.zombie_total; + if( enemies != 0 ) + level.zombiesCounter.label = &"Zombies: ^1"; + else + level.zombiesCounter.label = &"Zombies: ^6"; + level.zombiesCounter setValue( enemies ); + wait 0.05; + } +} + +setMysteryBoxPrice() //mystery box price +{ + i = 0; + while (i < level.chests.size) + { + level.chests[ i ].zombie_cost = level.customMysteryBoxPrice; + level.chests[ i ].old_cost = level.customMysteryBoxPrice; + i++; + } +} + +spawnIfRoundOne() //spawn player +{ + wait 3; + if ( self.sessionstate == "spectator" && level.round_number == 1 ) + self iprintln("Get ready to be spawned!"); + wait 5; + if ( self.sessionstate == "spectator" && level.round_number == 1 ) + { + self [[ level.spawnplayer ]](); + if ( level.script != "zm_tomb" || level.script != "zm_prison" || !is_classic() ) + thread maps\mp\zombies\_zm::refresh_player_navcard_hud(); + } +} + +solo_tombstone_removal() +{ + notify( "tombstone_on" ); +} + +turn_tombstone_on() +{ + 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 ); + } + } +} + +perk_machine_spawn_init() +{ + match_string = ""; + location = level.scr_zm_map_start_location; + if ( location != "default" && location == "" && isDefined( level.default_start_location ) ) + { + location = level.default_start_location; + } + match_string = ( level.scr_zm_ui_gametype + "_perks_" ) + location; + pos = []; + if ( isDefined( level.override_perk_targetname ) ) + { + structs = getstructarray( level.override_perk_targetname, "targetname" ); + } + else + { + structs = getstructarray( "zm_perk_machine", "targetname" ); + } + _a3578 = structs; + _k3578 = getFirstArrayKey( _a3578 ); + while ( isDefined( _k3578 ) ) + { + struct = _a3578[ _k3578 ]; + if ( isDefined( struct.script_string ) ) + { + tokens = strtok( struct.script_string, " " ); + _a3583 = tokens; + _k3583 = getFirstArrayKey( _a3583 ); + while ( isDefined( _k3583 ) ) + { + token = _a3583[ _k3583 ]; + if ( token == match_string ) + { + pos[ pos.size ] = struct; + } + _k3583 = getNextArrayKey( _a3583, _k3583 ); + } + } + else pos[ pos.size ] = struct; + _k3578 = getNextArrayKey( _a3578, _k3578 ); + } + if ( !isDefined( pos ) || pos.size == 0 ) + { + return; + } + precachemodel( "zm_collision_perks1" ); + i = 0; + while ( i < pos.size ) + { + perk = pos[ i ].script_noteworthy; + if ( isDefined( perk ) && isDefined( pos[ i ].model ) ) + { + use_trigger = spawn( "trigger_radius_use", pos[ i ].origin + vectorScale( ( 0, -1, 0 ), 30 ), 0, 40, 70 ); + use_trigger.targetname = "zombie_vending"; + use_trigger.script_noteworthy = perk; + use_trigger triggerignoreteam(); + perk_machine = spawn( "script_model", pos[ i ].origin ); + perk_machine.angles = pos[ i ].angles; + perk_machine setmodel( pos[ i ].model ); + if ( isDefined( level._no_vending_machine_bump_trigs ) && level._no_vending_machine_bump_trigs ) + { + bump_trigger = undefined; + } + else + { + bump_trigger = spawn( "trigger_radius", pos[ i ].origin, 0, 35, 64 ); + bump_trigger.script_activated = 1; + bump_trigger.script_sound = "zmb_perks_bump_bottle"; + bump_trigger.targetname = "audio_bump_trigger"; + if ( perk != "specialty_weapupgrade" ) + { + bump_trigger thread thread_bump_trigger(); + } + } + collision = spawn( "script_model", pos[ i ].origin, 1 ); + collision.angles = pos[ i ].angles; + collision setmodel( "zm_collision_perks1" ); + collision.script_noteworthy = "clip"; + collision disconnectpaths(); + use_trigger.clip = collision; + use_trigger.machine = perk_machine; + use_trigger.bump = bump_trigger; + if ( isDefined( pos[ i ].blocker_model ) ) + { + use_trigger.blocker_model = pos[ i ].blocker_model; + } + if ( isDefined( pos[ i ].script_int ) ) + { + perk_machine.script_int = pos[ i ].script_int; + } + if ( isDefined( pos[ i ].turn_on_notify ) ) + { + perk_machine.turn_on_notify = pos[ i ].turn_on_notify; + } + if ( perk == "specialty_scavenger" || perk == "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"; + } + } + if ( isDefined( level._custom_perks[ perk ] ) && isDefined( level._custom_perks[ perk ].perk_machine_set_kvps ) ) + { + [[ level._custom_perks[ perk ].perk_machine_set_kvps ]]( use_trigger, perk_machine, bump_trigger, collision ); + } + } + i++; + } +} + +isTown() +{ + if (isDefined(level.zombiemode_using_tombstone_perk) && level.zombiemode_using_tombstone_perk) + { + level thread perk_machine_spawn_init(); + thread solo_tombstone_removal(); + thread turn_tombstone_on(); + } +} diff --git a/Zombies Mods/Zombies++ v1.2/Source Code/_zm_powerups.gsc b/Zombies Mods/Zombies++ v1.2/Source Code/_zm_powerups.gsc new file mode 100644 index 0000000..efcfc21 --- /dev/null +++ b/Zombies Mods/Zombies++ v1.2/Source Code/_zm_powerups.gsc @@ -0,0 +1,3124 @@ +#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; +#include maps/mp/zombies/_zm; +#include maps/mp/gametypes_zm/_hud_message; +#include maps/mp/zombies/_zm_audio; +#include maps/mp/zombies/_zm_score; + +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 ); + if ( level.debugLogging_zm_powerups ) + { + level.maxPowerupsPerRound = getDvarIntDefault( "maxPowerupsPerRound", 4 ); + level.zombie_vars["zombie_powerup_drop_max_per_round"] = level.maxPowerupsPerRound; + } + onplayerconnect_callback( ::init_player_zombie_vars ); + level._effect[ "powerup_on" ] = loadfx( "misc/fx_zombie_powerup_on" ); + level._effect[ "powerup_off" ] = loadfx( "misc/fx_zombie_powerup_off" ); + 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(); + init_custom_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; + level thread track_pack_a_punch_drops(); + level thread onplayerconnecting_powerups(); +} + +onplayerconnecting_powerups() +{ + for(;;) + { + level waittill( "connecting", player ); + player thread startCustomPowerups(); + } +} + +custom_powerup_grab(powerup, player) //credit to _Ox much thx for powerup functions +{ + if(powerup.powerup_name == "money_drop") + player thread doRandomScore(); + else if(powerup.powerup_name == "pack_a_punch") + player thread doPackAPunchWeapon(); + else if(powerup.powerup_name == "unlimited_ammo") + player thread doUnlimitedAmmo(); + else if(powerup.powerup_name == "fast_feet") + player thread doFastFeet(); + else if (isDefined(level.original_zombiemode_powerup_grab)) + level thread [[level.original_zombiemode_powerup_grab]](powerup, player); +} + +startCustomPowerups() +{ + if(!isDefined(level.custompowerupinit)) + { + level.custompowerupinit = true; + wait 2; + if(isDefined(level._zombiemode_powerup_grab)) + level.original_zombiemode_powerup_grab = level._zombiemode_powerup_grab; + wait 2; + level._zombiemode_powerup_grab = ::custom_powerup_grab; + } +} + +init_custom_powerups() //credit goes to _Ox for most code +{ + level.unlimited_ammo_duration = 20; + include_zombie_powerup("unlimited_ammo"); + add_zombie_powerup("unlimited_ammo", "T6_WPN_AR_GALIL_WORLD", &"ZOMBIE_POWERUP_UNLIMITED_AMMO", ::func_should_always_drop, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("unlimited_ammo", 1); + if(getDvar("mapname") == "zm_prison") + { + + include_zombie_powerup("fast_feet"); + add_zombie_powerup("fast_feet", "bottle_whisky_01", &"ZOMBIE_POWERUP_FAST_FEET", ::func_should_always_drop, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("fast_feet", 1); + + include_zombie_powerup("pack_a_punch"); + add_zombie_powerup("pack_a_punch", "p6_zm_al_vending_pap_on", &"ZOMBIE_POWERUP_PACK_A_PUNCH", ::func_should_drop_pack_a_punch, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("pack_a_punch", 0); + + include_zombie_powerup("money_drop"); + add_zombie_powerup("money_drop", "p6_anim_zm_al_magic_box_lock_red", &"ZOMBIE_POWERUP_MONEY_DROP", ::func_should_always_drop, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("money_drop", 1); + } + else if ( level.script == "zm_nuked" ) + { + include_zombie_powerup("fast_feet"); + add_zombie_powerup("fast_feet", "t6_wpn_zmb_perk_bottle_doubletap_world", &"ZOMBIE_POWERUP_FAST_FEET", ::func_should_always_drop, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("fast_feet", 1); + + include_zombie_powerup("pack_a_punch"); + add_zombie_powerup("pack_a_punch", "p6_anim_zm_buildable_pap", &"ZOMBIE_POWERUP_PACK_A_PUNCH", ::func_should_drop_pack_a_punch, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("pack_a_punch", 0); + + include_zombie_powerup("money_drop"); + add_zombie_powerup("money_drop", "zombie_teddybear", &"ZOMBIE_POWERUP_MONEY_DROP", ::func_should_always_drop, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("money_drop", 1); + } + else + { + include_zombie_powerup("fast_feet"); + add_zombie_powerup("fast_feet", "zombie_pickup_perk_bottle", &"ZOMBIE_POWERUP_FAST_FEET", ::func_should_always_drop, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("fast_feet", 1); + + include_zombie_powerup("pack_a_punch"); + add_zombie_powerup("pack_a_punch", "p6_anim_zm_buildable_pap", &"ZOMBIE_POWERUP_PACK_A_PUNCH", ::func_should_drop_pack_a_punch, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("pack_a_punch", 0); + + include_zombie_powerup("money_drop"); + add_zombie_powerup("money_drop", "zombie_teddybear", &"ZOMBIE_POWERUP_MONEY_DROP", ::func_should_always_drop, 0, 0, 0); + powerup_set_can_pick_up_in_last_stand("money_drop", 1); + } +} + +init_powerups() +{ + flag_init( "zombie_drop_powerups" ); + level.unlimited_ammo_duration = 20; + 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() //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + 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() //checked partially changed to match cerberus output +{ + 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 ); + for ( powerup_key_index = 0; powerup_key_index < powerup_keys.size; powerup_key_index++ ) + { + if ( isDefined( level.zombie_powerups[ powerup_keys[ powerup_key_index ] ].client_field_name ) ) + { + 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; + } + } + client_field_keys = getarraykeys( client_fields ); + + while ( 1 ) + { + wait 0.05; + waittillframeend; + players = get_players(); + + for ( playerindex = 0; playerindex < players.size; playerindex++ ) + { + 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 = client_fields[ client_field_keys[ client_field_key_index ] ].client_field_name; + time_name = client_fields[ client_field_keys[ client_field_key_index ] ].time_name; + on_name = client_fields[ client_field_keys[ client_field_key_index ] ].on_name; + powerup_timer = undefined; + powerup_on = undefined; + if ( client_fields[ client_field_keys[ client_field_key_index ] ].solo ) + { + if ( 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 ); + } + else + { + player setclientfieldtoplayer( client_field_name, 0 ); + } + client_field_key_index++; + } + } + + } +} + +set_clientfield_powerups( clientfield_name, powerup_timer, powerup_on, flashing_timers, flashing_values ) //checked changed to match cerberus output +{ + if ( powerup_on ) + { + if ( powerup_timer < 10 ) + { + flashing_value = 3; + for ( i = flashing_timers.size - 1; i > 0; i-- ) + { + if ( powerup_timer < flashing_timers[ i ] ) + { + flashing_value = flashing_values[ i ]; + break; + } + } + self setclientfieldtoplayer( clientfield_name, flashing_value ); + } + else + { + self setclientfieldtoplayer( clientfield_name, 1 ); + } + } + else + { + self setclientfieldtoplayer( clientfield_name, 0 ); + } +} + +randomize_powerups() //checked matches cerberus output +{ + level.zombie_powerup_array = array_randomize( level.zombie_powerup_array ); +} + +get_next_powerup() //checked matches cerberus output +{ + 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() //checked partially matches cerberus output did not change +{ + 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() //checked matches cerberus output +{ + 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() //checked partially matches cerberus output did not change +{ + num = 0; + for ( i = 0; i < level.exterior_goals.size; i++ ) + { + if ( all_chunks_destroyed( level.exterior_goals[ i ], level.exterior_goals[ i ].barrier_chunks ) ) + { + num += 1; + } + } + return num; +} + +watch_for_drop() //checked partially matches cerberus output did not change +{ + 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; + for ( i = 0; i < players.size; i++ ) + { + if ( isDefined( players[ i ].score_total ) ) + { + curr_total_score += players[ i ].score_total; + } + } + 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 ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + level.zombie_powerups[ powerup_name ].can_pick_up_in_last_stand = b_can_pick_up; +} + +add_zombie_special_drop( powerup_name ) //checked matches cerberus output +{ + level.zombie_special_drop_array[ level.zombie_special_drop_array.size ] = powerup_name; +} + +include_zombie_powerup( powerup_name ) //checked matches cerberus output +{ + if ( !isDefined( level.zombie_include_powerups ) ) + { + level.zombie_include_powerups = []; + } + level.zombie_include_powerups[ powerup_name ] = 1; +} + +powerup_round_start() //checked matches cerberus output +{ + level.powerup_drop_count = 0; +} + +powerup_drop( drop_point ) //modified function +{ + 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, 1 ), 40 ) ); + valid_drop = 0; + for ( i = 0; i < playable_area.size; i++ ) + { + if ( powerup istouching( playable_area[ i ] ) ) + { + valid_drop = 1; + break; + } + } + 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 ) //checked partially changed to match cerberus output +{ + powerup = maps/mp/zombies/_zm_net::network_safe_spawn( "powerup", 1, "script_model", drop_spot + vectorScale( ( 0, 0, 1 ), 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 ) //changed to match cerberus output +{ + 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: + } + if ( skip ) + { + arrayremovevalue( keys, keys[ index ] ); + continue; + } + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); + level specific_powerup_drop( keys[ index ], position ); + return; + } + else + { + arrayremovevalue( keys, keys[ index ] ); + } + } +} + +quantum_bomb_random_zombie_grab_powerup_result( position ) //changed to match cerberus output +{ + 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; + } + else + { + arrayremovevalue( keys, keys[ index ] ); + } + } +} + +quantum_bomb_random_weapon_powerup_result( position ) //checked matches cerberus output +{ + self thread maps/mp/zombies/_zm_audio::create_and_play_dialog( "kill", "quant_good" ); + [[ level.quantum_bomb_play_player_effect_at_position_func ]]( position ); + level specific_powerup_drop( "random_weapon", position ); +} + +quantum_bomb_random_bonus_or_lose_points_powerup_result( position ) //checked matches cerberus output +{ + 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 ) //checked changed to match cerberus output +{ + if ( !isDefined( level.zombie_include_powerups ) || level.zombie_include_powerups.size == 0 ) + { + return; + } + powerup = spawn( "script_model", drop_point + vectorScale( ( 0, 0, 1 ), 40 ) ); + playable_area = getentarray( "player_volume", "script_noteworthy" ); + valid_drop = 0; + for ( i = 0; i < playable_area.size; i++ ) + { + if ( powerup istouching( playable_area[ i ] ) ) + { + valid_drop = 1; + break; + } + } + if ( !valid_drop ) + { + powerup delete(); + return; + } + powerup special_drop_setup(); +} + +cleanup_random_weapon_list() //checked matches cerberus output +{ + self waittill( "death" ); + arrayremovevalue( level.random_weapon_powerups, self ); +} + +powerup_setup( powerup_override, powerup_team, powerup_location ) //checked partially changed to match cerberus output +{ + 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( ( 1, 1, 1 ), 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() //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + self waittill_any( "powerup_timedout", "powerup_grabbed", "hacked" ); + trigger delete(); +} + +powerup_zombie_grab( powerup_team ) //checked changed to match cerberus output +{ + self endon( "powerup_timedout" ); + self endon( "powerup_grabbed" ); + self endon( "hacked" ); + zombie_grab_trigger = spawn( "trigger_radius", self.origin - vectorScale( ( 0, 0, 1 ), 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 ) ) + { + if ( !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 ); + } + 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) //checked partially changed to match cerberus output +{ + if ( isdefined( self ) && self.zombie_grabbable ) + { + self thread powerup_zombie_grab( powerup_team ); + return; + } + + self endon ( "powerup_timedout" ); + self endon ( "powerup_grabbed" ); + + range_squared = 4096; + while ( isdefined( self ) ) + { + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( ( self.powerup_name == "minigun" || self.powerup_name == "tesla" ) && players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() || players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && ( self.powerup_name == "random_weapon" || self.powerup_name == "meat_stink" ) || players[ i ] usebuttonpressed() && players[ i ] in_revive_trigger() ) + { + i++; + continue; + } + if ( isdefined( self.can_pick_up_in_last_stand ) && !self.can_pick_up_in_last_stand && players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() ) + { + i++; + continue; + } + ignore_range = 0; + if ( isdefined( players[ i ].ignore_range_powerup ) && players[ i ].ignore_range_powerup == self ) + { + players[ i ].ignore_range_powerup = undefined; + ignore_range = 1; + } + if ( DistanceSquared( players[ i ].origin, self.origin ) < range_squared || ignore_range ) + { + if ( isdefined(level._powerup_grab_check ) ) + { + if ( !self [[ level._powerup_grab_check ]]( players[ i ] ) ) + { + i++; + continue; + } + } + else if ( isdefined( level.zombie_powerup_grab_func ) ) + { + level thread [[ level.zombie_powerup_grab_func ]](); + break; + } + switch ( self.powerup_name ) + { + case "nuke": + level thread nuke_powerup( self, players[ i ].team ); + players[ i ] thread powerup_vo( "nuke" ); + zombies = getaiarray( level.zombie_team ); + players[ i ].zombie_nuked = arraysort( zombies, self.origin ); + players[ i ] notify( "nuke_triggered" ); + 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 ( is_classic() ) + { + players[ i ] thread maps/mp/zombies/_zm_pers_upgrades::persistent_carpenter_ability_check(); + } + 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 ); + break; + case "tesla": + level thread tesla_weapon_powerup( players[ i ] ); + players[ i ] thread powerup_vo( "tesla" ); + break; + case "random_weapon": + if ( !level random_weapon_powerup( self, players[ i ] ) ) + { + i++; + continue; + } + break; + case "bonus_points_player": + level thread bonus_points_player_powerup( self, players[ i ] ); + players[ i ] thread powerup_vo( "bonus_points_solo" ); + break; + case "bonus_points_team": + level thread bonus_points_team_powerup( self ); + players[ i ] thread powerup_vo( "bonus_points_team" ); + break; + case "teller_withdrawl": + level thread teller_withdrawl( self ,players[ i ] ); + break; + default: + if ( IsDefined( level._zombiemode_powerup_grab ) ) + { + level thread [[ level._zombiemode_powerup_grab ]]( self, players[ i ] ); + } + 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_player_stat( "drops" ); + players[i] maps/mp/zombies/_zm_stats::increment_client_stat( self.powerup_name + "_pickedup" ); + players[i] maps/mp/zombies/_zm_stats::increment_player_stat( self.powerup_name + "_pickedup" ); + } + + if ( self.solo ) + { + playfx( level._effect[ "powerup_grabbed_solo" ], self.origin ); + playfx( level._effect[ "powerup_grabbed_wave_solo" ], self.origin ); + } + 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 ( isdefined( self.stolen ) && self.stolen ) + { + level notify( "monkey_see_monkey_dont_achieved" ); + } + if ( isdefined( self.grabbed_level_notify ) ) + { + level notify( self.grabbed_level_notify ); + } + + self.claimed = true; + self.power_up_grab_player = players[ i ]; //Player who grabbed the power up + + wait 0.1 ; + + playsoundatposition("zmb_powerup_grabbed", self.origin); + self stoploopsound(); + self hide(); + + 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 ); + return; + } + 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" ); + } + i++; + } + wait 0.1; + } +} + + +start_fire_sale( item ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + 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 ) //checked partially changed to match cerberus output +{ + 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; + } + 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 ) //checked partially changed to match cerberus output +{ + current_window = undefined; + shortest_distance = undefined; + i = 0; + while ( i < windows.size ) + { + if ( all_chunks_intact( windows, windows[ i ].barrier_chunks ) ) + { + i++; + continue; + } + if ( !isDefined( current_window ) ) + { + current_window = windows[ i ]; + shortest_distance = distancesquared( current_window.origin, origin ); + i++; + continue; + } + 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 ) //checked matches cerberus output +{ + 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() //checked matches cerberus output +{ + 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() //checked matches cerberus output +{ + 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() //checked partially changed to match cerberus output +{ + 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; + } + wait 0.1; + i++; + } + self notify( "powerup_timedout" ); + self powerup_delete(); +} + +powerup_delete() //checked matches cerberus output +{ + arrayremovevalue( level.active_powerups, self, 0 ); + if ( isDefined( self.worldgundw ) ) + { + self.worldgundw delete(); + } + self delete(); +} + +powerup_delete_delayed( time ) //checked matches cerberus output +{ + if ( isDefined( time ) ) + { + wait time; + } + else + { + wait 0.01; + } + self powerup_delete(); +} + +nuke_powerup( drop_item, player_team ) //checked changed to match cerberus output +{ + 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; + } + if ( isdefined( zombies[ i ].marked_for_death ) && zombies[ i ].marked_for_death ) + { + i++; + continue; + } + if ( isdefined( zombies[ i ].nuke_damage_func ) ) + { + zombies[ i ] thread [[ zombies[ i ].nuke_damage_func ]](); + i++; + continue; + } + if ( is_magic_bullet_shield_enabled( zombies[ i ] ) ) + { + i++; + continue; + } + zombies[ i ].marked_for_death = 1; + //imported from bo3 _zm_powerup_nuke.gsc + if ( !zombies[ i ].nuked && !is_magic_bullet_shield_enabled( zombies[ i ] ) ) + { + zombies[ i ].nuked = 1; + zombies_nuked[ zombies_nuked.size ] = zombies[ i ]; + } + i++; + } + i = 0; + while ( i < zombies_nuked.size ) + { + wait randomfloatrange( 0.1, 0.7 ); + if ( !isdefined( zombies_nuked[ i ] ) ) + { + i++; + continue; + } + if ( is_magic_bullet_shield_enabled( zombies_nuked[ i ] ) ) + { + i++; + continue; + } + 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 ); + for ( i = 0; i < players.size; i++ ) + { + players[ i ] maps/mp/zombies/_zm_score::player_add_points( "nuke_powerup", 400 ); + } +} + +nuke_flash( team ) //checked matches cerberus output +{ + 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 ) //checked partially matches cerberus output did not change +{ + 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(); + for ( player_index = 0; player_index < players.size; player_index++ ) + { + if ( team == players[ player_index ].team ) + { + players[ player_index ] setclientfield( "score_cf_double_points_active", 1 ); + } + } + wait 30; + level.zombie_vars[ team ][ "zombie_point_scalar" ] = 1; + level._race_team_double_points = undefined; + players = get_players(); + for ( player_index = 0; player_index < players.size; player_index++ ) + { + if ( team == players[ player_index ].team ) + { + players[ player_index ] setclientfield( "score_cf_double_points_active", 0 ); + } + } +} + +full_ammo_powerup( drop_item, player ) //checked changed to match cerberus output +{ + players = get_players( player.team ); + if ( isdefined( level._get_game_module_players ) ) + { + players = [[ 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; + } + 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; + } + if ( isdefined( level.zombie_include_equipment ) && isdefined( level.zombie_include_equipment[ primary_weapons[ x ] ] ) ) + { + x++; + continue; + } + if ( isdefined( level.zombie_weapons_no_max_ammo ) && isdefined( level.zombie_weapons_no_max_ammo[ primary_weapons[ x ] ] ) ) + { + x++; + continue; + } + 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 ) //checked matches cerberus output +{ + 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() //checked matches cerberus output +{ + return level.zombie_vars[ self.team ][ "zombie_insta_kill" ]; +} + +check_for_instakill( player, mod, hit_location ) //checked changed to match cerberus output +{ + if ( isDefined( player ) && isalive( player ) && isDefined( level.check_for_instakill_override ) ) + { + if ( !self [[ level.check_for_instakill_override ]]( player ) ) + { + 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" ); + } + 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 ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + 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 ) //checked partially matches cerberus output did not change +{ + 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 ); + for ( i = 0; i < players.size; i++ ) + { + players[ i ] playsound( "zmb_points_loop_off" ); + } + temp_ent stoploopsound( 2 ); + level.zombie_vars[ player_team ][ "zombie_powerup_point_doubler_time" ] = 30; + temp_ent delete(); +} + +toggle_bonfire_sale_on() //checked matches cerberus output +{ + 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() //checked partially matches cerberus output did not change +{ + 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" ] ) + { + for ( i = 0; i < level.chests.size; i++ ) + { + show_firesale_box = level.chests[ i ] [[ level._zombiemode_check_firesale_loc_valid_func ]](); + if ( show_firesale_box ) + { + 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(); + } + } + } + level waittill( "fire_sale_off" ); + waittillframeend; + for ( i = 0; i < level.chests.size; i++ ) + { + show_firesale_box = level.chests[ i ] [[ level._zombiemode_check_firesale_loc_valid_func ]](); + if ( show_firesale_box ) + { + 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; + } + } + } +} + +fire_sale_weapon_wait() //checked matches cerberus output +{ + 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 ) //checked partially matches cerberus output did not change +{ + 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; + } + for ( i = 0; i < chest_index; i++ ) + { + wait_network_frame(); + } + 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() //checked matches cerberus output +{ + wait 1; +} + +full_ammo_on_hud( drop_item, player_team ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + if ( isDefined( flag( "ape_round" ) ) && flag( "ape_round" ) ) + { + return 0; + } + return 0; +} + +setup_firesale_audio() //checked changed to match cerberus output +{ + wait 2; + intercom = getentarray( "intercom", "targetname" ); + while ( 1 ) + { + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 0 ) + { + wait 0.2; + } + for ( i = 0; i < intercom.size; i++ ) + { + intercom [i ] thread play_firesale_audio(); + } + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 ) + { + wait 0.1; + } + level notify( "firesale_over" ); + } +} + +play_firesale_audio() //checked matches cerberus output +{ + 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() //checked changed to match cerberus output +{ + wait 2; + intercom = getentarray( "intercom", "targetname" ); + while ( 1 ) + { + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 0 ) + { + wait 0.2; + } + for ( i = 0; i < intercom.size; i++ ) + { + intercom[ i ] thread play_bonfiresale_audio(); + } + while ( level.zombie_vars[ "zombie_powerup_fire_sale_on" ] == 1 ) + { + wait 0.1; + } + level notify( "firesale_over" ); + } +} + +play_bonfiresale_audio() //checked matches cerberus output +{ + 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 ) //checked changed to match cerberus output +{ + players = get_players(); + for ( i = 0; i < players.size; i++ ) + { + 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 ); + } + } + } +} + +disable_perk_before_power( perk ) //checked matches cerberus output +{ + 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() //checked matches cerberus output +{ + self.random_weapon_powerup_throttle = 1; + wait 0.25; + self.random_weapon_powerup_throttle = 0; +} + +random_weapon_powerup( item, player ) //checked partially matches cerberus output did not change +{ + 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 ) //checked matches cerberus output +{ + 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 ) //checked changed to match cerberus output +{ + points = randomintrange( 1, 25 ) * 100; + if ( isDefined( level.bonus_points_powerup_override ) ) + { + points = [[ level.bonus_points_powerup_override ]](); + } + players = get_players(); + for ( i = 0; i < players.size; i++ ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) + { + players[ i ] maps/mp/zombies/_zm_score::player_add_points( "bonus_points_powerup", points ); + } + } +} + +lose_points_team_powerup( item ) //checked partially changed to match cerberus output +{ + points = randomintrange( 1, 25 ) * 100; + players = get_players(); + i = 0; + while ( i < players.size ) + { + if ( !players[ i ] maps/mp/zombies/_zm_laststand::player_is_in_laststand() && players[ i ].sessionstate != "spectator" ) + { + if ( ( players[ i ].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 ) //checked partially matches cerberus output +{ + players = get_players(); + for ( i = 0; i < players.size; i++ ) + { + 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(); + } + } +} + +empty_clip_powerup( item ) //checked partially matches cerberus output +{ + players = get_players(); + for ( i = 0; i < players.size; i++ ) + { + player = players[ i ]; + if ( !player maps/mp/zombies/_zm_laststand::player_is_in_laststand() && player.sessionstate != "spectator" ) + { + weapon = player getcurrentweapon(); + player setweaponammoclip( weapon, 0 ); + } + } +} + +minigun_weapon_powerup( ent_player, time ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + 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 ) //checked matches cerberus output +{ + 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 ) //checked partially matches cerberus output did not change +{ + 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(); + + for ( i = 0; i < player_weapons.size; i++ ) + { + if ( player_weapons[ i ] == ent_player._zombie_gun_before_minigun ) + { + ent_player switchtoweapon( ent_player._zombie_gun_before_minigun ); + return; + } + } + } + primaryweapons = ent_player getweaponslistprimaries(); + if ( primaryweapons.size > 0 ) + { + ent_player switchtoweapon( primaryweapons[ 0 ] ); + } + else + { + allweapons = ent_player getweaponslist( 1 ); + for ( i = 0; i < allweapons.size; i++ ) + { + if ( is_melee_weapon( allweapons[ i ] ) ) + { + ent_player switchtoweapon( allweapons[ i ] ); + return; + } + } + } +} + +minigun_weapon_powerup_off() //checked matches cerberus output +{ + self.zombie_vars[ "zombie_powerup_minigun_time" ] = 0; +} + +minigun_watch_gunner_downed() //checked partially matches cerberus output did not change +{ + if ( isDefined( self.has_minigun ) && !self.has_minigun ) + { + return; + } + primaryweapons = self getweaponslistprimaries(); + for ( i = 0; i < primaryweapons.size; i++ ) + { + if ( primaryweapons[ i ] == "minigun_zm" ) + { + self takeweapon( "minigun_zm" ); + } + } + 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 ) //checked changed to match cerberus output +{ + 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 ) //checked changed to match cerberus output +{ + 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; + } + } + 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 ) //checked matches cerberus output +{ + 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 ) //checked changed to match cerberus output +{ + 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(); + if ( isDefined( ent_player._zombie_gun_before_tesla ) ) + { + player_weapons = ent_player getweaponslistprimaries(); + for ( i = 0; i < player_weapons.size; i++ ) + { + if ( player_weapons[ i ] == ent_player._zombie_gun_before_tesla ) + { + ent_player switchtoweapon( ent_player._zombie_gun_before_tesla ); + return; + } + } + } + primaryweapons = ent_player getweaponslistprimaries(); + if ( primaryweapons.size > 0 ) + { + ent_player switchtoweapon( primaryweapons[ 0 ] ); + } + allweapons = ent_player getweaponslist( 1 ); + for ( i = 0; i < allweapons.size; i++ ) + { + if ( is_melee_weapon( allweapons[ i ] ) ) + { + ent_player switchtoweapon( allweapons[ i ] ); + return; + } + } +} + +tesla_weapon_powerup_off() //checked matches cerberus output +{ + self.zombie_vars[ "zombie_powerup_tesla_time" ] = 0; +} + +tesla_watch_gunner_downed() //checked changed to match cerberus output +{ + if ( isDefined( self.has_tesla ) && !self.has_tesla ) + { + return; + } + primaryweapons = self getweaponslistprimaries(); + for ( i = 0; i < primaryweapons.size; i++ ) + { + if ( primaryweapons[ i ] == "tesla_gun_zm" ) + { + self takeweapon( "tesla_gun_zm" ); + } + } + 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() //checked changed to match cerberus output +{ + players = get_players(); + for ( i = 0; i < players.size; i++ ) + { + if ( players[ i ].zombie_vars[ "zombie_powerup_tesla_on" ] ) + { + return 1; + } + } + return 0; +} + +print_powerup_drop( powerup, type ) //devcall only, deleted +{ + /* + /# + if(!isdefined(level.powerup_drop_time)) + { + level.powerup_drop_time = 0; + level.powerup_random_count = 0; + level.powerup_score_count = 0; + } + time = GetTime() - level.powerup_drop_time * 0.001; + level.powerup_drop_time = GetTime(); + if(type == "random") + { + level.powerup_random_count++; + } + else + { + level.powerup_score_count++; + } + println("========== POWER UP DROPPED =========="); + println("DROPPED: " + powerup); + println("HOW IT DROPPED: " + type); + println("--------------------"); + println("Drop Time: " + time); + println("Random Powerup Count: " + level.powerup_random_count); + println("Random Powerup Count: " + level.powerup_score_count); + println("======================================"); + #/ + */ +} + +register_carpenter_node( node, callback ) //checked matches cerberus output +{ + 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 ) //checked partially changed to match cerberus output +{ + 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; + } + chunk = get_random_destroyed_chunk( window, window.barrier_chunks ); + if ( !isDefined( chunk ) ) + { + break; + } + 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; + } + } + 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; + } + 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(); + for ( i = 0; i < players.size; i++ ) + { + players[ i ] maps/mp/zombies/_zm_score::player_add_points( "carpenter_powerup", 200 ); + } + carp_ent delete(); + level notify( "carpenter_finished" ); + level.carpenter_powerup_active = undefined; +} + +is_carpenter_boards_upgraded() //checked matches cerberus output +{ + if ( isDefined( level.pers_carpenter_boards_active ) && level.pers_carpenter_boards_active == 1 ) + { + return 1; + } + return 0; +} + +get_near_boards( windows ) //checked changed to match cerberus output +{ + players = get_players(); + boards_near_players = []; + for ( j = 0; j < windows.size; j++ ) + { + close = 0; + for ( i = 0; i < players.size; i++ ) + { + 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; + } + } + if ( close ) + { + boards_near_players[ boards_near_players.size ] = windows[ j ]; + } + } + return boards_near_players; +} + +get_far_boards( windows ) //checked changed to match cerberus output +{ + players = get_players(); + boards_far_from_players = []; + for ( j = 0; j < windows.size; j++ ) + { + close = 0; + for ( i = 0; i < players.size; i++ ) + { + 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; + } + } + if ( close ) + { + boards_far_from_players[ boards_far_from_players.size ] = windows[ j ]; + } + } + return boards_far_from_players; +} + +repair_far_boards( barriers, upgrade ) //checked changed to match cerberus output +{ + i = 0; + while ( i < barriers.size ) + { + barrier = barriers[ i ]; + if ( all_chunks_intact( barrier, barrier.barrier_chunks ) ) + { + i++; + continue; + } + if ( isdefined( barrier.zbarrier ) ) + { + a_pieces = barrier.zbarrier getzbarrierpieceindicesinstate( "open" ); + if ( 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; + } + barrier.zbarrier zbarrierpieceusedefaultmodel( chunk ); + barrier.zbarrier.chunk_health[ chunk ] = 0; + xx++; + } + } + for ( x = 0; x < barrier.zbarrier getnumzbarrierpieces(); x++ ) + { + barrier.zbarrier setzbarrierpiecestate( x, "closed" ); + barrier.zbarrier showzbarrierpiece( x ); + } + } + else 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++; + } +} + +track_pack_a_punch_drops() +{ + level endon("end_game"); + level.rounds_since_last_pack_a_punch = 0; + for(;;) + { + level waittill("start_of_round"); + level.rounds_since_last_pack_a_punch_drop += 1; + wait 0.5; + } +} + +func_should_drop_pack_a_punch() +{ + if ( level.zmPowerupsEnabled[ "pack_a_punch" ].active != 1 || level.round_number < 12 || isDefined( level.rounds_since_last_pack_a_punch_drop ) && level.rounds_since_last_pack_a_punch_drop < 5 ) + { + return 0; + } + return 1; +} + +func_should_never_drop() //checked matches cerberus output +{ + return 0; +} + +func_should_always_drop() //checked matches cerberus output +{ + 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 = []; + foreach ( powerup in level.active_powerups ) + { + if ( distancesquared( origin, powerup.origin ) < radius * radius ) + { + powerups[ powerups.size ] = powerup; + } + } + 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 ); +} + +zombies_always_drop_powerups() +{ + if ( !level.zombiesAlwaysDropPowerups ) + { + return; + } + while ( 1 ) + { + level.zombie_vars[ "zombie_drop_item" ] = level.zombiesAlwaysDropPowerups; + wait 0.05; + } +} + +doFastFeet() +{ + level endon("end_game"); + self endon( "disconnect" ); + self thread poweruptext("Fast Feet!"); + self playsound("zmb_cha_ching"); + self setmovespeedscale(3); + wait 15; + self setmovespeedscale(1); + self playsound("zmb_insta_kill"); +} + +doUnlimitedAmmo() +{ + level endon("end_game"); + foreach(player in level.players) + { + player notify("end_unlimited_ammo"); + player playsound("zmb_cha_ching"); + player thread poweruptext("Bottomless Clip"); + player thread monitorUnlimitedAmmo(); + player thread notifyUnlimitedAmmoEnd(); + } +} + +monitorUnlimitedAmmo() +{ + level endon("end_game"); + self endon("disonnect"); + self endon("end_unlimited_ammo"); + for(;;) + { + self setWeaponAmmoClip(self GetCurrentWeapon(), 150); + wait .05; + } +} + +notifyUnlimitedAmmoEnd() +{ + level endon("end_game"); + self endon("disonnect"); + self endon("end_unlimited_ammo"); + wait level.unlimited_ammo_duration; + self playsound("zmb_insta_kill"); + self notify("end_unlimited_ammo"); +} + +doPackAPunchWeapon() +{ + baseweapon = get_base_name(self getcurrentweapon()); + weapon = get_upgrade(baseweapon); + if(IsDefined(weapon) && isDefined(self.packapunching)) + { + level.rounds_since_last_pack_a_punch_drop = 0; + self.packapunching = undefined; + self takeweapon(baseweapon); + self giveweapon(weapon, 0, self get_pack_a_punch_weapon_options(weapon)); + self switchtoweapon(weapon); + self givemaxammo(weapon); + } + else + self playsoundtoplayer( level.zmb_laugh_alias, self ); +} + +get_upgrade(weapon) +{ + if(IsDefined(level.zombie_weapons[weapon].upgrade_name) && IsDefined(level.zombie_weapons[weapon])) + { + self.packapunching = true; + return get_upgrade_weapon(weapon, 0 ); + } + else + return get_upgrade_weapon(weapon, 1 ); +} + +doRandomScore() +{ + x = randomInt(9); + self playsound("zmb_cha_ching"); + if(x==1) + self.score += 50; + else if(x==2) + self.score += 100; + else if(x==3) + self.score += 250; + else if(x==4) + self.score += 500; + else if(x==5) + self.score += 750; + else if(x==6) + self.score += 1000; + else if(x==7) + self.score += 2500; + else if(x==8) + self.score += 5000; + else if(x==9) + self.score += 7500; + else + self.score += 10000; +} + +poweruptext(text) +{ + self endon("disconnect"); + level endon("end_game"); + hud_string = newclienthudelem(self); + hud_string.elemtype = "font"; + hud_string.font = "objective"; + hud_string.fontscale = 2; + hud_string.x = 0; + hud_string.y = 0; + hud_string.width = 0; + hud_string.height = int( level.fontheight * 2 ); + hud_string.xoffset = 0; + hud_string.yoffset = 0; + hud_string.children = []; + hud_string setparent(level.uiparent); + hud_string.hidden = 0; + hud_string maps/mp/gametypes_zm/_hud_util::setpoint("TOP", undefined, 0, level.zombie_vars["zombie_timer_offset"] - (level.zombie_vars["zombie_timer_offset_interval"] * 2)); + hud_string.sort = .5; + hud_string.alpha = 0; + hud_string fadeovertime(.5); + hud_string.alpha = 1; + hud_string setText(text); + hud_string thread poweruptextmove(); +} + +poweruptextmove() +{ + wait .5; + self fadeovertime(1.5); + self moveovertime(1.5); + self.y = 270; + self.alpha = 0; + wait 1.5; + self destroy(); +} diff --git a/Zombies Mods/Zombies++ v1.2/dedicated_zm.cfg b/Zombies Mods/Zombies++ v1.2/dedicated_zm.cfg new file mode 100644 index 0000000..6eacfa3 --- /dev/null +++ b/Zombies Mods/Zombies++ v1.2/dedicated_zm.cfg @@ -0,0 +1,249 @@ +////////////////////////////////////////////////// +/// PlutoT6 ZM ServerConfiguration file // +////////////////////////////////////////////////// +// This config best view with Notepad++ OR // +// Other *nix compatible editors of your choice.// +////////////////////////////////////////////////// +// 0.1 Basic version // +// 0.2 Added map list and map rotation // +// 0.3 Added Colors and B3/Log/RCon section // +// 0.4 Added gametype to map list and rotation // +// 0.5 Added location to map list and rotation // +// 0.6 Added Sharp Shooter and Gun game // +// 0.7 Clean up // +// 0.8 Additional gts -Fry // +// 0.9 Cleaned up the mess Fry merged, // +// added more comments // +////////////////////////////////////////////////// +// SERVER NAME & COLORS TIPS // +////////////////////////////////////////////////// +// ^0 Black // +// ^1 Red // +// ^2 Green // +// ^3 Yellow // +// ^4 Blue // +// ^5 Cyan // +// ^6 Pink // +// ^7 White // +////////////////////////////////////////////////// + +sv_hostname "^5ZOMBIES++ ^3[Dev:@ItsCahz]" //Give your server a name so you can spot it on the serverlist. + +////////////////////////////////////////////////// +// GENERAL SETTINGS // +////////////////////////////////////////////////// +sv_offline "0" // Enables the offline mode. 1 = offline, 0 = online useful for LANs or in the case we get shut down. +//g_password "" // Password protected Game Server +party_maxplayers "4" // Maximum players that are allowed in your server (1-8) +//sv_minPing "0" // Minimum ping neede to the server? (Terribly broken and inaccurate since ages!) +//sv_maxPing "400" // Maximum ping allowed to the server? (Terribly broken and inaccurate since ages!) +//zm_gungame "1" // Enable Pluto's custom Gun Game? +//zm_sharpshooter "1" // Enable Pluto's custom Sharp Shooter? +gts zmDifficulty "1" // Difficulty? 0 = Easy, 1 = Normal +gts startRound "1" // Starting Round. Only Survival and Grief have this option! +//gts autoTeamBalance "1" // Auto team balancing +//gts teamCount "2" // Turn this on for grief only! +//gts magic "0" // Remove all supernatural assistance? Only Survival and Grief have this option! +//gts headshotsonly "1" // Headshots only? Only Survival and Grief have this option! +//gts allowdogs "1" // Allow Hellhounds? Only Survival has this option! +//gts cleansedLoadout "1" // Allow players to choose their Loadout? Only Turned has this option! +//set g_loadScripts "0" + +//Welcome to Zombies++! you can enable or disable all functions in this file! +//almost no need to edit the GSC +//Developed by @ItsCahz +//huge credits to _Ox and JezuzLizard! without their releases, this wouldn't be possible! +//Zombies++ is not meant to be an "over the top" modded experience +//I wanted this to be an addition to the vanilla zombies +//credit to JezuzLizard! huge thanks for the server config base! +//game options +set playerStartingPoints 500 //staring points +set perkLimit 9 //perk limit *NOTE CUSTOM PERKS COUNT TOWARDS THE PERK LIMIT! EXCEPT PHD FLOPPER +set zombieAiLimit 24 //32 = hard mode fuck yes +set zombieActorLimit 32 //32 zombies tryna eat ur face haha get fuckd +set midroundDogs 0 //mid round puppers +set noEndGameCheck 0 //noendgamecheck +set soloLaststandWeapon "m1911_upgraded_zm" //Solo last stand weapon (so like if ur reviving urself with quick revive typ shit) +set coopLaststandWeapon "m1911_zm" //last stand weapon is in co-op +set startWeaponZm "m1911_zm" //weapon player starts with +set disableWalkers 0 //make all zombies runners (theyre fast af boi) +set roundNumber 1 //round number to start on +set soloModeDisabled 1 //disable solo mode - fixes quick revive price and Mob of the Dead Afterlife count to 1 instead of 3 +//main Zombies++ options +set enableZombieCounter 1 //enable or disable on screen zombie counter +set customMysteryBoxPriceEnabled 0 //override mystery box price +set customMysteryBoxPrice 10 //custom mystery box price +set disableAllCustomPerks 0 //override any enabled custom perks and disable all +set zmPowerupsNoPowerupDrops 0 //override powerup drops +//Zombies++ options + +//custom perk machines +set enablePHDFlopper 1 //enable custom phdflopper perk machine on maps (Nuketown, Tranzit, Buried, MOTD, Die Rise) +set enableStaminUp 1 //enable custom staminup perk machine on maps (Nuketown, Tranzit, MOTD, Die Rise) +set enableDeadshot 1 //enable custom deadshot perk machine on maps (Nuketown, Tranzit, Buried, Die Rise) +set enableMuleKick 1 //enable custom mulekick perk machine on maps (Nuketown, Tranzit) + +//custom powerup drops +set zmPowerupsMoneyDropEnabled 1 +set zmPowerupsPackAPunchEnabled 0 +set zmPowerupsUnlimitedAmmoEnabled 1 +set zmPowerupsFastFeetEnabled 1 + +//powerups properties +set maxPowerupsPerRound 4 //max number of powerups in any 1 round +set powerupDropRate 6000 //drop rate for powerups (lower is faster) 2000 is default(?) but that feels too easy +set zombiesAlwaysDropPowerups 0 //zombies always drop powerups (will stop dropping after max limit is hit) +set fourPlayerPowerupScore 50 //powerup score per kill with 4 players +set threePlayerPowerupScore 50 //powerup score per kill with 3 players +set twoPlayerPowerupScore 50 //powerup score per kill with 2 players +set onePlayerPowerupScore 50 //powerup score per kill with 1 player +set powerupScoreMeleeKill 80 //powerup score per melee kill +set powerupScoreHeadshotKill 50 //powerup score per headshot kill +set powerupScoreNeckKill 20 //powerup score per neck kill +set powerupScoreTorsoKill 10 //powerup score per torso kill + +//enable or disable powerups +set zmPowerupsNukeEnabled 1 //enable nuke powerup +set zmPowerupsInstaKillEnabled 1 //enable insta kill powerup +set zmPowerupsMaxAmmoEnabled 1 //enable max ammo powerup +set zmPowerupsDoublePointsEnabled 1 //enable double points powerup +set zmPowerupsCarpenterEnabled 1 //enable carpenter powerup +set zmPowerupsFireSaleEnabled 1 //enable fire sale powerup +set zmPowerupsPerkBottleEnabled 1 //enable perk bottle powerup +set zmPowerupsZombieBloodEnabled 1 //enable zombie blood powerup + +//zombie properties dvars +set overrideZombieTotalPermanently 0 +set overrideZombieTotalPermanentlyValue 100 +set overrideZombieHealthPermanently 0 +set overrideZombieHealthPermanentlyValue 150 +set overrideZombieMaxHealth 0 +set overrideZombieMaxHealthValue 150 +set zombieSpawnRate 1.75 //2 is default 1.75 feels slightly nicer +set zombieSpawnRateMultiplier 0.95 +set zombieSpawnRateLocked 0 +set zombiesPerPlayer 6 +set zombieHealthIncreaseFlat 100 +set zombieHealthIncreaseMultiplier 0.1 +set zombieHealthStart 150 +set zombieNewRunnerInterval 10 +set zombieMoveSpeed 10 +set zombieMoveSpeedLocked 1 +set zombieMoveSpeedCap 0 +set zombieMoveSpeedCapValue 1 +set zombieMoveSpeedMultiplier 10 +set zombieMoveSpeedMultiplierEasy 8 +set zombieMaxAi 24 +set belowWorldCheck -1000 + +//round properties +set customSpectatorsRespawn 1 +set zombieIntermissionTime 10 +set zombieBetweenRoundTime 15 +set roundStartDelay 0 + +//player properties +set bleedoutPointsLostAllPlayers 0.1 +set bleedoutPointsLostSelf 0.1 +set downedPointsLostSelf 0.05 +set playerStartingLives 1 +set fourPlayerScorePerZombieKill 50 +set threePlayerScorePerZombieKill 50 +set twoPlayerScorePerZombieKill 50 +set onePlayerScorePerZombieKill 50 +set pointsPerNormalAttack 10 +set pointsPerLightAttack 10 +set shouldZombifyPlayer 0 +set alliesPointsMultiplier 1 +set axisPointsMultiplier 1 + +//perk properties +set empPerkExplosionRadius 420 +set empPerkOffDuration 90 +set riotshieldHitPoints 2250 +set juggHealthBonus 160 +set permaJuggHealthBonus 190 +set minPhdExplosionDamage 1000 +set maxPhdExplosionDamage 5000 +set phdDamageRadius 300 + +//builtin dvars +//sets whether the mystery box moves ever +set magic_chest_movable 1 +//sets how close players have to be to revive another player +set revive_trigger_radius 75 +//sets the amount time before a player will bleedout after going down +set player_lastStandBleedoutTime 90 +//sets speed colas reload multiplier lower is better WARNING: animation doesn't sync +set perk_weapReloadMultiplier 0.5 +//sets double taps firing speed multiplier lower is better +set perk_weapRateMultiplier 0.75 +//sets deadshot crosshair size multiplier lower is better +set perk_weapSpreadMultiplier 0.70 +////////////////////////////////////////////////// +////////////////////////////////////////////////// +// B3, GAME LOG & RCON SETTINGS // +////////////////////////////////////////////////// +g_logSync 2 // 0 only flush on game end, 1 flush when buffer full, 2 always flush after a write, 3 append to old logs. +g_log "" // Disable logs per default. +g_log "logs\games_zm.log" // If you choose to use this make sure the filename is unique for each server! +rcon_password "" // RemoteCONtrol password, needed for most management tools. +////////////////////////////////////////////////// +////////////////////////////////////////////////// +// MAP LIST WITH ALL GAME MODES AND LOCATIONS // +////////////////////////////////////////////////// +// At the moment only the first game mode of // +// each map works on dedicated servers (31/3/18)// +////////////////////////////////////////////////// +// Buried aka Resolution 1295 // +////////////////////////////////////////////////// +//gametype zclassic loc processing map zm_buried// +////////////////////////////////////////////////// +// Die Rise aka Great Leap Forward // +////////////////////////////////////////////////// +//gametype zclassic loc rooftop map zm_highrise// +////////////////////////////////////////////////// +// Nuketown // +////////////////////////////////////////////////// +//gametype zstandard loc nuked map zm_nuked // +////////////////////////////////////////////////// +// Mob of the Dead // +////////////////////////////////////////////////// +//gametype zclassic loc prison map zm_prison// +////////////////////////////////////////////////// +// Origins // +//Make sure you don't allow more than 4 players!// +////////////////////////////////////////////////// +//gametype zclassic loc tomb map zm_tomb // +////////////////////////////////////////////////// +// Diner (Turned only) // +////////////////////////////////////////////////// +//gametype zcleansed loc diner map zm_transit_dr// +////////////////////////////////////////////////// +// Green Run aka Bus Depot aka Farm aka Town // +////////////////////////////////////////////////// +//gametype zclassic loc transit map zm_transit // +////////////////////////////////////////////////// +//g_gametype zgrief +////////////////////////////////////////////////////////////////////////////////////// +//Unlike in other games/MP you should always define the game type and location. // +////////////////////////////////////////////////////////////////////////////////////// +//Die Rise +sv_maprotation "gametype zclassic loc rooftop map zm_highrise" + +//Buried +//sv_maprotation "gametype zclassic loc processing map zm_buried" + +//Alcatraz +//sv_maprotation "gametype zclassic loc prison map zm_prison" + +//Tranzit +//sv_maprotation "gametype zclassic loc transit map zm_transit" + +//Origins +//sv_maprotation "gametype zclassic loc tomb map zm_tomb" + +//Nuketown +//sv_maprotation "gametype zstandard loc nuked map zm_nuked" + +map_rotate \ No newline at end of file