AddCSLuaFile( "cl_init.lua" ) AddCSLuaFile( "shared.lua" ) include('shared.lua') ENT.WireDebugName = "HUD Indicator" function ENT:Initialize() self.Entity:PhysicsInit( SOLID_VPHYSICS ) self.Entity:SetMoveType( MOVETYPE_VPHYSICS ) self.Entity:SetSolid( SOLID_VPHYSICS ) self.A = 0 self.AR = 0 self.AG = 0 self.AB = 0 self.AA = 0 self.B = 0 self.BR = 0 self.BG = 0 self.BB = 0 self.BA = 0 // List of players who have hooked this indicator self.RegisteredPlayers = {} self.PrefixText = "(Hud) Color = " self.Inputs = Wire_CreateInputs(self.Entity, { "A", "HideHUD" }) end function ENT:Setup(a, ar, ag, ab, aa, b, br, bg, bb, ba) self.A = a or 0 self.AR = ar or 255 self.AG = ag or 0 self.AB = ab or 0 self.AA = aa or 255 self.B = b or 1 self.BR = br or 0 self.BG = bg or 255 self.BB = bb or 0 self.BA = ba or 255 // Why is this here? (TheApathetic) //local factor = math.max(0, math.min(self.Inputs.A.Value-self.A/(self.B-self.A), 1)) // Moved to HUDSetup() to ensure that the entity is // registered in the HUD before the first value is passed //self:TriggerInput("A", 0) end // For HUD Indicators function ENT:HUDSetup(showinhud, huddesc, hudaddname, hudshowvalue, hudstyle, allowhook, fullcircleangle) local ply = self:GetPlayer() local eindex = self.Entity:EntIndex() // If user updates with the STool to take indicator off of HUD if (!showinhud && self.ShowInHUD) then self:UnRegisterPlayer(ply) // Adjust inputs back to normal //Wire_AdjustInputs(self.Entity, { "A" }) elseif (showinhud) then // Basic style is useless without a value // to show so set a default if necessary if (hudstyle == 0 && hudshowvalue == 0) then hudshowvalue = 1 end if (!self:CheckRegister(ply)) then // First-time register // Updating this player is handled further down self:RegisterPlayer(ply, true) end // Add name if desired if (hudaddname) then self.Entity:SetNetworkedString("WireName", huddesc) elseif (self.Entity:GetNetworkedString("WireName") == huddesc) then // Only remove it if the HUD Description was there // because there might be another name on it self.Entity:SetNetworkedString("WireName", "") end // Adjust inputs accordingly /* if (!self.Inputs.HideHUD) then Wire_AdjustInputs(self.Entity, { "A", "HideHUD" }) self:TriggerInput("HideHUD", 0) self.PrevHideHUD = false end */ end self.ShowInHUD = showinhud self.HUDDesc = huddesc self.HUDAddName = hudaddname self.HUDShowValue = hudshowvalue self.HUDStyle = hudstyle self.AllowHook = allowhook self.FullCircleAngle = fullcircleangle // To tell if you can hook a HUD Indicator at a glance if (allowhook) then self.PrefixText = "(Hud) Color = " else self.PrefixText = "(Hud - Locked) Color = " end // Update all registered players with this info for k,v in pairs(self.RegisteredPlayers) do self:RegisterPlayer(v.ply, v.hookhidehud) end // Only trigger this input on the // first time that Setup() is called if (!self.HasBeenSetup) then self:TriggerInput("A", self.A) self:TriggerInput("HideHUD", 0) self.PrevHideHUD = false self.HasBeenSetup = true end end // This is called from RegisterPlayer to send any style-specific info function ENT:SetupHUDStyle(hudstyle, rplayer) // 0 (Basic) and 1 (Gradient) don't require any extra info local pl = rplayer or self:GetPlayer() // Allow for hooked players //if (rplayer) then pl = rplayer end if (hudstyle == 2) then // Percent Bar // Send as string (there should be a way to send colors) local ainfo = self.AR.."|"..self.AG.."|"..self.AB local binfo = self.BR.."|"..self.BG.."|"..self.BB umsg.Start("HUDIndicatorStylePercent", pl) umsg.Short(self.Entity:EntIndex()) umsg.String(ainfo) umsg.String(binfo) umsg.End() elseif (hudstyle == 3) then // Full Circle Gauge umsg.Start("HUDIndicatorStyleFullCircle", pl) umsg.Short(self.Entity:EntIndex()) umsg.Float(self.FullCircleAngle) umsg.End() end end // Hook this player to the HUD Indicator function ENT:RegisterPlayer(ply, hookhidehud, podonly) local plyuid = ply:UniqueID() local eindex = self.Entity:EntIndex() // If player is already registered, this will send an update // The podonly is used for players who are registered only because they are in a linked pod if (!self.RegisteredPlayers[plyuid]) then self.RegisteredPlayers[plyuid] = { ply = ply, hookhidehud = hookhidehud, podonly = podonly } // This is used to check for pod-only status in ClientCheckRegister() self.Entity:SetNetworkedBool( plyuid, util.tobool(podonly) ) end umsg.Start("HUDIndicatorRegister", ply) umsg.Short(eindex) umsg.String(self.HUDDesc or "") umsg.Short(self.HUDShowValue) umsg.Short(self.HUDStyle) umsg.End() self:SetupHUDStyle(self.HUDStyle, ply) // Trigger inputs to fully add this player to the list // Force factor to update self.PrevOutput = nil self:TriggerInput("A", self.Inputs.A.Value) if (hookhidehud) then self:TriggerInput("HideHUD", self.Inputs.HideHUD.Value) end end function ENT:UnRegisterPlayer(ply) umsg.Start("HUDIndicatorUnRegister", ply) umsg.Short(self.Entity:EntIndex()) umsg.End() self.RegisteredPlayers[ply:UniqueID()] = nil end // Is this player registered? function ENT:CheckRegister(ply) return (self.RegisteredPlayers[ply:UniqueID()] != nil) end // Is this player registered only because he is in a linked pod? function ENT:CheckPodOnly(ply) local plyuid = ply:UniqueID() return (self.RegisteredPlayers[plyuid] != nil && self.RegisteredPlayers[plyuid].podonly) end function ENT:TriggerInput(iname, value) if (iname == "A") then local factor = math.Clamp((value-self.A)/(self.B-self.A), 0, 1) self:ShowOutput(factor, value) local r = math.Clamp((self.BR-self.AR)*factor+self.AR, 0, 255) local g = math.Clamp((self.BG-self.AG)*factor+self.AG, 0, 255) local b = math.Clamp((self.BB-self.AB)*factor+self.AB, 0, 255) local a = math.Clamp((self.BA-self.AA)*factor+self.AA, 0, 255) self.Entity:SetColor(r, g, b, a) elseif (iname == "HideHUD") then if (self.PrevHideHUD == (value > 0)) then return end self.PrevHideHUD = (value > 0) // Value has updated, so send information self:SendHUDInfo(self.PrevHideHUD) end end function ENT:ShowOutput(factor, value) if (factor ~= self.PrevOutput) then self:SetOverlayText( self.PrefixText .. string.format("%.1f", (factor * 100)) .. "%" ) self.PrevOutput = factor local rf = RecipientFilter() local pl = self:GetPlayer() // RecipientFilter will contain all registered players for index,rplayer in pairs(self.RegisteredPlayers) do if (rplayer.ply) then if (rplayer.ply != pl || (self.ShowInHUD || self.PodPly == pl)) then rf:AddPlayer(rplayer.ply) end else self.RegisteredPlayers[index] = nil end end umsg.Start("HUDIndicatorFactor", rf) umsg.Short(self.Entity:EntIndex()) // Send both to ensure that all styles work properly umsg.Float(factor) umsg.Float(value) umsg.End() end end function ENT:SendHUDInfo(hidehud) // Sends information to player local pl = self:GetPlayer() for index,rplayer in pairs(self.RegisteredPlayers) do if (rplayer.ply) then if (rplayer.ply != pl || (self.ShowInHUD || self.PodPly == pl)) then umsg.Start("HUDIndicatorHideHUD", rplayer.ply) umsg.Short(self.Entity:EntIndex()) // Check player's preference if (rplayer.hookhidehud) then umsg.Bool(hidehud) else umsg.Bool(false) end umsg.End() end else self.RegisteredPlayers[index] = nil end end end // Despite everything being named "pod", any vehicle will work function ENT:LinkVehicle(pod) if (!pod || !pod:IsValid() || !string.find(pod:GetClass(), "prop_vehicle_")) then return false end local ply = nil // Check if a player is in pod first for k,v in pairs(player.GetAll()) do if (v:GetVehicle() == pod) then ply = v break end end if (ply && !self:CheckRegister(ply)) then // Register as "only in pod" if not registered before self:RegisterPlayer(ply, false, true) // Force factor to update self.PrevOutput = nil self:TriggerInput("A", self.Inputs.A.Value) end self.Pod = pod self.PodPly = ply return true end function ENT:UnLinkVehicle() local ply = self.PodPly if (ply && self:CheckPodOnly(ply)) then // Only unregister if player is registered only because he is in a linked pod self:UnRegisterPlayer(ply) end self.Pod = nil self.PodPly = nil end function ENT:Think() self.BaseClass.Think(self) if (self.Pod && self.Pod:IsValid()) then local ply = nil if (!self.PodPly || self.PodPly:GetVehicle() != self.Pod) then for k,v in pairs(player.GetAll()) do if (v:GetVehicle() == self.Pod) then ply = v break end end else ply = self.PodPly end // Has the player changed? if (ply != self.PodPly) then if (self.PodPly && self:CheckPodOnly(self.PodPly)) then // Don't send umsg if player disconnected or is registered otherwise self:UnRegisterPlayer(self.PodPly) end self.PodPly = ply if (self.PodPly && !self:CheckRegister(self.PodPly)) then self:RegisterPlayer(self.PodPly, false, true) // Force factor to update self.PrevOutput = nil self:TriggerInput("A", self.Inputs.A.Value) end end else // If we deleted this pod and there was a player in it if (self.PodPly && self:CheckPodOnly(self.PodPly)) then self:UnRegisterPlayer(self.PodPly) end self.PodPly = nil end self.Entity:NextThink(CurTime() + 0.1) return true end // Advanced Duplicator Support function ENT:BuildDupeInfo() local info = self.BaseClass.BuildDupeInfo(self) or {} if (self.Pod) and (self.Pod:IsValid()) then info.pod = self.Pod:EntIndex() end return info end function ENT:ApplyDupeInfo(ply, ent, info, GetEntByID) self.BaseClass.ApplyDupeInfo(self, ply, ent, info, GetEntByID) if (info.pod) then self.Pod = GetEntByID(info.pod) if (!self.Pod) then self.Pod = ents.GetByIndex(info.pod) end end end