Skip to main content

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

OperationDescription
GetBagGridGet grid layout with positions
GetBagItemsGet full item details
MoveBagItemMove 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

OperationDescription
GetTabsAsyncList all stash tabs
GetTabItemsAsyncGet items in a tab
AddItemAsyncAdd item to stash
RemoveItemAsyncTake item from stash
TransferItemAsyncMove 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;
}

Calculation Flow