Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9411ced
Added ability to adjust the Cannibal's eat and digestion poop sound v…
Malivil Jul 29, 2026
b31b4d3
Added website changes to another section of the PR tempalte
Malivil Jul 29, 2026
4664c6c
Added `TTTHUDInfoPositionOverride` hook
joel4848 Jul 30, 2026
db15281
Added convars for player info HUD offset and updated docs accordingly
joel4848 Jul 31, 2026
c2f715e
Added 'Beta Only' tag in hooks.html
joel4848 Jul 31, 2026
201a540
Ported "Optimize player spawn queue randomization in TTT" from base TTT
Malivil Jul 31, 2026
9a8b4f6
Merge branch 'dev' of https://github.com/Malivil/TTT-Custom-Roles int…
Malivil Jul 31, 2026
7528b9c
Removed magic numbers from `cl_help.lua`
joel4848 Jul 31, 2026
a3f920b
Renamed 'traitor' variables to 'role' for clarity, and removed magic …
joel4848 Jul 31, 2026
be25125
`TTTHUDInfoPositionOverride` now exposes the actual x/y pos and size …
joel4848 Jul 31, 2026
aecfc79
Updated docs to reflect change to `TTTHUDInfoPositionOverride`; made …
joel4848 Jul 31, 2026
a500960
`TTTHUDInfoPaint` now exposes `label_top` and `label_left` based on i…
joel4848 Aug 1, 2026
70e13b2
Radar and Disguiser now reposition based on info HUD position
joel4848 Aug 1, 2026
1439773
Update gamemodes/terrortown/gamemode/cl_hud.lua
joel4848 Aug 1, 2026
95672ec
Added parameters to `TTTHUDInfoPaint`; made requested changes
joel4848 Aug 1, 2026
a111c1d
Merge branch 'dev' of https://github.com/joel4848/TTT-Custom-Roles in…
joel4848 Aug 1, 2026
37dd0b5
Fixed players swallowed by the Cannibal still being able to trigger t…
Malivil Aug 4, 2026
2a87976
Fixed various roles erroring about unsupported hook 'TTTUpdateRoleState'
Malivil Aug 5, 2026
78218d0
Removed beta marking from release notes
Malivil Aug 5, 2026
37eee10
Added the new role that a player gets by being deputized by a Marshal…
Malivil Aug 6, 2026
f4fed1d
Added ability to control whether killing the Sponge ends the round (e…
Malivil Aug 6, 2026
db49897
Cleanup
Malivil Aug 6, 2026
9eea72b
Added SpecSpirits script for people who want to see spectator spirit …
Malivil Aug 7, 2026
210fe89
Fixed default color
Malivil Aug 7, 2026
ab1b542
Merge pull request #968 from Malivil/dev
Malivil Aug 8, 2026
709f69f
Merge branch 'dev' into dev
Malivil Aug 8, 2026
156fe3f
Merge pull request #969 from joel4848/dev
Malivil Aug 8, 2026
6ad1e37
Updated release date
Malivil Aug 8, 2026
d678046
Merge pull request #970 from Custom-Roles-for-TTT/dev
Malivil Aug 8, 2026
6a5dd26
Fixed Cannibal's "Swallowed" label not staying with the info panel wh…
Malivil Aug 8, 2026
59f0a15
Merge pull request #971 from Malivil/dev
Malivil Aug 8, 2026
d08c6b4
Merge pull request #972 from Custom-Roles-for-TTT/dev
Malivil Aug 8, 2026
63cfda1
Cleanup
Malivil Aug 8, 2026
7d4b73b
Removed beta-only markings
Malivil Aug 9, 2026
2591e87
Merge branch 'Custom-Roles-for-TTT:dev' into dev
Malivil Aug 9, 2026
77fd6f7
Merge pull request #973 from Malivil/dev
Malivil Aug 9, 2026
69b47f1
Merge pull request #974 from Custom-Roles-for-TTT/dev
Malivil Aug 9, 2026
ef8ef45
Merge branch 'release' into beta
Malivil Aug 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
- [ ] ConVars added to ULX list
- [ ] `plymeta:IsRoleAbilityDisabled` used
- Otherwise:
- [ ] CONVARS.md updated, if applicable
- [ ] Documentation
- [ ] CONVARS.md
- [ ] Website (changes marked with "beta only" notation if applicable)
- [ ] ULX updated (either added to list of convars for a role, or PR created in [ULX](https://github.com/Custom-Roles-for-TTT/TTT-Custom-Roles-ULX) repo \[Add link below\])
17 changes: 16 additions & 1 deletion API/HOOKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ Called when someone uses a fake cure on a player.\
*Parameters:*
- *ply* - The target player who is being "cured"

### TTTHUDInfoPaint(client, labelX, labelY, activeLabels)
### TTTHUDInfoPaint(client, labelX, labelY, activeLabels, x, y)
Called after player information such as role, health, and ammo and equipment information such as radar cooldown and disguiser activation are drawn on the screen. Used to write additional persistent text on the screen for player reference.\
*Realm:* Client\
*Added in:* 1.3.1\
Expand All @@ -328,6 +328,21 @@ Called after player information such as role, health, and ammo and equipment inf
- *labelX* - The X value representing the correct indentation from the left side of the screen to add information
- *labelY* - The Y value representing the first clear space to add information
- *activeLabels* - The list of current active additional labels. Used to determine the labelY offset to use via: `labelY = labelY + (20 * #activeLabels)`. Be sure to insert an entry when you add your own label so other addons can space appropriately. *(Added in 1.6.11)*
- *x* - The X value representing the left edge of the player information HUD *(Added in 2.5.2)*
- *y* - The Y value representing the top edge of the player information HUD *(Added in 2.5.2)*

### TTTHUDInfoPositionOverride(client, x, y, width, height)
Allows overriding the position of the player information HUD (role, health, ammo etc.).\
*Realm:* Client\
*Added in:* 2.5.2\
*Parameters:*
- *client* - The local player
- *x* - The X position value of the top left corner of the element
- *y* - The Y position value of the top left corner of the element
- *width* - The element's width
- *height* - The element's height

*Return:* The new x and y positions for the element (e.g. `return newX, newY`)

### TTTHUDRoleColorOverride(client, colorType)
Allows overriding the color to use in place of the given player's normal role color.\
Expand Down
7 changes: 7 additions & 0 deletions CONVARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,8 @@ ttt_sponge_device_for_beggar 0 // Whether the Beggar sho
ttt_sponge_device_for_beggar_heal 0 // Whether the Beggar should be fully healed when using the spongifier
ttt_sponge_device_for_bodysnatcher 0 // Whether the Bodysnatcher should get the spongifier
ttt_sponge_device_for_bodysnatcher_heal 0 // Whether the Bodysnatcher be fully healed when using the spongifier
ttt_sponge_device_for_cannibal 0 // Whether the Cannibal should get the spongifier
ttt_sponge_device_for_cannibal_heal 0 // Whether the Cannibal should be fully healed when using the spongifier
ttt_sponge_device_for_clown 0 // Whether the Clown should get the spongifier
ttt_sponge_device_for_clown_heal 0 // Whether the Clown should be fully healed when using the spongifier
ttt_sponge_device_for_cupid 0 // Whether the Cupid should get the spongifier
Expand All @@ -754,6 +756,7 @@ ttt_sponge_device_for_shadow 0 // Whether the Shadow sho
ttt_sponge_device_for_shadow_heal 0 // Whether the Shadow should be fully healed when using the spongifier (only created and used when "ttt_shadow_is_jester" is enabled)
ttt_sponge_device_for_swapper 0 // Whether the Swapper should get the spongifier
ttt_sponge_device_for_swapper_heal 0 // Whether the Swapper should be fully healed when using the spongifier
ttt_sponge_win_ends_round 1 // Whether the round should end when the Sponge wins

// Guesser
ttt_guesser_can_guess_detectives 0 // Whether the Guesser is allowed to guess detectives
Expand All @@ -775,6 +778,7 @@ ttt_cannibal_notify_killer 1 // Whether to notify a Ca
ttt_cannibal_notify_sound 0 // Whether to play a cheering sound when a Cannibal is killed
ttt_cannibal_notify_confetti 0 // Whether to throw confetti when a Cannibal is a killed
ttt_cannibal_eat_cooldown 10 // The amount of time (in seconds) between uses of the Cannibal's Cannibalizer
ttt_cannibal_eat_sound_level 100 // The sound level (volume) to play the Cannibal's eat sound (set to 0 to disable)
ttt_cannibal_damage_penalty 0 // The fraction a Cannibal's damage will be scaled by when they are attacking (Only applies if ttt_cannibal_is_independent is enabled)
ttt_cannibal_can_see_jesters 0 // Whether jesters are revealed (via head icons, color/icon on the scoreboard, etc.) to the Cannibal (Only applies if ttt_cannibal_is_independent is enabled)
ttt_cannibal_update_scoreboard 0 // Whether the Cannibal shows dead players as missing in action (Only applies if ttt_cannibal_is_independent is enabled)
Expand All @@ -784,6 +788,7 @@ ttt_cannibal_digestion 0 // Whether the Cannibal d
ttt_cannibal_digestion_time 30 // How long in seconds a victim takes to be digested when eaten. Set to 0 for immediate digestion (Only applies if ttt_cannibal_digestion is enabled)
ttt_cannibal_digestion_poop 1 // Whether the Cannibal drops poop when a victim is digested (Only applies if ttt_cannibal_digestion is enabled)
ttt_cannibal_digestion_poop_sound 1 // Whether the Cannibal causes a sound when poop is dropped from a digested victim (Only applies if ttt_cannibal_digestion is enabled)
ttt_cannibal_digestion_poop_sound_level 100 // The sound level (volume) to play the Cannibal's digestion poop sound (set to 0 to disable). (Only applies if ttt_cannibal_digestion is enabled)

// ----------------------------------------

Expand Down Expand Up @@ -1419,6 +1424,8 @@ ttt_tracker_minimap_offset_y 14 // The screen offset from
// Misc.
// ----------------------------------------
ttt_distance_unit 1 // What unit to use when displaying distance. 0 - None (Source). 1 - Meters. 2 - Feet
ttt_infohud_offset_x 0 // The X (horizontal) offset of the player information HUD element
ttt_infohud_offset_y 0 // The Y (vertical) offset of the player information HUD element
```

## Role Weapon Shop
Expand Down
20 changes: 20 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Release Notes

## 2.5.2
**Released: August 8th, 2026**

### Additions
- Added the new role that a player gets by being deputized by a Marshal to the event log message
- Added ability to control whether killing the Sponge ends the round (enabled by default)
- Added ability to adjust the Cannibal's eat and digestion poop sound volumes
- Added `ttt_infohud_offset_x` and `ttt_infohud_offset_y` client convars to allow players to reposition the player information HUD (role, health, ammo etc.)

### Changes
- Ported "Optimize player spawn queue randomization in TTT" from base TTT

### Fixes
- Fixed players swallowed by the Cannibal still being able to trigger traitor traps
- Fixed various roles erroring about unsupported hook 'TTTUpdateRoleState'

### Developer
- Added `TTTHUDInfoPositionOverride` hook to override the position of the player information HUD (role, health, ammo etc.)
- Added new `x` and `y` parameters to `TTTHUDInfoPaint` hook which provide the raw position of the player information HUD (i.e. agnostic of any existing labels)

## 2.5.1
**Released: July 25th, 2026**

Expand Down
20 changes: 20 additions & 0 deletions docs/api/hooks.html
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,28 @@ <h3><a id="ttthudinfopaintclient-labelx-labely-activelabels" href="#ttthudinfopa
<li><em>labelX</em> - The X value representing the correct indentation from the left side of the screen to add information</li>
<li><em>labelY</em> - The Y value representing the first clear space to add information</li>
<li><em>activeLabels</em> - The list of current active additional labels. Used to determine the labelY offset to use via: <code>labelY = labelY + (20 * #activeLabels)</code>. Be sure to insert an entry when you add your own label so other addons can space appropriately. <em>(Added in 1.6.11)</em></li>
<li><em>x</em> - The X value representing the left edge of the player information HUD <em>(Added in 2.5.2)</em></li>
<li><em>y</em> - The Y value representing the top edge of the player information HUD <em>(Added in 2.5.2)</em></li>
</ul>

<h3><a id="ttthudinfopositionoverrideclient-x-y-width-height" href="#ttthudinfopositionoverrideclient-x-y-width-height">TTTHUDInfoPositionOverride(client, x, y, width, height)</a></h3>
<p>
Allows overriding the position of the player information HUD (role, health, ammo etc.).<br>
<em>Realm:</em> Client<br>
<em>Added in:</em> 2.5.2<br>
<em>Parameters:</em>
</p>
<ul>
<li><em>client</em> - The local player</li>
<li><em>x</em> - The X position value of the top left corner of the element</li>
<li><em>y</em> - The Y position value of the top left corner of the element</li>
<li><em>width</em> - The element's width</li>
<li><em>height</em> - The element's height</li>
</ul>
<p>
<em>Return:</em> The new x and y positions for the element (e.g. <code>return newX, newY</code>)
</p>

<h3><a id="ttthudrolecoloroverrideclient-colortype" href="#ttthudrolecoloroverrideclient-colortype">TTTHUDRoleColorOverride(client, colorType)</a></h3>
<p>
Allows overriding the color to use in place of the given player's normal role color.<br>
Expand Down
18 changes: 18 additions & 0 deletions docs/teams/jester.html
Original file line number Diff line number Diff line change
Expand Up @@ -600,12 +600,24 @@ <h3 style="margin: 10px 0; padding: 0;">Role Configuration:</h3>
<td>Boolean</td>
<td>Whether the Cannibal causes a sound when poop is dropped from a digested victim. <i>(Requires <code>ttt_cannibal_digestion</code> to be enabled.)</i></td>
</tr>
<tr>
<td>ttt_cannibal_digestion_poop_sound_level</td>
<td>100</td>
<td>Integer</td>
<td>The sound level (volume) to play the Cannibal's digestion poop sound (set to 0 to disable). <i>(Requires <code>ttt_cannibal_digestion</code> to be enabled.)</i></td>
</tr>
<tr>
<td>ttt_cannibal_eat_cooldown</td>
<td>10</td>
<td>Integer</td>
<td>The amount of time in seconds between uses of the Cannibal's Cannibalizer.</td>
</tr>
<tr>
<td>ttt_cannibal_eat_sound_level</td>
<td>100</td>
<td>Integer</td>
<td>The sound level (volume) to play the Cannibal's eat sound (set to 0 to disable).</td>
</tr>
<tr>
<td>ttt_cannibal_gains_health</td>
<td>0</td>
Expand Down Expand Up @@ -1205,6 +1217,12 @@ <h3 style="margin: 10px 0; padding: 0;">Role Configuration:</h3>
<td>Boolean</td>
<td>Whether a specific jester role should be fully healed when using the spongifier. Replace * with the name of the jester role you want to configure without spaces or capital letters.</td>
</tr>
<tr>
<td>ttt_sponge_win_ends_round</td>
<td>1</td>
<td>Boolean</td>
<td>Whether the round should end when the Sponge wins.</td>
</tr>
</tbody>
</table>
<p>A list of ConVars shared by every role and instructions for using ConVars can be found on the <a href="../tutorials/configuring_convars.html">Configuring ConVars</a> tutorial page.</p>
Expand Down
14 changes: 10 additions & 4 deletions gamemodes/terrortown/entities/weapons/weapon_can_eater.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ SWEP.DigestionConVar = CreateConVar("ttt_cannibal_digestion", "0", FCVAR_REPLICA
SWEP.DigestionTimeConVar = CreateConVar("ttt_cannibal_digestion_time", "30", FCVAR_REPLICATED, "How long in seconds a victim takes to be digested when eaten (set to 0 for immediate digestion)", 0, 300)

if SERVER then
SWEP.EatSoundLevelConVar = CreateConVar("ttt_cannibal_eat_sound_level", "100", FCVAR_NONE, "The sound level (volume) to play the Cannibal's eat sound (set to 0 to disable)", 0, 511)
SWEP.DigestionPoopConVar = CreateConVar("ttt_cannibal_digestion_poop", "1", FCVAR_NONE, "Whether the Cannibal drops poop when a victim is digested", 0, 1)
SWEP.DigestionPoopSoundConVar = CreateConVar("ttt_cannibal_digestion_poop_sound", "1", FCVAR_NONE, "Whether the Cannibal causes a sound when poop is dropped from a digested victim.", 0, 1)
SWEP.DigestionPoopSoundConVar = CreateConVar("ttt_cannibal_digestion_poop_sound", "1", FCVAR_NONE, "Whether the Cannibal causes a sound when poop is dropped from a digested victim", 0, 1)
SWEP.DigestionPoopSoundLevelConVar = CreateConVar("ttt_cannibal_digestion_poop_sound_level", "100", FCVAR_NONE, "The sound level (volume) to play the Cannibal's digestion poop sound (set to 0 to disable)", 0, 511)
end

local eatSounds = {
Expand Down Expand Up @@ -148,7 +150,10 @@ function SWEP:PrimaryAttack()
hitEnt:SetProperty("TTTCannibalEaten", owner:SteamID64())
hitEnt:QueueMessage(MSG_PRINTBOTH, "You have been eaten by " .. owner:Nick() .. "!")

owner:EmitSound(eatSounds[math.random(1, #eatSounds)], 100)
local soundLevel = self.EatSoundLevelConVar:GetInt()
if soundLevel > 0 then
owner:EmitSound(eatSounds[math.random(1, #eatSounds)], soundLevel)
end

local cooldown = self.DeviceCooldownConVar:GetInt()
if cooldown > 0 then
Expand Down Expand Up @@ -214,8 +219,9 @@ function SWEP:PrimaryAttack()
poop:SetCollisionGroup(COLLISION_GROUP_WEAPON)
poop.fingerprints = fingerprints

if self.DigestionPoopSoundConVar:GetBool()then
owner:EmitSound(poopSounds[math.random(#poopSounds)], 100)
soundLevel = self.DigestionPoopSoundLevelConVar:GetInt()
if self.DigestionPoopSoundConVar:GetBool() and soundLevel > 0 then
owner:EmitSound(poopSounds[math.random(#poopSounds)], soundLevel)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ SWEP.Secondary.Delay = 1
SWEP.IsGrenade = false

SWEP.Kind = WEAPON_MELEE
SWEP.WeaponID = AMMO_CROWBAR

SWEP.NoSights = true
SWEP.IsSilent = true
Expand Down
1 change: 0 additions & 1 deletion gamemodes/terrortown/entities/weapons/weapon_kil_knife.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ SWEP.Secondary.Ammo = "none"
SWEP.Secondary.Delay = 12

SWEP.Kind = WEAPON_NONE
SWEP.WeaponID = AMMO_CROWBAR

SWEP.IsSilent = true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ SWEP.Secondary.Delay = 1.0
SWEP.Kind = WEAPON_EQUIP
SWEP.CanBuy = { ROLE_QUACK }
SWEP.LimitedStock = true
SWEP.WeaponID = AMMO_HEALTHSTATION

SWEP.AllowDrop = false
SWEP.NoSights = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ SWEP.Category = WEAPON_CATEGORY_ROLE
SWEP.CanBuy = { ROLE_QUACK }
-- This is special equipment
SWEP.Kind = WEAPON_EQUIP2
SWEP.WeaponID = AMMO_STATIONBOMB

SWEP.BlockShopRandomization = true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ SWEP.Kind = WEAPON_ROLE
SWEP.CanBuy = {} -- only traitors can buy
SWEP.LimitedStock = true -- only buyable once
SWEP.AllowDrop = false
SWEP.WeaponID = AMMO_FLARE

SWEP.Tracer = "AR2Tracer"

Expand Down
31 changes: 22 additions & 9 deletions gamemodes/terrortown/gamemode/cl_disguise.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ function DISGUISE.CreateMenu(parent)
local owned = LocalPlayer():HasEquipmentItem(EQUIP_DISGUISE)

if not owned then
dform:Help(T("disg_not_owned"))
return dform
dform:Help(T("disg_not_owned"))
return dform
end

local dcheck = vgui.Create("DCheckBoxLabel", dform)
dcheck:SetText(T("disg_enable"))
dcheck:SetIndent(5)
dcheck:SetValue(LocalPlayer():GetNWBool("disguised", false))
dcheck.OnChange = function(s, val)
RunConsoleCommand("ttt_set_disguise", val and "1" or "0")
end
RunConsoleCommand("ttt_set_disguise", val and "1" or "0")
end
dform:AddItem(dcheck)

dform:Help(T("disg_help1"))
Expand All @@ -37,6 +37,23 @@ function DISGUISE.CreateMenu(parent)
return dform
end

local labelX = 0
local labelY = 0

function DISGUISE.Bought(is_item, id)
if is_item and id == EQUIP_DISGUISE then
hook.Add("TTTHUDInfoPaint", "DisguiseLabelPos", function(client, label_left, label_top, _)
labelX = label_left
labelY = ScrH() - label_top + 20

if not client:HasEquipmentItem(EQUIP_DISGUISE) then
hook.Remove("TTTHUDInfoPaint", "DisguiseLabelPos")
end
end)
end
end
hook.Add("TTTBoughtItem", "DisguiseBoughtItem", DISGUISE.Bought)

function DISGUISE.Draw(client)
if (not client) or not client:HasEquipmentItem(EQUIP_DISGUISE) then return end
if not client:GetNWBool("disguised", false) then return end
Expand All @@ -47,11 +64,7 @@ function DISGUISE.Draw(client)
local text = T("disg_hud")
local _, h = surface.GetTextSize(text)

local label_top = 140
if client:HasEquipmentItem(EQUIP_RADAR) then
label_top = label_top + 20
end
surface.SetTextPos(36, ScrH() - label_top - h)
surface.SetTextPos(labelX, labelY - h)
surface.DrawText(text)
end

Expand Down
6 changes: 6 additions & 0 deletions gamemodes/terrortown/gamemode/cl_help.lua
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,12 @@ function HELPSCRN:CreateConfig(dsettings)
cb = dgui:CheckBox(GetTranslation("set_hide_ammo"), "ttt_hide_ammo")
cb:SetTooltip(GetTranslation("set_hide_ammo_tip"))

cb = dgui:NumSlider(GetTranslation("set_infohud_offset_x"), "ttt_infohud_offset_x", 0, GetConVar("ttt_infohud_offset_x"):GetMax(), 0)
cb:SetTooltip(GetTranslation("set_infohud_offset_x_tip"))

cb = dgui:NumSlider(GetTranslation("set_infohud_offset_y"), "ttt_infohud_offset_y", 0, GetConVar("ttt_infohud_offset_y"):GetMax(), 0)
cb:SetTooltip(GetTranslation("set_infohud_offset_y_tip"))

cb = dgui:TextEntry(GetTranslation("set_radio_button"), "ttt_radio_button")
cb:SetTooltip(GetTranslation("set_radio_button_tip"))

Expand Down
Loading
Loading