if engine.ActiveGamemode() ~= "zombiesurvival" then return end local settings = { JackpotStart = 25, JackpotMax = 2500, JackpotMultiplier = 1.1, MinimumRounds = 5, EndroundPoints = 50, -- Points to give at the end of the round (Jackpot gets added to the points the players get) ZombiePointsFactor = 0.15, -- Factor of points zombies get of the points payout after round end LosePointReduction = 0.0 -- Factor of points that gets taken away from players who lost } -- Grab the data from the file about the map. local function getMapParams(mapName) local data = {} if file.Exists("zsmapinfo/"..mapName..".txt", "DATA") then data = util.JSONToTable(file.Read("zsmapinfo/"..mapName..".txt", "DATA")) or {} end -- Get map params or default values local mapParams = {} mapParams.Name = mapName mapParams.TimesWon = data.TimesWon or 0 mapParams.TimesLost = data.TimesLost or 0 mapParams.Boost = data.Boost or 1 mapParams.Jackpot = data.Jackpot or settings.JackpotStart return mapParams end local mapParams = getMapParams(string.lower(game.GetMap())) local function saveMapParams(mapParams) if not file.Exists("zsmapinfo", "DATA") then file.CreateDir("zsmapinfo") end file.Write("zsmapinfo/"..mapParams.Name..".txt", util.TableToJSON(mapParams)) end -- This hook checks to make sure there are zombies on the server. TODO: Check for AFK zombies local zombieIntervalCounter, totalIntervalCounter = 0, 0 hook.Add("WaveStateChanged", "pointsave_zombieintervalactivator", function() if not timer.Exists("pointsave_zombieintervalcounter") then timer.Create("pointsave_zombieintervalcounter", 10, 0, function() if #(team.GetPlayers(TEAM_UNDEAD)) > 0 then zombieIntervalCounter = zombieIntervalCounter + 1 end totalIntervalCounter = totalIntervalCounter + 1 end) end end) local function resetVariables() zombieIntervalCounter, totalIntervalCounter = 0, 0 end local function postStatistics(mapParams, timesPlayed, freqMult, zombiePercentCalcMap) PrintMessage(HUD_PRINTTALK,"This map has been played "..timesPlayed.." times with humans winning "..(mapParams.TimesWon).." times.("..(math.Round((mapParams.TimesWon/timesPlayed)*100)).."%)") PrintMessage(HUD_PRINTTALK,"Zombies were playing this map for "..math.Round(zombiePercentCalcMap * 100).."% of the time.") PrintMessage(HUD_PRINTTALK,"frequency multiplier for this map is "..math.Round(freqMult, 2)..". Play maps infrequently for a higher value!") PrintMessage(HUD_PRINTTALK,"Special boost for this map is "..(mapParams.Boost)..". Tell an admin if you think it should be changed!") PrintMessage(HUD_PRINTTALK,"Map jackpot is now "..(mapParams.Jackpot)..".") end -- TODO: When round is lost, take away points from human players that were there at the beginning of the game (All Human players that were there at the end of round 1, when late joiners join as zombies) --[[ Cases: - When round is lost: - Only players from the end of Wave 1 (online or disconnected) get the 85% reduction of points. But online players get some additional points - When round is won: - All humans get points + jackpot - Zombies get a few points (but a reduction of 85% if they were there since the end of wave 1) ]]-- hook.Add("PostEndRound", "pointsave_givedapoints", function(winner) timer.Destroy("pointsave_zombieintervalcounter") if PointSaving_shouldIgnoreMap(game.GetMap()) then return end timer.Simple(0, function() print("point bonus hook") local zombiePercentCalcMap = 1 if totalIntervalCounter > 0 then zombiePercentCalcMap = (zombieIntervalCounter / totalIntervalCounter) end local timesPlayed = mapParams.TimesWon + mapParams.TimesLost local freqMult = 1 / math.pow(math.Max(timesPlayed, 10) / 10, 0.2) + 1 -- Check if zombies did even play most of the map if zombiePercentCalcMap <= .5 then PrintMessage(HUD_PRINTTALK, "No end of game points because zombies were not even playing half the time!") postStatistics(mapParams, timesPlayed, freqMult, zombiePercentCalcMap) saveMapParams(mapParams) resetVariables() return end -- Increase counters if winner == TEAM_UNDEAD then mapParams.TimesLost = mapParams.TimesLost + 1 elseif winner == TEAM_HUMAN then mapParams.TimesWon = mapParams.TimesWon + 1 else print("Wow you fucked up! No seriously how do you not have a winner?") end -- Increase jackpot if winner == TEAM_UNDEAD then mapParams.Jackpot = mapParams.Jackpot * settings.JackpotMultiplier if mapParams.Jackpot > settings.JackpotMax then mapParams.Jackpot = settings.JackpotMax end end -- Again, as the counter changed timesPlayed = mapParams.TimesWon + mapParams.TimesLost local freqMult = 1 / math.pow(math.Max(timesPlayed, 10) / 10, 0.2) + 1 -- Check if map was played enough times if timesPlayed < settings.MinimumRounds then PrintMessage(HUD_PRINTTALK, "Sorry, this map needs to be played at least "..(settings.MinimumRounds - timesPlayed).." more times, before you can get points for winning.") postStatistics(mapParams, timesPlayed, freqMult, zombiePercentCalcMap) saveMapParams(mapParams) resetVariables() return end -- Calculate points to give local pointsToGive local jackpot = 0 if winner == TEAM_HUMAN then local finalMultiply = (mapParams.Boost * freqMult * (mapParams.TimesLost / timesPlayed) * zombiePercentCalcMap) PrintMessage(HUD_PRINTTALK, "Congratulations, every survivor won the jackpot of "..mapParams.Jackpot.." for winning this round") pointsToGive = math.Round((settings.EndroundPoints * finalMultiply)) jackpot = mapParams.Jackpot mapParams.Jackpot = settings.JackpotStart else local finalMultiply = (mapParams.Boost * (mapParams.TimesWon / timesPlayed) * zombiePercentCalcMap) pointsToGive = math.Round(settings.EndroundPoints * finalMultiply) end saveMapParams(mapParams) -- Give or take points, and output messages for each player for k, ply in pairs(player.GetAll()) do local pointsToGivePly local points = math.Round(ply:GetSavedPoints()) -- Calculate points to give for each player (Depending on if the round was lost or won) if ply:Team() == TEAM_HUMAN then points = math.Round(ply:GetPoints()) pointsToGivePly = math.Round(pointsToGive + jackpot) else pointsToGivePly = math.Round(pointsToGive * settings.ZombiePointsFactor - points * settings.LosePointReduction) end -- Limit pointsToGivePly if points + pointsToGivePly < 0 then pointsToGivePly = -points end -- Set points ply:SetPoints(points + pointsToGivePly) ply:SetSavedPoints(points + pointsToGivePly) -- Display message if pointsToGivePly > 0 then ply:PrintMessage(HUD_PRINTTALK, "You gained "..(pointsToGivePly).." this round for playing to the end!") elseif pointsToGivePly < 0 then ply:PrintMessage(HUD_PRINTTALK, "You lost "..(-pointsToGivePly).." points this round!") end end -- Output general stats about this map postStatistics(mapParams, timesPlayed, freqMult, zombiePercentCalcMap) resetVariables() end) end)