Skip to content

Commit

Permalink
allow role avoiding, role RNG optimized
Browse files Browse the repository at this point in the history
  • Loading branch information
EntranceJew committed Dec 18, 2023
1 parent b3d5fad commit 5e549e3
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 39 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel
- Moved reset buttons onto the left (by @a7f3)
- Added ammo icons to the weapon switch HUD and player status HUD elements (by @EntranceJew)
- Changed the disguiser icon to be more fitting (by @TimGoll)
- Role selection RNG improvements (by @EntranceJew):
- Uses `Player:CanSelectRole()` now instead of duplicating logic.
- Option for server to disregard player role selection preferences.
- Players can choose to avoid Traitor, in addition to the other base classes.

### Fixed

Expand Down
22 changes: 16 additions & 6 deletions gamemodes/terrortown/gamemode/server/sv_player_ext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -759,13 +759,23 @@ end
-- @return boolean
-- @realm server
function plymeta:CanSelectRole(roleData, choice_count, role_count)
local min_karmas = ConVarExists("ttt_" .. roleData.name .. "_karma_min") and GetConVar("ttt_" .. roleData.name .. "_karma_min"):GetInt() or 0
-- if there aren't enough players anymore to have a greater role variety
if choice_count <= role_count then return true end

return (
choice_count <= role_count
or self:GetBaseKarma() > min_karmas and GAMEMODE.LastRole[self:SteamID64()] == ROLE_INNOCENT
or math.random(3) == 2
) and (choice_count <= role_count or not self:GetAvoidRole(roleData.index))
-- and the player doesn't avoid this role
local allowRoleAvoiding = GetConVar("ttt2_roles_allow_avoiding"):GetBool()
if allowRoleAvoiding and self:GetAvoidRole(roleData.index) then return false end

-- or the player has enough karma
local minKarmaCVar = GetConVar("ttt_" .. roleData.name .. "_karma_min")
local minKarma = minKarmaCVar and minKarmaCVar:GetInt() or 0
if KARMA.cv.enabled:GetBool() and self:GetBaseKarma() > minKarma then return true end

-- or if the randomness decides
local trickleRate = roleselection.trickleDownRate
if trickleRate > 0 and math.random(trickleRate) == 1 then return true end

return false
end

---
Expand Down
56 changes: 24 additions & 32 deletions gamemodes/terrortown/gamemode/server/sv_roleselection.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ roleselection.finalRoles = {}
roleselection.selectableRoles = nil
roleselection.baseroleLayers = {}
roleselection.subroleLayers = {}
roleselection.trickleDownRate = 0

-- Convars
roleselection.cv = {
Expand All @@ -33,7 +34,7 @@ roleselection.cv = {

---
-- @realm server
ttt_max_baseroles_pct = CreateConVar("ttt_max_baseroles_pct", "0", {FCVAR_NOTIFY, FCVAR_ARCHIVE}, "Maximum amount of different baseroles based on player amount. ttt_max_baseroles needs to be 0")
ttt_max_baseroles_pct = CreateConVar("ttt_max_baseroles_pct", "0", {FCVAR_NOTIFY, FCVAR_ARCHIVE}, "Maximum amount of different baseroles based on player amount. ttt_max_baseroles needs to be 0"),
}

-- saving and loading
Expand Down Expand Up @@ -572,10 +573,14 @@ local function SetSubRoles(plys, availableRoles, selectableRoles, selectedForced
local plysAmount = #plys
local availableRolesAmount = #availableRoles
local tmpSelectableRoles = table.Copy(selectableRoles)
-- plys are already shuffled, continue with existing priority
local newPlys = table.Copy(plys)

while plysAmount > 0 and availableRolesAmount > 0 do
local pick = math.random(plysAmount)
local ply = plys[pick]
for i = #newPlys, 1, -1 do
if not (plysAmount > 0 and availableRolesAmount > 0) then
break
end
local ply = plys[i]

local rolePick = math.random(availableRolesAmount)
local subrole = availableRoles[rolePick]
Expand All @@ -586,16 +591,8 @@ local function SetSubRoles(plys, availableRoles, selectableRoles, selectedForced
roleCount = roleCount - selectedForcedRoles[subrole]
end

local minKarmaCVar = GetConVar("ttt_" .. roleData.name .. "_karma_min")
local minKarma = minKarmaCVar and minKarmaCVar:GetInt() or 0

-- give this player the role if
if plysAmount <= roleCount -- or there aren't enough players anymore to have a greater role variety
or ply:GetBaseKarma() > minKarma -- or the player has enough karma
and not ply:GetAvoidRole(subrole) -- and the player doesn't avoid this role
or math.random(3) == 2 -- or if the randomness decides
then
table.remove(plys, pick)
if ply:CanSelectRole(roleData, plysAmount, availableRolesAmount) then
table.remove(newPlys, i)

roleselection.finalRoles[ply] = subrole

Expand Down Expand Up @@ -782,30 +779,22 @@ end
local function SelectBaseRolePlayers(plys, subrole, roleAmount)
local curRoles = 0
local plysList = {}
local roleData = roles.GetByIndex(subrole)

local minKarmaCVar = GetConVar("ttt_" .. roles.GetByIndex(subrole).name .. "_karma_min")
local min_karmas = minKarmaCVar and minKarmaCVar:GetInt() or 0

while curRoles < roleAmount and #plys > 0 do
-- select random index in plys table
local pick = math.random(#plys)

for i = #plys, 1, -1 do
-- the player we consider
local ply = plys[pick]

-- give this player the role if
if subrole == ROLE_INNOCENT -- this role is an innocent role
or #plys <= roleAmount -- or there aren't enough players anymore to have a greater role variety
or ply:GetBaseKarma() > min_karmas -- or the player has enough karma
and not ply:GetAvoidRole(subrole) -- and the player doesn't avoid this role
or math.random(3) == 2 -- or if the randomness decides
then
table.remove(plys, pick)
local ply = plys[i]
-- do not unbrace this
if not (curRoles < roleAmount and #plys > 0) then break end

if subrole == ROLE_INNOCENT or ply:CanSelectRole(roleData, #plys, roleAmount) then
curRoles = curRoles + 1
plysList[curRoles] = ply

roleselection.finalRoles[ply] = subrole -- give the player the final baserole (maybe he will receive his subrole later)
-- give the player the final baserole (maybe he will receive his subrole later)
roleselection.finalRoles[ply] = subrole

table.remove(plys, i)
end
end

Expand All @@ -826,6 +815,9 @@ function roleselection.SelectRoles(plys, maxPlys)

plys = roleselection.GetSelectablePlayers(plys or player.GetAll())

-- Randomize role assignment by shuffling the list early.
table.Shuffle(plys)

maxPlys = maxPlys or #plys

if maxPlys < 2 then return end -- we don't need to select anything if there is just one player
Expand Down
4 changes: 4 additions & 0 deletions gamemodes/terrortown/gamemode/shared/sh_rolelayering.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

rolelayering = {}

---
-- @realm shared
CreateConVar("ttt2_roles_allow_avoiding", "1", {FCVAR_NOTIFY, FCVAR_ARCHIVE, FCVAR_REPLICATED}, "If enabled, players will be allowed to avoid specific roles.")

local function SendLayerData(layerTable)
local layerTableSize = #layerTable

Expand Down
6 changes: 5 additions & 1 deletion lua/terrortown/entities/roles/traitor/shared.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,13 @@ function ROLE:PreInitialize()
pct = 0.4,
maximum = 32,
minPlayers = 1,

traitorButton = 1,

credits = 2,
creditsAwardDeadEnable = 1,
creditsAwardKillEnable = 1
creditsAwardKillEnable = 1,

togglable = true
}
end
5 changes: 5 additions & 0 deletions lua/terrortown/lang/en.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2074,6 +2074,11 @@ L.label_keyhelper_ammo_drop = "drop ammo from selected weapon out of clip"
-- 2023-11-18
L.entity_pickup_owner_only = "Only the owner can pick this up"

-- 2023-11-20
L.help_ttt_role_avoid_disabled = "WARNING! Role avoidance is disabled on this server, but you can still change your settings here."
L.label_roles_allow_avoiding = "Allow Avoiding Roles"
L.help_roles_allow_avoiding = "If enabled, allows players to opt out of specific roles from within the Avoid Role Selection menu."

-- 2023-12-18
L.body_confirm_one = "{finder} confirmed the death of {victim}."
L.body_confirm_more = "{finder} confirmed the {count} deaths of: {victims}."
9 changes: 9 additions & 0 deletions lua/terrortown/menus/gamemode/administration/roles.lua
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@ function CLGAMEMODESUBMENU:Populate(parent)
master = masterEnb
})

form:MakeHelp({
label = "help_roles_allow_avoiding"
})

form:MakeCheckBox({
serverConvar = "ttt2_roles_allow_avoiding",
label = "label_roles_allow_avoiding"
})

local form2 = vgui.CreateTTT2Form(parent, "header_roles_reward_credits")

form2:MakeHelp({
Expand Down
7 changes: 7 additions & 0 deletions lua/terrortown/menus/gamemode/gameplay/avoidroles.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ CLGAMEMODESUBMENU.title = "submenu_gameplay_avoidroles_title"
function CLGAMEMODESUBMENU:Populate(parent)
local form = vgui.CreateTTT2Form(parent, "header_roleselection")

if GetConVar("ttt2_roles_allow_avoiding"):GetBool() then
form:MakeHelp({
label = "help_ttt_role_avoid_disabled"
})
end


local roles = roles.GetList()

for i = 1, #roles do
Expand Down

0 comments on commit 5e549e3

Please sign in to comment.