diff --git a/CHANGELOG.md b/CHANGELOG.md index 88cf0a657..f5482e4b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,16 +44,19 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel ### Changed -- TargetID is now hidden when a marker vision element is focused -- Tracers are now drawn for every shot/pellet instead of only 25% of shots/pellets +- Placeable Entities are now checked for pickup clientside first (by @ZenBre4ker) + - C4 UI is not routed over the server anymore +- Visualizer can now only be picked up by the originator (by @ZenBre4ker) +- TargetID is now hidden when a marker vision element is focused (by @TimGoll) +- Tracers are now drawn for every shot/pellet instead of only 25% of shots/pellets (by @EntranceJew) - The ConVar "ttt_debug_preventwin" will now also prevent the time limit from ending the round (by @NickCloudAT) - `TTT2GiveFoundCredits` hook is no longer called when checking whether a player is allowed to take credits from a given corpse. (by @Spanospy) -- Micro optimizations +- Micro optimizations (by @EntranceJew) - switched from `player.GetAll()` to `select(2, player.Iterator())` - use `net.ReadPlayer` / `net.WritePlayer` if applicable instead of `net.Read|WriteEntity` - Reduced radar bit size for net message - The holdtype for pistol weapons now matches the viewmodel -- `VOICE.IsSpeaking(ply)` (clientside) can now be used to check if any player is speaking to you +- `VOICE.IsSpeaking(ply)` (clientside) can now be used to check if any player is speaking to you (by @TimGoll) - Unified the spec color usage throughout the whole UI (by @TimGoll) - Cleanup and performance optimizations for marks library (by @WardenPotato) - Updated the Turkish localization file (by @NovaDiablox) @@ -78,7 +81,8 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel ### Removed -- Removed radio tab in shop UI +- Removed radio tab in shop UI (by @ZenBre4ker) +- Removed all uses of UseOverride-Hook inside TTT2 (It's still available for addons!) (by @ZenBre4ker) - Removed `round_restart`, `round_selected` and `round_started` MStack messages to reduce message spawm (by @TimGoll) - Removed the old tips panel visible to spectators (moved to the new loading screen) (by @TimGoll) diff --git a/gamemodes/terrortown/entities/entities/ttt_base_placeable.lua b/gamemodes/terrortown/entities/entities/ttt_base_placeable.lua index 699eaa217..feb17023a 100644 --- a/gamemodes/terrortown/entities/entities/ttt_base_placeable.lua +++ b/gamemodes/terrortown/entities/entities/ttt_base_placeable.lua @@ -14,6 +14,8 @@ ENT.isDestructible = true ENT.pickupWeaponClass = nil +local soundDeny = Sound("HL2Player.UseDeny") + --- -- @realm shared function ENT:Initialize() @@ -41,6 +43,39 @@ function ENT:SetupDataTables() self:NetworkVar("Entity", 0, "Originator") end +--- +-- Run if a valid player tries to pick up this entity to check if this pickup is accepted. +-- @param Player activator The player that used their use key +-- @return[default=true] boolean Return true to allow pickup +-- @hook +-- @realm shared +function ENT:PlayerCanPickupWeapon(activator) + return true +end + +if CLIENT then + --- + -- 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 + -- @realm client + function ENT:ClientUse() + local client = LocalPlayer() + + if not IsValid(client) or not client:IsTerror() or not self.pickupWeaponClass then + return true + end + + if not self:PlayerCanPickupWeapon(client) then + LANG.Msg(client, "pickup_fail", nil, MSG_MSTACK_WARN) + + self:EmitSound(soundDeny) + + return true + end + end +end -- CLIENT + if SERVER then local soundRumble = { Sound("physics/concrete/concrete_break2.wav"), @@ -67,8 +102,6 @@ if SERVER then local soundThrow = Sound("Weapon_SLAM.SatchelThrow") - local soundDeny = Sound("HL2Player.UseDeny") - local soundWeaponPickup = Sound("items/ammo_pickup.wav") AccessorFunc(ENT, "hitNormal", "HitNormal", FORCE_VECTOR) @@ -232,12 +265,11 @@ if SERVER then --- -- Hook that is called if a player uses their use key while focusing on the entity. - -- @note When overwriting this function BaseClass.UseOverwrite has to be called if + -- @note When overwriting this function BaseClass.Use has to be called if -- the entity pickup system should be used. -- @param Player activator The player that used their use key - -- @hook -- @realm server - function ENT:UseOverride(activator) + function ENT:Use(activator) if not IsValid(activator) or not activator:IsTerror() or not self.pickupWeaponClass then return end @@ -281,16 +313,6 @@ if SERVER then self:Remove() end - --- - -- Run if a valid player tries to pick up this entity to check if this pickup is accepted. - -- @param Player activator The player that used their use key - -- @return[default=true] boolean Return true to allow pickup - -- @hook - -- @realm server - function ENT:PlayerCanPickupWeapon(activator) - return true - end - --- -- Called when this entity is picked up and about to be removed. -- @param Player activator The player that used their use key @@ -392,4 +414,4 @@ if SERVER then return true end -end +end -- SERVER diff --git a/gamemodes/terrortown/entities/entities/ttt_beacon.lua b/gamemodes/terrortown/entities/entities/ttt_beacon.lua index fa709f31a..7c0358d0b 100644 --- a/gamemodes/terrortown/entities/entities/ttt_beacon.lua +++ b/gamemodes/terrortown/entities/entities/ttt_beacon.lua @@ -19,7 +19,6 @@ ENT.Model = "models/props_lab/reciever01a.mdl" ENT.CanHavePrints = true -ENT.CanUseKey = true ENT.pickupWeaponClass = "weapon_ttt_beacon" ENT.timeLastBeep = CurTime() @@ -50,6 +49,13 @@ function ENT:Initialize() end end +--- +-- @param Player activator +-- @realm shared +function ENT:PlayerCanPickupWeapon(activator) + return self:GetOriginator() == activator +end + if SERVER then local soundBeep = Sound("weapons/c4/cc4_beep1.wav") @@ -127,13 +133,6 @@ if SERVER then self:RemoveMarkerVision("beacon_owner") end - --- - -- @param Player activator - -- @realm server - function ENT:PlayerCanPickupWeapon(activator) - return self:GetOriginator() == activator - end - --- -- @realm server function ENT:UpdateTransmitState() @@ -164,7 +163,7 @@ if SERVER then end --- - -- @realm server + -- @realm server -- stylua: ignore if hook.Run("TTT2BeaconDeathNotify", victim, beacon) == false then continue end @@ -229,12 +228,12 @@ if CLIENT then tData:SetTitle(TryT(ent.PrintName)) - if ent:GetOriginator() == client then + if ent:PlayerCanPickupWeapon(client) then tData:SetKeyBinding("+use") tData:SetSubtitle(ParT("target_pickup", { usekey = Key("+use", "USE") })) else tData:AddIcon(roles.DETECTIVE.iconMaterial) - tData:SetSubtitle(TryT("beacon_pickup_disabled")) + tData:SetSubtitle(TryT("entity_pickup_owner_only")) end tData:AddDescriptionLine(TryT("beacon_short_desc")) diff --git a/gamemodes/terrortown/entities/entities/ttt_c4/cl_init.lua b/gamemodes/terrortown/entities/entities/ttt_c4/cl_init.lua index bde1e872e..79ebb8dba 100644 --- a/gamemodes/terrortown/entities/entities/ttt_c4/cl_init.lua +++ b/gamemodes/terrortown/entities/entities/ttt_c4/cl_init.lua @@ -494,19 +494,6 @@ end ---- Communication -local function C4ConfigHook() - local bomb = net.ReadEntity() - - if IsValid(bomb) then - if not bomb:GetArmed() then - ShowC4Config(bomb) - else - ShowC4Disarm(bomb) - end - end -end -net.Receive("TTT_C4Config", C4ConfigHook) - local function C4DisarmResultHook() local bomb = net.ReadEntity() local correct = net.ReadBit() == 1 diff --git a/gamemodes/terrortown/entities/entities/ttt_c4/shared.lua b/gamemodes/terrortown/entities/entities/ttt_c4/shared.lua index c83a9b4c9..b162e6b93 100644 --- a/gamemodes/terrortown/entities/entities/ttt_c4/shared.lua +++ b/gamemodes/terrortown/entities/entities/ttt_c4/shared.lua @@ -33,7 +33,6 @@ ENT.Base = "ttt_base_placeable" ENT.Model = "models/weapons/w_c4_planted.mdl" ENT.CanHavePrints = true -ENT.CanUseKey = true ENT.Avoidable = true ENT.isDestructible = false @@ -126,15 +125,6 @@ function ENT:SetDetonateTimer(length) self:SetExplodeTime(CurTime() + length) end ---- --- @param Entity activator --- @realm shared -function ENT:UseOverride(activator) - if IsValid(activator) and activator:IsPlayer() then - self:ShowC4Config(activator) - end -end - --- -- @param number t -- @return number @@ -527,16 +517,6 @@ if SERVER then mvObject:SyncToClients() end - --- - -- @param Player ply - -- @realm server - function ENT:ShowC4Config(ply) - -- show menu to player to configure or disarm us - net.Start("TTT_C4Config") - net.WriteEntity(self) - net.Send(ply) - end - local function ReceiveC4Config(ply, cmd, args) if not (IsValid(ply) and ply:IsTerror() and #args == 2) then return @@ -793,6 +773,23 @@ else -- CLIENT antialias = false, }) + --- + -- 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 + -- @realm client + function ENT:ClientUse() + if IsValid(self) then + if not self:GetArmed() then + ShowC4Config(self) + else + ShowC4Disarm(self) + end + end + + return true + end + --- -- @return table pos -- @realm client diff --git a/gamemodes/terrortown/entities/entities/ttt_cse_proj.lua b/gamemodes/terrortown/entities/entities/ttt_cse_proj.lua index d2ded1247..6208053e5 100644 --- a/gamemodes/terrortown/entities/entities/ttt_cse_proj.lua +++ b/gamemodes/terrortown/entities/entities/ttt_cse_proj.lua @@ -18,7 +18,6 @@ ENT.MaxScenesPerPulse = 3 ENT.SceneDuration = 10 ENT.PulseDelay = 10 -ENT.CanUseKey = true ENT.pickupWeaponClass = "weapon_ttt_cse" --- @@ -38,6 +37,13 @@ function ENT:Initialize() self:SetHealth(50) end +--- +-- @param Player activator +-- @realm shared +function ENT:PlayerCanPickupWeapon(activator) + return self:GetOriginator() == activator +end + --- -- @realm shared function ENT:GetNearbyCorpses() @@ -186,15 +192,6 @@ if SERVER then return true end - - --- - -- @param Player activator - -- @realm server - function ENT:PlayerCanPickupWeapon(activator) - local roleDataActivator = activator:GetSubRoleData() - - return roleDataActivator.isPolicingRole and roleDataActivator.isPublicRole - end end if CLIENT then @@ -214,7 +211,6 @@ if CLIENT then hook.Add("TTTRenderEntityInfo", "HUDDrawTargetIDVisualizer", function(tData) local client = LocalPlayer() local ent = tData:GetEntity() - local roleData = client:GetSubRoleData() if not IsValid(client) @@ -233,12 +229,11 @@ if CLIENT then tData:SetTitle(TryT("vis_name")) - if roleData.isPublicRole and roleData.isPolicingRole then - tData:SetSubtitle(ParT("target_pickup", { usekey = Key("+use", "USE") })) + if ent:PlayerCanPickupWeapon(client) then tData:SetKeyBinding("+use") + tData:SetSubtitle(ParT("target_pickup", { usekey = Key("+use", "USE") })) else - tData:SetSubtitle(TryT("vis_no_pickup")) - tData:AddIcon(roles.DETECTIVE.iconMaterial) + tData:SetSubtitle(TryT("entity_pickup_owner_only")) end tData:AddDescriptionLine(TryT("vis_short_desc")) diff --git a/gamemodes/terrortown/entities/entities/ttt_decoy.lua b/gamemodes/terrortown/entities/entities/ttt_decoy.lua index 129ba1ab2..703839799 100644 --- a/gamemodes/terrortown/entities/entities/ttt_decoy.lua +++ b/gamemodes/terrortown/entities/entities/ttt_decoy.lua @@ -16,7 +16,6 @@ ENT.Model = "models/props_lab/reciever01b.mdl" ENT.CanHavePrints = false -ENT.CanUseKey = true ENT.pickupWeaponClass = "weapon_ttt_decoy" --- @@ -47,6 +46,14 @@ function ENT:OnRemove() self:GetOriginator().decoy = nil end +--- +-- @param Player activator +-- @realm shared +function ENT:PlayerCanPickupWeapon(activator) + return activator:HasTeam() + and self:GetNWString("decoy_owner_team", "none") == activator:GetTeam() +end + if SERVER then --- -- @realm server @@ -59,14 +66,6 @@ if SERVER then LANG.Msg(originator, "decoy_broken", nil, MSG_MSTACK_WARN) end - - --- - -- @param Player activator - -- @realm server - function ENT:PlayerCanPickupWeapon(activator) - return activator:HasTeam() - and self:GetNWString("decoy_owner_team", "none") == activator:GetTeam() - end end if CLIENT then @@ -95,10 +94,15 @@ if CLIENT then tData:SetOutlineColor(client:GetRoleColor()) tData:SetTitle(TryT("decoy_name")) - tData:SetSubtitle(ParT("target_pickup", { usekey = Key("+use", "USE") })) - tData:SetKeyBinding("+use") tData:AddDescriptionLine(TryT("decoy_short_desc")) + if ent:PlayerCanPickupWeapon(client) then + tData:SetSubtitle(ParT("target_pickup", { usekey = Key("+use", "USE") })) + tData:SetKeyBinding("+use") + else + tData:SetSubtitle(TryT("entity_pickup_owner_only")) + end + if ent:GetNWString("decoy_owner_team", "none") == client:GetTeam() then return end diff --git a/gamemodes/terrortown/entities/entities/ttt_hat_deerstalker.lua b/gamemodes/terrortown/entities/entities/ttt_hat_deerstalker.lua index c34c8a615..f2bd5659d 100644 --- a/gamemodes/terrortown/entities/entities/ttt_hat_deerstalker.lua +++ b/gamemodes/terrortown/entities/entities/ttt_hat_deerstalker.lua @@ -10,7 +10,6 @@ ENT.Base = "base_anim" ENT.PrintName = "hat_deerstalker_name" ENT.Model = Model("models/ttt/deerstalker.mdl") ENT.CanHavePrints = false -ENT.CanUseKey = true --- -- @realm shared @@ -131,7 +130,7 @@ if SERVER then --- -- @param Player ply -- @realm server - function ENT:UseOverride(ply) + function ENT:Use(ply) if not ttt_hats_reclaim:GetBool() then return end diff --git a/gamemodes/terrortown/entities/entities/ttt_health_station.lua b/gamemodes/terrortown/entities/entities/ttt_health_station.lua index 8e488070b..a88ac9dc3 100644 --- a/gamemodes/terrortown/entities/entities/ttt_health_station.lua +++ b/gamemodes/terrortown/entities/entities/ttt_health_station.lua @@ -17,7 +17,6 @@ end ENT.Base = "ttt_base_placeable" ENT.Model = "models/props/cs_office/microwave.mdl" ---ENT.CanUseKey = true ENT.CanHavePrints = true ENT.MaxHeal = 25 ENT.MaxStored = 200 @@ -146,24 +145,6 @@ function ENT:GiveHealth(ply, healthMax) return false end ---- --- @param Player ply --- @realm shared -function ENT:Use(ply) - if not IsValid(ply) or not ply:IsPlayer() or not ply:IsActive() then - return - end - - local t = CurTime() - if t < self.NextHeal then - return - end - - local healed = self:GiveHealth(ply, self.HealRate) - - self.NextHeal = t + (self.HealFreq * (healed and 1 or 2)) -end - if SERVER then -- recharge local nextcharge = 0 @@ -180,6 +161,24 @@ if SERVER then nextcharge = CurTime() + self.RechargeFreq end + --- + -- @param Player ply + -- @realm server + function ENT:Use(ply) + if not IsValid(ply) or not ply:IsPlayer() or not ply:IsActive() then + return + end + + local t = CurTime() + if t < self.NextHeal then + return + end + + local healed = self:GiveHealth(ply, self.HealRate) + + self.NextHeal = t + (self.HealFreq * (healed and 1 or 2)) + end + --- -- @realm server function ENT:WasDestroyed() @@ -200,6 +199,19 @@ 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() diff --git a/gamemodes/terrortown/entities/entities/ttt_radio.lua b/gamemodes/terrortown/entities/entities/ttt_radio.lua index a44df58dd..bfade0da7 100644 --- a/gamemodes/terrortown/entities/entities/ttt_radio.lua +++ b/gamemodes/terrortown/entities/entities/ttt_radio.lua @@ -21,7 +21,6 @@ ENT.Model = "models/props/cs_office/radio.mdl" ENT.CanHavePrints = false -ENT.CanUseKey = true ENT.pickupWeaponClass = "weapon_ttt_radio" ENT.SoundLimit = 5 @@ -63,6 +62,13 @@ function ENT:Initialize() self.fingerprints = {} end +--- +-- @param Player activator +-- @realm shared +function ENT:PlayerCanPickupWeapon(activator) + return activator == self:GetOriginator() +end + if SERVER then --- -- @realm server @@ -76,13 +82,6 @@ if SERVER then LANG.Msg(originator, "radio_broken", nil, MSG_MSTACK_WARN) end - --- - -- @param Player activator - -- @realm server - function ENT:PlayerCanPickupWeapon(activator) - return activator == self:GetOriginator() - end - --- -- @param Player activator -- @param Weapon wep @@ -332,13 +331,13 @@ if CLIENT then tData:SetTitle(TryT(ent.PrintName)) - if ent:GetOriginator() == client then + if ent:PlayerCanPickupWeapon(client) then + tData:SetKeyBinding("+use") tData:SetSubtitle(ParT("target_pickup", { usekey = Key("+use", "USE") })) else tData:SetSubtitle(TryT("entity_pickup_owner_only")) end - tData:SetKeyBinding("+use") tData:AddDescriptionLine(TryT("radio_short_desc")) end) diff --git a/gamemodes/terrortown/gamemode/server/sv_main.lua b/gamemodes/terrortown/gamemode/server/sv_main.lua index f2db2f7a4..7136c08f3 100644 --- a/gamemodes/terrortown/gamemode/server/sv_main.lua +++ b/gamemodes/terrortown/gamemode/server/sv_main.lua @@ -168,7 +168,6 @@ util.AddNetworkString("TTT_PerformGesture") util.AddNetworkString("TTT_Role") util.AddNetworkString("TTT_RoleList") util.AddNetworkString("TTT_ConfirmUseTButton") -util.AddNetworkString("TTT_C4Config") util.AddNetworkString("TTT_C4DisarmResult") util.AddNetworkString("TTT_ScanResult") util.AddNetworkString("TTT_FlareScorch") diff --git a/lua/terrortown/lang/en.lua b/lua/terrortown/lang/en.lua index 73dfe3fa6..b9c8ff478 100644 --- a/lua/terrortown/lang/en.lua +++ b/lua/terrortown/lang/en.lua @@ -2095,7 +2095,6 @@ Use to keep track of locations on the map that are hard to see.]] L.msg_beacon_destroyed = "One of your beacons has been destroyed!" L.msg_beacon_death = "A player died in close proximity to one of your beacons." -L.beacon_pickup_disabled = "Only the owner of the beacon can pick it up" L.beacon_short_desc = "Beacons are used by policing roles to add local wallhacks around them" -- 2023-12-18