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 05: Skill Queue

Overview

The skill queue is Delve’s core strategic system. Players build an ordered list of 6-10 combat skills with optional conditions. The server executes this queue during combat simulation. This feature covers building, saving, validating, and managing multiple named queues.

Dependencies

  • Feature 04 (Character Progression) — for skill unlocks and weapon proficiency

Technical Tasks

1. Static Game Data — Skills

  • Flesh out data/skills/ TOML files (started in Feature 04) with full combat skill details:
    • Per skill: id, name, description, type (attack/heal/buff/debuff/utility), resource_cost (type + amount), cooldown (rounds), base_damage/healing, success_modifier, initiative_modifier, target_type (single/aoe/self/ally), conditions_applied, weapon_type_required
    • Weapon skills: 10 per weapon type (sword, axe, dagger, bow, staff, wand, shield, mace, spear)
    • Class skills: 8-12 per class, unlocked at level milestones
    • Species skills: 1 passive per species (not queued — applied automatically)
    • Gear skills: defined on Legendary/Artifact weapon templates (not in skills data — on item templates)

2. Skill Queue Types (crates/types)

  • Create src/skill.rs:
    • SkillQueueSlot { skill_id: String, condition: QueueCondition }
    • QueueCondition enum with all condition variants:
      • Always
      • IfHpBelow { threshold: u8 }
      • IfHpAbove { threshold: u8 }
      • IfTargetHpBelow { threshold: u8 }
      • IfEnemyCountAbove { count: u8 }
      • IfEnemyCountBelow { count: u8 }
      • IfAllyHpBelow { threshold: u8 }
      • IfResourceAbove { resource: ResourceType, amount: u16 }
      • IfResourceBelow { resource: ResourceType, amount: u16 }
      • IfHasCondition { condition: StatusEffect }
      • IfTargetHasCondition { condition: StatusEffect }
    • ResourceType enum: Stamina, Momentum, Mana, Devotion, Focus, Fury, Resonance, Zeal, Essence

3. Skill Queue Validation (crates/game)

  • Create src/skill_queue.rs:
    • validate_queue(character: &Character, slots: &[SkillQueueSlot], proficiencies: &[WeaponProficiency], equipped: &[Item]) -> Result<()>:
      • Queue length: 1-10 slots (minimum 1, maximum 10)
      • Every skill_id must be known by the character (from class, weapon proficiency, or equipped gear)
      • Weapon skills require the matching weapon type equipped
      • Conditions must reference valid resource types for the character’s class
      • Thresholds must be in valid ranges (0-100 for HP%, valid amounts for resources)
      • Must have at least one Always condition or the queue may never fire
    • get_available_skills(character: &Character, proficiencies: &[WeaponProficiency], equipped: &[Item]) -> Vec<SkillInfo>:
      • Return all skills the character can use based on class, weapon proficiency, and gear
      • Used by the client to populate the skill picker

4. Skill Queue Database Operations

  • Already created skill_queues table in Feature 04 migration
  • Create src/queries/skill_queues.rs:
    • create_skill_queue(pool, character_id, name, slots_json) -> SkillQueue
    • find_skill_queues(pool, character_id) -> Vec<SkillQueue>
    • find_active_queue(pool, character_id) -> Option<SkillQueue>
    • update_skill_queue(pool, id, name?, slots_json?)
    • set_active_queue(pool, character_id, queue_id) — deactivates all others, activates this one
    • delete_skill_queue(pool, id)

5. Skill Queue Routes (crates/api)

  • Create src/routes/skill_queues.rs:
    • GET /api/characters/:id/skill-queues:
      • Return all saved queues for the character (each with name, is_active, slots)
    • POST /api/characters/:id/skill-queues:
      • Body: { name, slots: [{ skill_id, condition }] }
      • Validate queue (all skills owned, conditions valid)
      • Save to DB
      • Return created queue
    • PUT /api/characters/:id/skill-queues/:queue_id:
      • Update name and/or slots
      • Re-validate if slots changed
    • DELETE /api/characters/:id/skill-queues/:queue_id:
      • Cannot delete the active queue (must activate another first)
    • POST /api/characters/:id/skill-queues/:queue_id/activate:
      • Set as active queue (used for the next run)
    • GET /api/characters/:id/available-skills:
      • Return all skills the character can currently use (for the queue builder UI)

6. Client — Skill Queue Builder

  • Create routes/(game)/character/skill-queue/+page.svelte:
    • Queue selector: dropdown of saved queues, “New Queue” button
    • Queue builder:
      • Ordered list of skill slots (drag-and-drop reordering)
      • Each slot shows: skill icon/name + condition dropdown
      • “Add Skill” button opens skill picker
      • Skill picker: filterable list of available skills grouped by source (class, weapon, gear)
      • Condition editor: dropdown per slot with type + threshold input
    • Save/rename/delete queue buttons
    • “Set Active” button
    • Validation feedback: highlight invalid slots, show error messages
  • Create lib/components/character/SkillQueueBuilder.svelte
  • Create lib/components/character/SkillPicker.svelte
  • Create lib/components/character/ConditionEditor.svelte

Tests

Unit Tests

  • validate_queue: accepts valid queue with all skills owned
  • validate_queue: rejects empty queue
  • validate_queue: rejects queue > 10 slots
  • validate_queue: rejects skill not owned by character
  • validate_queue: rejects weapon skill without matching weapon equipped
  • validate_queue: rejects invalid condition threshold (e.g., HP > 100%)
  • validate_queue: warns (but allows) queue with no Always fallback
  • get_available_skills: returns class skills for character’s class
  • get_available_skills: returns weapon skills up to current proficiency
  • get_available_skills: returns gear skills from equipped Legendary weapon
  • get_available_skills: doesn’t return skills for unequipped weapon types
  • QueueCondition serialization round-trips correctly (serde JSON)

Integration Tests

  • GET /api/characters/:id/skill-queues returns empty list for new character
  • POST /api/characters/:id/skill-queues creates queue and returns it
  • POST /api/characters/:id/skill-queues with invalid skill → 422
  • PUT /api/characters/:id/skill-queues/:id updates name and slots
  • POST /api/characters/:id/skill-queues/:id/activate sets active flag
  • Only one queue is active at a time (activating one deactivates others)
  • DELETE on active queue → 409
  • GET /api/characters/:id/available-skills returns skills based on class + proficiency + gear
  • Queue slots JSONB round-trips correctly (stored and retrieved identically)