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 15: Achievements & Collections

Overview

Long-term completionist goals: achievements across all game systems (combat, crafting, social, exploration, PVP, collection), the bestiary (creature catalog), item catalog, recipe collection, titles, and leaderboards. Achievements grant points, titles, and cosmetic rewards.

Dependencies

  • Feature 07 (Quests & Runs) — combat and exploration achievements
  • Feature 08 (Crafting & Gathering) — crafting achievements
  • Feature 11 (PVP) — PVP achievements and leaderboards
  • Feature 10 (Guilds) — social achievements

Technical Tasks

1. Static Game Data — Achievements

  • Create data/achievements/:
    • combat.toml: First Blood, Dungeon Crawler (all dungeons), Deadly Survivor (complete Deadly), etc.
    • progression.toml: level milestones, Paragon milestones, full feat selection
    • crafting.toml: First Craft, Master Blacksmith (skill 100), Grand Master (all 100), Critical Crafter (10 crits)
    • social.toml: Guilded (join guild), Raid Ready (first raid), Social Butterfly (10 friends)
    • exploration.toml: Explorer (all regions), Lore Hunter, Cartographer
    • pvp.toml: First Duel, Gladiator (Gold rating), Legend (Diamond)
    • collection.toml: Bestiary Complete, Fashionista (25 cosmetics), Title Collector (10 titles)
    • Per achievement: id, name, description, category, points, reward (title?, portrait_frame?, gold?, materials?), criteria (structured conditions)

2. Achievement Tracking Types (crates/types)

  • Create src/achievement.rs:
    • AchievementCriteria enum:
      • KillCount { creature_id: Option<String>, count: u32 } — kill N creatures (or specific type)
      • DungeonComplete { dungeon_id: Option<String>, difficulty: Option<Difficulty> }
      • CraftCount { profession: Option<String>, count: u32 }
      • ReachLevel { level: u16 }
      • ReachProficiency { weapon_type: String, level: u16 }
      • ReachReputation { faction_id: String, tier: ReputationTier }
      • PvpRating { bracket: String, rating: i32 }
      • FriendCount { count: u32 }
      • GuildAction { action: String } — join, create, etc.
      • CollectionCount { collection: String, count: u32 }
    • Achievement: id, name, description, category, points, reward, criteria

3. Database Migration

  • Create migration 0014_create_achievements.sql:
    • character_achievements: character_id, achievement_id, earned_at — PK: character_id + achievement_id
    • character_bestiary: character_id, creature_id, kills, first_killed — PK: character_id + creature_id
    • character_titles: character_id, title_id, earned_at, is_active — PK: character_id + title_id

4. Achievement Engine (crates/game)

  • Create src/achievements.rs:
    • check_achievements(character: &Character, event: &GameEvent, state: &AchievementState) -> Vec<String>:
      • Given a game event (kill, craft, level up, etc.), check all relevant achievements
      • Return IDs of newly earned achievements
    • GameEvent enum:
      • CreatureKilled { creature_id: String }
      • RunCompleted { quest_id: String, difficulty: Difficulty }
      • ItemCrafted { profession: String }
      • LevelReached { level: u16 }
      • ProficiencyReached { weapon_type: String, level: u16 }
      • ReputationChanged { faction_id: String, new_rep: i32 }
      • PvpMatchCompleted { bracket: String, new_rating: i32 }
      • FriendAdded { total_friends: u32 }
      • GuildJoined / GuildCreated
    • AchievementState: set of already-earned achievement IDs (to avoid re-checking)

5. Bestiary Tracking

  • Create src/bestiary.rs:
    • record_kill(character_id: Uuid, creature_id: &str):
      • Increment kill count
      • If first kill, record timestamp
    • get_bestiary_completion(character_id: Uuid) -> BestiaryProgress:
      • Total creatures encountered / total creatures in game
      • Per-region completion percentage

6. Queries (crates/db)

  • Create src/queries/achievements.rs:
    • get_earned_achievements(pool, character_id) -> Vec<CharacterAchievement>
    • grant_achievement(pool, character_id, achievement_id)
    • get_achievement_points(pool, character_id) -> u32
    • get_bestiary(pool, character_id) -> Vec<BestiaryEntry>
    • upsert_bestiary_entry(pool, character_id, creature_id, kills_delta)
    • get_active_title(pool, character_id) -> Option<String>
    • set_active_title(pool, character_id, title_id)
    • get_earned_titles(pool, character_id) -> Vec<Title>

7. Integrate Achievement Checks into Workers

  • After every significant game event, call check_achievements:
    • Simulation worker: after each encounter (CreatureKilled), after run (RunCompleted, LevelReached)
    • Crafting worker: after craft (ItemCrafted)
    • PVP worker: after match (PvpMatchCompleted)
    • Reputation updates: after rep change (ReputationChanged)
    • Social actions: on friend add, guild join/create
  • For each newly earned achievement:
    • Grant achievement record
    • Grant reward (title, gold, materials)
    • Create notification (AchievementEarned)
  • Update bestiary after combat encounters (record creature kills)

8. Leaderboard System

  • Redis sorted sets for leaderboards (already defined in tech architecture):
    • leaderboard:pvp:1v1:season:{n} — rating
    • leaderboard:pvp:3v3:season:{n} — rating
    • leaderboard:achievements — total points
    • leaderboard:wealth — gold
  • Update leaderboards when relevant data changes:
    • PVP: after match resolution
    • Achievements: after achievement granted
    • Wealth: after gold change (debounced — update every 5 minutes via scheduler)

9. API Routes (crates/api)

  • Create src/routes/achievements.rs:
    • GET /api/characters/:id/achievements:
      • Return earned achievements with timestamps + total points
      • Include unearned achievements as “locked” entries with descriptions (progression visibility)
    • GET /api/characters/:id/bestiary:
      • Return creature entries: name, kills, first killed, completion percentage
    • GET /api/characters/:id/titles:
      • Return earned titles, active title
    • POST /api/characters/:id/titles/set:
      • Body: { title_id }
      • Set active title (displayed on profile)
    • GET /api/leaderboards/:type:
      • Query params: page, bracket (for PVP)
      • Return top 100 + requesting player’s rank
    • GET /api/characters/:id/showcase:
      • Return selected 5 achievements for profile display
    • PUT /api/characters/:id/showcase:
      • Body: { achievement_ids: [5 max] }

10. Client — Achievements UI

  • Create routes/(game)/achievements/+page.svelte:
    • Category tabs: Combat, Progression, Crafting, Social, Exploration, PVP, Collection
    • Achievement cards: name, description, progress bar (if trackable), earned/locked indicator, points, reward preview
    • Total achievement points prominently displayed
  • Create routes/(game)/bestiary/+page.svelte:
    • Grid of creature entries (unlocked show art + stats, locked show silhouette)
    • Regional filters
    • Completion percentage
  • Create routes/(game)/leaderboards/+page.svelte:
    • Leaderboard tabs: PVP, Achievements, Wealth, Dungeon Speed, Weekly
    • Top 100 table with rank, name, score
    • “Your Rank” indicator
  • Create routes/(game)/profile/+page.svelte:
    • Character card: name, level, class, active title
    • Achievement showcase (5 selected)
    • Key stats: total achievements, bestiary %, PVP rating

Tests

Unit Tests

  • check_achievements: CreatureKilled event triggers “First Blood” when first kill
  • check_achievements: doesn’t re-trigger already-earned achievements
  • check_achievements: LevelReached(10) triggers level 10 achievement
  • check_achievements: multiple achievements can trigger from one event
  • record_kill: increments count, first kill sets timestamp
  • get_bestiary_completion: correct percentage calculation

Integration Tests

  • Run completion triggers relevant combat achievements
  • Achievement grant creates notification
  • Achievement grant adds points to leaderboard
  • GET /api/characters/:id/achievements returns earned + locked achievements
  • GET /api/characters/:id/bestiary returns entries after combat
  • GET /api/leaderboards/achievements returns sorted by points
  • POST /api/characters/:id/titles/set changes active title
  • PUT /api/characters/:id/showcase saves 5 achievement selections
  • Bestiary entry created after first encounter with creature
  • Kill count increments across multiple runs