Benny/gamemodes/benny/gamemode/gamestate.lua

387 lines
10 KiB
Lua

BennyGame = BennyGame or {}
BG_GTYPE_CAMPAIGN = 0
BG_GTYPE_MP = 1
local cGametype = CreateConVar("b-gametype", 1, nil, "0 for Campaign, 1 for MP")
local cGamemode = CreateConVar("b-gamemode", "dom", nil, "")
local cMinplayers = CreateConVar("b-g_minplayers", 2)
local cPregame = CreateConVar("b-g_pregame", 15)
local cPostgame = CreateConVar("b-g_postgame", 15)
local cIntermission = CreateConVar("b-g_intermission", 10)
function BennyGame:GetType()
return cGametype:GetBool() and BG_GTYPE_MP or BG_GTYPE_CAMPAIGN
end
function BennyGame:GetMode()
return cGamemode:GetString()
end
function BennyGame:GetModeData()
return BennyGame.Gamemodes[ BennyGame:GetMode() ]
end
BennyGame.TeamsInPlay = {
4,
3,
--2,
--1,
--5,
--6,
}
BennyGame.TeamCount = #BennyGame.TeamsInPlay
BennyGame.Gamemodes = {
["free"] = {
name = "#Gamemode.free.Name",
description = "#Gamemode.free.Description",
},
["tdm"] = {
name = "#Gamemode.tdm.Name",
description = "#Gamemode.tdm.Description",
scorelimit = CreateConVar("b-g_tdm_scorelimit", 75 ),
timelimit = CreateConVar("b-g_tdm_timelimit", 10*60 ),
},
["ffa"] = {
name = "#Gamemode.ffa.Name",
description = "#Gamemode.ffa.Description",
scorelimit = CreateConVar("b-g_ffa_scorelimit", 30 ),
timelimit = CreateConVar("b-g_ffa_timelimit", 10*60 ),
},
["snd"] = {
name = "#Gamemode.snd.Name",
description = "#Gamemode.snd.Description",
scorelimit = CreateConVar("b-g_snd_scorelimit", 6 ),
timelimit = CreateConVar("b-g_snd_timelimit", 2.5*60 ),
},
["ctf"] = {
name = "#Gamemode.ctf.Name",
description = "#Gamemode.ctf.Description",
scorelimit = CreateConVar("b-g_ctf_scorelimit", 3 ),
timelimit = CreateConVar("b-g_ctf_timelimit", 10*60 ),
},
["dom"] = {
name = "#Gamemode.dom.Name",
description = "#Gamemode.dom.Description",
scorelimit = CreateConVar("b-g_dom_scorelimit", 1000 ),
timelimit = CreateConVar("b-g_dom_timelimit", 10*60 ),
roundlimit = CreateConVar("b-g_dom_roundlimit", 1 ),
},
["dem"] = {
name = "#Gamemode.dem.Name",
description = "#Gamemode.dem.Description",
scorelimit = CreateConVar("b-g_dem_scorelimit", 3 ),
timelimit = CreateConVar("b-g_dem_timelimit", 5*60 ),
roundlimit = CreateConVar("b-g_dom_roundlimit", 2 ),
},
["hp"] = {
name = "#Gamemode.hp.Name",
description = "#Gamemode.hp.Description",
scorelimit = CreateConVar("b-g_hp_scorelimit", 300 ),
timelimit = CreateConVar("b-g_hp_timelimit", 10*60 ),
},
}
local thetypes = {
"Float",
"Int",
"Bool",
"Entity",
}
function BennyGame:Accessor( name, typey, default )
local World = game.GetWorld()
if typey == "Float" then
BennyGame["Get" .. name] = function( self )
return World:GetNW2Float( name, default )
end
BennyGame["Set" .. name] = function( self, val )
World:SetNW2Float( name, val )
end
return
end
if typey == "Int" then
BennyGame["Get" .. name] = function( self )
return World:GetNW2Int( name, default )
end
BennyGame["Set" .. name] = function( self, val )
World:SetNW2Int( name, val )
end
return
end
if typey == "Bool" then
BennyGame["Get" .. name] = function( self )
return World:GetNW2Bool( name, default )
end
BennyGame["Set" .. name] = function( self, val )
World:SetNW2Bool( name, val )
end
return
end
if typey == "Entity" then
BennyGame["Get" .. name] = function( self )
return World:GetNW2Entity( name, default )
end
BennyGame["Set" .. name] = function( self, val )
World:SetNW2Entity( name, val )
end
return
end
end
BG_STATE_WAITINGFORPLAYERS = 0
BG_STATE_PRE = 1
BG_STATE_ACTIVE = 2
BG_STATE_POST = 3
hook.Add("InitPostEntity", "Benny_Gamestate_InitPostEntity", function()
BennyGame:Accessor( "RoundStartedAt", "Float", 0 )
BennyGame:Accessor( "PregameStartedAt", "Float", 0 )
BennyGame:Accessor( "RoundFinishedAt", "Float", 0 )
BennyGame:Accessor( "State", "Int", 0 )
BennyGame:Accessor( "Round", "Int", 1 )
BennyGame:Accessor( "SwappedAtRound", "Int", 1 )
BennyGame:Accessor( "TimeExtension", "Int", 0 )
BennyGame:Accessor( "Team1_Score", "Int", 0 )
BennyGame:Accessor( "Team2_Score", "Int", 0 )
BennyGame:Accessor( "Team3_Score", "Int", 0 )
BennyGame:Accessor( "Team4_Score", "Int", 0 )
BennyGame:Accessor( "Team5_Score", "Int", 0 )
BennyGame:Accessor( "Team6_Score", "Int", 0 )
BennyGame:Accessor( "TeamsSwapped", "Bool", false )
end)
function BennyGame:GetScoreLimit()
if !BennyGame.Gamemodes[BennyGame:GetMode()].scorelimit then return false end
return BennyGame.Gamemodes[BennyGame:GetMode()].scorelimit:GetInt()
end
function BennyGame:GetTimeLimit()
if !BennyGame.Gamemodes[BennyGame:GetMode()].timelimit then return false end
return BennyGame.Gamemodes[BennyGame:GetMode()].timelimit:GetInt() + BennyGame:GetTimeExtension()
end
function BennyGame:GetRoundLimit()
if !BennyGame.Gamemodes[BennyGame:GetMode()].roundlimit then return false end
return BennyGame.Gamemodes[BennyGame:GetMode()].roundlimit:GetInt()
end
function BennyGame:GetPregameTime()
return cPregame:GetInt()
end
function BennyGame:GetPostgameTime()
return cPostgame:GetInt()
end
function BennyGame:GetIntermissionTime()
return cIntermission:GetInt()
end
function BennyGame:GetScoreForTeam( teamid )
return BennyGame["GetTeam" .. teamid .. "_Score"]( self )
end
function BennyGame:SetScoreForTeam( teamid, var )
return BennyGame["SetTeam" .. teamid .. "_Score"]( self, var )
end
function BennyGame:AddScoreForTeam( teamid, var )
if Nuke then return end
if BennyGame:GetState() != BG_STATE_ACTIVE then return end
self:SetScoreForTeam( teamid, self:GetScoreForTeam( teamid ) + (var or 1) )
if self:GetScoreForTeam( teamid ) >= BennyGame:GetScoreLimit() then
BennyGame:EndRound( BG_ER_SCORELIMIT, teamid )
end
end
BG_ER_TIMELIMIT = 0
BG_ER_SCORELIMIT = 1
BG_ER_NUKE = 2
BG_ER_FORCE = 3
function BennyGame:StartRound()
PrintMessage(HUD_PRINTCENTER, "Round start!")
BennyGame:SetState( BG_STATE_ACTIVE )
BennyGame:SetRoundStartedAt( CurTime() )
game.CleanUpMap()
for _, ply in player.Iterator() do
ply:Spawn()
end
end
function BennyGame:EndRound( reason, forceteam )
local winningteam = forceteam
BennyGame:SetState( BG_STATE_POST )
BennyGame:SetRoundFinishedAt( CurTime() )
if !winningteam then
-- who has the most score
local HighestScore, HighestTeam = 0, 0
for TeamID, RealTeamID in ipairs( BennyGame.TeamsInPlay ) do
local ThisScore = BennyGame:GetScoreForTeam( RealTeamID )
if HighestScore < ThisScore then
HighestScore = ThisScore
HighestTeam = RealTeamID
winningteam = HighestTeam
end
end
for TeamID, RealTeamID in ipairs( BennyGame.TeamsInPlay ) do
local ThisScore = BennyGame:GetScoreForTeam( RealTeamID )
if RealTeamID == HighestTeam then continue end
if HighestScore < ThisScore then
-- print("clearly there's been a failure", RealTeamID, ThisScore, HighestTeam, HighestScore)
elseif HighestScore == ThisScore then
-- print("this looks like a tie", RealTeamID, HighestTeam)
winningteam = 0
break
end
end
end
local TheFull = "["
TheFull = TheFull .. ((reason==0 and "TIME END!] ") or (reason==1 and "SCORE END!] ") or ("MISSING END!] "))
if winningteam == 0 then
TheFull = "It's a tie! "
else
TheFull = TheFull .. l8(TEAMS[winningteam].name) .. " wins! "
end
TheFull = TheFull .. cPostgame:GetInt() .. "s until the next round."
PrintMessage(HUD_PRINTCENTER, TheFull)
local roundtime = CurTime() - BennyGame:GetRoundStartedAt()
local rf = string.FormattedTime( 269 )
local nicely = ""
if rf.h > 0 then
nicely = nicely .. rf.h .. ":"
end
nicely = nicely .. string.format( "%02i:%02i.", rf.m, rf.s )
print( "That round lasted " .. nicely )
end
concommand.Add("b-cheat_scoreset", function( ply, cmd, args )
if !args[1] then
print( "Needs a team ID." )
for index, data in ipairs( TEAMS ) do
print( index .. " - " .. data.id )
end
elseif !args[2] then
print( "Needs an integer." )
else
BennyGame:SetScoreForTeam( TEAMS_IDorName( args[1] ), args[2] )
print( "Team " .. args[1] .. " score now " .. BennyGame:GetScoreForTeam( TEAMS_IDorName( args[1] ) ) )
end
end, function( cmd, args )
return BENNY.SimpleAutoComplete( cmd, args, TEAMS_IDs )
end )
concommand.Add("b-cheat_scoreadd", function( ply, cmd, args )
if !args[1] then
print( "Needs a team ID." )
for index, data in ipairs( TEAMS ) do
print( index .. " - " .. data.id )
end
else
BennyGame:AddScoreForTeam( TEAMS_IDorName( args[1] ), args[2] )
print( "Team " .. args[1] .. " score now " .. BennyGame:GetScoreForTeam( TEAMS_IDorName( args[1] ) ) )
end
end, function( cmd, args )
return BENNY.SimpleAutoComplete( cmd, args, TEAMS_IDs )
end )
concommand.Add("b-cheat_setstate", function( ply, cmd, args )
if !args[1] then
print( "Needs an integer 0 waiting for palyers 1 pre 2 active 3 post" )
else
BennyGame:SetState( args[1] )
end
end, function( cmd, args )
return BENNY.SimpleAutoComplete( cmd, args, TEAMS_IDs )
end )
concommand.Add("b-cheat_endround", function( ply, cmd, args )
BennyGame:EndRound( args[1] or BG_ER_FORCE, args[2] )
end, function( cmd, args )
return BENNY.SimpleAutoComplete( cmd, args, TEAMS_IDs )
end )
hook.Add("Think", "Benny_Gamestate_Think", function()
if SERVER then
local World = Entity(0)
if BennyGame:GetType() == BG_GTYPE_MP then
local roundstate = BennyGame:GetState()
if roundstate == BG_STATE_WAITINGFORPLAYERS then
-- Waiting for players
local count = 0
for index, ply in player.Iterator() do
if ply:Team() == TEAM_CONNECTING then continue end
if ply:Team() == TEAM_UNASSIGNED then continue end
if ply:Team() == TEAM_SPECTATOR then continue end
count = count + 1
end
if count >= cMinplayers:GetInt() then
roundstate = BG_STATE_PRE
BennyGame:SetState( roundstate )
BennyGame:SetPregameStartedAt( CurTime() )
PrintMessage(HUD_PRINTCENTER, "Pregame. " .. cPregame:GetInt() .. "s until the round starts")
end
end
if roundstate == BG_STATE_PRE then
-- Pregame
if BennyGame:GetPregameStartedAt() + BennyGame:GetPregameTime() <= CurTime() then
BennyGame:StartRound()
end
elseif roundstate == BG_STATE_POST then
-- Postgame
if BennyGame:GetRoundFinishedAt() + BennyGame:GetPostgameTime() <= CurTime() then
for TeamID, RealTeamID in ipairs( BennyGame.TeamsInPlay ) do
BennyGame:SetScoreForTeam( RealTeamID, 0 )
end
BennyGame:SetState( BG_STATE_WAITINGFORPLAYERS )
end
elseif roundstate == BG_STATE_ACTIVE then
-- Active round
if (BennyGame:GetRoundStartedAt()+BennyGame:GetTimeLimit()) <= CurTime() then
-- Round time expired
BennyGame:EndRound( BG_ER_TIMELIMIT )
end
end
end
end
end)