> For the complete documentation index, see [llms.txt](https://akequ.gitbook.io/scp-classified-site-plugin-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://akequ.gitbook.io/scp-classified-site-plugin-api/docs/creating-new-item-class.md).

# Creating New Item Class

{% hint style="warning" %}
All Item classes must be placed under namespace **Plugin.Items**
{% endhint %}

### Class Functions

* Init() - <mark style="color:green;">\[OPTIONAL]</mark> class initialization(called when item spawned, both on Player and ItemPickup).
* Update() - <mark style="color:green;">\[OPTIONAL]</mark> called every frame on clients.
* ServerUpdate() - <mark style="color:green;">\[OPTIONAL]</mark> called every frame on server.
* OnPickup() - <mark style="color:green;">\[OPTIONAL]</mark> called when item pickuped(on Player).
* OnDrop() - <mark style="color:green;">\[OPTIONAL]</mark> called when item dropped(on Player).
* OnUse() - <mark style="color:green;">\[OPTIONAL]</mark> called when Player use this item.
* OnHolster() - <mark style="color:green;">\[OPTIONAL]</mark> called when Player holster this item.
* OnDestroy() - <mark style="color:green;">\[OPTIONAL]</mark> called on class destroy.
* GetName() - <mark style="color:yellow;">\[REQUIRED]</mark> return displayed item name, return string \[DEFAULT: "item"].
* GetImage() - <mark style="color:yellow;">\[REQUIRED]</mark> return image ID that displayed in inventory, return string \[DEFAULT: "item"].
* OnRefine(int type) - <mark style="color:green;">\[OPTIONAL]</mark> return item ID(empty to destroy item) when item used in SCP-914(type: 0 - rough, 1 - coarse, 2 - 1:1, 3 - fine, 4 - very fine), return string \[DEFAULT: ""].
* GetKeyData() - <mark style="color:green;">\[OPTIONAL]</mark> return information about key card, return KeyData class \[DEFAULT: null].

### Local Properties

* player - return current Player class, if player contains it in inventory.&#x20;
* itemPickup- return current ItemPickup class, if item dropped.

### Local Functions

* SendToEveryone(string FunctionName, params object\[] arguments) - send command to every player to call function with arguments.
* SendToClient(string FunctionName, NetworkConnection connection, params object\[] arguments) - send command to player with connection to call function with arguments.
* SendToServer(string FunctionName, params object\[] arguments) - send command to server to call function with arguments.
* Invoke(Function, float seconds) - same logic as UnityEngine.Object.Invoke, call function after time.

### Example

```csharp
using System.Collections.Generic;
using UnityEngine;

namespace Plugin.Items
{
    public class NewCard : Akequ.Base.Item
    {
        private GameObject model;

        private KeyData keyData = new KeyData()
        {
            containment = 1
        };

        public override void Init()
        {
            model = ResourcesManager.SpawnObject("item_w_key");
            if (player == null)
            {
                model.transform.parent = itemPickup.transform;
                model.transform.localPosition = Vector3.zero;
                model.transform.localRotation = Quaternion.identity;
            }
            else
            {
                model.transform.parent = player.GetBoneTransform("mixamorig:RightHand");
                model.transform.localPosition = new Vector3(-0.002f, 0.165f, 0.032f);
                model.transform.localRotation = Quaternion.Euler(182.021f, -272.248f, -287.107f);
                model.transform.localScale = new Vector3(0.05174018f, 0.06509144f, -0.04974974f);
            }

            model.layer = 6;
            model.GetComponent<MeshRenderer>().sharedMaterial = ResourcesManager.GetObject("mat_key_janitor") as Material;
        }

        public override void OnDrop()
        {
            if (model != null)
            {
                GameObject.Destroy(model);
            }
        }

        public override void OnPickup()
        {
            if (model != null)
            {
                GameObject.Destroy(model);
            }

            if (player.isLocalPlayer)
            {
                model = ResourcesManager.SpawnObject("item_v_key");
                model.transform.parent = player.transform.Find("Recoil/MainCamera");
                model.transform.localPosition = Vector3.zero;
                model.transform.localRotation = Quaternion.identity;
                model.transform.localScale = new Vector3(-0.05f, 0.05f, 0.05f);
                model.GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial = (Material)ResourcesManager
                    .GetObject(
                        player.playerClass.GetHand());
            }
            else
            {
                model = ResourcesManager.SpawnObject("item_w_key");
                model.transform.parent = player.GetBoneTransform("mixamorig:RightHand");
                model.transform.localPosition = new Vector3(-0.002f, 0.165f, 0.032f);
                model.transform.localRotation = Quaternion.Euler(182.021f, -272.248f, -287.107f);
                model.transform.localScale = new Vector3(0.05174018f, 0.06509144f, -0.04974974f);
            }
            model.GetComponentInChildren<MeshRenderer>().sharedMaterial = ResourcesManager.GetObject("mat_key_janitor") as Material;
            model.SetActive(false);
        }

        public override void OnUse()
        {
            model.SetActive(true);
            player.SetHandAnim(4);
            if (player.isLocalPlayer)
            {
                UIManager.SetMobileButtons(new List<string>(){ "Move", "Rotate", "Pause", "PlayerList", "Interact", "Jump", "Run",
                    "Inventory", "Voice" });
            }
        }
        
        public override void OnHolster()
        {
            model.SetActive(false);
            player.SetHandAnim(0);
            if (player.isLocalPlayer)
            {
                UIManager.SetMobileButtons(new List<string>(){ "Move", "Rotate", "Pause", "PlayerList", "Interact", "Jump", "Run",
                    "Inventory", "Voice" });
            }
        }

        public override string GetName()
        {
            return "NewCard";
        }
        
        public override string GetImage()
        {
            return "inv_key_janitor";
        }
        
        public override KeyData GetKeyData()
        {
            return keyData;
        }

        public override string OnRefine(int mode)
        {
            int rand = Random.Range(0, 100);
            if (mode == 2 && rand < 25)
                return "RecruitCard";
            else if (mode == 2 && rand < 50)
                return "AssistantCard";
            else if (mode == 2 && rand < 75)
                return "JanitorCard";
            else if (mode == 2 && rand <= 100)
                return "FoundationAgentCard";
            else if (mode == 3)
                return "EngineerCard";
            else if (mode == 4 && rand < 75)
                return "ContainmentSpecialistCard";
            return "";
        }
    }
}
```

Example Solution can be downloaded here:\
[Link to archive](https://drive.google.com/file/d/1iT4OPJpX_YNxtVkDZWyRiip8tEZHM128/view?usp=sharing)

### Testing

Now we can compile this plugin and move library to server plugins folder according to [Folder Structure](/scp-classified-site-plugin-api/docs/folder-structure.md)\
\
Now we can spawn our item:

<figure><img src="/files/TcSlEpY2CD5k60n5zsTi" alt=""><figcaption></figcaption></figure>
