157 lines
5.1 KiB
Markdown
157 lines
5.1 KiB
Markdown
|
|
# **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).
|