# **Inventory System Specification**

This document defines the architecture for item management, covering individual Explorer loadouts and the shared Party/Hub storage.

## **1. System Overview**

The Inventory system operates in two distinct contexts:

1. **Run Context (The Expedition):**
   - **Unit Loadout:** Active gear affecting stats. Locked during combat (usually), editable during rest.
   - **Run Stash (The Bag):** Temporary storage for loot found during the run. Infinite (or high) capacity.
   - **Rule:** If the squad wipes, the _Run Stash_ is lost. Only equipped gear might be recovered (depending on difficulty settings).
2. **Hub Context (The Armory):**
   - **Master Stash:** Persistent storage for all unequipped items.
   - **Management:** Players move items between the Master Stash and Unit Loadouts to prepare for the next run.
   - **Extraction:** Upon successful run completion, _Run Stash_ contents are merged into _Master Stash_.

## **2. Visual Description (UI)**

### **A. Unit Loadout (The Paper Doll)**

- **Visual:** A silhouette or 3D model of the character.
- **Slots:**
  - **Primary Hand:** Weapon (Sword, Staff, Wrench).
  - **Off-Hand:** Shield, Focus, Tool, or 2H (occupies both).
  - **Body:** Armor (Plate, Robes, Vest).
  - **Accessory/Relic:** Stat boosters or Passive enablers.
  - **Belt (2 Slots):** Consumables (Potions, Grenades) usable in combat via Bonus Action.
- **Interaction:** Drag-and-drop from Stash to Slot. Invalid slots highlight Red. Valid slots highlight Green.

### **B. The Stash (Grid View)**

- **Visual:** A grid of item tiles on the right side of the screen.
- **Filters:** Tabs for [All] [Weapons] [Armor] [Utility] [Consumables].
- **Sorting:** By Rarity (Color Coded border) or Tier.
- **Context Menu:** Right-click an item to "Equip to Active Unit" or "Salvage/Sell".

## **3. TypeScript Interfaces (Data Model)**

```typescript
// src/types/Inventory.ts

export type ItemType =
  | "WEAPON"
  | "ARMOR"
  | "RELIC"
  | "UTILITY"
  | "CONSUMABLE"
  | "MATERIAL";
export type Rarity = "COMMON" | "UNCOMMON" | "RARE" | "ANCIENT";
export type SlotType = "MAIN_HAND" | "OFF_HAND" | "BODY" | "ACCESSORY" | "BELT";

/**
 * A specific instance of an item.
 * Allows for RNG stats or durability in the future.
 */
export interface ItemInstance {
  uid: string; // Unique Instance ID (e.g. "ITEM_12345_A")
  defId: string; // Reference to static registry (e.g. "ITEM_RUSTY_BLADE")
  isNew: boolean; // For UI "New!" badges
  quantity: number; // For stackables (Potions/Materials)
}

/**
 * The inventory of a single character.
 */
export interface UnitLoadout {
  mainHand: ItemInstance | null;
  offHand: ItemInstance | null;
  body: ItemInstance | null;
  accessory: ItemInstance | null;
  belt: [ItemInstance | null, ItemInstance | null]; // Fixed 2 slots
}

/**
 * The shared storage (Run Bag or Hub Stash).
 */
export interface InventoryStorage {
  id: string; // "RUN_LOOT" or "HUB_VAULT"
  items: ItemInstance[]; // Unordered list
  currency: {
    aetherShards: number;
    ancientCores: number;
  };
}

/**
 * Data payload for moving items.
 */
export interface TransferRequest {
  itemUid: string;
  sourceContainer: "STASH" | "UNIT_LOADOUT";
  targetContainer: "STASH" | "UNIT_LOADOUT";
  targetSlot?: SlotType; // If moving to Unit
  slotIndex?: number; // For Belt slots (0 or 1)
  unitId?: string; // Which unit owns the loadout
}
```

## **4. Logic & Rules**

### **A. Equipping Items**

1. **Validation:**
   - Check Item.requirements (Class Lock, Min Stats) against Unit.baseStats.
   - Check Slot Compatibility (Can't put Armor in Weapon slot).
   - _Two-Handed Logic:_ If equipping a 2H weapon, unequip Off-Hand automatically.
2. **Swapping:**
   - If target slot is occupied, move the existing item to Stash (or Swap if source was another slot).
3. **Stat Recalculation:**
   - Trigger unit.recalculateStats() immediately.

### **B. Stacking**

- **Equipment:** Non-stackable. Each Sword is a unique instance.
- **Consumables/Materials:** Stackable up to 99.
- **Logic:** When adding a Potion to Stash, check if defId exists. If yes, quantity++. If no, create new entry.

### **C. The Extraction (End of Run)**

```js
function finalizeRun(runInventory, hubInventory) {
  // 1. Transfer Currency
  hubInventory.currency.shards += runInventory.currency.shards;

  // 2. Transfer Items
  for (let item of runInventory.items) {
    hubInventory.addItem(item);
  }

  // 3. Clear Run Inventory
  runInventory.clear();
}
```

## **5. Conditions of Acceptance (CoA)**

**CoA 1: Class Restrictions**

- Attempting to equip a "Tinker Only" item on a "Vanguard" must fail.
- The UI should visually dim incompatible items when a unit is selected.

**CoA 2: Stat Updates**

- Equipping a `+5 Attack` sword must immediately update the displayed Attack stat in the Character Sheet.
- Unequipping it must revert the stat.

**CoA 3: Belt Logic**

- Using a Consumable in combat (via `ActionSystem`) must reduce its quantity.
- If quantity reaches 0, the item reference is removed from the Belt slot.

**CoA 4: Persistence**

- Saving the game must serialize the `InventoryStorage` array correctly.
- Loading the game must restore specific item instances (not just generic definitions).

---

## **6. Integration Strategy (Wiring)**

This section defines where the Inventory System connects to the rest of the engine.

### **A. Game Loop (Looting)**

- **Trigger:** Player unit moves onto a tile with a Loot Chest / Item Drop.
- **Logic:** `GameLoop` detects collision -> calls `InventoryManager.runStash.addItem(foundItem)`.
- **Visual:** `VoxelManager` removes the chest model. UI shows "Item Acquired" toast.

### **B. Character Sheet (Management)**

- **Trigger:** Player opens Character Sheet -> Inventory Tab.
- **Logic:** The UI Component imports `InventoryManager`.
- **Display:** It renders `InventoryManager.runStash.items` (if in dungeon) or `hubStash.items` (if in hub).
- **Action:** Dragging an item to a slot calls `InventoryManager.equipItem(activeUnit, itemUid, slot)`.

### **C. Combat System (Consumables)**

- **Trigger:** Player selects a "Potion" from the Combat HUD Action Bar.
- **Logic:**
  1. Check `unit.equipment.belt` for the item.
  2. Execute Effect (Heal).
  3. Call `InventoryManager.consumeItem(unit, slotIndex)`.
  4. Update Unit Inventory state.

### **D. Persistence (Saving)**

- **Trigger:** `GameStateManager.saveRun()` or `saveRoster()`.
- **Logic:** The `Explorer` class's `equipment` object and the `InventoryManager`'s `runStash` must be serialized to JSON.
- **Requirement:** Ensure `ItemInstance` objects are saved with their specific `uid` and `quantity`, not just `defId`.
