update!!11!

This commit is contained in:
Jonny_Bro (Nikita) 2023-06-04 14:49:25 +05:00
parent 019aa24125
commit 636f78953f
11 changed files with 115 additions and 746 deletions

36
Courses client.md Normal file
View file

@ -0,0 +1,36 @@
"C:\Users\Jonny\Desktop\xd\lua\weapons\mg_base\modules\client\cl_spawnmenu.lua"
Courses client
Beatrun_Apikey
Beatrun_Domain
Viewpunch client
Beatrun_ViewbobIntensity
Beatrun_ViewbobStabilized
Courses client
Beatrun_FastStart
Beatrun_CPSave
Misc server
Beatrun_AllowPropSpawn (Server)
Beatrun_AllowOvedriveInMultiplayer (server)
Purist mode
Beatrun_PuristMode (client)
Beatrun_PuristModeForce (server)
Beatrun_PuristWallrun (server)
Moves
Beatrun_QuickturnGround (client)
Beatrun_KickGlitch (server)
Beatrun_QuakeJump (server)
Beatrun_SideStep (server)
Beatrun_MaxSpeed (server)
Beatrun_Disarm (server)
Dive
Beatrun_Totsugeki
Beatrun_TotsugekiSpam
Beatrun_TotsugekiHeading
Beatrun_TotsugekiDir

View file

@ -1,14 +1,15 @@
# beatrun # beatrun
Modified beatrun's source code.<br><br> Modified beatrun's source code.<br><br>
There are lua modules ([source](https://github.com/fluffy-servers/gmod-discord-rpc)), they are for Discord Rich Presence to work, if you want pure Lua just don't extract them, but your Level and Map will not be shown in your Discord status.<br> There are lua modules, they are for Discord Rich Presence to work, if you want pure Lua just don't extract them, but your Level and Map will not be shown in your Discord status.<br>
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).
[Old Kick Glitch Version](https://github.com/JonnyBro/beatrun/tree/old-kickglitch) [Old Kick Glitch Version](https://github.com/JonnyBro/beatrun/tree/old-kickglitch)
# Installation # Installation
0. Delete `beatrun` folder in *addons* if you have it!
1. Extract `beatrun` folder to *your_game_folder/garrysmod/addons*. 1. Extract `beatrun` folder to *your_game_folder/garrysmod/addons*.
2. Extract `lua` folder to *your_game_folder/garrysmod*. 2. Extract `lua` folder to *your_game_folder/garrysmod*.
* `lua` folder constains modules for Discord Rich Presense to work. They are open source, visit [this](https://github.com/fluffy-servers/gmod-discord-rpc) link to see the source * `lua` folder constains modules for Discord Rich Presense to work. They are open source, visit [this](https://github.com/fluffy-servers/gmod-discord-rpc) to see the source.
## Changes added by me ## Changes added by me
* [Custom online courses database](https://courses.beatrun.ru)! It's free 🤯! * [Custom online courses database](https://courses.beatrun.ru)! It's free 🤯!
@ -26,10 +27,7 @@ This version of the beatrun works on any version of the game (Chromium or not).
- [ ] Gamemodes menu - [ ] Gamemodes menu
## Fixes and changes from previous version ## Fixes and changes from previous version
* Hacky fix for weapon damage. * You can now dive to your death =)
* Proper Kick Glitch (Like in original ME: https://www.youtube.com/watch?v=zK5y3NBUStc)
* Grapple fixes. Now it moves with entity it attached to and other players can see it.
* More reliable grappling.
# All changes and fixes # All changes and fixes
* Course saving works with compression and without. * Course saving works with compression and without.
@ -39,3 +37,7 @@ This version of the beatrun works on any version of the game (Chromium or not).
* Fixed DataTheft crash when touching data bank. * Fixed DataTheft crash when touching data bank.
* Fixed error when loading course. * Fixed error when loading course.
* Fixed collisions issues. * Fixed collisions issues.
* Fixed and tweaked player-player weapon damage.
* Proper Kick Glitch (Like in original ME: https://www.youtube.com/watch?v=zK5y3NBUStc)
* Grapple fixes. Now it moves with entity it attached to and other players can see it.
* More reliable grappling.

View file

@ -18,7 +18,7 @@ local function FallCheck()
if not IsValid(ply) then return end if not IsValid(ply) then return end
local speed = ply:GetVelocity().z local speed = ply:GetVelocity().z
if not ply.FallStatic and speed <= -800 and ply:GetMoveType() ~= MOVETYPE_NOCLIP then if not ply.FallStatic and speed <= -800 and ply:GetMoveType() ~= MOVETYPE_NOCLIP and ply:GetDive() == false then
ply:EmitSound("FallStatic") ply:EmitSound("FallStatic")
ply.FallStatic = true ply.FallStatic = true

View file

@ -1,10 +0,0 @@
hook.Add("AddToolMenuCategories", "Beatrun_Category", function()
spawnmenu.AddToolCategory("Beatrun", "beatrun_category", "Beatrun Settings")
end)
hook.Add("PopulateToolMenu", "CustomMenuSettings", function()
spawnmenu.AddToolMenuOption("Utilities", "Beatrun Settings", "Custom_Menu", "#My Custom Menu", "", "", function(panel)
panel:ClearControls()
panel:NumSlider("Gravity", "sv_gravity", 0, 600)
end)
end)

View file

@ -1,96 +0,0 @@
local gamemodePanel = {
w = 1200,
h = 650,
bgcolor = Color(32, 32, 32),
outlinecolor = Color(54, 55, 56),
alpha = 0.9,
elements = {}
}
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_ToggleGamemode")
net.WriteString("infection")
net.SendToServer()
end
local function datatheftButton()
net.Start("Beatrun_ToggleGamemode")
net.WriteString("datatheft")
net.SendToServer()
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()
end
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
local datatheftbutton = AEUI:AddButton(gamemodePanel, "Toggle Data Theft", datatheftButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 450)
datatheftbutton.greyed = isSA
-- local loadoutbutton = AEUI:AddButton(gamemodePanel, "Create a new loadout", createButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 450)
-- loadoutbutton.greyed = isSA
-- local resetbutton = AEUI:AddButton(gamemodePanel, "Resets all loadouts", resetloadoutButton, "AEUILarge", gamemodePanel.w - 330, gamemodePanel.h - 550)
-- resetbutton.greyed = isSA
-- local leftloadout = AEUI:AddButton(gamemodePanel, " < ", leftButton, "AEUILarge", gamemodePanel.w - 225, gamemodePanel.h - 175)
-- leftloadout.greyed = isSA
-- local rightloadout = AEUI:AddButton(gamemodePanel, " > ", rightButton, "AEUILarge", gamemodePanel.w - 150, gamemodePanel.h - 175)
-- rightloadout.greyed = isSA
-- AEUI:AddText(gamemodePanel, "Change through loadouts", "AEUILarge", gamemodePanel.w - 360, gamemodePanel.h - 125)
local weaponsList = {
w = 800,
h = 450,
x = 979.2 - gamemodePanel.w * 0.5,
y = 648 - gamemodePanel.h * 0.5,
bgcolor = Color(32, 32, 32),
outlinecolor = Color(54, 55, 56),
alpha = 0.9,
elements = {}
}
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
end
end
end
hook.Add("InitPostEntity", "GMMenuCommand", function()
concommand.Add("Beatrun_GamemodesMenu", OpenGMMenu)
hook.Remove("InitPostEntity", "GMMenuCommand")
end)
concommand.Add("Beatrun_GamemodesMenu", OpenGMMenu)

View file

@ -1,490 +0,0 @@
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

@ -1,122 +0,0 @@
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

@ -0,0 +1,67 @@
local function StartInfection()
net.Start("Beatrun_ToggleGamemode")
net.WriteString("infection")
net.SendToServer()
end
local function StartDataTheft()
net.Start("Beatrun_ToggleGamemode")
net.WriteString("datatheft")
net.SendToServer()
end
hook.Add("AddToolMenuCategories", "Beatrun_Category", function()
spawnmenu.AddToolCategory("Beatrun", "Client", "Client")
end)
hook.Add("PopulateToolMenu", "Beatrun_ToolMenu", function()
--[[
Beatrun_FOV
Beatrun_HUDXP
Beatrun_HUDSway
Beatrun_HUDDynamic
Beatrun_HUDHidden
Beatrun_HUDReticle
Beatrun_HUDTextColor
Beatrun_HUDCornerColor
Beatrun_HUDFloatingXPColor
Beatrun_MinimalVM
Beatrun_Wind
--]]
spawnmenu.AddToolMenuOption("Beatrun", "Client", "beatrun_hud", "HUD", "", "", function(panel)
panel:ClearControls()
panel:SetName("HUD Setttings")
panel:CheckBox("Show total XP near your nickname", "Beatrun_HUDXP")
panel:CheckBox("Display HUD swaying", "Beatrun_HUDSway")
panel:CheckBox("Hide HUD when moving", "Beatrun_HUDDynamic")
panel:CheckBox("Display a dot in the center of the screen", "Beatrun_HUDReticle")
panel:NumSlider("FOV", "Beatrun_FOV", 90, 120, 0)
panel:ControlHelp("You need to respawn after changing FOV!")
panel:NumSlider("Hide HUD", "Beatrun_HUDHidden", 0, 2, 0)
panel:ControlHelp("0 - Shown\n1 - Gamemode only\n2 - Hidden")
local divider = vgui.Create("DHorizontalDivider")
panel:AddItem(divider)
panel:Help("HUD Text Color")
local HudTextColor = vgui.Create("DColorMixer", Frame)
HudTextColor:Dock(FILL)
HudTextColor:SetPalette(true)
HudTextColor:SetAlphaBar(true)
HudTextColor:SetWangs(true)
HudTextColor:SetColor(string.ToColor(GetConVar("Beatrun_HUDTextColor"):GetString()))
function HudTextColor:ValueChanged(color)
RunConsoleCommand("Beatrun_HUDTextColor", string.FromColor(col))
end
panel:AddItem(HudTextColor)
end)
end)

View file

@ -40,7 +40,7 @@ if SERVER then
end end
if CLIENT then if CLIENT then
CreateClientConVar("Beatrun_FOV", 90, true, true, "'Woah how are you moving this fast' and other hilarious jokes", 70, 175) CreateClientConVar("Beatrun_FOV", 90, true, true, "'Woah how are you moving this fast' and other hilarious jokes", 70, 120)
CreateClientConVar("Beatrun_CPSave", 1, true, true, "Respawning during a course will go back to the last hit checkpoint", 0, 1) CreateClientConVar("Beatrun_CPSave", 1, true, true, "Respawning during a course will go back to the last hit checkpoint", 0, 1)
end end

View file

@ -8,6 +8,7 @@ net.Receive("Beatrun_ToggleGamemode", function(_, ply)
if gm == "datatheft" then if gm == "datatheft" then
datatheft = not datatheft datatheft = not datatheft
if datatheft then if datatheft then
Beatrun_StartDataTheft() Beatrun_StartDataTheft()
else else
@ -15,6 +16,7 @@ net.Receive("Beatrun_ToggleGamemode", function(_, ply)
end end
elseif gm == "infection" then elseif gm == "infection" then
infection = not infection infection = not infection
if infection then if infection then
Beatrun_StartInfection() Beatrun_StartInfection()
else else

View file

@ -1,20 +0,0 @@
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)