Merge pull request #67 from The-Order-Of-The-Sacred-Framework/dev

0.5.0
This commit is contained in:
MrNewb authored and GitHub committed 2025-04-08 23:58:12 -04:00
commit 01db36ea80
90 files changed
+2083 -765

No files matched your search

+4 -4
View File
@@ -8,11 +8,11 @@ This project incorporates code from several libraries and resources licensed und
- **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
## dirk_lib
- **Purpose**: Vehicle fuel, vehicle key bridging.
- **Modifications to the code**: None.
- **Credit**: **clean_lib** client side code is used to manage vehicle fuel and keys, bridging these systems.
[\[clean_lib\]](https://github.com/Clean-Server-Pack/clean_lib)
- **Credit**: **dirk_lib** client side code is used to manage vehicle fuel and keys, bridging these systems.
[\[dirk_lib\]](https://github.com/DirkDigglerz/dirk_lib)
## ox_lib
- **Purpose**: Utility functions for printing raycasting and point registering.
@@ -34,4 +34,4 @@ This project incorporates code from several libraries and resources licensed und
Thank you to the creators and maintainers of these libraries/bridges/internet points for their hard work and contributions to the FiveM community.
Thank you to the creators and maintainers of these libraries/bridges/internet points for their hard work and contributions to the FiveM community.
+5 -4
View File
@@ -4,7 +4,7 @@ lua54 'yes'
use_experimental_fxv2_oal '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.4.0'
version '0.5.0'
shared_scripts {
'@ox_lib/init.lua',
@@ -50,6 +50,7 @@ client_scripts {
'modules/notify/**/client.lua',
'modules/dialogue/**/client/*.lua',
'modules/shops/**/client.lua',
'modules/accessibility/client.lua',
'init.lua',
}
@@ -60,9 +61,9 @@ files {
'web/dist/assets/*.css',
'web/dist/assets/*.js',
'locales/*.json',
'lib/client/*.lua',
'lib/shared/*.lua',
'lib/server/*.lua',
'lib/**/client/*.lua',
'lib/**/shared/*.lua',
'lib/**/server/*.lua',
'lib/init.lua',
}
+4
View File
@@ -79,6 +79,7 @@ if not IsDuplicityVersion() then goto client end
Bridge.RegisterModule("SQL", cLib.SQL)
Bridge.RegisterModule("Logs", cLib.Logs)
Bridge.RegisterModule("ItemsBuilder", cLib.ItemsBuilder)
Bridge.RegisterModule("LootTables", cLib.LootTables)
Bridge.RegisterModule("Version", Version)
@@ -98,6 +99,7 @@ Bridge.RegisterModule("Weather", Weather)
Bridge.RegisterModule("Target", Target)
Bridge.RegisterModule("Menu", Menu)
Bridge.RegisterModule("Dialogue", Dialogue)
Bridge.RegisterModule("Accessibility", Accessibility) -- new
Bridge.RegisterModule("Utility", cLib.Utility)
Bridge.RegisterModule("Placeable", cLib.Placeable)--new
@@ -105,6 +107,8 @@ Bridge.RegisterModule("Gizmo", cLib.Gizmo)
Bridge.RegisterModule("Scaleform", cLib.Scaleform)
Bridge.RegisterModule("Raycast", cLib.Raycast)
Bridge.RegisterModule("PlaceableObject", cLib.PlaceableObject)
Bridge.RegisterModule("Point", cLib.Point)
Bridge.RegisterModule("Object", cLib.Object)
+51
View File
@@ -0,0 +1,51 @@
-- Objects
Utility = Utility or Require("lib/utility/client/utility.lua")
Ids = Ids or Require("lib/utility/shared/ids.lua")
Point = Point or Require("lib/points/client/points.lua")
local Entities = {}
BaseEntity = {}
function BaseEntity.Create(id, model, coords, rotation, meta)
local self = meta or {}
if id and type(id) == "table" then
self = id
self.id = id.id or Ids.CreateUniqueId(Entities)
self.rotation = id.rotation or vector3(0.0, 0.0, 0.0)
else
self.id = id or Ids.CreateUniqueId(Entities)
self.model = model
self.coords = coords
self.rotation = rotation or vector3(0.0, 0.0, 0.0)
end
assert(self.id, "ID Failed to generate")
assert(self.model, "Model is required for entity creation")
assert(self.coords, "Coords are required for entity creation")
self.Spawn = self.Spawn or function() end
self.Remove = self.Remove or function() end
return Point.Register(self.id, self.coords, 50.0, self.Spawn, self.Remove, nil, self)
end
function BaseEntity.GetAll()
return Entities
end
function BaseEntity.Get(id)
return Entities[id]
end
function BaseEntity.Add(self)
Entities[self.id] = self
end
function BaseEntity.Remove(id)
Entities[id] = nil
end
function BaseEntity.LoadModel(model)
return Utility.LoadModel(model)
end
return BaseEntity
+71
View File
@@ -0,0 +1,71 @@
BaseEntity = BaseEntity or Require("lib/entities/client/entity_base.lua")
local Objects = {}
Object = {}
function Object.Create(id, model, coords, rotation, meta)
local base = meta or {}
if id and type(id) == "table" then
base = id
base.id = id.id or Ids.CreateUniqueId(Objects)
base.rotation = id.rotation or vector3(0.0, 0.0, 0.0)
else
base.id = id or Ids.CreateUniqueId(Objects)
base.model = model
base.coords = coords
base.rotation = rotation or vector3(0.0, 0.0, 0.0)
end
assert(base.id, "ID Failed to generate")
assert(base.model, "Model is required for entity creation")
assert(base.coords, "Coords are required for entity creation")
base.Spawn = function(self)
print("Spawning object", self)
if not BaseEntity.LoadModel(self.model) then return end
self.entity = CreateObject(self.model, self.coords.x, self.coords.y, self.coords.z, false, false, false)
SetEntityRotation(self.entity, self.rotation.x, self.rotation.y, self.rotation.z, 2, false)
SetEntityAsMissionEntity(self.entity, true, true)
SetModelAsNoLongerNeeded(self.model)
if self.OnSpawn then self.OnSpawn(self, self.entity, self.coords, self.rotation) end
return self.entity
end
base.Remove = function(self)
DeleteEntity(self.entity)
if self.OnRemove then self.OnRemove(self, self.entity) end
self.entity = nil
end
Object.Add(base)
return BaseEntity.Create(base)
end
function Object.GetAll()
return Objects
end
function Object.Get(id)
return Objects[id]
end
function Object.Add(self)
Objects[self.id] = self
end
function Object.Remove(id)
Objects[id] = nil
end
function Object.SetOnSpawn(id, callback)
local obj = Object.Get(id)
if not obj then return end
obj.OnSpawn = callback
return true
end
function Object.SetOnRemove(id, callback)
local obj = Object.Get(id)
if not obj then return end
obj.OnRemove = callback
return true
end
return Object
+65
View File
@@ -0,0 +1,65 @@
-- Objects
Ids = Ids or Require("lib/utility/shared/ids.lua")
local Entities = {}
EntityRelay = {}
function EntityRelay.Create(id, model, coords, rotation, meta)
local self = meta or {}
if id and type(id) == "table" then
self = id
self.id = id.id or Ids.CreateUniqueId(Entities)
self.rotation = id.rotation or vector3(0.0, 0.0, 0.0)
else
self.id = id or Ids.CreateUniqueId(Entities)
self.model = model
self.coords = coords
self.rotation = rotation or vector3(0.0, 0.0, 0.0)
end
assert(self.id, "ID Failed to generate")
assert(self.model, "Model is required for entity creation")
assert(self.coords, "Coords are required for entity creation")
EntityRelay.Add(self)
TriggerClientEvent(GetCurrentResourceName() .. "client:CreateEntity", -1, self)
end
function EntityRelay.GetAll()
return Entities
end
function EntityRelay.Get(id)
return Entities[id]
end
function EntityRelay.Add(self)
Entities[self.id] = self
end
function EntityRelay.Remove(id)
Entities[id] = nil
end
function EntityRelay.LoadModel(model)
return Utility.LoadModel(model)
end
return EntityRelay
-- RegisterCommand("entityobj", function()
-- local entity = Bridge.Object.Create({
-- id = "something", -- optional
-- model = "prop_beach_fire",
-- coords = GetEntityCoords(PlayerPedId()),
-- rotation = vector3(0.0, 0.0, 0.0),
-- })
-- Bridge.Object.SetOnSpawn("something", function(self, coords, rotation)
-- print("Entity spawned")
-- end)
-- Bridge.Object.SetOnRemove("something", function(self, entity)
-- print("Entity removed")
-- end)
-- end)
File renamed without changes.
+100
View File
@@ -0,0 +1,100 @@
ItemsBuilder = ItemsBuilder or {}
ItemsBuilder = {}
---This will generate the items in the formats of qb_core, qb_core_old and ox_inventory. It will then build a lua file in the generateditems folder of the community_bridge.
---@param invoking string
---@param itemsTable table
ItemsBuilder.Generate = function(invoking, itemsTable)
if not invoking or not itemsTable then return end
local resourcePath = GetResourcePath(GetCurrentResourceName()) .. "/generateditems/"
local function fileExists(path)
local file = io.open(path, "r")
if file then
file:close()
return true
else
return false
end
end
local qbOldFilePath = resourcePath .. invoking .. "_qb_core_old.lua"
local qbNewFilePath = resourcePath .. invoking .. "_qb_core_new.lua"
local oxInventoryFilePath = resourcePath .. invoking .. "_ox_inventory.lua"
if fileExists(qbOldFilePath) or fileExists(qbNewFilePath) or fileExists(oxInventoryFilePath) then return end
local qbOld = {}
for key, item in pairs(itemsTable) do
qbOld[key] = string.format(
"['%s'] = {label = '%s', weight = %d, stack = %s, close = %s, description = '%s'}",
key, item.label, item.weight, tostring(item.stack), tostring(item.close), item.description
)
end
local qbNew = {}
for key, item in pairs(itemsTable) do
qbNew[key] = string.format(
"%s = {label = '%s', weight = %d, stack = %s, close = %s, description = '%s'}",
key, item.label, item.weight, tostring(item.stack), tostring(item.close), item.description
)
end
local oxInventory = {}
for key, item in pairs(itemsTable) do
oxInventory[key] = {
label = item.label,
weight = item.weight,
stack = item.stack,
close = item.close
}
end
local function writeInlineFile(fileName, content, useBrackets)
local filePath = resourcePath .. fileName
local file = io.open(filePath, "w")
if file then
for key, value in pairs(content) do
if useBrackets then
-- For qb_core_old with brackets
file:write(string.format("['%s'] = %s,\n", key, value))
else
-- For qb_core_new without brackets
file:write(string.format("%s = %s,\n", key, value))
end
end
file:close()
print("🌮 Items File Created: " .. filePath)
else
print("🌮 Something Broke for: " .. filePath)
end
end
local function writeSimplifiedFile(fileName, content)
local filePath = resourcePath .. fileName
local file = io.open(filePath, "w")
if file then
for key, item in pairs(content) do
file:write(string.format('["%s"] = {\n', key))
for k, v in pairs(item) do
local formattedValue = type(v) == "string" and string.format('"%s"', v) or tostring(v)
file:write(string.format(" %s = %s,\n", k, formattedValue))
end
file:write("},\n")
end
file:close()
print("🌮 Items File Created: " .. filePath)
else
print("🌮 Something Broke for: " .. filePath)
end
end
writeInlineFile(invoking.."_".."qb_core_old.lua", qbOld, true)
writeInlineFile(invoking.."_".."qb_core_new.lua", qbNew, false)
writeSimplifiedFile(invoking.."_".."ox_inventory.lua", oxInventory)
end
exports('ItemsBuilder', ItemsBuilder)
return ItemsBuilder
File renamed without changes.
+20 -17
View File
@@ -37,14 +37,14 @@ end
cLib = {
Require = Require,
Callback = Callback or Require("lib/shared/callbacks.lua"),
Ids = Ids or Require("lib/shared/ids.lua"),
ReboundEntities = ReboundEntities or Require("lib/shared/rebound_entities.lua"),
Tables = Tables or Require("lib/shared/tables.lua"),
Prints = Prints or Require("lib/shared/prints.lua"),
Math = Math or Require("lib/shared/math.lua"),
LA = LA or Require("lib/shared/la.lua"),
Perlin = Perlin or Require("lib/shared/perlin.lua"),
Callback = Callback or Require("lib/utility/shared/callbacks.lua"),
Ids = Ids or Require("lib/utility/shared/ids.lua"),
ReboundEntities = ReboundEntities or Require("lib/utility/shared/rebound_entities.lua"),
Tables = Tables or Require("lib/utility/shared/tables.lua"),
Prints = Prints or Require("lib/utility/shared/prints.lua"),
Math = Math or Require("lib/utility/shared/math.lua"),
LA = LA or Require("lib/utility/shared/la.lua"),
Perlin = Perlin or Require("lib/utility/shared/perlin.lua"),
-- Actions = Actions or Require("lib/shared/actions.lua"),
}
@@ -52,18 +52,21 @@ exports('cLib', cLib)
if not IsDuplicityVersion() then goto client end
cLib.SQL = SQL or Require("lib/server/sqlHandler.lua")
cLib.Logs = Logs or Require("lib/server/logs.lua")
cLib.LootTables = LootTables or Require("lib/server/lootTables.lua")
cLib.SQL = SQL or Require("lib/sql/server/sqlHandler.lua")
cLib.Logs = Logs or Require("lib/logs/server/logs.lua")
cLib.ItemsBuilder = ItemsBuilder or Require("lib/generators/server/ItemsBuilder.lua")
cLib.LootTables = LootTables or Require("lib/generators/server/lootTables.lua")
if IsDuplicityVersion() then return cLib end
::client::
cLib.Gizmo = Gizmo or Require("lib/client/gizmo.lua")
cLib.Scaleform = Scaleform or Require("lib/client/scaleform.lua")
cLib.Placeable = Placeable or Require("lib/client/object_placer.lua")
cLib.Utility = Utility or Require("lib/client/utility.lua")
cLib.PlaceableObject = PlaceableObject or Require("lib/client/placeable_object.lua")
cLib.Raycast = Raycast or Require("lib/client/raycast.lua")
cLib.Gizmo = Gizmo or Require("lib/placers/client/gizmo.lua")
cLib.Scaleform = Scaleform or Require("lib/scaleform/client/scaleform.lua")
cLib.Placeable = Placeable or Require("lib/placers/client/object_placer.lua")
cLib.Utility = Utility or Require("lib/utility/client/utility.lua")
cLib.PlaceableObject = PlaceableObject or Require("lib/placers/client/placeable_object.lua")
cLib.Raycast = Raycast or Require("lib/raycast/client/raycast.lua")
cLib.Point = Point or Require("lib/points/client/points.lua")
cLib.Object = Object or Require("lib/entities/client/entity_object.lua")
return cLib
@@ -3,6 +3,10 @@ Logs = Logs or {}
local WebhookURL = ""
local LogoForEmbed = ""
---This will send a log to the configured webhook or log system.
---@param src number
---@param message string
---@return nil
Logs.Send = function(src, message)
if not src or not message then return end
if BridgeServerConfig.LogSystem == "builtin" then
File renamed without changes.
@@ -1,4 +1,3 @@
function CreateParticleFX(dict, ptfx, pos, rot, scale, color, looped, loopLength)
CreateThread(function()
local failed = 5
@@ -45,8 +44,6 @@ function CreateParticleFXOnEntityBone(dict, ptfx, entity, bone, offset, rot, sc
return bleh
end
function PlayParticleFX(dict, name, looped, x, y, z, rotX, rotY, rotZ, scale)
RequestNamedPtfxAsset(dict)
while not HasNamedPtfxAssetLoaded(dict) do
File renamed without changes.
@@ -2,7 +2,7 @@
-- CREDITS
-- Andyyy7666: https://github.com/overextended/ox_lib/pull/453
-- AvarianKnight: https://forum.cfx.re/t/allow-drawgizmo-to-be-used-outside-of-fxdk/5091845/8?u=demi-automatic
local dataview = Require("lib/client/dataview.lua")
local dataview = Require("lib/placers/client/dataview.lua")
local enableScale = false -- allow scaling mode. doesnt scale collisions and resets when physics are applied it seems
local gizmoEnabled = false
local currentMode = 'translate'
@@ -1,5 +1,5 @@
Placeable = Placeable or {}
Utility = Utility or Require("lib/client/utility.lua")
Utility = Utility or Require("lib/utility/client/utility.lua")
local activePlacementProp = nil
lib.locale()
@@ -1,7 +1,7 @@
Scaleform = Scaleform or Require("lib/client/scaleform.lua")
Utility = Utility or Require("lib/client/utility.lua")
Gizmo = Gizmo or Require("lib/client/gizmo.lua")
Raycast = Raycast or Require("lib/client/raycast.lua")
Scaleform = Scaleform or Require("lib/scaleform/client/scaleform.lua")
Utility = Utility or Require("lib/utility/client/utility.lua")
Gizmo = Gizmo or Require("lib/placers/client/gizmo.lua")
Raycast = Raycast or Require("lib/raycast/client/raycast.lua")
PlaceableObject = PlaceableObject or {}
@@ -71,7 +71,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett
{type = "SET_BACKGROUND_COLOUR"},
})
local heading = -GetEntityHeading(PlayerPedId())
local pos = PlaceableObject.Eyetrace(depth, disableSphere)
if not data.spawned and model then
--get player heading
@@ -81,7 +81,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett
assert(data.spawned, "Failed to create object")
SetEntityCollision(data.spawned, false, false)
SetEntityAlpha(data.spawned, 150, false)
SetPedConfigFlag(PlayerPedId(), 146, true)
SetCanClimbOnEntity(data.spawned, false)
SetEntityCompletelyDisableCollision(data.spawned, true, false)
@@ -96,7 +96,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett
inBounds = true
SetEntityDrawOutlineColor(0, 255, 0, 255)
SetEntityDrawOutline(data.spawned, true)
end
end
elseif inBounds then
inBounds = false
SetEntityDrawOutline(data.spawned, false)
@@ -113,7 +113,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett
DisableControlAction(0, 24, true) -- Attack
DisableControlAction(0, 25, true) -- Aim
DisableControlAction(0, 36, true) -- INPUT_DUCK.
if IsDisabledControlJustPressed(0, 223) then -- left click
if not inBounds then
Notify.SendNotify("You can't place this object here", "error", 5000)
@@ -190,6 +190,4 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett
end)
end
return PlaceableObject
return PlaceableObject
+266
View File
@@ -0,0 +1,266 @@
-- Grid-based point system
Point = {}
local ActivePoints = {}
local GridCells = {}
local LoopStarted = false
local insidePoints = {}
local data = {} -- 👈 Move this outside the function
-- Grid configuration
local GRID_SIZE = 500.0 -- Size of each grid cell
local CELL_BUFFER = 1 -- Number of adjacent cells to check
-- Consider adding these optimizations
local ADAPTIVE_WAIT = true -- Adjust wait time based on player speed
---This is an internal function, do not call this externally
function Point.GetCellKey(coords)
local cellX = math.floor(coords.x / GRID_SIZE)
local cellY = math.floor(coords.y / GRID_SIZE)
return cellX .. ":" .. cellY
end
---This is an internal function, do not call this externally
function Point.RegisterInGrid(point)
local cellKey = Point.GetCellKey(point.coords)
-- Initialize cell if it doesn't exist
GridCells[cellKey] = GridCells[cellKey] or {
points = {},
count = 0
}
-- Add point to cell
GridCells[cellKey].points[point.id] = point
GridCells[cellKey].count = GridCells[cellKey].count + 1
-- Store cell reference in point
point.cellKey = cellKey
end
---This is an internal function, do not call this externally
function Point.UpdateInGrid(point, oldCellKey)
-- Remove from old cell if cell key changed
if oldCellKey and oldCellKey ~= point.cellKey then
if GridCells[oldCellKey] and GridCells[oldCellKey].points[point.id] then
GridCells[oldCellKey].points[point.id] = nil
GridCells[oldCellKey].count = GridCells[oldCellKey].count - 1
-- Clean up empty cells
if GridCells[oldCellKey].count <= 0 then
GridCells[oldCellKey] = nil
end
end
-- Add to new cell
Point.RegisterInGrid(point)
end
end
---Gets nearby cells based on the coords
---@param coords table
---@return table
function Point.GetNearbyCells(coords)
local cellX = math.floor(coords.x / GRID_SIZE)
local cellY = math.floor(coords.y / GRID_SIZE)
local nearbyCells = {}
-- Get current and adjacent cells
for x = cellX - CELL_BUFFER, cellX + CELL_BUFFER do
for y = cellY - CELL_BUFFER, cellY + CELL_BUFFER do
local key = x .. ":" .. y
if GridCells[key] then
table.insert(nearbyCells, key)
end
end
end
return nearbyCells
end
---Returns all points in the same cell as the given point
---This will require you to pass the point object
---@param point table
---@return table
function Point.CheckPointsInSameCell(point)
local cellKey = point.cellKey
if not GridCells[cellKey] then return {} end
local nearbyPoints = {}
for id, otherPoint in pairs(GridCells[cellKey].points) do
if id ~= point.id then
local distance = #(point.coords - otherPoint.coords)
if distance < (point.distance + otherPoint.distance) then
nearbyPoints[id] = otherPoint
end
end
end
return nearbyPoints
end
---Internal function that starts the loop. Do not call this function directly.
function Point.StartLoop()
if LoopStarted then return false end
LoopStarted = true
-- Remove the "local data = {}" line from here
CreateThread(function()
while LoopStarted do
local playerPed = PlayerPedId()
while playerPed == -1 do
Wait(100)
playerPed = PlayerPedId()
end
local playerCoords = GetEntityCoords(playerPed)
local targetsExist = false
local playerCellKey = Point.GetCellKey(playerCoords)
local nearbyCells = Point.GetNearbyCells(playerCoords)
local playerSpeed = GetEntitySpeed(playerPed)
local maxWeight = 1000
local waitTime = ADAPTIVE_WAIT and math.max(maxWeight/10, maxWeight - playerSpeed * maxWeight/10) or maxWeight
-- Process only points in nearby cells
for _, cellKey in ipairs(nearbyCells) do
if GridCells[cellKey] then
for id, point in pairs(GridCells[cellKey].points) do
targetsExist = true
-- Update entity position if needed
local oldCellKey = point.cellKey
if point.isEntity then
point.coords = GetEntityCoords(point.target)
point.cellKey = Point.GetCellKey(point.coords)
Point.UpdateInGrid(point, oldCellKey)
end
local coords = point.coords and vector3(point.coords.x, point.coords.y, point.coords.z) or vector3(0, 0, 0)
local distance = #(playerCoords - coords)
--local distance = #(playerCoords - point.coords)
-- Check if player entered/exited the point
if distance < point.distance then
if not point.inside then
point.inside = true
data[point.id] = data[point.id] or point.args or {}
data[point.id] = point.onEnter(point, data[point.id])
insidePoints[point.id] = point
end
-- Modified main loop exit handler
elseif point.inside then
point.inside = false
data[point.id] = data[point.id] or point.args or {}
local result = point.onExit(point, data[point.id])
data[point.id] = result ~= nil and result or data[point.id] -- ← Use consistent fallback
point.args = data[point.id] -- ← Update point.args to match data[point.id]
insidePoints[point.id] = nil
end
if point.onNearby then
point.onNearby(GridCells[cellKey]?.points, waitTime)
end
end
end
end
for id, insidepoint in pairs(insidePoints) do
local pos = insidepoint.coords and vector3(insidepoint.coords.x, insidepoint.coords.y, insidepoint.coords.z) or vector3(0, 0, 0)
local dist = #(playerCoords - pos)
if dist > insidepoint.distance then
insidepoint.inside = false
data[insidepoint.id] = data[insidepoint.id] or insidepoint.args or {}
local result = insidepoint.onExit(insidepoint, data[insidepoint.id])
data[insidepoint.id] = result ~= nil and result or data[insidepoint.id]
insidepoint.args = data[insidepoint.id] -- ← Keep data in sync
insidePoints[insidepoint.id] = nil
end
end
Wait(waitTime) -- Faster updates when moving quickly
end
end)
return true
end
---Create a point based on a vector or entityID
---@param id string
---@param target number || vector3
---@param distance number
---@param _onEnter function
---@param _onExit function
---@param _onNearby function
---@param data self
---@return table
function Point.Register(id, target, distance, args, _onEnter, _onExit, _onNearby)
local isEntity = type(target) == "number"
local coords = isEntity and GetEntityCoords(target) or target
local self = {}
self.id = id
self.target = target -- Store entity ID or Vector3
self.isEntity = isEntity
self.coords = coords
self.distance = distance
self.onEnter = _onEnter or function() end
self.onExit = _onExit or function() end
self.onNearby = _onNearby or function() end
self.inside = false -- Track if player is inside
self.args = args or {}
ActivePoints[id] = self
Point.RegisterInGrid(self)
Point.StartLoop()
return self
end
---Remove an exsisting point by its id
---@param id string
function Point.Remove(id)
local point = ActivePoints[id]
if point then
local cellKey = point.cellKey
if GridCells[cellKey] and GridCells[cellKey].points[id] then
GridCells[cellKey].points[id] = nil
GridCells[cellKey].count = GridCells[cellKey].count - 1
if GridCells[cellKey].count <= 0 then
GridCells[cellKey] = nil
end
end
ActivePoints[id] = nil
end
end
---Returnes a point by its id
---@param id string
---@return table
function Point.Get(id)
return ActivePoints[id]
end
---Returns all points
---@return table
function Point.GetAll()
return ActivePoints
end
-- Usage example for checking nearby points
-- --
-- ▀█▀ █▄█ █ ▄▀▀ █ ▄▀▀ █▀ █ █ ▄▀▀ █▄▀ █ █▄ █ ▄▀ █▄█ ▄▀▄ ▀█▀ █▀▄ ▄▀▄ █ █▄ █ ▀█▀ ▄▀▀ █▀ ▄▀▄ █▀▄ ▄▀▀ █▀▄ ▄▀▄ █ █ █ ██▀ ▀▄▀
-- █ █ █ █ ▄█▀ █ ▄█▀ █▀ ▀▄█ ▀▄▄ █ █ █ █ ▀█ ▀▄█ █ █ ▀▄▀ █ ██ █▀ ▀▄▀ █ █ ▀█ █ ▄█▀ █▀ ▀▄▀ █▀▄ ▀▄▄ █▀▄ ▀▄▀ ▀▄▀▄▀ █▄▄ █▄▄ █
--[[
Point.Register("point1", vector3(100, 100, 30), 5.0,
function(point)
print("Entered point1")
end,
function(point)
print("Exited point1")
end,
function(nearbyPoints)
print("Point1 has nearby points:")
for id, point in pairs(nearbyPoints) do
print("- " .. id .. " at distance: " .. #(point.coords - ActivePoints["point1"].coords))
end
end
)
--]]
return Point
@@ -3,12 +3,12 @@ Raycast = {}
--Rework of oxs Raycast system
function Raycast.GetForwardVector(rotation)
local camRot = rotation or GetFinalRenderedCamRot(2)
-- Convert each component to radians
local rx = math.rad(camRot.x)
local ry = math.rad(camRot.y)
local rz = math.rad(camRot.z)
-- Calculate sin and cos for each axis
local sx = math.sin(rx)
local cx = math.cos(rx)
@@ -16,12 +16,12 @@ function Raycast.GetForwardVector(rotation)
local cy = math.cos(ry)
local sz = math.sin(rz)
local cz = math.cos(rz)
-- Create forward vector components
local x = -sz * math.abs(cx)
local y = cz * math.abs(cx)
local z = sx
return vector3(x, y, z)
end
@@ -34,7 +34,7 @@ function Raycast.ToCoords(startCoords, endCoords, flag, ignore)
retval, entity, finalCoords, normals, material = GetShapeTestResultIncludingMaterial(probe)
timeout = timeout - 1
Wait(0)
end
end
return retval, entity, finalCoords, normals, material
end
File renamed without changes.
-144
View File
@@ -1,144 +0,0 @@
Callbacks = {}
cbData = {}
Callback = Callback or {}
--=======================================
-- ▀█▀ █▄█ █ █▄ █ █▄▀ ▄▀▄ ██▄ ▄▀▄ █ █ ▀█▀ ▄▀▄ █▀▄ █▀▄ █ █▄ █ ▄▀ █▀▄ █▀▄ ▄▀▄ █▄ ▄█ █ ▄▀▀ ██▀ ▄▀▀ ▀█▀ ▄▀▄ ▄▀▀ ▄▀▄ █ █ ██▄ ▄▀▄ ▄▀▀ █▄▀ ▄▀▀
-- █ █ █ █ █ ▀█ █ █ █▀█ █▄█ ▀▄▀ ▀▄█ █ █▀█ █▄▀ █▄▀ █ █ ▀█ ▀▄█ █▀ █▀▄ ▀▄▀ █ ▀ █ █ ▄█▀ █▄▄ ▄█▀ █ ▀▄▀ ▀▄▄ █▀█ █▄▄ █▄▄ █▄█ █▀█ ▀▄▄ █ █ ▄█▀
--=======================================
local resource = GetCurrentResourceName() or 'unknown'
local clientToServerName = resource .. ':server:CS:TriggerCallback'
local clientToServerBackToClientName = resource .. ':client:CSC:TriggerCallback'
local serverToClientName = resource .. ':client:SC:TriggerCallback'
local serverToClientBackToServerName = resource .. ':server:SCS:TriggerCallback'
exports('Callback', Callback)
if not IsDuplicityVersion() then goto client end
-- -- -- -- -- -- -- -- -- --
-- ▄▀▀ ██▀ █▀▄ █ █ ██▀ █▀▄
-- ▄█▀ █▄▄ █▀▄ ▀▄▀ █▄▄ █▀▄
-- -- -- -- -- -- -- -- -- --
-- client to server rebound
function Callback.Register(name, callback, all)
Callback[name] = {
callback = callback,
toAll = all
}
end
RegisterNetEvent(clientToServerName, function(name, ...)
local src = source
local data = Callback[name]
if not data then return end
local func = data.callback
if not func then return end
local toAll = data.toAll and -1 or src
local cb = function(...)
TriggerClientEvent(clientToServerBackToClientName, toAll, name, ...)
end
func(src, cb, ...)
end)
-----------------------------
-- server to client rebound
function Callback.Trigger(name, src, func, ...)
if src == nil then src = -1 end
local p = promise.new()
cbData[name] = {cb = func, p = p}
if type(src) == 'table' then
for i, d in pairs(src) do
TriggerClientEvent(serverToClientName, tonumber(d), name, ...)
end
return Citizen.Await(p)
end
TriggerClientEvent(serverToClientName, tonumber(src), name, ...)
return Citizen.Await(p)
end
RegisterNetEvent(serverToClientBackToServerName, function(name, ...)
print('Rebound')
local data = cbData[name]
if not data then return end
local func = data.cb
if not func then return end
data.p:resolve(func(...) or true)
cbData[name] = nil
end)
-----------------------------
exports('RegisterCallback', Callback.Register)
exports('TriggerCallback', Callback.Trigger)
-- -- -- -- -- -- -- -- -- --
-- ▄▀▀ █ █ ██▀ █▄ █ ▀█▀
-- ▀▄▄ █▄▄ █ █▄▄ █ ▀█ █
-- -- -- -- -- -- -- -- -- --
if IsDuplicityVersion() then return Callback end
::client::
cbRebounds = {}
function Callback.Register(name, callback, all)
Callback[name] = {
callback = callback,
}
end
function Callback.RegisterRebound(name, callback)
cbRebounds[name] = callback
end
-- client to server rebound
function Callback.Trigger(name, func, ...)
local p = promise.new()
TriggerServerEvent(clientToServerName, name, ...)
cbData[name] = {cb = func, p = p}
return Citizen.Await(p)
end
RegisterNetEvent(clientToServerBackToClientName, function(name, ...)
local clientRebound = cbRebounds[name]
if clientRebound then
clientRebound(...)
end
local data = cbData[name]
if not data then return end
local func = data.cb
if not func then return end
data.p:resolve(func(...) or true)
cbData[name] = nil
end)
-----------------------------
-- server to client rebound
RegisterNetEvent(serverToClientName, function(name, ...)
local data = Callback[name]
if not data then return end
local func = data.callback
if not func then return end
local cb = function(...)
TriggerServerEvent(serverToClientBackToServerName, name, ...)
end
func(cb, ...)
end)
-----------------------------
exports('RegisterCallback', Callback.Register)
exports('RegisterRebound', Callback.RegisterRebound)
exports('TriggerCallback', Callback.Trigger)
return Callback
-35
View File
@@ -1,35 +0,0 @@
local ReboundEntities = ReboundEntities or Require("shared/rebound_entities.lua")
local Actions = Actions or Require("shared/actions.lua")
local LA = LA or Require("shared/la.lua")
REA = {}
if not IsDuplicityVersion() then goto client end
if IsDuplicityVersion() then return end
::client::
local ActionsInProgress = {}
Action.Create("LerpToPosition", function(reboundId, start, position, duration, shouldRepeat, overrideStartTime)
local re = ReboundEntities.Get(reboundId)
assert(re, "Rebound entity not found")
local entity = re and re.entity
if not entity then return end
local startTime = GetGameTimer()
local endTime = overrideStartTime or startTime + duration
ActionsInProgress[reboundId] = {reboundId, start, position, duration, shouldRepeat, startTime}
local t = 0
CreateThread(function()
while shouldRepeat or t < 1 do
t = (GetGameTimer() - startTime) / duration
local lerpPosition = LA.LerpVector(start, position, t)
SetEntityCoords(entity, lerpPosition)
Wait(0)
end
end)
end)
File renamed without changes.
@@ -1,20 +1,43 @@
Utility = Utility or {}
local blipIDs = {}
local spawnedPeds = {}
local ActivePoints = {}
---commentThis will create a prop with the passed model string at the coords and heading specified optionally networked or not.
---@param model string | number
---@param coords table
---@param heading number
---@param networked boolean
---@return number | nil
Utility.CreateProp = function(model, coords, heading, networked)
Utility.LoadModel(model)
if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end
if not HasModelLoaded(model) then return nil, 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
---This will get the street name and crossing name at the specified coordinates.
---@param coords table
---@return string
---@return string
Utility.GetStreetNameAtCoords = function(coords)
local streetHash, crossingHash = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
local streetName = GetStreetNameFromHashKey(streetHash)
local crossingName = GetStreetNameFromHashKey(crossingHash)
return streetName, crossingName
end
---This will create a vehicle with the passed model string at the coords and heading specified.
---@param model string
---@param coords table
---@param heading number
---@param networked boolean
---@return number| nil
---@return table
Utility.CreateVehicle = function(model, coords, heading, networked)
Utility.LoadModel(model)
if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end
if not HasModelLoaded(model) then return nil, {}, 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)
@@ -23,15 +46,24 @@ Utility.CreateVehicle = function(model, coords, heading, networked)
return vehicle, { networkid = NetworkGetNetworkIdFromEntity(vehicle) or 0, coords = GetEntityCoords(vehicle), heading = GetEntityHeading(vehicle), }
end
---This will create a ped with the passed model string at the coords and heading specified.
---@param model string
---@param coords table
---@param heading number
---@param networked boolean
---@return number| nil
Utility.CreatePed = function(model, coords, heading, networked, settings)
Utility.LoadModel(model)
if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end
if not HasModelLoaded(model) then return nil, Prints.Error("Model Has Not Loaded") end
local spawnedEntity = CreatePed(0, model, coords.x, coords.y, coords.z, heading, networked, false)
SetModelAsNoLongerNeeded(model)
table.insert(spawnedPeds, spawnedEntity)
return spawnedEntity
end
---This will display a busy spinner with the passed text.
---@param text string
---@return boolean
Utility.StartBusySpinner = function(text)
AddTextEntry(text, text)
BeginTextCommandBusyString(text)
@@ -40,6 +72,8 @@ Utility.StartBusySpinner = function(text)
return true
end
---This will stop a busy spinner if one is currently active.
---@return boolean
Utility.StopBusySpinner = function()
if BusyspinnerIsOn() then
BusyspinnerOff()
@@ -48,6 +82,15 @@ Utility.StopBusySpinner = function()
return false
end
---comment Creates a blip at the specified coordinates with the specified parameters. If sprite/color/scale/label are not provided, default values will be used.
---@param coords table
---@param sprite number
---@param color number
---@param scale number
---@param label string
---@param shortRange boolean
---@param displayType number
---@return integer
Utility.CreateBlip = function(coords, sprite, color, scale, label, shortRange, displayType)
local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
SetBlipSprite(blip, sprite or 8)
@@ -62,6 +105,9 @@ Utility.CreateBlip = function(coords, sprite, color, scale, label, shortRange, d
return blip
end
---This will remove a blip if it exists in the blipIDs table.
---@param blip number
---@return boolean
Utility.RemoveBlip = function(blip)
local success = false
for i, storedBlip in ipairs(blipIDs) do
@@ -75,6 +121,9 @@ Utility.RemoveBlip = function(blip)
return success
end
---Loads a model into memory. If the model is not valid or not in the game files, it will return false.
---@param model string | number
---@return boolean
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
@@ -87,6 +136,9 @@ Utility.LoadModel = function(model)
return HasModelLoaded(model)
end
---This function will request an animation dictionary and wait until it is loaded. If the dictionary is not valid, it will return false.
---@param dict string
---@return boolean
Utility.RequestAnimDict = function(dict)
RequestAnimDict(dict)
local count = 0
@@ -97,6 +149,9 @@ Utility.RequestAnimDict = function(dict)
return HasAnimDictLoaded(dict)
end
---This will remove a ped if it exists in the spawnedPeds table. It will also delete the entity if it exists.
---@param entity number
---@return boolean
Utility.RemovePed = function(entity)
local success = false
if DoesEntityExist(entity) then
@@ -112,6 +167,10 @@ Utility.RemovePed = function(entity)
return success
end
---This will use a native text input menu to allow the user to enter text. It will return the entered text or false if cancelled.
---@param text string
---@param length number
---@return string
Utility.NativeInputMenu = function(text, length)
local maxLength = Math.Clamp(length, 1, 50)
local menutText = text or 'enter text'
@@ -128,6 +187,9 @@ Utility.NativeInputMenu = function(text, length)
return false
end
---This will get the current skin data of the entity passed. It will return a table with the clothing and props data.
---@param entity number
---@return table
Utility.GetEntitySkinData = function(entity)
local skinData = {}
for i = 0, 11 do
@@ -139,6 +201,10 @@ Utility.GetEntitySkinData = function(entity)
return skinData
end
---This will set the skin data of the entity passed. It will set the clothing and props data from the skinData table.
---@param entity number
---@param skinData table
---@return boolean
Utility.SetEntitySkinData = function(entity, skinData)
for i = 0, 11 do
SetPedComponentVariation(entity, i, skinData.clothing[i][1], skinData.clothing[i][2], 0)
@@ -149,6 +215,8 @@ Utility.SetEntitySkinData = function(entity, skinData)
return true
end
---This will reload the skin data of the entity passed. It will set the clothing and props data from the skinData table and delete any attached objects.
---@return boolean
Utility.ReloadSkin = function()
local skinData = Utility.GetEntitySkinData(cache.ped)
Utility.SetEntitySkinData(cache.ped, skinData)
@@ -162,18 +230,47 @@ Utility.ReloadSkin = function()
return true
end
---This will display a native help text on the screen. It will add a text entry and display it for the specified duration.
---@param text string
---@param duration number
Utility.HelpText = function(text, duration)
AddTextEntry(text, text)
BeginTextCommandDisplayHelp(text)
EndTextCommandDisplayHelp(0, false, true, duration or 5000)
end
---This will display 3D help text at the specified coordinates.
---@param coords table
---@param text string
---@param scale number
Utility.Draw3DHelpText = function(coords, text, scale)
local onScreen, x, y = GetScreenCoordFromWorldCoord(coords.x, coords.y, coords.z)
if onScreen then
SetTextScale(scale or 0.35, scale or 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry("STRING")
SetTextCentre(1)
AddTextComponentString(text)
DrawText(x, y)
local factor = (string.len(text)) / 370
DrawRect(x, y + 0.0125, 0.015 + factor, 0.03, 41, 11, 41, 100)
end
end
---This will display a native help text on the screen. It will add a text entry and display it for the specified duration.
---@param text string
Utility.NotifyText = function(text)
AddTextEntry(text, text)
SetNotificationTextEntry(text)
DrawNotification(false, true)
end
---This will teleport a player to the specified coordinates. If a condition function is passed it will verify that condition is met and then it will fade the screen out and in, freeze the player during the teleport to allow for collisions to load, and call the afterTeleportFunction if provided.
---@param coords table
---@param conditionFunction function | optional
---@param afterTeleportFunction function | optional
Utility.TeleportPlayer = function(coords, conditionFunction, afterTeleportFunction)
if conditionFunction ~= nil then
if not conditionFunction() then
@@ -200,11 +297,21 @@ Utility.TeleportPlayer = function(coords, conditionFunction, afterTeleportFuncti
end
end
---This will get a model hash from a string or number.
---@param model string | number
---@return number
Utility.GetEntityHashFromModel = function(model)
if type(model) ~= 'number' then model = joaat(model) end
return model
end
---commentThis will get the closest player, the distance to that player from the coords and the server ID of that player.
---@param coords table
---@param distanceScope number
---@param includeMe boolean
---@return integer
---@return integer
---@return integer
Utility.GetClosestPlayer = function(coords, distanceScope, includeMe)
local players = GetActivePlayers()
local closestPlayer = 0
@@ -227,7 +334,7 @@ Utility.GetClosestPlayer = function(coords, distanceScope, includeMe)
return closestPlayer, closestDistance, GetPlayerServerId(closestPlayer)
end
---This function is used to register a point on the map, functions are fired when in the distance/exiting the area
---This function is is deprecated and will be removed in the future. Please use Pont.Register instead.
---@param pointID string
---@param pointCoords table
---@param pointDistance number
@@ -235,39 +342,26 @@ end
---@param _onExit function
---@param _nearby function
Utility.RegisterPoint = function(pointID, pointCoords, pointDistance, _onEnter, _onExit, _nearby)
ActivePoints[pointID] = lib.points.new({
coords = pointCoords,
distance = pointDistance,
onEnter = function(self)
_onEnter(self)
end,
onExit = function(self)
_onExit(self)
end,
nearby = function(self)
_nearby(self)
end
})
return Point.Register(pointID, pointCoords, pointDistance, nil, _onEnter, _onExit, _nearby)
end
-- Function to retrieve the zone by the pointID
---This function is is deprecated and will be removed in the future. Please use Point.Get instead.
---@param pointID string
Utility.GetPointById = function(pointID)
return ActivePoints[pointID]
return Point.Get(pointID)
end
---This function is is deprecated and will be removed in the future. Please use Point.GetAll instead.
---@return table | nil
Utility.GetActivePoints = function()
return ActivePoints
return Point.GetAll()
end
---Pass the point ID to remove the point from the map
---This function is is deprecated and will be removed in the future. Please use Point.Remove instead.
---@param pointID string
---@return boolean
---@return nil
Utility.RemovePoint = function(pointID)
if not ActivePoints[pointID] then return false end
ActivePoints[pointID]:remove()
ActivePoints[pointID] = nil
return true
return Point.Remove(pointID)
end
AddEventHandler('onResourceStop', function(resource)
View File
Whitespace-only changes.
+197
View File
@@ -0,0 +1,197 @@
Callbacks = {}
cbData = {}
Callback = Callback or {}
--=======================================
-- ▀█▀ █▄█ █ █▄ █ █▄▀ ▄▀▄ ██▄ ▄▀▄ █ █ ▀█▀ ▄▀▄ █▀▄ █▀▄ █ █▄ █ ▄▀ █▀▄ █▀▄ ▄▀▄ █▄ ▄█ █ ▄▀▀ ██▀ ▄▀▀ ▀█▀ ▄▀▄ ▄▀▀ ▄▀▄ █ █ ██▄ ▄▀▄ ▄▀▀ █▄▀ ▄▀▀
-- █ █ █ █ █ ▀█ █ █ █▀█ █▄█ ▀▄▀ ▀▄█ █ █▀█ █▄▀ █▄▀ █ █ ▀█ ▀▄█ █▀ █▀▄ ▀▄▀ █ ▀ █ █ ▄█▀ █▄▄ ▄█▀ █ ▀▄▀ ▀▄▄ █▀█ █▄▄ █▄▄ █▄█ █▀█ ▀▄▄ █ █ ▄█▀
--=======================================
local resource = GetCurrentResourceName() or 'unknown'
local clientToServerName = resource .. ':server:CS:TriggerCallback'
local clientToServerBackToClientName = resource .. ':client:CSC:TriggerCallback'
local serverToClientName = resource .. ':client:SC:TriggerCallback'
local serverToClientBackToServerName = resource .. ':server:SCS:TriggerCallback'
exports('Callback', Callback)
if not IsDuplicityVersion() then goto client end
-- -- -- -- -- -- -- -- -- --
-- ▄▀▀ ██▀ █▀▄ █ █ ██▀ █▀▄
-- ▄█▀ █▄▄ █▀▄ ▀▄▀ █▄▄ █▀▄
-- -- -- -- -- -- -- -- -- --
-- client to server rebound
function Callback.Register(name, callback, all)
Callback[name] = {
callback = callback,
toAll = all
}
end
-- Handle client requests and send response back to client(s)
RegisterNetEvent(clientToServerName, function(name, cbId, ...)
local src = source
local data = Callback[name]
if not data then return end
local func = data.callback
if not func then return end
local toAll = data.toAll and -1 or src
-- Create response handler
local packed = table.pack(func(src, ...))
TriggerClientEvent(clientToServerBackToClientName, toAll, name, cbId, table.unpack(packed))
end)
-- Server to client trigger function - supports both callback and direct return
function Callback.Trigger(name, src, callbackOrArg, ...)
if src == nil then src = -1 end
-- Determine if the third parameter is a callback function or an argument
local hasCallback = type(callbackOrArg) == 'function' or (type(callbackOrArg) == 'table' and rawget(callbackOrArg, '__cfx_functionReference'))
local callback = hasCallback and callbackOrArg or nil
-- Adjust args based on whether the callback is present
local args = hasCallback and {...} or {callbackOrArg, ...}
local cbId = name .. '_' .. math.random(1000000, 9999999)
local p = promise.new()
-- Store promise data
cbData[cbId] = {
cb = callback,
p = p
}
-- Trigger for single player or multiple players
if type(src) == 'table' then
for i, d in pairs(src) do
TriggerClientEvent(serverToClientName, tonumber(d), name, cbId, table.unpack(args))
end
else
TriggerClientEvent(serverToClientName, tonumber(src), name, cbId, table.unpack(args))
end
-- If no callback was provided, wait for the promise and return directly
local result = Citizen.Await(p)
-- If there's only one value, return it directly
if #result == 1 then
return result[1]
else
return table.unpack(result or {})
end
end
-- Handle responses to server requests
RegisterNetEvent(serverToClientBackToServerName, function(name, cbId, ...)
local data = cbData[cbId]
if not data then return end
-- Process callback if provided
if data.cb then
data.cb({...})
end
-- Always resolve the promise with all args for direct returns
data.p:resolve({...})
cbData[cbId] = nil
end)
exports('RegisterCallback', Callback.Register)
exports('TriggerCallback', Callback.Trigger)
-- -- -- -- -- -- -- -- -- --
-- ▄▀▀ █ █ ██▀ █▄ █ ▀█▀
-- ▀▄▄ █▄▄ █ █▄▄ █ ▀█ █
-- -- -- -- -- -- -- -- -- --
if IsDuplicityVersion() then return Callback end
::client::
cbRebounds = {}
function Callback.Register(name, callback)
Callback[name] = {
callback = callback,
}
end
function Callback.RegisterRebound(name, callback)
cbRebounds[name] = callback
end
-- Client to server trigger - supports both callback and direct return
function Callback.Trigger(name, callbackOrArg, ...)
-- Determine if the second parameter is a callback function or an argument
local hasCallback = type(callbackOrArg) == 'function' or (type(callbackOrArg) == 'table' and rawget(callbackOrArg, '__cfx_functionReference'))
local callback = hasCallback and callbackOrArg or nil
-- Adjust args based on whether the callback is present
local args = hasCallback and {...} or {callbackOrArg, ...}
local cbId = name .. '_' .. math.random(1000000, 9999999)
local p = promise.new()
-- Store promise data
cbData[cbId] = {
cb = callback,
p = p
}
-- Trigger the server event
TriggerServerEvent(clientToServerName, name, cbId, table.unpack(args))
-- If no callback was provided, wait for the promise and return directly
if not hasCallback then
local result = Citizen.Await(p)
-- If there's only one value, return it directly
if #result == 1 then
return result[1]
else
return table.unpack(result)
end
end
-- Otherwise, return nothing (callback will handle it)
return nil
end
-- Handle responses from server
RegisterNetEvent(clientToServerBackToClientName, function(name, cbId, ...)
-- Check for global rebounding callbacks
local clientRebound = cbRebounds[name]
if clientRebound then
clientRebound(...)
end
-- Handle the specific callback instance
local data = cbData[cbId]
if not data then return end
-- Process callback if provided
if data.cb then
data.cb(...)
end
-- Always resolve the promise with all args for direct returns
data.p:resolve({...})
cbData[cbId] = nil
end)
-- Handle server requests to client
RegisterNetEvent(serverToClientName, function(name, cbId, ...)
local data = Callback[name]
if not data then return end
local func = data.callback
if not func then return end
-- Create response handler
TriggerServerEvent(serverToClientBackToServerName, name, cbId, func(...))
end)
exports('RegisterCallback', Callback.Register)
exports('RegisterRebound', Callback.RegisterRebound)
exports('TriggerCallback', Callback.Trigger)
return Callback
@@ -1,5 +1,11 @@
Ids = Ids or {}
-- for unique ids
---This will generate a unique id.
---@param tbl table
---@param len number
---@param pattern string
---@return string
Ids.CreateUniqueId = function(tbl, len, pattern) -- both optional
tbl = tbl or {} -- table to check uniqueness. Ids to check against must be the key to the tables value
len = len or 8
@@ -21,22 +27,43 @@ Ids.CreateUniqueId = function(tbl, len, pattern) -- both optional
return id
end
---This will generate a unique id.
---@param tbl table
---@param len number
---@return string
Ids.RandomUpper = function(tbl, len)
return Ids.CreateUniqueId(tbl, len, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
end
---This will generate a unique id.
---@param tbl table
---@param len number
---@return string
Ids.RandomLower = function(tbl, len)
return Ids.CreateUniqueId(tbl, len, "abcdefghijklmnopqrstuvwxyz")
end
---This will generate a unique id.
---@param tbl table
---@param len number
---@return string
Ids.RandomString = function(tbl, len)
return Ids.CreateUniqueId(tbl, len, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
end
---This will generate a unique id.
---@param tbl table
---@param len number
---@return string
Ids.RandomNumber = function(tbl, len)
return Ids.CreateUniqueId(tbl, len, "0123456789")
end
---This will generate a unique id.
---@param tbl table
---@param len number
---@return string
Ids.Random = function(tbl, len)
return Ids.CreateUniqueId(tbl, len)
end
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,18 +6,27 @@ local function printMessage(level, color, message)
print(color .. '[' .. level .. ']:', message)
end
---This will print a colored message to the console with the designated prefix.
---@param message string
Prints.Info = function(message)
printMessage('INFO', '^5', message)
end
---This will print a colored message to the console with the designated prefix.
---@param message string
Prints.Warn = function(message)
printMessage('WARN', '^3', message)
end
---This will print a colored message to the console with the designated prefix.
---@param message string
Prints.Error = function(message)
printMessage('ERROR', '^1', message)
end
---This will print a colored message to the console with the designated prefix.
---@param message string
Prints.Debug = function(message)
printMessage('DEBUG', '^2', message)
end
File renamed without changes.
@@ -0,0 +1,35 @@
-- local ReboundEntities = ReboundEntities or Require("shared/rebound_entities.lua")
-- local Actions = Actions or Require("shared/actions.lua")
-- local LA = LA or Require("shared/la.lua")
-- REA = {}
-- if not IsDuplicityVersion() then goto client end
-- if IsDuplicityVersion() then return end
-- ::client::
-- local ActionsInProgress = {}
-- Action.Create("LerpToPosition", function(reboundId, start, position, duration, shouldRepeat, overrideStartTime)
-- local re = ReboundEntities.Get(reboundId)
-- assert(re, "Rebound entity not found")
-- local entity = re and re.entity
-- if not entity then return end
-- local startTime = GetGameTimer()
-- local endTime = overrideStartTime or startTime + duration
-- ActionsInProgress[reboundId] = {reboundId, start, position, duration, shouldRepeat, startTime}
-- local t = 0
-- CreateThread(function()
-- while shouldRepeat or t < 1 do
-- t = (GetGameTimer() - startTime) / duration
-- local lerpPosition = LA.LerpVector(start, position, t)
-- SetEntityCoords(entity, lerpPosition)
-- Wait(0)
-- end
-- end)
-- end)
@@ -46,6 +46,14 @@ Table.TableContainsKey = function(tbl, search)
return false
end
Table.TableGetKeys = function(tbl)
local keys = {}
for k ,_ in pairs(tbl) do
table.insert(keys,k)
end
return keys
end
Table.GetClosest = function(coords, tbl)
local closestPoint = nil
local dist = math.huge
+43 -14
View File
@@ -1,16 +1,45 @@
{
"locale-unit-test": "This is a test string",
"place_object_place": "[E] Place \n",
"place_object_cancel": "[X] Cancel \n",
"place_object_scroll_up": "[SCROLL UP] Turn right \n",
"place_object_scroll_down": "[SCROLL DOWN] Turn left",
"enter_text": "Enter Text",
"no_prop_defined": "You didnt define any object to place",
"Shops": {"NotEnoughMoney": "You dont have enough money to buy this item", "Input":"Amount Input", "PurchaseAmount":"Purchase Quanity","PurchasedItem": "You Have Purchased ", "CurrencySymbol": "$", "Confirm":"Confirm Purchase","AreYouSure":"Are you sure you want to purchase a ", "PayByCash": "Pay by cash", "PayByCard": "Pay by card" },
"locale-unit-test": "This is a test string",
"place_object_place": "[E] Place \n",
"place_object_cancel": "[X] Cancel \n",
"place_object_scroll_up": "[SCROLL UP] Turn right \n",
"place_object_scroll_down": "[SCROLL DOWN] Turn left",
"enter_text": "Enter Text",
"no_prop_defined": "You didnt define any object to place",
"Shops": {
"NotEnoughMoney": "You dont have enough money to buy this item",
"Input": "Amount Input",
"PurchaseAmount": "Purchase Quanity",
"PurchasedItem": "You Have Purchased ",
"CurrencySymbol": "$",
"Confirm": "Confirm Purchase",
"AreYouSure": "Are you sure you want to purchase a ",
"PayByCash": "Pay by cash",
"PayByCard": "Pay by card"
},
"UNITTEST": {
"UNITTESTA": "Im a %s %s",
"UNITTEST": {
"UNITTESTA": "Im a %s %s",
"UNITTEST": {
"UNITTESTA": "\n.-._ _,-,\n`._`-._ _,-'_,'\n `._ `-._ _,-' _,'\n `._ `-._ __.-----.__ _,-' _,'\n `._ `#===\\\"\\\"\\\" \\\"\\\"\\\"===#' _,'\n `._/) ._ _. (\\_,'\n )*' **.__ __.** '*(\n # .==..__ \\\"\\\" \\\"\\\" __..==, #\n # `\\\"._(_). .(_)_.\\\"' #"
}
}
}
"UNITTESTA": "\n.-._ _,-,\n`._`-._ _,-'_,'\n `._ `-._ _,-' _,'\n `._ `-._ __.-----.__ _,-' _,'\n `._ `#===\\\"\\\"\\\" \\\"\\\"\\\"===#' _,'\n `._/) ._ _. (\\_,'\n )*' **.__ __.** '*(\n # .==..__ \\\"\\\" \\\"\\\" __..==, #\n # `\\\"._(_). .(_)_.\\\"' #"
}
},
"accessibility": {
"cb_command": "colourblindness",
"cb_title": "Colourblindness Options",
"cb_desc": "Select your type of colourblindness\nCurrent Colourblindness: %s",
"cb_none": "None",
"cb_updated": "Colourblindness has been updated to %s",
"cb_default_title": "No Colourblindness",
"cb_default_desc": "No colourblindness.\nThis is the default option.",
"cb_protanomaly_title": "Protanomaly",
"cb_protanomaly_desc": "Red-green color blindness.\nMakes certain shades of red look more green and less bright.\nThis type is mild and usually doesn’t get in the way of normal activities.",
"cb_deuteranomaly_title": "Deuteranomaly",
"cb_deuteranomaly_desc": "Red-green color blindness.\nIt makes certain shades of green look more red.\nThis type is mild and doesn’t usually get in the way of normal activities.",
"cb_dual_title": "Protanopia and Deuteranopia",
"cb_dual_desc": "Red-green color blindness.\nMakes someone unable to tell the difference between red and green at all.",
"cb_tritanopia_title": "Tritanopia",
"cb_tritanopia_desc": "Blue-yellow color blindness that makes someone unable to tell the difference between blue and green, purple and red, and yellow and pink.\nIt also makes colors look less bright.",
"cb_tritanomaly_title": "Tritanomaly",
"cb_tritanomaly_desc": "Blue-yellow color blindness makes it hard to tell the difference between blue and green and between yellow and red."
}
}
+20 -1
View File
@@ -5,5 +5,24 @@
"place_object_scroll_up": "[SCROLL UP] Direita\n",
"place_object_scroll_down": "[SCROLL DOWN] Esquerda",
"enter_text": "Inserir Texto",
"no_prop_defined": "Não definiu nenhum objeto para colocar"
"no_prop_defined": "Não definiu nenhum objeto para colocar",
"accessibility": {
"cb_command": "daltônico",
"cb_title": "Opções de daltonismo",
"cb_desc": "Selecione seu tipo de daltonismo\nDaltonismo atual: %s",
"cb_none": "Nenhum",
"cb_updated": "O daltonismo foi atualizado para %s",
"cb_default_title": "Sem daltonismo",
"cb_default_desc": "Sem daltonismo.\nEsta é a opção padrão.",
"cb_protanomaly_title": "Protanomalia",
"cb_protanomaly_desc": "Daltonismo vermelho-verde.\nFaz com que certos tons de vermelho pareçam mais verdes e menos brilhantes.\nEste tipo é leve e geralmente não atrapalha as atividades normais.",
"cb_deuteranomaly_title": "Deuteranomalia",
"cb_deuteranomaly_desc": "Daltonismo vermelho-verde.\nFaz com que certos tons de verde pareçam mais vermelhos.\nEste tipo é leve e geralmente não atrapalha as atividades normais.",
"cb_dual_title": "Protanopia e Deuteranopia",
"cb_dual_desc": "Daltonismo vermelho-verde.\nFaz com que alguém não consiga distinguir entre vermelho e verde.",
"cb_tritanopia_title": "Tritanopia",
"cb_tritanopia_desc": "Daltonismo azul-amarelo que faz com que alguém não consiga distinguir a diferença entre azul e verde, roxo e vermelho, e amarelo e rosa.\nTambém faz com que as cores pareçam menos brilhantes.",
"cb_tritanomaly_title": "Tritanomalia",
"cb_tritanomaly_desc": "O daltonismo azul-amarelo dificulta a distinção entre azul e verde e entre amarelo e vermelho.",
}
}
+210
View File
@@ -0,0 +1,210 @@
local colourblind = GetResourceKvpString('colourblind') or "default"
local QB = false
if (BridgeClientConfig.MenuSystem == "auto" and GetResourceState("qb-menu") ~= "started") or (BridgeClientConfig.MenuSystem ~= "auto" and BridgeClientConfig.MenuSystem == "qb-menu") then
QB = true
end
Accessibility = Accessibility or {}
RegisterCommand(locale("accessibility.cb_command"), function()
Accessibility.updatecolourblindness()
end, false)
Accessibility.updatecolourblindness = function()
local currentCB = locale("accessibility.cb_"..colourblind.."_title")
local cbIcon = "fas fa-eye-low-vision"
Menu.Open({
id = 'colourblind_update',
title = locale("accessibility.cb_title"),
options = {
{
title = locale("accessibility.cb_title"),
description = locale("accessibility.cb_desc"):format(currentCB),
disabled = true,
},
{
title = locale("accessibility.cb_default_title"),
description = locale("accessibility.cb_default_desc"),
icon = "fas fa-eye",
onSelect = function()
colourblind = "default"
SetResourceKvp('colourblind', colourblind)
Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000)
end
},
{
title = locale("accessibility.cb_protanomaly_title"),
description = locale("accessibility.cb_protanomaly_desc"),
icon = cbIcon,
onSelect = function()
colourblind = "protanomaly"
SetResourceKvp('colourblind', colourblind)
Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000)
end
},
{
title = locale("accessibility.cb_deuteranomaly_title"),
description = locale("accessibility.cb_deuteranomaly_desc"),
icon = cbIcon,
onSelect = function()
colourblind = "deuteranomaly"
SetResourceKvp('colourblind', colourblind)
Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000)
end
},
{
title = locale('accessibility.cb_dual_title'),
description = locale("accessibility.cb_dual_desc"),
icon = cbIcon,
onSelect = function()
colourblind = "dual"
SetResourceKvp('colourblind', colourblind)
Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000)
end
},
{
title = locale("accessibility.cb_tritanopia_title"),
description = locale("accessibility.cb_tritanopia_desc"),
icon = cbIcon,
onSelect = function()
colourblind = "tritanopia"
SetResourceKvp('colourblind', colourblind)
Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000)
end
},
{
title = locale("accessibility.cb_tritanomaly_title"),
description = locale("accessibility.cb_tritanomaly_desc"),
icon = cbIcon,
onSelect = function()
colourblind = "tritanomaly"
SetResourceKvp('colourblind', colourblind)
Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000)
end
},
}},QB)
end
Accessibility.hexToRgb = function(hex)
hex = hex:gsub("#", "")
local r,g,b = tonumber("0x" .. hex:sub(1, 2)),tonumber("0x" .. hex:sub(3, 4)),tonumber("0x" .. hex:sub(5, 6))
return r, g, b
end
Accessibility.rgbToHex = function(r, g, b)
return string.format("#%02x%02x%02x", r, g, b)
end
Accessibility.rgbToHsl = function(r, g, b)
r = r / 255
g = g / 255
b = b / 255
local max = math.max(r, g, b)
local min = math.min(r, g, b)
local h, s, l = 0, 0, (max + min) / 2
if max == min then
h, s = 0, 0 -- achromatic
else
local d = max - min
s = l > 0.5 and d / (2 - max - min) or d / (max + min)
if max == r then
h = (g - b) / d + (g < b and 6 or 0)
elseif max == g then
h = (b - r) / d + 2
elseif max == b then
h = (r - g) / d + 4
end
h = h / 6
end
return h, s, l
end
Accessibility.hslToRgb = function(h, s, l)
local r, g, b
if s == 0 then
r, g, b = l, l, l -- achromatic
else
local function hue2rgb(p, q, t)
if t < 0 then t = t + 1 end
if t > 1 then t = t - 1 end
if t < 1 / 6 then return p + (q - p) * 6 * t end
if t < 1 / 2 then return q end
if t < 2 / 3 then return p + (q - p) * (2 / 3 - t) * 6 end
return p
end
local q = l < 0.5 and l * (1 + s) or l + s - l * s
local p = 2 * l - q
r = hue2rgb(p, q, h + 1 / 3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1 / 3)
end
return math.floor(r * 255), math.floor(g * 255), math.floor(b * 255)
end
Accessibility.adjustColourForColourblindness = function(num, returnAsRGB)
local r, g, b
if type(num) ~= "table" and num:match("^#%x%x%x%x%x%x$") then
r, g, b = Accessibility.hexToRgb(num) -- Convert hex to RGB
else
r, g, b = num.r, num.g, num.b -- If it's already RGB, use it directly
end
local h, s, l = Accessibility.rgbToHsl(r, g, b) -- Convert RGB to HSL
-- Adjust hue values based on colourblindness type
if colourblind == "protanomaly" then -- Red-blind
-- Shift towards blue/cyan
h = (h + 0.5) % 1 -- Shift by 180 degrees
elseif colourblind == "deuteranomaly" then -- Green-blind
-- Shift towards blue/magenta
h = (h + 0.33) % 1 -- Shift by 120 degrees
elseif colourblind == "dual" then -- Protanopia and Deuteranopia (Red-Green blind)
-- More significant shift towards blue/yellow
-- This is a more drastic shift to maximize contrast
if h < 0.166 then -- Reddish hues
h = 0.66 -- Shift to blue
elseif h < 0.5 then -- Greenish hues
h = 0.166 -- Shift to yellow
else
h = h -- Leave blue/purple hues alone
end
-- Increase saturation and lightness to make colours more distinct
s = math.min(s * 1.5, 1)
l = math.min(l * 1.2, 1)
elseif colourblind == "tritanopia" then -- Blue-blind
-- Shift towards red/yellow
h = (h + 0.16) % 1 -- Shift by 60 degrees
elseif colourblind == "tritanomaly" then
h = (h + 0.08) % 1
end
-- Convert back to RGB
r, g, b = Accessibility.hslToRgb(h, s, l)
if returnAsRGB then
return {r = r, g = g, b = b}
else
-- Convert back to HEX
local newHex = Accessibility.rgbToHex(r, g, b)
return newHex
end
end
---@returns a colour adjusted for colourblindness in HEX if variable `returnAsRGB` is false
---@param colourName string Colour name in HEX format or RGB format
-- This is the trigger function for altering colours for colourblindness :D
Accessibility.getAdjustedColour = function(colourName, returnAsRGB)
local originalHex = colourName
if originalHex then
if colourblind == "default" then
if type(colourName) == "table" and not returnAsRGB then
return Accessibility.rgbToHex(colourName.r, colourName.g, colourName.b)
else
return originalHex
end
else
return Accessibility.adjustColourForColourblindness(originalHex, returnAsRGB)
end
else
Prints.Error("Invalid Colour Name^0] [^3"..colourName.."^0")
return "#FFFFFF" -- Default to white if the colour name is invalid
end
end
+12
View File
@@ -1,22 +1,34 @@
--[[This module is incomplete]]--
Clothing = Clothing or {}
ClothingBackup = {}
---This will set the peds skin data to the specified table. It will also store previous skin in the event it needs returned to original.
---@param data table
---@return boolean
Clothing.SetAppearance = function(data)
ClothingBackup = Clothing.GetAppearance()
Utility.SetEntitySkinData(cache.ped, data)
return true
end
---This will return a table of the players ped appearance
---@return table
Clothing.GetAppearance = function()
return Utility.GetEntitySkinData(cache.ped)
end
---This will return the peds clothing to the previously stored clothing
---@return boolean
Clothing.RestoreAppearance = function()
Utility.SetEntitySkinData(cache.ped, ClothingBackup)
return true
end
---This will reload the peds skin data from the backup table. This is used when the skin data is changed and needs to be reloaded.
---@return boolean
Clothing.ReloadSkin = function()
Utility.SetEntitySkinData(cache.ped, ClothingBackup)
return true
+2 -2
View File
@@ -1,3 +1,5 @@
--[[This module is incomplete]]--
Clothing = Clothing or {}
Clothing.SetAppearance = function(src, data)
@@ -13,8 +15,6 @@ Clothing.ReloadSkin = function(src)
end
RegisterNetEvent('community_bridge:client:SetAppearance', function(data)
Clothing.SetAppearance(data)
end)
-142
View File
@@ -1,142 +0,0 @@
if GetResourceState('esx_skin') ~= 'started' then return end
Clothing = Clothing or {}
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
@@ -1,31 +0,0 @@
if GetResourceState('fivem-appearance') ~= 'started' then return end
Clothing = Clothing or {}
Clothing.SetAppearance = function(data)
local clothing = {}
if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
clothing = data.male
else
clothing = data.female
end
ClothingBackup = exports['fivem-appearance']:getPedAppearance(cache.ped)
exports['fivem-appearance']:setPedAppearance(cache.ped, clothing)
return true
end
Clothing.GetAppearance = function()
return exports['fivem-appearance']:getPedAppearance(cache.ped)
end
Clothing.RestoreAppearance = function()
if not next(ClothingBackup) then
return false
end
exports['fivem-appearance']:setPedAppearance(cache.ped, ClothingBackup)
return true
end
Clothing.ReloadSkin = function()
TriggerEvent("fivem-appearance:client:reloadSkin", true)
return true
end
@@ -1,42 +0,0 @@
if GetResourceState('illenium-appearance') ~= 'started' then return end
Clothing = Clothing or {}
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)
Prints.Debug(json.encode(clothingData, {indent = true}))
ClothingBackup = 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, ClothingBackup.components)
exports['illenium-appearance']:setPedProp(cache.ped, ClothingBackup.props)
return true
end
Clothing.ReloadSkin = function()
TriggerEvent("illenium-appearance:client:reloadSkin", true)
end
-75
View File
@@ -1,75 +0,0 @@
if GetResourceState('qb-clothing') ~= 'started' then return end
Clothing = Clothing or {}
Clothing.SetAppearance = function(data)
local clothingData = {}
local repackedTable = {}
if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
clothingData = data.male
else
clothingData = data.female
end
ClothingBackup = 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 _, v in pairs(clothingData) do
if componentMap[v.component_id] then
repackedTable[componentMap[v.component_id]] = {drawable = v.drawable, texture = v.texture}
elseif propMap[v.prop_id] then
repackedTable[propMap[v.prop_id]] = {drawable = v.drawable, texture = v.texture}
elseif specialMap[v.eye_color_id] then
repackedTable[specialMap[v.eye_color_id]] = {drawable = v.drawable, texture = v.texture}
elseif specialMap[v.moles_id] then
repackedTable[specialMap[v.moles_id]] = {drawable = v.drawable, texture = v.texture}
elseif specialMap[v.ageing_id] then
repackedTable[specialMap[v.ageing_id]] = {drawable = v.drawable, texture = v.texture}
elseif specialMap[v.hair_id] then
repackedTable[specialMap[v.hair_id]] = {drawable = v.drawable, texture = v.texture}
elseif specialMap[v.face_id] then
repackedTable[specialMap[v.face_id]] = {drawable = v.drawable, texture = v.texture}
end
end
TriggerEvent('qb-clothing:client:loadOutfit', repackedTable)
return true
end
Clothing.GetAppearance = function()
ClothingBackup = Utility.GetEntitySkinData(cache.ped)
return Utility.GetEntitySkinData(cache.ped)
end
Clothing.RestoreAppearance = function()
return Utility.SetEntitySkinData(cache.ped, ClothingBackup)
end
Clothing.ReloadSkin = function()
return exports['qb-clothing']:reloadSkin(GetEntityHealth(cache.ped))
end
-8
View File
@@ -1,8 +0,0 @@
if GetResourceState('qb-clothing') ~= 'started' then return end
RegisterNetEvent('qb-clothing:saveSkin', function(model, skin)
local src = source
if model and skin then
TriggerClientEvent('community_bridge:client:updateClothingBackup', src, skin)
end
end)
+4 -1
View File
@@ -1,3 +1,6 @@
--[[This module is incomplete]]--
local promises = {}
local activeDialogue = nil
local pendingCameraDestroy = false
@@ -59,7 +62,7 @@ function Dialogue.Open( name, dialogue, characterOptions, dialogueOptions, onSel
local offsetY = math.cos(angleRad) * 1.5
-- Get position in front of ped based on their heading
local endLocation = GetEntityCoords(entity) + vector3(offsetX, offsetY, 0.5) + offset
local endLocation = GetEntityCoords(entity) + vector3(offsetX * offset.x, offsetY * offset.y, 0.5)
if not cam then cam = CreateCam("DEFAULT_SCRIPTED_CAMERA", 1) end
local camPos = GetCamCoord(cam)
@@ -1,5 +1,8 @@
Dispatch = Dispatch or {}
---This will send an alert to currently supported dispatch systems.
---@param data table The data to send to the dispatch system.
---@return nil
Dispatch.SendAlert = function(data)
TriggerServerEvent('community_bridge:Server:DispatchAlert', {
sprite = data.blipData.sprite or 161,
@@ -0,0 +1,40 @@
if GetResourceState('lb-tablet') ~= 'started' then return end
Dispatch = Dispatch or {}
local function getPriorityLevel(priority)
if priority == 1 then
return 'low'
elseif priority == 2 then
return 'medium'
elseif priority == 3 then
return 'high'
else
return 'medium'
end
end
---commentThis will send an alert to the passed jobs
---@param data table
Dispatch.SendAlert = function(data)
local streetName, _ = Utility.GetStreetNameAtCoords(data.coords)
local priority = getPriorityLevel(data.priority)
if type(data.jobs) == 'table' then
data.jobs = data.jobs[1]
end
if data.time and data.time > 1000 then
data.time = math.floor((data.time / 1000) + 0.5)
end
local alertData = {
priority = priority,
code = data.code or '10-80',
title = 'Dispatch Alert!',
description = data.message,
location = {
label = streetName,
coords = vec2(data.coords.x, data.coords.y)
},
time = data.time or 10000,
job = data.jobs,
}
TriggerServerEvent("community_bridge:server:dispatch:sendAlert", alertData)
end
@@ -0,0 +1,6 @@
if GetResourceState('lb-tablet') ~= 'started' then return end
Dispatch = Dispatch or {}
RegisterNetEvent("community_bridge:server:dispatch:sendAlert", function(data)
exports["lb-tablet"]:AddDispatch(data) -- this has a return value but we dont really have a use for it atm.
end)
@@ -1,4 +1,5 @@
if GetResourceState('ps-dispatch') ~= 'started' then return end
if GetResourceState('lb-tablet') == 'started' then return end
Dispatch = Dispatch or {}
Dispatch.SendAlert = function(data)
@@ -1,2 +1,3 @@
if GetResourceState('ps-dispatch') ~= 'started' then return end
if GetResourceState('lb-tablet') == 'started' then return end
Dispatch = Dispatch or {}
@@ -0,0 +1,14 @@
if GetResourceState('redutzu-mdt') ~= 'started' then return end
Dispatch = Dispatch or {}
Dispatch.SendAlert = function(data)
local streetName, _ = Utility.GetStreetNameAtCoords(data.coords)
local alertData = {
code = data.code or '10-80',
message = data.message or "Dispatch Alert",
street = streetName,
time = data.time or 10000,
coords = data.coords,
}
TriggerServerEvent("community_bridge:server:dispatch:sendAlert", alertData)
end
@@ -0,0 +1,12 @@
if GetResourceState('redutzu-mdt') ~= 'started' then return end
Dispatch = Dispatch or {}
RegisterNetEvent("community_bridge:server:dispatch:sendAlert", function(data)
TriggerEvent('redutzu-mdt:server:addDispatchToMDT', {
code = data.code,
title = data.message,
street = data.street,
duration = data.time,
coords = data.coords
})
end)
@@ -2,6 +2,11 @@ if GetResourceState('doors_creator') ~= 'started' then return end
Doorlock = Doorlock or {}
---This will toggle the lock status of the door.
---@param doorID string
---@param toggle boolean
---@return boolean
Doorlock.ToggleDoorLock = function(doorID, toggle)
local state = toggle
if state then
+2
View File
@@ -2,6 +2,8 @@ if GetResourceState('ox_doorlock') ~= 'started' then return end
Doorlock = Doorlock or {}
---This will get the closest door to the ped
---@return string | nil
Doorlock.GetClosestDoor = function()
return exports.ox_doorlock:getClosestDoor()
end
+14
View File
@@ -14,6 +14,11 @@ Framework.GetPlayerData = function()
return ESX.PlayerData
end
Framework.GetFrameworkJobs = function()
local jobs = lib.callback.await('community_bridge:Callback:GetFrameworkJobs', false)
return jobs
end
---comment
---@return string
Framework.GetPlayerDob = function()
@@ -75,6 +80,15 @@ Framework.GetPlayerInventory = function()
return playerData.inventory
end
---comment
---@param item string
---@return number
Framework.GetItemCount = function(item)
local inventory = Framework.GetPlayerInventory()
if not inventory then return 0 end
return inventory[item].count or 0
end
---comment
---@return boolean
Framework.GetIsPlayerDead = function()
+13
View File
@@ -23,6 +23,10 @@ Framework.GetPlayerIdentifier = function(src)
return xPlayer.getIdentifier()
end
Framework.GetFrameworkJobs = function()
return ESX.GetJobs()
end
-- Framework.GetPlayerName(src)
-- Returns the first and last name of the player.
Framework.GetPlayerName = function(src)
@@ -259,6 +263,11 @@ Framework.RegisterUsableItem = function(itemName, cb)
ESX.RegisterUsableItem(itemName, func)
end
RegisterNetEvent("esx:playerLoaded", function()
local src = source
TriggerEvent("community_bridge:Server:OnPlayerLoaded", src)
end)
RegisterNetEvent("esx:playerLogout", function()
local src = source
TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
@@ -269,6 +278,10 @@ AddEventHandler("playerDropped", function()
TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
end)
lib.callback.register('community_bridge:Callback:GetFrameworkJobs', function(source)
return Framework.GetFrameworkJobs() or {}
end)
Framework.Commands = {}
Framework.Commands.Add = function(name, help, arguments, argsrequired, callback, permission, ...)
ESX.RegisterCommand(name, permission, function(xPlayer, args, showError)
+47
View File
@@ -5,6 +5,8 @@ QBCore = exports['qb-core']:GetCoreObject()
Framework = {}
---This will get the name of the framework being used (if a supported framework).
---@return string
Framework.GetFrameworkName = function()
return 'qb-core'
end
@@ -13,12 +15,31 @@ Framework.GetPlayerData = function()
return QBCore.Functions.GetPlayerData()
end
---This will return a table of all the jobs in the framework.
---@return table
Framework.GetFrameworkJobs = function()
local jobs = {}
for k, v in pairs(QBCore.Shared.Jobs) do
table.insert(jobs, {
name = k,
label = v.label,
grade = v.grades
})
end
return jobs
end
---This will get the players birth date
---@return string
Framework.GetPlayerDob = function()
local player = QBCore.Functions.GetPlayerData()
local playerData = player.PlayerData
return playerData.charinfo.birthdate
end
---This will return the players metadata for the specified metadata key.
---@param metadata table | string
---@return table | string | number | boolean
Framework.GetPlayerMetaData = function(metadata)
return QBCore.Functions.GetPlayerData().metadata[metadata]
end
@@ -49,15 +70,25 @@ Framework.GetItemInfo = function(item)
return repackedTable
end
---This will get the players identifier (citizenid) etc.
---@return string
Framework.GetPlayerIdentifier = function()
return QBCore.Functions.GetPlayerData().citizenid
end
---This will get the players name (first and last).
---@return string
---@return string
Framework.GetPlayerName = function()
local playerData = QBCore.Functions.GetPlayerData()
return playerData.charinfo.firstname, playerData.charinfo.lastname
end
---This will return the players job name, job label, job grade name and job grade level.
---@return string
---@return string
---@return string
---@return string
Framework.GetPlayerJob = function()
local playerData = QBCore.Functions.GetPlayerData()
return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
@@ -67,6 +98,20 @@ Framework.HasItem = function(item)
return QBCore.Functions.HasItem(item)
end
---comment
---@param item string
---@return number
Framework.GetItemCount = function(item)
local frameworkInv = QBCore.Functions.GetPlayerData().items
local count = 0
for _, v in pairs(frameworkInv) do
if v.name == item then
count = count + v.amount
end
end
return count
end
Framework.GetPlayerInventory = function()
local items = {}
local frameworkInv = QBCore.Functions.GetPlayerData().items
@@ -85,6 +130,8 @@ Framework.GetPlayerInventory = function()
return items
end
---This will get a players dead status.
---@return boolean
Framework.GetIsPlayerDead = function()
local playerData = QBCore.Functions.GetPlayerData()
return playerData.metadata["isdead"] or playerData.metadata["inlaststand"]
+68 -12
View File
@@ -18,8 +18,21 @@ Framework.GetPlayerIdentifier = function(src)
return playerData.citizenid
end
Framework.GetFrameworkJobs = function()
local jobs = {}
for k, v in pairs(QBCore.Shared.Jobs) do
table.insert(jobs, {
name = k,
label = v.label,
grade = v.grades
})
end
return jobs
end
-- Framework.GetPlayerName(src)
-- Returns the first and last name of the player.
---@return string, string
Framework.GetPlayerName = function(src)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -27,6 +40,8 @@ Framework.GetPlayerName = function(src)
return playerData.charinfo.firstname, playerData.charinfo.lastname
end
---This will get the players birth date
---@return string
Framework.GetPlayerDob = function(src)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -126,6 +141,7 @@ end
-- Framework.SetMetadata(src, metadata, value)
-- Adds the specified metadata key and number value to the player's data.
---@return boolean | nil
Framework.SetPlayerMetadata = function(src, metadata, value)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -144,6 +160,7 @@ end
-- Framework.AddStress(src, value)
-- Adds the specified value to the player's stress level and updates the client HUD.
---@return number | nil
Framework.AddStress = function(src, value)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -156,6 +173,7 @@ end
-- Framework.RemoveStress(src, value)
-- Removes the specified value from the player's stress level and updates the client HUD.
---@return number | nil
Framework.RemoveStress = function(src, value)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -168,6 +186,7 @@ end
-- Framework.AddHunger(src, value)
-- Adds the specified value from the player's hunger level.
---@return number | nil
Framework.AddHunger = function(src, value)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -180,6 +199,7 @@ end
-- Framework.AddThirst(src, value)
-- Adds the specified value from the player's thirst level.
---@return number | nil
Framework.AddThirst = function(src, value)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -190,6 +210,9 @@ Framework.AddThirst = function(src, value)
return newThirst
end
---This will get the hunger of a player
---@param src any
---@return number | nil
Framework.GetHunger = function(src)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -198,6 +221,10 @@ Framework.GetHunger = function(src)
return newHunger
end
---This will get the thirst of a player
---@param src any
---@return number | nil
Framework.GetThirst = function(src)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -224,8 +251,9 @@ Framework.GetPlayerGang = function(src)
return playerData.gang.name
end
-- Framework.GetPlayersByJob(jobname)
-- returns a table of player sources that have the specified job name.
---This will get a table of player sources that have the specified job name.
---@param job any
---@return table
Framework.GetPlayersByJob = function(job)
local players = QBCore.Functions.GetPlayers()
local playerList = {}
@@ -238,8 +266,12 @@ Framework.GetPlayersByJob = function(job)
return playerList
end
-- Framework.GetPlayerJob(src)
-- Returns the job name, label, grade name, and grade level of the player.
---This will get the players job info
---@param src number
---@return string
---@return string
---@return string
---@return string
Framework.GetPlayerJob = function(src)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -247,14 +279,21 @@ Framework.GetPlayerJob = function(src)
return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
end
-- Framework.SetPlayerJob(src, name, grade)
-- Sets the player's job to the specified name and grade.
---@param src number
---@param name string
---@param grade string
---@return nil
Framework.SetPlayerJob = function(src, name, grade)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
return player.Functions.SetJob(name, grade)
end
---This will toggle a players duty status
---@param src number
---@param status boolean
---@return nil
Framework.ToggleDuty = function(src, status)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -262,8 +301,12 @@ Framework.ToggleDuty = function(src, status)
TriggerEvent('QBCore:Server:SetDuty', src, player.PlayerData.job.onduty)
end
-- Framework.AddAccountBalance(src, _type, amount)
-- Adds the specified amount to the player's account balance of the specified type.
---This will add money based on the type of account (money/bank)
---@param src number
---@param _type string
---@param amount number
---@return boolean | nil
Framework.AddAccountBalance = function(src, _type, amount)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -271,8 +314,11 @@ Framework.AddAccountBalance = function(src, _type, amount)
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.
---This will remove money based on the type of account (money/bank)
---@param src number
---@param _type string
---@param amount number
---@return boolean | nil
Framework.RemoveAccountBalance = function(src, _type, amount)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -280,8 +326,10 @@ Framework.RemoveAccountBalance = function(src, _type, amount)
return player.Functions.RemoveMoney(_type, amount)
end
-- Framework.GetAccountBalance(src, _type)
-- Returns the player's account balance of the specified type.
---This will remove money based on the type of account (money/bank)
---@param src number
---@param _type string
---@return string | nil
Framework.GetAccountBalance = function(src, _type)
local player = QBCore.Functions.GetPlayer(src)
if not player then return end
@@ -329,6 +377,9 @@ Framework.SetMetadata = function(src, item, slot, metadata)
return player.Functions.AddItem(item, 1, freeSlot, metadata)
end
---This will get all owned vehicles for the player
---@param src number
---@return table
Framework.GetOwnedVehicles = function(src)
local citizenId = Framework.GetPlayerIdentifier(src)
local result = MySQL.Sync.fetchAll("SELECT vehicle, plate FROM player_vehicles WHERE citizenid = '" .. citizenId .. "'")
@@ -352,7 +403,12 @@ Framework.RegisterUsableItem = function(itemName, cb)
QBCore.Functions.CreateUseableItem(itemName, func)
end
RegisterNetEvent("QBCore:Server:OnPlayerUnload", function()
RegisterNetEvent("QBCore:Server:OnPlayerLoaded", function()
local src = source
TriggerEvent("community_bridge:Server:OnPlayerLoaded", src)
end)
RegisterNetEvent("QBCore:Server:OnPlayerUnload", function(source)
local src = source
TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
end)
+12
View File
@@ -12,6 +12,10 @@ Framework.GetPlayerData = function()
return QBox.GetPlayerData()
end
Framework.GetFrameworkJobs = function()
return QBox.GetJobs()
end
Framework.GetPlayerDob = function()
local playerData = QBox.GetPlayerData()
return playerData.charinfo.birthdate
@@ -40,6 +44,14 @@ Framework.GetPlayerInventory = function()
return QBox.GetPlayerData().items
end
---comment
---@param item string
---@return number
Framework.GetItemCount = function(item)
-- This seems to be exclusively for ox_inventory, if other inventories are used, they need to be bridged in the inventory module. Until then we will return 0 and a print.
return 0, print("Community_bridge:WARN: GetItemCount is not implemented for this framework, please use the inventory module to get the item count. If you are using a diffrent inventory please let us know so we can bridge it and have less nonsense.")
end
Framework.GetIsPlayerDead = function()
local platerData = QBox.GetPlayerData()
return platerData.metadata["isdead"] or platerData.metadata["inlaststand"]
+9
View File
@@ -15,6 +15,10 @@ Framework.GetPlayerDob = function(src)
return playerData.charinfo.birthdate
end
Framework.GetFrameworkJobs = function()
return QBox.GetJobs()
end
-- Framework.GetPlayerIdentifier(src)
-- Returns the citizen ID of the player.
Framework.GetPlayerIdentifier = function(src)
@@ -297,6 +301,11 @@ Framework.GetOwnedVehicles = function(src)
return vehicles
end
RegisterNetEvent("QBCore:Server:OnPlayerLoaded", function()
local src = source
TriggerEvent("community_bridge:Server:OnPlayerLoaded", src)
end)
RegisterNetEvent("QBCore:Server:OnPlayerUnload", function()
local src = source
TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
+9 -2
View File
@@ -1,11 +1,18 @@
Fuel = Fuel or {}
----print("Fuel: Loading Defualt")
---This will get the fuel level of the vehicle.
---@param vehicle number The vehicle entity ID.
---@return number fuel The fuel level of the vehicle.
Fuel.GetFuel = function(vehicle)
if not DoesEntityExist(vehicle) then return 0.0 end
return GetVehicleFuelLevel(vehicle)
end
Fuel.SetFuel = function(vehicle, fuel, type)
---This will set the fuel level of the vehicle.
---@param vehicle number The vehicle entity ID.
---@param fuel number The fuel level to set.
---@return nil
Fuel.SetFuel = function(vehicle, fuel)
if not DoesEntityExist(vehicle) then return end
return SetVehicleFuelLevel(vehicle, fuel)
end
+4 -2
View File
@@ -2,6 +2,7 @@ local resourceName = "lc_fuel"
local configValue = BridgeClientConfig.Fuel
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
--print("Fuel: Loading lc_fuel")
if GetResourceState('lc_fuel') ~= 'started' then return end
Fuel = Fuel or {}
Fuel.GetFuel = function(vehicle)
@@ -9,7 +10,8 @@ Fuel.GetFuel = function(vehicle)
return exports["lc_fuel"]:GetFuel(vehicle)
end
Fuel.SetFuel = function(vehicle, fuel)
Fuel.SetFuel = function(vehicle, fuel, type)
if not DoesEntityExist(vehicle) then return end
return exports["lc_fuel"]:SetFuel(vehicle, fuel)
end
end
+4
View File
@@ -14,6 +14,10 @@ Inventory.HasItem = function(item)
return Framework.HasItem(item)
end
Inventory.GetItemCount = function(item)
return Framework.GetItemCount(item)
end
---comment
---@param item string
---@return string
+1 -1
View File
@@ -83,4 +83,4 @@ end
---@return string
Inventory.GetImagePath = function(item)
return "https://avatars.githubusercontent.com/u/47620135"
end
end
@@ -27,6 +27,18 @@ Inventory.HasItem = function(item)
return origin:HasItem(item)
end
---comment
---@param item string
---@return number
Inventory.GetItemCount = function(item)
local searchItem = origin:Search('slots', item)
local count = 0
for _, v in pairs(searchItem) do
count = count + v.count
end
return count
end
---comment
---@param item string
---@return string
@@ -29,6 +29,13 @@ Inventory.HasItem = function(item)
return hasItem
end
---comment
---@param item string
---@return number
Inventory.GetItemCount = function(item)
return ox_inventory:GetItemCount(item, nil, false)
end
---comment
---@param item string
---@return string
+8 -8
View File
@@ -37,7 +37,7 @@ Inventory.GetItem = function(src, item, metadata)
return ox_inventory:GetItem(src, item, metadata, false)
end
---comment
---This will get the item from the specified slot.
---@param src number
---@param slot number
---@return table
@@ -63,14 +63,14 @@ Inventory.HasItem = function(src, item)
return count > 0
end
---comment
---This wil return the players inventory.
---@param src number
---@return table
Inventory.GetPlayerInventory = function(src)
return ox_inventory:GetInventoryItems(src, false)
end
---comment
---This is to get if there is available space in the inventory.
---@param src number
---@param item string
---@param count number
@@ -79,7 +79,7 @@ Inventory.CanCarryItem = function(src, item, count)
return ox_inventory:CanCarryItem(src, item, count)
end
---comment
---This will register a stash
---@param id number||string
---@param label string
---@param slots number
@@ -106,7 +106,7 @@ Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coo
TriggerClientEvent('ox_inventory:openInventory', src, 'stash', 'stash_' .. id)
end
---comment
---This will get the data about an item such as name, label, stack, weight, description and image.
---@param item string
---@return table
Inventory.GetItemInfo = function(item)
@@ -123,7 +123,7 @@ Inventory.GetItemInfo = function(item)
return repackedTable
end
---comment
---This will set the metadata of an item in the inventory.
---@param src number
---@param item string
---@param slot number
@@ -133,7 +133,7 @@ Inventory.SetMetadata = function(src, item, slot, metadata)
ox_inventory:SetMetadata(src, slot, metadata)
end
---comment
---This will update the plate to the vehicle inside the inventory. (It will also update with jg-mechanic if using it)
---@param oldplate string
---@param newplate string
---@return boolean
@@ -144,7 +144,7 @@ Inventory.UpdatePlate = function(oldplate, newplate)
return true
end
---comment
---This will get the image path for an item, it is an alternate option to GetItemInfo. If a image isnt found will revert to community_bridge logo (useful for menus)
---@param item string
---@return string
Inventory.GetImagePath = function(item)
@@ -44,6 +44,14 @@ Inventory.GetImagePath = function(item)
return imagePath or "https://avatars.githubusercontent.com/u/47620135"
end
---comment
---@param item string
---@return number
Inventory.GetItemCount = function(item)
local searchItem = quasar:Search(item)
return searchItem or 0
end
---comment
---@return table
Inventory.GetPlayerInventory = function()
@@ -25,6 +25,14 @@ Inventory.GetItemInfo = function(item)
return repackedTable
end
---comment
---@param item string
---@return number
Inventory.GetItemCount = function(item)
local searchItem = tgiann:GetItemCount(item, nil, false)
return searchItem or 0
end
---This will return a boolean if the player has the item in the inventory
---@param item string
---@return boolean
-25
View File
@@ -47,29 +47,4 @@ function Language.Locale(str, ...)
return current
end
if BridgeSharedConfig.DebugLevel == 2 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"))
RegisterCommand("lang", function(source, args, raw)
print(Language.Locale("UNITTEST.UNITTEST.UNITTESTA"))
print(Language.Locale("UNITTEST.UNITTESTA", "Devil", "GERRRRRRR!"))
print( "Oh also this works", Language.Locale("place_object_scroll_down"))
end)
end
return Language
@@ -1,14 +1,25 @@
if GetResourceState('Renewed-Banking') ~= 'started' then return end
Managment = Managment or {}
---This will return a table with account details
---@param account string
---@return table
Managment.GetAccountMoney = function(account)
return exports['Renewed-Banking']:getAccountMoney(account)
end
---This will add money to the specified account of the passed amount
---@param account string
---@param amount number
---@return boolean
Managment.AddAccountMoney = function(account, amount)
return exports['Renewed-Banking']:addAccountMoney(account, amount)
end
---This will remove money from the specified account of the passed amount
---@param account string
---@param amount number
---@return boolean
Managment.RemoveAccountMoney = function(account, amount)
return exports['Renewed-Banking']:removeAccountMoney(account, amount)
end
+11
View File
@@ -1,14 +1,25 @@
if GetResourceState('okokBanking') ~= 'started' then return end
Managment = Managment or {}
---This will return a table with account details
---@param account string
---@return table
Managment.GetAccountMoney = function(account)
return exports['okokBanking']:GetAccount(account)
end
---This will add money to the specified account of the passed amount
---@param account string
---@param amount number
---@return boolean
Managment.AddAccountMoney = function(account, amount)
return exports['okokBanking']:AddMoney(account, amount)
end
---This will remove money from the specified account of the passed amount
---@param account string
---@param amount number
---@return boolean
Managment.RemoveAccountMoney = function(account, amount)
return exports['okokBanking']:RemoveMoney(account, amount)
end
+11
View File
@@ -1,14 +1,25 @@
if GetResourceState('qb-banking') ~= 'started' then return end
Managment = Managment or {}
---This will return a table with account details
---@param account string
---@return table
Managment.GetAccountMoney = function(account)
return exports['qb-banking']:GetAccountBalance(account)
end
---This will add money to the specified account of the passed amount
---@param account string
---@param amount number
---@return boolean
Managment.AddAccountMoney = function(account, amount)
return exports['qb-banking']:AddMoney(account, amount)
end
---This will remove money from the specified account of the passed amount
---@param account string
---@param amount number
---@return boolean
Managment.RemoveAccountMoney = function(account, amount)
return exports['qb-banking']:RemoveMoney(account, amount)
end
+1
View File
@@ -18,6 +18,7 @@ function OxToQBMenu(id, menu)
header = v.title,
txt = v.description,
icon = v.icon,
disabled = v.disabled,
}
if v.onSelect then
+4 -2
View File
@@ -2,7 +2,7 @@ Notify = Notify or {}
local notifyType = BridgeClientConfig.NotifySystem
local helptextType = BridgeClientConfig.ShowHelpText
---comment
---This will send a notify message of the type and time passed
---@param message string
---@param _type string
---@param time number
@@ -34,7 +34,7 @@ Notify.SendNotify = function(message, _type, time)
end
end
---comment
---This will show a help text message at the screen position passed
---@param message string
---@param _position string
---@return nil
@@ -61,6 +61,8 @@ Notify.ShowHelpText = function(message, _position)
end
end
---This will hide the help text message on the screen
---@return nil
Notify.HideHelpText = function()
if helptextType == 'ox' then
return exports.ox_lib:hideTextUI()
+4 -2
View File
@@ -1,6 +1,6 @@
Notify = Notify or {}
---comment
---This will send a notification to the specified player of the passed message and type
---@param src number
---@param message string
---@param _type string
@@ -9,7 +9,7 @@ Notify.SendNotify = function(src, message, _type, time)
TriggerClientEvent('community_bridge:Client:Notify', src, message, _type, time)
end
---comment
---This will show a help text message to the specified player at the screen position passed
---@param src number
---@param message string
---@param position string
@@ -17,6 +17,8 @@ Notify.ShowHelpText = function(src, message, position)
TriggerClientEvent('community_bridge:Client:ShowHelpText', src, message, position)
end
---This will hide the help text message on the screen for the specified player
---@param src number
Notify.HideHelpText = function(src)
TriggerClientEvent('community_bridge:Client:HideHelpText', src)
end
+11 -24
View File
@@ -7,30 +7,7 @@ RegisterNetEvent('community_bridge:openShop', function(_type, _title, shopData)
Shops.OpenShop(_title, shopData.inventory)
end)
Shops.FinalizeCheckOut = function(shopName, item, itemLabel, price)
if not shopName and not item and not itemLabel and not price then return end
local generatedID = Ids.CreateUniqueId()
local buildMenu = {
{
title = locale('Shops.PayByCash')..tostring(price),
description = locale('Shops.AreYouSure') .. itemLabel,
icon = "fa-solid fa-money-bill-wave",
onSelect = function(_, __, ___)
TriggerServerEvent('community_bridge:completeCheckout', shopName, item, "cash")
end
},
{
title = locale('Shops.PayByCard')..tostring(price),
description = locale('Shops.AreYouSure') .. itemLabel,
icon = "fa-solid fa-building-column",
onSelect = function(_, __, ___)
TriggerServerEvent('community_bridge:completeCheckout', shopName, item, "bank")
end
}
}
Bridge.Menu.Open({ id = generatedID, title = locale("Shops.Confirm"), options = buildMenu }, false)
end
---This is an internal event that is used to complete a transaction and offer cash/card pay
Shops.FinalizeCheckOut = function(shopName, item, itemLabel, price, amount)
if not shopName and not item and not itemLabel and not price then return end
local mathStuff = tonumber(price) * tonumber(amount)
@@ -56,6 +33,11 @@ Shops.FinalizeCheckOut = function(shopName, item, itemLabel, price, amount)
Menu.Open({ id = generatedID, title = locale("Shops.Input"), options = buildMenu }, false)
end
---This is an internal event that is used to open the amount select menu
---@param shopName string
---@param item string
---@param itemLabel string
---@param price number
Shops.AmountSelect = function(shopName, item, itemLabel, price)
if not shopName and not item and not itemLabel and not price then return end
local numberOptions = {}
@@ -71,6 +53,11 @@ Shops.AmountSelect = function(shopName, item, itemLabel, price)
end
end
---This will open a shop with the passed title and data. It will create a menu with the items in the shopData table. The items will be clickable and will open a checkout menu.
---This also verifies the shop exsists and was made first server side. This will not work when only used client side and the server side verifies the item exsists in the table as well as the shop id.
---@param title any
---@param shopData any
---@return nil
Shops.OpenShop = function(title, shopData)
if not title and not shopData and not title then return print("No Title Passed") end
local generatedID = Ids.CreateUniqueId()
+19 -2
View File
@@ -2,20 +2,37 @@ Shops = Shops or {}
local registeredShops = {}
---commentThis can open a shop for the client
---@param src number
---@param shopTitle string
---@return boolean
Shops.OpenShop = function(src, shopTitle)
if not shopTitle and not registeredShops[shopTitle] then return false end
TriggerClientEvent('community_bridge:openShop', src, 'shop', shopTitle, registeredShops[shopTitle])
return true
end
---This will create a shop to use on the client side, shops must be registered server side and exsist in the shop inventory table to allow any purchases passed.
---@param shopTitle string
---@param shopInventory table
---@param shopCoords table
---@param shopGroups table
---@return boolean
Shops.CreateShop = function(shopTitle, shopInventory, shopCoords, shopGroups)
if not shopTitle and not shopInventory and not shopCoords then return end
if not shopTitle and not shopInventory and not shopCoords then return false end
if registeredShops[shopTitle] then return true end
registeredShops[shopTitle] = {name = shopTitle, inventory = shopInventory, shopCoords = shopCoords, groups = shopGroups}
return true
end
---This is an internal event to complete a shop transaction, it will verify pass items and amounts are registered to the created shop.
---@param src number
---@param shopName string
---@param item string
---@param amount number
---@param paymentType string
---@return nil
Shops.CompleteCheckout = function(src, shopName, item, amount, paymentType)
if not src and not shopName and not item and not amount and not paymentType then return end
local ilocale = Language.Locale
local shopData = registeredShops[shopName]
+95 -2
View File
@@ -4,6 +4,20 @@ local function warnUser()
print("Currently Only Targeting Is Supported By Community Bridge, You Are Using A Resource That Requires The Target Module To Be Used.")
end
Target.FixOptions = function(options)
for k, v in pairs(options) do
local action = v.onSelect or v.action
local select = function(entityOrData)
if type(entityOrData) == 'table' then
return action(entityOrData.entity)
end
return action(entityOrData)
end
options[k].onSelect = select
end
return options
end
Target.AddGlobalPlayer = function(options)
warnUser()
end
@@ -17,15 +31,94 @@ Target.RemoveGlobalVehicle = function(options)
end
Target.AddLocalEntity = function(entities, _options)
warnUser()
local fixedOptions = Target.FixOptions(_options)
if type(entities) == "string" or type(entities) == "number" then
entities = { entities }
end
for _, entity in pairs(entities) do
local id = Ids.RandomString()
local menuData = { id = id, title = "Options", options = {} }
for k, v in pairs(fixedOptions) do
table.insert(menuData.options, {
title = ("Option " .. k),
description = "No Description",
icon = v.icon or "fas fa-code-pull-request",
args = {},
onSelect = function(selected, secondary, args)
if v.onSelect then
v.onSelect(selected, secondary, args)
end
end
})
end
Point.Register(id, entity, 5, args,
function()
local coords = GetEntityCoords(entity)
local sleep = 3000
while DoesEntityExist(entity) do
Wait(sleep)
local distance = #(coords - GetEntityCoords(PlayerPedId()))
if distance < 10 then
sleep = 0
Utility.Draw3DHelpText(coords, "Press [E] To Interact", 0.35)
if IsControlJustPressed(0, 38) then
Menu.Open(menuData, false)
end
else
sleep = 3000
end
end
end,
function()
Point.Remove(id)
end, function()
--No need for this in this one
end)
end
end
Target.AddModel = function(models, options)
warnUser()
end
Target.AddBoxZone = function(name, coords, size, heading, options)
warnUser()
local fixedOptions = Target.FixOptions(_options)
local id = Ids.RandomString()
local menuData = { id = id, title = "Options", options = {} }
for k, v in pairs(fixedOptions) do
table.insert(menuData.options, {
title = ("Option " .. k),
description = "No Description",
onSelect = function(selected, secondary, args)
if v.onSelect then
v.onSelect(selected, secondary, args)
end
end
})
end
Point.Register(id, coords, 5, args,
function()
local sleep = 3000
while true do
Wait(sleep)
local distance = #(coords - GetEntityCoords(PlayerPedId()))
if distance < 10 then
sleep = 0
Utility.Draw3DHelpText(coords, "Press [E] To Interact", 0.35)
if IsControlJustPressed(0, 38) then
Menu.Open(menuData, false)
end
else
sleep = 3000
end
end
end,
function()
Point.Remove(id)
end, function()
--No need for this in this one
end)
end
Target.RemoveGlobalPlayer = function()
+60 -40
View File
@@ -17,6 +17,9 @@ local targetZones = {}
Target = Target or {}
---This is an internal function that is used to fix the options passed to fit alternative target systems, for example qb-ox or ox-qb etc.
---@param options table
---@return table
Target.FixOptions = function(options)
for k, v in pairs(options) do
local action = v.onSelect or v.action
@@ -31,25 +34,34 @@ Target.FixOptions = function(options)
return options
end
---comment
---This will add target options to players.
---@param options table
---@return nil
Target.AddGlobalPlayer = function(options)
options = Target.FixOptions(options)
ox_target:addGlobalPlayer(options)
end
---comment
---This will remove target options from all players.
Target.RemoveGlobalPlayer = function()
---@diagnostic disable-next-line: missing-parameter
ox_target:removeGlobalPlayer()
end
---This will toggle the targeting system on or off. This is useful for when you want to disable the targeting system for a specific player entirely.
---@param bool boolean
Target.DisableTargeting = function(bool)
ox_target:disableTargeting(bool)
end
---This will add taget options to all vehicles.
---@param options table
---@return nil
Target.AddGlobalVehicle = function(options)
options = Target.FixOptions(options)
ox_target:addGlobalVehicle(options)
end
---comment
---This will remove target options from all vehicles.
---@param options table
---@return nil
Target.RemoveGlobalVehicle = function(options)
local assembledLables = {}
for k, v in pairs(options) do
@@ -58,31 +70,40 @@ Target.RemoveGlobalVehicle = function(options)
ox_target:removeGlobalVehicle(assembledLables)
end
---comment
---@param entities table
---This will generate targets on non networked entites with the passed options.
---@param entities number | table
---@param options table
---@return nil
Target.AddLocalEntity = function(entities, options)
options = Target.FixOptions(options)
ox_target:addLocalEntity(entities, options)
end
---comment
---@param models table
---This will remove the target options from a local entity. This is useful for when you want to remove target options from a specific entity.
---@param entity any
Target.RemoveLocalEntity = function(entity)
ox_target:removeLocalEntity(entity)
end
---This will add target options to all specified models. This is useful for when you want to add target options to all models of a specific type.
---@param models number | table
---@param options table
---@return nil
Target.AddModel = function(models, options)
options = Target.FixOptions(options)
ox_target:addModel(models, options)
end
---comment
---This will remove target options from all specified models.
---@param model number
Target.RemoveModel = function(model)
ox_target:removeModel(model)
end
---This will add a box zone to the target system. This is useful for when you want to add target options to a specific area.
---@param name string
---@param coords table
---@param size table
---@param heading number
---@param options table
---@return number
Target.AddBoxZone = function(name, coords, size, heading, options)
options = Target.FixOptions(options)
local target = ox_target:addBoxZone({
@@ -96,28 +117,28 @@ Target.AddBoxZone = function(name, coords, size, heading, options)
return target
end
Target.RemoveGlobalPlayer = function()
ox_target:removeGlobalPlayer()
end
---comment
---@param entity number
---@return nil
Target.RemoveLocalEntity = function(entity)
ox_target:removeLocalEntity(entity)
end
---comment
---@param model string
---@return nil
Target.RemoveModel = function(model)
ox_target:removeModel(model)
end
---comment
---This will add a circle zone to the target system. This is useful for when you want to add target options to a specific area.
---@param name string
---@param coords table
---@param radius number
---@param options table
Target.AddSphereZone = function(name, coords, radius, heading, options)
options = Target.FixOptions(options)
local target = ox_target:addSphereZone({
coords = coords,
radius = radius,
name = name,
debug = targetDebug,
options = options
})
table.insert(targetZones, { name = name, id = target, creator = GetInvokingResource() })
return target
end
---This will remove target options from a specific zone.
---@param name string
---@return nil
Target.RemoveZone = function(name)
if not name then return end
for _, data in pairs(targetZones) do
if data.name == name then
ox_target:removeZone(data.id)
@@ -128,12 +149,11 @@ Target.RemoveZone = function(name)
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
if resource ~= GetCurrentResourceName() then return end
for _, target in pairs(targetZones) do
if target.creator == resource then
ox_target:removeZone(target.id)
end
targetZones = {}
end
targetZones = {}
end)
+76 -24
View File
@@ -15,7 +15,12 @@ detectDebugEnabled()
local targetZones = {}
Target = Target or {}
local qb_target = exports['qb-target']
---This is an internal function that is used to fix the options passed to fit alternative target systems, for example qb-ox or ox-qb etc.
---@param options table
---@return table
Target.FixOptions = function(options)
for k, v in pairs(options) do
local action = v.onSelect or v.action
@@ -23,7 +28,7 @@ Target.FixOptions = function(options)
if type(entityOrData) == 'table' then
return action(entityOrData.entity)
end
return action(entityOrData)
return action(entityOrData)
end
options[k].action = select
options[k].job = v.job or v.groups
@@ -31,50 +36,90 @@ Target.FixOptions = function(options)
return options
end
---This will toggle the targeting system on or off. This is useful for when you want to disable the targeting system for a specific player entirely.
---@param bool boolean
Target.DisableTargeting = function(bool)
qb_target:AllowTargeting(not bool)
end
---This will add target options to players.
---@param options table
Target.AddGlobalPlayer = function(options)
options = Target.FixOptions(options)
exports['qb-target']:AddGlobalPlayer({
qb_target:AddGlobalPlayer({
options = options,
distance = options.distance or 1.5
})
end
---This will remove target options from all players.
Target.RemoveGlobalPlayer = function()
qb_target:RemoveGlobalPlayer()
end
---This will add taget options to all vehicles.
---@param options table
Target.AddGlobalVehicle = function(options)
options = Target.FixOptions(options)
exports['qb-target']:AddGlobalVehicle({
qb_target:AddGlobalVehicle({
options = options,
distance = options.distance or 1.5
})
end
---This will remove target options from all vehicles.
---@param options table
Target.RemoveGlobalVehicle = function(options)
local assembledLables = {}
for k, v in pairs(options) do
table.insert(assembledLables, v.label)
end
exports['qb-target']:RemoveGlobalVehicle(assembledLables)
qb_target:RemoveGlobalVehicle(assembledLables)
end
---This will generate targets on non networked entites with the passed options.
---@param entities number | table
---@param options table
Target.AddLocalEntity = function(entities, options)
options = Target.FixOptions(options)
exports['qb-target']:AddTargetEntity(entities, {
qb_target:AddTargetEntity(entities, {
options = options,
distance = options.distance or 1.5
})
end
---This will remove the target options from a local entity. This is useful for when you want to remove target options from a specific entity.
---@param entity any
Target.RemoveLocalEntity = function(entity)
qb_target:RemoveTargetEntity(entity)
end
---This will add target options to all specified models. This is useful for when you want to add target options to all models of a specific type.
---@param models number | table
---@param options table
Target.AddModel = function(models, options)
options = Target.FixOptions(options)
exports['qb-target']:AddTargetModel(models, {
qb_target:AddTargetModel(models, {
options = options,
distance = options.distance or 1.5,
})
end
---This will remove target options from all specified models.
---@param model number
Target.RemoveModel = function(model)
qb_target:RemoveTargetModel(model)
end
---This will add a box zone to the target system. This is useful for when you want to add target options to a specific area.
---@param name string
---@param coords table
---@param size table
---@param heading number
---@param options table
Target.AddBoxZone = function(name, coords, size, heading, options)
options = Target.FixOptions(options)
exports['qb-target']:AddBoxZone(name, coords, size.x, size.y, {
qb_target:AddBoxZone(name, coords, size.x, size.y, {
name = name,
debugPoly = targetDebug,
heading = heading,
@@ -87,22 +132,30 @@ Target.AddBoxZone = function(name, coords, size, heading, options)
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)
---This will add a circle zone to the target system. This is useful for when you want to add target options to a specific area.
---@param name string
---@param coords table
---@param radius number
---@param options table
Target.AddSphereZone = function(name, coords, radius, options)
options = Target.FixOptions(options)
qb_target:AddCircleZone(name, coords, radius, {
name = name,
debugPoly = targetDebug,
}, {
options = options,
distance = options.distance or 1.5,
})
table.insert(targetZones, { name = name, creator = GetInvokingResource() })
end
---This will remove target options from a specific zone.
---@param name string
Target.RemoveZone = function(name)
if not name then return end
for _, data in pairs(targetZones) do
if data.name == name then
exports['qb-target']:RemoveZone(name)
qb_target:RemoveZone(name)
table.remove(targetZones, _)
break
end
@@ -110,12 +163,11 @@ Target.RemoveZone = function(name)
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
if resource ~= GetCurrentResourceName() then return end
for _, target in pairs(targetZones) do
if target.creator == resource then
qb_target:RemoveZone(target.name)
end
targetZones = {}
end
targetZones = {}
end)
+116 -15
View File
@@ -2,10 +2,18 @@ local resourceName = "sleepless_interact"
local configValue = BridgeClientConfig.TargetSystem
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
--if GetResourceState('sleepless_interact') ~= 'started' then return end
-- This is only partially supported
local sleepless = exports.sleepless_interact
local targetDebug = false
local function detectDebugEnabled()
if BridgeClientConfig.DebugLevel == 2 then
targetDebug = true
end
end
detectDebugEnabled()
local sleepless_interact = exports.sleepless_interact
local targetZones = {}
Target = Target or {}
@@ -23,18 +31,111 @@ Target.FixOptions = function(options)
return options
end
Target.AddLocalEntity = function(entity, _options)
local options = Target.FixOptions(_options)
sleepless:addLocalEntity({
id = entity,
entity = entity,
options = options,
renderDistance = 10.0,
activeDistance = 2.0,
cooldown = 1500
})
---comment
---@param options table
---@return nil
Target.AddGlobalPlayer = function(options)
options = Target.FixOptions(options)
sleepless_interact:addGlobalPlayer(options)
end
Target.DisableTargeting = function(bool)
--sleepless_interact:disableTargeting(bool)
sleepless_interact:disableInteract(bool)
end
---comment
---@param options table
---@return nil
Target.AddGlobalVehicle = function(options)
options = Target.FixOptions(options)
sleepless_interact:addGlobalVehicle(options)
end
---comment
---@param options table
---@return nil
Target.RemoveGlobalVehicle = function(options)
local assembledLables = {}
for k, v in pairs(options) do
table.insert(assembledLables, v.name)
end
sleepless_interact:removeGlobalVehicle(assembledLables)
end
---comment
---@param entities table
---@param options table
---@return nil
Target.AddLocalEntity = function(entities, options)
options = Target.FixOptions(options)
sleepless_interact:addLocalEntity(entities, options)
end
---comment
---@param models table
---@param options table
---@return nil
Target.AddModel = function(models, options)
options = Target.FixOptions(options)
sleepless_interact:addModel(models, options)
end
---comment
---@param name string
---@param coords table
---@param size table
---@param heading number
---@param options table
---@return number
Target.AddBoxZone = function(name, coords, size, heading, options)
options = Target.FixOptions(options)
local target = sleepless_interact:addCoords({
coords = coords,
options = options,
})
table.insert(targetZones, { name = name, id = target, creator = GetInvokingResource() })
return target
end
Target.RemoveGlobalPlayer = function()
sleepless_interact:removeGlobalPlayer()
end
---comment
---@param entity number
---@return nil
Target.RemoveLocalEntity = function(entity)
sleepless:removeLocalEntity(entity)
end
sleepless_interact:removeLocalEntity(entity)
end
---comment
---@param model string
---@return nil
Target.RemoveModel = function(model)
sleepless_interact:removeModel(model)
end
---comment
---@param name string
---@return nil
Target.RemoveZone = function(name)
for _, data in pairs(targetZones) do
if data.name == name then
sleepless_interact:removeCoords(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
sleepless_interact:removeZone(target.id)
end
end
targetZones = {}
end
end)
@@ -1,9 +1,16 @@
VehicleKey = VehicleKey or {}
---This will give keys to the specifed vehicle/plate.
---@param vehicle number The vehicle entity ID.
---@param plate string The plate of the vehicle.
VehicleKey.GiveKeys = function(vehicle, plate)
return true, print("There Is No Vehicle Key System Installed")
end
---This will remove keys from the specifed vehicle/plate.
---@param vehicle number The vehicle entity ID.
---@param plate string The plate of the vehicle.
---@return boolean | nil
VehicleKey.RemoveKeys = function(vehicle, plate)
return true, print("There Is No Vehicle Key System Installed")
end
+8
View File
@@ -0,0 +1,8 @@
Weather = Weather or {}
---This will toggle the players weather/time sync
---@param toggle boolean
---@return nil
Weather.ToggleSync = function(toggle)
end
+8
View File
@@ -0,0 +1,8 @@
if GetResourceState('cd_easytime') ~= 'started' then return end
Weather = Weather or {}
---comment
---@param toggle boolean
Weather.ToggleSync = function(toggle)
TriggerEvent('cd_easytime:PauseSync', toggle)
end
@@ -1,5 +1,5 @@
if GetResourceState('qb-weathersync') ~= 'started' then return end
Weather = {}
Weather = Weather or {}
---comment
---@param toggle boolean
@@ -1,5 +1,5 @@
if GetResourceState('Renewed-Weathersync') ~= 'started' then return end
Weather = {}
Weather = Weather or {}
---comment
---@param toggle boolean
-12
View File
@@ -1,12 +0,0 @@
if GetResourceState('qb-weathersync') ~= 'started' then return end
Weather = {}
---comment
---@param toggle boolean
Weather.ToggleSync = function(toggle)
if toggle then
TriggerEvent("qb-weathersync:client:EnableSync")
else
TriggerEvent("qb-weathersync:client:DisableSync")
end
end
+17 -21
View File
@@ -6,20 +6,19 @@
-- ▄█▀ █▄▄ █▀▄ ▀▄▀ █▄▄ █▀▄
-- -- -- -- -- -- -- -- -- --
if not IsDuplicityVersion() then goto client end
exports.community_bridge:RegisterCallback('ClientToServerToClient', function(src, cb, ftpcsftug)
cb(ftpcsftug, 'some random string')
exports.community_bridge:RegisterCallback('callback_test1_name_here', function(src, var1)
if var1 == "herpaderpa" then
print("this is a test")
end
return 'some random string', "some other string"
end)
RegisterCommand('cb_server_test', function(source)
local someData = exports.community_bridge:TriggerCallback('ServerToClientToServer', source, function(ftpcsftug, derpa)
print(ftpcsftug, derpa)
return "This data gets passed up the chain"
end,"herpaderpa")
print("print", someData)
RegisterCommand('callback_test2', function(source)
local someData, other = exports.community_bridge:TriggerCallback('callback_test2_name_here', source, "herpaderpa")
print("Data From Client: ", someData, other)
end)
-- -- -- -- -- -- -- -- -- --
-- ▄▀▀ █ █ ██▀ █▄ █ ▀█▀
-- ▀▄▄ █▄▄ █ █▄▄ █ ▀█ █
@@ -27,18 +26,15 @@ end)
if IsDuplicityVersion() then return end
::client::
RegisterCommand('cb_client_test', function()
local someData = exports.community_bridge:TriggerCallback('ClientToServerToClient', function(ftpcsftug, derpa)
print(ftpcsftug, derpa, "This will fire on the player who triggered the event")
end,"herpaderpa")
print(someData)
RegisterCommand('callback_test1', function()
local somerandomstring, someotherrandomstring = exports.community_bridge:TriggerCallback('callback_test1_name_here', "herpaderpa")
print("Data From Server: ", somerandomstring, someotherrandomstring)
end)
exports.community_bridge:RegisterRebound('ClientToServerToClient', function(src, cb, ftpcsftug)
print("this is a rebound from another player or himself")
end)
-- exports.community_bridge:RegisterRebound('callback_test1', function(src, cb, ftpcsftug)
-- print("this is a rebound to all players")
-- end)
exports.community_bridge:RegisterCallback('ServerToClientToServer', function(cb, ftpcsftug)
cb(ftpcsftug, 'TestyMcTesterton')
exports.community_bridge:RegisterCallback('callback_test2_name_here', function(ftpcsftug)
return ftpcsftug, 'TestyMcTesterton'
end)
+19
View File
@@ -0,0 +1,19 @@
-- 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"))
RegisterCommand("lang", function(source, args, raw)
print(Language.Locale("UNITTEST.UNITTEST.UNITTESTA"))
print(Language.Locale("UNITTEST.UNITTESTA", "Devil", "GERRRRRRR!"))
print( "Oh also this works", Language.Locale("place_object_scroll_down"))
end, false)