You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
7.4 KiB
Lua

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 to winners (Jackpot gets added to the points the players get)
ZombiePointsFactor = 0.00, -- Factor of points zombies get of the EndroundPoints after round end
LosePointReduction = 0.00, -- Factor of the total saved points, which get taken away from players who lost
LosePointDifferenceReduction = 0.85 -- Factor of the players gained points, which get 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())
local gainedPoints = points - (ply.PointSaving_StartPoints or 0)
--print("GAINED: "..gainedPoints)
if gainedPoints < 0 or not ply.PointSaving_StartPoints then gainedPoints = 0 end
-- Calculate points to give for each player (Depending on if the round was lost or won)
if ply:Team() == TEAM_HUMAN and winner == TEAM_HUMAN then
points = math.Round(ply:GetPoints())
pointsToGivePly = math.Round(pointsToGive + jackpot)
else
pointsToGivePly = math.Round(pointsToGive * settings.ZombiePointsFactor - points * settings.LosePointReduction - gainedPoints * settings.LosePointDifferenceReduction)
end
-- Limit pointsToGivePly
if points + pointsToGivePly < 0 then pointsToGivePly = -points end
-- Set points
ply:SetPoints(points + pointsToGivePly)
ply:SetSavedPoints(points + pointsToGivePly)
ply.PointSaving_StartPoints = nil
-- Display message
if pointsToGivePly > 0 then
ply:PrintMessage(HUD_PRINTTALK, "In the end, you gained additional "..(pointsToGivePly).." points!")
elseif pointsToGivePly < 0 then
ply:PrintMessage(HUD_PRINTTALK, ""..(-pointsToGivePly).." points will be retracted from you this round!")
end
end
-- Output general stats about this map
postStatistics(mapParams, timesPlayed, freqMult, zombiePercentCalcMap)
resetVariables()
end)
end)