Inventory Management
Characters have a bag for carrying items and equipment slots for wearing them.
Bag System
The bag uses a grid-based layout:
InventoryGrid
interface InventoryGrid {
width: number; // Default: 10
height: number; // Default: 10
items: GridItem[];
}
interface GridItem {
itemId: string;
x: number; // Left position
y: number; // Top position
width: number; // From base type
height: number; // From base type
}
Operations
| Operation | Description |
|---|---|
GetBagGrid | Get grid layout with positions |
GetBagItems | Get full item details |
MoveBagItem | Move item to new position |
Collision Detection
Items cannot overlap. The grain validates positions:
public async Task<bool> MoveBagItemAsync(Guid itemId, int newX, int newY)
{
var item = _state.BagItems[itemId];
// Check bounds
if (newX + item.Width > GridWidth || newY + item.Height > GridHeight)
return false;
// Check collision with other items
foreach (var other in _state.BagItems.Values)
{
if (other.ItemId != itemId && Overlaps(newX, newY, item, other))
return false;
}
// Move successful
UpdatePosition(itemId, newX, newY);
return true;
}
Equipment Slots
Characters have 10 equipment slots:
EquipmentSlot Enum
enum EquipmentSlot {
Head = 0,
Body = 1,
Gloves = 2,
Boots = 3,
MainHand = 4,
OffHand = 5,
Amulet = 6,
Ring1 = 7,
Ring2 = 8,
Belt = 9
}
Equip Operation
EquipResult
interface EquipResult {
success: boolean;
swappedItem?: Item; // Item that was in the slot
errorMessage?: string; // Why equip failed
}
Stash Tabs
Account stash is shared across characters (per season):
Operations
| Operation | Description |
|---|---|
GetTabsAsync | List all stash tabs |
GetTabItemsAsync | Get items in a tab |
AddItemAsync | Add item to stash |
RemoveItemAsync | Take item from stash |
TransferItemAsync | Move between tabs |
Character Stats
Stats are calculated from base stats + equipment bonuses:
interface CharacterStats {
baseStats: Record<string, number>; // Without equipment
totalStats: Record<string, number>; // With equipment
bonuses: StatBonus[]; // Breakdown
}
interface StatBonus {
source: string; // Item name
slot: EquipmentSlot;
stat: string;
value: number;
}