version '0.0.7'
This commit is contained in:
1 parent
89a9a371bd
commit
47977ce701
105 files changed
+5036
-1
No files matched your search
@@ -0,0 +1,37 @@
|
||||
# Attributions
|
||||
|
||||
This project incorporates code from several libraries and resources licensed under GPLv3, as it inherits their licensing, and the creators are credited below:
|
||||
|
||||
## r_bridge
|
||||
- **Purpose**: Code for codem-inventory bridging, targeting, and framework item registration.
|
||||
- **Modifications to the code**: Code was not used for inventory, but was refrenced while doing my bridging for inventories and the idea of native helper functions came from that entirely. Targeting code still remains as is and is used as well as the method of registering usables.
|
||||
- **Credit**: **r_bridge** inventory bridging code for codem-inventory is used in this. Targeting code still remains as is and is used.
|
||||
[\[r_bridge\]](https://github.com/rumaier/r_bridge)
|
||||
|
||||
## clean_lib
|
||||
- **Purpose**: Vehicle fuel, vehicle key bridging and the loading and saving methods of json files.
|
||||
- **Modifications to the code**: None.
|
||||
- **Credit**: **clean_lib** code is used to manage vehicle fuel and keys, bridging these systems seamlessly.
|
||||
[\[clean_lib\]](https://github.com/Clean-Server-Pack/clean_lib)
|
||||
|
||||
## ox_lib
|
||||
- **Purpose**: Utility functions for printing raycasting and point registering.
|
||||
- **Credit**: **ox_lib** provides various utility functions for printing and interacting with other objects in this resource. While theres no code pulled directly from the resource, it is still the backbone to it so a thanks is nessesary.
|
||||
[\[ox_lib\]](https://github.com/overextended/ox_lib)
|
||||
|
||||
## renewed_lib
|
||||
- **Purpose**: Object placer functionality.
|
||||
- **Modifications to the code**: Variable naming, added missing params for the natives used, updated a depreciated export from oxlib for the raycast camera, altered the showtext ui to now work with multiple showtextui systems, moved the text for placement into locales, the requestModel exports from ox_lib were replaced with the function my bridge uses to request models from ox_lib.
|
||||
- **Credit**: **renewed_lib** code is used for its object placement snippet.
|
||||
[\[renewed_lib\]](https://github.com/Renewed-Scripts/Renewed-Lib)
|
||||
|
||||
|
||||
## duff
|
||||
- **Purpose**: Version Checker.
|
||||
- **Modifications to the code**: Variables removed, now will pull repo information from passed string.
|
||||
- **Credit**: **duff** code was refrenced and some used for version checker formatting and print style.
|
||||
[\[duff\]](https://github.com/DonHulieo/duff/blob/d89ed3b0051194babf5711114a0c437d4e41f433/server/init.lua#L10C1-L28C4)
|
||||
|
||||
|
||||
|
||||
Thank you to the creators and maintainers of these libraries/bridges/internet points for their hard work and contributions to the FiveM community.
|
||||
@@ -1,4 +1,4 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# community_bridge
|
||||
|
||||
## By The Order of the Sacred Bridge
|
||||
|
||||
The **Order of the Sacred Bridge**, a fellowship born of noble intention and quiet passion, has crafted a bridge to simplify the journey of all who dare venture into the world of development. This bridge, much like a well-worn path through the woods, is modular in design, offering an array of systems and tools that serve the wanderer and the scholar alike:
|
||||
|
||||
- Clothing Systems
|
||||
- Dispatch Systems
|
||||
- Doorlock Systems
|
||||
- Frameworks
|
||||
- Fuel Systems
|
||||
- Input Systems
|
||||
- Inventory Systems
|
||||
- Locale Systems
|
||||
- Vehicle Key Systems
|
||||
- Management Systems
|
||||
- Math Library
|
||||
- Menu Systems
|
||||
- Notify Systems
|
||||
- Phone Systems
|
||||
- Progress Bars
|
||||
- Target Systems
|
||||
- Weather Systems
|
||||
- A vast trove of helpful functions
|
||||
- And many more...
|
||||
|
||||
As with any grand creation, this bridge also includes utility functions, some of which may be of great use, while others may seem like hidden treasures, waiting to be discovered by those with keen eyes.
|
||||
|
||||
This bridge proudly incorporates snippets from the wide and varied community, some of which are crafted under the honorable **GPLv3** license. All contributions are duly credited in the **Attributions** file, ensuring we respect the deeds of those who came before us and maintain our adherence to the principles of the **GPLv3**.
|
||||
|
||||
A **labor of love** it has been, this bridge, forged with a deep **passion for scripts** and a desire to unite the scattered folk of the development world. In the spirit of cooperation, it seeks to bring together those with differing preferences and ideas, creating something that is **entry-level**, **versatile**, and filled with **compatibility wrappers** for all the major resources. It also lays the groundwork for future resources that wish to cross its sturdy spans.
|
||||
|
||||
This bridge, a curious blend of its own **library** and a tool of great utility, is full of **helper functions** that will guide you on your journey, making the most complex tasks simpler and more straightforward, like a trusty map in a foreign land.
|
||||
|
||||
Crafted with care, the bridge is as **user-friendly** as a friendly hobbit’s home, catering to both beginners and seasoned travelers. It is a bridge of great adaptability, easily modified to suit the needs of those who walk across it.
|
||||
|
||||
This bridge will **not fall victim to the ego of any single individual**, for its foundation lies in the belief that any contribution of value to the community, if it adheres to the simple philosophy of **simplicity**, and ensures an easy path for all, is **welcome**.
|
||||
|
||||
The aim, much like the hobbits' journey to Morridor, is to create a **free, open, community-driven bridge**, one that serves the needs of the many and welcomes all who wish to add their mark to the map.
|
||||
@@ -0,0 +1,154 @@
|
||||
|
||||
local Tables = Require('use/tables.lua')
|
||||
local Ids = Require("use/ids.lua")
|
||||
|
||||
local AllInstances = {}
|
||||
|
||||
|
||||
---@class Class
|
||||
Class = {}
|
||||
Class.ClassName = "Class"
|
||||
Class.__call = function(this, ...)
|
||||
return this:new(...)
|
||||
end
|
||||
Builders = {}
|
||||
|
||||
function Class.SetInstance(instance)
|
||||
AllInstances[instance.id] = instance
|
||||
end
|
||||
|
||||
function Class.GetInstance(id)
|
||||
return AllInstances[id]
|
||||
end
|
||||
|
||||
--- Default (empty) constructor
|
||||
--- @param self Class
|
||||
--- @vararg any
|
||||
function Class:init(...) end
|
||||
|
||||
--- Creates a subclass of the current class.
|
||||
--- This function copies the properties and methods of the current class to a new object.
|
||||
--- It also sets up metatables to allow for object-oriented behavior, such as method calls and property access.
|
||||
--- @param obj object | nil: The table to extend. If nil, a new table will be created.
|
||||
--- @return obj object: The extended object with properties and methods from the given class obj.
|
||||
function Class:extend(obj)
|
||||
local className = obj.ClassName or "Class"
|
||||
|
||||
|
||||
local old = Tables.DeepClone(self, {}, {components = true})
|
||||
local new = Tables.DeepClone(obj, old, {ClassName = true})
|
||||
|
||||
new.components = self.components or {}
|
||||
new.components[className] = obj
|
||||
|
||||
if not new.id then new.id = Ids.CreateUniqueId(new.components) end
|
||||
|
||||
-- create new objects directly, like o = Object()
|
||||
self = setmetatable(new, Class)
|
||||
|
||||
if not Class.GetInstance(new.id) then Class.SetInstance(self) end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets a property on the object. NOTE: This is mostly for internal purposes.
|
||||
--- @param prop string|table: The property name or a table of properties to set.
|
||||
--- @param value any: The value to set the property to.
|
||||
function Class:set(prop, value)
|
||||
if not value and type(prop) == "table" then
|
||||
for k, v in pairs(prop) do
|
||||
rawset(self._, k, v)
|
||||
end
|
||||
else
|
||||
rawset(self._, prop, value)
|
||||
end
|
||||
end
|
||||
|
||||
--- This function is used to create a new instance of the class.
|
||||
--- It calls the init function if it exists.
|
||||
--- @vararg any: The arguments to pass to the init
|
||||
--- @return object: The new instance of the class.
|
||||
function Class:new(...)
|
||||
local obj = self:extend({})
|
||||
if obj.init then obj:init(...) end
|
||||
return obj
|
||||
end
|
||||
|
||||
--- This function is used to create a new instance of the class.
|
||||
--- It calls the struct function if it exists.
|
||||
--- @vararg object(s): List of objects to extend the class with.
|
||||
--- @return object: The new instance of the class with the data and functions from the objects passed.
|
||||
function class(className, ...)
|
||||
local newObj = Class:extend({})
|
||||
local components = table.pack(...)
|
||||
newObj.ClassName = className
|
||||
if components then
|
||||
for k, v in pairs(components) do
|
||||
local clName = v.ClassName
|
||||
if not Builders[clName] then -- builders are used to reconstruct an object usually when pulled from server to client or vice versa
|
||||
Builders[clName] = Tables.DeepClone(newObj)
|
||||
end
|
||||
end
|
||||
end
|
||||
if components.n > 0 then
|
||||
for k, v in pairs(components) do
|
||||
if k ~= "n" then
|
||||
local newNewObject = nil
|
||||
if v.Struct and type(v.Struct) == "function" then
|
||||
newNewObject = v:Struct()
|
||||
end
|
||||
newObj = newObj:extend(newNewObject or v)
|
||||
end
|
||||
end
|
||||
else
|
||||
return newObj
|
||||
end
|
||||
|
||||
return newObj
|
||||
end
|
||||
|
||||
function reconstruct(obj)
|
||||
local newTable = {}
|
||||
local tbl = obj.components or {}
|
||||
for k, v in pairs(tbl) do
|
||||
local builder = Builders[k]
|
||||
if builder then
|
||||
newTable[k] = builder
|
||||
end
|
||||
end
|
||||
return class(table.unpack(newTable))
|
||||
end
|
||||
|
||||
--- Overwrites the type(self) value to return "Class".
|
||||
--- @return string: The string "Class".
|
||||
function Class:__type()
|
||||
return self.ClassName or "Class"
|
||||
end
|
||||
|
||||
--- Overwrites the call operator to call the new function. Ex: Class()
|
||||
--- @vararg any: The arguments to pass to the new function.
|
||||
--- @return object: The new instance of the class.
|
||||
function Class:__call(...)
|
||||
return self:new(...)
|
||||
end
|
||||
|
||||
|
||||
--- Checks to see if the class is an instance of the given class.
|
||||
--- @param cls Class: The class to check against.
|
||||
--- @return boolean: True if the class is an instance of the given class, false otherwise.
|
||||
function Class:IsA(cls)
|
||||
local p = promise.new()
|
||||
CreateThread(function()
|
||||
local m = getmetatable(self)
|
||||
while m do
|
||||
if m == cls then
|
||||
return p:resolve(true)
|
||||
end
|
||||
m = getmetatable(m)
|
||||
Wait(0)
|
||||
end
|
||||
return p:resolve(false)
|
||||
end)
|
||||
return Citizen.Await(p)
|
||||
end
|
||||
|
||||
return {Class, class}
|
||||
@@ -0,0 +1,38 @@
|
||||
local classModule = Require("components/class.lua")
|
||||
local _, class = table.unpack(classModule)
|
||||
|
||||
-- Registry to store singletons for classes
|
||||
local SingletonRegistry = {}
|
||||
|
||||
--- @class Singleton
|
||||
local Singleton = class()
|
||||
Singleton.ClassName = "Singleton"
|
||||
--- Ensures the class instance is a singleton.
|
||||
--- If an instance already exists, it returns the existing one.
|
||||
--- If not, it initializes and registers a new singleton.
|
||||
function Singleton:Struct()
|
||||
local className = self.ClassName or "UnnamedClass"
|
||||
-- Check if the singleton already exists
|
||||
if SingletonRegistry[className] then
|
||||
self = SingletonRegistry[className]
|
||||
return self
|
||||
end
|
||||
-- Register this instance as the singleton for its class
|
||||
SingletonRegistry[className] = self
|
||||
return self
|
||||
end
|
||||
--- Clears the singleton instance for this class (if needed).
|
||||
function Singleton:ClearSingleton()
|
||||
local destroy = self.Destroy
|
||||
if destroy and type(destroy) == "function" then self:Destroy() end
|
||||
local className = self.ClassName or "UnnamedClass"
|
||||
SingletonRegistry[className] = nil
|
||||
end
|
||||
--- Returns the existing singleton for a class.
|
||||
--- @param className string: The name of the class to check.
|
||||
--- @return any: The singleton instance, or nil if none exists.
|
||||
function Singleton.Get(className)
|
||||
return SingletonRegistry[className]
|
||||
end
|
||||
|
||||
return Singleton
|
||||
@@ -0,0 +1,103 @@
|
||||
local classModule = Require("components/class.lua")
|
||||
local _, class = table.unpack(classModule)
|
||||
local ids = Require("use/ids.lua")
|
||||
|
||||
local SyncObjects = {}
|
||||
|
||||
function GetSyncObject(syndId)
|
||||
return SyncObjects[syndId]
|
||||
end
|
||||
|
||||
function GetSyncObjects()
|
||||
return SyncObjects
|
||||
end
|
||||
|
||||
function SetSyncObject(syncId, sync)
|
||||
SyncObjects[syncId] = sync
|
||||
end
|
||||
|
||||
--- @class Sync
|
||||
local Sync = class("Sync")
|
||||
--- Initializes the Sync object.
|
||||
function Sync:Struct()
|
||||
self.syncId = ids.CreateUniqueId(SyncObjects)
|
||||
self.sync = {}
|
||||
self.updateWaitTime = 500
|
||||
SyncObjects[self.syncId] = self
|
||||
return self
|
||||
end
|
||||
|
||||
--- Retrieves the value associated with the given key in the sync table.
|
||||
--- @param key any: The key to retrieve the value for.
|
||||
--- @return any: The value associated with the key.
|
||||
function Sync:GetSyncKey(key)
|
||||
return self.sync[key]
|
||||
end
|
||||
|
||||
--- Called when a sync key is initialized.
|
||||
--- @param key any: The key being initialized.
|
||||
--- @param value any: The value being set.
|
||||
function Sync:OnSyncKeyInit(key, value) end
|
||||
|
||||
--- Called when a sync key is updated.
|
||||
--- @param key any: The key being updated.
|
||||
--- @param oldValue any: The old value of the key.
|
||||
--- @param newValue any: The new value of the key.
|
||||
function Sync:OnSyncKeyUpdate(key, oldValue, newValue) end
|
||||
|
||||
--- Called when a sync key is removed.
|
||||
--- @param key any: The key being removed.
|
||||
function Sync:OnSyncKeyRemove(key) end
|
||||
|
||||
-- Server
|
||||
if not IsDuplicityVersion() then goto client end
|
||||
|
||||
--- Sets a sync key and triggers a client event to update the sync table.
|
||||
--- @param key any: The key to set.
|
||||
--- @param value any: The value to set for the key.
|
||||
function Sync:SetSynckey(key, value)
|
||||
self.sync[key] = value
|
||||
CreateThread(function()
|
||||
SetTimeout(self.updateWaitTime, function()
|
||||
TriggerClientEvent("Sync:Setup", -1, self.syncId, self.sync)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Client
|
||||
if IsDuplicityVersion() then return Sync end
|
||||
::client::
|
||||
|
||||
--- Compares the current sync table with a new table and updates accordingly.
|
||||
--- @param newTable table: The new sync table to compare with.
|
||||
function Sync:_CompareAndUpdate(newTable)
|
||||
local oldTable = self.sync
|
||||
for key, oldValue in pairs(oldTable) do
|
||||
local newValue = newTable[key]
|
||||
if newValue == nil then
|
||||
self:OnSyncKeyRemove(key)
|
||||
elseif oldValue ~= newValue then
|
||||
self:OnSyncKeyUpdate(key, oldValue, newValue)
|
||||
end
|
||||
end
|
||||
|
||||
for key, newValue in pairs(newTable) do
|
||||
if oldTable[key] == nil then
|
||||
self:OnSyncKeyInit(key, newValue)
|
||||
end
|
||||
end
|
||||
self.sync = newTable
|
||||
end
|
||||
|
||||
RegisterNetEvent("Sync:Setup", function(syncId, sync)
|
||||
local syncObj = GetSyncObject(syncId)
|
||||
if not syncObj then
|
||||
syncObj = reconstruct(Sync)
|
||||
assert(syncObj, "Failed to sync: ", syncId)
|
||||
syncObj.syncId = syncId
|
||||
SetSyncObject(syncId, syncObj)
|
||||
end
|
||||
syncObj:_CompareAndUpdate(sync)
|
||||
end)
|
||||
|
||||
return table.pack({Sync})
|
||||
@@ -0,0 +1,59 @@
|
||||
fx_version 'cerulean'
|
||||
game 'gta5'
|
||||
lua54 'yes'
|
||||
author 'The Order of the Sacred Framework'
|
||||
description 'A bridge made for the community to use as a base for their own projects. This bridge will allow a single format to work with nearly all commonly used systems while still offering expandability.'
|
||||
version '0.0.7'
|
||||
|
||||
shared_scripts {
|
||||
'settings/sharedConfig.lua',
|
||||
'use/*.lua',
|
||||
'modules/utilities/shared/*.lua',
|
||||
'modules/locales/*.lua',
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
'@oxmysql/lib/MySQL.lua',
|
||||
'settings/serverConfig.lua',
|
||||
'modules/locales/shared.lua',
|
||||
'modules/utilities/server/*.lua',
|
||||
'modules/framework/**/server.lua',
|
||||
'modules/inventory/**/server.lua',
|
||||
'modules/stashes/server.lua',
|
||||
'modules/phones/**/server.lua',
|
||||
'modules/managment/**/server.lua',
|
||||
'modules/notify/server.lua',
|
||||
'init.lua',
|
||||
}
|
||||
|
||||
client_scripts {
|
||||
'settings/clientConfig.lua',
|
||||
'modules/locales/shared.lua',
|
||||
'modules/input/client.lua',
|
||||
'modules/utilities/client/*.lua',
|
||||
'modules/framework/**/client.lua',
|
||||
'modules/inventory/**/client.lua',
|
||||
'modules/keys/**/client.lua',
|
||||
'modules/fuel/**/client.lua',
|
||||
'modules/target/**/client.lua',
|
||||
'modules/menu/client.lua',
|
||||
'modules/notify/client.lua',
|
||||
'modules/dispatch/**/client.lua',
|
||||
'modules/progressbars/**/client.lua',
|
||||
'modules/clothing/**/client.lua',
|
||||
'modules/weather/**/client.lua',
|
||||
'modules/points/*.lua',
|
||||
'modules/math/*.lua',
|
||||
'init.lua',
|
||||
}
|
||||
|
||||
files {
|
||||
'locales/*.json',
|
||||
'components/*.lua',
|
||||
}
|
||||
|
||||
dependencies {
|
||||
'/server:6116',
|
||||
'/onesync',
|
||||
'ox_lib',
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
Bridge = {
|
||||
modules = {},
|
||||
}
|
||||
PlayerLoaded = false
|
||||
PlayerIdentifier = nil
|
||||
PlayerJobName = nil
|
||||
PlayerJobLabel = nil
|
||||
PlayerJobGradeName = nil
|
||||
PlayerJobGradeLevel = nil
|
||||
|
||||
Bridge.Inventory = Inventory
|
||||
Bridge.Menu = Menu
|
||||
Bridge.Language = Language
|
||||
Bridge.Debugger = Debugger
|
||||
Bridge.Framework = Framework
|
||||
Bridge.Doorlock = Doorlock
|
||||
Bridge.Phone = Phone
|
||||
Bridge.Notify = Notify
|
||||
Bridge.Vehicle = Vehicle
|
||||
Bridge.Dispatch = Dispatch
|
||||
Bridge.Weather = Weather
|
||||
Bridge.Target = Target
|
||||
Bridge.Table = Table
|
||||
Bridge.Math = Math
|
||||
Bridge.Clothing = Clothing
|
||||
Bridge.Progressbar = Progressbar
|
||||
Bridge.Helper = Helper
|
||||
|
||||
-- Fill the bridge tables with player data.
|
||||
function FillBridgeTables()
|
||||
PlayerLoaded = true
|
||||
PlayerIdentifier = Framework.GetPlayerIdentifier()
|
||||
PlayerJobName, PlayerJobLabel, PlayerJobGradeName, PlayerJobGradeLevel = Framework.GetPlayerJob()
|
||||
end
|
||||
|
||||
-- Clean the bridge tables.
|
||||
function ClearClientSideVariables()
|
||||
PlayerLoaded = false
|
||||
PlayerIdentifier = nil
|
||||
PlayerJobName = nil
|
||||
PlayerJobLabel = nil
|
||||
PlayerJobGradeName = nil
|
||||
PlayerJobGradeLevel = nil
|
||||
StoredOldClothing = {}
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
for k, v in pairs(Bridge) do
|
||||
if type(v) == 'table' then
|
||||
exports(k, function()
|
||||
return v
|
||||
end)
|
||||
v.__index = function(key, value)
|
||||
IndexingFallback(v, key, value)
|
||||
end
|
||||
else
|
||||
exports(k, v)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function IndexingFallback(module, k, v)
|
||||
if not module[k] then
|
||||
local func = Framework[k] and type(Framework[k]) == 'function' and Framework[k] or nil
|
||||
return function(...)
|
||||
return func(...)
|
||||
end
|
||||
end
|
||||
return module[k]
|
||||
end
|
||||
|
||||
OverRide = function(module, key, value)
|
||||
module[key] = value
|
||||
end
|
||||
|
||||
RegisterCompatibility = function(key, module)
|
||||
module = module or {}
|
||||
module.__index = IndexingFallback
|
||||
module.OverRide = function(key, value)
|
||||
OverRide(module, key, value)
|
||||
end
|
||||
Bridge[key] = module
|
||||
end
|
||||
exports('RegisterCompatibility', RegisterCompatibility)
|
||||
|
||||
exports('Bridge', function()
|
||||
return Bridge
|
||||
end)
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"locale-unit-test": "This is a test string",
|
||||
"place_object": "-- Place Object -- \n",
|
||||
"place_object_place": "[E] Place \n",
|
||||
"place_object_cancel": "[X] Cancel \n",
|
||||
"place_object_scroll_up": "[SCROLL UP] Change Heading \n",
|
||||
"place_object_scroll_down": "[SCROLL DOWN] Change Heading",
|
||||
"enter_text": "Enter Text",
|
||||
"no_prop_defined": "You didnt define any object to place"
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
if GetResourceState('esx_skin') ~= 'started' then return end
|
||||
|
||||
Clothing = {}
|
||||
|
||||
StoredOldClothing = {}
|
||||
|
||||
RegisterNetEvent('community_bridge:client:updateStoredClothing', function(skindata)
|
||||
StoredOldClothing = skindata
|
||||
end)
|
||||
|
||||
local clothingData = {
|
||||
male = {
|
||||
components = {
|
||||
face = {component_id = 0, texture = 0, drawable = 2},
|
||||
mask = {component_id = 1, texture = 0, drawable = 2},
|
||||
hair = {component_id = 2, texture = 0, drawable = 2},
|
||||
arms = {component_id = 3, texture = 0, drawable = 2},
|
||||
pants = {component_id = 4, texture = 0, drawable = 22},
|
||||
bag = {component_id = 5, texture = 1, drawable = 33},
|
||||
shoes = {component_id = 6, texture = 1, drawable = 33},
|
||||
accessory = {component_id = 7, texture = 1, drawable = 33},
|
||||
shirt = {component_id = 8, texture = 1, drawable = 11},
|
||||
bodyarmor = {component_id = 9, texture = 1, drawable = 33},
|
||||
decals = {component_id = 10, texture = 1, drawable = 33},
|
||||
jacket = {component_id = 11, texture = 2, drawable = 4},
|
||||
},
|
||||
props = {
|
||||
hats = {prop_id = 0, texture = 2, drawable = 4},
|
||||
glasses = {prop_id = 1, texture = 2, drawable = 4},
|
||||
ears = {prop_id = 2, texture = 2, drawable = 4},
|
||||
watches = {prop_id = 6, texture = 2, drawable = 4},
|
||||
bracelets = {prop_id = 7, texture = 2, drawable = 4},
|
||||
}
|
||||
},
|
||||
female = {
|
||||
components = {
|
||||
face = {component_id = 0, texture = 0, drawable = 2},
|
||||
mask = {component_id = 1, texture = 0, drawable = 2},
|
||||
hair = {component_id = 2, texture = 0, drawable = 2},
|
||||
arms = {component_id = 3, texture = 0, drawable = 2},
|
||||
pants = {component_id = 4, texture = 0, drawable = 22},
|
||||
bag = {component_id = 5, texture = 1, drawable = 33},
|
||||
shoes = {component_id = 6, texture = 1, drawable = 33},
|
||||
accessory = {component_id = 7, texture = 1, drawable = 33},
|
||||
shirt = {component_id = 8, texture = 1, drawable = 11},
|
||||
bodyarmor = {component_id = 9, texture = 1, drawable = 33},
|
||||
decals = {component_id = 10, texture = 1, drawable = 33},
|
||||
jacket = {component_id = 11, texture = 2, drawable = 4},
|
||||
},
|
||||
props = {
|
||||
hats = {prop_id = 0, texture = 2, drawable = 4},
|
||||
glasses = {prop_id = 1, texture = 2, drawable = 4},
|
||||
ears = {prop_id = 2, texture = 2, drawable = 4},
|
||||
watches = {prop_id = 6, texture = 2, drawable = 4},
|
||||
bracelets = {prop_id = 7, texture = 2, drawable = 4},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
local function convertDataToFormat(characterData)
|
||||
local gender = characterData.sex
|
||||
|
||||
local repackedClothingData = {
|
||||
[gender] = {
|
||||
components = {},
|
||||
props = {}
|
||||
}
|
||||
}
|
||||
|
||||
local componentMap = {
|
||||
tshirt_1 = 8, -- shirt
|
||||
torso_1 = 11, -- jacket
|
||||
decals_1 = 10, -- decals
|
||||
arms = 3, -- arms
|
||||
pants_1 = 4, -- pants
|
||||
shoes_1 = 6, -- shoes
|
||||
mask_1 = 1, -- mask
|
||||
bproof_1 = 9, -- body armor
|
||||
chain_1 = 7, -- accessory (could be a necklace)
|
||||
bags_1 = 5, -- bag
|
||||
}
|
||||
|
||||
for componentName, componentId in pairs(componentMap) do
|
||||
if characterData[componentName] then
|
||||
repackedClothingData[gender].components[componentName] = {
|
||||
component_id = componentId,
|
||||
texture = characterData[componentName.."_2"],
|
||||
drawable = characterData[componentName.."_1"],
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local propMap = {
|
||||
{"helmet_1", 0}, -- helmet
|
||||
{"glasses_1", 1}, -- glasses
|
||||
{"ears_1", 2}, -- ears
|
||||
{"watches_1", 6}, -- watches
|
||||
{"bracelets_1", 7} -- bracelets
|
||||
}
|
||||
|
||||
for _, prop in ipairs(propMap) do
|
||||
local propName = prop[1]
|
||||
local propId = prop[2]
|
||||
|
||||
if characterData[propName] then
|
||||
repackedClothingData[gender].props[propName] = {
|
||||
prop_id = propId,
|
||||
texture = characterData[propName.."_2"],
|
||||
drawable = characterData[propName.."_1"],
|
||||
}
|
||||
end
|
||||
end
|
||||
return repackedClothingData
|
||||
end
|
||||
|
||||
Clothing.SetAppearance = function(clothingData)
|
||||
if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
|
||||
clothingData = clothingData.male
|
||||
clothingData.sex = 0
|
||||
else
|
||||
clothingData = clothingData.female
|
||||
clothingData.sex = 1
|
||||
end
|
||||
local repackedClothingData = convertDataToFormat(clothingData)
|
||||
StoredOldClothing = Clothing.GetAppearance
|
||||
TriggerEvent('skinchanger:loadSkin', repackedClothingData)
|
||||
return true
|
||||
end
|
||||
|
||||
Clothing.GetAppearance = function()
|
||||
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin)
|
||||
StoredOldClothing = skin
|
||||
end)
|
||||
return true
|
||||
end
|
||||
|
||||
Clothing.RestoreAppearance = function()
|
||||
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin)
|
||||
TriggerEvent('skinchanger:loadSkin', skin)
|
||||
end)
|
||||
return true
|
||||
end
|
||||
|
||||
Clothing.ReloadSkin = function()
|
||||
local tableCheck = Table.TableContains(StoredOldClothing, "sex")
|
||||
if not tableCheck then return Clothing.RestoreAppearance() end
|
||||
return TriggerEvent('skinchanger:loadSkin', StoredOldClothing)
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
if GetResourceState('esx_skin') ~= 'started' then return end
|
||||
|
||||
RegisterNetEvent("esx_skin:save", function(skin)
|
||||
local src = source
|
||||
TriggerClientEvent('community_bridge:client:updateStoredClothing', src, skin)
|
||||
end)
|
||||
@@ -0,0 +1,28 @@
|
||||
if GetResourceState('fivem-appearance') ~= 'started' then return end
|
||||
|
||||
Clothing = {}
|
||||
|
||||
StoredOldClothing = {}
|
||||
|
||||
Clothing.SetAppearance = function(clothingData)
|
||||
if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
|
||||
clothingData = clothingData.male
|
||||
else
|
||||
clothingData = clothingData.female
|
||||
end
|
||||
StoredOldClothing = exports['fivem-appearance']:getPedAppearance(cache.ped)
|
||||
exports['fivem-appearance']:setPedAppearance(cache.ped, clothingData)
|
||||
return true
|
||||
end
|
||||
|
||||
Clothing.GetAppearance = function()
|
||||
return exports['fivem-appearance']:getPedAppearance(cache.ped)
|
||||
end
|
||||
|
||||
Clothing.RestoreAppearance = function()
|
||||
return exports['fivem-appearance']:setPedAppearance(cache.ped, StoredOldClothing)
|
||||
end
|
||||
|
||||
Clothing.ReloadSkin = function()
|
||||
TriggerEvent("fivem-appearance:client:reloadSkin", true)
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
if GetResourceState('illenium-appearance') ~= 'started' then return end
|
||||
|
||||
Clothing = {}
|
||||
|
||||
StoredOldClothing = {}
|
||||
|
||||
Clothing.SetAppearance = function(clothingData)
|
||||
local clothing = {}
|
||||
if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
|
||||
clothingData = clothingData.male
|
||||
else
|
||||
clothingData = clothingData.female
|
||||
end
|
||||
clothing.components = exports['illenium-appearance']:getPedComponents(cache.ped)
|
||||
clothing.props = exports['illenium-appearance']:getPedProps(cache.ped)
|
||||
|
||||
print(json.encode(clothingData, {indent = true}))
|
||||
StoredOldClothing = clothing
|
||||
exports['illenium-appearance']:setPedComponents(cache.ped, clothingData.components)
|
||||
exports['illenium-appearance']:setPedProp(cache.ped, clothingData.props)
|
||||
return true
|
||||
end
|
||||
|
||||
Clothing.GetAppearance = function()
|
||||
local clothing = {}
|
||||
if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
|
||||
clothing = clothing.male
|
||||
else
|
||||
clothing = clothing.female
|
||||
end
|
||||
clothing.components = exports['illenium-appearance']:getPedComponents(cache.ped)
|
||||
clothing.props = exports['illenium-appearance']:getPedProps(cache.ped)
|
||||
|
||||
return clothing
|
||||
end
|
||||
|
||||
Clothing.RestoreAppearance = function()
|
||||
exports['illenium-appearance']:setPedComponents(cache.ped, StoredOldClothing.components)
|
||||
exports['illenium-appearance']:setPedProp(cache.ped, StoredOldClothing.props)
|
||||
return true
|
||||
end
|
||||
|
||||
Clothing.ReloadSkin = function()
|
||||
TriggerEvent("illenium-appearance:client:reloadSkin", true)
|
||||
end
|
||||
@@ -0,0 +1,80 @@
|
||||
if GetResourceState('qb-clothing') ~= 'started' then return end
|
||||
|
||||
Clothing = {}
|
||||
|
||||
StoredOldClothing = {}
|
||||
|
||||
RegisterNetEvent('community_bridge:client:updateStoredClothing', function(skindata)
|
||||
StoredOldClothing = skindata
|
||||
end)
|
||||
|
||||
Clothing.SetAppearance = function(clothingData)
|
||||
if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
|
||||
clothingData = clothingData.male
|
||||
else
|
||||
clothingData = clothingData.female
|
||||
end
|
||||
local repackedTable = {}
|
||||
StoredOldClothing = Clothing.GetAppearance
|
||||
local componentMap = {
|
||||
[1] = 'mask',
|
||||
[3] = 'arms',
|
||||
[4] = 'pants',
|
||||
[5] = 'bag',
|
||||
[6] = 'shoes',
|
||||
[7] = 'accessory',
|
||||
[8] = 't-shirt',
|
||||
[9] = 'vest',
|
||||
[10] = 'decals',
|
||||
[11] = 'torso2'
|
||||
}
|
||||
|
||||
local propMap = {
|
||||
[0] = 'hat',
|
||||
[1] = 'glass',
|
||||
[2] = 'ear',
|
||||
[6] = 'watch',
|
||||
[7] = 'bracelet'
|
||||
}
|
||||
|
||||
local specialMap = {
|
||||
eye_color_id = 'eye_color',
|
||||
moles_id = 'moles',
|
||||
ageing_id = 'ageing',
|
||||
hair_id = 'hair',
|
||||
face_id = 'face'
|
||||
}
|
||||
|
||||
for _, data in pairs(clothingData) do
|
||||
if componentMap[data.component_id] then
|
||||
repackedTable[componentMap[data.component_id]] = {drawable = data.drawable, texture = data.texture}
|
||||
elseif propMap[data.prop_id] then
|
||||
repackedTable[propMap[data.prop_id]] = {drawable = data.drawable, texture = data.texture}
|
||||
elseif specialMap[data.eye_color_id] then
|
||||
repackedTable[specialMap[data.eye_color_id]] = {drawable = data.drawable, texture = data.texture}
|
||||
elseif specialMap[data.moles_id] then
|
||||
repackedTable[specialMap[data.moles_id]] = {drawable = data.drawable, texture = data.texture}
|
||||
elseif specialMap[data.ageing_id] then
|
||||
repackedTable[specialMap[data.ageing_id]] = {drawable = data.drawable, texture = data.texture}
|
||||
elseif specialMap[data.hair_id] then
|
||||
repackedTable[specialMap[data.hair_id]] = {drawable = data.drawable, texture = data.texture}
|
||||
elseif specialMap[data.face_id] then
|
||||
repackedTable[specialMap[data.face_id]] = {drawable = data.drawable, texture = data.texture}
|
||||
end
|
||||
end
|
||||
TriggerEvent('qb-clothing:client:loadOutfit', repackedTable)
|
||||
return true
|
||||
end
|
||||
|
||||
Clothing.GetAppearance = function()
|
||||
StoredOldClothing = Utility.GetEntitySkinData(cache.ped)
|
||||
return Utility.GetEntitySkinData(cache.ped)
|
||||
end
|
||||
|
||||
Clothing.RestoreAppearance = function()
|
||||
return Utility.SetEntitySkinData(cache.ped, StoredOldClothing)
|
||||
end
|
||||
|
||||
Clothing.ReloadSkin = function()
|
||||
return exports['qb-clothing']:reloadSkin(GetEntityHealth(cache.ped))
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if GetResourceState('qb-clothing') ~= 'started' then return end
|
||||
|
||||
RegisterServerEvent('qb-clothing:saveSkin', function(model, skin)
|
||||
local src = source
|
||||
if model ~= nil and skin ~= nil then
|
||||
TriggerClientEvent('community_bridge:client:updateStoredClothing', src, skin)
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,18 @@
|
||||
if GetResourceState('cd_dispatch') ~= 'started' then return end
|
||||
|
||||
Dispatch = {}
|
||||
|
||||
Dispatch.SendAlert = function(data)
|
||||
local playerData = exports['cd_dispatch']:GetPlayerInfo()
|
||||
local randomID = Bridge.helper.RandomString()
|
||||
TriggerServerEvent('cd_dispatch:AddNotification', {
|
||||
job_table = data.job,
|
||||
coords = data.coords or playerData.coords,
|
||||
title = data.code or '10-80',
|
||||
message = data.message,
|
||||
flash = 0,
|
||||
unique_id = randomID,
|
||||
sound = 1,
|
||||
blip = { sprite = 431, scale = 1.2, colour = 3, flashes = false, text = data.message, time = 10000, radius = 0, }
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
if GetResourceState('linden_outlawalert') ~= 'started' then return end
|
||||
|
||||
Dispatch = {}
|
||||
|
||||
Dispatch.SendAlert = function(data)
|
||||
local formattedData = {
|
||||
displayCode = data.code or '10-80',
|
||||
description = data.message,
|
||||
isImportant = data.priority or 0,
|
||||
recipientList = data.job,
|
||||
length = '10000',
|
||||
infoM = data.icon or 'fas fa-question',
|
||||
info = data.message
|
||||
}
|
||||
local dispatchData = {
|
||||
dispatchData = formattedData,
|
||||
caller = 'Anonymous',
|
||||
coords = GetEntityCoords(cache.ped)
|
||||
}
|
||||
TriggerServerEvent('wf-alerts:svNotify', dispatchData)
|
||||
end
|
||||
@@ -0,0 +1,75 @@
|
||||
if GetResourceState('ps-dispatch') ~= 'started' then return end
|
||||
|
||||
Dispatch = {}
|
||||
|
||||
Dispatch.SendAlert = function(data)
|
||||
local customData = {
|
||||
message = data.message,
|
||||
code = data.code or '10-80',
|
||||
icon = data.icon or 'fas fa-question',
|
||||
priority = data.priority or 2,
|
||||
coords = data.coords or vec3(0.0, 0.0, 0.0),
|
||||
gender = data.gender or nil,
|
||||
camId = data.camId or nil,
|
||||
color = data.firstColor or nil,
|
||||
callsign = data.callsign or nil,
|
||||
name = data.name or nil,
|
||||
vehicle = data.model or nil,
|
||||
plate = data.plate or nil,
|
||||
alertTime = data.alertTime or nil,
|
||||
doorCount = data.doorCount or nil,
|
||||
automaticGunfire = data.automaticGunfire or false,
|
||||
alert = {
|
||||
radius = data.radius or 0,
|
||||
recipientList = data.job or { 'leo' },
|
||||
sprite = data.sprite or 1,
|
||||
color = data.color or 1,
|
||||
scale = data.scale or 0.5,
|
||||
length = data.length or 2,
|
||||
sound = data.sound or "Lose_1st",
|
||||
sound2 = data.sound2 or "GTAO_FM_Events_Soundset",
|
||||
offset = data.offset or false,
|
||||
flash = data.flash or false
|
||||
},
|
||||
jobs = { data.job or 'leo' }
|
||||
}
|
||||
exports["ps-dispatch"]:CustomAlert(customData)
|
||||
end
|
||||
|
||||
--[[
|
||||
-- tested, it worked
|
||||
CreateThread(function()
|
||||
local data = {
|
||||
message = "Fart",
|
||||
code = '10-80',
|
||||
icon = 'fas fa-question',
|
||||
priority = 2,
|
||||
coords = vec3(0.0, 0.0, 0.0),
|
||||
gender = nil,
|
||||
camId = nil,
|
||||
color = nil,
|
||||
callsign = nil,
|
||||
name = "Test Name",
|
||||
vehicle = nil,
|
||||
plate = nil,
|
||||
alertTime = 30000,
|
||||
doorCount = nil,
|
||||
automaticGunfire = false,
|
||||
alert = {
|
||||
radius = 0,
|
||||
recipientList = { 'leo' },
|
||||
sprite = 1,
|
||||
color = 1,
|
||||
scale = 0.5,
|
||||
length = 2,
|
||||
sound = "Lose_1st",
|
||||
sound2 = "GTAO_FM_Events_Soundset",
|
||||
offset = false,
|
||||
flash = false
|
||||
},
|
||||
jobs = { 'leo' }
|
||||
}
|
||||
Dispatch.SendAlert(data)
|
||||
print("Dispatched")
|
||||
end)
|
||||
--]]
|
||||
@@ -0,0 +1,16 @@
|
||||
if GetResourceState('rcore_dispatch') ~= 'started' then return end
|
||||
|
||||
Dispatch = {}
|
||||
|
||||
Dispatch.SendAlert = function(data)
|
||||
local playerData = exports['rcore_dispatch']:GetPlayerData()
|
||||
TriggerEvent('rcore_dispatch:server:sendAlert', {
|
||||
code = data.code or '10-80',
|
||||
default_priority = 'low',
|
||||
coords = data.coords or playerData.coords,
|
||||
job = data.job,
|
||||
text = data.message or 'No message provided',
|
||||
type = 'alerts',
|
||||
blip = { sprite = 54, colour = 3, scale = 0.7, text = data.message or "No Message", flashes = false, radius = 0 }
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if GetResourceState('doors_creator') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.GetClosestDoor = function()
|
||||
return exports["doors_creator"]:getClosestActiveDoor()
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
if GetResourceState('doors_creator') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
|
||||
local state = toggle
|
||||
if state then
|
||||
exports["doors_creator"]:setDoorState(doorID, 1)
|
||||
else
|
||||
exports["doors_creator"]:setDoorState(doorID, 0)
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
if GetResourceState('ox_doorlock') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.GetClosestDoor = function()
|
||||
return exports.ox_doorlock:getClosestDoor()
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
if GetResourceState('ox_doorlock') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
|
||||
local state = toggle
|
||||
if state then
|
||||
exports.ox_doorlock:setDoorState(doorID, 1)
|
||||
else
|
||||
exports.ox_doorlock:setDoorState(doorID, 0)
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
if GetResourceState('qb-doorlock') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.GetClosestDoor = function()
|
||||
local closestDoor = exports["qb-doorlock"]:GetClosestDoor()
|
||||
if Table.CheckPopulated(closestDoor) then return closestDoor end
|
||||
local allDoors = exports["qb-doorlock"]:GetDoorList()
|
||||
local pedCoords = GetEntityCoords(cache.ped)
|
||||
local door = 0
|
||||
local doorDist = 1000.0
|
||||
for doorID, data in pairs(allDoors) do
|
||||
local dist = #(pedCoords - data.objCoords)
|
||||
if dist < doorDist then
|
||||
door = doorID
|
||||
doorDist = dist
|
||||
end
|
||||
end
|
||||
return door
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
if GetResourceState('qb-doorlock') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
|
||||
TriggerClientEvent('qb-doorlock:client:setState', -1, 0, doorID, toggle, false, false, false)
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if GetResourceState('rcore_doorlock') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.GetClosestDoor = function()
|
||||
local allDoors = exports.rcore_doorlock:getLoadedDoors()
|
||||
local pedCoords = GetEntityCoords(cache.ped)
|
||||
local door = 0
|
||||
local doorDist = 1000.0
|
||||
for _, data in pairs(allDoors) do
|
||||
local dist = #(pedCoords - data.coords)
|
||||
if dist < doorDist then
|
||||
door = data.id
|
||||
doorDist = dist
|
||||
end
|
||||
end
|
||||
return door
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
if GetResourceState('rcore_doorlock') ~= 'started' then return end
|
||||
|
||||
Doorlock = {}
|
||||
|
||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
|
||||
local state = toggle
|
||||
if state then
|
||||
exports.rcore_doorlock:changeDoorState(doorID, 0)
|
||||
else
|
||||
exports.rcore_doorlock:changeDoorState(doorID, 1)
|
||||
end
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
if GetResourceState('es_extended') ~= 'started' then return end
|
||||
|
||||
ESX = exports["es_extended"]:getSharedObject()
|
||||
|
||||
Framework = {}
|
||||
|
||||
Framework.GetPlayerData = function()
|
||||
return ESX.PlayerData
|
||||
end
|
||||
|
||||
Framework.GetPlayerMetaData = function(metadata)
|
||||
return ESX.GetPlayerData().metadata[metadata]
|
||||
end
|
||||
|
||||
Framework.GetPlayerIdentifier = function()
|
||||
return ESX.GetPlayerData().identifier
|
||||
end
|
||||
|
||||
Framework.GetPlayerName = function()
|
||||
local playerData = ESX.GetPlayerData()
|
||||
return playerData.firstName, playerData.lastName
|
||||
end
|
||||
|
||||
Framework.GetPlayerJob = function()
|
||||
local playerData = ESX.GetPlayerData()
|
||||
return playerData.job.name, playerData.job.label, playerData.job.grade_label, playerData.job.grade
|
||||
end
|
||||
|
||||
Framework.GetPlayerInventory = function()
|
||||
return ESX.GetPlayerData().inventory
|
||||
end
|
||||
|
||||
Framework.GetIsPlayerDead = function()
|
||||
return ESX.GetPlayerData().dead
|
||||
end
|
||||
|
||||
RegisterNetEvent('esx:playerLoaded', function(xPlayer)
|
||||
Wait(1500)
|
||||
FillBridgeTables()
|
||||
TriggerEvent('community_bridge:Client:OnPlayerLoaded')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:onPlayerLogout', function()
|
||||
ClearClientSideVariables()
|
||||
TriggerEvent('community_bridge:Client:OnPlayerUnload')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:setJob', function(data)
|
||||
PlayerJobName = data.name
|
||||
PlayerJobLabel = data.label
|
||||
PlayerJobGradeName = data.grade_label
|
||||
PlayerJobGradeLevel = data.grade
|
||||
TriggerEvent('community_bridge:Client:OnPlayerJobUpdate',PlayerJobName, PlayerJobLabel, PlayerJobGradeName, PlayerJobGradeLevel)
|
||||
end)
|
||||
@@ -0,0 +1,196 @@
|
||||
if GetResourceState('es_extended') ~= 'started' then return end
|
||||
|
||||
ESX = exports["es_extended"]:getSharedObject()
|
||||
|
||||
Framework = {}
|
||||
|
||||
-- Framework.GetPlayerIdentifier(src)
|
||||
-- Returns the citizen ID of the player.
|
||||
Framework.GetPlayerIdentifier = function(src)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.getIdentifier()
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerName(src)
|
||||
-- Returns the first and last name of the player.
|
||||
Framework.GetPlayerName = function(src)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.variables.firstName, xPlayer.variables.lastName
|
||||
end
|
||||
|
||||
-- Framework.GetItem(src, item, metadata)
|
||||
-- Returns a table of items matching the specified name and if passed metadata from the player's inventory.
|
||||
-- returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
|
||||
Framework.GetItem = function(src, item, _)
|
||||
local playerItems = ESX.GetPlayerFromId(src).getInventory()
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerItems) do
|
||||
if v.name == item then
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.count,
|
||||
--metadata = v.metadata,
|
||||
--slot = v.slot,
|
||||
})
|
||||
end
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
-- Framework.GetItemCount(src, item, _)
|
||||
-- Returns the count of items matching the specified name and if passed metadata from the player's inventory.
|
||||
Framework.GetItemCount = function(src, item, _)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.getInventoryItem(item).count
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerInventory(src)
|
||||
-- Returns the entire inventory of the player as a table.
|
||||
-- returns {name = v.name, count = v.amount, _, _}
|
||||
Framework.GetPlayerInventory = function(src)
|
||||
local playerItems = ESX.GetPlayerFromId(src).getInventory()
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerItems) do
|
||||
if v.count > 0 then
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.count,
|
||||
--metadata = v.metadata,
|
||||
--slot = v.slot,
|
||||
})
|
||||
end
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
-- Framework.SetMetadata(src, metadata, value)
|
||||
-- Adds the specified metadata key and number value to the player's data.
|
||||
Framework.SetPlayerMetadata = function(src, metadata, value)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
xPlayer.setMeta(metadata, value, nil)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Framework.GetMetadata(src, metadata)
|
||||
-- Gets the specified metadata key and value to the player's data.
|
||||
Framework.GetPlayerMetadata = function(src, metadata)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.getMeta(metadata) or false
|
||||
end
|
||||
|
||||
-- defualt esx Available tables are
|
||||
-- identifier, accounts, group, inventory, job, job_grade, loadout,
|
||||
-- metadata, position, firstname, lastname, dateofbirth, sex, height,
|
||||
-- skin, status, is_dead, id, disabled, last_property, created_at, last_seen,
|
||||
-- phone_number, pincode
|
||||
Framework.GetStatus = function(src, column)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.get(column) or nil
|
||||
end
|
||||
|
||||
-- Framework.AddThirst(src, value)
|
||||
-- Adds the specified value from the player's thirst level.
|
||||
Framework.AddThirst = function(src, value)
|
||||
local clampIT = Math.Clamp(value, 0, 200000)
|
||||
local levelForEsx = clampIT * 2000
|
||||
TriggerClientEvent('esx_status:add', src, 'thirst', levelForEsx)
|
||||
return levelForEsx
|
||||
end
|
||||
|
||||
-- Framework.AddHunger(src, value)
|
||||
-- Adds the specified value from the player's hunger level.
|
||||
Framework.AddHunger = function(src, value)
|
||||
local clampIT = Math.Clamp(value, 0, 200000)
|
||||
local levelForEsx = clampIT * 2000
|
||||
TriggerClientEvent('esx_status:add', src, 'hunger', levelForEsx)
|
||||
return levelForEsx
|
||||
end
|
||||
|
||||
Framework.GetHunger = function(src)
|
||||
local status = Framework.GetStatus(src, "status")
|
||||
if not status then return 0 end
|
||||
return status.hunger
|
||||
end
|
||||
|
||||
Framework.GetThirst = function(src)
|
||||
local status = Framework.GetStatus(src, "status")
|
||||
if not status then return 0 end
|
||||
return status.thirst
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerPhone(src)
|
||||
-- Returns the phone number of the player.
|
||||
Framework.GetPlayerPhone = function(src)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.get("phone_number")
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerJob(src)
|
||||
-- Returns the job name, label, grade name, and grade level of the player.
|
||||
Framework.GetPlayerJob = function(src)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.getJob().name, xPlayer.getJob().label, xPlayer.getJob().grade_label, xPlayer.getJob().grade
|
||||
end
|
||||
|
||||
-- Framework.GetPlayersByJob(jobname)
|
||||
-- returns a table of player sources that have the specified job name.
|
||||
Framework.GetPlayersByJob = function(job)
|
||||
local players = GetPlayers()
|
||||
local playerList = {}
|
||||
for _, src in pairs(players) do
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
if xPlayer.getJob().name == job then
|
||||
table.insert(playerList, src)
|
||||
end
|
||||
end
|
||||
return playerList
|
||||
end
|
||||
|
||||
-- Framework.SetPlayerJob(src, name, grade)
|
||||
-- Sets the player's job to the specified name and grade.
|
||||
Framework.SetPlayerJob = function(src, name, grade)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
if not ESX.DoesJobExist(name, grade) then lib.print.error("Job Does Not Exsist In Framework :NAME "..name.." Grade:"..grade) return end
|
||||
return xPlayer.setJob(name, grade)
|
||||
end
|
||||
|
||||
-- Framework.AddAccountBalance(src, _type, amount)
|
||||
-- Adds the specified amount to the player's account balance of the specified type.
|
||||
Framework.AddAccountBalance = function(src, _type, amount)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.addAccountMoney(_type, amount)
|
||||
end
|
||||
|
||||
-- Framework.RemoveAccountBalance(src, _type, amount)
|
||||
-- Removes the specified amount from the player's account balance of the specified type.
|
||||
Framework.RemoveAccountBalance = function(src, _type, amount)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.removeAccountMoney(_type, amount)
|
||||
end
|
||||
|
||||
-- Framework.GetAccountBalance(src, _type)
|
||||
-- Returns the player's account balance of the specified type.
|
||||
Framework.GetAccountBalance = function(src, _type)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.getAccount(_type).money
|
||||
end
|
||||
|
||||
-- Framework.AddItem(src, item, amount, _, _)
|
||||
-- Adds the specified item to the player's inventory.
|
||||
Framework.AddItem = function(src, item, amount, slot, metadata)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.addInventoryItem(item, amount)
|
||||
end
|
||||
|
||||
-- Framework.RemoveItem(src, item, amount, _, _)
|
||||
-- Removes the specified item from the player's inventory.
|
||||
Framework.RemoveItem = function(src, item, amount, slot, metadata)
|
||||
local xPlayer = ESX.GetPlayerFromId(src)
|
||||
return xPlayer.removeInventoryItem(item, amount)
|
||||
end
|
||||
|
||||
-- Framework.RegisterUsableItem(item, cb)
|
||||
-- Registers a usable item with a callback function.
|
||||
Framework.RegisterUsableItem = function(item, cb)
|
||||
ESX.RegisterUsableItem(item, cb)
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
if GetResourceState('ox_core') ~= 'started' then return end
|
||||
@@ -0,0 +1 @@
|
||||
if GetResourceState('ox_core') ~= 'started' then return end
|
||||
@@ -0,0 +1,71 @@
|
||||
if GetResourceState('qb-core') ~= 'started' then return end
|
||||
if GetResourceState('qbx_core') == 'started' then return end
|
||||
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
|
||||
Framework = {}
|
||||
|
||||
Framework.GetPlayerData = function()
|
||||
return QBCore.Functions.GetPlayerData()
|
||||
end
|
||||
|
||||
Framework.GetPlayerMetaData = function(metadata)
|
||||
return QBCore.Functions.GetPlayerData().metadata[metadata]
|
||||
end
|
||||
|
||||
Framework.GetItemInfo = function(item)
|
||||
local itemData = QBCore.Shared.Items[item]
|
||||
if not itemData then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name,
|
||||
label = itemData.label,
|
||||
stack = itemData.unique,
|
||||
weight = itemData.weight,
|
||||
description = itemData.description,
|
||||
image = itemData.image
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Framework.GetPlayerIdentifier = function()
|
||||
return QBCore.Functions.GetPlayerData().citizenid
|
||||
end
|
||||
|
||||
Framework.GetPlayerName = function()
|
||||
local playerData = QBCore.Functions.GetPlayerData()
|
||||
return playerData.charinfo.firstname, playerData.charinfo.lastname
|
||||
end
|
||||
|
||||
Framework.GetPlayerJob = function()
|
||||
local playerData = QBCore.Functions.GetPlayerData()
|
||||
return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
|
||||
end
|
||||
|
||||
Framework.GetPlayerInventory = function()
|
||||
return QBCore.Functions.GetPlayerData().items
|
||||
end
|
||||
|
||||
Framework.GetIsPlayerDead = function()
|
||||
return QBCore.Functions.GetPlayerData().metadata["isdead"] or QBCore.GetPlayerData().metadata["inlaststand"]
|
||||
end
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||
Wait(1500)
|
||||
FillBridgeTables()
|
||||
TriggerEvent('community_bridge:Client:OnPlayerLoaded')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
|
||||
ClearClientSideVariables()
|
||||
TriggerEvent('community_bridge:Client:OnPlayerUnload')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(data)
|
||||
PlayerJobName = data.name
|
||||
PlayerJobLabel = data.label
|
||||
PlayerJobGradeName = data.grade.name
|
||||
PlayerJobGradeLevel = data.grade.level
|
||||
TriggerEvent('community_bridge:Client:OnPlayerJobUpdate',PlayerJobName, PlayerJobLabel, PlayerJobGradeName, PlayerJobGradeLevel)
|
||||
end)
|
||||
|
||||
Bridge.RegisterModule("Framework", Framework)
|
||||
@@ -0,0 +1,247 @@
|
||||
if GetResourceState('qb-core') ~= 'started' then return end
|
||||
if GetResourceState('qbx_core') == 'started' then return end
|
||||
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
|
||||
Framework = {}
|
||||
|
||||
-- Framework.GetPlayerIdentifier(src)
|
||||
-- Returns the citizen ID of the player.
|
||||
Framework.GetPlayerIdentifier = function(src)
|
||||
return QBCore.Functions.GetPlayer(src).PlayerData.citizenid
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerName(src)
|
||||
-- Returns the first and last name of the player.
|
||||
Framework.GetPlayerName = function(src)
|
||||
local playerData = QBCore.Functions.GetPlayer(src).PlayerData
|
||||
return playerData.charinfo.firstname, playerData.charinfo.lastname
|
||||
end
|
||||
|
||||
-- Framework.GetItem(src, item, metadata)
|
||||
-- Returns a table of items matching the specified name and if passed metadata from the player's inventory.
|
||||
-- returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
|
||||
Framework.GetItem = function(src, item, metadata)
|
||||
local playerInventory = QBCore.Functions.GetPlayer(src).PlayerData.items
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerInventory) do
|
||||
if v.name == item and (not metadata or v.info == metadata) then
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.amount,
|
||||
metadata = v.info,
|
||||
slot = v.slot,
|
||||
})
|
||||
end
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
-- Framework.GetItemCount(src, item, metadata)
|
||||
-- Returns the count of items matching the specified name and if passed metadata from the player's inventory.
|
||||
Framework.GetItemCount = function(src, item, metadata)
|
||||
local playerInventory = QBCore.Functions.GetPlayer(src).PlayerData.items
|
||||
local count = 0
|
||||
for _, v in pairs(playerInventory) do
|
||||
if v.name == item and (not metadata or v.info == metadata) then
|
||||
count = count + v.amount
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerInventory(src)
|
||||
-- Returns the entire inventory of the player as a table.
|
||||
-- returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
|
||||
Framework.GetPlayerInventory = function(src)
|
||||
local playerItems = QBCore.Functions.GetPlayer(src).PlayerData.items
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerItems) do
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.amount,
|
||||
metadata = v.info,
|
||||
slot = v.slot,
|
||||
})
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
-- Framework.SetMetadata(src, metadata, value)
|
||||
-- Adds the specified metadata key and number value to the player's data.
|
||||
Framework.SetPlayerMetadata = function(src, metadata, value)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
player.Functions.SetMetaData(metadata, value)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Framework.GetMetadata(src, metadata)
|
||||
-- Gets the specified metadata key to the player's data.
|
||||
Framework.GetPlayerMetadata = function(src, metadata)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
return playerData.metadata[metadata] or false
|
||||
end
|
||||
|
||||
-- Framework.AddStress(src, value)
|
||||
-- Adds the specified value to the player's stress level and updates the client HUD.
|
||||
Framework.AddStress = function(src, value)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newStress = playerData.metadata.stress + value
|
||||
player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
|
||||
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newStress
|
||||
end
|
||||
|
||||
-- Framework.RemoveStress(src, value)
|
||||
-- Removes the specified value from the player's stress level and updates the client HUD.
|
||||
Framework.RemoveStress = function(src, value)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newStress = (playerData.metadata.stress or 0) - value
|
||||
player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
|
||||
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newStress
|
||||
end
|
||||
|
||||
-- Framework.AddHunger(src, value)
|
||||
-- Adds the specified value from the player's hunger level.
|
||||
Framework.AddHunger = function(src, value)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newHunger = (playerData.metadata.hunger or 0) + value
|
||||
player.Functions.SetMetaData('hunger', Math.Clamp(newHunger, 0, 100))
|
||||
--TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newHunger
|
||||
end
|
||||
|
||||
-- Framework.AddThirst(src, value)
|
||||
-- Adds the specified value from the player's thirst level.
|
||||
Framework.AddThirst = function(src, value)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newThirst = (playerData.metadata.thirst or 0) + value
|
||||
player.Functions.SetMetaData('thirst', Math.Clamp(newThirst, 0, 100))
|
||||
--TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newThirst
|
||||
end
|
||||
|
||||
Framework.GetHunger = function(src)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newHunger = (playerData.metadata.hunger or 0)
|
||||
return newHunger
|
||||
end
|
||||
|
||||
Framework.GetThirst = function(src)
|
||||
local player = QBCore.Functions.GetPlayer(src).PlayerData
|
||||
local newThirst = (player.metadata.thirst or 0)
|
||||
return newThirst
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerPhone(src)
|
||||
-- Returns the phone number of the player.
|
||||
Framework.GetPlayerPhone = function(src)
|
||||
local playerData = QBCore.Functions.GetPlayer(src).PlayerData
|
||||
return playerData.charinfo.phone
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerGang(src)
|
||||
-- Returns the gang name of the player.
|
||||
Framework.GetPlayerGang = function(src)
|
||||
local player = QBCore.Functions.GetPlayer(src).PlayerData
|
||||
return player.gang.name
|
||||
end
|
||||
|
||||
-- Framework.GetPlayersByJob(jobname)
|
||||
-- returns a table of player sources that have the specified job name.
|
||||
Framework.GetPlayersByJob = function(job)
|
||||
local players = QBCore.Functions.GetPlayers()
|
||||
local playerList = {}
|
||||
for _, src in pairs(players) do
|
||||
local player = QBCore.Functions.GetPlayer(src).PlayerData
|
||||
if player.job.name == job then
|
||||
table.insert(playerList, src)
|
||||
end
|
||||
end
|
||||
return playerList
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerJob(src)
|
||||
-- Returns the job name, label, grade name, and grade level of the player.
|
||||
Framework.GetPlayerJob = function(src)
|
||||
local player = QBCore.Functions.GetPlayer(src).PlayerData
|
||||
return player.job.name, player.job.label, player.job.grade.name, player.job.grade.level
|
||||
end
|
||||
|
||||
-- Framework.SetPlayerJob(src, name, grade)
|
||||
-- Sets the player's job to the specified name and grade.
|
||||
Framework.SetPlayerJob = function(src, name, grade)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
return player.Functions.SetJob(name, grade)
|
||||
end
|
||||
|
||||
-- Framework.AddAccountBalance(src, _type, amount)
|
||||
-- Adds the specified amount to the player's account balance of the specified type.
|
||||
Framework.AddAccountBalance = function(src, _type, amount)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
if _type == 'money' then _type = 'cash' end
|
||||
return player.Functions.AddMoney(_type, amount)
|
||||
end
|
||||
|
||||
-- Framework.RemoveAccountBalance(src, _type, amount)
|
||||
-- Removes the specified amount from the player's account balance of the specified type.
|
||||
Framework.RemoveAccountBalance = function(src, _type, amount)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
if _type == 'money' then _type = 'cash' end
|
||||
return player.Functions.RemoveMoney(_type, amount)
|
||||
end
|
||||
|
||||
-- Framework.GetAccountBalance(src, _type)
|
||||
-- Returns the player's account balance of the specified type.
|
||||
Framework.GetAccountBalance = function(src, _type)
|
||||
local playerData = QBCore.Functions.GetPlayer(src).PlayerData
|
||||
if _type == 'money' then _type = 'cash' end
|
||||
return playerData.money[_type]
|
||||
end
|
||||
|
||||
-- Framework.AddItem(src, item, amount, slot, metadata)
|
||||
-- Adds the specified item to the player's inventory.
|
||||
Framework.AddItem = function(src, item, amount, slot, metadata)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
return player.Functions.AddItem(item, amount, slot, metadata)
|
||||
end
|
||||
|
||||
-- Framework.RemoveItem(src, item, amount, slot, metadata)
|
||||
-- Removes the specified item from the player's inventory.
|
||||
Framework.RemoveItem = function(src, item, amount, slot, metadata)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
return player.Functions.RemoveItem(item, amount, slot or nil)
|
||||
end
|
||||
|
||||
-- Framework.SetMetadata(src, item, slot, metadata)
|
||||
-- Sets the metadata for the specified item in the player's inventory.
|
||||
-- Notes, this is kinda a jank workaround. with the framework aside from updating the entire table theres not really a better way
|
||||
Framework.SetMetadata = function(src, item, slot, metadata)
|
||||
local player = QBCore.Functions.GetPlayer(src)
|
||||
local slotFinder = Framework.GetPlayerInventory(src)
|
||||
local freeSlot = Table.FindFirstUnoccupiedSlot(slotFinder)
|
||||
local itemSlot = slot or nil
|
||||
if itemSlot == nil then
|
||||
for _, v in pairs(slotFinder) do
|
||||
if v.name == item then
|
||||
slot = v.slot
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
player.Functions.RemoveItem(item, 1, itemSlot)
|
||||
return player.Functions.AddItem(item, 1, freeSlot, metadata)
|
||||
end
|
||||
|
||||
-- Framework.RegisterUsableItem(item, cb)
|
||||
-- Registers a usable item with a callback function.
|
||||
Framework.RegisterUsableItem = function(item, cb)
|
||||
QBCore.Functions.CreateUseableItem(item, cb)
|
||||
end
|
||||
@@ -0,0 +1,65 @@
|
||||
if GetResourceState('qbx_core') ~= 'started' then return end
|
||||
|
||||
-- This fork is a cult, they just belittle people and degrade them to feel better about themselves.
|
||||
-- Defualt support for the best free inventory currently available is cool though.
|
||||
|
||||
QBox = exports.qbx_core
|
||||
|
||||
Framework = {}
|
||||
|
||||
Framework.GetPlayerData = function()
|
||||
return QBox.GetPlayerData()
|
||||
end
|
||||
|
||||
Framework.GetPlayerMetaData = function(metadata)
|
||||
local playerData = QBox.GetPlayerData()
|
||||
return playerData.metadata[metadata]
|
||||
end
|
||||
|
||||
Framework.GetPlayerIdentifier = function()
|
||||
return QBox.GetPlayerData().citizenid
|
||||
end
|
||||
|
||||
Framework.GetPlayerName = function()
|
||||
local playerData = QBox.GetPlayerData()
|
||||
return playerData.charinfo.firstname, playerData.charinfo.lastname
|
||||
end
|
||||
|
||||
Framework.GetPlayerJob = function()
|
||||
local playerData = QBox.GetPlayerData()
|
||||
return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
|
||||
end
|
||||
|
||||
Framework.GetPlayerInventory = function()
|
||||
return QBox.GetPlayerData().items
|
||||
end
|
||||
|
||||
Framework.GetIsPlayerDead = function()
|
||||
return QBox.GetPlayerData().metadata["isdead"] or QBox.GetPlayerData().metadata["inlaststand"]
|
||||
end
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
|
||||
Wait(1500)
|
||||
FillBridgeTables()
|
||||
TriggerEvent('community_bridge:Client:OnPlayerLoaded')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
|
||||
ClearClientSideVariables()
|
||||
TriggerEvent('community_bridge:Client:OnPlayerUnload')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(data)
|
||||
PlayerJobName = data.name
|
||||
PlayerJobLabel = data.label
|
||||
PlayerJobGradeName = data.grade.name
|
||||
PlayerJobGradeLevel = data.grade.level
|
||||
TriggerEvent('community_bridge:Client:OnPlayerJobUpdate',PlayerJobName, PlayerJobLabel, PlayerJobGradeName, PlayerJobGradeLevel)
|
||||
end)
|
||||
|
||||
--[[
|
||||
print("Qbox shit.")
|
||||
print(Framework.GetPlayerIdentifier())
|
||||
print(json.encode(Framework.GetPlayerInventory()))
|
||||
print(json.encode(Framework.GetIsPlayerDead()))
|
||||
--]]
|
||||
@@ -0,0 +1,238 @@
|
||||
if GetResourceState('qbx_core') ~= 'started' then return end
|
||||
|
||||
-- This fork is a cult, they just belittle people and degrade them to feel better about themselves.
|
||||
-- Defualt support for the best free inventory currently available is cool though.
|
||||
|
||||
local QBox = exports.qbx_core
|
||||
|
||||
Framework = {}
|
||||
|
||||
-- Framework.GetPlayerIdentifier(src)
|
||||
-- Returns the citizen ID of the player.
|
||||
Framework.GetPlayerIdentifier = function(src)
|
||||
local playerData = QBox:GetPlayer(src).PlayerData
|
||||
if not playerData then return false end
|
||||
return playerData.citizenid
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerName(src)
|
||||
-- Returns the first and last name of the player.
|
||||
Framework.GetPlayerName = function(src)
|
||||
local playerData = QBox:GetPlayer(src).PlayerData
|
||||
return playerData.charinfo.firstname, playerData.charinfo.lastname
|
||||
end
|
||||
|
||||
-- Framework.GetItem(src, item, metadata)
|
||||
-- Returns a table of items matching the specified name and if passed metadata from the player's inventory.
|
||||
-- returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
|
||||
Framework.GetItem = function(src, item, metadata)
|
||||
local playerInventory = QBox:GetPlayer(src).PlayerData.items
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerInventory) do
|
||||
if v.name == item and (not metadata or v.info == metadata) then
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.amount,
|
||||
metadata = v.info,
|
||||
slot = v.slot,
|
||||
})
|
||||
end
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
-- Framework.GetItemCount(src, item, metadata)
|
||||
-- Returns the count of items matching the specified name and if passed metadata from the player's inventory.
|
||||
Framework.GetItemCount = function(src, item, metadata)
|
||||
local playerInventory = QBox:GetPlayer(src).PlayerData.items
|
||||
local count = 0
|
||||
for _, v in pairs(playerInventory) do
|
||||
if v.name == item and (not metadata or v.info == metadata) then
|
||||
count = count + v.amount
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerInventory(src)
|
||||
-- Returns the entire inventory of the player as a table.
|
||||
-- returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
|
||||
Framework.GetPlayerInventory = function(src)
|
||||
local playerItems = QBox:GetPlayer(src).PlayerData.items
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerItems) do
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.amount,
|
||||
metadata = v.metadata,
|
||||
slot = v.slot,
|
||||
})
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
-- Framework.SetMetadata(src, metadata, value)
|
||||
-- Adds the specified metadata key and number value to the player's data.
|
||||
Framework.SetPlayerMetadata = function(src, metadata, value)
|
||||
local player = QBox:GetPlayer(src)
|
||||
player.Functions.SetMetaData(metadata, value)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Framework.GetMetadata(src, metadata)
|
||||
-- Gets the specified metadata key to the player's data.
|
||||
Framework.GetPlayerMetadata = function(src, metadata)
|
||||
local player = QBox:GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
return playerData.metadata[metadata] or false
|
||||
end
|
||||
|
||||
-- Framework.AddStress(src, value)
|
||||
-- Adds the specified value to the player's stress level and updates the client HUD.
|
||||
Framework.AddStress = function(src, value)
|
||||
local player = QBox:GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newStress = playerData.metadata.stress + value
|
||||
player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
|
||||
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newStress
|
||||
end
|
||||
|
||||
-- Framework.RemoveStress(src, value)
|
||||
-- Removes the specified value from the player's stress level and updates the client HUD.
|
||||
Framework.RemoveStress = function(src, value)
|
||||
local player = QBox:GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newStress = (playerData.metadata.stress or 0) - value
|
||||
player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
|
||||
TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newStress
|
||||
end
|
||||
|
||||
-- Framework.AddHunger(src, value)
|
||||
-- Adds the specified value from the player's hunger level.
|
||||
Framework.AddHunger = function(src, value)
|
||||
local player = QBox:GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newHunger = (playerData.metadata.hunger or 0) + value
|
||||
player.Functions.SetMetaData('hunger', Math.Clamp(newHunger, 0, 100))
|
||||
--TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newHunger
|
||||
end
|
||||
|
||||
-- Framework.AddThirst(src, value)
|
||||
-- Adds the specified value from the player's thirst level.
|
||||
Framework.AddThirst = function(src, value)
|
||||
local player = QBox:GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newThirst = (playerData.metadata.thirst or 0) + value
|
||||
player.Functions.SetMetaData('thirst', Math.Clamp(newThirst, 0, 100))
|
||||
--TriggerClientEvent('hud:client:UpdateStress', src, newStress)
|
||||
return newThirst
|
||||
end
|
||||
|
||||
Framework.GetHunger = function(src)
|
||||
local player = QBox:GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newHunger = (playerData.metadata.hunger or 0)
|
||||
return newHunger
|
||||
end
|
||||
|
||||
Framework.GetThirst = function(src)
|
||||
local player = QBox:GetPlayer(src)
|
||||
local playerData = player.PlayerData
|
||||
local newThirst = (playerData.metadata.thirst or 0)
|
||||
return newThirst
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerPhone(src)
|
||||
-- Returns the phone number of the player.
|
||||
Framework.GetPlayerPhone = function(src)
|
||||
local playerData = QBox:GetPlayer(src).PlayerData
|
||||
return playerData.charinfo.phone
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerGang(src)
|
||||
-- Returns the gang name of the player.
|
||||
Framework.GetPlayerGang = function(src)
|
||||
local player = QBox:GetPlayer(src).PlayerData
|
||||
return player.gang.name
|
||||
end
|
||||
|
||||
Framework.GetPlayersByJob = function(job)
|
||||
local playerList = {}
|
||||
local players = QBox:GetQBPlayers()
|
||||
for src, player in pairs(players) do
|
||||
if player.PlayerData.job.name == job then
|
||||
table.insert(playerList, src)
|
||||
end
|
||||
end
|
||||
return playerList
|
||||
end
|
||||
|
||||
-- Framework.GetPlayerJob(src)
|
||||
-- Returns the job name, label, grade name, and grade level of the player.
|
||||
Framework.GetPlayerJob = function(src)
|
||||
local player = QBox:GetPlayer(src).PlayerData
|
||||
return player.job.name, player.job.label, player.job.grade.name, player.job.grade.level
|
||||
end
|
||||
|
||||
-- Framework.SetPlayerJob(src, name, grade)
|
||||
-- Sets the player's job to the specified name and grade.
|
||||
Framework.SetPlayerJob = function(src, name, grade)
|
||||
local player = QBox:GetPlayer(src)
|
||||
return player.Functions.SetJob(name, grade)
|
||||
end
|
||||
|
||||
-- Framework.AddAccountBalance(src, _type, amount)
|
||||
-- Adds the specified amount to the player's account balance of the specified type.
|
||||
Framework.AddAccountBalance = function(src, _type, amount)
|
||||
local player = QBox:GetPlayer(src)
|
||||
if _type == 'money' then _type = 'cash' end
|
||||
return player.Functions.AddMoney(_type, amount)
|
||||
end
|
||||
|
||||
-- Framework.RemoveAccountBalance(src, _type, amount)
|
||||
-- Removes the specified amount from the player's account balance of the specified type.
|
||||
Framework.RemoveAccountBalance = function(src, _type, amount)
|
||||
local player = QBox:GetPlayer(src)
|
||||
if _type == 'money' then _type = 'cash' end
|
||||
return player.Functions.RemoveMoney(_type, amount)
|
||||
end
|
||||
|
||||
-- Framework.GetAccountBalance(src, _type)
|
||||
-- Returns the player's account balance of the specified type.
|
||||
Framework.GetAccountBalance = function(src, _type)
|
||||
local playerData = QBox:GetPlayer(src).PlayerData
|
||||
if _type == 'money' then _type = 'cash' end
|
||||
return playerData.money[_type]
|
||||
end
|
||||
|
||||
-- Framework.AddItem(src, item, amount, slot, metadata)
|
||||
-- Adds the specified item to the player's inventory.
|
||||
Framework.AddItem = function(src, item, amount, slot, metadata)
|
||||
local player = QBox:GetPlayer(src)
|
||||
return player.Functions.AddItem(item, amount, slot, metadata)
|
||||
end
|
||||
|
||||
-- Framework.RemoveItem(src, item, amount, slot, metadata)
|
||||
-- Removes the specified item from the player's inventory.
|
||||
Framework.RemoveItem = function(src, item, amount, slot, metadata)
|
||||
local player = QBox:GetPlayer(src)
|
||||
return player.Functions.RemoveItem(item, amount, slot)
|
||||
end
|
||||
|
||||
-- Framework.SetMetadata(src, item, slot, metadata)
|
||||
-- Sets the metadata for the specified item in the player's inventory.
|
||||
-- Notes, this is kinda a jank workaround. with the framework aside from updating the entire table theres not really a better way
|
||||
Framework.SetMetadata = function(src, item, slot, metadata)
|
||||
local player = QBox:GetPlayer(src)
|
||||
player.Functions.RemoveItem(item, 1, slot)
|
||||
return player.Functions.AddItem(item, 1, slot, metadata)
|
||||
end
|
||||
|
||||
-- Framework.RegisterUsableItem(item, cb)
|
||||
-- Registers a usable item with a callback function.
|
||||
Framework.RegisterUsableItem = function(item, cb)
|
||||
return QBox:CreateUseableItem(item, cb)
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('LegacyFuel') ~= 'started' then return end
|
||||
Fuel = {}
|
||||
|
||||
Fuel.GetFuel = function(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0.0 end
|
||||
return exports['LegacyFuel']:GetFuel(vehicle)
|
||||
end
|
||||
|
||||
Fuel.SetFuel = function(vehicle, fuel, type)
|
||||
if not DoesEntityExist(vehicle) then return end
|
||||
return exports['LegacyFuel']:SetFuel(vehicle, fuel)
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('Renewed-Fuel') ~= 'started' then return end
|
||||
Fuel = {}
|
||||
|
||||
Fuel.GetFuel = function(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0.0 end
|
||||
return exports['Renewed-Fuel']:GetFuel(vehicle)
|
||||
end
|
||||
|
||||
Fuel.SetFuel = function(vehicle, fuel, type)
|
||||
if not DoesEntityExist(vehicle) then return end
|
||||
return exports['Renewed-Fuel']:SetFuel(vehicle, fuel)
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('cdn-fuel') ~= 'started' then return end
|
||||
Fuel = {}
|
||||
|
||||
Fuel.GetFuel = function(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0.0 end
|
||||
return exports['cdn-fuel']:GetFuel(vehicle)
|
||||
end
|
||||
|
||||
Fuel.SetFuel = function(vehicle, fuel, type)
|
||||
if not DoesEntityExist(vehicle) then return end
|
||||
return exports['cdn-fuel']:SetFuel(vehicle, fuel)
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
if GetResourceState('cdn-fuel') ~= 'started' then return end
|
||||
Fuel = {}
|
||||
|
||||
Fuel.GetFuel = function(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0.0 end
|
||||
return Entity(vehicle).state.fuel
|
||||
end
|
||||
|
||||
Fuel.SetFuel = function(vehicle, fuel, type)
|
||||
if not DoesEntityExist(vehicle) then return end
|
||||
local currentFuel = Entity(vehicle).state.fuel
|
||||
Entity(vehicle).state.fuel = currentFuel + fuel
|
||||
return Entity(vehicle).state.fuel
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('ps-fuel') ~= 'started' then return end
|
||||
Fuel = {}
|
||||
|
||||
Fuel.GetFuel = function(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0.0 end
|
||||
return exports['ps-fuel']:GetFuel(vehicle)
|
||||
end
|
||||
|
||||
Fuel.SetFuel = function(vehicle, fuel, type)
|
||||
if not DoesEntityExist(vehicle) then return end
|
||||
return exports['ps-fuel']:SetFuel(vehicle, fuel)
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
if GetResourceState('ti_fuel') ~= 'started' then return end
|
||||
Fuel = {}
|
||||
|
||||
Fuel.GetFuel = function(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0.0, type end
|
||||
local level, type = exports["ti_fuel"]:getFuel(vehicle)
|
||||
return level, type
|
||||
end
|
||||
|
||||
Fuel.SetFuel = function(vehicle, fuel, type)
|
||||
if not DoesEntityExist(vehicle) then return end
|
||||
return exports['ti_fuel']:setFuel(vehicle, fuel, type or "RON91")
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
if GetResourceState('x-fuel') ~= 'started' then return end
|
||||
Fuel = {}
|
||||
|
||||
Fuel.GetFuel = function(vehicle)
|
||||
if not DoesEntityExist(vehicle) then return 0.0, type end
|
||||
local level, type = exports["x-fuel"]:getFuel(vehicle)
|
||||
return level, type
|
||||
end
|
||||
|
||||
Fuel.SetFuel = function(vehicle, fuel, type)
|
||||
if not DoesEntityExist(vehicle) then return end
|
||||
return exports['x-fuel']:SetFuel(vehicle, fuel)
|
||||
end
|
||||
@@ -0,0 +1,291 @@
|
||||
|
||||
if GetResourceState('ox_lib') ~= 'started' and GetResourceState('qb-menu') ~= 'started' then return end
|
||||
-- {
|
||||
-- header = "Test",
|
||||
-- submitText = "Bill",
|
||||
-- inputs = {
|
||||
-- {
|
||||
-- text = "Citizen ID (#)", -- text you want to be displayed as a place holder
|
||||
-- name = "citizenid", -- name of the input should be unique otherwise it might override
|
||||
-- type = "text", -- type of the input
|
||||
-- isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted
|
||||
-- -- default = "CID-1234", -- Default text option, this is optional
|
||||
-- },
|
||||
-- {
|
||||
-- text = "Secret Code (Give to Nobody)", -- text you want to be displayed as a place holder
|
||||
-- name = "code", -- name of the input should be unique otherwise it might override
|
||||
-- type = "password", -- type of the input
|
||||
-- isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted
|
||||
-- -- default = "password123", -- Default text option, this is optional
|
||||
-- },
|
||||
-- {
|
||||
-- text = "Bill Price ($)", -- text you want to be displayed as a place holder
|
||||
-- name = "billprice", -- name of the input should be unique otherwise it might override
|
||||
-- type = "number", -- type of the input - number will not allow non-number characters in the field so only accepts 0-9
|
||||
-- isRequired = false, -- Optional [accepted values: true | false] but will submit the form if no value is inputted
|
||||
-- -- default = 1, -- Default number option, this is optional
|
||||
-- },
|
||||
-- {
|
||||
-- text = "Bill Type", -- text you want to be displayed as a input header
|
||||
-- name = "billtype", -- name of the input should be unique otherwise it might override
|
||||
-- type = "radio", -- type of the input - Radio is useful for "or" options e.g; billtype = Cash OR Bill OR bank
|
||||
-- options = { -- The options (in this case for a radio) you want displayed, more than 6 is not recommended
|
||||
-- { value = "bill", text = "Bill" }, -- Options MUST include a value and a text option
|
||||
-- { value = "cash", text = "Cash" }, -- Options MUST include a value and a text option
|
||||
-- { value = "bank", text = "Bank" } -- Options MUST include a value and a text option
|
||||
-- },
|
||||
-- -- default = "cash", -- Default radio option, must match a value from above, this is optional
|
||||
-- },
|
||||
-- {
|
||||
-- text = "Include Tax?", -- text you want to be displayed as a input header
|
||||
-- name = "taxincl", -- name of the input should be unique otherwise it might override
|
||||
-- type = "checkbox", -- type of the input - Check is useful for "AND" options e.g; taxincle = gst AND business AND othertax
|
||||
-- options = { -- The options (in this case for a check) you want displayed, more than 6 is not recommended
|
||||
-- { value = "gst", text = "10% incl."}, -- Options MUST include a value and a text option
|
||||
-- { value = "business", text = "35% incl.", checked = true }, -- Options MUST include a value and a text option, checked = true is default value, optional
|
||||
-- { value = "othertax", text = "15% incl."} -- Options MUST include a value and a text option
|
||||
-- }
|
||||
-- },
|
||||
-- {
|
||||
-- text = "Some Select", -- text you want to be displayed as a input header
|
||||
-- name = "someselect", -- name of the input should be unique otherwise it might override
|
||||
-- type = "select", -- type of the input - Select is useful for 3+ amount of "or" options e.g; someselect = none OR other OR other2 OR other3...etc
|
||||
-- options = { -- Select drop down options, the first option will by default be selected
|
||||
-- { value = "none", text = "None" }, -- Options MUST include a value and a text option
|
||||
-- { value = "other", text = "Other"}, -- Options MUST include a value and a text option
|
||||
-- { value = "other2", text = "Other2" }, -- Options MUST include a value and a text option
|
||||
-- { value = "other3", text = "Other3" }, -- Options MUST include a value and a text option
|
||||
-- { value = "other4", text = "Other4" }, -- Options MUST include a value and a text option
|
||||
-- { value = "other5", text = "Other5" }, -- Options MUST include a value and a text option
|
||||
-- { value = "other6", text = "Other6" }, -- Options MUST include a value and a text option
|
||||
-- },
|
||||
-- -- default = 'other3', -- Default select option, must match a value from above, this is optional
|
||||
-- }
|
||||
-- },
|
||||
-- })
|
||||
|
||||
-- local input = lib.inputDialog('Dialog title', {
|
||||
-- {type = 'input', label = 'Text input', description = 'Some input description', required = true, min = 4, max = 16},
|
||||
-- {type = 'number', label = 'Number input', description = 'Some number description', icon = 'hashtag'},
|
||||
-- {type = 'checkbox', label = 'Simple checkbox'},
|
||||
-- {type = 'color', label = 'Colour input', default = '#eb4034'},
|
||||
-- {type = 'date', label = 'Date input', icon = {'far', 'calendar'}, default = true, format = "DD/MM/YYYY"}
|
||||
-- })
|
||||
|
||||
|
||||
--QB types: text, password, number, radio, checkbox, select,
|
||||
--
|
||||
-- "input", "number", "checkbox", "select", "multi-select", "slider", "color", "date", "date-range", "time", "textarea",
|
||||
Input = {}
|
||||
|
||||
|
||||
-- ox to Qb
|
||||
function OxTypeToQBType(_type)
|
||||
if _type == "input" then
|
||||
return "text"
|
||||
elseif _type == "number" then
|
||||
return "number"
|
||||
elseif _type == "checkbox" then
|
||||
return "checkbox"
|
||||
elseif _type == "select" then
|
||||
return "select"
|
||||
elseif _type == "multi-select" then
|
||||
return "select"
|
||||
elseif _type == "slider" then
|
||||
return "number"
|
||||
elseif _type == "color" then
|
||||
return "text"
|
||||
elseif _type == "date" then
|
||||
return "date"
|
||||
elseif _type == "date-range" then
|
||||
return "date"
|
||||
elseif _type == "time" then
|
||||
return "time"
|
||||
elseif _type == "textarea" then
|
||||
return "text"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function OxToQBInput(data)
|
||||
local returnData = {}
|
||||
for i, v in pairs(data) do
|
||||
local input = {
|
||||
text = v.label,
|
||||
name = i,
|
||||
type = OxTypeToQBType(v.type),
|
||||
isRequired = v.required,
|
||||
placeholder = v.default,
|
||||
}
|
||||
if v.type == "select" then
|
||||
input.text = ""
|
||||
input.options = {
|
||||
{value = v.value, text = v.label}
|
||||
}
|
||||
elseif v.type == "checkbox" then
|
||||
input.text = ""
|
||||
input.options = {
|
||||
{value = v.value, text = v.label}
|
||||
}
|
||||
end
|
||||
table.insert(returnData, input)
|
||||
end
|
||||
return returnData
|
||||
end
|
||||
|
||||
-- qb to ox
|
||||
|
||||
function QBTypeToOxType(_type)
|
||||
if _type == "text" then
|
||||
return "input"
|
||||
elseif _type == "password" then
|
||||
return "input"
|
||||
elseif _type == "number" then
|
||||
return "number"
|
||||
elseif _type == "radio" then
|
||||
return "checkbox"
|
||||
elseif _type == "checkbox" then
|
||||
return "checkbox"
|
||||
elseif _type == "select" then
|
||||
return "select"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function QBToOxInput(data)
|
||||
local returnData = {}
|
||||
for i, v in pairs(data) do
|
||||
local input = {
|
||||
label = v.text,
|
||||
name = i,
|
||||
type = QBTypeToOxType(v.type),
|
||||
required = v.isRequired,
|
||||
default = v.placeholder,
|
||||
}
|
||||
if v.type == "select" then
|
||||
input.options = {}
|
||||
for i, v in pairs(v.options) do
|
||||
table.insert(input.options, {value = v.value, label = v.text})
|
||||
end
|
||||
elseif v.type == "checkbox" then
|
||||
for i, v in pairs(v.options) do
|
||||
table.insert(returnData, {value = v.value, label = v.text})
|
||||
end
|
||||
end
|
||||
table.insert(returnData, input)
|
||||
end
|
||||
return returnData
|
||||
end
|
||||
|
||||
--Open menu
|
||||
|
||||
function Input.Open(title, data, isQB, submitText)
|
||||
if isQB then
|
||||
local inputs = data.inputs
|
||||
if BridgeClientConfig.InputSystem == "ox" then
|
||||
return lib.inputDialog(title, QBToOxInput(inputs))
|
||||
elseif BridgeClientConfig.InputSystem == "qb" then
|
||||
return exports['qb-input']:ShowInput({
|
||||
header = title,
|
||||
submitText = submitText or "Submit",
|
||||
inputs = inputs
|
||||
})
|
||||
end
|
||||
else
|
||||
if BridgeClientConfig.InputSystem == "ox" then
|
||||
return lib.inputDialog(title, data)
|
||||
elseif BridgeClientConfig.InputSystem == "qb" then
|
||||
return exports['qb-input']:ShowInput({
|
||||
header = title,
|
||||
submitText = submitText or "Submit",
|
||||
inputs = OxToQBInput(data)
|
||||
})
|
||||
end
|
||||
end
|
||||
return id
|
||||
end
|
||||
|
||||
--[[
|
||||
-- Unit tests
|
||||
local thisIsQB = {
|
||||
header = "Test",
|
||||
submitText = "Bill",
|
||||
inputs = {
|
||||
{
|
||||
text = "Citizen ID (#)", -- text you want to be displayed as a place holder
|
||||
name = "citizenid", -- name of the input should be unique otherwise it might override
|
||||
type = "text", -- type of the input
|
||||
isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted
|
||||
-- default = "CID-1234", -- Default text option, this is optional
|
||||
},
|
||||
{
|
||||
text = "Secret Code (Give to Nobody)", -- text you want to be displayed as a place holder
|
||||
name = "code", -- name of the input should be unique otherwise it might override
|
||||
type = "password", -- type of the input
|
||||
isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted
|
||||
-- default = "password123", -- Default text option, this is optional
|
||||
},
|
||||
{
|
||||
text = "Bill Price ($)", -- text you want to be displayed as a place holder
|
||||
name = "billprice", -- name of the input should be unique otherwise it might override
|
||||
type = "number", -- type of the input - number will not allow non-number characters in the field so only accepts 0-9
|
||||
isRequired = false, -- Optional [accepted values: true | false] but will submit the form if no value is inputted
|
||||
-- default = 1, -- Default number option, this is optional
|
||||
},
|
||||
{
|
||||
text = "Bill Type", -- text you want to be displayed as a input header
|
||||
name = "billtype", -- name of the input should be unique otherwise it might override
|
||||
type = "radio", -- type of the input - Radio is useful for "or" options e.g; billtype = Cash OR Bill OR bank
|
||||
options = { -- The options (in this case for a radio) you want displayed, more than 6 is not recommended
|
||||
{ value = "bill", text = "Bill" }, -- Options MUST include a value and a text option
|
||||
{ value = "cash", text = "Cash" }, -- Options MUST include a value and a text option
|
||||
{ value = "bank", text = "Bank" } -- Options MUST include a value and a text option
|
||||
},
|
||||
-- default = "cash", -- Default radio option, must match a value from above, this is optional
|
||||
},
|
||||
{
|
||||
text = "Include Tax?", -- text you want to be displayed as a input header
|
||||
name = "taxincl", -- name of the input should be unique otherwise it might override
|
||||
type = "checkbox", -- type of the input - Check is useful for "AND" options e.g; taxincle = gst AND business AND othertax
|
||||
options = { -- The options (in this case for a check) you want displayed, more than 6 is not recommended
|
||||
{ value = "gst", text = "10% incl."}, -- Options MUST include a value and a text option
|
||||
{ value = "business", text = "35% incl.", checked = true }, -- Options MUST include a value and a text option, checked = true is default value, optional
|
||||
{ value = "othertax", text = "15% incl."} -- Options MUST include a value and a text option
|
||||
}
|
||||
},
|
||||
{
|
||||
text = "Some Select", -- text you want to be displayed as a input header
|
||||
name = "someselect", -- name of the input should be unique otherwise it might override
|
||||
type = "select", -- type of the input - Select is useful for 3+ amount of "or" options e.g; someselect = none OR other OR other2 OR other3...etc
|
||||
options = { -- Select drop down options, the first option will by default be selected
|
||||
{ value = "none", text = "None" }, -- Options MUST include a value and a text option
|
||||
{ value = "other", text = "Other"}, -- Options MUST include a value and a text option
|
||||
{ value = "other2", text = "Other2" }, -- Options MUST include a value and a text option
|
||||
{ value = "other3", text = "Other3" }, -- Options MUST include a value and a text option
|
||||
{ value = "other4", text = "Other4" }, -- Options MUST include a value and a text option
|
||||
{ value = "other5", text = "Other5" }, -- Options MUST include a value and a text option
|
||||
{ value = "other6", text = "Other6" }, -- Options MUST include a value and a text option
|
||||
},
|
||||
-- default = 'other3', -- Default select option, must match a value from above, this is optional
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
local thisIsOx = {
|
||||
{type = 'input', label = 'Text input', description = 'Some input description', required = true, min = 4, max = 16},
|
||||
{type = 'number', label = 'Number input', description = 'Some number description', icon = 'hashtag'},
|
||||
{type = 'checkbox', label = 'Simple checkbox'},
|
||||
{type = 'color', label = 'Colour input', default = '#eb4034'},
|
||||
{type = 'date', label = 'Date input', icon = {'far', 'calendar'}, default = true, format = "DD/MM/YYYY"}
|
||||
}
|
||||
|
||||
-- qb to ox
|
||||
RegisterCommand('inputtest1', function()
|
||||
Input.Open("Test", thisIsQB, true)
|
||||
end)
|
||||
|
||||
-- ox to qb
|
||||
RegisterCommand('inputtest2', function()
|
||||
Input.Open("Test", thisIsOx, false)
|
||||
end)
|
||||
--]]
|
||||
@@ -0,0 +1,21 @@
|
||||
if GetResourceState('codem-inventory') ~= 'started' then return end
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = exports['codem-inventory']:GetItemList()
|
||||
if not itemData[item] then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local imagePath = string.format("nui://codem-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,78 @@
|
||||
if GetResourceState('codem-inventory') ~= 'started' then return end
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.AddItem = function(src, item, count, slot, metadata)
|
||||
return exports['codem-inventory']:AddItem(src, item, count, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.RemoveItem = function(src, item, count, slot, metadata)
|
||||
if metadata == nil then
|
||||
return exports['codem-inventory']:RemoveItem(src, item, count, slot)
|
||||
else
|
||||
local items = exports['codem-inventory']:GetInventory(nil, src)
|
||||
for _, itemInfo in pairs(items) do
|
||||
if itemInfo.name == item then
|
||||
if itemInfo.info == metadata then
|
||||
return exports['codem-inventory']:RemoveItem(src, item, count, itemInfo.slot)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = exports['codem-inventory']:GetItemList()
|
||||
if not itemData[item] then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.GetItemCount = function(src, item, metadata)
|
||||
if metadata == nil then
|
||||
return exports['codem-inventory']:GetItemsTotalAmount(src, item)
|
||||
else
|
||||
local count = 0
|
||||
local items = exports['codem-inventory']:GetInventory(nil, src)
|
||||
for _, itemInfo in pairs(items) do
|
||||
if itemInfo.name == item and itemInfo.info == metadata then
|
||||
count = count + itemInfo.amount
|
||||
end
|
||||
return count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Inventory.GetInventoryItems = function(src)
|
||||
local items = exports['codem-inventory']:GetInventory(nil, src)
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(items) do
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.amount,
|
||||
metadata = v.info,
|
||||
slot = v.slot,
|
||||
})
|
||||
end
|
||||
return items
|
||||
end
|
||||
|
||||
Inventory.SetMetadata = function(src, item, slot, metadata)
|
||||
exports['codem-inventory']:SetItemMetadata(src, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords)
|
||||
TriggerEvent('codem-inventory:server:openstash', id, slots, weight, label)
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local imagePath = string.format("nui://codem-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,23 @@
|
||||
if GetResourceState('origen_inventory') ~= 'started' then return end
|
||||
local origen_inventory = exports.origen_inventory
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = origen_inventory:Items(item)
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable or {}
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("origen_inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://origen_inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
if GetResourceState('origen_inventory') ~= 'started' then return end
|
||||
local origen_inventory = exports.origen_inventory
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.AddItem = function(src, item, count, slot, metadata)
|
||||
if not origen_inventory:CanCarryItem(src, item, count) then
|
||||
return Bridge.notify.SendNotify(src, "Inventory Full", "error", 5000)
|
||||
end
|
||||
return origen_inventory:AddItem(src, item, count, nil, nil, metadata)
|
||||
end
|
||||
|
||||
Inventory.RemoveItem = function(src, item, count, slot, metadata)
|
||||
return origen_inventory:RemoveItem(src, item, count, metadata)
|
||||
end
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = origen_inventory:Items(item)
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable or {}
|
||||
end
|
||||
|
||||
Inventory.GetItemCount = function(src, item, metadata)
|
||||
if not metadata then
|
||||
return origen_inventory:GetItemTotalAmount(src, item)
|
||||
else
|
||||
local items = origen_inventory:GetInventory(src)
|
||||
local count = 0
|
||||
for _, itemInfo in pairs(items) do
|
||||
if itemInfo.name == item and itemInfo.info == metadata then
|
||||
count = count + itemInfo.amount
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
end
|
||||
|
||||
Inventory.GetPlayerInventory = function(src)
|
||||
local playerItems = origen_inventory:GetInventory(src)
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerItems) do
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.amount,
|
||||
metadata = v.info,
|
||||
slot = v.slot,
|
||||
})
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.CanCarryItem = function(src, item, count)
|
||||
return origen_inventory:CanCarryItems(src, item, count)
|
||||
end
|
||||
|
||||
Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords)
|
||||
return origen_inventory:RegisterStash(id, { label = label, slots = slots, weight = weight })
|
||||
end
|
||||
|
||||
Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords)
|
||||
return origen_inventory:OpenInventory(src, 'stash', id)
|
||||
end
|
||||
|
||||
Inventory.SetMetadata = function(src, item, slot, metadata)
|
||||
origen_inventory:SetItemMetadata(src, item, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("origen_inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://origen_inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,26 @@
|
||||
if GetResourceState('ox_inventory') ~= 'started' then return end
|
||||
local ox_inventory = exports.ox_inventory
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = ox_inventory:Items(item)
|
||||
if not itemData then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.stack or "true",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = (itemData.client and itemData.client.image) or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("ox_inventory", string.format("web/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://ox_inventory/web/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
|
||||
--Bridge.RegisterModule("Inventory", Inventory)
|
||||
@@ -0,0 +1,67 @@
|
||||
if GetResourceState('ox_inventory') ~= 'started' then return end
|
||||
|
||||
local ox_inventory = exports.ox_inventory
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.AddItem = function(src, item, count, slot, metadata)
|
||||
return ox_inventory:AddItem(src, item, count, metadata)
|
||||
end
|
||||
|
||||
Inventory.RemoveItem = function(src, item, count, slot, metadata)
|
||||
return ox_inventory:RemoveItem(src, item, count, metadata, slot)
|
||||
end
|
||||
|
||||
Inventory.GetItem = function(src, item, metadata)
|
||||
return ox_inventory:GetItem(src, item, metadata, false)
|
||||
end
|
||||
|
||||
Inventory.GetItemCount = function(src, item, metadata)
|
||||
return ox_inventory:GetItemCount(src, item, metadata, false)
|
||||
end
|
||||
|
||||
Inventory.GetPlayerInventory = function(src)
|
||||
return ox_inventory:GetInventoryItems(src, false)
|
||||
end
|
||||
|
||||
Inventory.CanCarryItem = function(src, item, count)
|
||||
return ox_inventory:CanCarryItem(src, item, count)
|
||||
end
|
||||
|
||||
Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords)
|
||||
return ox_inventory:RegisterStash(id, label, slots, weight, owner)
|
||||
end
|
||||
|
||||
Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords)
|
||||
TriggerClientEvent('ox_inventory:openInventory', src, 'stash', 'stash_' .. id)
|
||||
end
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = ox_inventory:Items(item)
|
||||
if not itemData then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.stack or "true",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.client.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.SetMetadata = function(src, item, slot, metadata)
|
||||
ox_inventory:SetMetadata(src, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.UpdatePlate = function(oldplate, newplate)
|
||||
ox_inventory:UpdateVehicle(oldplate, newplate)
|
||||
if GetResourceState('jg-mechanic') ~= 'started' then return end
|
||||
exports["jg-mechanic"]:vehiclePlateUpdated(oldplate, newplate)
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("ox_inventory", string.format("web/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://ox_inventory/web/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
if GetResourceState('ps-inventory') ~= 'started' then return end
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
RegisterNetEvent('community_bridge:client:ps-inventory:openStash', function(id, data)
|
||||
if source ~= 65535 then return end
|
||||
TriggerEvent('ps-inventory:client:SetCurrentStash', id)
|
||||
TriggerServerEvent('ps-inventory:server:OpenInventory', 'stash', id, { maxweight = data.weight, slots = data.slots })
|
||||
end)
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("ps-inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://ps-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
if GetResourceState('ps-inventory') ~= 'started' then return end
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords)
|
||||
return true
|
||||
end
|
||||
|
||||
Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords)
|
||||
TriggerClientEvent('community_bridge:client:ps-inventory:openStash', src, id, { label = label, maxweight = weight, slots = slots, })
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("ps-inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://ps-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
if GetResourceState('qb-inventory') ~= 'started' then return end
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
RegisterNetEvent('community_bridge:client:qb-inventory:openStash', function(id, data)
|
||||
if source ~= 65535 then return end
|
||||
TriggerEvent("inventory:client:SetCurrentStash", id)
|
||||
TriggerServerEvent('inventory:server:OpenInventory', 'stash', id, { maxweight = data.weight, slots = data.slots })
|
||||
end)
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("qb-inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://qb-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
if GetResourceState('qb-inventory') ~= 'started' then return end
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords)
|
||||
return true
|
||||
end
|
||||
|
||||
Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords)
|
||||
TriggerClientEvent('community_bridge:client:qb-inventory:openStash', src, id, { weight = weight, slots = slots })
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("qb-inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://qb-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,27 @@
|
||||
if GetResourceState('qs-inventory') ~= 'started' then return end
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.OpenStash = function(id)
|
||||
exports['qs-inventory']:RegisterStash(id, 50, 50000)
|
||||
end
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = exports['qs-inventory']:GetItemList()
|
||||
if not itemData[item] then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("qs-inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://qs-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,67 @@
|
||||
if GetResourceState('qs-inventory') ~= 'started' then return end
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.AddItem = function(src, item, count, slot, metadata)
|
||||
if not exports['qs-inventory']:CanCarryItem(src, item, count) then return false end
|
||||
return exports['qs-inventory']:AddItem(src, item, count, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.RemoveItem = function(src, item, count, slot, metadata)
|
||||
return exports['qs-inventory']:RemoveItem(src, item, count, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.GetItemCount = function(src, item, metadata)
|
||||
return exports['qs-inventory']:GetItemTotalAmount(src, item)
|
||||
end
|
||||
|
||||
Inventory.GetPlayerInventory = function(src)
|
||||
local playerItems = exports['qs-inventory']:GetInventory(src)
|
||||
local repackedTable = {}
|
||||
for _, v in pairs(playerItems) do
|
||||
table.insert(repackedTable, {
|
||||
name = v.name,
|
||||
count = v.amount,
|
||||
metadata = v.info,
|
||||
slot = v.slot,
|
||||
})
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.CanCarryItem = function(src, item, count)
|
||||
return exports['qs-inventory']:CanCarryItem(src, item, count)
|
||||
end
|
||||
|
||||
Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords)
|
||||
return true
|
||||
end
|
||||
|
||||
Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords)
|
||||
TriggerEvent("inventory:server:OpenInventory", "stash", id, { maxweight = weight, slots = slots })
|
||||
TriggerClientEvent("inventory:client:SetCurrentStash",src, id)
|
||||
end
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = exports['qs-inventory']:GetItemList()
|
||||
if not itemData[item] then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.SetMetadata = function(src, item, slot, metadata)
|
||||
return exports['qs-inventory']:SetItemMetadata(src, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local file = LoadResourceFile("qs-inventory", string.format("html/images/%s.png", item))
|
||||
local imagePath = file and string.format("nui://qs-inventory/html/images/%s.png", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,29 @@
|
||||
if GetResourceState('tgiann-inventory') ~= 'started' then return end
|
||||
local tgiann = exports["tgiann-inventory"]
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.OpenStash = function(id)
|
||||
-- open stash export... not sure what it is yet.
|
||||
end
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = tgiann:GetItemList()
|
||||
if not itemData[item] then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local pngPath = LoadResourceFile("inventory_images", string.format("html/images/%s.png", item))
|
||||
local webpPath = LoadResourceFile("inventory_images", string.format("html/images/%s.webp", item))
|
||||
local imagePath = pngPath and string.format("nui://inventory_images/html/images/%s.png", item) or webpPath and string.format("nui://inventory_images/html/images/%s.webp", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
if GetResourceState('tgiann-inventory') ~= 'started' then return end
|
||||
local tgiann = exports["tgiann-inventory"]
|
||||
|
||||
Inventory = Inventory or {}
|
||||
|
||||
Inventory.AddItem = function(src, item, count, slot, metadata)
|
||||
if not tgiann:CanCarryItem(src, item, count) then return false end
|
||||
local action = tgiann:AddItem(src, item, count, metadata)
|
||||
return (action.itemAddRemoveLog == 'added')
|
||||
end
|
||||
|
||||
Inventory.RemoveItem = function(src, item, count, slot, metadata)
|
||||
return tgiann:RemoveItem(src, item, count, nil, metadata)
|
||||
end
|
||||
|
||||
Inventory.GetItem = function(src, item, metadata)
|
||||
local item = tgiann:GetItemByName(src, item, metadata)
|
||||
item.count = item.amount
|
||||
item.metadata = item.info
|
||||
return item
|
||||
end
|
||||
|
||||
Inventory.GetItemCount = function(src, item, metadata)
|
||||
local _item = tgiann:GetItemByName(src, item, metadata)
|
||||
return _item.amount or 0
|
||||
end
|
||||
|
||||
Inventory.GetInventoryItems = function(src)
|
||||
return tgiann:GetPlayerItems(src)
|
||||
end
|
||||
|
||||
Inventory.CanCarryItem = function(src, item, count)
|
||||
return tgiann:CanCarryItem(src, item, count)
|
||||
end
|
||||
|
||||
Inventory.RegisterStash = function(id, label, slots, weight, owner)
|
||||
return tgiann:CreateCustomStashWithItem(id, {})
|
||||
end
|
||||
|
||||
Inventory.GetItemInfo = function(item)
|
||||
local itemData = tgiann:GetItemList()
|
||||
if not itemData[item] then return {} end
|
||||
local repackedTable = {
|
||||
name = itemData.name or "Missing Name",
|
||||
label = itemData.label or "Missing Label",
|
||||
stack = itemData.unique or "false",
|
||||
weight = itemData.weight or "0",
|
||||
description = itemData.description or "none",
|
||||
image = itemData.image or Inventory.GetImagePath(item),
|
||||
}
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
Inventory.SetMetadata = function(src, item, slot, metadata)
|
||||
tgiann:UpdateItemMetadata(src, item, slot, metadata)
|
||||
end
|
||||
|
||||
Inventory.GetImagePath = function(item)
|
||||
local pngPath = LoadResourceFile("inventory_images", string.format("html/images/%s.png", item))
|
||||
local webpPath = LoadResourceFile("inventory_images", string.format("html/images/%s.webp", item))
|
||||
local imagePath = pngPath and string.format("nui://inventory_images/html/images/%s.png", item) or webpPath and string.format("nui://inventory_images/html/images/%s.webp", item)
|
||||
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
if GetResourceState('MrNewbVehicleKeys') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
if not DoesEntityExist(vehicle) then return false end
|
||||
return exports.MrNewbVehicleKeys:GiveKeys(vehicle)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
if not vehicle and not plate then return false end
|
||||
if not DoesEntityExist(vehicle) then
|
||||
return exports.MrNewbVehicleKeys:RemoveKeysByPlate(plate)
|
||||
end
|
||||
return exports.MrNewbVehicleKeys:RemoveKeys(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('Renewed-Vehiclekeys') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
if not DoesEntityExist(vehicle) then return false end
|
||||
return exports['Renewed-Vehiclekeys']:addKey(plate)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
if not DoesEntityExist(vehicle) then return false end
|
||||
return exports['Renewed-Vehiclekeys']:removeKey(plate)
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
if GetResourceState('cd_garage') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
TriggerEvent('cd_garage:AddKeys', plate)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('mk_vehiclekeys') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
if not DoesEntityExist(vehicle) then return false end
|
||||
return exports["mk_vehiclekeys"]:AddKey(vehicle)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
if not DoesEntityExist(vehicle) then return false end
|
||||
return exports["mk_vehiclekeys"]:RemoveKey(vehicle)
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
if GetResourceState('okokGarage') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
TriggerServerEvent('okokGarage:GiveKeys', plate)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
if GetResourceState('qb-vehiclekeys') ~= 'started' then return end
|
||||
if GetResourceState('qbx_vehiclekeys') == 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
if GetResourceState('qbx_vehiclekeys') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('qs-vehiclekeys') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
local model = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle))
|
||||
local verifiedPlate = GetVehicleNumberPlateText(vehicle)
|
||||
exports['qs-vehiclekeys']:GiveKeys(verifiedPlate, model, true)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
if GetResourceState('t1ger_keys') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
if not DoesEntityExist(vehicle) then return false end
|
||||
local vehicle_display_name = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle))
|
||||
return exports['t1ger_keys']:GiveTemporaryKeys(plate, vehicle_display_name, 'some_keys')
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
if GetResourceState('wasabi_carlock') ~= 'started' then return end
|
||||
VehicleKeys = {}
|
||||
|
||||
VehicleKeys.GiveKeys = function(vehicle, plate)
|
||||
exports.wasabi_carlock:GiveKey(plate)
|
||||
end
|
||||
|
||||
VehicleKeys.RemoveKeys = function(vehicle, plate)
|
||||
exports.wasabi_carlock:RemoveKey(plate)
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
local ConvarLang = GetConvar("lang", "none")
|
||||
local OXLang = GetConvar("ox:locale", "none")
|
||||
local QBXLang = GetConvar("qb_locale", "none")
|
||||
local txLang = GetConvar("txAdmin-locale", "none")
|
||||
local esxLang = GetConvar("esx:locale", "none")
|
||||
|
||||
BridgeSharedConfig = Require("settings/sharedConfig.lua")
|
||||
|
||||
Lang = ConvarLang ~= "none" and
|
||||
ConvarLang or BridgeSharedConfig.Lang ~= "auto" and BridgeSharedConfig.Lang or
|
||||
OXLang ~= "none" and OXLang or
|
||||
QBXLang ~= "none" and QBXLang or
|
||||
txLang ~= "none" and txLang or
|
||||
esxLang ~= "none" and esxLang or
|
||||
"en"
|
||||
|
||||
Language = {}
|
||||
|
||||
function Language.Locale(str, ...)
|
||||
local resource = GetInvokingResource() or GetCurrentResourceName()
|
||||
assert(resource, "Resource name not found")
|
||||
print(resource, "locales/" .. Lang .. ".json")
|
||||
local locales = LoadResourceFile(resource, "locales/" .. Lang .. ".json")
|
||||
print(locales, Lang)
|
||||
locales = locales and json.decode(locales) or {}
|
||||
local locale = locales[str]
|
||||
|
||||
if not locale then
|
||||
warn("Locale not found for language: " .. Lang)
|
||||
return str
|
||||
end
|
||||
|
||||
local args = {...}
|
||||
if #args > 0 then
|
||||
for i = 1, #args do
|
||||
locale = locale:gsub('{' .. i .. '}', args[i])
|
||||
end
|
||||
end
|
||||
|
||||
return locale
|
||||
end
|
||||
|
||||
if BridgeSharedConfig.DebugLevel == 3 then
|
||||
-- if outside this resource, use local whatever = Require("modules/locales/shared.lua")
|
||||
-- whatever.Locales("some-index-in-language-.json-file")
|
||||
-- Files must be stored in "locales" folder, within the resource.
|
||||
-- Instead of using Require you can also import it via the manifest.
|
||||
-- The Lang variable is available globally, which tells you what the server is using.
|
||||
print("Language: ", Lang)
|
||||
print("Locale: ", Language.Locale("locale-unit-test"))
|
||||
|
||||
-- Example outside community bridge resource:
|
||||
|
||||
-- local Language = Require('modules/locales/shared.lua')
|
||||
-- print("Language: ", Lang)
|
||||
-- print("Locale: ", Language.Locale("locale-unit-test"))
|
||||
end
|
||||
|
||||
return Language
|
||||
@@ -0,0 +1,14 @@
|
||||
if GetResourceState('Renewed-Banking') ~= 'started' then return end
|
||||
Managment = {}
|
||||
|
||||
Managment.GetAccountMoney = function(account)
|
||||
return exports['Renewed-Banking']:getAccountMoney(account)
|
||||
end
|
||||
|
||||
Managment.AddAccountMoney = function(account, amount)
|
||||
return exports['Renewed-Banking']:addAccountMoney(account, amount)
|
||||
end
|
||||
|
||||
Managment.RemoveAccountMoney = function(account, amount)
|
||||
return exports['Renewed-Banking']:removeAccountMoney(account, amount)
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
if GetResourceState('okokBanking') ~= 'started' then return end
|
||||
Managment = {}
|
||||
|
||||
Managment.GetAccountMoney = function(account)
|
||||
return exports['okokBanking']:GetAccount(account)
|
||||
end
|
||||
|
||||
Managment.AddAccountMoney = function(account, amount)
|
||||
return exports['okokBanking']:AddMoney(account, amount)
|
||||
end
|
||||
|
||||
Managment.RemoveAccountMoney = function(account, amount)
|
||||
return exports['okokBanking']:RemoveMoney(account, amount)
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
if GetResourceState('qb-banking') ~= 'started' then return end
|
||||
Managment = {}
|
||||
|
||||
Managment.GetAccountMoney = function(account)
|
||||
return exports['qb-banking']:GetAccountBalance(account)
|
||||
end
|
||||
|
||||
Managment.AddAccountMoney = function(account, amount)
|
||||
return exports['qb-banking']:AddMoney(account, amount)
|
||||
end
|
||||
|
||||
Managment.RemoveAccountMoney = function(account, amount)
|
||||
return exports['qb-banking']:RemoveMoney(account, amount)
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
---@class Math
|
||||
------@field public name string @add name field to class Car, you'll see it in code completion
|
||||
Math = {}
|
||||
|
||||
--- If the value is less than the minimum, it will return the minimum.
|
||||
--- If the value is greater than the maximum, it will return the maximum.
|
||||
--- Otherwise, it will return the value.
|
||||
---@param value number: The value to clamp.
|
||||
---@param min number: The minimum value.
|
||||
---@param max number: The maximum value.
|
||||
---@return number: The clamped value.
|
||||
function Math.Clamp(value, min, max)
|
||||
if value < min then
|
||||
return min
|
||||
elseif value > max then
|
||||
return max
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
--- Rounds a number to the nearest whole number.
|
||||
---@param value number: The value to round.
|
||||
---@return number: The rounded value.
|
||||
function Math.Round(value)
|
||||
return math.floor(value + 0.5)
|
||||
end
|
||||
|
||||
function Math.Truncate(value, decimals)
|
||||
local mul = decimals and (10 ^ decimals) or 1
|
||||
if value < 0 then
|
||||
return math.ceil(value * mul) / mul
|
||||
else
|
||||
return math.floor(value * mul) / mul
|
||||
end
|
||||
end
|
||||
|
||||
--- Warps the number around from max to min and vice versa.
|
||||
---@param value number: The value to wrap.
|
||||
---@param min number: The minimum value.
|
||||
---@param max number: The maximum value.
|
||||
---@return number: The wrapped value.
|
||||
function Math.Wrap(value, min, max)
|
||||
local range = max - min
|
||||
return (value - min) % range + min
|
||||
end
|
||||
|
||||
--- Gets an interpolated value between two numbers.
|
||||
---@see https://en.wikipedia.org/wiki/Smoothstep
|
||||
---@param value number The interpolation value.
|
||||
---@param min number : The minimum value.
|
||||
---@param max number : The maximum value.
|
||||
---@return number The interpolated value.
|
||||
function Math.Smooth(value, min, max)
|
||||
value = Math.Clamp((value - min) / (max - min), 0, 1)
|
||||
return value * value * (3 - 2 * value)
|
||||
end
|
||||
|
||||
--- Maps a value from one range to another.
|
||||
---@param value number The value to map.
|
||||
---@param inMin number The minimum value for the provided value.
|
||||
---@param inMax number The maximum value for the provided value.
|
||||
---@param outMin number The minimum value for the output.
|
||||
---@param outMax number The maximum value for the output.
|
||||
function Math.Map(value, inMin, inMax, outMin, outMax)
|
||||
return (value - inMin) / (inMax - inMin) * (outMax - outMin) + outMin
|
||||
end
|
||||
@@ -0,0 +1,207 @@
|
||||
local Menus = {}
|
||||
Menu = {}
|
||||
|
||||
if GetResourceState('ox_lib') ~= 'started' and GetResourceState('qb-menu') ~= 'started' then return end
|
||||
|
||||
--- Converts a QB menu to an Ox menu.
|
||||
---@param id string The menu ID.
|
||||
---@param menu table The QB menu data.
|
||||
---@return table The Ox menu data.
|
||||
function QBToOxMenu(id, menu)
|
||||
local oxMenu = {
|
||||
id = id,
|
||||
title = "",
|
||||
canClose = true,
|
||||
options = {},
|
||||
}
|
||||
for i, v in pairs(menu) do
|
||||
if v.isMenuHeader then
|
||||
if oxMenu.title == "" then
|
||||
oxMenu.title = v.header
|
||||
end
|
||||
else
|
||||
local option = {
|
||||
title = v.header,
|
||||
description = v.txt,
|
||||
icon = v.icon,
|
||||
args = v.params.args,
|
||||
onSelect = function(selected, secondary, args)
|
||||
local params = menu[id]?.options?[selected]?.params
|
||||
if not params then return end
|
||||
local event = params.event
|
||||
local isServer = params.isServer
|
||||
if not event then return end
|
||||
if isServer then
|
||||
return TriggerServerEvent(event, args)
|
||||
end
|
||||
return TriggerEvent(event, args)
|
||||
end
|
||||
|
||||
}
|
||||
table.insert(oxMenu.options, option)
|
||||
end
|
||||
end
|
||||
return oxMenu
|
||||
end
|
||||
|
||||
--- Converts an Ox menu to a QB menu.
|
||||
---@param id string The menu ID.
|
||||
---@param menu table The Ox menu data.
|
||||
---@return table The QB menu data.
|
||||
function OxToQBMenu(id, menu)
|
||||
local qbMenu = {
|
||||
{
|
||||
header = menu.title,
|
||||
isMenuHeader = true,
|
||||
}
|
||||
}
|
||||
for i, v in pairs(menu.options) do
|
||||
local button = {
|
||||
header = v.title,
|
||||
txt = v.description,
|
||||
icon = v.icon,
|
||||
}
|
||||
|
||||
if v.onSelect and type(v.onSelect) == 'function' then
|
||||
button.params = {
|
||||
event = "community_bridge:client:MenuCallback",
|
||||
args = {id = id, selected = i, args = v.args, onSelect = v.onSelect},
|
||||
}
|
||||
end
|
||||
table.insert(qbMenu, button)
|
||||
end
|
||||
return qbMenu
|
||||
end
|
||||
|
||||
--- Opens a menu based on the configuration.
|
||||
---@param data table The menu data.
|
||||
---@param useQb boolean Whether to use QB menu syntax.
|
||||
---@return id string The menu ID.
|
||||
function Menu.Open(data, useQb)
|
||||
--local id = data.id or CreateUniqueId(Menus)
|
||||
local id = data.id or Ids.CreateUniqueId(Menus, nil, nil)
|
||||
local menuExists = Menus[id]
|
||||
if useQb then
|
||||
if BridgeClientConfig.MenuSystem == "ox" then
|
||||
if not menuExists then
|
||||
Menus[id] = QBToOxMenu(id, data)
|
||||
lib.registerContext(Menus[id])
|
||||
end
|
||||
return lib.showContext(id)
|
||||
elseif BridgeClientConfig.MenuSystem == "qb" then
|
||||
Menus[id] = data
|
||||
return exports['qb-menu']:openMenu(Menus[id])
|
||||
end
|
||||
else
|
||||
if BridgeClientConfig.MenuSystem == "ox" then
|
||||
if not menuExists then
|
||||
Menus[id] = data
|
||||
lib.registerContext(Menus[id])
|
||||
end
|
||||
return lib.showContext(id)
|
||||
elseif BridgeClientConfig.MenuSystem == "qb" then
|
||||
Menus[id] = OxToQBMenu(id, data)
|
||||
return exports['qb-menu']:openMenu(Menus[id])
|
||||
end
|
||||
end
|
||||
return id
|
||||
end
|
||||
|
||||
--- Event to handle callback from menu selection.
|
||||
--- @param _args table The arguments passed to the callback.
|
||||
--- @return nil
|
||||
RegisterNetEvent('community_bridge:client:MenuCallback', function(_args)
|
||||
local id = _args.id
|
||||
local onSelect = _args.onSelect
|
||||
local args = _args.args
|
||||
if not Menus[id] then return end
|
||||
onSelect({number=_args.selected}, false, args)
|
||||
end)
|
||||
|
||||
|
||||
--[[
|
||||
|
||||
--Unit Tests
|
||||
local qbMenu = {
|
||||
{
|
||||
header = 'QBCore Test Menu',
|
||||
icon = 'fas fa-code',
|
||||
isMenuHeader = true, -- Set to true to make a nonclickable title
|
||||
},
|
||||
{
|
||||
header = 'First Button',
|
||||
txt = 'Open a secondary menu!',
|
||||
icon = 'fas fa-code-pull-request',
|
||||
-- disabled = false, -- optional, non-clickable and grey scale
|
||||
-- hidden = true, -- optional, hides the button completely
|
||||
params = {
|
||||
-- isServer = false, -- optional, specify event type
|
||||
event = 'community_bridge:client:TestEvent',
|
||||
args = {
|
||||
number = 1,
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
header = 'Second Button',
|
||||
txt = 'Open a secondary menu!',
|
||||
icon = 'fas fa-code-pull-request',
|
||||
params = {
|
||||
event = 'community_bridge:client:TestEvent',
|
||||
args = {
|
||||
number = 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local oxMenu = {
|
||||
id = "test",
|
||||
title = "Test Menu",
|
||||
options = {
|
||||
{
|
||||
title = "First Button",
|
||||
description = "Open a secondary menu!",
|
||||
icon = "fas fa-code-pull-request",
|
||||
args = {
|
||||
number = 1,
|
||||
},
|
||||
onSelect = function(selected, secondary, args)
|
||||
print("Selected", json.encode(selected))
|
||||
end
|
||||
},
|
||||
{
|
||||
title = "Second Button",
|
||||
description = "Open a secondary menu!",
|
||||
icon = "fas fa-code-pull-request",
|
||||
args = {
|
||||
number = 2,
|
||||
},
|
||||
onSelect = function(selected, secondary, args)
|
||||
print("Selected", json.encode(selected))
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegisterCommand("testmenu-qbtoox", function()
|
||||
Menu.Open(qbMenu, true)
|
||||
end)
|
||||
|
||||
RegisterCommand("testmenu-oxtoqb", function()
|
||||
Menu.Open(oxMenu, false)
|
||||
end)
|
||||
|
||||
RegisterCommand("testmenu-oxtoox", function()
|
||||
Menu.Open(oxMenu, false)
|
||||
end)
|
||||
|
||||
RegisterCommand("testmenu-qbtoqb", function()
|
||||
Menu.Open(qbMenu, true)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('community_bridge:client:TestEvent', function(args)
|
||||
print("Test Event", json.encode(args))
|
||||
end)
|
||||
|
||||
--]]
|
||||
@@ -0,0 +1,66 @@
|
||||
function InternalNotify(message, type, time)
|
||||
if BridgeClientConfig == nil or BridgeClientConfig.NotifySystem == nil then return Prints.error("You have not configured a compatable notify in community_bridge") end
|
||||
local notifyType = BridgeClientConfig.NotifySystem
|
||||
time = time or 3000
|
||||
if notifyType == 'qb' then
|
||||
return TriggerEvent('QBCore:Notify', message, 'primary', time)
|
||||
elseif notifyType == 'mythic_notify' then
|
||||
return exports['mythic_notify']:SendAlert('inform', message, time)
|
||||
elseif notifyType == 'pNotify' then
|
||||
return exports['pNotify']:SendNotification({ text = message, type = type, timeout = time, layout = 'centerRight' })
|
||||
elseif notifyType == 'esx_notify' then
|
||||
return ESX.ShowNotification(message, type, time)
|
||||
elseif notifyType == 'ox' then
|
||||
return exports.ox_lib:notify({ description = message, type = type, position = 'top' })
|
||||
elseif notifyType == 't-notify' then
|
||||
return exports['t-notify']:Alert({ style = 'info', message = message, duration = time, })
|
||||
elseif notifyType == 'wasabi_notify' then
|
||||
return exports.wasabi_notify:notify(type, message, time, type)
|
||||
elseif notifyType == 'lab' then
|
||||
return exports['swe-notify']:SendNotification(message, time, type)
|
||||
elseif notifyType == 'custom' then
|
||||
return Prints.error("You have not set up a custom notify in community_bridge")
|
||||
else
|
||||
return Prints.error("You have not configured a notify in community_bridge")
|
||||
end
|
||||
end
|
||||
|
||||
function InternalShowHelpText(message, position)
|
||||
if BridgeClientConfig == nil or BridgeClientConfig.ShowHelpText == nil then return Prints.error("You have not configured a compatable helptext in community_bridge") end
|
||||
local helptextType = BridgeClientConfig.ShowHelpText
|
||||
if helptextType == 'ox' then
|
||||
return exports.ox_lib:showTextUI(message, { position = 'left-center' })
|
||||
elseif helptextType == 'jg' then
|
||||
return exports['jg-textui']:DrawText(message)
|
||||
elseif helptextType == 'qb' then
|
||||
return exports['qb-core']:DrawText(message, 'left')
|
||||
elseif helptextType == 'lab' then
|
||||
return exports['lab-HintUI']:Show(message, "Hint Text")
|
||||
elseif helptextType == 'custom' then
|
||||
return Prints.error("You have not set up a custom ShowHelpText in community_bridge")
|
||||
else
|
||||
return Prints.error("You have not configured a ShowHelpText in community_bridge")
|
||||
end
|
||||
end
|
||||
|
||||
function InternalHideHelpText()
|
||||
if BridgeClientConfig == nil or BridgeClientConfig.ShowHelpText == nil then return Prints.error("You have not configured a compatable helptext in community_bridge") end
|
||||
local helptextType = BridgeClientConfig.ShowHelpText
|
||||
if helptextType == 'ox' then
|
||||
return exports.ox_lib:hideTextUI()
|
||||
elseif helptextType == 'jg' then
|
||||
return exports['jg-textui']:HideText()
|
||||
elseif helptextType == 'qb' then
|
||||
return exports['qb-core']:HideText()
|
||||
elseif helptextType == 'lab' then
|
||||
return exports['lab-HintUI']:Hide()
|
||||
elseif helptextType == 'custom' then
|
||||
return Prints.error("You have not set up a custom HideHelpText in community_bridge")
|
||||
else
|
||||
return Prints.error("You have not configured a HideHelpText in community_bridge")
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent('community_bridge:Client:Notify', function(message, type, time)
|
||||
InternalNotify(message, type, time)
|
||||
end)
|
||||
@@ -0,0 +1,5 @@
|
||||
Notify = {}
|
||||
|
||||
Notify.SendNotify = function(src, message, type, time)
|
||||
TriggerClientEvent('community_bridge:Client:Notify', src, message, type, time)
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
if GetResourceState('gksphone') ~= 'started' then return end
|
||||
Phones = {}
|
||||
|
||||
Phones.SendEmail = function(email, title, message)
|
||||
return exports["gksphone"]:SendNewMail({ sender = email, image = '/html/static/img/icons/mail.png', subject = title, message = message })
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
if GetResourceState('gksphone') ~= 'started' then return end
|
||||
Phones = {}
|
||||
|
||||
Phones.GetPlayerPhone = function(src)
|
||||
return exports["gksphone"]:GetPhoneBySource(src) or false
|
||||
end
|
||||
|
||||
Phones.SendEmail = function(src, email, title, message)
|
||||
local data = {}
|
||||
data.sender = email
|
||||
data.image = '/html/static/img/icons/mail.png'
|
||||
data.subject = title
|
||||
data.message = message
|
||||
exports["gksphone"]:SendNewMail(src, data)
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
if GetResourceState('lb-phone') ~= 'started' then return end
|
||||
Phones = {}
|
||||
|
||||
Phones.SendEmail = function(email, title, message)
|
||||
TriggerServerEvent('community_bridge:Server:genericEmail', {email = email, title = title, message = message})
|
||||
end
|
||||
@@ -0,0 +1,26 @@
|
||||
if GetResourceState('lb-phone') ~= 'started' then return end
|
||||
Phones = {}
|
||||
|
||||
Phones.GetPlayerPhone = function(src)
|
||||
return exports["lb-phone"]:GetEquippedPhoneNumber(src) or false
|
||||
end
|
||||
|
||||
Phones.SendEmail = function(src, email, title, message)
|
||||
local numberNumber = exports["lb-phone"]:GetEquippedPhoneNumber(src)
|
||||
if not numberNumber then return false, print("Could not Find Phone number") end
|
||||
local playerEmail = exports["lb-phone"]:GetEmailAddress(numberNumber)
|
||||
if not playerEmail then return false, print("Could not Find email") end
|
||||
local success, id = exports["lb-phone"]:SendMail({
|
||||
to = playerEmail,
|
||||
sender = email,
|
||||
subject = title,
|
||||
message = message,
|
||||
})
|
||||
return success
|
||||
end
|
||||
|
||||
RegisterNetEvent('community_bridge:Server:genericEmail', function(data)
|
||||
local src = source
|
||||
print('community_bridge:Server:genericEmail Hit')
|
||||
return Phones.SendEmail(src, data.email, data.title, data.message)
|
||||
end)
|
||||
@@ -0,0 +1,11 @@
|
||||
if GetResourceState('qs-smartphone') ~= 'started' then return end
|
||||
Phones = {}
|
||||
|
||||
Phones.SendEmail = function(email, title, message)
|
||||
return TriggerServerEvent('qs-smartphone:server:sendNewMail', { sender = email, subject = title, message = message, button = {} })
|
||||
end
|
||||
|
||||
RegisterNetEvent('community_bridge:Server:genericEmail', function(data)
|
||||
TriggerServerEvent('qs-smartphone:server:sendNewMail', { sender = data.email, subject = data.title, message = data.message, button = {} })
|
||||
return true
|
||||
end)
|
||||
@@ -0,0 +1,11 @@
|
||||
if GetResourceState('qs-smartphone') ~= 'started' then return end
|
||||
Phones = {}
|
||||
|
||||
Phones.GetPlayerPhone = function(src)
|
||||
return exports['qs-base']:GetPlayerPhone(src) or false
|
||||
end
|
||||
|
||||
Phones.SendEmail = function(src, email, title, message)
|
||||
TriggerClientEvent('community_bridge:Server:genericEmail', src, { sender = email, subject = title, message = message, button = {} })
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
Points = {}
|
||||
local ActivePoints = {}
|
||||
|
||||
Points.RegisterPoint = function(pointCoords, pointDistance, pointOnEnter, pointOnExit)
|
||||
local enterZone = lib.points.new({
|
||||
coords = pointCoords,
|
||||
distance = pointDistance,
|
||||
onEnter = function(self)
|
||||
pointOnEnter(self)
|
||||
end,
|
||||
onExit = function(self)
|
||||
pointOnExit(self)
|
||||
end,
|
||||
})
|
||||
local pointID = Ids.CreateUniqueId(nil, 5, nil)
|
||||
ActivePoints[pointID] = enterZone
|
||||
return enterZone, pointID
|
||||
end
|
||||
|
||||
-- Function to retrieve the enterZone using pointID
|
||||
Points.GetPointById = function(pointID)
|
||||
return ActivePoints[pointID]
|
||||
end
|
||||
|
||||
Points.RemovePoint = function(pointID)
|
||||
local point = ActivePoints[pointID]
|
||||
if point then
|
||||
print("Removing point with ID " .. pointID)
|
||||
point:remove() -- Call the remove method on the point (ensure this method stops all event listeners)
|
||||
ActivePoints[pointID] = nil -- Remove from ActivePoints table
|
||||
print("Point removed successfully.")
|
||||
return true
|
||||
else
|
||||
print("Point with ID " .. pointID .. " not found.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
if BridgeClientConfig.ProgressBar ~= "ox" then return end
|
||||
ProgressBar = {}
|
||||
local _progBarType = BridgeClientConfig.ProgressBarStyle or "bar"
|
||||
|
||||
ProgressBar.StartProgressBar = function(time, label, whiledead, cancancel, disable, animTable, successAction, canceledAction)
|
||||
local runTime = time or 10000
|
||||
local textLabel = label or "Doing something"
|
||||
local deadBool = whiledead or false
|
||||
local cancelBool = cancancel or false
|
||||
local disableKeys = disable or { move = true, sprint = true, car = true, combat = true, }
|
||||
local anim = animTable or nil
|
||||
local success = successAction or function() print("Success") end
|
||||
local canceled = canceledAction or function() print("Cancelled") end
|
||||
if _progBarType == "bar" then
|
||||
if exports.ox_lib:progressBar({
|
||||
duration = runTime,
|
||||
label = textLabel,
|
||||
useWhileDead = deadBool,
|
||||
canCancel = cancelBool,
|
||||
disable = disableKeys,
|
||||
anim = anim,
|
||||
}) then success() else canceled() end
|
||||
elseif _progBarType == "circle" then
|
||||
if exports.ox_lib:progressCircle({
|
||||
duration = runTime,
|
||||
label = textLabel,
|
||||
position = 'bottom',
|
||||
useWhileDead = deadBool,
|
||||
canCancel = cancelBool,
|
||||
disable = disableKeys,
|
||||
anim = anim,
|
||||
}) then success() else canceled() end
|
||||
end
|
||||
end
|
||||
|
||||
ProgressBar.IsProgressBarActive = function()
|
||||
return exports.ox_lib:progressActive()
|
||||
end
|
||||
@@ -0,0 +1,60 @@
|
||||
if BridgeClientConfig.ProgressBar ~= "qb" then return end
|
||||
ProgressBar = {}
|
||||
|
||||
local function convertOxToQB(disabledTable, animTable)
|
||||
local repackedTable = { disabled = {}, animations = {}}
|
||||
for _, v in pairs(disabledTable) do
|
||||
if v.move then
|
||||
repackedTable.disabled.disableMovement = v.move
|
||||
end
|
||||
if v.car then
|
||||
repackedTable.disabled.disableCarMovement = v.car
|
||||
end
|
||||
if v.combat then
|
||||
repackedTable.disabled.disableCombat = v.combat
|
||||
end
|
||||
if v.mouse then
|
||||
repackedTable.disabled.disableMouse = v.mouse
|
||||
end
|
||||
end
|
||||
for _, v in pairs(animTable) do
|
||||
if v.dict then
|
||||
repackedTable.animations.animDict = v.animDict
|
||||
end
|
||||
if v.clip then
|
||||
repackedTable.animations.anim = v.anim
|
||||
end
|
||||
end
|
||||
return repackedTable
|
||||
end
|
||||
|
||||
ProgressBar.StartProgressBar = function(time, label, whiledead, cancancel, disable, animTable, successAction, canceledAction)
|
||||
local runTime = time or 10000
|
||||
local textLabel = label or "Doing something"
|
||||
local deadBool = whiledead or false
|
||||
local cancelBool = cancancel or false
|
||||
local success = successAction or function() print("Success") end
|
||||
local canceled = canceledAction or function() print("Cancelled") end
|
||||
local repackedTable = convertOxToQB(disable, animTable)
|
||||
exports['progressbar']:Progress({
|
||||
name = "random_task",
|
||||
duration = runTime,
|
||||
label = textLabel,
|
||||
useWhileDead = deadBool,
|
||||
canCancel = cancelBool,
|
||||
controlDisables = repackedTable.disabled,
|
||||
animation = repackedTable.animations,
|
||||
prop = {},
|
||||
propTwo = {}
|
||||
}, function(cancelled)
|
||||
if not cancelled then
|
||||
success()
|
||||
else
|
||||
canceled()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
ProgressBar.IsProgressBarActive = function()
|
||||
return exports["progressbar"]:isDoingSomething()
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
Stashes = {}
|
||||
|
||||
-- Needs Redone
|
||||
@@ -0,0 +1,72 @@
|
||||
if GetResourceState('ox_target') ~= 'started' then return end
|
||||
|
||||
local targetDebug = false
|
||||
local function detectDebugEnabled()
|
||||
if BridgeClientConfig.DebugLevel == 3 then
|
||||
targetDebug = true
|
||||
end
|
||||
end
|
||||
|
||||
detectDebugEnabled()
|
||||
|
||||
local ox_target = exports.ox_target
|
||||
local targetZones = {}
|
||||
|
||||
Target = {}
|
||||
|
||||
Target.AddGlobalPlayer = function(options)
|
||||
ox_target:addGlobalPlayer(options)
|
||||
end
|
||||
|
||||
Target.AddLocalEntity = function(entities, options)
|
||||
ox_target:addLocalEntity(entities, options)
|
||||
end
|
||||
|
||||
Target.AddModel = function(models, options)
|
||||
ox_target:addModel(models, options)
|
||||
end
|
||||
|
||||
Target.AddBoxZone = function(name, coords, size, heading, options)
|
||||
local target = ox_target:addBoxZone({
|
||||
coords = coords,
|
||||
size = size,
|
||||
rotation = heading,
|
||||
debug = targetDebug,
|
||||
options = options,
|
||||
})
|
||||
table.insert(targetZones, { name = name, id = target, creator = GetInvokingResource() })
|
||||
return target
|
||||
end
|
||||
|
||||
Target.RemoveGlobalPlayer = function()
|
||||
ox_target:removeGlobalPlayer()
|
||||
end
|
||||
|
||||
Target.RemoveLocalEntity = function(entity)
|
||||
ox_target:removeLocalEntity(entity)
|
||||
end
|
||||
|
||||
Target.RemoveModel = function(model)
|
||||
ox_target:removeModel(model)
|
||||
end
|
||||
|
||||
Target.RemoveZone = function(name)
|
||||
for _, data in pairs(targetZones) do
|
||||
if data.name == name then
|
||||
ox_target:removeZone(data.id)
|
||||
table.remove(targetZones, _)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AddEventHandler('onResourceStop', function(resource)
|
||||
if resource ~= GetCurrentResourceName() then
|
||||
for _, target in pairs(targetZones) do
|
||||
if target.creator == resource then
|
||||
ox_target:removeZone(target.id)
|
||||
end
|
||||
end
|
||||
targetZones = {}
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,94 @@
|
||||
if GetResourceState('qb-target') ~= 'started' or GetResourceState('ox_target') == 'started' then return end
|
||||
|
||||
local targetDebug = false
|
||||
local function detectDebugEnabled()
|
||||
if BridgeClientConfig.DebugLevel == 3 then
|
||||
targetDebug = true
|
||||
end
|
||||
end
|
||||
|
||||
detectDebugEnabled()
|
||||
|
||||
local targetZones = {}
|
||||
|
||||
Target = {}
|
||||
|
||||
Target.AddGlobalPlayer = function(options)
|
||||
for k, v in pairs(options) do
|
||||
options[k].action = v.onSelect
|
||||
end
|
||||
exports['qb-target']:AddGlobalPlayer({
|
||||
options = options,
|
||||
distance = options.distance or 1.5
|
||||
})
|
||||
end
|
||||
|
||||
Target.AddLocalEntity = function(entities, options)
|
||||
for k, v in pairs(options) do
|
||||
options[k].action = v.onSelect
|
||||
end
|
||||
exports['qb-target']:AddTargetEntity(entities, {
|
||||
options = options,
|
||||
distance = options.distance or 1.5
|
||||
})
|
||||
end
|
||||
|
||||
Target.AddModel = function(models, options)
|
||||
for k, v in pairs(options) do
|
||||
options[k].action = v.onSelect
|
||||
end
|
||||
exports['qb-target']:AddTargetModel(models, {
|
||||
options = options,
|
||||
distance = options.distance or 1.5,
|
||||
})
|
||||
end
|
||||
|
||||
Target.AddBoxZone = function(name, coords, size, heading, options)
|
||||
for k, v in pairs(options) do
|
||||
options[k].action = v.onSelect
|
||||
end
|
||||
exports['qb-target']:AddBoxZone(name, coords, size.x, size.y, {
|
||||
name = name,
|
||||
debugPoly = targetDebug,
|
||||
heading = heading,
|
||||
minZ = coords.z - (size.x * 0.5),
|
||||
maxZ = coords.z + (size.x * 0.5),
|
||||
}, {
|
||||
options = options,
|
||||
distance = options.distance or 1.5,
|
||||
})
|
||||
table.insert(targetZones, { name = name, creator = GetInvokingResource() })
|
||||
end
|
||||
|
||||
Target.RemoveGlobalPlayer = function()
|
||||
exports['qb-target']:RemoveGlobalPlayer()
|
||||
end
|
||||
|
||||
Target.RemoveLocalEntity = function(entity)
|
||||
exports['qb-target']:RemoveTargetEntity(entity)
|
||||
end
|
||||
|
||||
Target.RemoveModel = function(model)
|
||||
exports['qb-target']:RemoveTargetModel(model)
|
||||
end
|
||||
|
||||
Target.RemoveZone = function(name)
|
||||
for _, data in pairs(targetZones) do
|
||||
if data.name == name then
|
||||
exports['qb-target']:RemoveZone(name)
|
||||
table.remove(targetZones, _)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AddEventHandler('onResourceStop', function(resource)
|
||||
if resource ~= GetCurrentResourceName() then
|
||||
for _, target in pairs(targetZones) do
|
||||
if target.creator == resource then
|
||||
exports['qb-target']:RemoveZone(target.name)
|
||||
end
|
||||
end
|
||||
targetZones = {}
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,251 @@
|
||||
Utility = {}
|
||||
local blipIDs = {}
|
||||
local spawnedPeds = {}
|
||||
lib.locale()
|
||||
|
||||
Utility.CreateVehicle = function(model, coords, heading, networked)
|
||||
if networked == nil then networked = true end
|
||||
Utility.LoadModel(model)
|
||||
if not HasModelLoaded(model) then return Prints.error("Model Has Not Loaded") end
|
||||
local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, heading, networked, false)
|
||||
SetVehicleHasBeenOwnedByPlayer(vehicle, true)
|
||||
SetVehicleNeedsToBeHotwired(vehicle, false)
|
||||
SetModelAsNoLongerNeeded(model)
|
||||
SetVehRadioStation(vehicle, "OFF")
|
||||
return vehicle, { networkid = NetworkGetNetworkIdFromEntity(vehicle) or 0, coords = GetEntityCoords(vehicle), heading = GetEntityHeading(vehicle), }
|
||||
end
|
||||
|
||||
Utility.StartBusySpinner = function(text)
|
||||
AddTextEntry(text, text)
|
||||
BeginTextCommandBusyString(text)
|
||||
AddTextComponentSubstringPlayerName(text)
|
||||
EndTextCommandBusyString(0)
|
||||
end
|
||||
|
||||
Utility.StopBusySpinner = function()
|
||||
if BusyspinnerIsOn() then BusyspinnerOff() end
|
||||
end
|
||||
|
||||
Utility.CreateProp = function(model, coords, heading, networked)
|
||||
if networked == nil then networked = true end
|
||||
Utility.LoadModel(model)
|
||||
if not HasModelLoaded(model) then return Prints.error("Model Has Not Loaded") end
|
||||
local propEntity = CreateObject(model, coords.x, coords.y, coords.z, networked, false, false)
|
||||
SetEntityHeading(propEntity, heading)
|
||||
SetModelAsNoLongerNeeded(model)
|
||||
return propEntity
|
||||
end
|
||||
|
||||
Utility.CreateBlip = function(coords, sprite, color, scale, label, shortRange)
|
||||
local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
|
||||
SetBlipSprite(blip, sprite or 8)
|
||||
SetBlipColour(blip, color or 3)
|
||||
SetBlipScale(blip, scale or 0.8)
|
||||
SetBlipAsShortRange(blip, shortRange)
|
||||
AddTextEntry(label, label)
|
||||
BeginTextCommandSetBlipName(label)
|
||||
EndTextCommandSetBlipName(blip)
|
||||
table.insert(blipIDs, blip)
|
||||
return blip
|
||||
end
|
||||
|
||||
Utility.RemoveBlip = function(blip)
|
||||
local success = false
|
||||
for i, storedBlip in ipairs(blipIDs) do
|
||||
if storedBlip == blip then
|
||||
RemoveBlip(blip)
|
||||
table.remove(blipIDs, i)
|
||||
success = true
|
||||
break
|
||||
end
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
Utility.LoadModel = function(model)
|
||||
if type(model) ~= 'number' then model = joaat(model) end
|
||||
if not IsModelValid(model) and not IsModelInCdimage(model) then return false end
|
||||
RequestModel(model)
|
||||
local count = 0
|
||||
while not HasModelLoaded(model) and count < 30000 do
|
||||
Wait(0)
|
||||
count = count + 1
|
||||
end
|
||||
return HasModelLoaded(model)
|
||||
end
|
||||
|
||||
Utility.CreatePed = function(model, coords, heading, networked, clothing)
|
||||
if networked == nil then networked = true end
|
||||
Utility.LoadModel(model)
|
||||
if not HasModelLoaded(model) then return Prints.error("Model Has Not Loaded") end
|
||||
local spawnedEntity = CreatePed(0, model, coords.x, coords.y, coords.z, heading, networked, false)
|
||||
if clothing then
|
||||
for componentID, v in pairs(clothing) do
|
||||
SetPedComponentVariation(spawnedEntity, componentID, v[1], v[2], 0)
|
||||
end
|
||||
end
|
||||
FreezeEntityPosition(spawnedEntity, true)
|
||||
SetEntityInvincible(spawnedEntity, true)
|
||||
SetBlockingOfNonTemporaryEvents(spawnedEntity, true)
|
||||
SetModelAsNoLongerNeeded(model)
|
||||
table.insert(spawnedPeds, spawnedEntity)
|
||||
return spawnedEntity
|
||||
end
|
||||
|
||||
Utility.RemovePed = function(entity)
|
||||
local success = false
|
||||
DeleteEntity(entity)
|
||||
for i, storedEntity in ipairs(spawnedPeds) do
|
||||
if storedEntity == entity then
|
||||
table.remove(spawnedPeds, i)
|
||||
success = true
|
||||
break
|
||||
end
|
||||
end
|
||||
return success
|
||||
end
|
||||
|
||||
Utility.NativeInputMenu = function(text, length)
|
||||
local maxLength = Math.Clamp(length, 1, 50)
|
||||
local menutText = text or 'enter text'
|
||||
AddTextEntry(menutText, menutText)
|
||||
DisplayOnscreenKeyboard(1, menutText, "", "", "", "", "", maxLength)
|
||||
while(UpdateOnscreenKeyboard() == 0) do
|
||||
DisableAllControlActions(0)
|
||||
Wait(0)
|
||||
end
|
||||
if(GetOnscreenKeyboardResult()) then
|
||||
local result = GetOnscreenKeyboardResult()
|
||||
return result
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
Utility.GetEntitySkinData = function(entity)
|
||||
local skinData = {}
|
||||
skinData.clothing = {}
|
||||
for i = 0, 11 do
|
||||
skinData.clothing[i] = {GetPedDrawableVariation(entity, i), GetPedTextureVariation(entity, i)}
|
||||
end
|
||||
return skinData
|
||||
end
|
||||
|
||||
Utility.SetEntitySkinData = function(entity, skinData)
|
||||
for i = 0, 11 do
|
||||
SetPedComponentVariation(entity, i, skinData.clothing[i][1], skinData.clothing[i][2], 0)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
Utility.NativeAlert = function(data)
|
||||
local message = data.message or 'No message provided'
|
||||
local coords = data.coords or GetEntityCoords(cache.ped)
|
||||
local job = data.job
|
||||
local scale = data.scale or 0.8
|
||||
local sprite = data.sprite or 1
|
||||
TriggerServerEvent('community_bridge:server:alert', {message = message, coords = coords, job = job, scale = scale, sprite = sprite})
|
||||
end
|
||||
|
||||
Utility.ReloadSkin = function()
|
||||
local skinData = Utility.GetEntitySkinData(cache.ped)
|
||||
Utility.SetEntitySkinData(cache.ped, skinData)
|
||||
for _, props in pairs(GetGamePool("CObject")) do
|
||||
if IsEntityAttachedToEntity(cache.ped, props) then
|
||||
SetEntityAsMissionEntity(props, true, true)
|
||||
DeleteObject(props)
|
||||
DeleteEntity(props)
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
Utility.RestoreAppearance = function(data)
|
||||
return Utility.SetEntitySkinData(cache.ped, data)
|
||||
end
|
||||
|
||||
Utility.HelpText = function(text, duration)
|
||||
AddTextEntry(text, text)
|
||||
BeginTextCommandDisplayHelp(text)
|
||||
EndTextCommandDisplayHelp(0, false, true, duration or 5000)
|
||||
end
|
||||
|
||||
Utility.NotifyText = function(text)
|
||||
AddTextEntry(text, text)
|
||||
SetNotificationTextEntry(text)
|
||||
DrawNotification(false, true)
|
||||
end
|
||||
|
||||
Utility.TeleportPlayer = function(coords, conditionFunction, afterTeleportFunction)
|
||||
if conditionFunction ~= nil then
|
||||
if not conditionFunction() then
|
||||
return
|
||||
end
|
||||
end
|
||||
DoScreenFadeOut(2500)
|
||||
Wait(2500)
|
||||
SetEntityCoords(cache.ped, coords.x, coords.y, coords.z, false, false, false, false)
|
||||
if coords.w then
|
||||
SetEntityHeading(cache.ped, coords.w)
|
||||
end
|
||||
FreezeEntityPosition(cache.ped, true)
|
||||
local count = 0
|
||||
while not HasCollisionLoadedAroundEntity(cache.ped) and count <= 30000 do
|
||||
RequestCollisionAtCoord(coords.x, coords.y, coords.z)
|
||||
Wait(0)
|
||||
count = count + 1
|
||||
end
|
||||
FreezeEntityPosition(cache.ped, false)
|
||||
DoScreenFadeIn(1000)
|
||||
if afterTeleportFunction ~= nil then
|
||||
afterTeleportFunction()
|
||||
end
|
||||
end
|
||||
|
||||
Utility.GetEntityHashFromModel = function(model)
|
||||
if type(model) ~= 'number' then model = joaat(model) end
|
||||
return model
|
||||
end
|
||||
|
||||
Utility.GetClosestPlayer = function(coords, distanceScope, includeMe)
|
||||
local players = GetActivePlayers()
|
||||
local closestPlayer = 0
|
||||
local selfPed = cache.ped
|
||||
local selfCoords = coords or GetEntityCoords(cache.ped)
|
||||
local closestDistance = distanceScope or 5
|
||||
|
||||
for _, player in ipairs(players) do
|
||||
local playerPed = GetPlayerPed(player)
|
||||
if includeMe or playerPed ~= selfPed then
|
||||
local playerCoords = GetEntityCoords(playerPed)
|
||||
local distance = #(selfCoords - playerCoords)
|
||||
if closestDistance == -1 or distance < closestDistance then
|
||||
closestPlayer = player
|
||||
closestDistance = distance
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return closestPlayer, closestDistance, GetPlayerServerId(closestPlayer)
|
||||
end
|
||||
|
||||
AddEventHandler('onResourceStop', function(resource)
|
||||
if resource ~= GetCurrentResourceName() then
|
||||
for _, blip in pairs(blipIDs) do
|
||||
if DoesBlipExist(blip.id) then
|
||||
RemoveBlip(blip.id)
|
||||
end
|
||||
end
|
||||
for _, ped in pairs(spawnedPeds) do
|
||||
if DoesEntityExist(ped) then
|
||||
DeleteEntity(ped)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('community_bridge:client:alert', function(data)
|
||||
local blip = Utility.CreateBlip(data.coords, data.sprite, 3, data.scale, data.message, true)
|
||||
SetTimeout(40000, function()
|
||||
Utility.RemoveBlip(blip)
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,107 @@
|
||||
local activePlacementProp = nil
|
||||
lib.locale()
|
||||
|
||||
-- Object placer --
|
||||
local placementText = {
|
||||
locale('place_object'),
|
||||
locale('place_object_place'),
|
||||
locale('place_object_cancel'),
|
||||
locale('place_object_scroll_up'),
|
||||
locale('place_object_scroll_down')
|
||||
}
|
||||
|
||||
local function finishPlacing()
|
||||
Bridge.notify.HideHelpText()
|
||||
if activePlacementProp == nil then return end
|
||||
DeleteObject(activePlacementProp)
|
||||
activePlacementProp = nil
|
||||
end
|
||||
|
||||
Utility.PlaceObject = function(object, distance, snapToGround, allowedMats, offset)
|
||||
if activePlacementProp then return end
|
||||
|
||||
if not object then lib.print.error('no_prop_defined') end
|
||||
|
||||
local propObject = type(object) == 'string' and joaat(object) or object
|
||||
local heading = 0.0
|
||||
local checkDist = distance or 10.0
|
||||
|
||||
Utility.LoadModel(propObject)
|
||||
|
||||
activePlacementProp = CreateObject(propObject, 1.0, 1.0, 1.0, false, true, true)
|
||||
SetModelAsNoLongerNeeded(propObject)
|
||||
SetEntityAlpha(activePlacementProp, 150, false)
|
||||
SetEntityCollision(activePlacementProp, false, false)
|
||||
SetEntityInvincible(activePlacementProp, true)
|
||||
FreezeEntityPosition(activePlacementProp, true)
|
||||
|
||||
Bridge.notify.ShowHelpText(type(placementText) == 'table' and table.concat(placementText) or placementText, {
|
||||
position = "left-center",
|
||||
})
|
||||
|
||||
local outLine = false
|
||||
|
||||
while activePlacementProp do
|
||||
--local hit, _, coords, _, materialHash = lib.raycast.fromCamera(1, 4)
|
||||
--local hit, _, coords, _, materialHash = lib.raycast.fromCamera(1, 4, nil)
|
||||
local hit, _, coords, _, materialHash = lib.raycast.fromCamera(1, 4)
|
||||
if hit then
|
||||
if offset then
|
||||
coords += offset
|
||||
end
|
||||
|
||||
SetEntityCoords(activePlacementProp, coords.x, coords.y, coords.z, false, false, false, false)
|
||||
local distCheck = #(GetEntityCoords(cache.ped) - coords)
|
||||
SetEntityHeading(activePlacementProp, heading)
|
||||
|
||||
if snapToGround then
|
||||
PlaceObjectOnGroundProperly(activePlacementProp)
|
||||
end
|
||||
|
||||
if outLine then
|
||||
outLine = false
|
||||
SetEntityDrawOutline(activePlacementProp, false)
|
||||
end
|
||||
|
||||
if (allowedMats and not allowedMats[materialHash]) or distCheck >= checkDist then
|
||||
if not outLine then
|
||||
outLine = true
|
||||
SetEntityDrawOutline(activePlacementProp, true)
|
||||
end
|
||||
end
|
||||
|
||||
if IsControlJustReleased(0, 38) then
|
||||
if not outLine and (not allowedMats or allowedMats[materialHash]) and distCheck < checkDist then
|
||||
finishPlacing()
|
||||
|
||||
return coords, heading
|
||||
end
|
||||
end
|
||||
|
||||
if IsControlJustReleased(0, 73) then
|
||||
finishPlacing()
|
||||
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
if IsControlJustReleased(0, 14) then
|
||||
heading = heading + 5
|
||||
if heading > 360 then heading = 0.0 end
|
||||
end
|
||||
|
||||
if IsControlJustReleased(0, 15) then
|
||||
heading = heading - 5
|
||||
if heading < 0 then
|
||||
heading = 360.0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Utility.StopPlacing = function()
|
||||
if not activePlacementProp then return end
|
||||
finishPlacing()
|
||||
end
|
||||
|
||||
-- This is derrived and slightly altered from its creator and licensed under GPL-3.0 license Author:Zoo, the original is located here https://github.com/Renewed-Scripts/Renewed-Lib/tree/main
|
||||
@@ -0,0 +1,38 @@
|
||||
VersionCheck = {}
|
||||
|
||||
function VersionCheck.VersionChecker(repoPath)
|
||||
local resource = repoPath:match("([^/]+)$")
|
||||
if not resource then return print('^1Invalid repository format. Expected format: "username/reponame"^0') end
|
||||
|
||||
local version = GetResourceMetadata(resource, "version", 0)
|
||||
if not version then return print(('^1Unable to determine current resource version for %s ^0'):format(resource)) end
|
||||
|
||||
version = version:match('%d+%.%d+%.%d+')
|
||||
if not version then return print(('^1Invalid version format for %s ^0'):format(resource)) end
|
||||
|
||||
local username, reponame = repoPath:match("([^/]+)/([^/]+)")
|
||||
if not username or not reponame then return print('^1Invalid repository format. Expected format: "username/reponame"^0') end
|
||||
PerformHttpRequest(('https://api.github.com/repos/%s/%s/releases/latest'):format(username, reponame), function(status, response)
|
||||
local failure = ('^1Unable locate github repo for resource %s ^0'):format(resource)
|
||||
|
||||
if status ~= 200 then return print(failure) end
|
||||
response = json.decode(response)
|
||||
|
||||
if response.prerelease then return print(failure) end
|
||||
|
||||
local latest = response.tag_name:match('%d+%.%d+%.%d+')
|
||||
if not latest then return print(failure) end
|
||||
|
||||
if latest == version then return print(('^2 %s is on the latest version.^0'):format(resource)) end
|
||||
local currentVersion, latestVersion = version:gsub('%D', ''), latest:gsub('%D', '')
|
||||
|
||||
if currentVersion < latestVersion then
|
||||
return print(('^1An update is available for %s (current version: %s)\r\n - ^5Please download the latest version from the GitHub release page.^7\r\n%s'):format(resource, version, response.html_url))
|
||||
end
|
||||
end, 'GET')
|
||||
end
|
||||
|
||||
AddEventHandler('onResourceStart', function(resourceName)
|
||||
if GetCurrentResourceName() ~= resourceName then return end
|
||||
VersionCheck.VersionChecker("MrNewb/community_bridge")
|
||||
end)
|
||||
@@ -0,0 +1,50 @@
|
||||
Logger = {}
|
||||
|
||||
local WebhookURL = BridgeServerConfig.WebhookURL
|
||||
local LogoForEmbed = BridgeServerConfig.WebhookImage
|
||||
|
||||
Logger.SendLog = function(src, message)
|
||||
if not src or not message then return end
|
||||
if BridgeServerConfig.LogSystem == "builtin" then
|
||||
PerformHttpRequest(WebhookURL, function(err, text, headers) end, 'POST', json.encode(
|
||||
{
|
||||
username = "Community_Bridge's Logger",
|
||||
avatar_url = 'https://cdn.discordapp.com/avatars/299410129982455808/31ce635662206e8bd0132c34ce9ce683?size=1024',
|
||||
embeds = {
|
||||
{
|
||||
color = "15769093",
|
||||
title = GetCurrentResourceName(),
|
||||
url = 'https://discord.gg/wsPAK5mEPg',
|
||||
--description = message,
|
||||
thumbnail = { url = LogoForEmbed },
|
||||
fields = {
|
||||
{
|
||||
name = '**Player ID**',
|
||||
value = src,
|
||||
inline = true,
|
||||
},
|
||||
{
|
||||
name = '**Player Identifier**',
|
||||
value = Framework.GetPlayerIdentifier(src),
|
||||
inline = true,
|
||||
},
|
||||
{
|
||||
name = 'Log Message',
|
||||
value = "```"..message.."```",
|
||||
inline = false,
|
||||
},
|
||||
},
|
||||
timestamp = os.date('!%Y-%m-%dT%H:%M:%S'),
|
||||
footer = {
|
||||
text = "Community_Bridge | "..GetCurrentResourceName(),
|
||||
icon_url = 'https://cdn.discordapp.com/avatars/299410129982455808/31ce635662206e8bd0132c34ce9ce683?size=1024',
|
||||
},
|
||||
}
|
||||
}
|
||||
}), { ['Content-Type']= 'application/json' })
|
||||
elseif BridgeServerConfig.LogSystem == "qb" then
|
||||
return TriggerEvent('qb-log:server:CreateLog', GetCurrentResourceName(), GetCurrentResourceName(), 'green', message)
|
||||
elseif BridgeServerConfig.LogSystem == "ox" then
|
||||
return exports.ox_lib:logger(src, GetCurrentResourceName(), message)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
LootTables = {}
|
||||
|
||||
LootTables.RegisterLootTable = function(name, items)
|
||||
local repackedTable = {}
|
||||
for k, v in pairs(items) do
|
||||
table.insert(repackedTable, {
|
||||
name = k,
|
||||
min = v.min,
|
||||
max = v.max,
|
||||
chance = v.chance,
|
||||
tier = v.tier,
|
||||
item = v.item,
|
||||
metadata = v.metadata
|
||||
})
|
||||
end
|
||||
LootTables[name] = repackedTable
|
||||
return LootTables[name]
|
||||
end
|
||||
|
||||
LootTables.GetLootTable = function(name)
|
||||
assert(name, "No Name Passed For Loot Table")
|
||||
return LootTables[name] or {}
|
||||
end
|
||||
|
||||
LootTables.GetRandomItem = function(name, tier, randomNumber)
|
||||
assert(name, "No Name Passed For Loot Table")
|
||||
if tier == nil then tier = 1 end
|
||||
local lootTable = LootTables[name] or {}
|
||||
math.randomseed(GetGameTimer())
|
||||
local chance = randomNumber or math.random(1, 100)
|
||||
for _, v in pairs(lootTable) do
|
||||
if v.chance <= chance and tier == v.tier then
|
||||
return { item = v.item, metadata = v.metadata, count = math.random(v.min, v.max), tier = v.tier, chance = v.chance}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
LootTables.GetRandomItems = function(name, tier, randomNumber)
|
||||
assert(name, "No Name Passed For Loot Table")
|
||||
if tier == nil then tier = 1 end
|
||||
local lootTable = LootTables.GetLootTable(name)
|
||||
math.randomseed(GetGameTimer())
|
||||
local chance = randomNumber or math.random(1, 100)
|
||||
local items = {}
|
||||
for _, v in pairs(lootTable) do
|
||||
if v.chance <= chance and tier == v.tier then
|
||||
table.insert(items,{item = v.item, metadata = v.metadata, count = math.random(v.min, v.max), tier = v.tier, chance = v.chance})
|
||||
end
|
||||
end
|
||||
return items
|
||||
end
|
||||
|
||||
LootTables.GetRandomItemsWithLimit = function(name, tier, randomNumber)
|
||||
assert(name, "No Name Passed For Loot Table")
|
||||
if tier == nil then tier = 1 end
|
||||
local lootTable = LootTables.GetLootTable(name)
|
||||
math.randomseed(GetGameTimer())
|
||||
local chance = randomNumber or math.random(1, 100)
|
||||
local items = {}
|
||||
for k = #lootTable, 1, -1 do
|
||||
local v = lootTable[k]
|
||||
if chance <= v.chance and tier == v.tier then
|
||||
table.insert(items, {v.item, v.metadata, math.random(v.min, v.max), v.tier, v.chance})
|
||||
table.remove(lootTable, k)
|
||||
end
|
||||
end
|
||||
return items
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
RegisterServerEvent("community_bridge:server:alert", function(data)
|
||||
local playersByJob = Framework.GetPlayersByJob(data.job)
|
||||
for _, src in pairs(playersByJob) do
|
||||
TriggerClientEvent("community_bridge:client:alert", src, data)
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,10 @@
|
||||
if GetResourceState('qb-weathersync') ~= 'started' then return end
|
||||
Weather = {}
|
||||
|
||||
Weather.ToggleSync = function(toggle)
|
||||
if toggle then
|
||||
TriggerEvent("qb-weathersync:client:EnableSync")
|
||||
else
|
||||
TriggerEvent("qb-weathersync:client:DisableSync")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
if GetResourceState('Renewed-Weathersync') ~= 'started' then return end
|
||||
Weather = {}
|
||||
|
||||
Weather.ToggleSync = function(toggle)
|
||||
LocalPlayer.state.syncWeather = toggle
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
if GetResourceState('qb-weathersync') ~= 'started' then return end
|
||||
Weather = {}
|
||||
|
||||
Weather.ToggleSync = function(toggle)
|
||||
if toggle then
|
||||
TriggerEvent("qb-weathersync:client:EnableSync")
|
||||
else
|
||||
TriggerEvent("qb-weathersync:client:DisableSync")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
BridgeClientConfig = {}
|
||||
BridgeClientConfig.NotifySystem = "ox" -- Change this to your notification system (ox/qb/esx?)
|
||||
BridgeClientConfig.ZoneSystem = "ox" -- Change this to your dialog system (ox/poly)
|
||||
BridgeClientConfig.InputSystem = "ox" -- Change this to your Input system (ox/qb)
|
||||
BridgeClientConfig.MenuSystem = "ox" -- Change this to your Menu system (ox/qb)
|
||||
BridgeClientConfig.ProgressBar = "ox" -- Change this to your preferred progress bar (ox/qb)
|
||||
BridgeClientConfig.DebugLevel = 3 -- Change this to your Debug level, 1 for none, 2 for some, 3 for all data
|
||||
BridgeClientConfig.ShowHelpText = "ox" --
|
||||
|
||||
Require("init.lua", "ox_lib")
|
||||
return BridgeClientConfig
|
||||
@@ -0,0 +1,8 @@
|
||||
BridgeServerConfig = {}
|
||||
BridgeServerConfig.LogSystem = "builtin" -- "builtin", "qb", "ox"
|
||||
BridgeServerConfig.WebhookURL = "PUT_WEBHOOK_URL_HERE"
|
||||
BridgeServerConfig.WebhookImage = "https://cdn.discordapp.com/avatars/299410129982455808/31ce635662206e8bd0132c34ce9ce683?size=1024"
|
||||
BridgeServerConfig.MaxInventorySlots = 50
|
||||
Require("init.lua", "ox_lib")
|
||||
|
||||
return BridgeServerConfig
|
||||
@@ -0,0 +1,5 @@
|
||||
BridgeSharedConfig = {}
|
||||
BridgeSharedConfig.Lang = "auto" -- Change this to your preferred language (must match the locale file name ex. en or fr etc)
|
||||
BridgeSharedConfig.DebugLevel = 3 -- Change this to your Debug level, 1 for none, 2 for some, 3 for all data
|
||||
|
||||
return BridgeSharedConfig
|
||||
@@ -0,0 +1,25 @@
|
||||
importing resource in shared -- should be an option, exports could be primary use but importing in shared should be available
|
||||
Locales do not seem to work using the export method.
|
||||
Serversided stashes are busted using internal method -- may be best to rework this logic https://github.com/Mustachedom/md-stashes/blob/main/server/server.lua
|
||||
|
||||
|
||||
-------[[ Crowley ]]--------
|
||||
^ Locales 1-1 with ox.
|
||||
|
||||
We need a simple easy to use locale system. Ox does it in a single line, we need the same otherwise why would they use it.
|
||||
|
||||
|
||||
^ Simpler Init method.
|
||||
|
||||
The tables are the only approach I could think of for this while having fallback functions
|
||||
fallback functions are **required**.
|
||||
|
||||
current location -- community_bridge\modules\initialize
|
||||
|
||||
|
||||
|
||||
----[[ Newb ]]----
|
||||
|
||||
|
||||
|
||||
1.8.25
|
||||
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user