OnTakeCurrencyItem
OnTakeCurrencyItem is called on a vending machine right after a purchase removes the currency item from the buyer and before the game moves that item into the machine's inventory. Returning a non-null value stops the default handling of the currency item.
object OnTakeCurrencyItem(VendingMachine vendingMachine, Item takenCurrencyItem)Parameters
| Parameter | Type | Description |
|---|---|---|
vendingMachine | VendingMachine | The vending machine that is receiving the currency item. For the player-driven machine it is a VendingMachine; for NPC/map shops the same hook fires with an NPCVendingMachine, so a narrower parameter type filters out the other case. |
takenCurrencyItem | Item | The item stack the buyer used to pay (for example scrap or a custom currency item). It is the single Item instance the game is about to move into the machine's inventory. |
Return value
Returning null lets the game continue: the currency item is moved into the machine's inventory (or dropped if that fails, or removed for NPC machines). Returning any non-null value stops that default handling, so the paid item is neither stored nor dropped by the game and your plugin becomes responsible for it.
How it works
The hook fires inside VendingMachine.TakeCurrencyItem, which the game calls as part of the buying flow once the buyer's payment has been taken out of their inventory. The original method tries to move the paid item into the machine's own container; if that fails it drops the item at the machine's drop position. The exact same hook also fires from NPCVendingMachine.TakeCurrencyItem for map/NPC shops, where the default path always moves the item into the inventory, removes it from the container and deletes it.
Use vendingMachine to identify the shop (position, owner, net ID) and takenCurrencyItem to inspect what was paid: info.shortname, amount, skin. Declaring the first parameter as VendingMachine makes Oxide skip the call for NPC shops, and declaring NPCVendingMachine does the reverse. This is useful for currency logging, per-shop tax, or refund logic. It only covers the payment item, not the item being sold or the transaction outcome — those belong to CanBuyItem, OnBuyVendingItem and OnGiveSoldItem.
Other signatures
Oxide also calls OnTakeCurrencyItem from other places in the game with these parameter types. Declare the overload you need, or several:
object OnTakeCurrencyItem(NPCVendingMachine nPCVendingMachine, Item takenCurrencyItem)
Example plugin: Log machine sales and give a scrap rebate
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("VendingCurrencyTax", "RustPluginGenerator", "1.0.0")]
[Description("Logs scrap payments to vending machines and pays a configurable rebate to the buyer.")]
public class VendingCurrencyTax : RustPlugin
{
private const string PermUse = "vendingcurrencytax.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Currency shortname to watch")]
public string CurrencyShortname = "scrap";
[JsonProperty("Rebate percentage of paid amount")]
public int RebatePercent = 10;
[JsonProperty("Log payments to server console")]
public bool LogToConsole = 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>
{
["Rebate"] = "You received {0} {1} back from your purchase.",
["ConsoleLog"] = "{0} paid {1} {2} to machine at {3}",
["NotAllowed"] = "This machine does not accept {0}."
}, 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 object OnTakeCurrencyItem(VendingMachine vendingMachine, Item takenCurrencyItem)
{
if (vendingMachine == null || takenCurrencyItem == null || takenCurrencyItem.info == null)
return null;
if (takenCurrencyItem.info.shortname != config.CurrencyShortname)
return null;
BasePlayer buyer = takenCurrencyItem.GetOwnerPlayer();
if (buyer == null || !buyer.IsConnected)
return null;
if (config.LogToConsole)
{
Puts(Msg("ConsoleLog", null, buyer.displayName, takenCurrencyItem.amount,
config.CurrencyShortname, vendingMachine.transform.position.ToString("F0")));
}
if (!permission.UserHasPermission(buyer.UserIDString, PermUse))
return null;
int rebate = takenCurrencyItem.amount * Mathf.Clamp(config.RebatePercent, 0, 100) / 100;
if (rebate <= 0)
return null;
Item refund = ItemManager.CreateByName(config.CurrencyShortname, rebate, 0);
if (refund == null)
return null;
if (!buyer.inventory.GiveItem(refund))
refund.Drop(buyer.transform.position, Vector3.zero);
buyer.ChatMessage(Msg("Rebate", buyer.UserIDString, rebate, config.CurrencyShortname));
return null;
}
}
}The plugin watches every payment received by admin-owned or owned vending machines. In OnTakeCurrencyItem it reads the paid item's shortname and amount, ignores anything that is not scrap, and sends a short log line to the admin console channel. It also pays back a configurable percentage of the paid scrap as a rebate directly to the buyer's inventory. The buyer is resolved from the currency item's owner while it still has one. Everything is driven by config and lang messages, and the hook returns null so the vanillapayment handling keeps working unchanged.
Common use cases
Track shop income
Read
takenCurrencyItem.amountand write a running total per machine into a data file so admins can see which vending machines actually earn scrap.Custom currency rebates
Give part of the paid scrap or a custom currency item back to the buyer via
GiveItemafter the purchase, without touching the sale itself.Currency whitelist per shop
Return a non-null value and drop or delete the paid item when its shortname is not on an allowed list for that machine, effectively refusing the payment type.
Pitfalls
Two machine types share the hook
The same hook fires for
NPCVendingMachine. If you declareVendingMachineyou will simply not be called for NPC shops; if you want both, use the base type or handle each signature separately.The paid item may have no owner
takenCurrencyItem.GetOwnerPlayer()relies onparentstill pointing at the buyer's container. Null-check it and fall back gracefully instead of assuming a player is present.Blocking does not refund the buyer
Returning non-null stops the game from storing the item, but nothing is returned to the buyer automatically. Move the item back yourself or it is lost.
Build a plugin with OnTakeCurrencyItem
Describe what should happen and get a compiled plugin that uses this hook.
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 OnTakeCurrencyItem
Generate