mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
350
gamemodes/terrortown/gamemode/cl_wepswitch.lua
Normal file
350
gamemodes/terrortown/gamemode/cl_wepswitch.lua
Normal file
@@ -0,0 +1,350 @@
|
||||
--[[
|
||||
| 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)
|
||||
Reference in New Issue
Block a user