diff --git a/fxmanifest.lua b/fxmanifest.lua
index 9c0f698..6f71174 100644
--- a/fxmanifest.lua
+++ b/fxmanifest.lua
@@ -1,9 +1,10 @@
-name "Jim_Bridge"
+name "Jim_RedBridge"
author "Jimathy"
version "2.0"
description "Framework Bridge By Jimathy"
fx_version "cerulean"
-game "gta5"
+rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'
+games { 'gta5', 'rdr3' }
lua54 'yes'
files {
diff --git a/shared/_loaders.lua b/shared/_loaders.lua
index c92a227..20d1fc4 100644
--- a/shared/_loaders.lua
+++ b/shared/_loaders.lua
@@ -53,6 +53,9 @@ function onPlayerLoaded(func, onStart)
elseif isStarted(OXCoreExport) then
onPlayerFramework = OXCoreExport
AddEventHandler('ox:playerLoaded', tempFunc)
+ elseif isStarted(RSGExport) then
+ onPlayerFramework = RSGExport
+ AddEventHandler('RSGCore:Client:OnPlayerLoaded', tempFunc)
end
if onPlayerFramework ~= "" then
@@ -75,6 +78,7 @@ end
function onPlayerUnload(func)
AddEventHandler('QBCore:Client:OnPlayerUnload', function() func() end)
AddEventHandler('ox:playerLogout', function() func() end)
+ AddEventHandler('RSGCore:Client:OnPlayerUnload', function() func() end)
--AddEventHandler('esx:playerLogout', function() func() end)
-- ^ Only server side for now, need a way to send it to client if not already available
diff --git a/shared/coreloader.lua b/shared/coreloader.lua
index 5b1d086..b81a659 100644
--- a/shared/coreloader.lua
+++ b/shared/coreloader.lua
@@ -36,6 +36,10 @@ OXInv, QBInv, PSInv, QSInv, CoreInv, CodeMInv, OrigenInv =
Exports.CodeMInv or "",
Exports.OrigenInv or ""
+RSGExport, RSGInv =
+ Exports.RSGExport or "",
+ Exports.RSGInv or ""
+
QBMenuExport = Exports.QBMenuExport or ""
QBTargetExport, OXTargetExport = Exports.QBTargetExport or "", Exports.OXTargetExport or ""
@@ -112,6 +116,18 @@ elseif isStarted(ESXExport) then
debugPrint("^6Bridge^7: ^2Loading ^6"..countTable(Items).." ^3Items^2 from ^7"..itemResource)
end
end)
+
+elseif isStarted(RSGExport) then
+ itemResource = RSGExport
+ Core = Core or exports[RSGExport]:GetCoreObject()
+ Items = Core and Core.Shared.Items or nil
+ if isStarted(RSGExport) and not isStarted(QBXExport) then
+ RegisterNetEvent('QBCore:Client:UpdateObject', function()
+ Core = Core or exports[RSGExport]:GetCoreObject()
+ Items = Core and Core.Shared.Items or nil
+ end)
+ end
+
end
if not isStarted(ESXExport) then
@@ -167,6 +183,17 @@ elseif isStarted(ESXExport) then
end
end
end)
+
+elseif isStarted(RSGExport) then
+ Core = Core or exports[RSGExport]:GetCoreObject()
+ Vehicles = Core and Core.Shared.Vehicles
+ if isStarted(RSGExport) then
+ RegisterNetEvent('RSGExport:Client:UpdateObject', function()
+ Core = Core or exports[RSGExport]:GetCoreObject()
+ Vehicles = Core and Core.Shared.Vehicles
+ end)
+ end
+ vehResource = RSGExport
end
if vehResource == nil then
@@ -239,6 +266,17 @@ elseif isStarted(ESXExport) then
Gangs = Jobs
end
end)
+
+elseif isStarted(RSGExport) then
+ jobResource = RSGExport
+ Core = Core or exports[RSGExport]:GetCoreObject()
+ Jobs, Gangs = Core.Shared.Jobs, Core.Shared.Gangs
+ if isStarted(RSGExport) and not isStarted(QBXExport) then
+ RegisterNetEvent('QBCore:Client:UpdateObject', function()
+ Core = exports[RSGExport]:GetCoreObject()
+ Jobs, Gangs = Core.Shared.Jobs, Core.Shared.Gangs
+ end)
+ end
end
if not isStarted(ESXExport) and Jobs then
diff --git a/shared/drawText.lua b/shared/drawText.lua
index 6d6fd85..17a30fb 100644
--- a/shared/drawText.lua
+++ b/shared/drawText.lua
@@ -71,6 +71,16 @@ function drawText(image, input, style, oxStyleTable)
icon = nil,
text = text,
})
+
+ elseif Config.System.drawText == "red" then
+ -- Concatenate input lines and apply GTA style formatting.
+ for i = 1, #input do
+ if input[i] ~= "" then
+ text = text..input[i].."\n~q~"
+ end
+ end
+ TriggerEvent("jim-redui:DrawText", text)
+
end
end
@@ -91,5 +101,7 @@ function hideText()
ClearAllHelpMessages()
elseif Config.System.drawText == "esx" then
ESX.HideUI()
+ elseif Config.System.drawText == "red" then
+ TriggerEvent("jim-redui:HideText")
end
end
\ No newline at end of file
diff --git a/shared/duifunctions.lua b/shared/duifunctions.lua
index ff5d777..ea9ffc1 100644
--- a/shared/duifunctions.lua
+++ b/shared/duifunctions.lua
@@ -1,165 +1,168 @@
+if gameName ~= "rdr3" then
--[[
- DUI Module (Experimental)
- --------------------------
- This module handles the creation, modification, and removal of custom DUI (Display UI)
- elements using runtime textures. It supports both client and server functionality to update DUI
- images dynamically.
-]]
+ DUI Module (Experimental)
+ --------------------------
+ This module handles the creation, modification, and removal of custom DUI (Display UI)
+ elements using runtime textures. It supports both client and server functionality to update DUI
+ images dynamically.
+ ]]
--- Create a runtime texture dictionary on the client if not running on the server.
-scriptTxd = not isServer() and CreateRuntimeTxd(getScript()..'scriptTxd') or nil
-customDUIList = {}
+ -- Create a runtime texture dictionary on the client if not running on the server.
+ scriptTxd = not isServer() and CreateRuntimeTxd(getScript()..'scriptTxd') or nil
+ customDUIList = {}
--------------------------------------------------------------
--- DUI Client Functions
--------------------------------------------------------------
+ -------------------------------------------------------------
+ -- DUI Client Functions
+ -------------------------------------------------------------
---- Creates or updates a DUI element.
----
---- @param name string The unique name for the DUI element.
---- @param http string The URL to load into the DUI.
---- @param size table A table with .x and .y fields specifying the DUI dimensions.
---- @param txd table The runtime texture dictionary where the DUI texture will be created.
---- @usage
---- ```lua
---- createDui("logo", "https://example.com/logo.png", { x = 512, y = 256 }, scriptTxd)
---- ```
-function createDui(name, http, size, txd)
- if not customDUIList[name] then
- local newDui = CreateDui(http, math.floor(size.x), math.floor(size.y))
- while not GetDuiHandle(newDui) do Wait(0) end
- CreateRuntimeTextureFromDuiHandle(txd, name, GetDuiHandle(newDui))
- customDUIList[name] = newDui
- SetDuiUrl(customDUIList[name], http)
- else
- SetDuiUrl(customDUIList[name], http)
- end
-end
-
---- Opens a DUI selection input allowing the user to change the DUI image URL.
----
---- @param data table A table containing DUI data:
---- - name: The key name in the DUI list.
---- - texn: The texture name.
---- - texd: The texture dictionary.
---- - size: A table with .x and .y dimensions.
----
---- @usage
---- ```lua
---- DuiSelect({ name = "logo", texn = "logoTex", texd = "someTxd", size = { x = 512, y = 256 } })
---- ```
-function DuiSelect(data)
- local imagePreview = ""
- for k, v in pairs(duiList[data.name]) do
- if v.tex.texn == data.texn and duiList[data.name][k] then
- imagePreview = "
- Current Image -
" ..
- "
" ..
- "Size: ["..math.floor(data.size.x)..", "..math.floor(data.size.y).."]
"
+ --- Creates or updates a DUI element.
+ ---
+ --- @param name string The unique name for the DUI element.
+ --- @param http string The URL to load into the DUI.
+ --- @param size table A table with .x and .y fields specifying the DUI dimensions.
+ --- @param txd table The runtime texture dictionary where the DUI texture will be created.
+ --- @usage
+ --- ```lua
+ --- createDui("logo", "https://example.com/logo.png", { x = 512, y = 256 }, scriptTxd)
+ --- ```
+ function createDui(name, http, size, txd)
+ if not customDUIList[name] then
+ local newDui = CreateDui(http, math.floor(size.x), math.floor(size.y))
+ while not GetDuiHandle(newDui) do Wait(0) end
+ CreateRuntimeTextureFromDuiHandle(txd, name, GetDuiHandle(newDui))
+ customDUIList[name] = newDui
+ SetDuiUrl(customDUIList[name], http)
+ else
+ SetDuiUrl(customDUIList[name], http)
end
end
- local dialog = exports['qb-input']:ShowInput({
- header = imagePreview..Loc[Config.Lan].menu["dui_new"],
- submitText = Loc[Config.Lan].menu["dui_change"],
- inputs = { { type = 'text', isRequired = true, name = 'url', text = Loc[Config.Lan].menu["dui_url"] } }
- })
- if dialog and dialog.url then
- data.url = dialog.url
- -- Scan URL for valid image extension and banned words.
- local searchList = { "png", "jpg", "jpeg", "gif", "webp", "bmp" }
- local banList = { "porn" }
- local searchFound = false
- for _, ext in pairs(searchList) do
- if string.find(tostring(data.url), ext) then
- searchFound = true
- break
- end
- end
- for _, banned in pairs(banList) do
- if string.find(tostring(data.url), banned) then
- searchFound = false
- print("BANNED WORD: "..banned)
- break
- end
- end
- if searchFound then
- TriggerServerEvent(getScript()..":Server:ChangeDUI", data)
- end
- end
-end
---- Client event handler to update DUI elements.
-RegisterNetEvent(getScript()..":Client:ChangeDUI", function(data)
- debugPrint("^6Bridge^7: ^2Receiving new DUI ^7- ^6"..data.url.."^7")
- if tostring(data.url) ~= "-" then
- createDui(data.texn, tostring(data.url), data.size, scriptTxd)
- AddReplaceTexture(tostring(data.texd), tostring(data.texn), getScript().."scriptTxd", tostring(data.texn))
- end
-end)
-
---- Client event handler to clear DUI elements.
-RegisterNetEvent(getScript()..":Client:ClearDUI", function(data)
- if customDUIList[tostring(data.texn)] then
- RemoveReplaceTexture(tostring(data.texd), tostring(data.texn))
- if IsDuiAvailable(customDUIList[tostring(data.texn)]) then
- SetDuiUrl(customDUIList[data.name], nil)
- end
- end
-end)
-
--------------------------------------------------------------
--- DUI Server Functions
--------------------------------------------------------------
-
---- Server event handler to change DUI settings.
---- If no URL is provided, resets to the preset value.
-RegisterNetEvent(getScript()..":Server:ChangeDUI", function(data)
- if not data.url then
+ --- Opens a DUI selection input allowing the user to change the DUI image URL.
+ ---
+ --- @param data table A table containing DUI data:
+ --- - name: The key name in the DUI list.
+ --- - texn: The texture name.
+ --- - texd: The texture dictionary.
+ --- - size: A table with .x and .y dimensions.
+ ---
+ --- @usage
+ --- ```lua
+ --- DuiSelect({ name = "logo", texn = "logoTex", texd = "someTxd", size = { x = 512, y = 256 } })
+ --- ```
+ function DuiSelect(data)
+ local imagePreview = ""
for k, v in pairs(duiList[data.name]) do
- if v.tex.texn == data.texn then
- debugPrint("^6Bridge^7: ^2Preset: ^6"..tostring(duiList[data.name][k].preset).."^7")
- data.url = duiList[data.name][k].preset
+ if v.tex.texn == data.texn and duiList[data.name][k] then
+ imagePreview = "- Current Image -
" ..
+ "
" ..
+ "Size: ["..math.floor(data.size.x)..", "..math.floor(data.size.y).."]
"
+ end
+ end
+ local dialog = exports['qb-input']:ShowInput({
+ header = imagePreview..Loc[Config.Lan].menu["dui_new"],
+ submitText = Loc[Config.Lan].menu["dui_change"],
+ inputs = { { type = 'text', isRequired = true, name = 'url', text = Loc[Config.Lan].menu["dui_url"] } }
+ })
+ if dialog and dialog.url then
+ data.url = dialog.url
+ -- Scan URL for valid image extension and banned words.
+ local searchList = { "png", "jpg", "jpeg", "gif", "webp", "bmp" }
+ local banList = { "porn" }
+ local searchFound = false
+ for _, ext in pairs(searchList) do
+ if string.find(tostring(data.url), ext) then
+ searchFound = true
+ break
+ end
+ end
+ for _, banned in pairs(banList) do
+ if string.find(tostring(data.url), banned) then
+ searchFound = false
+ print("BANNED WORD: "..banned)
+ break
+ end
+ end
+ if searchFound then
+ TriggerServerEvent(getScript()..":Server:ChangeDUI", data)
end
end
end
- for k, v in pairs(duiList[data.name]) do
- if v.tex.texn == data.texn then
- duiList[data.name][k].url = data.url
+
+ --- Client event handler to update DUI elements.
+ RegisterNetEvent(getScript()..":Client:ChangeDUI", function(data)
+ debugPrint("^6Bridge^7: ^2Receiving new DUI ^7- ^6"..data.url.."^7")
+ if tostring(data.url) ~= "-" then
+ createDui(data.texn, tostring(data.url), data.size, scriptTxd)
+ AddReplaceTexture(tostring(data.texd), tostring(data.texn), getScript().."scriptTxd", tostring(data.texn))
end
- end
- debugPrint("^6Bridge^7: ^3DUI^2 Sending new DUI to all players^7 - ^6"..data.url.."^7")
- TriggerClientEvent(getScript()..":Client:ChangeDUI", -1, data)
-end)
-
---- Server event handler to clear DUI settings.
-RegisterNetEvent(getScript()..":Server:ClearDUI", function(data)
- if data.url == "-" then
- for k, v in pairs(duiList[data.name]) do
- if v.tex.texn == data.texn then
- duiList[data.name][k].url = "-"
- end
- end
- end
- TriggerClientEvent(getScript()..":Client:ClearDUI", -1, data)
-end)
-
--------------------------------------------------------------
--- Resource Cleanup
--------------------------------------------------------------
-
-onResourceStop(function()
- for k, v in pairs(duiList or {}) do
- for i = 1, #v do
- RemoveReplaceTexture(tostring(v[i].tex.texd), tostring(v[i].tex.texn))
- end
- end
-end, true)
-
--------------------------------------------------------------
--- DUI List Callback (Server)
--------------------------------------------------------------
-
-if isServer() then
- createCallback(getScript()..":Server:duiList", function(source)
- return duiList
end)
+
+ --- Client event handler to clear DUI elements.
+ RegisterNetEvent(getScript()..":Client:ClearDUI", function(data)
+ if customDUIList[tostring(data.texn)] then
+ RemoveReplaceTexture(tostring(data.texd), tostring(data.texn))
+ if IsDuiAvailable(customDUIList[tostring(data.texn)]) then
+ SetDuiUrl(customDUIList[data.name], nil)
+ end
+ end
+ end)
+
+ -------------------------------------------------------------
+ -- DUI Server Functions
+ -------------------------------------------------------------
+
+ --- Server event handler to change DUI settings.
+ --- If no URL is provided, resets to the preset value.
+ RegisterNetEvent(getScript()..":Server:ChangeDUI", function(data)
+ if not data.url then
+ for k, v in pairs(duiList[data.name]) do
+ if v.tex.texn == data.texn then
+ debugPrint("^6Bridge^7: ^2Preset: ^6"..tostring(duiList[data.name][k].preset).."^7")
+ data.url = duiList[data.name][k].preset
+ end
+ end
+ end
+ for k, v in pairs(duiList[data.name]) do
+ if v.tex.texn == data.texn then
+ duiList[data.name][k].url = data.url
+ end
+ end
+ debugPrint("^6Bridge^7: ^3DUI^2 Sending new DUI to all players^7 - ^6"..data.url.."^7")
+ TriggerClientEvent(getScript()..":Client:ChangeDUI", -1, data)
+ end)
+
+ --- Server event handler to clear DUI settings.
+ RegisterNetEvent(getScript()..":Server:ClearDUI", function(data)
+ if data.url == "-" then
+ for k, v in pairs(duiList[data.name]) do
+ if v.tex.texn == data.texn then
+ duiList[data.name][k].url = "-"
+ end
+ end
+ end
+ TriggerClientEvent(getScript()..":Client:ClearDUI", -1, data)
+ end)
+
+ -------------------------------------------------------------
+ -- Resource Cleanup
+ -------------------------------------------------------------
+
+ onResourceStop(function()
+ for k, v in pairs(duiList or {}) do
+ for i = 1, #v do
+ RemoveReplaceTexture(tostring(v[i].tex.texd), tostring(v[i].tex.texn))
+ end
+ end
+ end, true)
+
+ -------------------------------------------------------------
+ -- DUI List Callback (Server)
+ -------------------------------------------------------------
+
+ if isServer() then
+ createCallback(getScript()..":Server:duiList", function(source)
+ return duiList
+ end)
+ end
+
end
\ No newline at end of file
diff --git a/shared/inventories.lua b/shared/inventories.lua
index ab4b07d..348cb65 100644
--- a/shared/inventories.lua
+++ b/shared/inventories.lua
@@ -148,6 +148,14 @@ function getPlayerInv(src)
grabInv = xPlayer.inventory
end
+ elseif isStarted(RSGInv) then
+ foundInv = RSGInv
+ if src then
+ grabInv = Core.Functions.GetPlayer(src).PlayerData.items
+ else
+ grabInv = Core.Functions.GetPlayerData().items
+ end
+
else
print("^4ERROR^7: ^2No Inventory detected ^7- ^2Check ^3starter^1.^2lua^7")
end
diff --git a/shared/itemcontrol.lua b/shared/itemcontrol.lua
index 7707b31..eb966f5 100644
--- a/shared/itemcontrol.lua
+++ b/shared/itemcontrol.lua
@@ -74,6 +74,8 @@ function invImg(item)
imgLink = "nui://"..OrigenInv.."/html/img/"..(Items[item].image or "")
elseif isStarted(QBInv) then
imgLink = "nui://"..QBInv.."/html/images/"..(Items[item].image or "")
+ elseif isStarted(RSGInv) then
+ imgLink = "nui://"..RSGInv.."/html/images/"..(Items[item].image or "")
else
print("^4ERROR^7: ^2No Inventory detected for invImg - Check starter.lua")
end
@@ -99,12 +101,15 @@ end
--- addItem("health_potion", 2, { quality = "high" })
--- ```
function addItem(item, amount, info, src)
- if not Items[item] then print("^6Bridge^7: ^1Error^7 - ^2Tried to give ^7'^3"..item.."^7'^2 but it doesn't exist") return end
+ if not Items[item] then
+ print("^6Bridge^7: ^1Error^7 - ^2Tried to give ^7'^3"..item.."^7'^2 but it doesn't exist")
+ return
+ end
if src then
TriggerEvent(getScript()..":server:toggleItem", true, item, amount, src, info)
else
- TriggerServerEvent(getScript()..":server:toggleItem", true, item, amount, currentToken, info)
+ TriggerServerEvent(getScript()..":server:toggleItem", true, item, amount, nil, info, nil, currentToken)
currentToken = nil -- clear client cached token
end
end
@@ -129,6 +134,7 @@ function removeItem(item, amount, src, slot)
end
if src then
+ debugPrint(src)
TriggerEvent(getScript()..":server:toggleItem", false, item, amount, src, nil, slot)
else
TriggerServerEvent(getScript()..":server:toggleItem", false, item, amount, nil, nil, slot)
@@ -155,26 +161,33 @@ end
--- ```lua
--- TriggerServerEvent(getScript()..":server:toggleItem", true, "health_potion", 1)
--- ```
-RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount, newsrc, info, slot)
+RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount, newsrc, info, slot, token)
+ debugPrint(GetInvokingResource())
+ if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= "qb-core" then
+ debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital function was called from an external resource^7")
+ return
+ end
if not Items[item] then
print("^6Bridge^7: ^1Error^7 - ^2Tried to "..(tostring(give) == "true" and "add" or "remove").." '^3"..item.."^7' but it doesn't exist")
return
end
- local src = source or newsrc
+ local src = newsrc or source
if (give == true or give == 1) then
if newsrc == nil then -- must be coming from client this would be blank
- debugPrint("^1Auth^7: ^1No token recieved^7")
- dupeWarn(src, item, "Auth: Player "..src.." attempted to spawn "..item.." without an auth token")
- else
- if type(newsrc) ~= "number" then -- checks if the newsrc is a source or token, if number its coming form the server itself
- debugPrint("^1Auth^7: ^2Auth token received^7, ^2checking against server cache^7..")
- if newsrc ~= validTokens[src] then
- debugPrint("^1Auth^7: ^1Tokens don't match! ^7", newsrc, validTokens[src])
- dupeWarn(src, item, "Auth: "..src.." attempted to spawn "..item.." with an incorrect auth token")
- else
- debugPrint("^1Auth^7: ^2Client and Server Auth tokens match^7!", newsrc, validTokens[src])
- validTokens[src] = nil
+ if token == nil then
+ debugPrint("^1Auth^7: ^1No token recieved^7")
+ dupeWarn(src, item, "Auth: Player "..src.." attempted to spawn "..item.." without an auth token")
+ else
+ if type(token) ~= "number" then -- checks if the newsrc is a source or token, if number its coming form the server itself
+ debugPrint("^1Auth^7: ^2Auth token received^7, ^2checking against server cache^7..")
+ if token ~= validTokens[src] then
+ debugPrint("^1Auth^7: ^1Tokens don't match! ^7", token, validTokens[src])
+ dupeWarn(src, item, "Auth: "..src.." attempted to spawn "..item.." with an incorrect auth token")
+ else
+ debugPrint("^1Auth^7: ^2Client and Server Auth tokens match^7!", token, validTokens[src])
+ validTokens[src] = nil
+ end
end
end
end
@@ -230,6 +243,20 @@ RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount,
if Config.Crafting.showItemBox then
TriggerClientEvent("inventory:client:ItemBox", src, Items[item], "remove", amount or 1)
end
+
+ elseif isStarted(RSGInv) then invName = RSGInv
+ while remamount > 0 do
+ if Core.Functions.GetPlayer(src).Functions.RemoveItem(item, 1, slot) then
+ remamount -= 1
+ else
+ print("^1Error removing "..item.." Amount left: "..remamount)
+ break
+ end
+ end
+ if Config.Crafting.showItemBox then
+ TriggerClientEvent("rsg-inventory:client:ItemBox", src, Items[item], "remove", amount or 1)
+ end
+
end
-----
-- Fallback for if no inventory found:
@@ -274,6 +301,11 @@ RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount,
TriggerClientEvent((isStarted(QBInv) and QBInvNew and "qb-" or "").."inventory:client:ItemBox", src, Items[item], "add", amountToAdd)
end
+ elseif isStarted(RSGInv) then invName = RSGInv
+ if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then
+ TriggerClientEvent("rsg-inventory:client:ItemBox", src, Items[item], "add", amountToAdd)
+ end
+
elseif isStarted(PSInv) then invName = PSInv
if Core.Functions.GetPlayer(src).Functions.AddItem(item, amountToAdd, nil, info) then
if Config.Crafting.showItemBox then
@@ -601,7 +633,12 @@ function canCarry(itemTable, src)
resultTable[k] = exports[OrigenInv]:canCarryItem(src, k, v)
end
- elseif isStarted(QBInv) or isStarted(PSInv) then
+ elseif isStarted(QBInv) then
+ for k, v in pairs(itemTable) do
+ resultTable[k] = exports[QBInv]:CanAddItem(src, k, v)
+ end
+
+ elseif isStarted(PSInv) then
local items = getPlayerInv(src)
local totalWeight = 0
if not items then return false end
@@ -616,6 +653,22 @@ function canCarry(itemTable, src)
resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight
end
end
+
+ elseif isStarted(RSGInv) then
+ local items = getPlayerInv(src)
+ local totalWeight = 0
+ if not items then return false end
+ for _, item in pairs(items) do
+ totalWeight += (item.weight * item.amount)
+ end
+ for k, v in pairs(itemTable) do
+ local itemInfo = Items[k]
+ if not itemInfo then
+ resultTable[k] = true
+ else
+ resultTable[k] = (totalWeight + (itemInfo.weight * v)) <= InventoryWeight
+ end
+ end
end
end
return resultTable
@@ -637,6 +690,11 @@ if isServer() then
createCallback(AuthEvent, function(source)
local src = source
local token = keyGen()..keyGen()..keyGen()..keyGen() -- Use a secure random generator here
+ debugPrint(GetInvokingResource())
+ if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= "qb-core" then
+ debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital function was called from an external resource^7")
+ return ""
+ end
debugPrint("^1Auth^7:^2 Player Source^7: "..src.." ^2requested new token^7:", token)
validTokens[src] = token
timeOutAuth(validTokens[src], src) -- Give script 10 seconds, then clear token
@@ -664,6 +722,11 @@ if isServer() then
receivedEvent = {}
createCallback(getScript()..":callback:GetAuthEvent", function(source)
local src = source
+ debugPrint(GetInvokingResource())
+ if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= "qb-core" then
+ debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital callback was called from an external resource^7")
+ return ""
+ end
debugPrint("^1Auth^7: ^2Player Source^7: "..src.." ^2requested ^3AuthEvent^7", AuthEvent)
if not receivedEvent[src] then receivedEvent[src] = true
return AuthEvent
@@ -673,8 +736,6 @@ if isServer() then
end
end)
else
- onResourceStart(function()
- debugPrint("^1Auth^7: ^2Requesting ^3Auth Event^7")
- AuthEvent = triggerCallback(getScript()..":callback:GetAuthEvent")
- end, true)
+ debugPrint("^1Auth^7: ^2Requesting ^3Auth Event^7")
+ AuthEvent = triggerCallback(getScript()..":callback:GetAuthEvent")
end
diff --git a/shared/jobfunctions.lua b/shared/jobfunctions.lua
index b338a3f..36cbb58 100644
--- a/shared/jobfunctions.lua
+++ b/shared/jobfunctions.lua
@@ -69,7 +69,7 @@ end
function jobCheck(job)
local canDo = true
if Jobs[job] then
- if not hasJob(job) or not onDuty then
+ if not hasJob(job) or not getPlayer().onDuty then
triggerNotify(nil, Loc[Config.Lan].error["not_clockedin"])
canDo = false
end
@@ -92,10 +92,10 @@ end
--- toggleDuty() -- Player receives a notification of their new duty status.
--- ```
function toggleDuty()
+ onDuty = not onDuty
if isStarted(QBExport) or isStarted(QBXExport) then
TriggerServerEvent("QBCore:ToggleDuty")
else
- onDuty = not onDuty
if onDuty then
triggerNotify(nil, "Now on duty", "success")
else
diff --git a/shared/make/makeBlip.lua b/shared/make/makeBlip.lua
index b773eae..52c9dbd 100644
--- a/shared/make/makeBlip.lua
+++ b/shared/make/makeBlip.lua
@@ -1,3 +1,5 @@
+local blipTable = {}
+
--- Creates a blip at specified coordinates with given properties.
--
-- This function adds a map blip at the provided coordinates and sets various display properties such as sprite, color, scale, and more.
@@ -30,31 +32,48 @@
-- local blip = makeBlip(blipData)
-- ```
function makeBlip(data)
- local blip = AddBlipForCoord(vec3(data.coords.x, data.coords.y, data.coords.z))
- SetBlipCoords(blip, data.coords.x, data.coords.y, data.coords.z) -- Manually set blip coordinates again as sometimes it just refuses
- SetBlipAsShortRange(blip, true)
- SetBlipSprite(blip, data.sprite or 106)
- SetBlipColour(blip, data.col or 5)
- SetBlipScale(blip, data.scale or 0.7)
- SetBlipDisplay(blip, data.disp or 6)
- if data.category then SetBlipCategory(blip, data.category) end
- BeginTextCommandSetBlipName('STRING')
- AddTextComponentString(tostring(data.name))
- EndTextCommandSetBlipName(blip)
- -- Handle preview image if certain resources are running
- if isStarted("fs_smallresources") or isStarted("blip_info") or isStarted("blipinfo") then
- if data.preview then
- local txname = string.gsub(tostring(data.name..'preview'..string.gsub(data.coords.z, "%.", "")), "[ ()~]", "")
- if data.preview:find("http") or data.preview:find("nui") then
- createDui(txname, data.preview, vec2(512, 256), scriptTxd)
- else
- CreateRuntimeTextureFromImage(scriptTxd, txname, data.preview)
+ local blip = nil
+ if gameName == "rdr3" then
+ blip = BlipAddForCoords(1664425300, data.coords.x, data.coords.y, data.coords.z)
+ SetBlipSprite(blip, data.sprite or `blip_shop_market_stall`)
+ SetBlipScale(blip, data.scale or 0.2)
+ SetBlipName(blip, data.name)
+ --BlipSetStyle(blip, data.col or `BLIP_STYLE_CREATOR_DEFAULT`)
+ else
+ blip = AddBlipForCoord(vec3(data.coords.x, data.coords.y, data.coords.z))
+ SetBlipCoords(blip, data.coords.x, data.coords.y, data.coords.z) -- Manually set blip coordinates again as sometimes it just refuses
+ SetBlipAsShortRange(blip, true)
+ SetBlipSprite(blip, data.sprite or 106)
+ SetBlipColour(blip, data.col or 5)
+ SetBlipScale(blip, data.scale or 0.7)
+ SetBlipDisplay(blip, data.disp or 6)
+ if data.category then
+ SetBlipCategory(blip, data.category)
+ end
+ BeginTextCommandSetBlipName('STRING')
+ AddTextComponentString(tostring(data.name))
+ EndTextCommandSetBlipName(blip)
+ -- Handle preview image if certain resources are running
+ if isStarted("fs_smallresources") or isStarted("blip_info") or isStarted("blipinfo") then
+ if data.preview then
+ local txname = string.gsub(tostring(data.name..'preview'..string.gsub(data.coords.z, "%.", "")), "[ ()~]", "")
+ if data.preview:find("http") or data.preview:find("nui") then
+ createDui(txname, data.preview, vec2(512, 256), scriptTxd)
+ else
+ CreateRuntimeTextureFromImage(scriptTxd, txname, data.preview)
+ end
+ exports["fs_smallresources"]:SetBlipInfoImage(blip, getScript()..'scriptTxd', txname)
+ exports["fs_smallresources"]:SetBlipInfoTitle(blip, data.name, false)
end
- exports["fs_smallresources"]:SetBlipInfoImage(blip, getScript()..'scriptTxd', txname)
- exports["fs_smallresources"]:SetBlipInfoTitle(blip, data.name, false)
end
end
- debugPrint("^6Bridge^7: ^6Blip ^2created^7: '^6"..data.name.."^7' - '"..formatCoord(data.coords).."'")
+ blipTable[blip] = blip
+
+ if DoesBlipExist(blip) then
+ debugPrint("^6Bridge^7: ^6Blip ^2created^7: '^6"..data.name.."^7' - '"..formatCoord(data.coords).."'")
+ else
+ print("Error making blip")
+ end
return blip
end
@@ -90,30 +109,54 @@ end
-- local blip = makeEntityBlip(blipData)
-- ```
function makeEntityBlip(data)
- AddBlipForEntity(data.entity)
- local blip = GetBlipFromEntity(data.entity)
- SetBlipAsShortRange(blip, true)
- SetBlipSprite(blip, data.sprite or 106)
- SetBlipColour(blip, data.col or 5)
- SetBlipScale(blip, data.scale or 0.7)
- SetBlipDisplay(blip, data.disp or 6)
- if data.category then SetBlipCategory(blip, data.category) end
- BeginTextCommandSetBlipName('STRING')
- AddTextComponentString(tostring(data.name))
- EndTextCommandSetBlipName(blip)
- -- Handle preview image if certain resources are running
- if isStarted("fs_smallresources") or isStarted("blip-info") or isStarted("blipinfo") then
- if data.preview then
- local txname = string.gsub(tostring(data.name..'preview'), "[ ()~]", "")
- if data.preview:find("http") or data.preview:find("nui") then
- createDui(txname, data.preview, vec2(512, 256), scriptTxd)
- else
- CreateRuntimeTextureFromImage(scriptTxd, txname, data.preview)
+ local blip = nil
+ if gameName == "rdr3" then
+ blip = BlipAddForEntity(1664425300, data.entity)
+ SetBlipSprite(blip, data.sprite or `blip_ambient_coach`)
+ SetBlipScale(blip, data.scale or 0.2)
+ SetBlipName(blip, data.name)
+
+ else
+ AddBlipForEntity(data.entity)
+ blip = GetBlipFromEntity(data.entity)
+ blipTable[blip] = blip
+ SetBlipAsShortRange(blip, true)
+ SetBlipSprite(blip, data.sprite or 106)
+ SetBlipColour(blip, data.col or 5)
+ SetBlipScale(blip, data.scale or 0.7)
+ SetBlipDisplay(blip, data.disp or 6)
+ if data.category then SetBlipCategory(blip, data.category) end
+ BeginTextCommandSetBlipName('STRING')
+ AddTextComponentString(tostring(data.name))
+ EndTextCommandSetBlipName(blip)
+ -- Handle preview image if certain resources are running
+ if isStarted("fs_smallresources") or isStarted("blip-info") or isStarted("blipinfo") then
+ if data.preview then
+ local txname = string.gsub(tostring(data.name..'preview'), "[ ()~]", "")
+ if data.preview:find("http") or data.preview:find("nui") then
+ createDui(txname, data.preview, vec2(512, 256), scriptTxd)
+ else
+ CreateRuntimeTextureFromImage(scriptTxd, txname, data.preview)
+ end
+ exports["fs_smallresources"]:SetBlipInfoImage(blip, getScript()..'previewTxd', txname)
+ exports["fs_smallresources"]:SetBlipInfoTitle(blip, data.name, false)
end
- exports["fs_smallresources"]:SetBlipInfoImage(blip, getScript()..'previewTxd', txname)
- exports["fs_smallresources"]:SetBlipInfoTitle(blip, data.name, false)
end
end
- debugPrint("^6Bridge^7: ^6Blip ^2created for Entity^7: '^6"..data.name.."^7'")
+ blipTable[blip] = blip
+
+ if DoesBlipExist(blip) then
+ debugPrint("^6Bridge^7: ^6Blip ^2created for Entity^7: '^6"..data.name.."^7'")
+ else
+ print("Error making blip")
+ end
return blip
+end
+
+if gameName == "rdr3" then
+ onResourceStop(function()
+ for k in pairs(blipTable) do
+ RemoveBlip(k)
+ end
+ end, true)
end
\ No newline at end of file
diff --git a/shared/make/makePed.lua b/shared/make/makePed.lua
index 0457b89..5910d6e 100644
--- a/shared/make/makePed.lua
+++ b/shared/make/makePed.lua
@@ -20,16 +20,16 @@ local Peds = {}
-- ```
function makeDistPed(data, coords, freeze, collision, scenario, anim, synced)
local zoneCoords = type(data) == "table" and data.coords or coords
-
+ local randName = keyGen()..keyGen()
createCirclePoly({
- name = keyGen()..keyGen(),
+ name = randName,
coords = vec3(zoneCoords.x, zoneCoords.y, zoneCoords.z - 1.03),
radius = 50.0,
onEnter = function()
- Peds[#Peds + 1] = makePed(data, coords, freeze, collision, scenario, anim, synced)
+ Peds[randName] = makePed(data, coords, freeze, collision, scenario, anim, synced)
end,
onExit = function()
- DeletePed(Peds[#Peds])
+ DeletePed(Peds[randName])
end,
debug = debugMode,
})
@@ -114,7 +114,14 @@ function makePed(data, coords, freeze, collision, scenario, anim, synced)
else
model = data
loadModel(model)
- ped = CreatePed(0, model, coords.x, coords.y, coords.z - 1.03, coords.w, synced or false, false)
+ if gameName == "rdr3" then
+ ped = CreatePed(model, coords.x, coords.y, coords.z - 1.03, coords.w, synced or false, false)
+ SetEntityVisible(ped, 1) -- SetEntityVisible
+ SetEntityAlpha(ped, 255, false) -- SetEntityAlpha
+ SetRandomOutfitVariation(ped, true) -- Invisible without
+ else
+ ped = CreatePed(0, model, coords.x, coords.y, coords.z - 1.03, coords.w, synced or false, false)
+ end
end
SetEntityInvincible(ped, true)
@@ -127,10 +134,13 @@ function makePed(data, coords, freeze, collision, scenario, anim, synced)
loadAnimDict(anim[1])
TaskPlayAnim(ped, anim[1], anim[2], 0.5, 1.0, -1, 1, 0.2, 0, 0, 0)
end
-
- debugPrint("^6Bridge^7: ^1Ped ^2Created^7: '^6"..ped.."^7' | ^2Hash^7: ^7'^5"..(model).."^7' | ^2Coord^7: "..formatCoord(coords))
+ if DoesEntityExist(ped) then
+ debugPrint("^6Bridge^7: ^1Ped ^2Created^7: '^6"..ped.."^7' | ^2Hash^7: ^7'^5"..(model).."^7' | ^2Coord^7: "..formatCoord(coords))
+ else
+ print("error ped")
+ end
unloadModel(model)
- Peds[#Peds + 1] = ped
+ Peds[keyGen()..keyGen()] = ped
return ped
end
@@ -229,4 +239,8 @@ function GenerateRandomPedData(data)
end
--- Cleans up all created Peds when the resource stops.
-onResourceStop(function() for i = 1, #Peds do DeletePed(Peds[i]) end end, true)
\ No newline at end of file
+onResourceStop(function()
+ for k in pairs(Peds) do
+ DeletePed(Peds[k])
+ end
+end, true)
\ No newline at end of file
diff --git a/shared/make/makeProp.lua b/shared/make/makeProp.lua
index 6067d3a..e95c304 100644
--- a/shared/make/makeProp.lua
+++ b/shared/make/makeProp.lua
@@ -28,7 +28,7 @@ function makeProp(data, freeze, synced)
debugPrint("^6Bridge^7: ^1Prop ^2Created^7: '^6"..prop.."^7' | ^2Hash^7: ^7'^6"..data.prop.."^7' | ^2Coord^7: "..formatCoord(data.coords))
SetModelAsNoLongerNeeded(data.prop)
- Props[#Props + 1] = prop
+ Props[keyGen()..keyGen()] = prop
return prop
end
@@ -52,16 +52,16 @@ end
--- makeDistProp(propData, true, false)
--- ```
function makeDistProp(data, freeze, synced, range)
- local prop = nil
+ local name = keyGen()..keyGen()
createCirclePoly({
- name = keyGen()..keyGen(),
+ name = name,
coords = vec3(data.coords.x, data.coords.y, data.coords.z - 1.03),
radius = range or 50.0,
onEnter = function()
- prop = makeProp(data, freeze, synced)
+ Props[name] = makeProp(data, freeze, synced)
end,
onExit = function()
- destroyProp(prop)
+ destroyProp(Props[name])
end,
debug = debugMode,
})
@@ -87,4 +87,8 @@ function destroyProp(entity)
end
--- Cleans up all created props when the resource stops.
-onResourceStop(function() for i = 1, #Props do destroyProp(Props[i]) end end, true)
+onResourceStop(function()
+ for k in pairs(Props) do
+ destroyProp(Props[k])
+ end
+end, true)
diff --git a/shared/make/makeVeh.lua b/shared/make/makeVeh.lua
index e08c04f..6403c4d 100644
--- a/shared/make/makeVeh.lua
+++ b/shared/make/makeVeh.lua
@@ -17,12 +17,14 @@ function makeVeh(model, coords)
loadModel(model)
local veh = CreateVehicle(model, coords.x, coords.y, coords.z, coords.w, true, false)
SetVehicleHasBeenOwnedByPlayer(veh, true)
- SetNetworkIdCanMigrate(NetworkGetNetworkIdFromEntity(veh), true)
- Wait(100)
- SetVehicleNeedsToBeHotwired(veh, false)
- SetVehRadioStation(veh, 'OFF')
- SetVehicleFuelLevel(veh, 100.0)
- SetVehicleModKit(veh, 0)
+ if gameName ~= "rdr3" then
+ SetNetworkIdCanMigrate(NetworkGetNetworkIdFromEntity(veh), true)
+ Wait(100)
+ SetVehicleNeedsToBeHotwired(veh, false)
+ SetVehRadioStation(veh, 'OFF')
+ SetVehicleFuelLevel(veh, 100.0)
+ SetVehicleModKit(veh, 0)
+ end
SetVehicleOnGroundProperly(veh)
debugPrint("^6Bridge^7: ^1Veh ^2Created^7: '^6"..veh.."^7' | ^2Hash^7: ^7'^6"..model.."^7' | ^2Coord^7: "..formatCoord(coords))
diff --git a/shared/make/progressBars.lua b/shared/make/progressBars.lua
index 7e425b0..e9e6d4c 100644
--- a/shared/make/progressBars.lua
+++ b/shared/make/progressBars.lua
@@ -93,6 +93,22 @@ function progressBar(data)
end
})
+ elseif Config.System.ProgressBar == "red" then
+ -- Currently only uses jim-redui if you choose this option
+ if exports["jim-redui"]:progressBar({
+ label = data.label,
+ time = debugMode and 1000 or data.time,
+ dict = data.dict,
+ anim = data.anim,
+ flag = data.flag or 32,
+ task = data.task,
+ cancel = true,
+ }) then
+ result = true
+ else
+ result = false
+ end
+
elseif Config.System.ProgressBar == "gta" then
loadTextureDict("timerbars")
if inProgress then return false end
diff --git a/shared/notify.lua b/shared/notify.lua
index 962d61b..d1b9532 100644
--- a/shared/notify.lua
+++ b/shared/notify.lua
@@ -76,6 +76,15 @@ function triggerNotify(title, message, type, src)
else
TriggerClientEvent("jim-nui:client:notify'", src, type, message)
end
+
+ elseif Config.System.Notify == "red" then
+ if isStarted("jim-redui") then
+ if not src then
+ TriggerEvent("jim-redui:Notify", title, message, type)
+ else
+ TriggerClientEvent("jim-redui:Notify", src, title, message, type)
+ end
+ end
end
end
diff --git a/shared/playerfunctions.lua b/shared/playerfunctions.lua
index d846f2b..1afd28d 100644
--- a/shared/playerfunctions.lua
+++ b/shared/playerfunctions.lua
@@ -161,9 +161,14 @@ function chargePlayer(cost, moneyType, newsrc)
if moneyType == "cash" then
if isStarted(OXInv) then fundResource = OXInv
exports[OXInv]:RemoveItem(src, "money", cost)
- elseif isStarted(QBExport) or isStarted(QBXExport) then fundResource = QBExport
+ elseif isStarted(QBExport) or isStarted(QBXExport) then
+ fundResource = QBExport
Core.Functions.GetPlayer(src).Functions.RemoveMoney("cash", cost)
- elseif isStarted(ESXExport) then fundResource = ESXExport
+ elseif isStarted(RSGExport) then
+ fundResource = QBExport
+ Core.Functions.GetPlayer(src).Functions.RemoveMoney("cash", cost)
+ elseif isStarted(ESXExport) then
+ fundResource = ESXExport
ESX.GetPlayerFromId(src).removeMoney(cost, "")
end
elseif moneyType == "bank" then
@@ -532,6 +537,27 @@ function getPlayer(source)
citizenId = info.citizenid,
}
end
+ elseif isStarted(RSGExport) then
+ if Core.Functions.GetPlayer then
+ local info = Core.Functions.GetPlayer(src).PlayerData
+ Player = {
+ firstname = info.charinfo.firstname,
+ lastname = info.charinfo.lastname,
+ name = info.charinfo.firstname.." "..info.charinfo.lastname,
+ cash = info.money["cash"],
+ bank = info.money["bank"],
+ source = info.source,
+ job = info.job.name,
+ jobBoss = info.job.isboss,
+ jobInfo = info.job,
+ gang = info.gang.name,
+ gangBoss = info.gang.isboss,
+ gangInfo = info.gang,
+ onDuty = info.job.onduty,
+ account = info.charinfo.account,
+ citizenId = info.citizenid,
+ }
+ end
else
print("^4ERROR^7: ^2No Core detected for getPlayer() - Check starter.lua")
end
@@ -614,6 +640,26 @@ function getPlayer(source)
account = info.charinfo.account,
citizenId = info.citizenid,
}
+ elseif isStarted(RSGExport) then
+ local info = nil
+ Core.Functions.GetPlayerData(function(PlayerData) info = PlayerData end)
+ Player = {
+ firstname = info.charinfo.firstname,
+ lastname = info.charinfo.lastname,
+ name = info.charinfo.firstname.." "..info.charinfo.lastname,
+ cash = info.money["cash"],
+ bank = info.money["bank"],
+ source = info.source,
+ job = info.job.name,
+ jobBoss = info.job.isboss,
+ jobInfo = info.job,
+ gang = info.gang.name,
+ gangBoss = info.gang.isboss,
+ gangInfo = info.gang,
+ onDuty = info.job.onduty,
+ account = info.charinfo.account,
+ citizenId = info.citizenid,
+ }
else
print("^4ERROR^7: ^2No Core detected for hasJob ^7- ^2Check ^3starter^1.^2lua^7")
end
diff --git a/shared/scaleforms/scaleform_basic.lua b/shared/scaleforms/scaleform_basic.lua
index 15100c2..253f1d9 100644
--- a/shared/scaleforms/scaleform_basic.lua
+++ b/shared/scaleforms/scaleform_basic.lua
@@ -78,6 +78,47 @@ function makeInstructionalButtons(info)
DrawScaleformMovieFullscreen(build, 255, 255, 255, 255, 0)
end
+-- EXPERIMENTAL --
+-- RedM Button Prompts --
+-- Creates the promot, then shows it, this needs to be run in a loop
+local promptGroups = {}
+
+function makeRedInstructionalButtons(info, title)
+ if not promptGroups[title] then -- Create group if not exists
+ promptGroups[title] = {
+ title = CreateVarString(10, 'LITERAL_STRING', title),
+ id = GetRandomIntInRange(0, 0xffffff),
+ prompts = {},
+ }
+ for i = 1, #info do
+ promptGroups[title].prompts[i] = {
+ keys = info[i].keys,
+ text = info[i].text,
+ }
+ local keyTitle = CreateVarString(10, 'LITERAL_STRING', info[i].text)
+ -- Create one prompt per entry
+ local promptSet = UiPromptRegisterBegin()
+ -- Register all keys for this prompt
+ for k = 1, #info[i].keys do
+ PromptSetControlAction(promptSet, info[i].keys[k])
+ end
+ PromptSetText(promptSet, keyTitle)
+ PromptSetEnabled(promptSet, true)
+ PromptSetVisible(promptSet, true)
+ PromptSetGroup(promptSet, promptGroups[title].id)
+ PromptRegisterEnd(promptSet)
+ end
+ end
+ PromptSetActiveGroupThisFrame(promptGroups[title].id, promptGroups[title].title)
+end
+
+onResourceStop(function()
+ for k, v in pairs(promptGroups) do
+ print("^5GTAUI^7: ^2Removing Prompt Group^7: ^3" .. k .. "^7")
+ PromptDelete(promptGroups[k].id, 1)
+ end
+end, true)
+
-------------------------------------------------------------
-- Debug Text Display Functionality
-------------------------------------------------------------
diff --git a/starter.lua b/starter.lua
index 12f7552..076043a 100644
--- a/starter.lua
+++ b/starter.lua
@@ -1,3 +1,5 @@
+gameName = not IsDuplicityVersion() and GetCurrentGameName()
+
Exports = {
QBExport = "qb-core",
QBXExport = "qbx_core",
@@ -17,7 +19,11 @@ Exports = {
QBMenuExport = "qb-menu",
QBTargetExport = "qb-target",
- OXTargetExport = "ox_target"
+ OXTargetExport = "ox_target",
+
+ -- REDM
+ RSGExport = "rsg-core",
+ RSGInv = "rsg-inventory"
}
-- Required variables
@@ -95,4 +101,4 @@ for _, v in pairs({ -- This is a specific load order
if debugMode then
print("^5Success^7: ^2loaded file^7: ^3"..(v):gsub("/", "^7/^3"):gsub("%.lua", "^7.lua").."^7")
end
-end
\ No newline at end of file
+end