Core libraryHelpers

Helpers

Police on duty, cooldowns, and loading models and animations.

On this page

Small things nearly every script needs, written once in tr_core so each script doesn't write its own.

Police on duty

TR.player.countJob(jobs, onDuty) counts the players with one of the jobs, on the server. The jobs are written the same way as for TR.player.hasJob: a name, a list of names, or names with the lowest grade that counts.

server/main.lua
local police = TR.player.countJob({ 'police', 'sheriff' }, true)
if police < Config.minPolice then
    return false, 'no_police'
end

With true, only players on duty count. TR.player.getPlayersWithJob(jobs, onDuty) gives their server ids instead, for sending each of them something.

server/main.lua
for _, cop in ipairs(TR.player.getPlayersWithJob({ police = 2 }, true)) do
    TR.notify.send(cop, { description = 'A safe is being cracked' })
end

Cooldowns

Make a cooldown once, on the server, then take it each time something starts:

server/main.lua
local robbery = TR.cooldown.new('store_robbery', {
    seconds = 1800,
    persist = true,
})

TR.callback.register('tr_robbery:start', function(src, store)
    local ok, left = robbery:take(store)
    if not ok then return false, 'cooldown', left end
    -- ...
end, { schema = { { type = 'string', max = 32 } }, rateLimit = 1 })

take starts it if it's over and returns true. If it's still running it returns false and the seconds to go, for the message.

What it's kept for is the first argument:

OwnerKept for
a player's server idthat player's character, so logging out or reconnecting doesn't reset it
any text ('fleeca_2')that one thing: a store, a bank, a site
nothingthe whole server
CallWhat it does
robbery:take(owner)Starts it if it's over; else false and the seconds to go
robbery:left(owner)Seconds to go, 0 when it's over
robbery:start(owner, seconds)Starts it, or starts it again if it's running; seconds is optional
robbery:clear(owner)Ends it now

persist = true keeps them through a server restart; without it a restart clears them. Each name can be made once in a resource.

Loading models and animations

A model, animation or particle effect has to be loaded before the game can use it. TR.stream loads it and waits, up to 5 seconds, so call it from a thread.

client/main.lua
local hash = TR.stream.model('prop_cs_cardbox_01')
if not hash then return end

local x, y, z = coords.x, coords.y, coords.z
local box = CreateObject(hash, x, y, z, false, false, false)
TR.stream.release('model', hash)
CallGives
TR.stream.model(name or hash)The model's hash, or nil
TR.stream.anim(dict)true once the animation dictionary is loaded
TR.stream.ptfx(asset)true once the particle asset is loaded
TR.stream.texture(dict)true once the texture dictionary is loaded

Each takes a timeout in ms as its second argument. Something missing from the game, or not loaded in time, gives nil or false and one line in the client console naming it.

TR.stream.release(kind, name) lets go of it (kind is 'model', 'anim', 'ptfx' or 'texture'). It is only unloaded once everything in your resource that loaded it has let go, so one part of a script can't unload a model another part still uses. An object you made keeps its model after you release it.

Still stuck? Open a ticket on Discord.