Skip to content
Draft
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
6 changes: 3 additions & 3 deletions gamemodes/terrortown/entities/entities/ttt_base_placeable.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ ENT.isDestructible = true

ENT.pickupWeaponClass = nil

ENT.CanUseKey = true

local soundDeny = Sound("HL2Player.UseDeny")

---
Expand Down Expand Up @@ -56,10 +54,12 @@ function ENT:PlayerCanPickupWeapon(activator)
end

if CLIENT then
-- TODO: Remove? This is not really that efficient anyway
---
-- Hook that is called if a player uses their use key while focusing on the entity.
-- Implement this to predict early if entity can be picked up
-- @return bool True to prevent pickup
-- @note This is only called once. Continuous use is not supported here.
-- @return bool True to suppress the actual +use operation of the entity on the Server.
-- @realm client
function ENT:ClientUse()
local client = LocalPlayer()
Expand Down
2 changes: 1 addition & 1 deletion gamemodes/terrortown/entities/entities/ttt_c4/shared.lua
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ else -- CLIENT
---
-- Hook that is called if a player uses their use key while focusing on the entity.
-- Shows C4 UI
-- @return bool True to prevent pickup
-- @return bool True to only run on the clientside
-- @realm client
function ENT:ClientUse()
if IsValid(self) then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ ENT.PrintName = "hat_deerstalker_name"
ENT.Model = Model("models/ttt/deerstalker.mdl")
ENT.CanHavePrints = false

ENT.CanUseKey = true

---
-- @realm shared
function ENT:SetupDataTables()
Expand Down
21 changes: 8 additions & 13 deletions gamemodes/terrortown/entities/entities/ttt_health_station.lua
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,14 @@ if SERVER then
return
end

Dev(
1,
"[TTT2][HealthStation] Player "
.. ply:Nick()
.. " used health station "
.. self:EntIndex()
)

local t = CurTime()
if t < self.NextHeal then
return
Expand Down Expand Up @@ -198,19 +206,6 @@ else
walkkey = Key("+walk", "WALK"),
}

---
-- Hook that is called if a player uses their use key while focusing on the entity.
-- Early check if client can use the health station
-- @return bool True to prevent pickup
-- @realm client
function ENT:ClientUse()
local client = LocalPlayer()

if not IsValid(client) or not client:IsPlayer() or not client:IsActive() then
return true
end
end

-- handle looking at healthstation
hook.Add("TTTRenderEntityInfo", "HUDDrawTargetIDHealthStation", function(tData)
local client = LocalPlayer()
Expand Down
97 changes: 70 additions & 27 deletions gamemodes/terrortown/gamemode/client/cl_keys.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ function GM:PlayerBindPress(ply, bindName, pressed)
return
end

Dev(2, "[TTT2][Keys] PlayerBindPress: " .. bindName .. " pressed: " .. tostring(pressed))

if bindName == "invnext" and pressed then
if not ply:IsSpec() then
WSWITCH:SelectNext()
Expand All @@ -64,6 +66,19 @@ function GM:PlayerBindPress(ply, bindName, pressed)
return true
end
elseif bindName == "+use" and pressed then
-- Handle special spectator use override
if ply:IsSpec() then
net.Start("TTT2PlayerUseEntity")
net.WriteEntity(nil)
net.WriteString("spectator_use")
net.SendToServer()

Dev(1, "specuse use triggered")

-- Suppress the +use bind
return true
end

-- Do old traitor button check
if TBHUD:PlayerIsFocused() then
if ply:KeyDown(IN_WALK) then
Expand All @@ -76,45 +91,73 @@ function GM:PlayerBindPress(ply, bindName, pressed)
end

-- Find out if a marker is focused otherwise check normal use
local isClientOnly = false
local useEnt = markerVision.GetFocusedEntity()
local isRemote = IsValid(useEnt)
if not isRemote then
local tr = util.TraceLine({
start = ply:GetShootPos(),
endpos = ply:GetShootPos() + ply:GetAimVector() * 100,
filter = ply,
mask = MASK_ALL,
})

useEnt = tr.Entity

if not tr.Hit or not IsValid(useEnt) then
useEnt = nil
end
local markerVisionFocusedEnt = markerVision.GetFocusedEntity()

if useEnt and isfunction(useEnt.ClientUse) then
isClientOnly = useEnt:ClientUse()
end
elseif isfunction(useEnt.RemoteUse) then
if IsValid(markerVisionFocusedEnt) and isfunction(markerVisionFocusedEnt.RemoteUse) then
sound.ConditionalPlay(soundUse, SOUND_TYPE_INTERACT)

isClientOnly = useEnt:RemoteUse(ply)
end
local clientsideOnly = markerVisionFocusedEnt:RemoteUse()

-- If returned true by ClientUse or RemoteUse, then dont call Use and UseOverride or RemoteUse serverside
if isClientOnly then
if not clientsideOnly then
-- Call this on the server too.
-- This cannot be done on the server's Entity:Use hook etc., because we suppress the +use bind here to not trigger it
-- on other close by entities.

net.Start("TTT2PlayerUseEntity")
net.WriteEntity(markerVisionFocusedEnt)
net.WriteString("remote_use")
net.SendToServer()
end

Dev(1, "markervision use triggered")

-- Suppress the +use bind here, so it does not trigger the Entity:Use hook on other close by entities.
-- Suppressing means, that the server will not see this key as being pressed anymore, even if the client is still pressing it.
return true
end

if IsValid(useEnt) and (ply:IsSpec() or useEnt:IsSpecialUsableEntity()) then
-- This can sometimes deviate from the entity that the server actually uses.
-- But this is fine for now.
-- See https://github.com/Facepunch/garrysmod-issues/issues/5027
local clientUseEnt = ply:GetUseEntity()

if IsValid(clientUseEnt) and isfunction(clientUseEnt.ClientUse) then
-- This does not reliably block +use on entities. You should not rely on this to block +use on entities.
-- E.g. when pressing +use and running into an enity, the server will still call Entity:Use on that entity.
-- Because this function is not reevaluated, when the player is still pressing +use.
-- TODO: Maybe remove the clientsideOnly?
local clientsideOnly = clientUseEnt:ClientUse()

Dev(
2,
"client use triggered on "
.. clientUseEnt:GetClass()
.. " with clientsideOnly: "
.. tostring(clientsideOnly)
)

if clientsideOnly then
-- Suppress the +use bind
return true
end
end

-- Handle special weapon pickup use override
local trace = util.QuickTrace(ply:GetShootPos(), ply:GetAimVector() * 100, ply)

if IsValid(trace.Entity) and trace.Entity:IsWeapon() then
net.Start("TTT2PlayerUseEntity")
net.WriteEntity(useEnt)
net.WriteBool(isRemote)
net.WriteEntity(trace.Entity)
net.WriteString("weapon_pickup")
net.SendToServer()

Dev(1, "weapon use triggered")

-- Suppress the +use bind
return true
end

-- Otherwise the +use is executed as usual, triggering the server-side Entity:Use function.
elseif string.sub(bindName, 1, 4) == "slot" and pressed then
local idx = tonumber(string.sub(bindName, 5, -1)) or 1

Expand Down
40 changes: 0 additions & 40 deletions gamemodes/terrortown/gamemode/server/sv_entity.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@
-- @ref https://wiki.facepunch.com/gmod/Entity
-- @class Entity

-- Caps taken from here: https://github.com/ValveSoftware/source-sdk-2013/blob/55ed12f8d1eb6887d348be03aee5573d44177ffb/mp/src/game/shared/baseentity_shared.h#L21-L38
FCAP_IMPULSE_USE = 16
FCAP_CONTINUOUS_USE = 32
FCAP_ONOFF_USE = 64
FCAP_DIRECTIONAL_USE = 128
FCAP_USE_ONGROUND = 256
FCAP_USE_IN_RADIUS = 512

local safeCollisionGroups = {
[COLLISION_GROUP_WEAPON] = true,
}
Expand Down Expand Up @@ -78,38 +70,6 @@ function entmeta:Spawn()
oldSpawn(self)
end

---
-- Checks if the entity has any use functionality attached. This can be attached in the engine/via hammer or by
-- setting `.CanUseKey` to true. Player ragdolls and weapons always have use functionality attached.
-- @param[default=0] number requiredCaps Use caps that are required for this entity
-- @return boolean Returns true if the entity is usable by the player
-- @ref https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/sp/src/game/server/player.cpp#L2766C71-L2781
-- @realm server
function entmeta:IsUsableEntity(requiredCaps)
requiredCaps = requiredCaps or 0

-- special case: TTT specific lua based use interactions
-- when we're looking for specifically the lua use
if self:IsSpecialUsableEntity() then
return true
end

local caps = self:ObjectCaps()

if
bit.band(
caps,
bit.bor(FCAP_IMPULSE_USE, FCAP_CONTINUOUS_USE, FCAP_ONOFF_USE, FCAP_DIRECTIONAL_USE)
)
> 0
and bit.band(caps, requiredCaps) == requiredCaps
then
return true
end

return false
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
Expand Down
Loading
Loading