mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
351 lines
8.1 KiB
Lua
351 lines
8.1 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/
|
|
--]]
|
|
|
|
|
|
-- we need our own weapon switcher because the hl2 one skips empty weapons
|
|
|
|
local math = math
|
|
local draw = draw
|
|
local surface = surface
|
|
local table = table
|
|
|
|
WSWITCH = {}
|
|
|
|
WSWITCH.Show = false
|
|
WSWITCH.Selected = -1
|
|
WSWITCH.NextSwitch = -1
|
|
WSWITCH.WeaponCache = {}
|
|
|
|
WSWITCH.cv = {}
|
|
WSWITCH.cv.stay = CreateConVar("ttt_weaponswitcher_stay", "0", FCVAR_ARCHIVE)
|
|
WSWITCH.cv.fast = CreateConVar("ttt_weaponswitcher_fast", "0", FCVAR_ARCHIVE)
|
|
WSWITCH.cv.display = CreateConVar("ttt_weaponswitcher_displayfast", "0", FCVAR_ARCHIVE)
|
|
|
|
local delay = 0.03
|
|
local showtime = 3
|
|
|
|
local margin = 10
|
|
local width = 300
|
|
local height = 20
|
|
|
|
local barcorner = surface.GetTextureID( "gui/corner8" )
|
|
|
|
local col_active = {
|
|
tip = {
|
|
[ROLE_INNOCENT] = Color(55, 170, 50, 255),
|
|
[ROLE_TRAITOR] = Color(180, 50, 40, 255),
|
|
[ROLE_DETECTIVE] = Color(50, 60, 180, 255)
|
|
},
|
|
|
|
bg = Color(20, 20, 20, 250),
|
|
|
|
text_empty = Color(200, 20, 20, 255),
|
|
text = Color(255, 255, 255, 255),
|
|
|
|
shadow = 255
|
|
};
|
|
|
|
local col_dark = {
|
|
tip = {
|
|
[ROLE_INNOCENT] = Color(60, 160, 50, 155),
|
|
[ROLE_TRAITOR] = Color(160, 50, 60, 155),
|
|
[ROLE_DETECTIVE] = Color(50, 60, 160, 155),
|
|
},
|
|
|
|
bg = Color(20, 20, 20, 200),
|
|
|
|
text_empty = Color(200, 20, 20, 100),
|
|
text = Color(255, 255, 255, 100),
|
|
|
|
shadow = 100
|
|
};
|
|
|
|
-- Draw a bar in the style of the the weapon pickup ones
|
|
local round = math.Round
|
|
function WSWITCH:DrawBarBg(x, y, w, h, col)
|
|
local rx = round(x - 4)
|
|
local ry = round(y - (h / 2)-4)
|
|
local rw = round(w + 9)
|
|
local rh = round(h + 8)
|
|
|
|
local b = 8 --bordersize
|
|
local bh = b / 2
|
|
|
|
local role = LocalPlayer():GetRole() or ROLE_INNOCENT
|
|
|
|
local c = col.tip[role]
|
|
|
|
-- Draw the colour tip
|
|
surface.SetTexture(barcorner)
|
|
|
|
surface.SetDrawColor(c.r, c.g, c.b, c.a)
|
|
surface.DrawTexturedRectRotated( rx + bh , ry + bh, b, b, 0 )
|
|
surface.DrawTexturedRectRotated( rx + bh , ry + rh -bh, b, b, 90 )
|
|
surface.DrawRect( rx, ry+b, b, rh-b*2 )
|
|
surface.DrawRect( rx+b, ry, h - 4, rh )
|
|
|
|
-- Draw the remainder
|
|
-- Could just draw a full roundedrect bg and overdraw it with the tip, but
|
|
-- I don't have to do the hard work here anymore anyway
|
|
c = col.bg
|
|
surface.SetDrawColor(c.r, c.g, c.b, c.a)
|
|
|
|
surface.DrawRect( rx+b+h-4, ry, rw - (h - 4) - b*2, rh )
|
|
surface.DrawTexturedRectRotated( rx + rw - bh , ry + rh - bh, b, b, 180 )
|
|
surface.DrawTexturedRectRotated( rx + rw - bh , ry + bh, b, b, 270 )
|
|
surface.DrawRect( rx+rw-b, ry+b, b, rh-b*2 )
|
|
|
|
end
|
|
|
|
local TryTranslation = LANG.TryTranslation
|
|
function WSWITCH:DrawWeapon(x, y, c, wep)
|
|
if not IsValid(wep) then return false end
|
|
|
|
local name = TryTranslation(wep:GetPrintName() or wep.PrintName or "...")
|
|
local cl1, am1 = wep:Clip1(), wep:Ammo1()
|
|
local ammo = false
|
|
|
|
-- Clip1 will be -1 if a melee weapon
|
|
-- Ammo1 will be false if weapon has no owner (was just dropped)
|
|
if cl1 != -1 and am1 != false then
|
|
ammo = Format("%i + %02i", cl1, am1)
|
|
end
|
|
|
|
-- Slot
|
|
local spec = {text=wep.Slot+1, font="Trebuchet22", pos={x+4, y}, yalign=TEXT_ALIGN_CENTER, color=c.text}
|
|
draw.TextShadow(spec, 1, c.shadow)
|
|
|
|
-- Name
|
|
spec.text = name
|
|
spec.font = "TimeLeft"
|
|
spec.pos[1] = x + 10 + height
|
|
draw.Text(spec)
|
|
|
|
if ammo then
|
|
local col = c.text
|
|
|
|
if wep:Clip1() == 0 and wep:Ammo1() == 0 then
|
|
col = c.text_empty
|
|
end
|
|
|
|
-- Ammo
|
|
spec.text = ammo
|
|
spec.pos[1] = ScrW() - margin*3
|
|
spec.xalign = TEXT_ALIGN_RIGHT
|
|
spec.color = col
|
|
draw.Text(spec)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function WSWITCH:Draw(client)
|
|
if not self.Show then return end
|
|
|
|
local weps = self.WeaponCache
|
|
|
|
local x = ScrW() - width - margin*2
|
|
local y = ScrH() - (#weps * (height + margin))
|
|
|
|
local col = col_dark
|
|
for k, wep in pairs(weps) do
|
|
if self.Selected == k then
|
|
col = col_active
|
|
else
|
|
col = col_dark
|
|
end
|
|
|
|
self:DrawBarBg(x, y, width, height, col)
|
|
if not self:DrawWeapon(x, y, col, wep) then
|
|
|
|
self:UpdateWeaponCache()
|
|
return
|
|
end
|
|
|
|
y = y + height + margin
|
|
end
|
|
end
|
|
|
|
local function SlotSort(a, b)
|
|
return a and b and a.Slot and b.Slot and a.Slot < b.Slot
|
|
end
|
|
|
|
local function CopyVals(src, dest)
|
|
table.Empty(dest)
|
|
for k, v in pairs(src) do
|
|
if IsValid(v) then
|
|
table.insert(dest, v)
|
|
end
|
|
end
|
|
end
|
|
|
|
function WSWITCH:UpdateWeaponCache()
|
|
-- GetWeapons does not always return a proper numeric table it seems
|
|
-- self.WeaponCache = LocalPlayer():GetWeapons()
|
|
-- So copy over the weapon refs
|
|
self.WeaponCache = {}
|
|
CopyVals(LocalPlayer():GetWeapons(), self.WeaponCache)
|
|
|
|
table.sort(self.WeaponCache, SlotSort)
|
|
end
|
|
|
|
function WSWITCH:SetSelected(idx)
|
|
self.Selected = idx
|
|
|
|
self:UpdateWeaponCache()
|
|
end
|
|
|
|
function WSWITCH:SelectNext()
|
|
if self.NextSwitch > CurTime() then return end
|
|
self:Enable()
|
|
|
|
local s = self.Selected + 1
|
|
if s > #self.WeaponCache then
|
|
s = 1
|
|
end
|
|
|
|
self:DoSelect(s)
|
|
|
|
self.NextSwitch = CurTime() + delay
|
|
end
|
|
|
|
function WSWITCH:SelectPrev()
|
|
if self.NextSwitch > CurTime() then return end
|
|
self:Enable()
|
|
|
|
local s = self.Selected - 1
|
|
if s < 1 then
|
|
s = #self.WeaponCache
|
|
end
|
|
|
|
self:DoSelect(s)
|
|
|
|
self.NextSwitch = CurTime() + delay
|
|
end
|
|
|
|
-- Select by index
|
|
function WSWITCH:DoSelect(idx)
|
|
self:SetSelected(idx)
|
|
|
|
if self.cv.fast:GetBool() then
|
|
-- immediately confirm if fastswitch is on
|
|
self:ConfirmSelection(self.cv.display:GetBool())
|
|
end
|
|
end
|
|
|
|
-- Numeric key access to direct slots
|
|
function WSWITCH:SelectSlot(slot)
|
|
if not slot then return end
|
|
|
|
self:Enable()
|
|
|
|
self:UpdateWeaponCache()
|
|
|
|
slot = slot - 1
|
|
|
|
-- find which idx in the weapon table has the slot we want
|
|
local toselect = self.Selected
|
|
for k, w in pairs(self.WeaponCache) do
|
|
if w.Slot == slot then
|
|
toselect = k
|
|
break
|
|
end
|
|
end
|
|
|
|
self:DoSelect(toselect)
|
|
|
|
self.NextSwitch = CurTime() + delay
|
|
end
|
|
|
|
-- Show the weapon switcher
|
|
function WSWITCH:Enable()
|
|
if self.Show == false then
|
|
self.Show = true
|
|
|
|
local wep_active = LocalPlayer():GetActiveWeapon()
|
|
|
|
self:UpdateWeaponCache()
|
|
|
|
-- make our active weapon the initial selection
|
|
local toselect = 1
|
|
for k, w in pairs(self.WeaponCache) do
|
|
if w == wep_active then
|
|
toselect = k
|
|
break
|
|
end
|
|
end
|
|
self:SetSelected(toselect)
|
|
end
|
|
|
|
-- cache for speed, checked every Think
|
|
self.Stay = self.cv.stay:GetBool()
|
|
end
|
|
|
|
-- Hide switcher
|
|
function WSWITCH:Disable()
|
|
self.Show = false
|
|
end
|
|
|
|
-- Switch to the currently selected weapon
|
|
function WSWITCH:ConfirmSelection(noHide)
|
|
if not noHide then self:Disable() end
|
|
|
|
for k, w in pairs(self.WeaponCache) do
|
|
if k == self.Selected and IsValid(w) then
|
|
input.SelectWeapon(w)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Allow for suppression of the attack command
|
|
function WSWITCH:PreventAttack()
|
|
return self.Show and !self.cv.fast:GetBool()
|
|
end
|
|
|
|
function WSWITCH:Think()
|
|
if (not self.Show) or self.Stay then return end
|
|
|
|
-- hide after period of inaction
|
|
if self.NextSwitch < (CurTime() - showtime) then
|
|
self:Disable()
|
|
end
|
|
end
|
|
|
|
-- Instantly select a slot and switch to it, without spending time in menu
|
|
function WSWITCH:SelectAndConfirm(slot)
|
|
if not slot then return end
|
|
WSWITCH:SelectSlot(slot)
|
|
WSWITCH:ConfirmSelection()
|
|
end
|
|
|
|
local function QuickSlot(ply, cmd, args)
|
|
if (not IsValid(ply)) or (not args) or #args != 1 then return end
|
|
|
|
local slot = tonumber(args[1])
|
|
if not slot then return end
|
|
|
|
local wep = ply:GetActiveWeapon()
|
|
if IsValid(wep) then
|
|
if wep.Slot == (slot - 1) then
|
|
RunConsoleCommand("lastinv")
|
|
else
|
|
WSWITCH:SelectAndConfirm(slot)
|
|
end
|
|
end
|
|
end
|
|
concommand.Add("ttt_quickslot", QuickSlot)
|
|
|
|
|
|
local function SwitchToEquipment(ply, cmd, args)
|
|
RunConsoleCommand("ttt_quickslot", tostring(7))
|
|
end
|
|
concommand.Add("ttt_equipswitch", SwitchToEquipment)
|