Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Feature 03: Items & Inventory

Overview

The item system: gear templates, item instances with random properties, inventory management (backpack, equipped slots, bank), equipping/unequipping, and salvaging. This must be in place before combat or quests, since characters need gear to do anything.

Dependencies

  • Feature 02 (Character Creation)

Technical Tasks

1. Static Game Data — Item Templates

  • Create data/items/ directory with TOML files organized by category:
    • weapons/swords.toml, weapons/axes.toml, weapons/daggers.toml, weapons/bows.toml, weapons/staves.toml, weapons/wands.toml, weapons/shields.toml
    • armor/heavy.toml, armor/medium.toml, armor/light.toml
    • accessories/rings.toml, accessories/amulets.toml, accessories/cloaks.toml, accessories/belts.toml
    • consumables/potions.toml, consumables/scrolls.toml, consumables/supplies.toml
    • materials/crafting.toml (placeholder — filled in Feature 09)
  • Define item template struct:
    name, item_type, subtype, slot, rarity, level_req,
    base_stats: { damage?, armor?, evasion?, speed? },
    signature_effect? (for Rare+),
    skill_granted? (for Legendary/Artifact weapons)
    
  • Start with Tier 1 (level 1-10) items — enough to test the full system. Higher tiers added later.
  • Create crates/game/src/items.rs:
    • load_item_templates()HashMap<String, ItemTemplate>
    • ItemTemplate struct
    • EquipmentSlot enum: MainHand, OffHand, Head, Chest, Hands, Feet, Cloak, Ring1, Ring2, Amulet, Belt

2. Random Bonus Property System (crates/game)

  • Create src/item_generation.rs:
    • Define bonus property pools:
      • Offensive: bonus damage, crit chance, attack speed, armor penetration
      • Defensive: bonus armor, evasion, HP, damage reduction
      • Attribute: +might, +logic, +speed, +presence, +fortitude, +luck
      • Resource: +max resource, +resource regen
      • Utility: +gold find, +XP gain, +crafting speed
    • Define potency tiers: Minor, Standard, Major, Grand
    • generate_item(template_id: &str, rng: &mut impl Rng) -> Item:
      • Common: base stats only
      • Uncommon: base stats + 1 random bonus
      • Rare: base + signature effect + 1-2 random bonuses
      • Very Rare: base + signature + 2-3 random bonuses
      • Legendary: base + signature + 3 random bonuses + gear skill
      • Artifact: hand-defined (no random generation)
    • Bonus selection uses weighted random from the appropriate pool

3. Item & Inventory Tables Migration

  • Create migration 0004_create_items.sql:
    • items table: id, owner_id, template_id, rarity, enhancement, bonus_properties (JSONB), location, slot_index, created_at
    • Index on (owner_id), (owner_id, location)
    • artifacts table: template_id (PK), held_by, acquired_at

4. Item Model & Queries (crates/db)

  • Create src/models/item.rs:
    • Item struct with FromRow
    • ItemLocation enum serialized as text
    • BonusProperty struct (for JSONB deserialization)
  • Create src/queries/items.rs:
    • create_item(pool, owner_id, template_id, rarity, bonuses, location) -> Item
    • find_items_by_owner(pool, owner_id) -> Vec<Item>
    • find_items_by_location(pool, owner_id, location) -> Vec<Item>
    • find_equipped_items(pool, owner_id) -> Vec<Item>
    • find_item_by_id(pool, id) -> Option<Item>
    • update_item_location(pool, item_id, new_location, slot_index)
    • delete_item(pool, item_id)
    • count_items_in_location(pool, owner_id, location) -> i64

5. Equip/Unequip Logic (crates/game)

  • Create src/equipment.rs:
    • can_equip(character: &Character, item: &Item, slot: EquipmentSlot) -> Result<()>:
      • Check level requirement
      • Check class restrictions (if any)
      • Check slot compatibility (e.g., can’t put a sword in head slot)
      • Check two-handed weapon rules (main hand + off hand)
    • get_equipped_stats(items: &[Item]) -> EquippedStats:
      • Sum all base stats + bonus properties from equipped items
      • Return aggregated damage, armor, evasion, attribute bonuses, etc.

6. Salvage System (crates/game)

  • Create src/salvage.rs:
    • salvage_item(item: &Item) -> Vec<SalvageMaterial>:
      • Returns materials based on rarity (NOT level — per design doc)
      • Common → Common Fragments
      • Uncommon → Uncommon Shards
      • Rare → Rare Cores
      • Very Rare → Prismatic Essences
      • Legendary → Legendary Sparks
    • Material quantities scale with rarity, not item level

7. Inventory Routes (crates/api)

  • Create src/routes/inventory.rs:
    • GET /api/characters/:id/inventory:
      • Return all items grouped by location: { equipped: [], backpack: [], bank: [] }
      • Each item includes resolved template data (name, base stats) merged with instance data (bonuses, enhancement)
    • POST /api/characters/:id/equip:
      • Body: { item_id, slot }
      • Validate ownership, slot compatibility, level requirement
      • If slot already occupied, swap to backpack
      • Update item locations in DB
    • POST /api/characters/:id/unequip:
      • Body: { slot }
      • Move equipped item to backpack
      • Check backpack isn’t full
    • POST /api/characters/:id/salvage:
      • Body: { item_ids: [uuid] }
      • Validate all items owned and in backpack/bank
      • Cannot salvage equipped items
      • Delete items, grant materials (materials are items in backpack with type: material)
      • Return list of materials gained
    • POST /api/characters/:id/move-item:
      • Body: { item_id, to_location, to_index? }
      • Move between backpack ↔ bank
      • Validate capacity limits

8. Starting Equipment

  • Update character creation (Feature 02) to grant starting gear:
    • Each class gets a weapon + basic armor appropriate to their archetype
    • Items are Common rarity, level 1
    • Created as item instances and placed in equipped slots

9. Client — Inventory UI

  • Create routes/(game)/inventory/+page.svelte:
    • Equipment panel: visual grid of 11 gear slots (character paper doll layout)
    • Backpack panel: grid of items with drag-and-drop support
    • Bank panel: accessible tab, grid layout
    • Item tooltip on hover/tap: name, rarity color, base stats, bonus properties, level req, slot
    • Equip: drag from backpack to slot, or right-click → “Equip”
    • Unequip: click equipped item → “Unequip”
    • Salvage: select multiple items → “Salvage” button with confirmation
  • Create lib/types/item.ts — TypeScript types for items
  • Create lib/components/inventory/ItemTooltip.svelte — reusable tooltip component
  • Create lib/components/inventory/ItemGrid.svelte — reusable grid component

Tests

Unit Tests

  • generate_item: Common items have no bonus properties
  • generate_item: Rare items have signature effect + 1-2 bonuses
  • generate_item: Legendary items have 3 bonuses + gear skill reference
  • generate_item: deterministic with seeded RNG (same seed → same item)
  • can_equip: accepts valid weapon in main hand
  • can_equip: rejects item below level requirement
  • can_equip: rejects sword in head slot
  • can_equip: handles two-handed weapon (clears off-hand)
  • get_equipped_stats: correctly sums stats from multiple items
  • get_equipped_stats: includes bonus properties
  • salvage_item: Common → correct Common Fragments count
  • salvage_item: Rare → Rare Cores (not affected by item level)
  • Item template loading: all templates load without error, no missing references

Integration Tests

  • GET /api/characters/:id/inventory returns equipped + backpack + bank items
  • POST /api/characters/:id/equip moves item from backpack to slot
  • POST /api/characters/:id/equip swaps existing equipped item to backpack
  • POST /api/characters/:id/equip rejects item not owned by character
  • POST /api/characters/:id/unequip moves item to backpack
  • POST /api/characters/:id/unequip fails when backpack is full
  • POST /api/characters/:id/salvage deletes items and returns materials
  • POST /api/characters/:id/salvage rejects equipped items
  • POST /api/characters/:id/move-item moves item between backpack and bank
  • Character creation grants starting equipment in correct slots
  • Inventory respects backpack capacity limit (default 30 slots)
  • Bank respects bank capacity limit (default 50 slots, upgradeable)