mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
323 lines
8.4 KiB
Lua
323 lines
8.4 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
-- Traitor radar rendering
|
|
|
|
local render = render
|
|
local surface = surface
|
|
local string = string
|
|
local player = player
|
|
local math = math
|
|
|
|
RADAR = {}
|
|
RADAR.targets = {}
|
|
RADAR.enable = false
|
|
RADAR.duration = 30
|
|
RADAR.endtime = 0
|
|
RADAR.bombs = {}
|
|
RADAR.bombs_count = 0
|
|
RADAR.repeating = true
|
|
RADAR.samples = {}
|
|
RADAR.samples_count = 0
|
|
|
|
RADAR.called_corpses = {}
|
|
|
|
function RADAR:EndScan()
|
|
self.enable = false
|
|
self.endtime = CurTime()
|
|
end
|
|
|
|
function RADAR:Clear()
|
|
self:EndScan()
|
|
self.bombs = {}
|
|
self.samples = {}
|
|
|
|
self.bombs_count = 0
|
|
self.samples_count = 0
|
|
end
|
|
|
|
function RADAR:Timeout()
|
|
self:EndScan()
|
|
|
|
if self.repeating and LocalPlayer() and LocalPlayer():IsActiveSpecial() and LocalPlayer():HasEquipmentItem(EQUIP_RADAR) then
|
|
RunConsoleCommand("ttt_radar_scan")
|
|
end
|
|
end
|
|
|
|
-- cache stuff we'll be drawing
|
|
function RADAR.CacheEnts()
|
|
-- also do some corpse cleanup here
|
|
for k, corpse in pairs(RADAR.called_corpses) do
|
|
if (corpse.called + 45) < CurTime() then
|
|
RADAR.called_corpses[k] = nil -- will make # inaccurate, no big deal
|
|
end
|
|
end
|
|
|
|
if RADAR.bombs_count == 0 then return end
|
|
|
|
-- Update bomb positions for those we know about
|
|
for idx, b in pairs(RADAR.bombs) do
|
|
local ent = Entity(idx)
|
|
if IsValid(ent) then
|
|
b.pos = ent:GetPos()
|
|
end
|
|
end
|
|
end
|
|
|
|
function RADAR.Bought(is_item, id)
|
|
if is_item and id == EQUIP_RADAR then
|
|
RunConsoleCommand("ttt_radar_scan")
|
|
end
|
|
end
|
|
hook.Add("TTTBoughtItem", "RadarBoughtItem", RADAR.Bought)
|
|
|
|
local function DrawTarget(tgt, size, offset, no_shrink)
|
|
local scrpos = tgt.pos:ToScreen() -- sweet
|
|
local sz = (IsOffScreen(scrpos) and (not no_shrink)) and size/2 or size
|
|
|
|
scrpos.x = math.Clamp(scrpos.x, sz, ScrW() - sz)
|
|
scrpos.y = math.Clamp(scrpos.y, sz, ScrH() - sz)
|
|
|
|
if IsOffScreen(scrpos) then return end
|
|
|
|
surface.DrawTexturedRect(scrpos.x - sz, scrpos.y - sz, sz * 2, sz * 2)
|
|
|
|
-- Drawing full size?
|
|
if sz == size then
|
|
local text = math.ceil(LocalPlayer():GetPos():Distance(tgt.pos))
|
|
local w, h = surface.GetTextSize(text)
|
|
|
|
-- Show range to target
|
|
surface.SetTextPos(scrpos.x - w/2, scrpos.y + (offset * sz) - h/2)
|
|
surface.DrawText(text)
|
|
|
|
if tgt.t then
|
|
-- Show time
|
|
text = util.SimpleTime(tgt.t - CurTime(), "%02i:%02i")
|
|
w, h = surface.GetTextSize(text)
|
|
|
|
surface.SetTextPos(scrpos.x - w / 2, scrpos.y + sz / 2)
|
|
surface.DrawText(text)
|
|
elseif tgt.nick then
|
|
-- Show nickname
|
|
text = tgt.nick
|
|
w, h = surface.GetTextSize(text)
|
|
|
|
surface.SetTextPos(scrpos.x - w / 2, scrpos.y + sz / 2)
|
|
surface.DrawText(text)
|
|
end
|
|
end
|
|
end
|
|
|
|
local indicator = surface.GetTextureID("effects/select_ring")
|
|
local c4warn = surface.GetTextureID("vgui/ttt/icon_c4warn")
|
|
local sample_scan = surface.GetTextureID("vgui/ttt/sample_scan")
|
|
local det_beacon = surface.GetTextureID("vgui/ttt/det_beacon")
|
|
|
|
local GetPTranslation = LANG.GetParamTranslation
|
|
local FormatTime = util.SimpleTime
|
|
|
|
local near_cursor_dist = 180
|
|
|
|
function RADAR:Draw(client)
|
|
if not client then return end
|
|
|
|
surface.SetFont("HudSelectionText")
|
|
|
|
-- C4 warnings
|
|
if self.bombs_count != 0 and client:IsActiveTraitor() then
|
|
surface.SetTexture(c4warn)
|
|
surface.SetTextColor(200, 55, 55, 220)
|
|
surface.SetDrawColor(255, 255, 255, 200)
|
|
|
|
for k, bomb in pairs(self.bombs) do
|
|
DrawTarget(bomb, 24, 0, true)
|
|
end
|
|
end
|
|
|
|
-- Corpse calls
|
|
if client:IsActiveDetective() and #self.called_corpses then
|
|
surface.SetTexture(det_beacon)
|
|
surface.SetTextColor(255, 255, 255, 240)
|
|
surface.SetDrawColor(255, 255, 255, 230)
|
|
|
|
for k, corpse in pairs(self.called_corpses) do
|
|
DrawTarget(corpse, 16, 0.5)
|
|
end
|
|
end
|
|
|
|
-- Samples
|
|
if self.samples_count != 0 then
|
|
surface.SetTexture(sample_scan)
|
|
surface.SetTextColor(200, 50, 50, 255)
|
|
surface.SetDrawColor(255, 255, 255, 240)
|
|
|
|
for k, sample in pairs(self.samples) do
|
|
DrawTarget(sample, 16, 0.5, true)
|
|
end
|
|
end
|
|
|
|
-- Player radar
|
|
if (not self.enable) or (not client:IsActiveSpecial()) then return end
|
|
|
|
surface.SetTexture(indicator)
|
|
|
|
local remaining = math.max(0, RADAR.endtime - CurTime())
|
|
local alpha_base = 50 + 180 * (remaining / RADAR.duration)
|
|
|
|
local mpos = Vector(ScrW() / 2, ScrH() / 2, 0)
|
|
|
|
local role, alpha, scrpos, md
|
|
for k, tgt in pairs(RADAR.targets) do
|
|
alpha = alpha_base
|
|
|
|
scrpos = tgt.pos:ToScreen()
|
|
if not scrpos.visible then
|
|
continue
|
|
end
|
|
md = mpos:Distance(Vector(scrpos.x, scrpos.y, 0))
|
|
if md < near_cursor_dist then
|
|
alpha = math.Clamp(alpha * (md / near_cursor_dist), 40, 230)
|
|
end
|
|
|
|
role = tgt.role or ROLE_INNOCENT
|
|
if role == ROLE_TRAITOR then
|
|
surface.SetDrawColor(255, 0, 0, alpha)
|
|
surface.SetTextColor(255, 0, 0, alpha)
|
|
|
|
elseif role == ROLE_DETECTIVE then
|
|
surface.SetDrawColor(0, 0, 255, alpha)
|
|
surface.SetTextColor(0, 0, 255, alpha)
|
|
|
|
elseif role == 3 then -- decoys
|
|
surface.SetDrawColor(150, 150, 150, alpha)
|
|
surface.SetTextColor(150, 150, 150, alpha)
|
|
|
|
else
|
|
surface.SetDrawColor(0, 255, 0, alpha)
|
|
surface.SetTextColor(0, 255, 0, alpha)
|
|
end
|
|
|
|
DrawTarget(tgt, 24, 0)
|
|
end
|
|
|
|
-- Time until next scan
|
|
surface.SetFont("TabLarge")
|
|
surface.SetTextColor(255, 0, 0, 230)
|
|
|
|
local text = GetPTranslation("radar_hud", {time = FormatTime(remaining, "%02i:%02i")})
|
|
local w, h = surface.GetTextSize(text)
|
|
|
|
surface.SetTextPos(36, ScrH() - 140 - h)
|
|
surface.DrawText(text)
|
|
end
|
|
|
|
local function ReceiveC4Warn()
|
|
local idx = net.ReadUInt(16)
|
|
local armed = net.ReadBit() == 1
|
|
|
|
if armed then
|
|
local pos = net.ReadVector()
|
|
local etime = net.ReadFloat()
|
|
|
|
RADAR.bombs[idx] = {pos=pos, t=etime}
|
|
else
|
|
RADAR.bombs[idx] = nil
|
|
end
|
|
|
|
RADAR.bombs_count = table.Count(RADAR.bombs)
|
|
end
|
|
net.Receive("TTT_C4Warn", ReceiveC4Warn)
|
|
|
|
local function ReceiveCorpseCall()
|
|
local pos = net.ReadVector()
|
|
table.insert(RADAR.called_corpses, {pos = pos, called = CurTime()})
|
|
end
|
|
net.Receive("TTT_CorpseCall", ReceiveCorpseCall)
|
|
|
|
local function ReceiveRadarScan()
|
|
local num_targets = net.ReadUInt(8)
|
|
|
|
RADAR.targets = {}
|
|
for i=1, num_targets do
|
|
local r = net.ReadUInt(2)
|
|
|
|
local pos = Vector()
|
|
pos.x = net.ReadInt(15)
|
|
pos.y = net.ReadInt(15)
|
|
pos.z = net.ReadInt(15)
|
|
|
|
table.insert(RADAR.targets, {role=r, pos=pos})
|
|
end
|
|
|
|
RADAR.enable = true
|
|
RADAR.endtime = CurTime() + RADAR.duration
|
|
|
|
timer.Create("radartimeout", RADAR.duration + 1, 1,
|
|
function() RADAR:Timeout() end)
|
|
end
|
|
net.Receive("TTT_Radar", ReceiveRadarScan)
|
|
|
|
local GetTranslation = LANG.GetTranslation
|
|
function RADAR.CreateMenu(parent, frame)
|
|
local w, h = parent:GetSize()
|
|
|
|
local dform = vgui.Create("DForm", parent)
|
|
dform:SetName(GetTranslation("radar_menutitle"))
|
|
dform:StretchToParent(0,0,0,0)
|
|
dform:SetAutoSize(false)
|
|
|
|
local owned = LocalPlayer():HasEquipmentItem(EQUIP_RADAR)
|
|
|
|
if not owned then
|
|
dform:Help(GetTranslation("radar_not_owned"))
|
|
return dform
|
|
end
|
|
|
|
local bw, bh = 100, 25
|
|
local dscan = vgui.Create("DButton", dform)
|
|
dscan:SetSize(bw, bh)
|
|
dscan:SetText(GetTranslation("radar_scan"))
|
|
dscan.DoClick = function(s)
|
|
s:SetDisabled(true)
|
|
RunConsoleCommand("ttt_radar_scan")
|
|
frame:Close()
|
|
end
|
|
dform:AddItem(dscan)
|
|
|
|
local dlabel = vgui.Create("DLabel", dform)
|
|
dlabel:SetText(GetPTranslation("radar_help", {num = RADAR.duration}))
|
|
dlabel:SetWrap(true)
|
|
dlabel:SetTall(50)
|
|
dform:AddItem(dlabel)
|
|
|
|
local dcheck = vgui.Create("DCheckBoxLabel", dform)
|
|
dcheck:SetText(GetTranslation("radar_auto"))
|
|
dcheck:SetIndent(5)
|
|
dcheck:SetValue(RADAR.repeating)
|
|
dcheck.OnChange = function(s, val)
|
|
RADAR.repeating = val
|
|
end
|
|
dform:AddItem(dcheck)
|
|
|
|
dform.Think = function(s)
|
|
if RADAR.enable or not owned then
|
|
dscan:SetDisabled(true)
|
|
else
|
|
dscan:SetDisabled(false)
|
|
end
|
|
end
|
|
|
|
dform:SetVisible(true)
|
|
|
|
return dform
|
|
end
|
|
|