Skip to content
RustPluginGenerator

OnDispenserBonus

OnDispenserBonus is called during ResourceDispenser.AssignFinishBonus, right after the game creates the bonus item for a player who finished a resource node. Return a different Item to substitute the reward, or return null to keep it.

Signature
object OnDispenserBonus(ResourceDispenser resourceDispenser, BasePlayer player, Item item)

Parameters

Hook parameters
ParameterTypeDescription
resourceDispenserResourceDispenserThe ResourceDispenser entity (tree, ore node, animal carcass, etc.) that awarded the bonus. Useful for reading its position, prefab name, or owner.
playerBasePlayerThe BasePlayer whose gather bonus is being applied. This is the player who hit the resource last and receives the finish bonus item.
itemItemThe freshly created Item holding the scaled bonus amount. Replace it by returning a different Item instance; the game then applies ownership to whatever item is current.

Return value

Return null to let the game keep the Item it already created. Return a different Item instance and the game replaces the working item with yours before ApplyItemOwnership runs, so your item gets the correct owner. Any other return type is ignored.

How it works

This hook fires inside ResourceDispenser.AssignFinishBonus, the method that hands out the extra resource item when a player depletes a resource node (tree, ore, carcass). By this point the game has already computed the base finish bonus, applied the gather bonus from held items, scaled the amount and created an Item via ItemManager.Create.

Parameters:

  • resourceDispenser is the node being depleted. It carries the prefab, position and any owner ID you might want to inspect.
  • player is the receiver of the bonus. It is the player whose gather bonus scaled the amount, so it can be null in unusual flows but is normally set.
  • item is the created item and its final amount. Read item.info.shortname and item.amount to see what is being granted.

The hook fires once per completed resource node, so it is a low-frequency place to add multipliers, event rewards or logging. Returning a non-null Item replaces the game's item before ownership is applied, which is why you can safely build a brand-new Item (or re-use the passed one after changing amount).

There is no way to cancel the award from this hook; to block or alter gather amounts use OnDispenserGather. Declaring BasePlayer for the second parameter is the exact type already, so no narrowing is needed.

Example plugin: Double finish bonus during a server event

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

namespace Oxide.Plugins
{
    [Info("Dispenser Bonus Booster", "RustPluginGenerator", "1.0.0")]
    [Description("Multiplies the finish bonus awarded when a player depletes a resource node during a timed event.")]
    public class DispenserBonusBooster : RustPlugin
    {
        private const string PermBoost = "dispenserbonusbooster.boost";

        private PluginConfig config;
        private bool boostActive;
        private Timer boostTimer;

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

            [JsonProperty("Event duration (seconds)")]
            public float Duration { get; set; } = 60f;
        }

        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 System.Collections.Generic.Dictionary<string, string>
            {
                ["NoPerm"] = "You do not have permission to start the bonus event.",
                ["Started"] = "Resource finish bonus is now x{0} for {1} seconds.",
                ["Ended"] = "Resource finish bonus event has ended."
            }, 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(PermBoost, this);
        }

        [ChatCommand("bonusboost")]
        private void CmdBoost(BasePlayer player, string command, string[] args)
        {
            if (player == null) return;
            if (!permission.UserHasPermission(player.UserIDString, PermBoost))
            {
                SendReply(player, Msg("NoPerm", player.UserIDString));
                return;
            }

            if (boostTimer != null) boostTimer.Destroy();
            boostActive = true;
            Server.Broadcast(Msg("Started", null, config.Multiplier, config.Duration));
            boostTimer = timer.Once(config.Duration, () =>
            {
                boostActive = false;
                boostTimer = null;
                Server.Broadcast(Msg("Ended"));
            });
        }

        private object OnDispenserBonus(ResourceDispenser resourceDispenser, BasePlayer player, Item item)
        {
            if (!boostActive || item == null || item.info == null) return null;
            if (player == null || player.IsNpc) return null;

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

            Item replacement = ItemManager.Create(item.info, boosted, item.skin);
            if (replacement == null) return null;

            return replacement;
        }

        private void Unload()
        {
            if (boostTimer != null)
            {
                boostTimer.Destroy();
                boostTimer = null;
            }
            boostActive = false;
        }
    }
}

The plugin tracks an active bonus window. OnDispenserBonus fires once per depleted resource node; while the window is open it reads the item's amount, doubles it, and returns a fresh Item created with the new amount so the player receives the boosted stack. The returned item is the one ownership is applied to, so no duplication happens. A small chat command starts a one-minute boost, a timer clears the flag, and the timer is destroyed in Unload. The config exposes the multiplier and event duration.

Common use cases

  • Weekend double-resource events

    Return an item with a scaled amount when a scheduled event flag is active, giving players a visible gather reward without touching base gather rates.

  • Rare bonus drops from depleted nodes

    Swap the returned item for a rarer resource (or a separate item) based on the dispenser prefab, effectively turning node depletion into a loot table.

  • Per-team bonus tracking

    Read player.currentTeam to determine whether to multiply the amount, giving organised groups an incentive to deplete nodes together.

Pitfalls

  • Returning the passed item is not required

    Returning the same instance you were given works but is pointless; just return null unless you actually want to change the item. Returning something of a different type (e.g. a string) is silently ignored.

  • This is not the gather hook

    OnDispenserBonus fires once at node completion, not on every hit. If you want per-hit scaling or cancellation, use OnDispenserGather instead.

  • Destroying the item breaks the flow

    If you call item.Remove() before returning null the game will still call ApplyItemOwnership on a removed item. Return a replacement item or leave the original alone.

Plugin recipes that use OnDispenserBonus

Build a plugin with OnDispenserBonus

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

Prompt: Weekend double-resource events using the OnDispenserBonus 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 OnDispenserBonus

Generate