diff --git a/CONVARS.md b/CONVARS.md
index b8d887dda..a5b3f0260 100644
--- a/CONVARS.md
+++ b/CONVARS.md
@@ -765,6 +765,14 @@ 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 1 // 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)
+ttt_cannibal_digests_victims 1 // 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)
+ttt_cannibal_does_poopy 1 // Whether the Cannibal poops themselves when a victim is digested
+ttt_cannibal_does_poopy_noise 1 // Whether the Cannibal's poops produce an audible cue
+
// ----------------------------------------
// INDEPENDENT TEAM SETTINGS
diff --git a/gamemodes/terrortown/content/materials/models/poo/poo.vmt b/gamemodes/terrortown/content/materials/models/poo/poo.vmt
new file mode 100644
index 000000000..91d40117a
--- /dev/null
+++ b/gamemodes/terrortown/content/materials/models/poo/poo.vmt
@@ -0,0 +1,10 @@
+"VertexLitGeneric"
+{
+ "$baseTexture" "Models/poo/poo"
+ "$bumpmap" "Models/poo/poo_n"
+ // -- From here down is new stuff which will only be applied if $phong is set to 1 --
+ "$phong" "1"
+ "$phongboost" "4"
+ "$phongexponent" "30"
+ "$phongfresnelranges" "[.2 .5 1]"
+}
diff --git a/gamemodes/terrortown/content/materials/models/poo/poo.vtf b/gamemodes/terrortown/content/materials/models/poo/poo.vtf
new file mode 100644
index 000000000..f32c30dc3
Binary files /dev/null and b/gamemodes/terrortown/content/materials/models/poo/poo.vtf differ
diff --git a/gamemodes/terrortown/content/materials/models/poo/poo_n.vtf b/gamemodes/terrortown/content/materials/models/poo/poo_n.vtf
new file mode 100644
index 000000000..3a9d0b58f
Binary files /dev/null and b/gamemodes/terrortown/content/materials/models/poo/poo_n.vtf differ
diff --git a/gamemodes/terrortown/content/models/poo/poo.dx80.vtx b/gamemodes/terrortown/content/models/poo/poo.dx80.vtx
new file mode 100644
index 000000000..3182d23c3
Binary files /dev/null and b/gamemodes/terrortown/content/models/poo/poo.dx80.vtx differ
diff --git a/gamemodes/terrortown/content/models/poo/poo.dx90.vtx b/gamemodes/terrortown/content/models/poo/poo.dx90.vtx
new file mode 100644
index 000000000..8c3f0539e
Binary files /dev/null and b/gamemodes/terrortown/content/models/poo/poo.dx90.vtx differ
diff --git a/gamemodes/terrortown/content/models/poo/poo.mdl b/gamemodes/terrortown/content/models/poo/poo.mdl
new file mode 100644
index 000000000..6cb10c73c
Binary files /dev/null and b/gamemodes/terrortown/content/models/poo/poo.mdl differ
diff --git a/gamemodes/terrortown/content/models/poo/poo.phy b/gamemodes/terrortown/content/models/poo/poo.phy
new file mode 100644
index 000000000..f2b486025
Binary files /dev/null and b/gamemodes/terrortown/content/models/poo/poo.phy differ
diff --git a/gamemodes/terrortown/content/models/poo/poo.sw.vtx b/gamemodes/terrortown/content/models/poo/poo.sw.vtx
new file mode 100644
index 000000000..df55c7972
Binary files /dev/null and b/gamemodes/terrortown/content/models/poo/poo.sw.vtx differ
diff --git a/gamemodes/terrortown/content/models/poo/poo.vvd b/gamemodes/terrortown/content/models/poo/poo.vvd
new file mode 100644
index 000000000..902257872
Binary files /dev/null and b/gamemodes/terrortown/content/models/poo/poo.vvd differ
diff --git a/gamemodes/terrortown/content/sound/cannibal/poop1.wav b/gamemodes/terrortown/content/sound/cannibal/poop1.wav
new file mode 100644
index 000000000..770aee196
Binary files /dev/null and b/gamemodes/terrortown/content/sound/cannibal/poop1.wav differ
diff --git a/gamemodes/terrortown/content/sound/cannibal/poop2.wav b/gamemodes/terrortown/content/sound/cannibal/poop2.wav
new file mode 100644
index 000000000..3adc03fee
Binary files /dev/null and b/gamemodes/terrortown/content/sound/cannibal/poop2.wav differ
diff --git a/gamemodes/terrortown/content/sound/cannibal/poop3.wav b/gamemodes/terrortown/content/sound/cannibal/poop3.wav
new file mode 100644
index 000000000..fde256fa8
Binary files /dev/null and b/gamemodes/terrortown/content/sound/cannibal/poop3.wav differ
diff --git a/gamemodes/terrortown/content/sound/cannibal/poop4.wav b/gamemodes/terrortown/content/sound/cannibal/poop4.wav
new file mode 100644
index 000000000..de94b9400
Binary files /dev/null and b/gamemodes/terrortown/content/sound/cannibal/poop4.wav differ
diff --git a/gamemodes/terrortown/content/sound/cannibal/poop5.wav b/gamemodes/terrortown/content/sound/cannibal/poop5.wav
new file mode 100644
index 000000000..683fac570
Binary files /dev/null and b/gamemodes/terrortown/content/sound/cannibal/poop5.wav differ
diff --git a/gamemodes/terrortown/content/sound/cannibal/poop6.wav b/gamemodes/terrortown/content/sound/cannibal/poop6.wav
new file mode 100644
index 000000000..ca0d00158
Binary files /dev/null and b/gamemodes/terrortown/content/sound/cannibal/poop6.wav differ
diff --git a/gamemodes/terrortown/entities/weapons/weapon_can_eater.lua b/gamemodes/terrortown/entities/weapons/weapon_can_eater.lua
index c4272d36e..9c0d386c5 100644
--- a/gamemodes/terrortown/entities/weapons/weapon_can_eater.lua
+++ b/gamemodes/terrortown/entities/weapons/weapon_can_eater.lua
@@ -37,6 +37,12 @@ SWEP.InLoadoutFor = {ROLE_CANNIBAL}
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", "1", 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.DigestsVictimsConVar = CreateConVar("ttt_cannibal_digests_victims", "1", 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)
+SWEP.RectallyIncontinentConVar = CreateConVar("ttt_cannibal_does_poopy", "1", FCVAR_REPLICATED, "Whether the Cannibal poops themselves when a victim is digested", 0, 1)
+SWEP.AudibleIncontinenceConVar = CreateConVar("ttt_cannibal_does_poopy_noise", "1", FCVAR_REPLICATED, "Whether the Cannibal's poops produce an audible cue", 0, 1)
local eatSounds = {
"cannibal/eat1.wav",
@@ -44,6 +50,15 @@ local eatSounds = {
"cannibal/eat3.wav"
}
+local poopSounds = {
+ "cannibal/poop1.wav",
+ "cannibal/poop2.wav",
+ "cannibal/poop3.wav",
+ "cannibal/poop4.wav",
+ "cannibal/poop5.wav",
+ "cannibal/poop6.wav"
+}
+
function SWEP:Initialize()
if CLIENT then
self:AddHUDHelp("can_eater_help_pri", nil, true)
@@ -125,6 +140,84 @@ function SWEP:PrimaryAttack()
if cooldown > 0 then
self:SetDeviceCooldownEnd(CurTime() + cooldown)
end
+
+ -- Cannibal health gain
+ if self.GainsHealthConVar:GetBool() then
+
+ local gainedhealthpercentage = self.GainedHealthPercentageConVar:GetInt()
+ local victimhealth = hitEnt:Health()
+ local cannibalhealth = owner:Health()
+
+ if gainedhealthpercentage == 0 then
+ gainedhealth = 100
+ else
+ gainedhealthunrounded = (gainedhealthpercentage / 100) * victimhealth
+ gainedhealth = math.floor(gainedhealthunrounded)
+ end
+
+ local newcannibalhealth = cannibalhealth + gainedhealth
+ if newcannibalhealth > cannibalhealth then
+ owner:SetHealth(newcannibalhealth)
+ end
+
+ end
+
+ -- Victim digestion
+ if self.DigestsVictimsConVar:GetBool() then
+
+ local digestiontime = self.DigestionTimeConVar:GetInt()
+
+ if digestiontime == 0 then
+ digestiontime = 0.1 -- short delay to avoid fuckyness?
+ end
+
+ local disgestiontimername = "TTTCannibalDigestion_" .. sID64
+
+ -- Remove existing digestion timer for victim if one somehow exists
+ if timer.Exists(disgestiontimername) then
+ timer.Remove(disgestiontimername)
+ end
+
+ timer.Create(disgestiontimername, digestiontime, 1, function()
+
+ -- Safety checks
+ if not IsValid(hitEnt) or not hitEnt:IsPlayer() then return end
+ if not IsValid(owner) or not owner:IsPlayer() then return end
+
+ -- Only digest if they are still in THIS cannibal's tummy
+ if hitEnt.TTTCannibalEaten == owner:SteamID64() then
+ hitEnt:KillSilent()
+ hitEnt:ClearProperty("TTTCannibalEaten")
+
+ hitEnt:SetParent(nil)
+ hitEnt:SpectateEntity(nil)
+
+ hitEnt:QueueMessage(MSG_PRINTBOTH, "You have been fully digested!", 3)
+ owner:QueueMessage(MSG_PRINTBOTH, "You have fully digested " .. hitEnt:Nick() .. "!", 3)
+
+ -- Spawn poop at cannibal's position
+ if self.RectallyIncontinentConVar:GetBool() then
+ local poop = ents.Create("prop_physics")
+ if IsValid(poop) then
+ poop:SetModel("models/poo/poo.mdl")
+
+ local forward = owner:GetForward()
+ local dropPos = owner:GetPos() + forward * -30 + Vector(0, 0, 10)
+ poop:SetPos(dropPos)
+
+ poop:SetAngles(Angle(0, math.random(0, 360), 0))
+ poop:Spawn()
+ poop:Activate()
+
+ if self.AudibleIncontinenceConVar:GetBool()then
+ owner:EmitSound(poopSounds[math.random(1, #poopSounds)], 100)
+ end
+ end
+ end
+ end
+
+ end)
+ end
end
end
diff --git a/gamemodes/terrortown/gamemode/roles/cannibal/cannibal.lua b/gamemodes/terrortown/gamemode/roles/cannibal/cannibal.lua
index e029f6505..1b3a1b115 100644
--- a/gamemodes/terrortown/gamemode/roles/cannibal/cannibal.lua
+++ b/gamemodes/terrortown/gamemode/roles/cannibal/cannibal.lua
@@ -46,6 +46,8 @@ local function ReleaseEatenPlayers(ply, message)
local sID64 = v:SteamID64()
+ timer.Remove("TTTCannibalDigestion_" .. sID64)
+
for _, data in ipairs(CANNIBAL.playerWeapons[sID64]) do
local wep = v:Give(data.class)
if not IsValid(wep) then continue end
diff --git a/gamemodes/terrortown/gamemode/roles/cannibal/cl_cannibal.lua b/gamemodes/terrortown/gamemode/roles/cannibal/cl_cannibal.lua
index a57af1f9d..b00e80bd1 100644
--- a/gamemodes/terrortown/gamemode/roles/cannibal/cl_cannibal.lua
+++ b/gamemodes/terrortown/gamemode/roles/cannibal/cl_cannibal.lua
@@ -189,10 +189,21 @@ AddHook("TTTTutorialRoleText", "Cannibal_TTTTutorialRoleText", function(role, ti
local roleTeamName, roleColor = GetRoleTeamInfo(roleTeam)
local html = "The " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " is a " .. roleTeamName .. " role whose goal is to eat all other players."
- html = html .. "Eaten players are not dead, but they are unable to do anything except talk with other eaten players and spectate the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. "."
+ if GetConVar("ttt_cannibal_digests_victims"):GetBool() then
+
+ html = html .. "Eaten players are not immediately dead, but they are unable to do anything except talk with other eaten players and spectate the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. "."
- html = html .. "If the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " dies, all eaten players are freed at the position where the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " died."
+ html = html .. "Eaten players are digested and killed " .. GetConVar("ttt_cannibal_digestion_time"):GetInt() .. " seconds after being eaten."
+ html = html .. "If the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " dies, all undigested eaten players are freed at the position where the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " died."
+
+ else
+
+ html = html .. "Eaten players are not dead, but they are unable to do anything except talk with other eaten players and spectate the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. "."
+
+ html = html .. "If the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " dies, all eaten players are freed at the position where the " .. ROLE_STRINGS[ROLE_CANNIBAL] .. " died."
+
+ end
return html
end
end)
\ No newline at end of file
diff --git a/gamemodes/terrortown/gamemode/roles/cannibal/shared.lua b/gamemodes/terrortown/gamemode/roles/cannibal/shared.lua
index 75e2f9c46..cdd21ce4e 100644
--- a/gamemodes/terrortown/gamemode/roles/cannibal/shared.lua
+++ b/gamemodes/terrortown/gamemode/roles/cannibal/shared.lua
@@ -49,6 +49,30 @@ table.insert(ROLE_CONVARS[ROLE_CANNIBAL], {
cvar = "ttt_cannibal_update_scoreboard",
type = ROLE_CONVAR_TYPE_BOOL
})
+table.insert(ROLE_CONVARS[ROLE_CANNIBAL], {
+ cvar = "ttt_cannibal_gains_health",
+ type = ROLE_CONVAR_TYPE_BOOL
+})
+table.insert(ROLE_CONVARS[ROLE_CANNIBAL], {
+ cvar = "ttt_cannibal_gained_health_percentage",
+ type = ROLE_CONVAR_TYPE_NUM
+})
+table.insert(ROLE_CONVARS[ROLE_CANNIBAL], {
+ cvar = "ttt_cannibal_digests_victims",
+ type = ROLE_CONVAR_TYPE_BOOL
+})
+table.insert(ROLE_CONVARS[ROLE_CANNIBAL], {
+ cvar = "ttt_cannibal_digestion_time",
+ type = ROLE_CONVAR_TYPE_NUM
+})
+table.insert(ROLE_CONVARS[ROLE_CANNIBAL], {
+ cvar = "ttt_cannibal_does_poopy",
+ type = ROLE_CONVAR_TYPE_BOOL
+})
+table.insert(ROLE_CONVARS[ROLE_CANNIBAL], {
+ cvar = "ttt_cannibal_does_poopy_noise",
+ type = ROLE_CONVAR_TYPE_BOOL
+})
-------------------
-- ROLE FEATURES --