Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Bill3621/CustomItems/llms.txt

Use this file to discover all available pages before exploring further.

Quick start

This guide walks you through creating your first custom item using CustomItems LabAPI. You’ll learn the basic structure of a custom item and how to register it with the framework.

Prerequisites

  • CustomItems LabAPI installed on your server
  • Visual Studio or another C# IDE
  • Basic knowledge of C# and SCP: Secret Laboratory modding

Understanding custom items

Every custom item in CustomItems LabAPI inherits from the CustomItem base class and implements several key components:
  • Properties: Define the item’s name, description, type, and weight
  • Event hooks: Respond to player interactions like using, dropping, or picking up the item
  • Registration callbacks: Handle setup and cleanup when the item is registered or unregistered

Create your first custom item

Let’s create a simple custom item: a speed boost syringe that increases the player’s movement speed when used.
1

Create a new class

In your plugin project, create a new class that inherits from CustomItem:
using CustomItems.API;
using LabApi.Events.Arguments.PlayerEvents;
using LabApi.Features.Wrappers;
using MEC;
using System.Collections.Generic;

namespace YourPlugin.CustomItems
{
    public class SpeedBoostSyringe : CustomItem
    {
        // Implementation goes here
    }
}
2

Define basic properties

Implement the required properties that define your item:
public override string Name => "Speed Boost Syringe";

public override string Description => "Temporarily increases movement speed.";

public override ItemType Type => ItemType.Adrenaline;

public override float Weight => 1.0f;
These properties determine how the item appears and behaves in the game. The Type property sets the base item model (in this case, an adrenaline syringe).
3

Implement registration callbacks

Add the required registration methods. These are called when your item is registered or unregistered:
public override void OnRegistered()
{
    // Called when the item is registered
    // Subscribe to events or initialize resources here
}

public override void OnUnregistered()
{
    // Called when the item is unregistered
    // Unsubscribe from events or clean up resources here
}
4

Add item behavior

Override the OnUsing method to define what happens when a player uses the item:
public override void OnUsing(PlayerUsingItemEventArgs ev)
{
    // Apply speed boost effect
    const float duration = 10f;
    const float speedMultiplier = 1.3f;
    
    // Start the speed boost coroutine
    Timing.RunCoroutine(ApplySpeedBoost(ev.Player, duration, speedMultiplier));
    
    // Remove the item from the player's inventory
    ev.Player.RemoveItem(ev.UsableItem);
}

private IEnumerator<float> ApplySpeedBoost(Player player, float duration, float multiplier)
{
    // Store the original speed
    float originalSpeed = player.MovementSpeed;
    
    // Apply the speed boost
    player.MovementSpeed *= multiplier;
    
    // Wait for the duration
    yield return Timing.WaitForSeconds(duration);
    
    // Restore original speed
    if (player.IsAlive)
        player.MovementSpeed = originalSpeed;
}

Complete example

Here’s the complete code for the Speed Boost Syringe:
CustomItems/SpeedBoostSyringe.cs
using CustomItems.API;
using LabApi.Events.Arguments.PlayerEvents;
using LabApi.Features.Wrappers;
using MEC;
using System.Collections.Generic;

namespace YourPlugin.CustomItems
{
    public class SpeedBoostSyringe : CustomItem
    {
        public override string Name => "Speed Boost Syringe";
        
        public override string Description => "Temporarily increases movement speed.";
        
        public override ItemType Type => ItemType.Adrenaline;
        
        public override float Weight => 1.0f;
        
        public override void OnRegistered() { }
        
        public override void OnUnregistered() { }
        
        public override void OnUsing(PlayerUsingItemEventArgs ev)
        {
            const float duration = 10f;
            const float speedMultiplier = 1.3f;
            
            Timing.RunCoroutine(ApplySpeedBoost(ev.Player, duration, speedMultiplier));
            ev.Player.RemoveItem(ev.UsableItem);
        }
        
        private IEnumerator<float> ApplySpeedBoost(Player player, float duration, float multiplier)
        {
            float originalSpeed = player.MovementSpeed;
            player.MovementSpeed *= multiplier;
            
            yield return Timing.WaitForSeconds(duration);
            
            if (player.IsAlive)
                player.MovementSpeed = originalSpeed;
        }
    }
}

Register your custom item

Once you’ve created your custom item class, you need to register it with the framework. In your plugin’s Enable method:
using CustomItems.API;

public override void Enable()
{
    // Register a single item
    var speedBoost = new SpeedBoostSyringe();
    CustomItems.Register(speedBoost);
}
The RegisterAll() method automatically finds and registers all classes in your assembly that inherit from CustomItem. This is the recommended approach for plugins with multiple custom items.
Don’t forget to unregister your items in the Disable method:
public override void Disable()
{
    CustomItems.UnregisterAll();
}

Give items to players

You can give custom items to players using the TryGive method:
// Get the item ID by name
ushort itemId = CustomItems.GetIdByName("Speed Boost Syringe");

// Give the item to a player
if (CustomItems.TryGive(itemId, player, out Item item))
{
    Log.Info($"Gave Speed Boost Syringe to {player.Nickname}");
}
You can also spawn items in the world:
// Spawn an item at a specific position
if (CustomItems.TrySpawn(itemId, position, out Pickup pickup))
{
    Log.Info($"Spawned Speed Boost Syringe at {position}");
}

Advanced example: Event-driven item

Let’s look at a more advanced example from the included EMP Grenade that uses event subscriptions:
Example: EMP Grenade
using CustomItems.API;
using CustomItems.Core;
using LabApi.Events.Arguments.ServerEvents;
using LabApi.Events.Handlers;
using LabApi.Features.Wrappers;
using MEC;
using Mirror;

namespace CustomItems.API.Example
{
    public class EMPGrenade : CustomItem
    {
        public override string Name => "EMP Grenade";
        
        public override string Description => "Locks doors and disables lights in current room.";
        
        public override ItemType Type => ItemType.GrenadeHE;
        
        public override void OnRegistered()
        {
            // Subscribe to the explosion event
            ServerEvents.ProjectileExploding += OnExplosion;
        }
        
        public override void OnUnregistered()
        {
            // Unsubscribe from the explosion event
            ServerEvents.ProjectileExploding -= OnExplosion;
        }
        
        private void OnExplosion(ProjectileExplodingEventArgs ev)
        {
            // Check if this is our custom item
            if (!Check(ev.TimedGrenade)) return;
            
            // Cancel the normal explosion
            ev.IsAllowed = false;
            
            Log.Debug($"EMP Grenade exploded at {ev.TimedGrenade.Position}");
            
            Room room = ev.TimedGrenade.Room;
            
            // Flicker lights for 10 seconds
            room.LightController.FlickerLights(10);
            
            // Lock all doors in the room
            foreach (var door in room.Doors)
            {
                if (door.IsLocked) continue;
                door.IsLocked = true;
                
                // Unlock after 10 seconds
                Timing.CallDelayed(10f, () => {
                    door.IsLocked = false;
                });
            }
            
            // Destroy the grenade object
            NetworkServer.Destroy(ev.TimedGrenade.GameObject);
        }
    }
}
This example demonstrates:
  • Subscribing to game events in OnRegistered() (CustomItems-LabAPI/API/Example/EMPGrenade.cs:18-21)
  • Using the Check() method to verify if an item is your custom item (CustomItems-LabAPI/API/Example/EMPGrenade.cs:30)
  • Manipulating game objects like rooms, lights, and doors (CustomItems-LabAPI/API/Example/EMPGrenade.cs:36-47)
  • Proper cleanup in OnUnregistered() (CustomItems-LabAPI/API/Example/EMPGrenade.cs:23-26)

Available event hooks

The CustomItem base class provides many event hooks you can override:
Event HookDescription
OnUsingCalled when a player starts using the item
OnUsedCalled after the player finishes using the item
OnDroppingCalled when a player starts dropping the item
OnDroppedCalled after the item is dropped
OnPickingUpCalled when a player starts picking up the item
OnPickedUpCalled after the item is picked up
OnSelectingCalled when a player starts selecting the item
OnSelectedCalled after the item is selected
OnUnselectingCalled when a player starts unselecting the item
OnUnselectedCalled after the item is unselected
All event hooks receive an event args parameter that contains information about the event and allows you to modify or cancel the event.

Next steps

Now that you’ve created your first custom item, explore more advanced topics:

API reference

Explore the complete API documentation

Examples

View more example implementations

Build docs developers (and LLMs) love