--[[ | 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)