Don's Utility Functions for FiveM
Has you're script gone up the duff? Well, this is the solution for you! This is a collection of optimised utility functions that are exports for you to use in your scripts.
- duff
- Always use the latest FiveM artifacts (tested on 6683), you can find them here.
- Download the latest version from releases.
- Extract the contents of the zip file into your resources folder, into a folder which starts after your framework and any script this is a dependency for, or;
- Ensure the script in your
server.cfg
after your framework and any script this is a dependency for.
Require is a function that allows you to import modules, emulating Lua Default require function, using package.path, package.preload and package.loaded. It also precaches all modules labled as file
in the fxmanifest.lua
file and any modules that are imported using the require
function.
---@param path string @The name of the module to require. This can be a path, or a module name. If a path is provided, it must be relative to the resource root.
---@return {[string]: any} module
exports.duff:require(path)
-- Using the `require` export
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Using '@duff/shared/import.lua' in your `fxmanifest.lua`
shared_script '@duff/shared/import.lua'
array is a class for the creation and manipulation of consecutive integer indexed arrays. It provides a number of Functional Programming methods, and is designed to be used in a similar way to the Array class in JavaScript.
This is a shared module, and can be used on both the client, server and shared enviroment.
-- Using the `require` export
---@module 'duff.shared.array'
local array = exports.duff:require 'duff.shared.array'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the array object to a local variable (Lua 5.4+)
local array in duff
-- Attaching the array object to a local variable
local array = duff.array
Creates a new array.
---@param list any[]
---@return array
local tbl = array.new(list)
---@param self array
---@param pos integer
---@param value any
function array.insert(self, pos, value)
---@param self array
---@param pos integer?
function array.remove(self, pos)
---@param self array
---@param compare fun(a: any, b: any): boolean
function array.sort(self, compare)
---@param self array
---@param sep any?
---@param i integer?
---@param j integer?
function array.concat(self, sep, i, j)
Checks if a table is an array.
---@param tbl any[]|array
---@return boolean?
function array.isarray(tbl)
Adds one or more elements to the end of the array.
---@param self array
---@param arg any?
---@param ... any?
---@return array
function array.push(self, arg, ...)
Adds all elements from a table to the end of the array.
---@param self array
---@param list any[]
---@return array
function array.pusharray(self, list)
Returns the element at the specified index without removing it.
---@param self array
---@param index integer?
---@return any
function array.peek(self, index)
Returns a new array containing the elements from the specified index to the end of the array.
---@param self array
---@param index integer?
---@return any[]
function array.peekarray(self, index)
Removes and returns the element at the specified index.
---@param self array
---@param index integer?
---@return any?, array?
function array.pop(self, index)
Removes and returns a new array containing the elements from the specified index to the end of the array.
---@param self array
---@param index integer?
---@return array
function array.poparray(self, index)
Checks if the array contains a specific element or key or key-value pair.
---@param self array
---@param key integer?
---@param value any?
---@return boolean?
function array.contains(self, key, value)
Creates a shallow copy of the array.
---@param self array
---@return array
function array.copy(self)
Applies a function to each element from left to right, accumulating a result.
---@param self array
---@param func fun(acc: any, val: any): any
---@param arg any?
function array.foldleft(self, func, arg)
Applies a function to each element from right to left, accumulating a result.
---@param self array
---@param func fun(acc: any, val: any): any
---@param arg any?
function array.foldright(self, func, arg)
Creates a read-only array that can be used for enumeration.
---@param self array
---@return array enum
function array.setenum(self)
Applies a function to each element and returns a new array with the results.
---@param self array
---@param func fun(val: any): any
---@param inPlace boolean?
---@return array
function array.map(self, func, inPlace)
Returns a new array containing only the elements that satisfy a given condition.
---@param self array
---@param func fun(val: any, i: integer): boolean
---@param inPlace boolean?
---@return array
function array.filter(self, func, inPlace)
Executes a function for each element across the array.
---@param self array
---@param func fun(val: any, i: integer)
function array.foreach(self, func)
Reverses the order of elements.
---@param self array
---@param length integer?
---@return array
function array.reverse(self, length)
debug is an internal class mainly used to ensure error handling and debugging is done correctly. It provides a number of methods to help with this.
The module can only be imported using the require
export.
-- Using the `require` export
---@module 'duff.shared.debug'
local debug = exports.duff:require 'duff.shared.debug'
Retrieves the function call chain at the specified level.
---@param level integer @The level of the stack to get the function chain from.
---@return string[]? func_chain @The function chain as a string array.
function debug.getfuncchain(level)
Retrieves the level of the specified function in the call stack.
---@param func fn @The function to get the level of.
---@return integer? level @The level of the function in the call stack, or nil if the function was not found.
function debug.getfunclevel(func)
Retrieves information about the specified function.
---@param func fn @The function to get information about.
---@return {name: string, source: string, line: integer}? info @A table containing the name, source, and line number of the function, or nil if the information could not be retrieved.function.
function debug.getfuncinfo(func)
Checks if the parameter matches the expected type(s).
---@param param any @The parameter to check the type of.
---@param type_name string|string[] @The expected type(s) of the parameter.
---@param fn function @The function where the parameter is being checked.
---@param arg_no integer|string? @The argument number or name being checked.
---@return boolean? type_valid, string param_type @Returns true if the parameter type matches the expected type, or false if it does not. Also returns the actual type of the parameter.
local function check_type(param, type_name, fn, arg_no)
locale is an object containing functions for localisation and translation. It's inspired by the i18n.lua library by kikito, and provides a simple way to manage translations in your FiveM scripts.
This is a shared module, and can be used on both the client, server and shared enviroment.
The module automatically uses the servers' convars to determine locale , both dialect and region. If the convars (sets locale
) are not set, it defaults to en
.
- Interpolation
welcome = 'Hello, {name}!'
->locale.translate('welcome', {name = 'John'})
->Hello, John!
(wherename
is a key in the data table)
- Fallbacks: When a value is not found, the lib has several fallback mechanisms:
- First, it will look in the current locale's parents. For example, if the locale was set to 'en-US' and the key 'msg' was not found there, it will be looked over in 'en'.
- Second, if the value is not found in the locale ancestry, a 'fallback locale' (by default: 'en') can be used. If the fallback locale has any parents, they will be looked over too.
- Third, if all the locales have failed, but there is a param called 'default' on the provided data, it will be used.
- Using files
- The language files are stored in the
locales
folder in the resource root. - The files are named after the locale they represent, e.g.
en.lua
,en-US.lua
,es.lua
.
- The language files are stored in the
-- Using the `require` export
---@module 'duff.shared.locale'
local locale = exports.duff:require 'duff.shared.locale'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the locale object to a local variable (Lua 5.4+)
local locale in duff
-- Attaching the locale object to a local variable
local locale = duff.locale
Sets a translation key to a value.
---@param key string @A dot-separated key to set the translation value for.
---@param value string @The value to set the translation key to.
function locale.set(key, value)
Loads a translation table from a table.
---@param context string? @The context to load the translations into.
---@param data {[string]: {[string]: string}|string} @A table containing translation keys and values.
function locale.load(context, data)
The table should contain translation keys and values.
locale.load(nil, {
en = {
welcome = 'Hello, {name}!',
goodbye = 'Goodbye, {name}!',
}
})
Loads a translation table from a file.
---@param resource string? @The resource name to load the translation file from.
---@param file string? @The file path to load the translation file from.
function locale.loadfile(resource, file)
The file should return a table containing translation keys and values.
return {
en = {
welcome = 'Hello, {name}!',
goodbye = 'Goodbye, {name}!',
}
}
You can also use a context to load translations into a specific context, or even load all translations into a single context.
return {
en = {
AU = {
welcome = 'G\'day, {name}!',
goodbye = 'Later, {name}!',
},
US = {
welcome = 'Howdy, {name}!',
goodbye = 'See ya later, {name}!',
}
},
es = {
welcome = '¡Hola, {name}!',
goodbye = '¡Adiós, {name}!',
}
}
This function has a wrapper function called t
.
Translates a key to a value. This function also supports placeholders, which can be replaced by providing a table of data.
---@param key string @The key to translate.
---@param data {[string]: string}? @A table containing data to replace placeholders in the translation.
---@return string? translation @The translated value, or nil if the key was not found.
function locale.translate(key, data)
math is an object containing some useful math functions. Most notably, it contains a seedrng
function which generates a random seed based on the current time, and a random
function which generates a random number between two values which should be an improvement over the default Lua pseudo-random number generator.
-- Using the `require` export
---@module 'duff.shared.math'
local math = exports.duff:require 'duff.shared.math'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the math object to a local variable (Lua 5.4+)
local math in duff
-- Attaching the math object to a local variable
local math = duff.math
---@param val number
---@param min number
---@param max number
---@return boolean?
function math.between(val, min, max)
---@param value number
---@param min number
---@param max number
---@return number
function math.clamp(value, min, max)
---@param value number
---@param increment integer?
---@return integer
function math.round(value, increment)
---@return integer?
function math.seedrng()
---@param min integer
---@param max integer?
---@return integer
function math.random(min, max)
---@param time integer
---@param limit integer?
---@return boolean
function math.timer(time, limit)
This is a shared module, but has functions which are exclusive to their respective enviroments.
-- Using the `require` export
---@module 'duff.shared.vector'
local vector = exports.duff:require 'duff.shared.vector'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the vector object to a local variable (Lua 5.4+)
local vector in duff
-- Attaching the vector object to a local variable
local vector = duff.vector
Checks if the table is a vector and converts it to a vector.
---@param tbl {x: number, y: number, z: number?, w: number?}
---@return vector2|vector3|vector4
function vector.tabletovector(tbl)
Finds the closest vector3 in an array to a given vector3.
---@param check integer|vector3|{x: number, y: number, z: number}
---@param tbl vector3[]|integer[]
---@param radius number?
---@param excluding any[]?
---@return integer|vector3?, number?, array?
function vector.getclosest(check, list, radius, ignore)
---@param entity integer
---@return vector3?
function vector.getentityright(entity)
---@param entity integer
---@return vector3?
function vector.getentityup(entity)
---@param entity integer
---@return vector3?, vector3?, vector3?, vector3?
function vector.getentitymatrix(entity)
---@param entity integer
---@return vector3?
function vector.getentityforward(entity)
---@param entity integer
---@param offsetX number
---@param offsetY number
---@param offsetZ number
---@return vector3?
function vector.getoffsetfromentityinworldcoords(entity, offsetX, offsetY, offsetZ)
This is a client module.
-- Using the `require` export
---@module 'duff.client.blips'
local blips = exports.duff:require 'duff.client.blips'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the blips object to a local variable (Lua 5.4+)
local blips in duff
-- Attaching the blips object to a local variable
local blips = duff.blips
---@return array? blips
function blips.getall()
---@return array? blips
function blips.onscreen()
---@param coords vector3|vector3[]
---@param radius number?
---@return array? blips
function blips.bycoords(coords, radius)
---@param sprite integer
---@return array? blips
function blips.bysprite(sprite)
---@param blip integer
---@return table? blip_info
function blips.getinfo(blip)
---@param blips integer|integer[]
function blips.remove(blips)
This is a client module.
-- Using the `require` export
---@module 'duff.client.pools'
local pools = exports.duff:require 'duff.client.pools'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the pools object to a local variable (Lua 5.4+)
local pools in duff
-- Attaching the pools object to a local variable
local pools = duff.pools
---@return array? peds
function pools.getpeds()
---@return array? vehicles
function pools.getvehicles()
---@return array? objects
function pools.getobjects()
---@return array? pickups
function pools.getpickups()
---@param coords vector3|integer?
---@param ped_type integer?
---@param radius number?
---@param ignore integer[]?
---@return integer? ped, number? distance, array? peds
function pools.getclosestped(coords, ped_type, radius, ignore)
---@param coords vector3|integer?
---@param vehicle_type integer?
---@param radius number?
---@param ignore integer[]?
---@return integer? vehicle, number? distance, array? vehicles
function pools.getclosestvehicle(coords, vehicle_type, radius, ignore)
---@param coords vector3|integer?
---@param radius number?
---@param ignore integer[]?
---@return integer? object, number? distance, array? objects
function pools.getclosestobject(coords, radius, ignore)
---@param coords vector3|integer?
---@param hash string|number?
---@param radius number?
---@param ignore integer[]?
---@return integer? pickup, number? distance, array? pickups
function pools.getclosestpickup(coords, hash, radius, ignore)
This is a client module.
-- Using the `require` export
---@module 'duff.client.streaming'
local streaming = exports.duff:require 'duff.client.streaming'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the streaming object to a local variable (Lua 5.4+)
local streaming in duff
-- Attaching the streaming object to a local variable
local streaming = duff.streaming
---@param dict string
---@param isAsync boolean?
---@return boolean?
function streaming.loadanimdict(dict, isAsync)
---@param set string
---@param isAsync boolean?
---@return boolean?
function streaming.loadanimset(set, isAsync)
---@param model string|number
---@param isAsync boolean?
---@return boolean?
function streaming.loadcollision(model, isAsync)
---@param ipl string
---@param isAsync boolean?
---@return boolean?
function streaming.loadipl(ipl, isAsync)
---@param model string|number
---@param isAsync boolean?
---@return boolean?
function streaming.loadmodel(model, isAsync)
---@param fx string
---@param isAsync boolean?
---@return boolean?
function streaming.loadptfx(fx, isAsync)
This is a server module.
-- Using the `require` export
---@module 'duff.server.scope'
local scope = exports.duff:require 'duff.server.scope'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the scope object to a local variable (Lua 5.4+)
local scope in duff
-- Attaching the scope object to a local variable
local scope = duff.scope
---@param source number|integer
---@return {[string]: boolean}? Scope
function scope.getplayerscope(source)
---@param event string
---@param source number|integer
---@param ... any
---@return {[string]: boolean}? targets
function scope.triggerscopeevent(event, source, ...)
---@param event string
---@param source number|integer
---@param timer integer?
---@param ... any
function scope.createsyncedscopeevent(event, source, timer, ...)
---@param event string
function scope.removesyncedscopeevent(event)
This is a server module.
-- Using the `require` export
---@module 'duff.server.zone'
local zone = exports.duff:require 'duff.server.zone'
-- Using the `require` export on the duff object
---@module 'duff.shared.import'
local duff = exports.duff:require 'duff.shared.import'
-- Attaching the zone object to a local variable (Lua 5.4+)
local zone in duff
-- Attaching the zone object to a local variable
local zone = duff.zone
---@param check vector3|{x: number, y: number, z: number}|string
---@return boolean?, integer?
function zone.contains(check)
---@param index integer
---@return table?
function zone.getzone(index)
---@param check vector3|{x: number, y: number, z: number}|string
---@return string? name
function zone.getzonename(check)
---@param check vector3|{x: number, y: number, z: number}|string
---@return integer? index
function zone.getzoneindex(check)
---@param event string
---@param zone_id vector3|{x: number, y: number, z: number}|string
---@param onEnter fun(player: string, coords: vector3)
---@param onExit fun(player: string, coords: vector3, disconnected: boolean?)
---@param time integer?
---@param players string?\
function zone.addzoneevent(event, zone_id, onEnter, onExit, time, players)
---@param event string
function zone.removezoneevent(event)
- Join my discord.
- Use the relevant support channels.