This commit is contained in:
Jonny_Bro (Nikita) 2023-05-28 16:19:59 +05:00
parent d80ccc84ec
commit c1568781ec
15 changed files with 699 additions and 77 deletions

View file

@ -4,7 +4,7 @@ There are lua modules ([source](https://github.com/fluffy-servers/gmod-discord-r
This version of the beatrun works on any version of the game (Chromium or not). This version of the beatrun works on any version of the game (Chromium or not).
## Changes added by me ## Changes added by me
* [Custom online courses service](https://courses.beatrun.ru)! It's free 🤯! DM @Jonny_Bro#4226 for an API key. * [Custom online courses database](https://courses.beatrun.ru)! It's free 🤯!
* Allow Overdrive usage on the server - `Beatrun_AllowOvedriveInMultiplayer`. * Allow Overdrive usage on the server - `Beatrun_AllowOvedriveInMultiplayer`.
* Change HUD's colors - `Beatrun_HUDTextColor`, `Beatrun_HUDCornerColor`, `Beatrun_HUDFloatingXPColor`. * Change HUD's colors - `Beatrun_HUDTextColor`, `Beatrun_HUDCornerColor`, `Beatrun_HUDFloatingXPColor`.
* Discord Rich Presence (extract `lua` folder to `garrysmod`, along side with `addons` folder). * Discord Rich Presence (extract `lua` folder to `garrysmod`, along side with `addons` folder).
@ -12,8 +12,10 @@ This version of the beatrun works on any version of the game (Chromium or not).
* Change max moving speed - `Beatrun_MaxSpeed`. * Change max moving speed - `Beatrun_MaxSpeed`.
* Ability to remove ziplines that created with *Zipline Gun* - RMB. * Ability to remove ziplines that created with *Zipline Gun* - RMB.
* Removed your SteamID from right corner, because I can. * Removed your SteamID from right corner, because I can.
* Allow players to spawn props without admin rights - `Beatrun_AllowPropSpawn`.
## Fixes from previous version ## Fixes from previous version
* Database update because Cloudflare 🤡. * Fixed player collision.
* Working on a new Gamemodes menu... (currently doesn't work at all).
### [All changes](https://github.com/JonnyBro/beatrun/blob/master/CHANGES.md) ### [All changes](https://github.com/JonnyBro/beatrun/blob/master/CHANGES.md)

View file

@ -36,7 +36,6 @@ function ENT:Initialize()
end end
hook.Add("ShouldCollide", "DataCubeCollisions", function(ent1, ent2) hook.Add("ShouldCollide", "DataCubeCollisions", function(ent1, ent2)
-- If players are about to collide with each other, then they won't collide.
if ent1.DataCube and ent2.DataCube then return false end if ent1.DataCube and ent2.DataCube then return false end
end) end)

View file

@ -26,8 +26,8 @@ SWEP.DrawWeaponInfoBox = false
SWEP.HoldType = "fist" SWEP.HoldType = "fist"
SWEP.Spawnable = false SWEP.Spawnable = true
SWEP.AdminSpawnable = false SWEP.AdminSpawnable = true
--[[Just don't draw the hands, we don't need 'em]] --[[Just don't draw the hands, we don't need 'em]]

View file

@ -9,51 +9,29 @@ local gamemodePanel = {
gamemodePanel.x = 960 - gamemodePanel.w * 0.5 gamemodePanel.x = 960 - gamemodePanel.w * 0.5
gamemodePanel.y = 540 - gamemodePanel.h * 0.5 gamemodePanel.y = 540 - gamemodePanel.h * 0.5
local function closeButton() local function closeButton()
AEUI:Clear() AEUI:Clear()
end end
local function infectionButton() local function infectionButton()
net.Start("Beatrun_ToggleInfection") net.Start("Beatrun_ToggleGamemode")
net.WriteString("infection")
net.SendToServer() net.SendToServer()
end end
local function datatheftButton() local function datatheftButton()
net.Start("Beatrun_ToggleDataTheft") net.Start("Beatrun_ToggleGamemode")
net.WriteString("datatheft")
net.SendToServer() net.SendToServer()
end end
local loadoutnum = 1 -- local function createButton()
local maxloadoutnum = 1 -- net.Start("Beatrun_CreateLoadout")
-- net.SendToServer()
local function createButton() -- maxloadoutnum = maxloadoutnum + 1
net.Start("Beatrun_CreateLoadout") -- LocalPlayer():EmitSound("buttonclick.wav")
net.SendToServer() -- end
maxloadoutnum = maxloadoutnum + 1
LocalPlayer():EmitSound("buttonclick.wav")
end
local function resetloadoutButton()
net.Start("Beatrun_ResetLoadouts")
net.SendToServer()
loadoutnum = 1
maxloadoutnum = 1
LocalPlayer():EmitSound("buttonclick.wav")
end
local function leftButton()
if loadoutnum ~= 1 then
loadoutnum = loadoutnum - 1
LocalPlayer():EmitSound("buttonclick.wav")
end
end
local function rightButton()
if loadoutnum ~= maxloadoutnum then
loadoutnum = loadoutnum + 1
LocalPlayer():EmitSound("buttonclick.wav")
end
end
local function isSA() local function isSA()
return not LocalPlayer():IsSuperAdmin() return not LocalPlayer():IsSuperAdmin()
@ -63,17 +41,17 @@ AEUI:AddText(gamemodePanel, "Gamemodes Select", "AEUIVeryLarge", 20, 30)
AEUI:AddButton(gamemodePanel, " X ", closeButton, "AEUILarge", gamemodePanel.w - 47, 0) AEUI:AddButton(gamemodePanel, " X ", closeButton, "AEUILarge", gamemodePanel.w - 47, 0)
local infectionbutton = AEUI:AddButton(gamemodePanel, "Toggle Infection", infectionButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 550) local infectionbutton = AEUI:AddButton(gamemodePanel, "Toggle Infection", infectionButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 550)
infectionbutton.greyed = isSA() infectionbutton.greyed = isSA
local datatheftbutton = AEUI:AddButton(gamemodePanel, "Toggle Data Theft", datatheftButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 450) local datatheftbutton = AEUI:AddButton(gamemodePanel, "Toggle Data Theft", datatheftButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 450)
datatheftbutton.greyed = isSA() datatheftbutton.greyed = isSA
-- local loadoutbutton = AEUI:AddButton(gamemodePanel, "Create a new loadout", createButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 450) -- local loadoutbutton = AEUI:AddButton(gamemodePanel, "Create a new loadout", createButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 450)
-- loadoutbutton.greyed = isSA() -- loadoutbutton.greyed = isSA
-- local resetbutton = AEUI:AddButton(gamemodePanel, "Resets all loadouts", resetloadoutButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 550) -- local resetbutton = AEUI:AddButton(gamemodePanel, "Resets all loadouts", resetloadoutButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 550)
-- resetbutton.greyed = isSA() -- resetbutton.greyed = isSA
-- local leftloadout = AEUI:AddButton(gamemodePanel, " < ", leftButton, "AEUILarge", gamemodePanel.w - 225, gamemodePanel.h - 175) -- local leftloadout = AEUI:AddButton(gamemodePanel, " < ", leftButton, "AEUILarge", gamemodePanel.w - 225, gamemodePanel.h - 175)
-- leftloadout.greyed = isSA() -- leftloadout.greyed = isSA
-- local rightloadout = AEUI:AddButton(gamemodePanel, " > ", rightButton, "AEUILarge", gamemodePanel.w - 150, gamemodePanel.h - 175) -- local rightloadout = AEUI:AddButton(gamemodePanel, " > ", rightButton, "AEUILarge", gamemodePanel.w - 150, gamemodePanel.h - 175)
-- rightloadout.greyed = isSA() -- rightloadout.greyed = isSA
-- AEUI:AddText(gamemodePanel, "Change through loadouts", "AEUILarge", gamemodePanel.w - 360, gamemodePanel.h - 125) -- AEUI:AddText(gamemodePanel, "Change through loadouts", "AEUILarge", gamemodePanel.w - 360, gamemodePanel.h - 125)
local weaponsList = { local weaponsList = {
@ -90,19 +68,22 @@ local weaponsList = {
function OpenGMMenu(ply) function OpenGMMenu(ply)
AEUI:AddPanel(gamemodePanel) AEUI:AddPanel(gamemodePanel)
AEUI:AddPanel(weaponsList) AEUI:AddPanel(weaponsList)
local loaded_weapons = {} local loaded_weapons = {}
for i, _ in pairs(DATATHEFT_LOADOUTS) do for i, _ in pairs(DATATHEFT_LOADOUTS) do
for _, v in pairs(DATATHEFT_LOADOUTS[i]) do for _, v in pairs(DATATHEFT_LOADOUTS[i]) do
table.insert(loaded_weapons, v) table.insert(loaded_weapons, v)
end end
end end
for _, v in pairs(weapons.GetList()) do for _, v in pairs(weapons.GetList()) do
if not string.find(v.ClassName:lower(), "base") then if not string.find(v.ClassName:lower(), "base") then
local weaponentry = AEUI:AddText(weaponsList, v.ClassName, "AEUILarge", 10, 40 * #weaponsList.elements) local weaponentry = AEUI:AddText(weaponsList, v.ClassName, "AEUILarge", 10, 40 * #weaponsList.elements)
function weaponentry:onclick() function weaponentry:onclick()
LocalPlayer():EmitSound("buttonclick.wav") LocalPlayer():EmitSound("buttonclick.wav")
end end
weaponentry.greyed = isSA() weaponentry.greyed = isSA
end end
end end
end end

View file

@ -0,0 +1,490 @@
function CLoadout:GetWeaponIcon(class)
if file.Exists("materials/entities/" .. class .. ".png", "GAME") then return "entities/" .. class .. ".png" end
if file.Exists("materials/vgui/entities/" .. class .. ".vtf", "GAME") then return "vgui/entities/" .. class end
end
function CLoadout:UpdateLists()
if IsValid(self.listAvailable) then
self:UpdateAvailableList()
end
if IsValid(self.listLoadoutItems) then
self:UpdateLoadoutList()
end
end
function CLoadout:CreateAvailableWeaponIcon(class)
local weapon = self.weaponRegistry[class]
if not weapon then return end
if self.categoryFilter and weapon.category ~= self.categoryFilter then return end
if self.filter ~= "" then
local foundClass = string.find(class, self.filter, 1, true)
local foundName = string.find(string.lower(weapon.name), self.filter, 1, true)
if not foundClass and not foundName then return end
end
local localPly = LocalPlayer()
local icon = self.listAvailable:Add("CLoadoutWeaponIcon")
icon:SetWeaponName(weapon.name)
icon:SetWeaponClass(class)
icon.DoClick = function()
if not localPly:IsAdmin() then
Derma_Message("You can't edit loadouts.", "Loadout editor", "OK")
else
self:AddWeapon(class)
self:UpdateLoadoutList()
icon:Remove()
end
end
icon.OpenMenu = function()
local menu = DermaMenu()
menu:AddOption("Copy to clipboard", function()
SetClipboardText(class)
end)
menu:Open()
end
end
function CLoadout:UpdateAvailableList()
self.listAvailable:Clear()
local inLoadout = {}
for _, item in ipairs(DATATHEFT_LOADOUTS[self.loadoutIndex]) do
inLoadout[item[1]] = true
end
for class, _ in SortedPairsByMemberValue(self.weaponRegistry, "name") do
if not inLoadout[class] then
self:CreateAvailableWeaponIcon(class)
end
end
self.listAvailable:InvalidateLayout(true)
self.scrollAvailable:InvalidateLayout()
end
function CLoadout:UpdateLoadoutList()
self.comboLoadouts._blockCallback = true
self.comboLoadouts:Clear()
for index, loadout in ipairs(DATATHEFT_LOADOUTS) do
self.comboLoadouts:AddChoice(tostring(index), nil, index == self.loadoutIndex)
end
self.comboLoadouts._blockCallback = nil
self.listLoadoutItems:Clear()
local items = DATATHEFT_LOADOUTS[self.loadoutIndex]
for index, item in ipairs(items) do
local class = item[1]
local icon = self.listLoadoutItems:Add("CLoadoutWeaponIcon")
icon:SetWeaponClass(class)
icon._itemIndex = index
icon.DoClick = function()
self:RemoveWeapon(index)
self:CreateAvailableWeaponIcon(class)
icon:Remove()
end
local regWeapon = self.weaponRegistry[class]
if not regWeapon then
if not self.hintedMissingWeapons then
self.hintedMissingWeapons = true
Derma_Message("This loadout has weapons that are currently unavailable.\nMake sure they are installed to use them.", "Missing weapons", "OK")
end
icon:SetWeaponName(class)
icon:SetMaterial("icon16/cancel.png")
continue
end
icon:SetWeaponName(regWeapon.name)
if regWeapon.adminOnly then
icon:SetAdminOnly(true)
end
if not regWeapon.noPrimary then
icon.Primary = item[2]
end
if not regWeapon.noSecondary then
icon.Secondary = item[3]
end
end
self.labelCount:SetTextColor(#items > self:GetWeaponLimit() and Color(255, 50, 50) or color_white)
self.labelCount:SetText(string.format("%d/%d", #items, self:GetWeaponLimit()))
self.labelCount:SizeToContents()
self.listLoadoutItems:InvalidateLayout(true)
self.scrollLoadoutItems:InvalidateLayout()
end
function CLoadout:ShowPanel()
if IsValid(self.frame) then
self.frame:Close()
self.frame = nil
return
end
local frameW = math.max(ScrW() * 0.6, 820)
local frameH = math.max(ScrH() * 0.6, 500)
frameW = math.Clamp(frameW, 600, ScrW())
frameH = math.Clamp(frameH, 400, ScrH())
local frame = vgui.Create("DFrame")
frame:SetTitle("Click on any weapon to add/remove it from your loadout.")
frame:SetPos(0, 0)
frame:SetSize(frameW, frameH)
frame:SetSizable(true)
frame:SetDraggable(true)
frame:SetDeleteOnClose(true)
frame:SetScreenLock(true)
frame:SetMinWidth(600)
frame:SetMinHeight(400)
frame:Center()
frame:MakePopup()
self.frame = frame
frame._maximized = false
frame.btnMaxim:SetDisabled(false)
frame.btnClose.DoClick = function()
frame:Close()
end
frame.OnClose = function()
self:Apply()
end
local leftPanel = vgui.Create("DPanel", frame)
local rightPanel = vgui.Create("DPanel", frame)
local function PaintBackground(_, sw, sh)
surface.SetDrawColor(32, 32, 32, 255)
surface.DrawRect(0, 0, sw, sh)
end
leftPanel.Paint = PaintBackground
rightPanel.Paint = PaintBackground
local div = vgui.Create("DHorizontalDivider", frame)
div:Dock(FILL)
div:SetLeft(leftPanel)
div:SetRight(rightPanel)
div:SetDividerWidth(4)
div:SetLeftMin(200)
div:SetRightMin(200)
div:SetLeftWidth(frameW * 0.56)
frame.btnMaxim.DoClick = function()
if frame._maximized then
frame:SetSize(frame._oldDimensions[1], frame._oldDimensions[2])
frame:Center()
frame._maximized = false
frame._oldDimensions = nil
else
frame._maximized = true
frame._oldDimensions = {frame:GetWide(), frame:GetTall()}
frame:SetPos(0, 0)
frame:SetSize(ScrW(), ScrH())
end
frame:SetDraggable(not frame._maximized)
frame:SetSizable(not frame._maximized)
div:SetLeftWidth(frame:GetWide() * 0.56)
end
----- LEFT PANEL STUFF
self.comboCategory = vgui.Create("DComboBox", leftPanel)
self.comboCategory:SetFont("Trebuchet24")
self.comboCategory:SetSortItems(false)
self.comboCategory:SetTextColor(Color(150, 255, 150))
self.comboCategory:SetTall(30)
self.comboCategory:Dock(TOP)
self.comboCategory:DockMargin(2, 2, 2, 2)
self.comboCategory:AddChoice("Available weapons", nil, true)
for _, name in ipairs(self.categories) do
self.comboCategory:AddChoice(name)
end
self.comboCategory.Paint = function(_, sw, sh)
surface.SetDrawColor(0, 0, 0, 240)
surface.DrawRect(0, 0, sw, sh)
end
self.comboCategory.OnSelect = function(_, index)
index = tonumber(index) - 1
if index == 0 then
self.categoryFilter = nil
else
self.categoryFilter = self.categories[index]
end
self:UpdateLists()
end
local entrySearch = vgui.Create("DTextEntry", leftPanel)
entrySearch:SetFont("ChatFont")
entrySearch:SetMaximumCharCount(64)
entrySearch:SetTabbingDisabled(true)
entrySearch:SetPlaceholderText("Search...")
entrySearch:SetTall(38)
entrySearch:Dock(BOTTOM)
entrySearch.OnChange = function(s)
self.filter = string.lower(string.Trim(s:GetText()))
self:UpdateAvailableList()
end
-- available weapons list
self.scrollAvailable = vgui.Create("DScrollPanel", leftPanel)
self.scrollAvailable:Dock(FILL)
self.listAvailable = vgui.Create("DIconLayout", self.scrollAvailable)
self.listAvailable:Dock(FILL)
self.listAvailable:DockMargin(0, 0, 0, 0)
self.listAvailable:SetSpaceX(4)
self.listAvailable:SetSpaceY(4)
----- RIGHT PANEL STUFF
local panelOptions = vgui.Create("DPanel", rightPanel)
panelOptions:SetTall(32)
panelOptions:Dock(TOP)
panelOptions:DockPadding(2, 2, 2, 2)
panelOptions:SetPaintBackground(false)
local buttonCopy = vgui.Create("DButton", panelOptions)
buttonCopy:SetText("")
buttonCopy:SetImage("icon16/brick_go.png")
buttonCopy:SetTooltip("Add weapons from your inventory")
buttonCopy:SetWide(24)
buttonCopy:Dock(RIGHT)
buttonCopy.DoClick = function()
Derma_Query("This will add all weapons that you're currently holding to this loadout. Continue?", "Add weapons from your inventory", "Yes", function()
self:AddInventoryWeapons()
end, "No")
end
local buttonRemove = vgui.Create("DButton", panelOptions)
buttonRemove:SetText("")
buttonRemove:SetImage("icon16/delete.png")
buttonRemove:SetTooltip("Delete loadout")
buttonRemove:SetWide(24)
buttonRemove:Dock(RIGHT)
buttonRemove.DoClick = function()
local loadoutName = DATATHEFT_LOADOUTS[self.loadoutIndex].name
local helpText = string.format("Are you sure you want to delete \"%s\"?", loadoutName)
Derma_Query(helpText, "Delete loadout", "Yes", function()
self:DeleteLoadout(self.loadoutIndex)
self:Save()
end, "No")
end
local buttonNew = vgui.Create("DButton", panelOptions)
buttonNew:SetText("")
buttonNew:SetImage("icon16/add.png")
buttonNew:SetTooltip("Create loadout")
buttonNew:SetWide(24)
buttonNew:Dock(RIGHT)
buttonNew.DoClick = function()
self.loadoutIndex = self:CreateLoadout(self.loadoutIndex + 1)
self:Save()
self:UpdateLists()
end
self.comboLoadouts = vgui.Create("DComboBox", panelOptions)
self.comboLoadouts:SetFont("Trebuchet24")
self.comboLoadouts:SetSortItems(false)
self.comboLoadouts:Dock(FILL)
self.comboLoadouts:SetTextColor(Color(193, 202, 255))
self.comboLoadouts.Paint = function(_, sw, sh)
surface.SetDrawColor(0, 0, 0, 240)
surface.DrawRect(0, 0, sw, sh)
end
self.comboLoadouts.OnSelect = function(s, index)
if s._blockCallback then return end
self.loadoutIndex = tonumber(index)
self.hintedMissingWeapons = nil
self:UpdateLists()
end
local panelToggle = vgui.Create("DPanel", rightPanel)
panelToggle:SetTall(52)
panelToggle:Dock(BOTTOM)
panelToggle:DockPadding(8, 8, 8, 8)
panelToggle._animState = self.enabled and 1 or 0
panelToggle.Paint = function(s, sw, sh)
s._animState = Lerp(FrameTime() * 10, s._animState, self.enabled and 1 or 0)
surface.SetDrawColor(50 + 50 * (1 - s._animState), 50 + 50 * s._animState, 50)
surface.DrawRect(0, 0, sw, sh)
end
self.labelCount = vgui.Create("DLabel", panelToggle)
self.labelCount:SetText("0/0")
self.labelCount:Dock(RIGHT)
self.scrollLoadoutItems = vgui.Create("DScrollPanel", rightPanel)
self.scrollLoadoutItems:Dock(FILL)
self.listLoadoutItems = vgui.Create("DIconLayout", self.scrollLoadoutItems)
self.listLoadoutItems:Dock(FILL)
self.listLoadoutItems:DockMargin(0, 0, 0, 0)
self.listLoadoutItems:SetSpaceX(4)
self.listLoadoutItems:SetSpaceY(4)
self:UpdateLists()
end
if engine.ActiveGamemode() == "beatrun" then
list.Set("DesktopWindows", "CLoadoutDesktopIcon", {
title = "DataTheft loadouts editor",
icon = "entities/weapon_smg1.png",
init = function()
CLoadout:ShowPanel()
end
})
end
do
local WeaponIcon = {}
local iconMaterials = {
ammo = Material("icon16/bullet_yellow.png")
}
AccessorFunc(WeaponIcon, "m_bAdminOnly", "AdminOnly")
AccessorFunc(WeaponIcon, "m_bFavorite", "Favorite")
function WeaponIcon:Init()
self:SetPaintBackground(false)
self:SetSize(140, 128)
self:SetText("")
self:SetDoubleClickingEnabled(false)
self.Image = self:Add("DImage")
self.Image:SetPos(0, 0)
self.Image:SetSize(128, 128)
self.Image:SetVisible(false)
self.Image:SetKeepAspect(false)
self.WeaponName = ""
self.WeaponClass = ""
self.Border = 0
self.TextColor = Color(255, 255, 255, 255)
self.TextOutlineColor = Color(0, 0, 0, 255)
end
function WeaponIcon:SetWeaponName(name)
self.WeaponName = name
end
function WeaponIcon:SetWeaponClass(class)
self.WeaponClass = class
local icon_path = CLoadout:GetWeaponIcon(class)
if icon_path then
self:SetMaterial(icon_path)
end
end
function WeaponIcon:SetMaterial(name)
self.m_MaterialName = name
local mat = Material(name)
if not mat or mat:IsError() then
name = name:Replace("entities/", "VGUI/entities/")
name = name:Replace(".png", "")
mat = Material(name)
end
if not mat or mat:IsError() then return end
self.Image:SetMaterial(mat)
end
function WeaponIcon:DoClick()
end
function WeaponIcon:OpenMenu()
end
function WeaponIcon:PaintOver()
end
function WeaponIcon:Paint(w, h)
self.Border = self.Depressed and 8 or 0
render.PushFilterMag(TEXFILTER.ANISOTROPIC)
render.PushFilterMin(TEXFILTER.ANISOTROPIC)
self.Image:PaintAt(self.Border, self.Border, w - self.Border * 2, h - self.Border * 2)
render.PopFilterMin()
render.PopFilterMag()
if self:IsHovered() or self.Depressed or self:IsChildHovered() then
surface.SetDrawColor(255, 255, 255, 255)
else
surface.SetDrawColor(0, 0, 0, 255)
end
surface.DrawOutlinedRect(0, 0, w, h, 4)
local infoH = 20
local infoY = h - infoH - 4
surface.SetDrawColor(30, 30, 30, 240)
surface.DrawRect(4, infoY, w - 8, infoH)
draw.SimpleTextOutlined(self.WeaponName, "Default", 8, infoY + infoH * 0.5, self.TextColor, 0, 1, 1, self.TextOutlineColor)
surface.SetDrawColor(255, 255, 255, 255)
local str
if self.Primary then
if self.Secondary then
str = self.Primary .. "/" .. self.Secondary
else
str = self.Primary
end
elseif self.Secondary then
str = self.Secondary
end
if str then
surface.SetMaterial(iconMaterials.ammo)
surface.DrawTexturedRect(w - 18, infoY + 3, 16, 16)
draw.SimpleTextOutlined(str, "Default", w - 18, infoY + infoH * 0.5, self.TextColor, 2, 1, 1, self.TextOutlineColor)
end
end
vgui.Register("CLoadoutWeaponIcon", WeaponIcon, "DButton")
end

View file

@ -0,0 +1,122 @@
function CLoadout:InitRegistry()
local registry = {}
for _, v in pairs(list.Get("Weapon")) do
if not v.ClassName or not v.Spawnable then continue end
registry[v.ClassName] = {
name = (v.PrintName and v.PrintName ~= "") and v.PrintName or v.ClassName,
}
end
self.weaponRegistry = registry
table.sort(self.categories)
end
function CLoadout:CreateLoadout(items)
local loadout = {}
if istable(items) and table.IsSequential(items) then
for _, item in ipairs(items) do
loadout[#loadout + 1] = { item[1] }
end
end
return table.insert(DATATHEFT_LOADOUTS, loadout)
end
function CLoadout:DeleteLoadout(index)
table.remove(DATATHEFT_LOADOUTS, index)
if #DATATHEFT_LOADOUTS == 0 then
self:CreateLoadout()
end
self.loadoutIndex = #DATATHEFT_LOADOUTS
self:UpdateLists()
end
function CLoadout:Apply()
local loadout = DATATHEFT_LOADOUTS[self.loadoutIndex]
loadout = util.Compress(util.TableToJSON(loadout))
if not loadut then
LocalPlayer():ChatPrint("Failed to compress the loadut!")
return
end
net.Start("Beatrun_UpdateLoadouts", false)
net.WriteData(loadout, #loadout)
net.SendToServer()
end
function CLoadout:AddWeapon(class)
local items = DATATHEFT_LOADOUTS[self.loadoutIndex]
if #items < self:GetWeaponLimit() then
table.insert(items, { class })
else
Derma_Message("Your loadout is full!", "Loadout", "OK")
end
end
function CLoadout:AddInventoryWeapons()
local items = DATATHEFT_LOADOUTS[self.loadoutIndex]
local alreadyInLoadout = {}
for _, v in ipairs(items) do
alreadyInLoadout[v[1]] = true
end
local weaponsList = LocalPlayer():GetWeapons()
for _, v in ipairs(weaponsList) do
local class = (v.GetClass and v:GetClass()) or v.ClassName
if not alreadyInLoadout[class] then
table.insert(DATATHEFT_LOADOUTS[self.loadoutIndex], { class })
end
end
self:UpdateLists()
end
function CLoadout:RemoveWeapon(index)
table.remove(DATATHEFT_LOADOUTS[self.loadoutIndex], index)
end
function CLoadout:Init()
self.filter = ""
self.loadoutIndex = 1
DATATHEFT_LOADOUTS = {}
if IsValid(self.frame) then
self.frame:Close()
self.frame = nil
end
self:InitRegistry()
if #DATATHEFT_LOADOUTS == 0 then
self:CreateLoadout()
end
self:Apply()
end
hook.Add("InitPostEntity", "CLoadout_Initialize", function()
hook.Remove("InitPostEntity", "CLoadout_Initialize")
timer.Simple(1, function()
CLoadout:Init()
end)
end)
concommand.Add("Beatrun_GamemodesMenu", function()
CLoadout:ShowPanel()
end, nil, "Opens the loadout customization window.")

View file

@ -301,7 +301,7 @@ hook.Add("SetupMove", "SpawnFreeze", function(ply, mv, cmd)
end) end)
hook.Add("ShouldCollide", "NoPlayerCollisions", function(ent1, ent2) hook.Add("ShouldCollide", "NoPlayerCollisions", function(ent1, ent2)
if ent1:IsPlayer() and ent2.NoPlayerCollisions then if ent1:IsPlayer() and (ent2:IsPlayer() or ent2.NoPlayerCollisions) then
if ent2.BRCollisionFunc then return ent2:BRCollisionFunc(ent1) if ent2.BRCollisionFunc then return ent2:BRCollisionFunc(ent1)
else return false end else return false end
end end

View file

@ -2,4 +2,8 @@ hook.Add("PlayerButtonDown", "CourseMenuBind", function(ply, button)
if (game.SinglePlayer() or CLIENT and IsFirstTimePredicted()) and button == KEY_F4 then if (game.SinglePlayer() or CLIENT and IsFirstTimePredicted()) and button == KEY_F4 then
ply:ConCommand("Beatrun_CourseMenu") ply:ConCommand("Beatrun_CourseMenu")
end end
if (game.SinglePlayer() or CLIENT and IsFirstTimePredicted()) and button == KEY_F3 then
ply:ConCommand("Beatrun_GamemodesMenu")
end
end) end)

View file

@ -1,5 +0,0 @@
hook.Add("PlayerButtonDown", "GMMenuBind", function(ply, button)
if (game.SinglePlayer() or CLIENT and IsFirstTimePredicted()) and button == KEY_F3 then
ply:ConCommand("Beatrun_GamemodesMenu")
end
end)

View file

@ -1,12 +1,13 @@
if SERVER then if SERVER then
local meta = FindMetaTable("Player") local meta = FindMetaTable("Player")
local allowPropSpawn = CreateConVar("Beatrun_AllowPropSpawn", "0", {FCVAR_ARCHIVE}, "Allow players to spawn props and entities")
util.AddNetworkString("SPParkourEvent") util.AddNetworkString("SPParkourEvent")
local spawn = {"PlayerGiveSWEP", "PlayerSpawnEffect", "PlayerSpawnNPC", "PlayerSpawnObject", "PlayerSpawnProp", "PlayerSpawnRagdoll", "PlayerSpawnSENT", "PlayerSpawnSWEP", "PlayerSpawnVehicle"} local spawn = {"PlayerGiveSWEP", "PlayerSpawnEffect", "PlayerSpawnNPC", "PlayerSpawnObject", "PlayerSpawnProp", "PlayerSpawnRagdoll", "PlayerSpawnSENT", "PlayerSpawnSWEP", "PlayerSpawnVehicle"}
local function BlockSpawn(ply) local function BlockSpawn(ply)
if not ply:IsSuperAdmin() then return false end if not ply:IsAdmin() and not allowPropSpawn:GetBool() then return false end
end end
for k, v in ipairs(spawn) do for k, v in ipairs(spawn) do
@ -16,7 +17,7 @@ if SERVER then
hook.Add("IsSpawnpointSuitable", "NoSpawnFrag", function(ply) return true end) hook.Add("IsSpawnpointSuitable", "NoSpawnFrag", function(ply) return true end)
hook.Add("AllowPlayerPickup", "AllowAdminsPickUp", function(ply, ent) hook.Add("AllowPlayerPickup", "AllowAdminsPickUp", function(ply, ent)
if not ply:IsSuperAdmin() then return false end if not ply:IsAdmin() and not allowPropSpawn:GetBool() then return false end
end) end)
function meta:GTAB(minutes) function meta:GTAB(minutes)

View file

@ -1,6 +1,8 @@
local vmatrixmeta = FindMetaTable("VMatrix") local vmatrixmeta = FindMetaTable("VMatrix")
local playermeta = FindMetaTable("Player") local playermeta = FindMetaTable("Player")
CLoadout = {}
function CLIENT_IFTP() function CLIENT_IFTP()
return CLIENT and IsFirstTimePredicted() return CLIENT and IsFirstTimePredicted()
end end

View file

@ -1,22 +0,0 @@
util.AddNetworkString("Beatrun_ToggleDataTheft")
util.AddNetworkString("Beatrun_ToggleInfection")
local datatheft, infection = false
net.Receive("Beatrun_ToggleDataTheft", function(_, ply)
datatheft = not datatheft
if datatheft then
Beatrun_StartDataTheft()
else
Beatrun_StopDataTheft()
end
end)
net.Receive("Beatrun_ToggleInfection", function(_, ply)
infection = not infection
if infection then
Beatrun_StartInfection()
else
Beatrun_StopInfection()
end
end)

View file

@ -0,0 +1,28 @@
util.AddNetworkString("Beatrun_ToggleGamemode")
util.AddNetworkString("Beatrun_UpdateDataTheftLoadout")
local datatheft, infection = false
net.Receive("Beatrun_ToggleGamemode", function(_, ply)
local gm = net.ReadString()
if gm == "datatheft" then
datatheft = not datatheft
if datatheft then
Beatrun_StartDataTheft()
else
Beatrun_StopDataTheft()
end
elseif gm == "infection" then
infection = not infection
if infection then
Beatrun_StartInfection()
else
Beatrun_StopInfection()
end
end
end)
net.Receive("Beatrun_UpdateDataTheftLoadout", function(_, ply)
end)

View file

@ -0,0 +1,20 @@
util.AddNetworkString("Beatrun_UpdateLoadouts")
local function IsAvailableForPlayer(ply)
return ply:IsAdmin()
end
net.Receive("Beatrun_UpdateLoadouts", function(len, ply)
local data = net.ReadData(len)
data = util.Decompress(data)
if not data or data == "" then return end
local loadout = util.JSONToTable(data)
if not loadout then return print("Failed to parse %s\"s loadout!", ply:Nick()) end
local canUse, reason = IsAvailableForPlayer(ply)
if not canUse then return ply:ChatPrint("[Loadout] " .. reason) end
end)