Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion CONVARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ ttt_cannibal_damage_penalty 0 // The fraction a Canniba
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)
ttt_cannibal_gains_health 0 // Whether the Cannibal gains their victim's health when eating them
ttt_cannibal_gained_health_percentage 100 // What percentage of their victim's health the Cannibal gains. Set to 0 to always gain a flat 100HP (Only applies if ttt_cannibal_gains_health is enabled)
ttt_cannibal_gained_health_percentage 15 // What percentage of their victim's health the Cannibal gains. Set to 0 to always gain a flat 100HP (Only applies if ttt_cannibal_gains_health is enabled)
ttt_cannibal_digestion 0 // Whether the Cannibal digests and permanently kills their victims over time
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)
Expand Down
6 changes: 4 additions & 2 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Release Notes

## 2.4.4 (Beta)
**Released:**
**Released: March 21st, 2026**

### Additions
- Added messages to existing twins when a player becomes a twin during an active round
- Added option to allow Cannibal to gain a configurable percentage of their victims' health (disabled by default) (Thanks Joel!)
- Added option to allow Cannibal to "digest" (permamnently kill) their victims a configurable amount of time after eating them (disabled by default) (Thanks Joel!)
- Added option to allow Cannibal to "digest" (permanently kill) their victims a configurable amount of time after eating them (disabled by default) (Thanks Joel!)
- Added option to allow Cannibal to drop a poop when a victim is fully digested, with or without an audible cue (enabled by default, but depends on digestion being enabled) (Thanks Joel!)

### Changes
Expand All @@ -20,6 +20,8 @@
- Fixed cheat sheet getting cut off when it exceeded the height of the screen and a role pack was enabled
- Fixed jester, detective, innocent, and traitor role rename ConVars not working
- Fixed error in Cannibal's role weapon HUD when weapon was selected from last round (Thanks Stig!)
- Fixed detective hats not hiding when the owning player was eaten by the Cannibal
- Ported "Add check for checking weapon GetHeadshotMultiplier"

### Developer
- Added `ROLE_STRINGS_DEFAULT` as a copy of `ROLE_STRINGS` from before role strings are changed by ConVars
Expand Down
34 changes: 32 additions & 2 deletions docs/teams/jester.html
Original file line number Diff line number Diff line change
Expand Up @@ -580,14 +580,44 @@ <h3 style="margin: 10px 0; padding: 0;">Role Configuration:</h3>
<td>ttt_cannibal_damage_penalty</td>
<td>0</td>
<td>Float</td>
<td>The fraction a Cannibal's damage will be scaled by when they are attacking. <i>(Requires <code>ttt_bodysnatcher_is_independent</code> to be enabled.)</i></td>
<td>The fraction a Cannibal's damage will be scaled by when they are attacking. <i>(Requires <code>ttt_cannibal_is_independent</code> to be enabled.)</i></td>
</tr>
<tr>
<td>ttt_cannibal_digestion <span data-text="Beta Only" class="betaonly betaicon tooltip">&nbsp;</span></td>
<td>0</td>
<td>Boolean</td>
<td>Whether the Cannibal digests and permanently kills their victims over time.</td>
</tr>
<tr>
<td>ttt_cannibal_digestion_poop <span data-text="Beta Only" class="betaonly betaicon tooltip">&nbsp;</span></td>
<td>1</td>
<td>Boolean</td>
<td>Whether the Cannibal drops poop when a victim is digested. <i>(Requires <code>ttt_cannibal_digestion</code> to be enabled.)</i></td>
</tr>
<tr>
<td>ttt_cannibal_digestion_poop_sound <span data-text="Beta Only" class="betaonly betaicon tooltip">&nbsp;</span></td>
<td>1</td>
<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_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_gains_health <span data-text="Beta Only" class="betaonly betaicon tooltip">&nbsp;</span></td>
<td>0</td>
<td>Boolean</td>
<td>Whether the Cannibal gains their victim's health when eating them.</td>
</tr>
<tr>
<td>ttt_cannibal_gained_health_percentage <span data-text="Beta Only" class="betaonly betaicon tooltip">&nbsp;</span></td>
<td>15</td>
<td>Integer</td>
<td>What percentage of their victim's health the Cannibal gains. Set to 0 to always gain a flat 100HP <i>(Requires <code>ttt_cannibal_gains_health</code> to be enabled.)</i></td>
</tr>
<tr>
<td>ttt_cannibal_is_independent</td>
<td>0</td>
Expand All @@ -598,7 +628,7 @@ <h3 style="margin: 10px 0; padding: 0;">Role Configuration:</h3>
<td>ttt_cannibal_update_scoreboard</td>
<td>0</td>
<td>Boolean</td>
<td>Whether the Cannibal shows dead players as missing in action. <i>(Requires <code>ttt_bodysnatcher_is_independent</code> to be enabled.)</i></td>
<td>Whether the Cannibal shows dead players as missing in action. <i>(Requires <code>ttt_cannibal_is_independent</code> to be enabled.)</i></td>
</tr>
</tbody>
</table>
Expand Down
33 changes: 17 additions & 16 deletions gamemodes/terrortown/entities/weapons/weapon_can_eater.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ SWEP.InLoadoutForDefault = {ROLE_CANNIBAL}

SWEP.DeviceCooldownConVar = CreateConVar("ttt_cannibal_eat_cooldown", "10", FCVAR_REPLICATED, "The amount of time (in seconds) between uses of the Cannibal's Cannibalizer", 0, 60)
SWEP.GainsHealthConVar = CreateConVar("ttt_cannibal_gains_health", "0", FCVAR_REPLICATED, "Whether the Cannibal gains their victim's health when eating them", 0, 1)
SWEP.GainedHealthPercentageConVar = CreateConVar("ttt_cannibal_gained_health_percentage", "100", FCVAR_REPLICATED, "What percentage of their victim's health the Cannibal gains (set to 0 to always gain a flat 100HP)", 0, 500)
SWEP.GainedHealthPercentageConVar = CreateConVar("ttt_cannibal_gained_health_percentage", "15", FCVAR_REPLICATED, "What percentage of their victim's health the Cannibal gains (set to 0 to always gain a flat 100HP)", 0, 500)
SWEP.DigestionConVar = CreateConVar("ttt_cannibal_digestion", "0", FCVAR_REPLICATED, "Whether the Cannibal digests and permanently kills their victims over time", 0, 1)
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)

Expand Down Expand Up @@ -124,6 +124,9 @@ function SWEP:PrimaryAttack()
hitEnt:SpectateEntity(owner)
hitEnt:DrawViewModel(false)
hitEnt:DrawWorldModel(false)
if IsValid(hitEnt.hat) then
hitEnt.hat:SetNoDraw(true)
end

local sID64 = hitEnt:SteamID64()

Expand Down Expand Up @@ -154,33 +157,31 @@ function SWEP:PrimaryAttack()

-- Cannibal health gain
if self.GainsHealthConVar:GetBool() then
local gainedhealthpercentage = self.GainedHealthPercentageConVar:GetInt()
local victimhealth = hitEnt:Health()
local cannibalhealth = owner:Health()
local gained_health_percentage = self.GainedHealthPercentageConVar:GetInt()
local victimHealth = hitEnt:Health()
local cannibalHealth = owner:Health()

local gainedhealth
if gainedhealthpercentage == 0 then
gainedhealth = 100
local gainedHealth
if gained_health_percentage == 0 then
gainedHealth = 100
else
local gainedhealthunrounded = (gainedhealthpercentage / 100) * victimhealth
gainedhealth = math.floor(gainedhealthunrounded)
gainedHealth = math.floor((gained_health_percentage / 100) * victimHealth)
end

local newcannibalhealth = cannibalhealth + gainedhealth
if newcannibalhealth > cannibalhealth then
owner:SetHealth(newcannibalhealth)
if gainedHealth > 0 then
owner:SetHealth(cannibalHealth + gainedHealth)
end
end

-- Victim digestion
if self.DigestionConVar:GetBool() then
local digestiontime = self.DigestionTimeConVar:GetInt()
local digestion_time = self.DigestionTimeConVar:GetInt()
-- Ensure there's a short delay to allow time for the vars to be set first
if digestiontime == 0 then
digestiontime = 0.1
if digestion_time == 0 then
digestion_time = 0.1
end

timer.Create("TTTCannibalDigestion_" .. sID64, digestiontime, 1, function()
timer.Create("TTTCannibalDigestion_" .. sID64, digestion_time, 1, function()
if not IsPlayer(hitEnt) then return end
if not IsPlayer(owner) then return end

Expand Down
2 changes: 1 addition & 1 deletion gamemodes/terrortown/gamemode/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ function GM:ScalePlayerDamage(ply, hitgroup, dmginfo)

local wep = util.WeaponFromDamage(dmginfo)

if IsValid(wep) and not GetConVar("ttt_disable_headshots"):GetBool() then
if IsValid(wep) and wep.GetHeadshotMultiplier and not GetConVar("ttt_disable_headshots"):GetBool() then
local s = wep:GetHeadshotMultiplier(ply, dmginfo) or 2
dmginfo:ScaleDamage(s)
end
Expand Down
3 changes: 3 additions & 0 deletions gamemodes/terrortown/gamemode/roles/cannibal/cannibal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ local function ReleaseEatenPlayers(ply, message)
v:DrawViewModel(true)
v:DrawWorldModel(true)
v:SetNoDraw(false)
if IsValid(v.hat) then
v.hat:SetNoDraw(false)
end
v:Spawn()
local pos = ply:GetPos()
v:SetPos(FindRespawnLocation(pos) or pos)
Expand Down
31 changes: 24 additions & 7 deletions gamemodes/terrortown/gamemode/roles/cannibal/cl_cannibal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -189,17 +189,34 @@ AddHook("TTTTutorialRoleText", "Cannibal_TTTTutorialRoleText", function(role, ti
local roleTeamName, roleColor = GetRoleTeamInfo(roleTeam)
local html = "The " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " is a <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>" .. roleTeamName .. "</span> role whose goal is to eat all other players."

if GetConVar("ttt_cannibal_digestion"):GetBool() then
html = html .. "<span style='display: block; margin-top: 10px;'>Eaten players are not immediately dead, but they are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>unable to do anything</span> except talk with other eaten players and spectate the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. ".</span>"
if GetConVar("ttt_cannibal_gains_health"):GetBool() then
local gained_health_percentage = GetConVar("ttt_cannibal_gained_health_percentage"):GetInt()
local gained
if gained_health_percentage > 0 then
gained = gained_health_percentage .. "% of the victim's health"
else
gained = "100HP"
end

html = html .. "<span style='display: block; margin-top: 10px;'>When the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " eats a player, they <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>gain " .. gained .. "</span> immediately.</span>"
end

html = html .. "<span style='display: block; margin-top: 10px;'>Eaten players are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>digested and killed </span>" .. GetConVar("ttt_cannibal_digestion_time"):GetInt() .. " seconds after being eaten.</span>"
local eatenDetail = ""
local deathDetail = ""

if GetConVar("ttt_cannibal_digestion"):GetBool() then
eatenDetail = " immediately"
deathDetail = " undigested"
end

html = html .. "<span style='display: block; margin-top: 10px;'>If the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " dies, all undigested eaten players are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>freed</span> at the position where the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " died.</span>"
else
html = html .. "<span style='display: block; margin-top: 10px;'>Eaten players are not dead, but they are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>unable to do anything</span> except talk with other eaten players and spectate the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. ".</span>"
html = html .. "<span style='display: block; margin-top: 10px;'>Eaten players are not" .. eatenDetail .. " dead, but they are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>unable to do anything</span> except talk with other eaten players and spectate the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. ".</span>"

html = html .. "<span style='display: block; margin-top: 10px;'>If the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " dies, all eaten players are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>freed</span> at the position where the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " died.</span>"
if GetConVar("ttt_cannibal_digestion"):GetBool() then
html = html .. "<span style='display: block; margin-top: 10px;'>Eaten players are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>digested and killed </span> " .. GetConVar("ttt_cannibal_digestion_time"):GetInt() .. " seconds after being eaten.</span>"
end

html = html .. "<span style='display: block; margin-top: 10px;'>If the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " dies, all" .. deathDetail .. " eaten players are <span style='color: rgb(" .. roleColor.r .. ", " .. roleColor.g .. ", " .. roleColor.b .. ")'>freed</span> at the position where the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " died.</span>"

return html
end
end)
2 changes: 1 addition & 1 deletion gamemodes/terrortown/gamemode/shared.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ local Utf8Sub = utf8.sub
include("player_class/player_ttt.lua")

-- Version string for display and function for version checks
CR_VERSION = "2.4.3"
CR_VERSION = "2.4.4"
CR_BETA = true
CR_WORKSHOP_ID = CR_BETA and "2404251054" or "2421039084"

Expand Down
Loading