// sh_func.lua
// Houses the most important functions server-side
function Announcement(text, time, player)
local rf = RecipientFilter()
rf:AddAllPlayers()
rf = player or rf
umsg.Start("Announcement", rf)
umsg.Long(time)
umsg.Long(table.getn(text))
for k, v in pairs(text) do
umsg.String(v)
end
umsg.End()
end
function SyncTime()
local rf = RecipientFilter()
rf:AddAllPlayers()
umsg.Start("timercountdown", rf)
umsg.Long(gb_RoundTimer)
umsg.End()
//im planning on adding more to this...
end
function StopClientTime()
local rf = RecipientFilter()
rf:AddAllPlayers()
umsg.Start("timercountdownstop", rf)
umsg.End()
end
function SurvivalTime()
for k, v in pairs(player.GetAll()) do
if (v:GetNetworkedEntity("gb_core"):IsValid()) then
v:SetVar("gb_time", gb_FightTime - gb_RoundTimer)
end
end
end
function ChangeRound(round)
gb_CurrentRound = round
local rf = RecipientFilter()
rf:AddAllPlayers()
umsg.Start("changeround", rf)
umsg.Long(round)
umsg.End()
SyncTime()
end
function NoUndo( player, command, args )
player:PrintMessage( HUD_PRINTTALK, "Sorry, but undo is disabled during the fight round." )
end
function StartFight()
gb_RoundTimer = gb_FightTime
ChangeRound(2)
// Put everyone in spectator mode
local allplayers = player.GetAll()
for k, v in pairs(allplayers) do
// Put them into spectator mode
local cam = v:GetNetworkedEntity("gb_cam")
if(cam:IsValid()) then
v:Spectate( OBS_MODE_CHASE )
v:SpectateEntity(cam)
v:StripWeapons()
v:SetNetworkedBool("spectating", true)
else
v:Spectate( OBS_MODE_ROAMING )
v:StripWeapons()
v:SetNetworkedBool("spectating", false)
end
end
// Teleport all the robots into the arena
robotspawns = ents.FindByClass("info_robot")
local UsedProps = {}
for k, v in pairs(allplayers) do
local core = v:GetNetworkedEntity("gb_core")
if(core:IsValid()) then
if (#robotspawns <= 0) then break end //no more spawns...
local randomspawn = math.random(#robotspawns)
local spawnent = table.remove(robotspawns, randomspawn)
local spawnpos = spawnent:GetPos()
local corepos = core:GetPos()
table.insert(UsedProps, core)
table.insert(UsedProps, core:GetTable().DamageProp)
local const = constraint.GetAllConstrainedEntities(core:GetTable().DamageProp)
for _, Ent in pairs(const) do
local phys1 = Ent:GetPhysicsObject()
if (phys1 && phys1:IsValid()) then
phys1:EnableMotion( true )
phys1:Wake()
phys1:ApplyForceCenter( Vector( 0, 0, -1) )
end
Ent:SetPos((Ent:GetPos() - corepos + spawnpos))
table.insert(UsedProps, Ent)
end
core:GetTable().DamageProp:SetPos(spawnent:GetPos())
local phys = core:GetTable().DamageProp:GetPhysicsObject()
if phys and phys:IsValid() then
phys:EnableMotion( true )
phys:Wake()
phys:ApplyForceCenter( Vector( 0, 0, -1) )
end
table.remove(robotspawns, randomspawn)
end
end
//clean up scrap
/*for k, ent in pairs(ents.GetAll()) do
if ent:GetVar( "Founder" ) then
if !table.HasValue(UsedProps, ent) then
ent:Remove()
end
end
end*/
concommand.Add("undo", NoUndo )
concommand.Add("gmod_undo", NoUndo )
concommand.Add("gmod_undonum", NoUndo )
timer.Create("survival time", 1, 0, SurvivalTime)
timer.Create("checkcores", 1, 0, CheckCores)
end
function CheckCores()
if gb_CurrentRound != 2 then return end
if (gb_NumBlueCores <= 0 || gb_NumRedCores <= 0) then
GameOver()
end
end
VoteSkipInfo = {}
function VoteSkip( ply, command, args )
if (VoteSkipInfo == "vetoed") then
ply:PrintMessage( HUD_PRINTTALK, "Voteskip has been vetoed for this round." )
return
end
if (gb_CurrentRound != 1) then
ply:PrintMessage( HUD_PRINTTALK, "You may only voteskip the build round." )
return
end
if !table.HasValue(VoteSkipInfo, ply) then
table.insert(VoteSkipInfo, ply)
for k, v in pairs(VoteSkipInfo) do
if !v:IsPlayer() then
VoteSkipInfo[k] = nil
end
end
local percent = table.getn(VoteSkipInfo) / table.getn(player.GetAll())
local required = math.ceil(gb_VoteSkipPercent * table.getn(player.GetAll()))
local remaining = required - table.getn(VoteSkipInfo)
if (percent >= gb_VoteSkipPercent) then
Announcement({ply:Name().." has voted to skip the build round.", "Required "..required.." voteskips reached", "FIGHT!"}, 5)
StartFight()
else
Announcement({ply:Name().." has voted to skip the build round.", remaining.." more votes needed"}, 5)
end
end
end
concommand.Add("gb_voteskip", VoteSkip )
function Changethemap()
maps = {}
maps[1] = gb_24arena
maps[2] = gb_conflagration
maps[3] = gb_battle_arena_v2
randint = math.random( 1, 3)
roundint = math.round( randint )
game.ConsoleCommand("changelevel "..tostring(maps[roundint])..."/n")
end
function GameOver(winteam)
ChangeRound(3)
local winmsg
if winteam then //override win
if winteam == 0 then
winmsg = "It's a tie!"
elseif winteam == 1 then
winmsg = "Red team wins!"
elseif winteam == 2 then
winmsg = "Blue team wins!"
end
else //normal win
if gb_NumRedCores > gb_NumBlueCores then
// Red team wins!
winteam = 1
winmsg = "Red team wins!"
elseif gb_NumRedCores < gb_NumBlueCores then
// Blue team wins!
winteam = 2
winmsg = "Blue team wins!"
elseif gb_NumRedCores == gb_NumBlueCores then
// It was a tie! D:
winteam = 0
winmsg = "It's a tie!"
end
end
local times = {}
for k, v in pairs(player.GetAll()) do
table.insert(times, {v, v:GetVar("gb_time", 0)})
end
local new_times = {}
for i=1, table.getn(times) do
local longest = {0,0,0}
for k, v in pairs(times) do
if (v[2] > longest[2] || longest[1] == 0) then
longest = {v[1], v[2], k}
end
end
if (longest[2] != 0) then
table.insert(new_times, {longest[1], longest[2]})
end
table.remove(times, longest[3])
end
local time_count = table.getn(new_times)
if time_count > 10 then
time_count = 10
end
local healths = {}
for k, v in pairs(player.GetAll()) do
if (v:GetVar("gb_time", 0) > 0) then
table.insert(healths, {v, v:GetNetworkedInt("gb_corehealth", 0)})
end
end
local new_healths = {}
for i=1, table.getn(healths) do
local longest = {0,0,0}
for k, v in pairs(healths) do
if (v[2] > longest[2] || longest[1] == 0) then
longest = {v[1], v[2], k}
end
end
//if (longest[2] != 0) then
table.insert(new_healths, {longest[1], longest[2]})
//end
table.remove(healths, longest[3])
end
local health_count = table.getn(new_healths)
if health_count > 10 then
health_count = 10
end
local damages = {}
for k, v in pairs(player.GetAll()) do
if (v:GetVar("gb_time", 0) > 0) then
table.insert(damages, {v, v:GetVar("DamageDelt", 0)})
end
end
local new_damages = {}
for i=1, table.getn(damages) do
local longest = {0,0,0}
for k, v in pairs(damages) do
if (v[2] > longest[2] || longest[1] == 0) then
longest = {v[1], v[2], k}
end
end
//if (longest[2] != 0) then
table.insert(new_damages, {longest[1], longest[2]})
//end
table.remove(damages, longest[3])
end
local damage_count = table.getn(new_damages)
if damage_count > 20 then
damage_count = 20
end
local wincolor = team.GetColor(winteam)
if (winteam == 0) then
wincolor = Color(128, 128, 128, 255)
end
local rf = RecipientFilter()
rf:AddAllPlayers()
umsg.Start("PostGame", rf)
umsg.Short(time_count)
for i=1, time_count do
umsg.Entity(new_times[i][1])
umsg.Short(new_times[i][2])
end
umsg.Short(health_count)
for i=1, health_count do
umsg.Entity(new_healths[i][1])
umsg.Short(new_healths[i][2])
end
umsg.Short(damage_count)
for i=1, damage_count do
umsg.Entity(new_damages[i][1])
umsg.Short(new_damages[i][2])
end
umsg.Short(wincolor.r)
umsg.Short(wincolor.g)
umsg.Short(wincolor.b)
umsg.String(winmsg)
umsg.End()
timer.Simple(gb_PostGameTime, Changethemap)
timer.Remove("RoundTimer")
StopClientTime()
timer.Remove("survival time")
timer.Remove("checkcores")
end
function TimerCountdown()
gb_RoundTimer = gb_RoundTimer - 1
//announcements and sudden death
if gb_CurrentRound == 1 then
if gb_RoundTimer == 10*60 then
Announcement({"Ten minutes remaining."}, 5)
elseif gb_RoundTimer == 5*60 then
Announcement({"Five minutes remaining."}, 5)
elseif gb_RoundTimer == 1*60 then
Announcement({"One minute remaining!"}, 5)
elseif gb_RoundTimer == 30 then
Announcement({"30 seconds remaining!"}, 5)
elseif gb_RoundTimer == 10 then
Announcement({"10 seconds remaining!"}, 5)
elseif gb_RoundTimer == 5 then
Announcement({"5..."}, 2)
elseif gb_RoundTimer == 4 then
Announcement({"4..."}, 2)
elseif gb_RoundTimer == 3 then
Announcement({"3..."}, 2)
elseif gb_RoundTimer == 2 then
Announcement({"2..."}, 2)
elseif gb_RoundTimer == 1 then
Announcement({"1..."}, 2)
end
elseif gb_CurrentRound == 2 then
if gb_RoundTimer == 10*60 then
Announcement({"Ten minutes remaining."}, 5)
elseif gb_RoundTimer == 5*60 then
Announcement({"Five minutes remaining."}, 5)
elseif gb_RoundTimer == 1*60 then
if gb_SuddenDeath then
Announcement({ "One minute remaining!", "Sudden Death is now ON" }, 5)
for k, ent in pairs(ents.FindByClass("prop_physics")) do
if ent:IsValid() then
ent:Fire("physdamagescale", tostring(gb_SuddenDeathPropDamageScale))
end
end
else
Announcement({"One minute remaining!"}, 5)
end
elseif gb_RoundTimer == 30 then
Announcement({"30 seconds remaining!"}, 5)
elseif gb_RoundTimer == 10 then
Announcement({"10 seconds remaining!"}, 5)
elseif gb_RoundTimer == 5 then
Announcement({"5..."}, 2)
elseif gb_RoundTimer == 4 then
Announcement({"4..."}, 2)
elseif gb_RoundTimer == 3 then
Announcement({"3..."}, 2)
elseif gb_RoundTimer == 2 then
Announcement({"2..."}, 2)
elseif gb_RoundTimer == 1 then
Announcement({"1..."}, 2)
end
end
if gb_RoundTimer <= 0 then
if gb_CurrentRound == 1 then
Announcement({"FIGHT!"}, 5)
StartFight()
elseif gb_CurrentRound == 2 then
GameOver()
end
end