From 8facb41acf1405dcb0b20a6ff28eea78a64f7b86 Mon Sep 17 00:00:00 2001 From: Fesiug Date: Sun, 15 Sep 2024 18:18:31 -0400 Subject: [PATCH] Domination flag progress, teams, gamestate, --- .../benny/entities/entities/benny_domflag.lua | 103 +++++++----- gamemodes/benny/gamemode/gamestate.lua | 112 ++++++++++++- gamemodes/benny/gamemode/hud.lua | 153 ++++++++++-------- gamemodes/benny/gamemode/player.lua | 6 +- gamemodes/benny/gamemode/teams.lua | 32 +++- 5 files changed, 294 insertions(+), 112 deletions(-) diff --git a/gamemodes/benny/entities/entities/benny_domflag.lua b/gamemodes/benny/entities/entities/benny_domflag.lua index be07658..70b8e0f 100644 --- a/gamemodes/benny/entities/entities/benny_domflag.lua +++ b/gamemodes/benny/entities/entities/benny_domflag.lua @@ -32,64 +32,85 @@ function ENT:SetupDataTables() self:NetworkVar( "Int", "TeamOwned" ) end --- indev: --- 0 - unassigned --- 1 - me --- 2 - my enemeis - function ENT:Think() if CLIENT then return end - local onthis = 0 + + local Contested = false + local TeamOnPoint = nil + local amtOnPoint = 0 for ply, edata in pairs(self.Memory) do if edata.time+0.1 < CurTime() then --self.Memory[ply] = nil continue end - onthis = onthis + 1 + amtOnPoint = amtOnPoint + 1 + if !TeamOnPoint then + TeamOnPoint = ply:Team() + elseif TeamOnPoint != ply:Team() then + Contested = true + end end - if onthis > 0 then -- Someones capturing - if self:GetCapturePercent() != 1 and self:GetTeamOwned() != 1 then -- if its not full progress - local COLLECTED = (1/(6-onthis)) * FrameTime() - self:SetCapturePercent( math.Approach( self:GetCapturePercent(), 1, COLLECTED ) ) - self:SetTeamTaking( 1 ) + if amtOnPoint > 0 then + -- People on point - if self:GetCapturePercent() == 1 then - self:SetTeamOwned( self:GetTeamTaking() ) - self:SetTeamTaking( 0 ) - self:SetCapturePercent( 0 ) - end + if Contested then + -- Point is currently contested + else + if self:GetTeamOwned() == 0 and self:GetTeamTaking() != TeamOnPoint then + -- Clearing a neutral point + local COLLECTED = (1/math.max( 1, 6-amtOnPoint )) * FrameTime() + self:SetCapturePercent( math.Approach( self:GetCapturePercent(), 0, COLLECTED ) ) + + if self:GetCapturePercent() == 0 then + -- Point successfully cleared + self:SetTeamTaking( TeamOnPoint ) + self:EmitSound("buttons/button9.wav", 70, 100, 1) + end + elseif self:GetTeamOwned() != TeamOnPoint then + -- Enemy or early bird taking this point + local COLLECTED = (1/math.max( 1, 6-amtOnPoint )) * FrameTime() + self:SetCapturePercent( math.Approach( self:GetCapturePercent(), 1, COLLECTED ) ) + self:SetTeamTaking( TeamOnPoint ) + + if self:GetCapturePercent() == 1 then + -- Point successfully captured! + self:SetTeamOwned( TeamOnPoint ) + self:SetTeamTaking( 0 ) + self:SetCapturePercent( 0 ) + self:EmitSound("buttons/blip1.wav", 70, 100, 1) + end + elseif self:GetTeamOwned() == TeamOnPoint then + -- Team that owns the point is on the point + + if self:GetCapturePercent() > 0 then + -- There's progress on it, revert it + local COLLECTED = (1/math.max( 1, 6-amtOnPoint )) * FrameTime() + self:SetCapturePercent( math.Approach( self:GetCapturePercent(), 0, COLLECTED ) ) + + if self:GetCapturePercent() == 0 then + -- Point successfully cleared + self:SetTeamTaking( 0 ) + self:EmitSound("buttons/button10.wav", 70, 100, 1) + end - -- rewards - for ply, edata in pairs(self.Memory) do - edata.xpcollected = (edata.xpcollected or 0) + (COLLECTED * 200) - local sap = math.floor(edata.xpcollected) - if sap >= 1 then - edata.xpcollected = edata.xpcollected - sap - ply:RewardXP( sap ) end end - end self.LastCaptureTime = CurTime() - elseif (self.LastCaptureTime or 0)+3 < CurTime() and self:GetTeamOwned() != 2 then - self:SetTeamTaking( 2 ) - self:SetCapturePercent( math.Approach( self:GetCapturePercent(), 1, (1/5) * FrameTime() ) ) - - if self:GetCapturePercent() == 1 then - self:SetTeamOwned( self:GetTeamTaking() ) - self:SetTeamTaking( 0 ) - self:SetCapturePercent( 0 ) - end - elseif (self.LastCaptureTime or 0)+3 < CurTime() and self:GetCapturePercent() > 0 and false then - self:SetCapturePercent( math.Approach( self:GetCapturePercent(), 0, (1/10) * FrameTime() ) ) - - if self:GetCapturePercent() == 0 then - self:SetTeamTaking( 0 ) - self:SetCapturePercent( 0 ) - end end + + -- rewards + --for ply, edata in pairs(self.Memory) do + -- edata.xpcollected = (edata.xpcollected or 0) + (COLLECTED * 200) + -- local sap = math.floor(edata.xpcollected) + -- if sap >= 1 then + -- edata.xpcollected = edata.xpcollected - sap + -- ply:RewardXP( sap ) + -- end + --end + local per = self:GetCapturePercent() self:NextThink( CurTime()-1 ) diff --git a/gamemodes/benny/gamemode/gamestate.lua b/gamemodes/benny/gamemode/gamestate.lua index 0b2da05..3c57511 100644 --- a/gamemodes/benny/gamemode/gamestate.lua +++ b/gamemodes/benny/gamemode/gamestate.lua @@ -1,12 +1,16 @@ -BennyGame = {} +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", 2, nil, "MP:\n0 - TDM\n1 - FFA\n2 - Domination\n3 - CTF\n4 - Bomb\n5 - Hardpoint\n6 - Demolition") + + function BennyGame:GetType() - return BG_GTYPE_MP + return cGametype:GetBool() and BG_GTYPE_MP or BG_GTYPE_CAMPAIGN end BennyGame.TeamsInPlay = { @@ -38,4 +42,108 @@ hook.Add("InitPostEntity", "Benny_InitPostEntity", function() -- local mapscript = "benny_maps/" .. game.GetMap() .. "_initpostentity.lua" -- AddCSLuaFile(mapscript) -- include(mapscript) +end) + +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( "TeamsSwapped", "Bool", false ) +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 + end + + if roundstate == BG_STATE_PRE then + -- Pregame + + elseif roundstate == BG_STATE_POST then + -- Postgame + + elseif roundstate == BG_STATE_ACTIVE then + -- Active round + + if (BennyGame:GetRoundStartedAt()) <= CurTime() then + -- Round time expired + end + end + + + end + end end) \ No newline at end of file diff --git a/gamemodes/benny/gamemode/hud.lua b/gamemodes/benny/gamemode/hud.lua index b95538c..48957a4 100644 --- a/gamemodes/benny/gamemode/hud.lua +++ b/gamemodes/benny/gamemode/hud.lua @@ -182,11 +182,6 @@ local CURRCHAR = "mp_arng" local COLOR_MAIN = FACTIONS[CURRCHAR].COLOR_MAIN local COLOR_DARK = FACTIONS[CURRCHAR].COLOR_DARK local CHARNAME = FACTIONS[CURRCHAR].CHARNAME - -local E_CURRCHAR = "mp_plasof" -local E_COLOR_MAIN = FACTIONS[E_CURRCHAR].COLOR_MAIN -local E_COLOR_DARK = FACTIONS[E_CURRCHAR].COLOR_DARK -local E_CHARNAME = FACTIONS[E_CURRCHAR].CHARNAME local COLOR_BRIGHT = Color( 94, 94, 94 ) local show_letters = { @@ -306,15 +301,17 @@ function GM:HUDPaint() local handler = p:HandlerCheck() stack = util.Stack() - local CURRCHAR = TEAMS[p:Team()].factionid + local myteam = p:Team() + local CURRCHAR + if BennyGame:GetType() == BG_GTYPE_CAMPAIGN then + CURRCHAR = "benny" + else + CURRCHAR = TEAMS[myteam].factionid + end local COLOR_MAIN = FACTIONS[CURRCHAR].COLOR_MAIN local COLOR_DARK = FACTIONS[CURRCHAR].COLOR_DARK local CHARNAME = FACTIONS[CURRCHAR].CHARNAME - local E_CURRCHAR = TEAMS[4].factionid - local E_COLOR_MAIN = FACTIONS[E_CURRCHAR].COLOR_MAIN - local E_COLOR_DARK = FACTIONS[E_CURRCHAR].COLOR_DARK - local E_CHARNAME = FACTIONS[E_CURRCHAR].CHARNAME local MP = BennyGame:GetType() == BG_GTYPE_MP @@ -488,26 +485,6 @@ function GM:HUDPaint() S_Pop() end - --S_Push( 0 + 1 + GAP, 0 ) - -- QuickDrawBar( BARWIDE, BARTALL, E_CURRCHAR, true ) - --S_Pop() - - --S_Push( -BARWIDE - 1 - GAP, BARTALL+2+16+2 ) - -- QuickDrawBar( BARWIDE, BARTALL, "mp_arng" ) - --S_Pop() - - --S_Push( 0 + 1 + GAP, BARTALL+2+16+2 ) - -- QuickDrawBar( BARWIDE, BARTALL, "mp_militia", true ) - --S_Pop() - - --S_Push( -BARWIDE - 1 - GAP, (BARTALL+2+16+2)*2 ) - -- QuickDrawBar( BARWIDE, BARTALL, "mp_plasof" ) - --S_Pop() - - --S_Push( 0 + 1 + GAP, (BARTALL+2+16+2)*2 ) - -- QuickDrawBar( BARWIDE, BARTALL, "mp_viper", true ) - --S_Pop() - -- Timer local DISPLAYWIDE, DISPLAYTALL = 150, 48 S_Push( -DISPLAYWIDE/2, 0 ) @@ -517,31 +494,35 @@ function GM:HUDPaint() hORect( 2, 2, DISPLAYWIDE-4, DISPLAYTALL-4, 1 ) local d1, d2 - local tt = string.FormattedTime( math.max( ROUNDEND-CurTime(), 0 ) ) - if tt.m > 0 then - d1 = string.format( "%01i:%02i", tt.m, tt.s ) - d2 = false--tt.s - if tt.h > 0 then - d1 = tt.h .. ":" .. d1 + if BennyGame:GetState() == BG_STATE_ACTIVE then + local tt = string.FormattedTime( math.max( ROUNDEND-CurTime(), 0 ) ) + if tt.m > 0 then + d1 = string.format( "%01i:%02i", tt.m, tt.s ) + d2 = false--tt.s + if tt.h > 0 then + d1 = tt.h .. ":" .. d1 + end + else + d1 = string.format( "%02i", tt.s ) + d2 = string.format( ".%02i", tt.ms ) end - else - d1 = string.format( "%02i", tt.s ) - d2 = string.format( ".%02i", tt.ms ) end - surface.SetFont("HUD_48") - local twid = surface.GetTextSize(d1) - if d2 then - surface.SetFont("HUD_36") - twid = twid + surface.GetTextSize(".00") - end + if d1 then + surface.SetFont("HUD_48") + local twid = surface.GetTextSize(d1) + if d2 then + surface.SetFont("HUD_36") + twid = twid + surface.GetTextSize(".00") + end - local x, y = hXY( DISPLAYWIDE/2 + 0 - twid/2, 4 ) - draw.SimpleText( d1, "HUD_48", x, y, COLOR_MAIN ) - local twid2 = surface.GetTextSize(d1) - if d2 then - local x, y = hXY( DISPLAYWIDE/2 + twid2 - twid/2, 11 ) - draw.SimpleText( d2, "HUD_36", x, y, COLOR_MAIN ) + local x, y = hXY( DISPLAYWIDE/2 + 0 - twid/2, 4 ) + draw.SimpleText( d1, "HUD_48", x, y, COLOR_MAIN ) + local twid2 = surface.GetTextSize(d1) + if d2 then + local x, y = hXY( DISPLAYWIDE/2 + twid2 - twid/2, 11 ) + draw.SimpleText( d2, "HUD_36", x, y, COLOR_MAIN ) + end end if false then @@ -585,10 +566,10 @@ function GM:HUDPaint() for i, ent in ipairs( AllFlags ) do--for i=1, count do local o = i-1 - local faction_name = (ent:GetTeamOwned()==2 and E_CURRCHAR or ent:GetTeamOwned()==1 and CURRCHAR or "unassigned") + local faction_name = TEAMS[ent:GetTeamOwned()].factionid local faction_info = FACTIONS[faction_name] - local taking_faction_name = (ent:GetTeamTaking()==2 and E_CURRCHAR or ent:GetTeamTaking()==1 and CURRCHAR or "unassigned") + local taking_faction_name = TEAMS[ent:GetTeamTaking()].factionid local taking_faction_info = FACTIONS[taking_faction_name] local capturepercent = ent:GetCapturePercent()--math.Remap( CurTime()%4, 0, 3, 0, 1 ) @@ -630,21 +611,59 @@ function GM:HUDPaint() local obj = p:GetTouchedObjective() if obj:IsValid() then S_Push( 0, 200 ) - local BWIDE, BTALL = 180, 16 - local x, y = hXY( -BWIDE/2, -2 ) - qt( "CAPTURING", "HUD_24", x, y, COLOR_MAIN, TEXT_ALIGN_LEFT, nil, COLOR_DARK ) - local x, y = hXY( -BWIDE/2, 36 ) - qt( "POINT " .. (alphabet[ AllFlagFlip[obj] ] or AllFlagFlip[obj]), "HUD_24", x, y, COLOR_MAIN, TEXT_ALIGN_LEFT, nil, COLOR_DARK ) - local x, y = hXY( BWIDE/2, 32 ) - qt( math.floor(obj:GetCapturePercent()*100) .. "%", "HUD_36", x, y, COLOR_MAIN, TEXT_ALIGN_RIGHT, nil, COLOR_DARK ) + + local TITLE = "CAPTURING" + local PERCENT = obj:GetCapturePercent() + if obj:GetTeamOwned() == myteam then + if obj:GetCapturePercent() > 0 then + TITLE = "CLEARING" + else + TITLE = "SECURE" + PERCENT = 1 + end + elseif obj:GetTeamOwned() == 0 and obj:GetTeamTaking() != myteam then + TITLE = "CLEARING" + end - S_Push( -BWIDE/2, 18 ) - hCol( COLOR_DARK ) - hRect( 0, 0, 180, BTALL ) - hCol( COLOR_MAIN ) - hORect( 1, 1, 180-2, BTALL-2 ) - hRect( 3, 3, math.floor((BWIDE-6) * obj:GetCapturePercent()), BTALL-6 ) - S_Pop() + local BARCOLOR_MAIN = TEAMS[obj:GetTeamOwned()].factionid + BARCOLOR_MAIN = FACTIONS[BARCOLOR_MAIN].COLOR_MAIN + local BARCOLOR_DARK = TEAMS[obj:GetTeamOwned()].factionid + BARCOLOR_DARK = FACTIONS[BARCOLOR_DARK].COLOR_DARK + + local TAKCOLOR_MAIN = TEAMS[obj:GetTeamTaking()].factionid + TAKCOLOR_MAIN = FACTIONS[TAKCOLOR_MAIN].COLOR_MAIN + local TAKCOLOR_DARK = TEAMS[obj:GetTeamTaking()].factionid + TAKCOLOR_DARK = FACTIONS[TAKCOLOR_DARK].COLOR_DARK + + local BWIDE, BTALL = 180, 16 + + hCol( BARCOLOR_DARK ) + hRect( -80, 0, 160, 38 ) + hCol( BARCOLOR_DARK ) + hRect( -100, 35, 200, 76 ) + hCol( BARCOLOR_MAIN ) + hORect( -100+1, 35+1, 200-2, 76-2 ) + hCol( BARCOLOR_MAIN ) + hORect( -80+1, 1, 160-2, 38-2, 1 ) + local x, y = hXY( 0, 4 ) + qt( "POINT " .. (alphabet[ AllFlagFlip[obj] ] or AllFlagFlip[obj]), "HUD_36", x, y, BARCOLOR_MAIN, TEXT_ALIGN_CENTER, nil, BARCOLOR_DARK ) + + + local x, y = hXY( 0, TITLE=="SECURE" and 62 or 40 ) + qt( TITLE, "HUD_24", x, y, COLOR_MAIN, TEXT_ALIGN_CENTER, nil, COLOR_DARK ) + + if TITLE!="SECURE" then + S_Push( -BWIDE/2, 62 ) + hCol( COLOR_DARK ) + hRect( 0, 0, 180, BTALL ) + hCol( COLOR_MAIN ) + hORect( 1, 1, 180-2, BTALL-2 ) + hCol( TITLE=="CLEARING" and TAKCOLOR_MAIN or COLOR_MAIN ) + hRect( 3, 3, math.floor((BWIDE-6) * PERCENT), BTALL-6 ) + S_Pop() + local x, y = hXY( 0, 78 ) + qt( math.floor(PERCENT*100) .. "%", "HUD_36", x, y, COLOR_MAIN, TEXT_ALIGN_CENTER, nil, COLOR_DARK ) + end S_Pop() end end diff --git a/gamemodes/benny/gamemode/player.lua b/gamemodes/benny/gamemode/player.lua index 1f3d533..887d593 100644 --- a/gamemodes/benny/gamemode/player.lua +++ b/gamemodes/benny/gamemode/player.lua @@ -4,7 +4,11 @@ --------------------- function GM:PlayerInitialSpawn( ply, transiton ) - ply:SetTeam( 1 ) + if BennyGame:GetType() == BG_GTYPE_MP then + ply:SetTeam( BennyGame:BestAutoJoinTeam() ) + else + ply:SetTeam( 7 ) + end end function GM:PlayerSpawn( ply ) diff --git a/gamemodes/benny/gamemode/teams.lua b/gamemodes/benny/gamemode/teams.lua index 366d4a1..acd3eff 100644 --- a/gamemodes/benny/gamemode/teams.lua +++ b/gamemodes/benny/gamemode/teams.lua @@ -3,10 +3,23 @@ concommand.Add("b-cheat_setteam", function( ply, cmd, args ) if !ply or !ply:IsValid() then return end - ply:SetTeam( args[1] ) + if !args[1] then + print( "Needs an integer." ) + for index, data in ipairs( TEAMS ) do + print( index .. " - " .. data.id ) + end + else + ply:SetTeam( args[1] ) + end end) TEAMS = { + [0] = { + name = "unassigned", + description = "unassigned", + factionid = "unassigned", + id = "UNASSIGNED", + }, { name = "#Team.cia.Name", description = "#Team.cia.Description", @@ -61,6 +74,7 @@ TEAMS_IDtoTeam = { } TEAMS_FIDtoTeam = { + [TEAMS[0].factionid] = TEAMS[0], [TEAMS[1].factionid] = TEAMS[1], [TEAMS[2].factionid] = TEAMS[2], [TEAMS[3].factionid] = TEAMS[3], @@ -119,4 +133,20 @@ function GM:PlayerSelectTeamSpawn( TeamID, ply ) end return ChosenSpawnPoint +end + +function BennyGame:BestAutoJoinTeam() + local SmallestTeam = BennyGame.TeamToFaction[math.random( 1, BennyGame.TeamCount )] + local SmallestPlayers = 1000 + + for id, TeamInPlayID in pairs( BennyGame.TeamsInPlay ) do + if ( id != TEAM_SPECTATOR && id != TEAM_UNASSIGNED && id != TEAM_CONNECTING ) then + local PlayerCount = team.NumPlayers( id ) + if PlayerCount < SmallestPlayers or (PlayerCount == SmallestPlayers and id < SmallestTeam ) then + SmallestPlayers = PlayerCount + SmallestTeam = id + end + end + end + return SmallestTeam end \ No newline at end of file