This is the server-side code i have at the moment only set to 3 rounds for testing
local extendtime = 0 -- Extend Map for x Minutes
local retry = 0 -- Retrys if nobody voted
local minvoteneed = 0.60 -- In percent
local maxextend = 0 -- Maximum Extend do -1 to deactivate
local minvotes = 6 -- How many maps should be in the vote
local rocksneeded = 0.6 -- in % how many rockvotes are needed to force a mapvote
local RoundCount
function AVMS.StartVote()
RoundCount = RoundCount + 1
if RoundCount == 3 then
AVMS.StartVote()
RoundCount = 0
end
end
hook.Add("TTTEndRound", "AVMS.StartVote", AVMS.StartVote )
function AVMS.StartVote(maps,title,lenght,recallfunc)
if timer.IsTimer("VoteMap") then return end
AVMS.Votes = {}
AVMS.Maps = maps
AVMS.Func = recallfunc
AVMS.Currentmaps = table.Count(maps)
AVMS.Voters = #player.GetAll()
local tbl = {title = title,maps = maps}
datastream.StreamToClients(player.GetAll(),"_startvotemap", tbl)
timer.Create("VoteMap",lenght,1,function()
AVMS.EndVote()
end)
end
function AVMS.DoVote(ply,cmd,args)
if !ValidEntity(ply) or !args[1] or !AVMS.Votes then return end
if AVMS.Votes[ply:EntIndex()] then return end
local voted = tonumber(args[1])
if voted > AVMS.Currentmaps then return end
AVMS.Votes[ply:EntIndex()] = voted
AVMS.UpdateVote()
if table.Count(AVMS.Votes) >= #player.GetAll() then AVMS.EndVote() end
end
concommand.Add("_votefor",AVMS.DoVote)
function AVMS.UpdateVote()
if !AVMS.Votes then return end
local maps = AVMS.Maps
local tbl = {}
for k,v in pairs(AVMS.Votes) do
if !tbl[v] then tbl[v] = 0 end
tbl[v] = tbl[v] + 1
end
datastream.StreamToClients(player.GetAll(),"_updatevotemap", tbl)
end
function AVMS.EndVote()
local tbl = {}
local maps = AVMS.Maps
local recallfunc = AVMS.Func
tbl.options = maps
tbl.results = {}
tbl.votes = table.Count(AVMS.Votes)
tbl.voters = AVMS.Voters
for id,votearg in pairs(AVMS.Votes) do
if !tbl.results[votearg] then tbl.results[votearg] = 1 end
tbl.results[votearg] = tbl.results[votearg] + 1
end
pcall(recallfunc,tbl,maps)
AVMS.Votes = nil
AVMS.Currentmaps = nil
AVMS.Maps = nil
AVMS.Func = nil
AVMS.Voters = nil
timer.Remove("VoteMap")
umsg.Start("_closevote")
umsg.End()
table.Empty(Nominated)
table.Empty(RockTheVote)
end
local trys = 0
function AVMS.VoteFinished(t, maps)
local winner
local winnernum = 0
local resultsnum = table.Count(t.options)
local dontwanttochange = t.results[resultsnum] or 0 -- people who dont want to change the map
local wanttochange = t.voters - dontwanttochange
for id, numvotes in pairs( t.results ) do
if numvotes > winnernum then
winner = id
winnernum = numvotes
end
end
local function AdminAbortMap(ply, txt)
if string.find(txt, "!abort") != nil and ply:IsAdmin() then
timer.Remove("VoteMapTimer")
timer.Remove("AutoVoteMapMessage")
AutoMapVoteTime = extendtime
nextmap = nil
changingmap = nil
AVMS.UpdatePlayers()
MessageAll("Mapchange aborted!")
hook.Remove("PlayerSay", "VoteMapAbort")
end
end
local str
local time
local timerun = 0
local map
if not winner then
time = 50
if trys >= retry then
map = maps[math.random(1, #maps - 1)]
str = "No one voted, change map to "..map.." in 5 Minutes"
timer.Create("VoteMapTimer",time,1, function() game.ConsoleCommand("changelevel "..map.."\n") end)
hook.Add("PlayerSay", "VoteMapAbort", AdminAbortMap)
else
timer.Create("AutoVoteMap",300,1, AVMS.VoteNextMap )
trys = trys + 1
local left = retry - trys + 1
str = "No Votes "..left.." votes left."
end
elseif winner == resultsnum and doextend then
AutoMapVoteTime = extendtime
extendvotes = extendvotes + 1
str = "Map will be extended for "..extendtime.." Minutes ("..maxextend - extendvotes.." extends left)"
elseif wanttochange / t.votes < minvoteneed and doextend then
AutoMapVoteTime = extendtime
extendvotes = extendvotes + 1
str = "Not enough people want to change. Extend map for "..extendtime.." Minutes ("..maxextend - extendvotes.." extends left)"
else
time = 5
local winnermap = t.options[winner]
map = winnermap
str = "Next map is "..map..". Changemap in 5 Minutes. Admin write !abort to abort the mapchange."
timer.Create("VoteMapTimer",time,1, function() game.ConsoleCommand("changelevel "..winnermap.."\n") end)
hook.Add("PlayerSay", "VoteMapAbort", AdminAbortMap)
end
if map then
changingmap = CurTime() + time
timer.Create("AutoVoteMapMessage", 1,0, function()
if !changingmap then timer.Remove("AutoVoteMapMessage"); timer.Remove("VoteMapTimer") return end
local count = math.Round(changingmap - CurTime())
if count == 60 then
MessageAll( "Change to "..map.." in 1 minute" )
elseif count < 60 and string.find(count, 0) and count != 0 then
MessageAll( "Change to "..map.." in "..count.." seconds" )
elseif count <= 5 then
MessageAll( "Change map in "..count.." seconds" )
end
end)
else
nextmap = nil
changingmap = nil
end
if str then
MessageAll( str )
Msg( str .. "\n" )
end
nextmap = map
AVMS.UpdatePlayers()
end
local function PlayerOnServer(id)
for k,v in pairs(player.GetAll()) do
if v:UniqueID() == id then return true end
end
return false
end
local function GetValidMap(str)
if !str then return false end
for k,v in pairs(NextMapTable) do
if v and string.find(string.lower(v),string.lower(str)) then return string.lower(v) end
end
return false
end
function AVMS.VoteNextMap(extend)
local maps = {}
local num
local current = game.GetMap()
local max = #NextMapTable
LastVote = CurTime()
if max <= 0 then print("No map to vote") return end
for k,v in pairs(Nominated) do
if PlayerOnServer(k) then
if !table.HasValue(maps,v) then
table.insert(maps,v)
end
end
end
if max <= minvotes then
for i = 1, max do
if #maps < minvotes and NextMapTable[i] != current and !table.HasValue(maps, NextMapTable[i]) then
table.insert(maps, NextMapTable[i])
end
end
else
while #maps < minvotes do
num = math.random(1, max)
if !table.HasValue(maps, NextMapTable[num]) and NextMapTable[num] != current then
table.insert(maps, NextMapTable[num])
end
end
end
if extendvotes >= maxextend and maxextend > -1 and !extend then
doextend = false
else
table.insert(maps, "Extend for "..extendtime.." Minutes")
end
local str = "Mapvote started"
Msg( str .. "\n" )
AVMS.StartVote(maps,"Vote for next map",30,AVMS.VoteFinished)
end
if file.Exists("mapcycle.txt") then
local maps = file.Read("mapcycle.txt")
local mapcycle = string.Explode("\n", maps)
for k,map in pairs(mapcycle) do
map = string.Trim(map)
AVMS.AddNextMap(_, _, { map,false })
end
print("// Mapcycle Loaded //")
else
print("// No mapcycle found //")
end
timer.Create("AutoVoteMapTimer",1, 0, function()
if CurTime() - LastVote > AutoMapVoteTime * 60 then
AVMS.VoteNextMap()
end
end)
concommand.Add("admin_startmapvote",function(ply,cmd,args)
if ValidEntity(ply) and !ply:IsAdmin() then return end
local extend = tobool(args[1]) or false
AVMS.VoteNextMap(extend)
end)
concommand.Add("admin_setextend",function(ply,cmd,args)
if ValidEntity(ply) and !ply:IsAdmin() then return end
if !args[1] then return end
local num = tonumber(args[1])
maxextend = num
extendvotes = 0
AVMS.UpdatePlayers()
end)
timer.Create("UpdatePlayerClocks",10,0,AVMS.UpdatePlayers)
hook.Add("PlayerSay", "NominateOrRockTheVote", function(ply,txt)
if !ValidEntity(ply) then return end
txt = string.lower(txt)
local texttbl = string.Explode(" ",txt)
local id = ply:UniqueID()
if texttbl[1] == "!nominate" then
local map = GetValidMap(texttbl[2])
if !map then
ply:ChatPrint("Map not valid!\nValid maps are listed in the Console")
for k,v in pairs(NextMapTable) do
ply:PrintMessage(HUD_PRINTCONSOLE,v)
end
return
end
Nominated[id] = map
ply:ChatPrint("Nominated map: "..map)
elseif texttbl[1] == "!rtv" or texttbl[1] == "!rockthevote" then
if AVMS.Votes then return end
if !table.HasValue(RockTheVote,id) then
table.insert(RockTheVote,id)
end
if (table.Count(RockTheVote) / #player.GetAll()) >= rocksneeded then
AVMS.VoteNextMap()
else
local have,need = table.Count(RockTheVote), math.Round(#player.GetAll() * rocksneeded)
ply:ChatPrint(have.." / "..need.." voted for a mapchange.")
end
end
end)
timer.Create("Advertise",300,0,MessageAll," TTT Non-fretta Map voting ssytem")
--Add Server Tag and keep the old one
local _tagstart = CurTime()
hook.Add("Think","AddNewTag",function()
local oldtags = GetConVarString("sv_tags")
if !oldtags and CurTime() - _tagstart >= 10 then return end
RunConsoleCommand("sv_tags",oldtags..",mapvote")
hook.Remove("Think","AddNewTag")
end)