> For the complete documentation index, see [llms.txt](https://malbersanimations.gitbook.io/animal-controller/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://malbersanimations.gitbook.io/animal-controller/super-item/super-item-system/super-item-manager/item-offsets.md).

# Item Offsets

## Overview

**Super Item Offsets** is a ScriptableObject that stores **every** offset for one character's items: where each item sits in each hand, where it sits in each holster slot, which holster slots it prefers, and the two Animator overrides.

It exists because an offset is a property of the **pair**, not of either side. A dagger sits one way in a human's right hand, another way in the same human's left hand, and another way again in an orc's hand — while remaining one prefab. Putting the offset on the item cannot express that; putting it on the equip point cannot either.

Create it with `Assets ▸ Create ▸ Malbers Animations ▸ Super Item ▸ Item Offsets`, or with the `+` button next to the **Item Offsets** field on the Super Item Manager.

{% hint style="warning" %}
**One asset per character model.** Two characters with the same rig can share one; two different rigs should not. This is the single most common source of "my sword is inside the hand" reports.
{% endhint %}

***

## Requirements

Assign the asset to the **Item Offsets** field on the character's Super Item Manager — it is on both the **Equip Points** and the **Holsters** tab, and each tab draws the matching table inline. On `Awake` the Manager injects it into every Equip Point and every Holster.

Without an asset — or without a matching entry — the **identity offset** is used:

| Value                 | Default                            |
| --------------------- | ---------------------------------- |
| Position              | `(0, 0, 0)`                        |
| Rotation              | `(0, 0, 0)`                        |
| Scale                 | `(1, 1, 1)`                        |
| Holster Slots         | `[0]`                              |
| Anim Type override    | none — the item's own `Item Type`  |
| Holster Anim override | none — the item's own `Holster` ID |

That means a missing entry is never an error. The item simply snaps to the bone origin.

***

## How it works

The asset holds two independent tables.

### Equip Point Offsets

Keyed by **(Super Item ID + Equip Point ID)**.

| Column                          | Meaning                                                                                                                                      |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| **Super Item**                  | The `SuperItemID` — which kind of item.                                                                                                      |
| **Equip Point**                 | The `EquipPointID` — which hand or attachment point.                                                                                         |
| **Position / Rotation / Scale** | The local transform applied after parenting.                                                                                                 |
| **Anim Type**                   | Optional `SuperItemID` sent to the `Left/Right Item Type` Animator parameter **instead of** the item's own. Empty uses the item's Item Type. |

The **Anim Type** override is how a specialised item reuses an existing animation set. A ceremonial sword with its own `Item Type` (so Conditions can tell it apart) can still animate as a plain `Sword` by overriding the animator type — no duplicated animator layers.

### Holster Offsets

Keyed by **(Super Item ID + Holster ID)**.

| Column                          | Meaning                                                                                                         |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| **Super Item**                  | The `SuperItemID`.                                                                                              |
| **Holster**                     | The `HolsterID`.                                                                                                |
| **Position / Rotation / Scale** | The local transform applied inside the slot.                                                                    |
| **Holster Anim**                | Optional `HolsterID` used as the **ability index** of the draw/store Mode instead of the item's own Holster ID. |
| **Holster Slots**               | A **list** of indexes into the holster's `Slots` list, in priority order.                                       |

The **Holster Slots** list is what lets a sword and a spear share the `Left Holster` while sitting on the hip and the back respectively — and what makes dual wielding work in a holster.

{% hint style="info" %}
**Slots is a priority list, not a single index.** The item takes the **first** slot in the list that is still free. `[0, 2]` sends the first dagger to slot `0` and the second copy of the same dagger to slot `2`. An empty list means slot `0`.

Assets authored before the list existed keep their value: the old single `Holster Slot` integer is folded into the list on load, so nothing has to be re-authored.
{% endhint %}

The **Holster Anim** override lets two items in the same holster play different draw animations — a pistol and a knife both on the right thigh, drawn differently.

***

## Authoring offsets

The fastest way is not to type numbers.

1. On the Super Item Manager, select the **Equip Points** (or **Holsters**) tab.
2. Assign the item to the point or holster you are authoring — or press **Equip in Char** / **Holster in Char** on the item's own inspector, which does the assignment for you.
3. The Scene View draws the item's mesh at its current runtime transform, with position, rotation and scale handles.
4. Drag it into place.

That is the whole loop. **There is no Save button** — the handles write straight into the `SuperItemOffsets` asset, and assigning an item to a row creates its entry (or updates the existing one) automatically.

{% hint style="info" %}
The row sync also **creates missing entries** for items that are assigned to a point but not parented to it. There is nothing to capture in that case, but the pair still needs to appear in the list so you can author it later.
{% endhint %}

***

## Validation

The asset's inspector validates both tables on every repaint:

* An entry with an **empty** Super Item or Equip Point / Holster is tinted **red**, and a warning counts them. Such an entry can never be found at runtime.
* **Duplicated** (Super Item + Equip Point) or (Super Item + Holster) pairs are tinted **yellow**. Only the first is ever used.

New entries always start with Scale `(1,1,1)`. Each expanded entry has a **Reset** button that returns Position and Rotation to zero and Scale to one.

***

## API

```csharp
// Equip Point entries
bool          found  = offsets.TryGetOffset(itemID, equipPointID, out TransformOffset offset);
TransformOffset o    = offsets.GetOffset(itemID, equipPointID);        // identity if missing
SuperItemID   over   = offsets.GetItemTypeOverride(itemID, equipPointID);

bool added = offsets.SetOffset(itemID, equipPointID, offset);          // upsert
bool added = offsets.EnsureOffset(itemID, equipPointID);               // create if missing only

// Holster entries
SItemHolsterOffset entry = offsets.GetHolsterEntry(itemID, holsterID);
TransformOffset    o     = offsets.GetHolsterOffset(itemID, holsterID); // identity if missing
int                slot  = offsets.GetHolsterSlot(itemID, holsterID);   // the FIRST (preferred) slot, 0 if missing
List<int>          slots = offsets.GetHolsterSlots(itemID, holsterID);  // the whole priority list, never empty
HolsterID          anim  = offsets.GetHolsterAnim(itemID, holsterID);   // null if missing

bool added = offsets.SetHolsterOffset(itemID, holsterID, offset, slot);
void         offsets.SetHolsterSlot(itemID, holsterID, slot);
bool added = offsets.EnsureHolsterOffset(itemID, holsterID);
```

***

## Migrating from the Weapon Manager

On `MWeapon` the offsets lived on the weapon itself (`Right Hand Offset`, `Left Hand Offset`, `Holster Offset`). If you are porting a weapon:

| Old (on the weapon)              | New (in the character's `SuperItemOffsets`)                  |
| -------------------------------- | ------------------------------------------------------------ |
| Hand offset                      | Equip Point Offsets entry for (Item Type + Right/Left Hand)  |
| Holster offset                   | Holster Offsets entry for (Item Type + Holster)              |
| `Holster Slot` on the weapon     | The **Holster Slots** list of the Holster Offsets entry      |
| Weapon Type sent to the Animator | The **Anim Type** column, when it differs from the Item Type |
