From eb3b7f3aef7a79eacd4d54f86427879f75c9224c Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Sat, 25 Nov 2017 13:23:20 +0100 Subject: [PATCH] gamemode: Add new 'Selection Halo' feature This feature allows Hiders to easily tell which prop they will turn into if they press Use. As always, it can be fully configured and even turned off. By default it is enabled and set to Approximate mode. In Approximate mode, the client is responsible for guessing the best match to the Use key, but does not have any actual influence on what they will really turn into. This will in most cases be enough, as the internal Use test relies on the forward vector, which is checked by this mode. For those requiring more accuracy, there is the Accurate mode. In Accurate mode, the server is responsible for exactly knowing the best match to the Use key and sending this to the user. This has a server performance impact that scales with the player base and the rate at which these updates are performed can be configured. This mode is affected by lag and packet loss, so only really useful for high performance LAN servers or testing. --- .../prophuntextended/gamemode/cl_init.lua | 64 +++++++++++----- .../gamemode/player_class/class_default.lua | 5 +- .../gamemode/player_class/class_hider.lua | 26 +++++++ .../prophuntextended/gamemode/sh_config.lua | 76 +++++++++++++++++++ .../prophuntextended/prophuntextended.txt | 26 +++++++ 5 files changed, 178 insertions(+), 19 deletions(-) diff --git a/source/gamemodes/prophuntextended/gamemode/cl_init.lua b/source/gamemodes/prophuntextended/gamemode/cl_init.lua index 1df1506..1e5555b 100644 --- a/source/gamemodes/prophuntextended/gamemode/cl_init.lua +++ b/source/gamemodes/prophuntextended/gamemode/cl_init.lua @@ -230,26 +230,54 @@ function DrawNamePlates(bDrawingDepth, bDrawingSkybox) end hook.Add("PostDrawTranslucentRenderables", "PHDrawNamePlates", DrawNamePlates) +function DrawSelectionHalo(bDrawingDepth, bDrawingSkybox) + if (!GAMEMODE.Config.SelectionHalo:Enabled()) then return end + local ent = nil + if (GAMEMODE.Config.SelectionHalo:Approximate()) then + local trace = { + start = LocalPlayer():EyePos(), + endpos = LocalPlayer():EyePos() + LocalPlayer():EyeAngles():Forward() * 80, + mins = Vector(-16, -16, -16), + maxs = Vector( 16, 16, 16), + mask = MASK_SOLID + CONTENTS_DEBRIS + CONTENTS_PLAYERCLIP, + filter = function(ent) + -- Ensure that we don't actually hit ourselves by accident, or our "hands" model. + if (!IsValid(ent) + || (ent == LocalPlayer()) + || (ent == LocalPlayer():GetHands())) then + return false + end + if table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass()) then return true end + return false + end, + output = {} + } + util.TraceLine(trace) + if !IsValid(trace.output.Entity) then util.TraceHull(trace) end + if IsValid(trace.output.Entity) then + if (!table.HasValue(GAMEMODE.Config.Lists:ModelBlacklist(), trace.output.Entity:GetModel())) then + ent = trace.output.Entity + end + end + else + ent = LocalPlayer():GetNWEntity("SelectionHalo") + end + if IsValid(ent) then + local color = HSVToColor( + GAMEMODE.Config.SelectionHalo:TintHue(), + GAMEMODE.Config.SelectionHalo:TintSaturation(), + GAMEMODE.Config.SelectionHalo:TintValue() + ) + halo.Add({ ent }, color, + GAMEMODE.Config.SelectionHalo:BlurX(), GAMEMODE.Config.SelectionHalo:BlurY(), GAMEMODE.Config.SelectionHalo:Passes(), + GAMEMODE.Config.SelectionHalo:Additive(), GAMEMODE.Config.SelectionHalo:IgnoreZ()) + end +end +hook.Add("PostDrawEffects", "PHDrawSelectionHalo", DrawSelectionHalo) + -- ------------------------------------------------------------------------- -- --! Old Code -- ------------------------------------------------------------------------- -- --[[ -function DrawPlayerHalos(bDrawingDepth, bDrawingSkybox) - for i,v in ipairs(player.GetAll()) do - if v:Alive() then - local pos = v:GetPos() + Vector(0, 0, 1) * (v:OBBMaxs().z - v:OBBMins().z + 5) - local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x) - local healthPrc = v:Health() / v:GetMaxHealth() - local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0) - - if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then - local ent = v - if v.ph_prop && v.ph_prop:IsValid() then ent = v.ph_prop end - - halo.Add({ent}, healthCol, 2, 2, 1) - end - end - end -end ---hook.Add("PostDrawEffects", "PH_DrawPlayerHalos", DrawPlayerHalos) + ]] \ No newline at end of file diff --git a/source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua b/source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua index 2907973..4df17a9 100644 --- a/source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua +++ b/source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua @@ -44,7 +44,10 @@ CLASS.UseVMHands = true -- Uses viewmodel hands --! Server-Side -- ------------------------------------------------------------------------- -- -- Spawn -function CLASS:InitialSpawn() end +function CLASS:InitialSpawn() + self.Player.Data = {} + self.Player.Data.SelectionHaloTime = CurTime() +end function CLASS:Spawn() end function CLASS:Loadout() end diff --git a/source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua b/source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua index 48f1510..e558843 100644 --- a/source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua +++ b/source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua @@ -179,6 +179,32 @@ end -- ------------------------------------------------------------------------- -- --! Shared -- ------------------------------------------------------------------------- -- +if SERVER then + function CLASS:FindUseEntity(defEnt) + return self.Player:FindUseEntity() + end + + function CLASS:Tick(mv) + if (self.Player.Data == nil) then return end + + -- Selection Halo + if (GAMEMODE.Config.SelectionHalo:Allow()) && (!GAMEMODE.Config.SelectionHalo:Approximate()) then + if (self.Player.Data.SelectionHaloTime == nil) then + self.Player.Data.SelectionHaloTime = CurTime() + elseif ((CurTime() - self.Player.Data.SelectionHaloTime) > GAMEMODE.Config.SelectionHalo:Interval()) then + self.Player.Data.SelectionHaloTime = CurTime() + local ent = self.Player:FindUseEntity() + if (IsValid(ent) + && table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass()) + && !table.HasValue(GAMEMODE.Config.Lists:ModelBlacklist(), ent:GetModel())) then + self.Player:SetNWEntity("SelectionHalo", ent) + else + self.Player:SetNWBool("SelectionHalo", false) + end + end + end + end +end -- ------------------------------------------------------------------------- -- --! Client-Side diff --git a/source/gamemodes/prophuntextended/gamemode/sh_config.lua b/source/gamemodes/prophuntextended/gamemode/sh_config.lua index f26ee4b..f90f50a 100644 --- a/source/gamemodes/prophuntextended/gamemode/sh_config.lua +++ b/source/gamemodes/prophuntextended/gamemode/sh_config.lua @@ -462,3 +462,79 @@ if CLIENT then return self.ConVars.TintTeam:GetBool() end end + +-- ------------------------------------------------------------------------- -- +--! Selection Halo +-- ------------------------------------------------------------------------- -- +GM.Config.SelectionHalo = {} +GM.Config.SelectionHalo.ConVars = {} + +-- Allow +GM.Config.SelectionHalo.ConVars.Allow = CreateConVarIfNotExists("ph_selectionhalo_allow", "1", FCVAR_REPLICATED, "Selection Halo: Allow clients to enable halo around the currently looked at prop?") +function GM.Config.SelectionHalo:Allow() + return self.ConVars.Allow:GetBool() +end + +-- Approximate +GM.Config.SelectionHalo.ConVars.Approximate = CreateConVarIfNotExists("ph_selectionhalo_approximate", "1", FCVAR_REPLICATED, "Selection Halo: Enable approximate selection halo, which only checks the forward vector on the client.") +function GM.Config.SelectionHalo:Approximate() + return self.ConVars.Approximate:GetBool() +end + +if SERVER then + -- Update Interval + GM.Config.SelectionHalo.ConVars.Interval = CreateConVarIfNotExists("ph_selectionhalo_interval", "0.05", FCVAR_ARCHIVE, "Selection Halo: Interval for updates of the accuracte selection halo in seconds.") + function GM.Config.SelectionHalo:Interval() + return self.ConVars.Interval:GetFloat() + end +end + +if CLIENT then + -- Enabled + GM.Config.SelectionHalo.ConVars.Enabled = CreateConVarIfNotExists("ph_selectionhalo_enabled", "1", FCVAR_ARCHIVE, "Selection Halo: Enable halo around prop you might become.") + function GM.Config.SelectionHalo:Enabled() + if (self:Allow()) then + return self.ConVars.Enabled:GetBool() + else + return false + end + end + + -- Settings + GM.Config.SelectionHalo.ConVars.Passes = CreateConVarIfNotExists("ph_selectionhalo_passes", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Passes") + function GM.Config.SelectionHalo:Passes() + return self.ConVars.Passes:GetInt() + end + GM.Config.SelectionHalo.ConVars.Additive = CreateConVarIfNotExists("ph_selectionhalo_additive", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Additive") + function GM.Config.SelectionHalo:Additive() + return self.ConVars.Additive:GetBool() + end + GM.Config.SelectionHalo.ConVars.IgnoreZ = CreateConVarIfNotExists("ph_selectionhalo_ignorez", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Ignore Z") + function GM.Config.SelectionHalo:IgnoreZ() + return self.ConVars.IgnoreZ:GetBool() + end + + -- Blur + GM.Config.SelectionHalo.ConVars.BlurX = CreateConVarIfNotExists("ph_selectionhalo_blur_x", "2", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Blur X") + function GM.Config.SelectionHalo:BlurX() + return self.ConVars.BlurX:GetFloat() + end + GM.Config.SelectionHalo.ConVars.BlurY = CreateConVarIfNotExists("ph_selectionhalo_blur_y", "2", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Blur Y") + function GM.Config.SelectionHalo:BlurY() + return self.ConVars.BlurY:GetFloat() + end + + -- Tint Color + GM.Config.SelectionHalo.ConVars.TintHue = CreateConVarIfNotExists("ph_selectionhalo_tint_hue", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Tint Hue") + function GM.Config.SelectionHalo:TintHue() + return self.ConVars.TintHue:GetFloat() + end + GM.Config.SelectionHalo.ConVars.TintSaturation = CreateConVarIfNotExists("ph_selectionhalo_tint_saturation", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Tint Saturation") + function GM.Config.SelectionHalo:TintSaturation() + return self.ConVars.TintSaturation:GetFloat() + end + GM.Config.SelectionHalo.ConVars.TintValue = CreateConVarIfNotExists("ph_selectionhalo_tint_value", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Tint Value") + function GM.Config.SelectionHalo:TintValue() + return self.ConVars.TintValue:GetFloat() + end +end diff --git a/source/gamemodes/prophuntextended/prophuntextended.txt b/source/gamemodes/prophuntextended/prophuntextended.txt index 197f81d..ace6727 100644 --- a/source/gamemodes/prophuntextended/prophuntextended.txt +++ b/source/gamemodes/prophuntextended/prophuntextended.txt @@ -371,5 +371,31 @@ "help" "Camera: Maximum Camera Lag." } + // Selection Halo + 900 + { + "name" "ph_selectionhalo_allow" + "text" "Selection Halo Allowed" + "type" "CheckBox" + "default" "1" + "help" "Selection Halo: Allow clients to enable halo around the currently looked at prop?" + } + 901 + { + "name" "ph_selectionhalo_approximate" + "text" "Selection Approximate Mode" + "type" "CheckBox" + "default" "1" + "help" "Selection Halo: Enable approximate selection halo, which only checks the forward vector on the client." + } + 902 + { + "name" "ph_selectionhalo_interval" + "text" "Selection Halo Allowed" + "type" "Numeric" + "default" "0.05" + "help" "Selection Halo: Interval for updates of the accuracte selection halo in seconds." + } + } }