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)