Files
OpenFUT-Core/data/achievements/achievements.json
T
funman300 679f147c6a
CI / Build, lint & test (push) Failing after 1m19s
Phase 20: achievement system
18 data-driven achievements (achievements.json) across 8 trigger categories:
matches_played, matches_won, goals_scored, packs_opened, sbcs_completed,
cards_owned, level, objectives_completed, drafts_completed. Rarities span
common → epic. Coin rewards range from 500 (first_match) to 6000 (win_50).

check_and_unlock() queries the relevant metric from existing tables, skips
already-earned achievements via INSERT OR IGNORE, grants coin rewards, and
fires a persistent notification per unlock. Trigger values are cached per
call to avoid redundant DB round-trips for same-trigger achievements.

Checks run automatically after every match result (all triggers), every
pack open (packs_opened), and every successful SBC submission (sbcs_completed).

GET /achievements returns all definitions annotated with unlocked/unlocked_at,
plus earned and total counts. POST /matches/result response gains an
achievements_unlocked array (empty when nothing new unlocked).

AppState gains achievement_defs (Arc<Vec<AchievementDefinition>>) loaded
from data/achievements/**/*.json at startup — same pattern as obj_defs.

5 new tests: list endpoint, first_match unlock, first_win unlock, no-dup
guard, coin reward verification. Core now at 82 tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 18:03:54 -07:00

183 lines
4.0 KiB
JSON

[
{
"id": "first_match",
"title": "Debut Match",
"description": "Play your very first match.",
"icon": "⚽",
"trigger": "matches_played",
"threshold": 1,
"reward_coins": 500,
"rarity": "common"
},
{
"id": "match_veteran",
"title": "Match Veteran",
"description": "Play 10 matches.",
"icon": "🏟️",
"trigger": "matches_played",
"threshold": 10,
"reward_coins": 1500,
"rarity": "common"
},
{
"id": "match_pro",
"title": "Pro Player",
"description": "Play 50 matches.",
"icon": "🎖️",
"trigger": "matches_played",
"threshold": 50,
"reward_coins": 4000,
"rarity": "rare"
},
{
"id": "first_win",
"title": "First Blood",
"description": "Win your first match.",
"icon": "🏆",
"trigger": "matches_won",
"threshold": 1,
"reward_coins": 500,
"rarity": "common"
},
{
"id": "win_10",
"title": "On Fire",
"description": "Win 10 matches.",
"icon": "🔥",
"trigger": "matches_won",
"threshold": 10,
"reward_coins": 2000,
"rarity": "rare"
},
{
"id": "win_50",
"title": "Unstoppable",
"description": "Win 50 matches.",
"icon": "👑",
"trigger": "matches_won",
"threshold": 50,
"reward_coins": 6000,
"rarity": "epic"
},
{
"id": "goalscorer_10",
"title": "Goalscorer",
"description": "Score 10 goals across all matches.",
"icon": "⚡",
"trigger": "goals_scored",
"threshold": 10,
"reward_coins": 750,
"rarity": "common"
},
{
"id": "top_scorer_50",
"title": "Top Scorer",
"description": "Score 50 goals across all matches.",
"icon": "🥅",
"trigger": "goals_scored",
"threshold": 50,
"reward_coins": 3000,
"rarity": "rare"
},
{
"id": "first_pack",
"title": "Pack Opener",
"description": "Open your first pack.",
"icon": "📦",
"trigger": "packs_opened",
"threshold": 1,
"reward_coins": 500,
"rarity": "common"
},
{
"id": "pack_10",
"title": "Pack Addict",
"description": "Open 10 packs.",
"icon": "🎁",
"trigger": "packs_opened",
"threshold": 10,
"reward_coins": 2500,
"rarity": "rare"
},
{
"id": "collector_20",
"title": "Collector",
"description": "Own 20 cards in your collection.",
"icon": "🗂️",
"trigger": "cards_owned",
"threshold": 20,
"reward_coins": 1000,
"rarity": "common"
},
{
"id": "hoarder_50",
"title": "Hoarder",
"description": "Own 50 cards in your collection.",
"icon": "💎",
"trigger": "cards_owned",
"threshold": 50,
"reward_coins": 3500,
"rarity": "rare"
},
{
"id": "first_sbc",
"title": "Squad Builder",
"description": "Complete your first SBC challenge.",
"icon": "🧩",
"trigger": "sbcs_completed",
"threshold": 1,
"reward_coins": 750,
"rarity": "common"
},
{
"id": "sbc_master",
"title": "SBC Master",
"description": "Complete 5 SBC challenges.",
"icon": "🔧",
"trigger": "sbcs_completed",
"threshold": 5,
"reward_coins": 4000,
"rarity": "epic"
},
{
"id": "level_5",
"title": "Rising Star",
"description": "Reach Level 5.",
"icon": "⬆",
"trigger": "level",
"threshold": 5,
"reward_coins": 2000,
"rarity": "rare"
},
{
"id": "level_10",
"title": "Elite Player",
"description": "Reach Level 10.",
"icon": "⭐",
"trigger": "level",
"threshold": 10,
"reward_coins": 5000,
"rarity": "epic"
},
{
"id": "first_objective",
"title": "On a Mission",
"description": "Complete your first objective.",
"icon": "✅",
"trigger": "objectives_completed",
"threshold": 1,
"reward_coins": 500,
"rarity": "common"
},
{
"id": "draft_debut",
"title": "Draft Veteran",
"description": "Complete a draft session.",
"icon": "🃏",
"trigger": "drafts_completed",
"threshold": 1,
"reward_coins": 1500,
"rarity": "rare"
}
]