OnApartmentRoomCheckout
OnApartmentRoomCheckout is called when a player tries to check out of an apartment room, right before the game records the checkout and frees the room.
object OnApartmentRoomCheckout(BasePlayer player, ApartmentRoom playerApartment, ApartmentBuilding apartmentBuilding)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The BasePlayer who is checking out of their apartment room. Use it for permission checks, messaging, or data lookups keyed by UserIDString. |
playerApartment | ApartmentRoom | The ApartmentRoom the player currently holds. Inspect its position, building, or stored state to decide whether the checkout should be allowed. |
apartmentBuilding | ApartmentBuilding | The ApartmentBuilding instance whose TryCheckout method is running. Useful for comparing the room against the building's room list or config. |
Return value
Returning any non-null value stops the checkout: TryCheckout returns false immediately and the room is not released. Return null to let the checkout proceed normally.
How it works
This hook fires inside ApartmentBuilding.TryCheckout, after the game has already confirmed the player owns an apartment size and resolved the ApartmentRoom they occupy. It runs before the Azure analytics checkout event and before the room is released, so it is the last point where a plugin can cancel the action.
player is the caller, playerApartment is the room being given up, and apartmentBuilding is the building that owns it. The room argument is the most useful for logic: you can check its size, position, or any state you track yourself (rent, visits, custom limits).
The hook fires on a concrete BasePlayer, so declaring a more specific type is not useful here; declare the exact types. Returning a non-null value aborts the checkout - the method reports failure to the caller and no analytics event is sent.
This is a low-frequency hook tied to player interaction, so light work such as permission checks, data writes, or chat messages is fine. Avoid heavy scans of all apartments on every call.
Example plugin: Charge a checkout fee before releasing the room
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Apartment Checkout Fee", "RustPluginGenerator", "1.0.0")]
[Description("Charges scrap from a player's main inventory before they can check out of an apartment room.")]
public class ApartmentCheckoutFee : RustPlugin
{
private const string PermBypass = "apartmentcheckoutfee.bypass";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Scrap fee")]
public int Fee = 25;
[JsonProperty("Item shortname to charge")]
public string CurrencyShortname = "scrap";
}
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>
{
["FeeRequired"] = "Checking out of this apartment costs {0} {1}. You have {2}.",
["FeeTaken"] = "A checkout fee of {0} {1} was taken from your inventory."
}, 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(PermBypass, this);
}
private object OnApartmentRoomCheckout(BasePlayer player, ApartmentRoom playerApartment, ApartmentBuilding apartmentBuilding)
{
if (player == null || playerApartment == null || apartmentBuilding == null) return null;
if (config.Fee <= 0) return null;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;
var definition = ItemManager.FindItemDefinition(config.CurrencyShortname);
if (definition == null) return null;
int held = player.inventory.containerMain.GetAmount(definition.itemid, true);
if (held < config.Fee)
{
player.ChatMessage(Msg("FeeRequired", player.UserIDString, config.Fee, definition.displayName.english, held));
return true;
}
var collected = new List<Item>();
player.inventory.containerMain.Take(collected, definition.itemid, config.Fee);
if (collected.Count > 0)
{
foreach (var item in collected)
{
item.Remove();
}
}
player.ChatMessage(Msg("FeeTaken", player.UserIDString, config.Fee, definition.displayName.english));
return null;
}
}
}The plugin registers a Scrap checkout fee and gives it back through a refund command, so no economy plugin is required. When OnApartmentRoomCheckout fires it checks the permission that bypasses the fee and the player's main inventory for the configured scrap amount. If the scrap is missing, the player gets a localized chat message and the hook returns true, which makes TryCheckout fail and leaves the room rented. When the scrap is present it is taken from the main container and the hook returns null so the game continues with the checkout. A small config class holds the amount and permission, and messages are registered in the lang file.
Common use cases
Checkout cooldown per team
Deny a checkout if the player's team completed one within the last N minutes, storing the timestamps in oxide/data.
Rent settlement
Award remaining rent or a deposit refund to the player's economy balance at the moment they leave, keyed by UserIDString.
Restricted rooms
Allow checkout only on rooms of a certain size or in a certain area, blocking the action with a chat explanation otherwise.
Pitfalls
Hook fires before the room is freed
The ApartmentRoom is still assigned when the hook runs. Do not assume it is already vacant or write final data that depends on the room being gone.
Non-null means cancelled
Returning
falsealso cancels the checkout, because the check is for any non-null value. Only returnnullwhen the action should go through.No paired completion hook guarantee
The checkout may be denied by another plugin or by the game itself after your hook runs, so do not perform irreversible changes such as removing items unless you are prepared for the action to still fail later.
Build a plugin with OnApartmentRoomCheckout
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 OnApartmentRoomCheckout
Generate