Skip to content
RustPluginGenerator

OnDispenserBonusReceived

OnDispenserBonusReceived is called when a ResourceDispenser has finished granting its bonus item for a gather, right before the bonus is handed to the player. It fires from ResourceDispenser.AssignFinishBonus, after ownership is applied and just before the item is split into stackable chunks and given.

Signature
void OnDispenserBonusReceived(ResourceDispenser resourceDispenser, BasePlayer player, Item item)

Parameters

Hook parameters
ParameterTypeDescription
resourceDispenserResourceDispenserThe ResourceDispenser component on the gatherable entity (tree, ore node, animal corpse, etc.) whose finish bonus was just created. Use it to read the entity, its position or its prefab.
playerBasePlayerThe BasePlayer who will receive the bonus item. This is the player you reward, message or check permissions for.
itemItemThe bonus Item instance that was just created and is about to be split down to stack size and given to the player. You can inspect its info.shortname and amount, or change them.

Return value

The hook's return value is ignored; this signature returns void in the game method. Returning anything has no effect on the item, the amount or the delivery, so mutate item directly if you need to change the reward.

How it works

This hook fires inside ResourceDispenser.AssignFinishBonus, the step where a gatherer receives the bonus item that a dispenser grants after a resource node, corpse or similar object is finished. The game has already created the item, applied item ownership to the player and logged the gather analytics; the hook runs immediately before the while loop that splits the item into stackable pieces and calls player.GiveItem. The parameters let you inspect the dispenser entity, the receiving player and the exact bonus Item (its info.shortname, amount, skin). Because the hook fires before the stack-splitting loop, changing item.amount here changes what the player actually receives. Narrowing the signature does not help much here since ResourceDispenser, BasePlayer and Item are model classes; Oxide still passes the same arguments. The hook is not tied to ordinary per-hit gather events, so use OnDispenserGather for that and this hook for the end-of-node bonus. It fires once per finishing bonus, not once per hit, so it is reasonably safe for light logic, though you should still avoid heavy logging.

Example plugin: Multiply the finish bonus for players with a permission

BonusBoost.cs
using System.Collections.Generic;
using System;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("BonusBoost", "RustPluginGenerator", "1.0.0")]
    [Description("Multiplies resource dispenser finish bonuses for players with a permission.")]
    public class BonusBoost : RustPlugin
    {
        private const string PermUse = "bonusboost.vip";

        private PluginConfig config;

        public class PluginConfig
        {
            [JsonProperty("Bonus multiplier")]
            public float Multiplier = 2f;

            [JsonProperty("Notify player in chat")]
            public bool Notify = true;
        }

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Boosted"] = "Bonus boosted: {0} x {1}",
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args)
            => string.Format(lang.GetMessage(key, this, userId), args);

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
        }

        private void OnDispenserBonusReceived(ResourceDispenser resourceDispenser, BasePlayer player, Item item)
        {
            if (resourceDispenser == null || player == null || item == null || item.info == null) return;
            if (config.Multiplier <= 1f) return;
            if (!permission.UserHasPermission(player.UserIDString, PermUse)) return;

            int original = item.amount;
            int boosted = (int)Math.Round(original * config.Multiplier);
            if (boosted <= original) return;

            item.amount = boosted;
            item.MarkDirty();

            if (config.Notify && player.IsConnected)
            {
                player.ChatMessage(Msg("Boosted", player.UserIDString, item.info.displayName.english, boosted));
            }
        }
    }
}

The plugin registers a bonusboost.vip permission and a configurable multiplier. When OnDispenserBonusReceived fires it null-checks the dispenser, player and item, verifies the player still has the permission, and then scales item.amount by the multiplier. Because the hook runs before the game splits the item into stackable chunks, the increased amount flows straight into the player's inventory. The adjusted amount is not allowed to exceed the item's max stack multiplied out, so the game's split loop handles overflow. A short chat message tells the player they received a boosted bonus, and Unload cleans up the registered permission.

Common use cases

  • Boost bonuses for donators

    Scale item.amount for players with a permission so VIPs get more stone, wood or ore from finish bonuses without touching the rest of the economy.

  • Log bonus economy data

    Collect the shortname and amount per player to feed an external balance or stats system; keep it cheap because it only fires on finish bonuses.

  • Swap the reward item

    Change item.info by removing the default item and giving a different ItemDefinition via ItemManager.CreateByName and player.GiveItem yourself.

Pitfalls

  • Not the same as OnDispenserGather

    OnDispenserBonusReceived fires once for the finishing bonus, not on every hit. Use OnDispenserGather for per-hit adjustments; mixing them up produces double counting.

  • Amount is split afterwards

    The game splits the item down to item.MaxStackable() inside the loop that follows the hook. Very large amounts still end up in multiple stacks, so do not assume one stack in inventory logic.

  • Item may already be owned

    Ownership is applied before the hook fires, so item.GetOwnerPlayer() is the receiving player. Rely on the player parameter rather than inspecting ownership flags.

Build a plugin with OnDispenserBonusReceived

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Boost bonuses for donators using the OnDispenserBonusReceived hook, with a config file and a permission
Generate this plugin

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with OnDispenserBonusReceived

Generate