Zyke ResourcesDocumentation

Consumption Rewards

All information you would need regarding consumption rewards.

#Consumption Rewards

Consumption rewards control what effects are applied when a player consumes an item. Food can restore hunger, drinks can quench thirst, drugs can trigger addictions, and so on. These are split across server and client, so you have control over both authoritative state changes and local effects.


#Table of Contents


#How It Works

  1. Items are configured in the Creator Menu with one or more consumption rewards (e.g. food, drink, health).
  2. Each reward has a multiplier on the item, and a global multiplier defined in the reward registration.
  3. When a player consumes, the system calculates the reward amount from the consumed quantity, multipliers, and quality, then calls each reward's registered function.

The reward functions are where your actual logic lives. This is where you apply status effects, heal, add addictions, or do anything else you want to happen on consumption.


#Server vs Client

Consumption rewards are split into two files:

SideFileUse Cases
Serverserver/unlocked/on_consumption.luaAuthoritative changes like hunger, thirst, stress, drug effects. Anything that should be validated server-side
Clientclient/unlocked/on_consumption.luaLocal effects like health, armor, screen effects. Anything that needs to run on the player's client

Both sides use the same pattern: register a reward with a name, label, global multiplier, and a callback function.

The client file is also streamed to the server so the system knows which client-side rewards exist for validation purposes. You don't need to do anything special for this, it happens automatically.


#Reward Calculation

Every time a player consumes, the reward amount is calculated as:

rewardAmount = consumedAmount × globalMultiplier × itemMultiplier × (quality / 100)
FactorDescription
consumedAmountHow much of the item was consumed in this tick
globalMultiplierSet when registering the reward. Affects all items using this reward
itemMultiplierSet per-item in the Creator Menu. Lets individual items give more or less
qualityItem quality from 0 to 100, applied as a percentage

The callback also receives rewardAmountNoQuality, which is the amount before quality is applied. This is useful when you want to do your own math with quality.


#Adding a New Server Reward

Open server/unlocked/on_consumption.lua and add a new RegisterConsumptionReward call:

---@param cData ConsumptionData
RegisterConsumptionReward({name = "my_effect", label = "My Effect", globalMultiplier = 0.1}, function(cData)
    -- cData.plyId    = Player server ID
    -- cData.rewardAmount = Calculated amount (with quality applied)
    -- Do something with it:
    print("Applying my_effect to player:", cData.plyId, cData.rewardAmount)
end)
FieldTypeDescription
namestringInternal name, must be unique across all rewards
labelstringDisplay name shown in the Creator Menu
globalMultipliernumberGlobal scale factor for this reward across all items

After adding the reward, restart the resource. The new reward will automatically appear in the Creator Menu when configuring items.

#Example: Energy Drink Effect

---@param cData ConsumptionData
RegisterConsumptionReward({name = "energy", label = "Energy", globalMultiplier = 0.08}, function(cData)
    exports["zyke_status"]:AutoToStatus(cData.plyId, {"stamina"}, cData.rewardAmount)
end)

#Adding a New Client Reward

Open client/unlocked/on_consumption.lua and use the local registerConsumptionReward function:

---@param cData ConsumptionClientData
registerConsumptionReward({name = "my_client_effect", label = "My Client Effect", globalMultiplier = 0.1}, function(cData)
    -- No plyId here, this runs on the consuming player's client
    -- cData.rewardAmount = Calculated amount (with quality applied)
    print("Client effect:", cData.rewardAmount)
end)

The client side works the same as the server side, with two differences:

  • There is no plyId since the function always runs on the consuming player's client
  • Use this for effects that need to happen client-side (health, armor, screen effects, local particles, etc.)

#Example: Screen Flash

---@param cData ConsumptionClientData
registerConsumptionReward({name = "screen_flash", label = "Screen Flash", globalMultiplier = 1.0}, function(cData)
    AnimpostfxPlay("FocusOut", 500, false)
    Citizen.Wait(500)
    AnimpostfxStop("FocusOut")
end)

#Modifying Existing Rewards

#Changing the Global Multiplier

Find the reward in the corresponding file and change the globalMultiplier value:

diff
-RegisterConsumptionReward({name = "drink", label = "Drink", globalMultiplier = 0.15}, function(cData)
+RegisterConsumptionReward({name = "drink", label = "Drink", globalMultiplier = 0.20}, function(cData)

This scales the reward across every item that uses it. A higher multiplier means players need to consume less to fill their status, and a lower one means they need more.

#Changing the Callback Logic

The callback function is where the actual effect is applied. You can change what happens without affecting the calculation:

RegisterConsumptionReward({name = "food", label = "Food", globalMultiplier = 0.25}, function(cData)
    -- Original: just adds to hunger
    exports["zyke_status"]:AutoToStatus(cData.plyId, {"hunger"}, cData.rewardAmount)

    -- You could also add a secondary effect:
    if (cData.rewardAmount > 5.0) then
        exports["zyke_status"]:AutoToStatus(cData.plyId, {"stress"}, -1.0)
    end
end)

#Changing Per-Item Multipliers

Per-item multipliers are configured in the Creator Menu, not in code. Open the menu, select the item, and adjust the multiplier on the specific consumption reward.


#Callback Data Reference

#Server (ConsumptionData)

FieldTypeDescription
plyIdnumberServer ID of the consuming player
idstringItem ID
amountnumberRaw consumed amount
consumNamestringName of this consumption reward
itemMetadatatableFull metadata table from the item
rewardAmountnumberFinal calculated amount (quality applied)
rewardAmountNoQualitynumberCalculated amount without quality scaling
qualitynumberItem quality (0 to 100)
qualityThresholdnumberMinimum quality required for this reward to activate
qualityTypestring"basic" or "chance"
maxAmountnumber?Optional cap. A helper value for your logic, not enforced automatically

#Client (ConsumptionClientData)

Same as above, except there is no plyId field. The function always runs on the consuming player's client.


#Quality and Thresholds

Each consumption reward on an item can have a quality threshold and a quality type:

#Quality Threshold

The minimum quality an item must have for this reward to activate. If the item's quality is below the threshold, the reward is skipped entirely.

You can also reverse the threshold, which flips the behavior so the reward only activates when quality is below the threshold. This is useful for negative effects like food poisoning from low-quality food.

#Quality Types

TypeDescription
basicStandard behavior. Quality scales the reward amount linearly
chanceThe reward amount can be used as a probability. Useful for random effects

#Max Amount

The maxAmount field is a helper value that you can set per-reward in the Creator Menu. It is not enforced automatically. It is passed into your callback so you can check against it in your own logic:

RegisterConsumptionReward({name = "heal", label = "Heal", globalMultiplier = 0.1}, function(cData)
    if (cData.maxAmount and cData.rewardAmount > cData.maxAmount) then
        return -- Skip if over the cap
    end
    exports["zyke_status"]:AddToStat("health", cData.rewardAmount, cData.maxAmount)
end)

If the reward amount is negative, maxAmount acts as a floor (the lowest the value can go).


#Built-in Rewards

#Server Rewards

NameLabelGlobal MultiplierDescription
drinkDrink0.15Adds to thirst status
foodFood0.25Adds to hunger status
stressStress0.05Adds to stress status
nicotineNicotine1.0Adds nicotine addiction and high
cocaineCocaine1.0Adds cocaine addiction and high
lsdLSD1.0Adds LSD addiction and high
alcoholAlcohol0.2Adds drunk effect
caffeineCaffeine0.04Adds caffeine effect
custom_exampleCustom Example1.0Example with dice-roll logic (for reference)

#Client Rewards

NameLabelGlobal MultiplierDescription
healthHealth0.1Adds to player health
armorArmor0.1Adds to player armor

#FAQ

Q: Where do I add new consumption rewards? Server-side rewards go in server/unlocked/on_consumption.lua. Client-side rewards go in client/unlocked/on_consumption.lua. After adding, restart the resource and the new reward will appear in the Creator Menu.

Q: Do I need to register rewards somewhere else for them to show up in the Creator Menu? No. The system automatically picks up all registered rewards and makes them available in the Creator Menu.

Q: What's the difference between rewardAmount and rewardAmountNoQuality? rewardAmount has quality scaling applied (× quality / 100). rewardAmountNoQuality is the raw amount before quality. Use the latter when you want to handle quality in your own way.

Q: Can a single item have both server and client rewards? Yes. An item can have any combination of server and client rewards. They are processed independently.

Q: How do I balance rewards across all items? Use the globalMultiplier. For example, if all drinks feel too weak, increase the drink reward's global multiplier. For individual items, adjust the per-item multiplier in the Creator Menu.

Q: How does the global multiplier interact with the per-item multiplier? They stack multiplicatively. If the global multiplier is 0.15 and the per-item multiplier is 2.0, the effective multiplier is 0.30.

Q: Can I use item metadata in my reward callback? Yes. cData.itemMetadata contains the full metadata table from the item. You can use this to create rewards that behave differently based on custom metadata fields.

Q: What happens if I register two rewards with the same name? The second one overwrites the first. Each reward name must be unique.