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.RTeamID = table.Flip( BennyGame.TeamsInPlay ) 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)