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 14: Dailies, Weeklies & Seasons

Overview

Recurring engagement systems: daily first-run bonus, 3 daily bounties with bonus chest, daily faction quests (Feature 12), weekly challenge dungeons, rotating seasonal events with free/premium reward tracks, and the rested XP bonus for offline players. Designed to reward regular play without punishing absence.

Dependencies

  • Feature 07 (Quests & Runs) — daily bounties and weekly challenges are run types
  • Feature 04 (Character Progression) — XP bonuses, rested bonus
  • Feature 12 (Factions) — daily faction quests

Technical Tasks

1. Database Migrations

  • Create migration 0013_create_dailies.sql:
    • daily_tracking: character_id, date, first_run_bonus (bool), bounties_completed (smallint), bounty_chest_claimed (bool), faction_quests (JSONB) — PK: character_id + date
    • weekly_tracking: character_id, week_start (date), challenge_completed (bool), raid_tokens_earned (int) — PK: character_id + week_start
    • season_progress: character_id, season_id, track (‘free’/‘premium’), tier_reached (smallint), xp (int) — PK: character_id + season_id
    • seasons: id, name, starts_at, ends_at, theme, is_active

2. Daily Reset Logic (crates/game)

  • Create src/dailies.rs:
    • DAILY_FIRST_RUN_XP_BONUS: f64 = 0.50 (50% bonus XP)
    • DAILY_FIRST_RUN_GOLD_BONUS: f64 = 0.50 (50% bonus gold)
    • DAILY_BOUNTY_COUNT: u8 = 3
    • generate_daily_bounties(character_level: u16, date: NaiveDate) -> Vec<DailyBounty>:
      • 3 short bounties, seeded by date for server-wide consistency
      • Different content than the quest board
    • check_bounty_chest_eligible(bounties_completed: u8) -> bool: all 3 done
    • roll_bounty_chest(character_level: u16, rng: &mut impl Rng) -> Vec<GeneratedItem>:
      • Guaranteed Uncommon+ item, bonus materials, gold

3. Weekly Challenge Logic (crates/game)

  • Create src/weeklies.rs:
    • generate_weekly_challenge(week_start: NaiveDate) -> WeeklyChallenge:
      • Rotating modifier dungeon (harder than normal, unique mechanic)
      • Same challenge for all players (seeded by week)
      • Duration: 1-2 hours
    • roll_weekly_chest(character_level: u16, rng: &mut impl Rng) -> Vec<GeneratedItem>:
      • Guaranteed Rare+ item, premium materials

4. Rested Bonus Logic (crates/game)

  • Create src/rested.rs:
    • calculate_rested_bonus(last_active: DateTime, now: DateTime) -> f64:
      • +25% XP after 24 hours offline
      • Caps at +50% after 3+ days
      • Linear ramp: 0% at 0h, 25% at 24h, 50% at 72h
    • consume_rested_bonus(current: f64, xp_earned: u64) -> (f64, u64):
      • Apply bonus to earned XP
      • Deplete rested pool proportionally
      • Returns (remaining_bonus, bonus_xp_amount)

5. Seasonal Content Logic (crates/game)

  • Create src/seasons.rs:
    • Season: id, name, starts_at, ends_at, theme, free_track (Vec), premium_track (Vec)
    • SeasonTier: tier_number, xp_required, rewards (Vec)
    • Free track: 15 tiers
    • Premium track: 30 additional tiers (Patron only)
    • calculate_season_xp(activity: &str, difficulty: Difficulty) -> u32:
      • XP from seasonal dungeons, regular runs, PVP, daily completion
    • check_tier_up(current_xp: u32, current_tier: u16, track: &[SeasonTier]) -> Option<TierUpResult>
    • Seasonal challenge dungeons: unique encounter modifiers per season theme

6. Queries (crates/db)

  • Create src/queries/dailies.rs:
    • get_or_create_daily_tracking(pool, character_id, date) -> DailyTracking
    • update_daily_tracking(pool, character_id, date, updates)
    • get_or_create_weekly_tracking(pool, character_id, week_start) -> WeeklyTracking
    • update_weekly_tracking(pool, character_id, week_start, updates)
    • get_season_progress(pool, character_id, season_id) -> Option<SeasonProgress>
    • update_season_progress(pool, character_id, season_id, new_xp, new_tier)
    • get_active_season(pool) -> Option<Season>

7. Scheduled Workers

  • Update scheduler in crates/workers:
    • daily-reset (00:00 UTC): no DB mutation needed — daily_tracking rows are created per-day on first access
    • weekly-reset (Monday 00:00 UTC): same pattern for weekly_tracking
    • rested-bonus-tick (every 1 hour): update rested_bonus for characters inactive > 24h
    • season-transition (manual or scheduled): end current season, archive progress, activate next season

8. Update Run Completion for Dailies

  • In simulation worker, after resolving a run:
    • If this is the character’s first run today: apply first-run XP/gold bonus
    • If this was a daily bounty: increment bounties_completed, check for chest
    • If this was the weekly challenge: mark challenge_completed, grant chest
    • If season is active: add season XP, check for tier up
    • Apply rested bonus to XP earned (if any rested bonus available)

9. API Routes (crates/api)

  • Create src/routes/dailies.rs:
    • GET /api/characters/:id/dailies:
      • Return: first_run_bonus_available, daily_bounties (3 with completion status), bounty_chest_available, rested_bonus_percentage
    • GET /api/characters/:id/weeklies:
      • Return: weekly_challenge (details + completion status), raid_tokens (earned / cap)
    • GET /api/seasons/current:
      • Return: active season info, tracks, rewards per tier
    • GET /api/characters/:id/season-progress:
      • Return: current tier, XP, rewards claimed, next tier preview

10. Client — Dailies & Season UI

  • Add daily/weekly panel to main game dashboard:
    • Daily bounties: 3 checkboxes, bonus chest indicator
    • First run bonus indicator
    • Weekly challenge: name, completion status
    • Rested bonus display
  • Create routes/(game)/season/+page.svelte:
    • Season theme banner
    • Reward track visualization: horizontal progress bar with tier markers
    • Free track on top, premium track below (greyed if not Patron)
    • Claimed/unclaimed reward indicators

Tests

Unit Tests

  • generate_daily_bounties: returns 3 bounties
  • generate_daily_bounties: deterministic per date
  • check_bounty_chest_eligible: true when 3/3, false otherwise
  • generate_weekly_challenge: deterministic per week
  • generate_weekly_challenge: different each week
  • calculate_rested_bonus: 0% at 0 hours
  • calculate_rested_bonus: 25% at 24 hours
  • calculate_rested_bonus: 50% at 72+ hours
  • calculate_rested_bonus: linear interpolation between thresholds
  • consume_rested_bonus: depletes bonus proportionally
  • calculate_season_xp: returns correct XP per activity type
  • check_tier_up: returns tier-up when XP sufficient
  • check_tier_up: returns None when insufficient

Integration Tests

  • GET /api/characters/:id/dailies returns correct state for today
  • First run of the day applies 50% XP and gold bonus
  • Second run of the day does NOT apply bonus
  • Completing 3 daily bounties enables bonus chest claim
  • Weekly challenge completion grants weekly chest
  • Season XP accumulates across activities
  • Season tier-up triggers notification
  • Rested bonus applies to run XP after offline period
  • Daily tracking resets per calendar day (UTC)
  • Weekly tracking resets on Monday