From b51b972effe0ddc29fd331134ef9fe05e4ae7e40 Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 09:23:37 +0800 Subject: [PATCH 01/21] add Entity:IsSpecialUsableEntity() for special ttt-specific usables --- gamemodes/terrortown/gamemode/server/sv_entity.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gamemodes/terrortown/gamemode/server/sv_entity.lua b/gamemodes/terrortown/gamemode/server/sv_entity.lua index 3ceb9130d..c0112d158 100644 --- a/gamemodes/terrortown/gamemode/server/sv_entity.lua +++ b/gamemodes/terrortown/gamemode/server/sv_entity.lua @@ -90,7 +90,7 @@ function entmeta:IsUsableEntity(requiredCaps) -- special case: TTT specific lua based use interactions -- when we're looking for specifically the lua use - if self:IsWeapon() or self.player_ragdoll or (self:IsScripted() and self.CanUseKey) then + if self:IsSpecialUsableEntity() then return true end @@ -110,6 +110,13 @@ function entmeta:IsUsableEntity(requiredCaps) return false end +--- +-- @return boolean +-- @realm server +function entmeta:IsSpecialUsableEntity() + return self:IsWeapon() or self.player_ragdoll or self.CanUseKey +end + --- -- Some sounds are important enough that they shouldn't be affected by CPASAttenuationFilter -- @param string snd The name of the sound to be played From f8535d345c5768040c94eee0840a292660855c9d Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 09:25:27 +0800 Subject: [PATCH 02/21] make ttt2 no longer override +use fixes a billion bugs related to doing +use on map entities --- .../terrortown/gamemode/server/sv_player.lua | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/gamemodes/terrortown/gamemode/server/sv_player.lua b/gamemodes/terrortown/gamemode/server/sv_player.lua index 0b2736b6f..f669cada2 100644 --- a/gamemodes/terrortown/gamemode/server/sv_player.lua +++ b/gamemodes/terrortown/gamemode/server/sv_player.lua @@ -343,18 +343,30 @@ end -- Triggered when the @{Player} presses use on an object. -- Continuously runs until USE is released but will not activate other Entities -- until the USE key is released; dependent on activation type of the @{Entity}. --- @note TTT2 blocks all gmod internal use and only checks this for addons -- @param Player ply The @{Player} pressing the "use" key. -- @param Entity ent The entity which the @{Player} is looking at / activating USE on. --- @param bool overrideDoPlayerUse This is used to override the default outcome of the check -- @return boolean Return false if the @{Player} is not allowed to USE the entity. -- Do not return true if using a hook, otherwise other mods may not get a chance to block a @{Player}'s use. -- @hook -- @realm server -- @ref https://wiki.facepunch.com/gmod/GM:PlayerUse -- @local -function GM:PlayerUse(ply, ent, overrideDoPlayerUse) - return overrideDoPlayerUse or false +function GM:PlayerUse(ply, ent) + if not ply:IsTerror() then + return false + end + + if + ent:IsButton() + --- + -- @realm server + and hook.Run("TTT2OnButtonUse", ply, ent, ent:GetInternalVariable("m_toggle_state")) + == false + then + return false + end + + return true end --- @@ -514,11 +526,8 @@ end local function EntityContinuousUse(ent, ply) --- - -- Enable addons to allow handling PlayerUse - -- Otherwise default to old IsTerror Check -- @realm server - -- stylua: ignore - if hook.Run("PlayerUse", ply, ent, ply:IsTerror()) then + if hook.Run("PlayerUse", ply, ent) then ent:Use(ply, ply) end @@ -590,11 +599,7 @@ net.Receive("TTT2PlayerUseEntity", function(len, ply) local ent = net.ReadEntity() local isRemote = net.ReadBool() - if not hasEnt or not ent:IsUsableEntity() then - ent = ply:GetUseEntity() - end - - if not IsValid(ent) then + if not (IsValid(ent) and ent:IsSpecialUsableEntity()) then return end @@ -613,16 +618,6 @@ net.Receive("TTT2PlayerUseEntity", function(len, ply) return end - if - ent:IsButton() - --- - -- @realm server - and hook.Run("TTT2OnButtonUse", ply, ent, ent:GetInternalVariable("m_toggle_state")) - == false - then - return - end - EntityContinuousUse(ent, ply) end) From 441cd9815ae7489452e890730d00fd0a3d8c92b1 Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 11:22:32 +0800 Subject: [PATCH 03/21] fix targetid detection --- lua/ttt2/libraries/buttons.lua | 3 -- lua/ttt2/libraries/targetid.lua | 54 +++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lua/ttt2/libraries/buttons.lua b/lua/ttt2/libraries/buttons.lua index af45aca6a..399acbb4f 100644 --- a/lua/ttt2/libraries/buttons.lua +++ b/lua/ttt2/libraries/buttons.lua @@ -31,9 +31,6 @@ if SERVER then for j = 1, #buttonsTable do local foundButton = buttonsTable[j] - foundButton:SetNotSolid(false) - foundButton:SetSolid(SOLID_BSP) - foundButton:SetNWInt("button_class", i) end end diff --git a/lua/ttt2/libraries/targetid.lua b/lua/ttt2/libraries/targetid.lua index 07101382b..2ae074a2e 100644 --- a/lua/ttt2/libraries/targetid.lua +++ b/lua/ttt2/libraries/targetid.lua @@ -69,6 +69,8 @@ function targetid.Initialize() } end +local PLAYER_USE_RADIUS = 80 + --- -- This function handles finding Entities by casting a ray from a point in a direction, filtering out certain entities -- Use this in combination with the hook @GM:TTTModifyTargetedEntity to create your own Remote Camera with TargetIDs. @@ -82,9 +84,8 @@ end -- @realm client function targetid.FindEntityAlongView(pos, dir, filter) local client = LocalPlayer() - local endpos = dir - endpos:Mul(MAX_TRACE_LENGTH) + local endpos = dir * MAX_TRACE_LENGTH endpos:Add(pos) if entspawnscript.IsEditing(client) then @@ -108,15 +109,56 @@ function targetid.FindEntityAlongView(pos, dir, filter) return ent, pos:Distance(ent:GetPos()) end - local trace = util.TraceLine({ + local tracedata = { start = pos, endpos = endpos, - mask = MASK_ALL, filter = filter, - }) + } + + local trace = util.TraceLine(tracedata) + + -- if nothing is hit, check again with a different mask + -- this will hit any solid buttons + if not IsValid(trace.Entity) then + tracedata.mask = bit.bor(MASK_SOLID, CONTENTS_DEBRIS, CONTENTS_PLAYERCLIP) + + trace = util.TraceLine(tracedata) + end -- this is the entity the player is looking at right now local ent = trace.Entity + local distance = trace.StartPos:Distance(trace.HitPos) + + -- if nothing is hit, try to look for non-solid buttons + if not IsValid(ent) then + --local buttons = ents.FindInCone(pos, dir, PLAYER_USE_RADIUS, 0.8) + local buttons = ents.FindByClass("class C_BaseEntity") + + local rayDelta = dir * PLAYER_USE_RADIUS + + for i = 1, #buttons do + local e = buttons[i] + + if e:IsSolid() or not e:IsButton() then + continue + end + + local _, _, frac = util.IntersectRayWithOBB( + pos, rayDelta, e:GetPos(), e:GetAngles(), e:GetCollisionBounds() + ) + + if not frac then + continue + end + + local dist = frac * PLAYER_USE_RADIUS + + if dist < distance then + distance = dist + ent = e + end + end + end -- if a vehicle, we identify the driver instead if IsValid(ent) and ent:IsVehicle() then @@ -127,7 +169,7 @@ function targetid.FindEntityAlongView(pos, dir, filter) end end - return ent, trace.StartPos:Distance(trace.HitPos) + return ent, distance end --- From 47f2da4aaec9e7cda0cd22160a3df3c91d412cec Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 11:24:54 +0800 Subject: [PATCH 04/21] Update targetid.lua --- lua/ttt2/libraries/targetid.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/ttt2/libraries/targetid.lua b/lua/ttt2/libraries/targetid.lua index 2ae074a2e..57b7e24bd 100644 --- a/lua/ttt2/libraries/targetid.lua +++ b/lua/ttt2/libraries/targetid.lua @@ -132,7 +132,7 @@ function targetid.FindEntityAlongView(pos, dir, filter) -- if nothing is hit, try to look for non-solid buttons if not IsValid(ent) then --local buttons = ents.FindInCone(pos, dir, PLAYER_USE_RADIUS, 0.8) - local buttons = ents.FindByClass("class C_BaseEntity") + local buttons = ents.FindInSphere(pos, PLAYER_USE_RADIUS) local rayDelta = dir * PLAYER_USE_RADIUS From 41fe5cb9bafd7e71b3ccf5f7e14fa06a3a47214c Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 15:04:09 +0800 Subject: [PATCH 05/21] destructible door stuff --- .../terrortown/gamemode/server/sv_player.lua | 12 ++++++++++ .../terrortown/gamemode/shared/sh_door.lua | 9 ++++++-- lua/ttt2/libraries/door.lua | 23 +++++++++++++++++-- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/gamemodes/terrortown/gamemode/server/sv_player.lua b/gamemodes/terrortown/gamemode/server/sv_player.lua index f669cada2..f390e789a 100644 --- a/gamemodes/terrortown/gamemode/server/sv_player.lua +++ b/gamemodes/terrortown/gamemode/server/sv_player.lua @@ -1319,6 +1319,18 @@ function GM:EntityTakeDamage(ent, dmginfo) end end +--- +-- Called after an entity receives a damage event, after passing damage filters, etc. +-- @param Entity ent The @{Entity} taking damage +-- @param CTakeDamageInfo dmginfo Damage info +-- @param boolean wasDamageTaken Whether the entity actually took the damage +-- @hook +-- @realm server +-- @ref https://wiki.facepunch.com/gmod/GM:PostEntityTakeDamage +function GM:PostEntityTakeDamage(ent, dmginfo, wasDamageTaken) + door.PostHandleDamage(ent, dmginfo, wasDamageTaken) +end + --- -- Called by @{GM:EntityTakeDamage} -- @param Entity ent The @{Entity} taking damage diff --git a/gamemodes/terrortown/gamemode/shared/sh_door.lua b/gamemodes/terrortown/gamemode/shared/sh_door.lua index 6d7234923..21613c070 100644 --- a/gamemodes/terrortown/gamemode/shared/sh_door.lua +++ b/gamemodes/terrortown/gamemode/shared/sh_door.lua @@ -110,7 +110,7 @@ function entmeta:DoorAutoCloses() end --- --- Retuens if a door is destructible. +-- Returns if a door is destructible. -- @return boolean If a door is destructible -- @realm shared function entmeta:DoorIsDestructible() @@ -118,6 +118,11 @@ function entmeta:DoorIsDestructible() return end + -- might be a little hacky + if self:Health() > 0 and self:GetMaxHealth() > 0 and (self:GetInternalVariable("m_takedamage") or 2) > 1 then + return true + end + return self:GetNWBool("ttt2_door_is_destructable", false) end @@ -138,7 +143,7 @@ end -- @return number The synced health -- @realm shared function entmeta:GetFastSyncedHealth() - return math.max(0, self:GetNWInt("fast_sync_health", 100)) + return math.max(0, self:GetNWInt("fast_sync_health", self:Health())) end if SERVER then diff --git a/lua/ttt2/libraries/door.lua b/lua/ttt2/libraries/door.lua index 4b4138453..c3c1dadd5 100644 --- a/lua/ttt2/libraries/door.lua +++ b/lua/ttt2/libraries/door.lua @@ -365,7 +365,7 @@ if SERVER then if door.IsValidNormal(cls) then return ent:HasSpawnFlags(SF_PROP_DOOR_START_BREAKABLE) elseif door.IsValidSpecial(cls) then - return false + return (ent:GetInternalVariable("m_takedamage") or 0) > 1 end return false @@ -454,6 +454,11 @@ if SERVER then return end + -- skip if engine already handles damage + if (ent:GetInternalVariable("m_takedamage") or 0) > 1 then + return + end + local damage = math.max(0, dmginfo:GetDamage()) local health = ent:Health() - damage @@ -473,7 +478,21 @@ if SERVER then end ent:SetHealth(health) - ent:SetNWInt("fast_sync_health", health) + end + + --- + -- Called in @{GM:PostEntityTakeDamage}. + -- @param Entity ent The entity that is damaged + -- @param CTakeDamageInfo dmginfo The damage info object + -- @param boolean wasDamageTaken Whether the entity actually took the damage + -- @internal + -- @realm server + function door.PostHandleDamage(ent, dmginfo, wasDamageTaken) + if not ent:DoorIsDestructible() then + return + end + + ent:SetNWInt("fast_sync_health", ent:Health()) end --- From de8a1c623cd52a5efa3cf122064d0987e9429d39 Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 16:00:00 +0800 Subject: [PATCH 06/21] let targetid check for children of doors/buttons --- lua/ttt2/libraries/targetid.lua | 41 +++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/lua/ttt2/libraries/targetid.lua b/lua/ttt2/libraries/targetid.lua index 57b7e24bd..8692078f3 100644 --- a/lua/ttt2/libraries/targetid.lua +++ b/lua/ttt2/libraries/targetid.lua @@ -663,13 +663,19 @@ function targetid.HUDDrawTargetIDButtons(tData) local client = LocalPlayer() local ent = tData:GetEntity() - if - not IsValid(client) - or not client:IsTerror() - or not IsValid(ent) - or not ent:IsButton() - or tData:GetEntityDistance() > 100 - then + if not IsValid(client) or not client:IsTerror() or not IsValid(ent) then + return + end + + if not ent:IsButton() then + ent = ent:GetMoveParent() + + if not IsValid(ent) or not ent:IsButton() then + return + end + end + + if tData:GetEntityDistance() > 100 then return end @@ -699,14 +705,19 @@ function targetid.HUDDrawTargetIDDoors(tData) local client = LocalPlayer() local ent = tData:GetEntity() - if - not IsValid(client) - or not client:IsTerror() - or not IsValid(ent) - or not ent:IsDoor() - or not ent:PlayerCanOpenDoor() - or tData:GetEntityDistance() > 90 - then + if not IsValid(client) or not client:IsTerror() or not IsValid(ent) then + return + end + + if not ent:IsDoor() then + ent = ent:GetMoveParent() + + if not IsValid(ent) or not ent:IsDoor() then + return + end + end + + if not ent:PlayerCanOpenDoor() or tData:GetEntityDistance() > 90 then return end From 926078ee764a527e5cb8b4c0c3c9fc6e1233b0d0 Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 16:02:27 +0800 Subject: [PATCH 07/21] use nw2vars instead of nwvars for doors --- .../terrortown/gamemode/shared/sh_door.lua | 26 +++++++-------- lua/ttt2/libraries/buttons.lua | 4 +-- lua/ttt2/libraries/door.lua | 32 +++++++++---------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/gamemodes/terrortown/gamemode/shared/sh_door.lua b/gamemodes/terrortown/gamemode/shared/sh_door.lua index 21613c070..4b95a2305 100644 --- a/gamemodes/terrortown/gamemode/shared/sh_door.lua +++ b/gamemodes/terrortown/gamemode/shared/sh_door.lua @@ -45,7 +45,7 @@ function entmeta:IsDoorLocked() return end - return self:GetNWBool("ttt2_door_locked", false) + return self:GetNW2Bool("ttt2_door_locked", false) end --- @@ -57,7 +57,7 @@ function entmeta:IsDoorForceclosed() return end - return self:GetNWBool("ttt2_door_forceclosed", false) + return self:GetNW2Bool("ttt2_door_forceclosed", false) end --- @@ -70,7 +70,7 @@ function entmeta:UseOpensDoor() return end - return self:GetNWBool("ttt2_door_player_use", false) + return self:GetNW2Bool("ttt2_door_player_use", false) end --- @@ -82,7 +82,7 @@ function entmeta:TouchOpensDoor() return end - return self:GetNWBool("ttt2_door_player_touch", false) + return self:GetNW2Bool("ttt2_door_player_touch", false) end --- @@ -106,7 +106,7 @@ function entmeta:DoorAutoCloses() return end - return self:GetNWBool("ttt2_door_auto_close", false) + return self:GetNW2Bool("ttt2_door_auto_close", false) end --- @@ -123,7 +123,7 @@ function entmeta:DoorIsDestructible() return true end - return self:GetNWBool("ttt2_door_is_destructable", false) + return self:GetNW2Bool("ttt2_door_is_destructable", false) end --- @@ -135,7 +135,7 @@ function entmeta:IsDoorOpen() return end - return self:GetNWBool("ttt2_door_open", false) + return self:GetNW2Bool("ttt2_door_open", false) end --- @@ -143,7 +143,7 @@ end -- @return number The synced health -- @realm shared function entmeta:GetFastSyncedHealth() - return math.max(0, self:GetNWInt("fast_sync_health", self:Health())) + return math.max(0, self:GetNW2Int("fast_sync_health", self:Health())) end if SERVER then @@ -264,7 +264,7 @@ if SERVER then function entmeta:SetDoorCanTouchOpen(state, surpressPair) door.SetPlayerCanTouch(self, state) - self:SetNWBool("ttt2_door_player_touch", door.PlayerCanTouch(self)) + self:SetNW2Bool("ttt2_door_player_touch", door.PlayerCanTouch(self)) -- if the door is grouped as a pair, call the other one as well if not surpressPair and IsValid(self.otherPairDoor) then @@ -280,7 +280,7 @@ if SERVER then function entmeta:SetDoorCanUseOpen(state, surpressPair) door.SetPlayerCanUse(self, state) - self:SetNWBool("ttt2_door_player_use", door.PlayerCanUse(self)) + self:SetNW2Bool("ttt2_door_player_use", door.PlayerCanUse(self)) -- if the door is grouped as a pair, call the other one as well if not surpressPair and IsValid(self.otherPairDoor) then @@ -296,7 +296,7 @@ if SERVER then function entmeta:SetDoorAutoCloses(state, surpressPair) door.SetAutoClose(self, state) - self:SetNWBool("ttt2_door_auto_close", door.AutoCloses(self)) + self:SetNW2Bool("ttt2_door_auto_close", door.AutoCloses(self)) -- if the door is grouped as a pair, call the other one as well if not surpressPair and IsValid(self.otherPairDoor) then @@ -314,12 +314,12 @@ if SERVER then return end - self:SetNWBool("ttt2_door_is_destructable", state) + self:SetNW2Bool("ttt2_door_is_destructable", state) if self:Health() == 0 then self:SetHealth(cvDoorHealth:GetInt()) - self:SetNWInt("fast_sync_health", self:Health()) + self:SetNW2Int("fast_sync_health", self:Health()) end -- if the door is grouped as a pair, call the other one as well diff --git a/lua/ttt2/libraries/buttons.lua b/lua/ttt2/libraries/buttons.lua index 399acbb4f..06493f16e 100644 --- a/lua/ttt2/libraries/buttons.lua +++ b/lua/ttt2/libraries/buttons.lua @@ -31,7 +31,7 @@ if SERVER then for j = 1, #buttonsTable do local foundButton = buttonsTable[j] - foundButton:SetNWInt("button_class", i) + foundButton:SetNW2Int("button_class", i) end end @@ -59,7 +59,7 @@ end -- @return boolean Returns true if the entity matches the provided class name -- @realm shared function button.IsClass(ent, class) - local classID = ent:GetNWInt("button_class") + local classID = ent:GetNW2Int("button_class") if not classID or classID > #validButtons then return diff --git a/lua/ttt2/libraries/door.lua b/lua/ttt2/libraries/door.lua index c3c1dadd5..4828581d3 100644 --- a/lua/ttt2/libraries/door.lua +++ b/lua/ttt2/libraries/door.lua @@ -182,14 +182,14 @@ if SERVER then doors[#doors + 1] = ent - ent:SetNWBool("ttt2_door_locked", ent:GetInternalVariable("m_bLocked") or false) - ent:SetNWBool("ttt2_door_forceclosed", ent:GetInternalVariable("forceclosed") or false) - ent:SetNWBool("ttt2_door_open", door.IsOpen(ent) or false) + ent:SetNW2Bool("ttt2_door_locked", ent:GetInternalVariable("m_bLocked") or false) + ent:SetNW2Bool("ttt2_door_forceclosed", ent:GetInternalVariable("forceclosed") or false) + ent:SetNW2Bool("ttt2_door_open", door.IsOpen(ent) or false) - ent:SetNWBool("ttt2_door_player_use", door.PlayerCanUse(ent)) - ent:SetNWBool("ttt2_door_player_touch", door.PlayerCanTouch(ent)) - ent:SetNWBool("ttt2_door_auto_close", door.AutoCloses(ent)) - ent:SetNWBool("ttt2_door_is_destructable", door.IsDestructible(ent)) + ent:SetNW2Bool("ttt2_door_player_use", door.PlayerCanUse(ent)) + ent:SetNW2Bool("ttt2_door_player_touch", door.PlayerCanTouch(ent)) + ent:SetNW2Bool("ttt2_door_auto_close", door.AutoCloses(ent)) + ent:SetNW2Bool("ttt2_door_is_destructable", door.IsDestructible(ent)) entityOutputs.RegisterMapEntityOutput(ent, "OnOpen", "TTT2DoorOpens") entityOutputs.RegisterMapEntityOutput(ent, "OnClose", "TTT2DoorCloses") @@ -492,7 +492,7 @@ if SERVER then return end - ent:SetNWInt("fast_sync_health", ent:Health()) + ent:SetNW2Int("fast_sync_health", ent:Health()) end --- @@ -596,7 +596,7 @@ if SERVER then -- we expect the door to be locked now, but we check the real state after a short -- amount of time to be sure - ent:SetNWBool("ttt2_door_locked", true) + ent:SetNW2Bool("ttt2_door_locked", true) -- check if the assumed state was correct timer.Create("ttt2_recheck_door_lock_" .. ent:EntIndex(), 1, 1, function() @@ -604,7 +604,7 @@ if SERVER then return end - ent:SetNWBool("ttt2_door_locked", ent:GetInternalVariable("m_bLocked") or false) + ent:SetNW2Bool("ttt2_door_locked", ent:GetInternalVariable("m_bLocked") or false) end) elseif name == "unlock" then --- @@ -617,7 +617,7 @@ if SERVER then -- we expect the door to be unlocked now, but we check the real state after a short -- amount of time to be sure - ent:SetNWBool("ttt2_door_locked", false) + ent:SetNW2Bool("ttt2_door_locked", false) -- check if the assumed state was correct timer.Create("ttt2_recheck_door_unlock_" .. ent:EntIndex(), 1, 1, function() @@ -625,7 +625,7 @@ if SERVER then return end - ent:SetNWBool("ttt2_door_locked", ent:GetInternalVariable("m_bLocked") or false) + ent:SetNW2Bool("ttt2_door_locked", ent:GetInternalVariable("m_bLocked") or false) end) elseif name == "use" and ent:IsDoorOpen() then -- do not stack closing time if door closes automatically @@ -676,7 +676,7 @@ if SERVER then return end - doorEntity:SetNWBool("ttt2_door_open", true) + doorEntity:SetNW2Bool("ttt2_door_open", true) end --- @@ -690,7 +690,7 @@ if SERVER then return end - doorEntity:SetNWBool("ttt2_door_open", true) + doorEntity:SetNW2Bool("ttt2_door_open", true) end --- @@ -704,7 +704,7 @@ if SERVER then return end - doorEntity:SetNWBool("ttt2_door_open", false) + doorEntity:SetNW2Bool("ttt2_door_open", false) end --- @@ -718,7 +718,7 @@ if SERVER then return end - doorEntity:SetNWBool("ttt2_door_open", false) + doorEntity:SetNW2Bool("ttt2_door_open", false) end --- From 624f4a676f10f16de9a3a94da623744791ba141c Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 16:43:29 +0800 Subject: [PATCH 08/21] fix invisible buttons being highlighted by targetid --- lua/ttt2/libraries/targetid.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lua/ttt2/libraries/targetid.lua b/lua/ttt2/libraries/targetid.lua index 8692078f3..ff6f97f55 100644 --- a/lua/ttt2/libraries/targetid.lua +++ b/lua/ttt2/libraries/targetid.lua @@ -667,6 +667,11 @@ function targetid.HUDDrawTargetIDButtons(tData) return end + -- button is supposed to be invisible + if ent:GetNoDraw() or ent:GetRenderMode() == RENDERMODE_NONE then + return + end + if not ent:IsButton() then ent = ent:GetMoveParent() @@ -709,6 +714,11 @@ function targetid.HUDDrawTargetIDDoors(tData) return end + -- door is supposed to be invisible + if ent:GetNoDraw() or ent:GetRenderMode() == RENDERMODE_NONE then + return + end + if not ent:IsDoor() then ent = ent:GetMoveParent() From 0f5b652554a15bee70a534a1484d5e086b3ba9d7 Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 16:57:02 +0800 Subject: [PATCH 09/21] style --- gamemodes/terrortown/gamemode/client/cl_keys.lua | 2 +- gamemodes/terrortown/gamemode/server/sv_player.lua | 2 +- gamemodes/terrortown/gamemode/shared/sh_door.lua | 6 +++++- lua/ttt2/libraries/targetid.lua | 6 +++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/gamemodes/terrortown/gamemode/client/cl_keys.lua b/gamemodes/terrortown/gamemode/client/cl_keys.lua index 8b2935db6..22a862852 100644 --- a/gamemodes/terrortown/gamemode/client/cl_keys.lua +++ b/gamemodes/terrortown/gamemode/client/cl_keys.lua @@ -108,7 +108,7 @@ function GM:PlayerBindPress(ply, bindName, pressed) end net.Start("TTT2PlayerUseEntity") - net.WriteBool(useEnt ~= nil) + --net.WriteBool(useEnt ~= nil) net.WriteEntity(useEnt) net.WriteBool(isRemote) net.SendToServer() diff --git a/gamemodes/terrortown/gamemode/server/sv_player.lua b/gamemodes/terrortown/gamemode/server/sv_player.lua index f390e789a..ef930c257 100644 --- a/gamemodes/terrortown/gamemode/server/sv_player.lua +++ b/gamemodes/terrortown/gamemode/server/sv_player.lua @@ -595,7 +595,7 @@ end -- @realm server -- @internal net.Receive("TTT2PlayerUseEntity", function(len, ply) - local hasEnt = net.ReadBool() + --local hasEnt = net.ReadBool() local ent = net.ReadEntity() local isRemote = net.ReadBool() diff --git a/gamemodes/terrortown/gamemode/shared/sh_door.lua b/gamemodes/terrortown/gamemode/shared/sh_door.lua index 4b95a2305..b27351cd6 100644 --- a/gamemodes/terrortown/gamemode/shared/sh_door.lua +++ b/gamemodes/terrortown/gamemode/shared/sh_door.lua @@ -119,7 +119,11 @@ function entmeta:DoorIsDestructible() end -- might be a little hacky - if self:Health() > 0 and self:GetMaxHealth() > 0 and (self:GetInternalVariable("m_takedamage") or 2) > 1 then + if + self:Health() > 0 + and self:GetMaxHealth() > 0 + and (self:GetInternalVariable("m_takedamage") or 2) > 1 + then return true end diff --git a/lua/ttt2/libraries/targetid.lua b/lua/ttt2/libraries/targetid.lua index ff6f97f55..8c9cc405d 100644 --- a/lua/ttt2/libraries/targetid.lua +++ b/lua/ttt2/libraries/targetid.lua @@ -144,7 +144,11 @@ function targetid.FindEntityAlongView(pos, dir, filter) end local _, _, frac = util.IntersectRayWithOBB( - pos, rayDelta, e:GetPos(), e:GetAngles(), e:GetCollisionBounds() + pos, + rayDelta, + e:GetPos(), + e:GetAngles(), + e:GetCollisionBounds() ) if not frac then From 3d6c8ba9d4a7fd134f65ea00718e738ebd947c37 Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 20:48:04 +0800 Subject: [PATCH 10/21] change how clientside door.GetAll() works --- lua/ttt2/libraries/door.lua | 63 +++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/lua/ttt2/libraries/door.lua b/lua/ttt2/libraries/door.lua index 4828581d3..ed9f14d7c 100644 --- a/lua/ttt2/libraries/door.lua +++ b/lua/ttt2/libraries/door.lua @@ -14,8 +14,6 @@ local Angle = Angle if SERVER then AddCSLuaFile() - - util.AddNetworkString("TTT2SyncDoorEntities") end --- @@ -58,9 +56,7 @@ SF_FUNC_DOOR_SILENT_GENERAL = 4096 door = door or {} -local door_list = { - doors = {}, -} +local door_list = {} local valid_doors = { special = { @@ -214,35 +210,7 @@ if SERVER then --- -- @realm server hook.Run("TTT2PostDoorSetup", doors) - - local amountDoors = #doors - - net.Start("TTT2SyncDoorEntities") - net.WriteUInt(amountDoors, 16) - - -- sync door list with clients - for i = 1, amountDoors do - net.WriteEntity(doors[i]) - end - - net.Broadcast() end -else -- CLIENT - net.Receive("TTT2SyncDoorEntities", function() - local amount = net.ReadUInt(16) - - local doors = {} - - for i = 1, amount do - doors[i] = net.ReadEntity() - end - - door_list.doors = doors - - --- - -- @realm client - hook.Run("TTT2PostDoorSetup", doors) - end) end --- @@ -276,7 +244,34 @@ end -- @return table A table of door entities -- @realm shared function door.GetAll() - return door_list.doors + return door_list.doors or {} +end + +if CLIENT then + function door.GetAll() + if not door_list.doors then + local doors = {} + + for _, ent in ents.Iterator() do + if IsValid(ent) and ent:IsDoor() then + doors[#doors + 1] = ent + end + end + + door_list.doors = doors + end + + return door_list.doors + end + + local function InvalidateDoorCache(ent) + if ent.IsDoor and ent:IsDoor() then + door_list.doors = nil + end + end + + hook.Add("OnEntityCreated", "TTT2InvalidateDoorCache", InvalidateDoorCache) + hook.Add("EntityRemoved", "TTT2InvalidateDoorCache", InvalidateDoorCache) end if SERVER then From 9747fd3877132a3072662182c47cafdb13f5eeba Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 20:50:46 +0800 Subject: [PATCH 11/21] style --- lua/ttt2/libraries/door.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lua/ttt2/libraries/door.lua b/lua/ttt2/libraries/door.lua index ed9f14d7c..3eb4f91cb 100644 --- a/lua/ttt2/libraries/door.lua +++ b/lua/ttt2/libraries/door.lua @@ -5,7 +5,6 @@ local string = string local player = player -local net = net local hook = hook local util = util local timer = timer @@ -260,7 +259,7 @@ if CLIENT then door_list.doors = doors end - + return door_list.doors end From 486eb5600a7f869f679d2d84e5b2855e25e853bf Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 20:53:52 +0800 Subject: [PATCH 12/21] style --- lua/ttt2/libraries/door.lua | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lua/ttt2/libraries/door.lua b/lua/ttt2/libraries/door.lua index 3eb4f91cb..38a2cd538 100644 --- a/lua/ttt2/libraries/door.lua +++ b/lua/ttt2/libraries/door.lua @@ -238,15 +238,19 @@ function door.IsValidSpecial(cls) return valid_doors.special[cls] or false end ---- --- Returns all valid door entities found on a map --- @return table A table of door entities --- @realm shared -function door.GetAll() - return door_list.doors or {} -end - -if CLIENT then +if SERVER then + --- + -- Returns all valid door entities found on a map + -- @return table A table of door entities + -- @realm server + function door.GetAll() + return door_list.doors or {} + end +else + --- + -- Returns all valid door entities found on a map + -- @return table A table of door entities + -- @realm client function door.GetAll() if not door_list.doors then local doors = {} From 17518e287d8af9cd6299f4a039ae1bf11c393bac Mon Sep 17 00:00:00 2001 From: wget Date: Mon, 10 Mar 2025 22:26:47 +0800 Subject: [PATCH 13/21] Update targetid.lua --- lua/ttt2/libraries/targetid.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lua/ttt2/libraries/targetid.lua b/lua/ttt2/libraries/targetid.lua index 8c9cc405d..e08cbd364 100644 --- a/lua/ttt2/libraries/targetid.lua +++ b/lua/ttt2/libraries/targetid.lua @@ -676,6 +676,7 @@ function targetid.HUDDrawTargetIDButtons(tData) return end + -- check if parent is button (for prop models parented to buttons and such) if not ent:IsButton() then ent = ent:GetMoveParent() @@ -723,6 +724,7 @@ function targetid.HUDDrawTargetIDDoors(tData) return end + -- check if parent is door (for doors with breakable glass and such) if not ent:IsDoor() then ent = ent:GetMoveParent() From 3c6c3211ded462b3120eb8bbb7d147c087e2c7f2 Mon Sep 17 00:00:00 2001 From: wget Date: Tue, 11 Mar 2025 10:36:53 +0800 Subject: [PATCH 14/21] override +use when using corpses and such --- .../terrortown/gamemode/client/cl_keys.lua | 17 ++++++++++------- .../terrortown/gamemode/server/sv_entity.lua | 7 ------- .../terrortown/gamemode/server/sv_player.lua | 1 - .../terrortown/gamemode/shared/sh_entity.lua | 12 ++++++++++++ 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/gamemodes/terrortown/gamemode/client/cl_keys.lua b/gamemodes/terrortown/gamemode/client/cl_keys.lua index 22a862852..c75651184 100644 --- a/gamemodes/terrortown/gamemode/client/cl_keys.lua +++ b/gamemodes/terrortown/gamemode/client/cl_keys.lua @@ -75,7 +75,7 @@ function GM:PlayerBindPress(ply, bindName, pressed) return TBHUD:UseFocused() end - -- Find out if a marker is focussed otherwise check normal use + -- Find out if a marker is focused otherwise check normal use local isClientOnly = false local useEnt = markerVision.GetFocusedEntity() local isRemote = IsValid(useEnt) @@ -104,14 +104,17 @@ function GM:PlayerBindPress(ply, bindName, pressed) -- If returned true by ClientUse or RemoteUse, then dont call Use and UseOverride or RemoteUse serverside if isClientOnly then - return + return true end - net.Start("TTT2PlayerUseEntity") - --net.WriteBool(useEnt ~= nil) - net.WriteEntity(useEnt) - net.WriteBool(isRemote) - net.SendToServer() + if IsValid(useEnt) and useEnt:IsSpecialUsableEntity() then + net.Start("TTT2PlayerUseEntity") + net.WriteEntity(useEnt) + net.WriteBool(isRemote) + net.SendToServer() + + return true + end elseif string.sub(bindName, 1, 4) == "slot" and pressed then local idx = tonumber(string.sub(bindName, 5, -1)) or 1 diff --git a/gamemodes/terrortown/gamemode/server/sv_entity.lua b/gamemodes/terrortown/gamemode/server/sv_entity.lua index c0112d158..9618ada46 100644 --- a/gamemodes/terrortown/gamemode/server/sv_entity.lua +++ b/gamemodes/terrortown/gamemode/server/sv_entity.lua @@ -110,13 +110,6 @@ function entmeta:IsUsableEntity(requiredCaps) return false end ---- --- @return boolean --- @realm server -function entmeta:IsSpecialUsableEntity() - return self:IsWeapon() or self.player_ragdoll or self.CanUseKey -end - --- -- Some sounds are important enough that they shouldn't be affected by CPASAttenuationFilter -- @param string snd The name of the sound to be played diff --git a/gamemodes/terrortown/gamemode/server/sv_player.lua b/gamemodes/terrortown/gamemode/server/sv_player.lua index ef930c257..6ce2a80d6 100644 --- a/gamemodes/terrortown/gamemode/server/sv_player.lua +++ b/gamemodes/terrortown/gamemode/server/sv_player.lua @@ -595,7 +595,6 @@ end -- @realm server -- @internal net.Receive("TTT2PlayerUseEntity", function(len, ply) - --local hasEnt = net.ReadBool() local ent = net.ReadEntity() local isRemote = net.ReadBool() diff --git a/gamemodes/terrortown/gamemode/shared/sh_entity.lua b/gamemodes/terrortown/gamemode/shared/sh_entity.lua index 6b95d1659..56b6a2d85 100644 --- a/gamemodes/terrortown/gamemode/shared/sh_entity.lua +++ b/gamemodes/terrortown/gamemode/shared/sh_entity.lua @@ -40,3 +40,15 @@ end function entmeta:IsButton() return self:IsDefaultButton() or self:IsRotatingButton() end + +--- +-- @return boolean +-- @realm server +function entmeta:IsSpecialUsableEntity() + return self:IsWeapon() + or self.player_ragdoll + or self:IsPlayerRagdoll() + or self.CanUseKey + or self.ClientUse + or self.RemoteUse +end \ No newline at end of file From eda95cecd1575780457ff64e41d90ff12777f866 Mon Sep 17 00:00:00 2001 From: wget Date: Tue, 11 Mar 2025 10:48:35 +0800 Subject: [PATCH 15/21] style --- gamemodes/terrortown/gamemode/shared/sh_entity.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamemodes/terrortown/gamemode/shared/sh_entity.lua b/gamemodes/terrortown/gamemode/shared/sh_entity.lua index 56b6a2d85..9c215d8f0 100644 --- a/gamemodes/terrortown/gamemode/shared/sh_entity.lua +++ b/gamemodes/terrortown/gamemode/shared/sh_entity.lua @@ -51,4 +51,4 @@ function entmeta:IsSpecialUsableEntity() or self.CanUseKey or self.ClientUse or self.RemoteUse -end \ No newline at end of file +end From 9db7f8ba8fb633786f0a6ff255c75e0fb019e449 Mon Sep 17 00:00:00 2001 From: wget Date: Tue, 11 Mar 2025 11:07:07 +0800 Subject: [PATCH 16/21] Update weapon_zm_improvised.lua --- .../terrortown/entities/weapons/weapon_zm_improvised.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua b/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua index fb868589d..b73ebbfc4 100644 --- a/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua +++ b/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua @@ -85,7 +85,7 @@ local pmnc_tbl = { } local function OpenableEnt(ent) - return pmnc_tbl[ent:GetClass()] or OPEN_NO + return ent:GetName() ~= "" and pmnc_tbl[ent:GetClass()] or OPEN_NO end local function CrowbarCanUnlock(t) @@ -108,7 +108,7 @@ function SWEP:OpenEnt(hitEnt) hitEnt:Fire("Unlock", nil, 0) end - if unlock or hitEnt:HasSpawnFlags(SF_NPC_LONG_RANGE) then -- Long Visibility/Shoot + if unlock or hitEnt:HasSpawnFlags(256) then if openable == OPEN_ROT then hitEnt:Fire("OpenAwayFrom", self:GetOwner(), 0) end From 4aa5ac24464bf9f3395c6d752a7b6b4c74a35f03 Mon Sep 17 00:00:00 2001 From: wget Date: Tue, 11 Mar 2025 11:51:58 +0800 Subject: [PATCH 17/21] Update CHANGELOG.md --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dd28403e..7b501d2df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,17 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel - Fixed classic armour protecting against crowbar damage (by @wgetJane) - Fixed C4/Radio sounds not playing outside of PAS (Facepunch/garrysmod/pull/2203, by @figardo) - Fixed players sometimes being revealed as dead when they chat/voicechat right as they die (Facepunch/garrysmod/pull/2229, by @wgetJane) +- Fixed various bugs related to using doors and buttons, to match base TTT behavior (by @wgetJane) + - Fixed brush doors on certain maps not being usable + - Fixed certain doors on certain maps being forcibly usable when they shouldn't be + - Fixed func_rotating being forcibly usable + - Removed forced button solidity + - Improved targetID trace detection for doors and buttons + - Allow brush doors to be detected as destructible for targetID + - Use NW2Vars instead of NWVars for door variables for more efficient networking + - Fixed clientside door.GetAll() to return a more updated list of doors + - Removed clientside TTT2PostDoorSetup hook + - Changed crowbar unlocking behavior to match base TTT ## [v0.14.2b](https://github.com/TTT-2/TTT2/tree/v0.14.2b) (2025-02-02) From f8e625c90f6dc3ad25c5151214f442b7ec577bda Mon Sep 17 00:00:00 2001 From: wget Date: Tue, 11 Mar 2025 13:18:40 +0800 Subject: [PATCH 18/21] make GM:TTT2PostDoorSetup server-only --- gamemodes/terrortown/gamemode/server/sv_main.lua | 7 +++++++ gamemodes/terrortown/gamemode/shared/sh_main.lua | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gamemodes/terrortown/gamemode/server/sv_main.lua b/gamemodes/terrortown/gamemode/server/sv_main.lua index 2f039fe11..c199c8aab 100644 --- a/gamemodes/terrortown/gamemode/server/sv_main.lua +++ b/gamemodes/terrortown/gamemode/server/sv_main.lua @@ -1007,3 +1007,10 @@ function GM:TTT2PreEndRound(result, duration) -- send the clients the round log, players will be shown the report events.StreamToClients() end + +--- +-- Called right after all doors are initialized on the map. +-- @param table doorsTable A table with the newly registered door entities +-- @hook +-- @realm server +function GM:TTT2PostDoorSetup(doorsTable) end diff --git a/gamemodes/terrortown/gamemode/shared/sh_main.lua b/gamemodes/terrortown/gamemode/shared/sh_main.lua index b0c90ca32..7d8378ddf 100644 --- a/gamemodes/terrortown/gamemode/shared/sh_main.lua +++ b/gamemodes/terrortown/gamemode/shared/sh_main.lua @@ -548,13 +548,6 @@ function GM:InitFallbackShops() end -- @realm shared function GM:LoadedFallbackShops() end ---- --- Called right after all doors are initialized on the map. --- @param table doorsTable A table with the newly registered door entities --- @hook --- @realm shared -function GM:TTT2PostDoorSetup(doorsTable) end - -- Called after all roles were loaded, @{ROLE:Preinitialize} and @{ROLE:Initialize} were called -- and their convars were set up. -- @hook From e53288a1076934fc9d999a6cce75dfd3eb95ed90 Mon Sep 17 00:00:00 2001 From: wget Date: Tue, 11 Mar 2025 15:55:24 +0800 Subject: [PATCH 19/21] whoever wrote this did not know that Entity:GetPos() does not return the centre of the entity and in fact it can even return Vector(0, 0, 0) so the correct function to use for this is Entity:WorldSpaceCenter() --- gamemodes/terrortown/gamemode/server/sv_player.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gamemodes/terrortown/gamemode/server/sv_player.lua b/gamemodes/terrortown/gamemode/server/sv_player.lua index 6ce2a80d6..0b510e3c2 100644 --- a/gamemodes/terrortown/gamemode/server/sv_player.lua +++ b/gamemodes/terrortown/gamemode/server/sv_player.lua @@ -577,7 +577,7 @@ local function EntityContinuousUse(ent, ply) end -- make sure the entity is still in a good position - local distance = ply:GetShootPos():Distance(ent:GetPos()) + local distance = ply:GetShootPos():Distance(ent:WorldSpaceCenter()) if distance > 100 + ent:BoundingRadius() then return @@ -612,7 +612,7 @@ net.Receive("TTT2PlayerUseEntity", function(len, ply) -- Check if the use interaction is possible -- Add the bounding radius to compensate for center position - local distance = ply:GetShootPos():Distance(ent:GetPos()) + local distance = ply:GetShootPos():Distance(ent:WorldSpaceCenter()) if distance > 100 + ent:BoundingRadius() then return end From 23df640064c8e60263f5e8156cc5768a3ef8e2cd Mon Sep 17 00:00:00 2001 From: wget Date: Wed, 12 Mar 2025 05:49:33 +0800 Subject: [PATCH 20/21] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b501d2df..90a87adb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel - Fixed brush doors on certain maps not being usable - Fixed certain doors on certain maps being forcibly usable when they shouldn't be - Fixed func_rotating being forcibly usable + - Fixed vehicles not being usable - Removed forced button solidity - Improved targetID trace detection for doors and buttons - Allow brush doors to be detected as destructible for targetID From bfb9673cbae145af11dbae1b4c8e586b7e58424e Mon Sep 17 00:00:00 2001 From: wget Date: Wed, 12 Mar 2025 06:02:32 +0800 Subject: [PATCH 21/21] Update weapon_zm_improvised.lua --- gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua b/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua index b73ebbfc4..341dbfda1 100644 --- a/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua +++ b/gamemodes/terrortown/entities/weapons/weapon_zm_improvised.lua @@ -108,7 +108,7 @@ function SWEP:OpenEnt(hitEnt) hitEnt:Fire("Unlock", nil, 0) end - if unlock or hitEnt:HasSpawnFlags(256) then + if unlock or hitEnt:HasSpawnFlags(256) then -- SF_DOOR_PUSE if openable == OPEN_ROT then hitEnt:Fire("OpenAwayFrom", self:GetOwner(), 0) end