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

@ -5,4 +5,4 @@
* Fixed grapple usage in courses and gamemodes.
* Fixed DataTheft crash when touching data bank.
* Fixed error when loading course.
* Fixed collisions issues.
* Fixed collisions issues.

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).
## 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`.
* Change HUD's colors - `Beatrun_HUDTextColor`, `Beatrun_HUDCornerColor`, `Beatrun_HUDFloatingXPColor`.
* 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`.
* Ability to remove ziplines that created with *Zipline Gun* - RMB.
* Removed your SteamID from right corner, because I can.
* Allow players to spawn props without admin rights - `Beatrun_AllowPropSpawn`.
## 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
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
end)

View file

@ -26,8 +26,8 @@ SWEP.DrawWeaponInfoBox = false
SWEP.HoldType = "fist"
SWEP.Spawnable = false
SWEP.AdminSpawnable = false
SWEP.Spawnable = true
SWEP.AdminSpawnable = true
--[[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.y = 540 - gamemodePanel.h * 0.5
local function closeButton()
AEUI:Clear()
end
local function infectionButton()
net.Start("Beatrun_ToggleInfection")
net.Start("Beatrun_ToggleGamemode")
net.WriteString("infection")
net.SendToServer()
end
local function datatheftButton()
net.Start("Beatrun_ToggleDataTheft")
net.Start("Beatrun_ToggleGamemode")
net.WriteString("datatheft")
net.SendToServer()
end
local loadoutnum = 1
local maxloadoutnum = 1
local function createButton()
net.Start("Beatrun_CreateLoadout")
net.SendToServer()
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 createButton()
-- net.Start("Beatrun_CreateLoadout")
-- net.SendToServer()
-- maxloadoutnum = maxloadoutnum + 1
-- LocalPlayer():EmitSound("buttonclick.wav")
-- end
local function isSA()
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)
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)
datatheftbutton.greyed = isSA()
datatheftbutton.greyed = isSA
-- 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)
-- resetbutton.greyed = isSA()
-- resetbutton.greyed = isSA
-- 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)
-- rightloadout.greyed = isSA()
-- rightloadout.greyed = isSA
-- AEUI:AddText(gamemodePanel, "Change through loadouts", "AEUILarge", gamemodePanel.w - 360, gamemodePanel.h - 125)
local weaponsList = {
@ -90,19 +68,22 @@ local weaponsList = {
function OpenGMMenu(ply)
AEUI:AddPanel(gamemodePanel)
AEUI:AddPanel(weaponsList)
local loaded_weapons = {}
for i, _ in pairs(DATATHEFT_LOADOUTS) do
for _, v in pairs(DATATHEFT_LOADOUTS[i]) do
table.insert(loaded_weapons, v)
end
end
for _, v in pairs(weapons.GetList()) do
if not string.find(v.ClassName:lower(), "base") then
local weaponentry = AEUI:AddText(weaponsList, v.ClassName, "AEUILarge", 10, 40 * #weaponsList.elements)
function weaponentry:onclick()
LocalPlayer():EmitSound("buttonclick.wav")
end
weaponentry.greyed = isSA()
weaponentry.greyed = isSA
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)
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)
else return false 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
ply:ConCommand("Beatrun_CourseMenu")
end
if (game.SinglePlayer() or CLIENT and IsFirstTimePredicted()) and button == KEY_F3 then
ply:ConCommand("Beatrun_GamemodesMenu")
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
local meta = FindMetaTable("Player")
local allowPropSpawn = CreateConVar("Beatrun_AllowPropSpawn", "0", {FCVAR_ARCHIVE}, "Allow players to spawn props and entities")
util.AddNetworkString("SPParkourEvent")
local spawn = {"PlayerGiveSWEP", "PlayerSpawnEffect", "PlayerSpawnNPC", "PlayerSpawnObject", "PlayerSpawnProp", "PlayerSpawnRagdoll", "PlayerSpawnSENT", "PlayerSpawnSWEP", "PlayerSpawnVehicle"}
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
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("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)
function meta:GTAB(minutes)

View file

@ -1,6 +1,8 @@
local vmatrixmeta = FindMetaTable("VMatrix")
local playermeta = FindMetaTable("Player")
CLoadout = {}
function CLIENT_IFTP()
return CLIENT and IsFirstTimePredicted()
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)