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
4 changes: 2 additions & 2 deletions .github/workflows/luacheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ jobs:
uses: leafo/gh-actions-luarocks@v4

- name: Setup dependencies
run: luarocks install --deps-only gluacheck-dev-1.rockspec
run: luarocks install --deps-only luacheck-dev-1.rockspec

- name: Build ‘luacheck’ (bootstrap)
run: luarocks make gluacheck-dev-1.rockspec
run: luarocks make luacheck-dev-1.rockspec

- name: Run ‘luacheck’ (dogfood)
run: lua -e 'package.path="./gluacheck/src/?.lua;./gluacheck/src/?/init.lua;"..package.path' gluacheck/bin/luacheck.lua gamemodes scripts
4 changes: 4 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,9 @@ globals = {
"VAMPIRE_DEATH_NONE",
"VAMPIRE_DEATH_KILL_CONVERTED",
"VAMPIRE_DEATH_REVERT_CONVERTED",
"VAMPIRE_OVERHEAL_MODE_HEALTH",
"VAMPIRE_OVERHEAL_MODE_MAX_HEALTH",
"VAMPIRE_OVERHEAL_MODE_BOTH",
"VAMPIRE_THRALL_FF_MODE_NONE",
"VAMPIRE_THRALL_FF_MODE_REFLECT",
"VAMPIRE_THRALL_FF_MODE_IMMUNE",
Expand Down Expand Up @@ -1250,6 +1253,7 @@ std = {
EqualValues = {},
ExcludedKeys = {},
GetKeys = {},
GetFirstItemWithPropertyValue = {},
HasItemWithPropertyValue = {},
HasTable = {},
HasValue = {},
Expand Down
6 changes: 4 additions & 2 deletions API/HOOKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1263,13 +1263,14 @@ Called before a team chat message is sent. Used to modify the targets of the tea

*Return:* Whether or not this team chat message should be sent (Defaults to `true`)

### TTTTeamVoiceChatTargets(speaker, targets)
### TTTTeamVoiceChatTargets(speaker, targets, state)
Called before a team voice state message is sent. Used to modify the targets of the team voice state message.\
*Realm:* Server\
*Added in:* 2.0.7\
*Parameters:*
- *speaker* - The player trying to send their team voice state message
- *targets* - The table of players that this message will be sent to. Add or remove players from this table to change the message recipients
- *state* - Whether the speaker is speaking globally (`true`) or only to their team (`false`) *(Added in 2.3.5)*

*Return:* Whether or not this team voice state message should be sent (Defaults to `true`)

Expand Down Expand Up @@ -1340,7 +1341,7 @@ Called after globals are synced but but before role colors and strings are set.
*Realm:* Client and Server\
*Added in:* 1.2.7

### TTTVampireBodyEaten(ply, ent, living, healed)
### TTTVampireBodyEaten(ply, ent, living, healed, maxchange)
Called after a vampire eats a body.\
*Realm:* Server\
*Added in:* 1.6.16\
Expand All @@ -1349,6 +1350,7 @@ Called after a vampire eats a body.\
- *ent* - The target entity. Generally either a player or a ragdoll
- *living* - Whether the target entity was living at the time they were eaten
- *healed* - The amount of health the player gained from eating the body
- *maxchange* - The amount of maximum health the player gained from eating the body *(Added in 2.3.5)*

### TTTVampireInvisibilityChange(ply, invisible)
Called when a vampire starts or ends their invisibility.\
Expand Down
11 changes: 10 additions & 1 deletion API/METHODS_TABLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@ Returns new table that contains the keys not present as values in in the given e
- *tbl* - The table whose keys are being inspected
- *excludes* - Table of values to exclude

### table.GetFirstItemWithPropertyValue(tbl, key, val)
Returns the first item in the given table that has an item whose property specified by the provided `key` has a value that matches the given `val`.\
*Realm:* Client and Server\
*Added in:* 2.3.5\
*Parameters:*
- *tbl* - The table whose values are being inspected
- *key* - The property name whose value is being compared
- *val* - The value to find in the given property

### table.HasItemWithPropertyValue(tbl, key, val)
Returns whether the given table has an item whose property specified by the provided `key` has a value that makes the given `val`.\
Returns whether the given table has an item whose property specified by the provided `key` has a value that matches the given `val`.\
*Realm:* Client and Server\
*Added in:* 1.8.7\
*Parameters:*
Expand Down
7 changes: 5 additions & 2 deletions CONVARS.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,10 @@ ttt_vampire_show_target_icon 0 // Whether Vampires have
ttt_vampire_damage_reduction 0 // The fraction an attacker's bullet damage will be reduced by when they are shooting a Vampire
ttt_vampire_fang_timer 5 // The amount of time fangs must be used to fully drain a target's blood
ttt_vampire_fang_dead_timer 0 // The amount of time fangs must be used to fully drain a dead target's blood. Set to 0 to use the same time as "ttt_vampire_fang_timer"
ttt_vampire_fang_heal 50 // The amount of health a vVampire will heal by when they fully drain a target's blood
ttt_vampire_fang_heal 50 // The amount of health a Vampire will heal by when they fully drain a target's blood
ttt_vampire_fang_overheal 25 // The amount over the Vampire's normal maximum health (e.g. 100 + this ConVar) that the Vampire can heal to by drinking blood.
ttt_vampire_fang_overheal_living -1 // The amount of overheal (see "ttt_vampire_fang_overheal") to give if the Vampire's target is living. Set to -1 to use the same amount as "ttt_vampire_fang_overheal" instead
ttt_vampire_fang_overheal_mode 0 // How to handle healing a vampire over their maximum health. 0 - Increase health. 1 - Increase max health. 2 - Increase both.
ttt_vampire_fang_unfreeze_delay 2 // The number of seconds before players who were frozen in place by the fangs should be released if the Vampire stops using the fangs on them
ttt_vampire_prime_death_mode 0 // What to do when the prime Vampire(s) (e.g. players who spawn as Vampires originally) are killed. 0 - Do nothing. 1 - Kill all Vampire thralls (non-prime Vampires). 2 - Revert all Vampire thralls (non-prime Vampires) to their original role
ttt_vampire_prime_only_convert 1 // Whether only prime Vampires (e.g. players who spawn as Vampire originally) are allowed to convert other players
Expand Down Expand Up @@ -411,6 +412,7 @@ ttt_deputy_activation_credits 0 // The number of credits

// Mercenary
ttt_mercenary_credits_starting 1 // The number of credits a Mercenary should start with
ttt_mercenary_armor_loadout 1 // Whether the mercenary should get body armor as part of their loadout

// Veteran
ttt_veteran_damage_bonus 0.5 // Damage bonus that the Veteran has when they are the last innocent alive (e.g. 0.5 = 50% more damage)
Expand Down Expand Up @@ -1240,7 +1242,8 @@ ttt_dna_scan_detectives_loadout 0 // Whether all detectives
ttt_dna_scan_on_dialog 1 // Whether to show a button to open the DNA scanner on the body search dialog
ttt_dna_scan_only_drop_on_death 0 // Whether the DNA scanner should only be droppable when the holder dies
ttt_spectator_corpse_search 1 // Whether spectators can search bodies (not shared with other players)
ttt_corpse_search_not_shared 0 // Whether corpse searches are not shared with other players (only affects non-detective-like searchers)
ttt_corpse_search_auto_confirm 1 // Whether corpse searches are not shared with other players (only affects non-detective-like searchers)
ttt_corpse_search_not_shared 0 // Whether corpse searches automatically confirm the death of the player
ttt_corpse_search_killer_team_text_traitor 0 // Whether corpse searches should include flavor text hinting at the team of their traitor team killer
ttt_corpse_search_killer_team_text_innocent 0 // Whether corpse searches should include flavor text hinting at the team of their innocent team killer
ttt_corpse_search_killer_team_text_monster 0 // Whether corpse searches should include flavor text hinting at the team of their monster team killer
Expand Down
21 changes: 21 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Release Notes

## 2.3.5 (Beta)
**Released:**

### Changes
- Updated weapon switch and pickup HUD elements to use the same logic for getting weapon names
- Fixes very rare cases where they would say different things

### Additions
- Added ability to control whether the mercenary gets body armor as part of their loadout (defaults to `true`)
- Added ability to change vampire's fang drain overheal to overheal (default), increase max health, or do both
- Added ability to disable automatically confirming a players death when searching their body (disabled by default)

### Fixes
- Fixed illusionist not blocking traitor team voice chat
- Fixed promoted impersonator and deputy who are searched by a detective not always showing their true role on the scoreboard

### Developer
- Added `state` parameter to `TTTTeamVoiceChatTargets` hook
- Added `table.GetFirstItemWithPropertyValue` static method
- Added `maxchange` parameter to `TTTVampireBodyEaten` hook

## 2.3.4 (Beta)
**Released: August 9th, 2025**

Expand Down
6 changes: 4 additions & 2 deletions docs/api/hooks.html
Original file line number Diff line number Diff line change
Expand Up @@ -1889,7 +1889,7 @@ <h3><a id="tttteamchattargetssender-msg-targets-from_chat" href="#tttteamchattar
<em>Return:</em> Whether or not this team chat message should be sent (Defaults to <code>true</code>).
</p>

<h3><a id="tttteamvoicechattargetsspeaker-targetsfrom_chat" href="#tttteamvoicechattargetsspeaker-targetsfrom_chat">TTTTeamVoiceChatTargets(speaker, targets)</a></h3>
<h3><a id="tttteamvoicechattargetsspeaker-targets-state" href="#tttteamvoicechattargetsspeaker-targets-state">TTTTeamVoiceChatTargets(speaker, targets, state)</a></h3>
<p>
Called before a team voice state message is sent. Used to modify the targets of the team voice state message.<br>
<em>Realm:</em> Server<br>
Expand All @@ -1899,6 +1899,7 @@ <h3><a id="tttteamvoicechattargetsspeaker-targetsfrom_chat" href="#tttteamvoicec
<ul>
<li><em>speaker</em> - The player trying to send their team voice state message</li>
<li><em>targets</em> - The table of players that this message will be sent to. Add or remove players from this table to change the message recipients</li>
<li><em>state</em> - Whether the speaker is speaking globally (<code>true</code>) or only to their team (<code>false</code>) <em>(Added in 2.3.5)</em></li>
</ul>
<p>
<em>Return:</em> Whether or not this team voice state message should be sent (Defaults to <code>true</code>).
Expand Down Expand Up @@ -2001,7 +2002,7 @@ <h3><a id="tttupdaterolestate" href="#tttupdaterolestate">TTTUpdateRoleState()</
<em>Added in:</em> 1.2.7
</p>

<h3><a id="tttvampirebodyeatenply-ent-living-healed" href="#tttvampirebodyeatenply-ent-living-healed">TTTVampireBodyEaten(ply, ent, living, healed)</a></h3>
<h3><a id="tttvampirebodyeatenply-ent-living-healed-maxchange" href="#tttvampirebodyeatenply-ent-living-healed-maxchange">TTTVampireBodyEaten(ply, ent, living, healed, maxchange)</a></h3>
<p>
Called after a Vampire eats a body.<br>
<em>Realm:</em> Server<br>
Expand All @@ -2013,6 +2014,7 @@ <h3><a id="tttvampirebodyeatenply-ent-living-healed" href="#tttvampirebodyeatenp
<li><em>ent</em> - The target entity. Generally either a player or a ragdoll</li>
<li><em>living</em> - Whether the target entity was living at the time they were eaten</li>
<li><em>healed</em> - The amount of health the player gained from eating the body</li>
<li><em>maxchange</em> - The amount of maximum health the player gained from eating the body <em>(Added in 2.3.5)</em> <span data-text="Beta Only" class="betaonly betaicon tooltip">&nbsp;</span></li>
</ul>

<h3><a id="tttvampireinvisibilitychangeply-invisible" href="#tttvampireinvisibilitychangeply-invisible">TTTVampireInvisibilityChange(ply, invisible)</a></h3>
Expand Down
15 changes: 14 additions & 1 deletion docs/api/methods_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,22 @@ <h3><a id="tableexcludedkeystbl-excludes" href="#tableexcludedkeystbl-excludes">
<li><em>excludes</em> - Table of values to exclude</li>
</ul>

<h3><a id="tablegetfirstitemwithpropertyvaluetbl-key-val" href="#tablegetfirstitemwithpropertyvaluetbl-key-val">table.GetFirstItemWithPropertyValue(tbl, key, val)</a></h3>
<p>
Returns the first item in the given table that has an item whose property specified by the provided <code>key</code> has a value that matches the given <code>val</code>.<br>
<em>Realm:</em> Client and Server<br>
<em>Added in:</em> 2.3.5<br>
<em>Parameters:</em>
</p>
<ul>
<li><em>tbl</em> - The table whose values are being inspected</li>
<li><em>key</em> - The property name whose value is being compared</li>
<li><em>val</em> - The value to find in the given property</li>
</ul>

<h3><a id="tablehasitemwithpropertyvaluetbl-key-val" href="#tablehasitemwithpropertyvaluetbl-key-val">table.HasItemWithPropertyValue(tbl, key, val)</a></h3>
<p>
Returns whether the given table has an item whose property specified by the provided <code>key</code> has a value that makes the given <code>val</code>.<br>
Returns whether the given table has an item whose property specified by the provided <code>key</code> has a value that matches the given <code>val</code>.<br>
<em>Realm:</em> Client and Server<br>
<em>Added in:</em> 1.8.7<br>
<em>Parameters:</em>
Expand Down
6 changes: 6 additions & 0 deletions docs/teams/innocent.html
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ <h3 style="margin: 10px 0; padding: 0;">Role Configuration:</h3>
</tr>
</thead>
<tbody>
<tr>
<td>ttt_mercenary_armor_loadout <span data-text="Beta Only" class="betaonly betaicon tooltip">&nbsp;</span></td>
<td>1</td>
<td>Boolean</td>
<td>Whether the mercenary should get body armor as part of their loadout.</td>
</tr>
<tr>
<td>ttt_mercenary_credits_starting</td>
<td>1</td>
Expand Down
12 changes: 12 additions & 0 deletions docs/teams/traitor.html
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,18 @@ <h3 style="margin: 10px 0; padding: 0;">Role Configuration:</h3>
<td>Integer</td>
<td>The amount over the Vampire's normal maximum health that the Vampire can heal to by drinking blood from living players. <i>(Set to -1 to use the same amount as <code>ttt_vampire_fang_overheal</code> instead.)</i></td>
</tr>
<tr>
<td>ttt_vampire_fang_overheal_mode</td>
<td>0</td>
<td>Integer (0-1)</td>
<td>How to handle healing a vampire over their maximum health:
<ol start="0">
<li>Heal over their max health.</li>
<li>Increase their max health.</li>
<li>Increase their max health and heal them to full.</li>
</ol>
</td>
</tr>
<tr>
<td>ttt_vampire_fang_timer</td>
<td>5</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ local confirm = Sound("npc/turret_floor/click1.wav")
function SWEP:IdentifyCorpse()
if SERVER then
local tr = self:GetOwner():GetEyeTrace(MASK_SHOT)
CORPSE.ShowSearch(self:GetOwner(), tr.Entity, false, true)
CORPSE.ShowSearch(self:GetOwner(), tr.Entity, not GetConVar("ttt_corpse_search_auto_confirm"):GetBool(), true)
elseif IsFirstTimePredicted() then
LocalPlayer():EmitSound(confirm)
end
Expand Down
30 changes: 26 additions & 4 deletions gamemodes/terrortown/entities/weapons/weapon_vam_fangs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ if SERVER then
CreateConVar("ttt_vampire_fang_dead_timer", "0", FCVAR_NONE, "The amount of time fangs must be used to fully drain a dead target's blood. Set to 0 to use the same time as \"ttt_vampire_fang_timer\"", 0, 30)
CreateConVar("ttt_vampire_fang_timer", "5", FCVAR_NONE, "The amount of time fangs must be used to fully drain a target's blood", 0, 30)
CreateConVar("ttt_vampire_fang_heal", "50", FCVAR_NONE, "The amount of health a vampire will heal by when they fully drain a target's blood", 0, 100)
CreateConVar("ttt_vampire_fang_overheal_mode", "0", FCVAR_NONE, "How to handle healing a vampire over their maximum health. 0 - Increase health. 1 - Increase max health. 2 - Do both", 0, 2)
CreateConVar("ttt_vampire_fang_overheal", "25", FCVAR_NONE, "The amount over the vampire's normal maximum health (e.g. 100 + this ConVar) that the vampire can heal to by drinking blood", 0, 100)
CreateConVar("ttt_vampire_fang_overheal_living", "-1", FCVAR_NONE, "The amount of overheal (see \"ttt_vampire_fang_overheal\") to give if the vampire's target is living. Set to -1 to use the same amount as \"ttt_vampire_fang_overheal\" instead", -1, 100)
CreateConVar("ttt_vampire_fang_unfreeze_delay", "2", FCVAR_NONE, "The number of seconds before players who were frozen in place by the fangs should be released if the vampire stops using the fangs on them", 0, 15)
Expand Down Expand Up @@ -364,16 +365,37 @@ function SWEP:DoKill()
end

function SWEP:DoHeal(living)
local mode = GetConVar("ttt_vampire_fang_overheal_mode"):GetInt()
local vamheal = GetConVar("ttt_vampire_fang_heal"):GetInt()
local vamoverheal = GetConVar("ttt_vampire_fang_overheal_living"):GetInt()
if not living or vamoverheal < 0 then
vamoverheal = GetConVar("ttt_vampire_fang_overheal"):GetInt()
end

local vamheal = GetConVar("ttt_vampire_fang_heal"):GetInt()
local owner = self:GetOwner()
local health = math.min(owner:Health() + vamheal, owner:GetMaxHealth() + vamoverheal)
hook.Call("TTTVampireBodyEaten", nil, owner, self.TargetEntity, living, health - owner:Health())
owner:SetHealth(health)
local health = owner:Health()
local maxhealth = owner:GetMaxHealth()
local newhealth = math.min(health + vamheal, maxhealth + vamoverheal)
local maxchange = 0

-- If we've exceeded the max health and we're set to not actually overheal, update max health instead
if newhealth > maxhealth and mode > VAMPIRE_OVERHEAL_MODE_HEALTH then
-- Count how much the max health is about to change
maxchange = newhealth - maxhealth
owner:SetMaxHealth(newhealth)

-- If we're only changing the max health, reduce the amount we're healing to the previous max health
if mode == VAMPIRE_OVERHEAL_MODE_MAX_HEALTH then
newhealth = maxhealth
-- Otherwise heal them by the amount their max health changed
else
newhealth = health + maxchange
end
end

local healed = newhealth - owner:Health()
owner:SetHealth(newhealth)
hook.Call("TTTVampireBodyEaten", nil, owner, self.TargetEntity, living, healed, maxchange)
end

function SWEP:UnfreezeTarget()
Expand Down
2 changes: 1 addition & 1 deletion gamemodes/terrortown/gamemode/cl_hudpickup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ end
function GM:HUDWeaponPickedUp(wep)
if not (IsValid(wep) and IsValid(LocalPlayer())) or (not LocalPlayer():Alive()) then return end

local name = TryTranslation(wep.GetPrintName and wep:GetPrintName() or wep:GetClass() or "Unknown Weapon Name")
local name = TryTranslation(wep.GetPrintName and wep:GetPrintName() or wep.PrintName or wep:GetClass() or "Unknown Weapon Name")

local pickup = {}
pickup.time = CurTime()
Expand Down
3 changes: 2 additions & 1 deletion gamemodes/terrortown/gamemode/cl_search.lua
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,8 @@ local function ShowSearchScreen(search_raw)
btn:SetDisabled(true)
end,
disabled = function()
return client:IsSpec() or not client:KeyDownLast(IN_WALK) or CORPSE.GetFound(rag, false)
local covert = client:KeyDownLast(IN_WALK) or not GetConVar("ttt_corpse_search_auto_confirm"):GetBool()
return client:IsSpec() or not covert or CORPSE.GetFound(rag, false)
end
})

Expand Down
Loading
Loading