Sulfito_PointSaving/lua/autorun/server/pointsaving_mapstats.lua
2018-07-17 19:24:31 +02:00

169 lines
6.7 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 (Jackpot gets added to the points the players get)
ZombiePointsFactor = 0.5, -- Factor of points zombies get of the points payout after round end
LosePointReduction = 0.85 -- 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 "..freqMult..". 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 = (zombieIntervalCounter / totalIntervalCounter)
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
if winner == TEAM_HUMAN then
local finalMultiply = (mapParams.Boost * freqMult * (mapParams.TimesLost / timesPlayed) * zombiePercentCalcMap)
PrintMessage(HUD_PRINTTALK, "Congratulations, you won the jackpot of "..mapParams.Jackpot.." for winning this round")
pointsToGive = math.Round((settings.EndroundPoints * finalMultiply) + 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 = ply:GetPoints()
-- Calculate points to give for each player (Depending on if the round was lost or won)
if ply:Team() == TEAM_HUMAN then
pointsToGivePly = math.Round(pointsToGive)
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)