Consumables & Portions
Consumables & Portions
Effects
An item's effect is what using it does.
burger = {
label = 'Burger',
weight = 700,
useTime = 2500,
effect = { hunger = 25 },
}
Effects are applied by the server when the use completes. A cancelled animation applies nothing.
anim names the clip from Config.Anim (eat, drink, bandage, pill, ...). The clip carries a default object for the hand; an item that looks like something else names its own with prop, and only the object changes:
cola = { effect = { thirst = 22, anim = 'drink', prop = 'prop_ecola_can' } },
coffee = { effect = { thirst = 15, anim = 'drink', prop = 'p_amb_coffeecup_01' } },
prop can also be a table — { model = ..., bone = ..., offset = vector3(...), rot = vector3(...) } — for a model whose origin sits differently in the hand. Props hang off PH_R_Hand (bone 60309), the bone the game puts held objects on, and the shipped food and drink carry the position each was measured at.
Finding those numbers is a matter of looking, not arithmetic:
invprop <playerId> prop_ecola_can
puts the model in that player's hand with the clip running — arrows move, SHIFT rotates, CTRL for fine steps, ENTER prints the line to paste, both for data/items.lua and for the admin panel's Held object box.
Who runs an item
A framework handler wins. If qb has a CreateUseableItem for the item, that handler runs it end to end — its progress bar, its animation, its prop, its numbers, and its own RemoveItem. The inventory does not consume the item first and does not apply its own effect on top, even when data/items.lua describes the same name.
That is deliberate. Your framework's food, drink and medical items already work and your scripts are written around them; replacing their behaviour because this inventory happens to be installed is a change nobody asked for. The catalogue here describes items — it does not claim them.
Two things overrule a handler, and both are a decision somebody made on this server:
- A claim.
RegisterUsable(name, ...)from a resource that means to own the item. - A takeover on the admin panel. Set a Use animation, a Held object or an effect amount (Hunger, Thirst, Health, Armour) on the item screen, and the inventory runs that item from then on: its bar, its clip, its prop, its effect. Clear the fields to hand it back.
Items nothing else handles — the ones only this catalogue knows — are run here, because there is nobody else to run them.
invroute cola
[route] cola — Cola (defined in data/items.lua)
used by: the framework handler (its own bar, clip and prop)
framework handler: yes, and it runs this item
invroute <item> answers the whole question for any item: who runs it, whether a handler exists and is being overruled, which clip and prop the player will see, and whether the item has a condition.
Portions
Off by default, as in ox_inventory: with Config.Portions.enabled = false every item is worth exactly one use and portions is ignored. A unit that was already part-eaten when portions were turned off finishes on its next use. Turn it on to have bites:
Config.Portions = { enabled = true }
portions = 4 means one burger is four bites. Each use spends one portion; the unit disappears when the last one is gone. Portions live on the unit's metadata, so a half-eaten burger stays half-eaten when it is traded or stored.
exports.aty_inventory:GetPortions(inv, slot)
exports.aty_inventory:TakePortion(inv, slot)
Use time and cancellation
useTime is how long the action bar runs. An item without one is used at once, with no bar, as ox_inventory does without usetime. The shipped food, drink and bandage take 2.5 s and body armour 3.5 s, ox's own numbers. Two rules matter:
The portion is spent at the end, never at the start. A player who cancels half way through has not eaten anything.
Cancelling actually cancels. Dying, or the cancel key on an item that allows it, stops the action and nothing is applied. Following ox_inventory, only an item that says cancel = true can be cancelled with the key (the shipped water does), and getting into a car no longer interrupts a use (Config.Consume.cancelOnVehicle = false).
disable = { move = true, sprint = true, car = true, combat = true } on an item is what the player cannot do while using it. Combat is off during every use unless the item says combat = false; the shipped bandage also stops you walking and driving. The table is handed to ox_lib's or qb's bar when one draws the action, and applied by this inventory when it draws its own.
Using an item closes the inventory, as in ox_inventory. An item that should leave it open says close = false; adopted items keep ox's close and qb's shouldClose. If you are extending this, make sure your handler answers the cancellation — a handler that ignores it produces the worst bug in this area: the progress bar disappears but the effect still lands.
exports.aty_inventory:StartConsume(src, slot)
exports.aty_inventory:CancelConsume(src)
exports.aty_inventory:IsConsuming(src)
One bar, whoever draws it. An item that the framework already has a handler for — a qb CreateUseableItem — is handed straight to that handler, with no action bar from the inventory first: qb handlers run their own progress bar, and running both showed two bars for one item. A handler registered through RegisterUsable is timed by the inventory as before; one that draws its own bar says so with bar = false and keeps the timing, the cancellation and the portion bookkeeping.
exports.aty_inventory:RegisterUsable('bandage', {
useTime = 4000,
bar = false, -- your own progress bar, on aty_inventory:consumeBegin
use = function(src, info) ... end,
})
Whose progress bar
A server that runs ox_lib or qb's progressbar already has a bar its players know. By default every timed action here — eating, drinking, bandages, a body search, a timed reload — is drawn on that bar, with the same label, duration, animation and object in the hand.
Config.Consume.progress = 'auto' -- 'auto' | 'ox_lib' | 'qb' | 'aty'
| Value | Draws with |
|---|---|
auto (default) |
ox_lib when it is started, else qb's progressbar when qb-core and it are started, else this inventory's own bar |
ox_lib |
ox_lib's progressBar |
qb |
qb's progressbar |
aty |
this inventory's own bar and animation |
ox_lib is not a dependency: it is only asked when it is running, and a provider that is named but not running falls back to aty. The other bar only decides when the client says it finished — the server still checks the time before anything is spent, and cancelling (the cancel key where the item allows it, dying) still spends nothing. The setting can be changed live from the admin panel's Settings tab.
Cooldowns
adrenaline = {
cooldown = 120000, -- two minutes between uses
}
Cooldowns are per player per item and are enforced on the server. The shipped items carry none, as ox_inventory's do; the field is there for an item that needs one.
Custom usables
Register a handler for anything the built-in effects cannot express:
exports.aty_inventory:RegisterUsable('radio', function(src, info)
-- info = { slot, name, label, metadata, spoiled, ... }
TriggerClientEvent('my_radio:open', src)
end)
The item itself still has to say usable = true, or using it is refused before any handler is asked. Add consume = false when using it should not spend it — a radio, a phone.
A worked example ships in examples/usable_handler.lua.