agentskills.codes
AD

add-achievement-data

Transform raw achievement lists (IDs + comments) into properly formatted Lua achievement data entries for Krowi's Achievement Filter addon. Handles reward type mapping, season references, faction detection, and maintains consistent code style.

Install

mkdir -p .claude/skills/add-achievement-data && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16614" && unzip -o skill.zip -d .claude/skills/add-achievement-data && rm skill.zip

Installs to .claude/skills/add-achievement-data

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Transform raw achievement lists (IDs + comments) into properly formatted Lua achievement data entries for Krowi's Achievement Filter addon. Handles reward type mapping, season references, faction detection, and maintains consistent code style.
243 charsno explicit “when” trigger

About this skill

Transform raw achievement lists (IDs + comments) into properly formatted Lua achievement data entries for the Krowi's Achievement Filter addon. Uses the V2 fluent builder format (Ach(id):Method():...) which is the current standard for all new data across all expansions and clients.

Provide your achievement list in this format and I'll:

  1. Scan the currently open AchievementData.lua file to detect the expansion and latest patch
  2. Confirm the target patch with you (append to existing or create new)
  3. Query wow.tools.local for each achievement to get authoritative name, faction, and reward data
  4. Cross-check Wowhead for any reward or description details the DB doesn't clarify
  5. Parse achievements, detect rewards, seasons, and factions — using DB + web data to fill gaps
  6. Generate properly formatted Lua code using V2 format
  7. Insert or display the results

When to Use

  • Adding new batch of achievements for a patch
  • Converting achievement data from WoW API or external sources
  • Bulk adding achievements with their associated metadata

Input Format

Provide a raw achievement list with this format:

{AchievementID}, -- Achievement Name (optional: Reward: description, Season/Event info, Faction)

Example:

{61792}, -- T-A-G that spells "Gotcha!"
{61793}, -- Deployed to the Void
{ -- Abyss Anglers: Pressurized Eyeglass (Reward: Unlock Pressurized Eyeglass for purchase from Depthdiver Jeju)
    62506,
    {
        RewardType = rewardType.NotCategorized,
    },
},

Processing Steps

0. Determine Target Patch (First Step)

Before parsing achievements, use the Patch Version Determination process (see section below) to establish which patch/expansion these achievements will be added to.

0.5. DB & Web Lookup (Before Parsing)

Before applying comment-based heuristics, query authoritative sources. The DB is ground truth; Wowhead fills gaps.

wow.tools.local (primary — game DB)

Query all IDs in a single batch. Use the build that matches the expansion/client being worked on. Full API reference: .github/skills/verify-achievement-data/API.md.

# Batch lookup — replace with actual IDs and build
$ids  = @(61792, 61793, 62506)
$build = "12.0.5.67602"  # retail; use wow_classic build string for Classic files
$pat  = "^(" + ($ids -join "|") + ")$"
$body = "draw=1&start=0&length=$($ids.Count + 10)&columns[3][search][value]=$pat&columns[3][search][regex]=true"
$resp = Invoke-WebRequest "http://localhost:5000/dbc/data/achievement/?build=$build" `
            -Method POST -Body $body -ContentType "application/x-www-form-urlencoded" -UseBasicParsing
$rows = ($resp.Content | ConvertFrom-Json).data
$byId = @{}
$rows | ForEach-Object { $byId[$_[3]] = $_ }

Column index map (key fields for data entry):

IndexDB columnWhat it tells you
0Description_langAchievement description — use when reward type or category is ambiguous
1Title_langAuthoritative achievement name — use to correct inline comments
2Reward_langNon-empty means reward exists. "Title Reward: X" or "Title: X":Title(). "Reward: X" (no "Title") → tangible reward (mount/pet/toy/etc.)
3IDConfirm ID exists in DB (recordsFiltered == 0 means not found)
5Faction-1 = both, 0 = Horde only, 1 = Alliance only
13RewardItemIDNon-"0" = item reward exists (Retail only — unreliable in Classic)

What to do with DB data:

  • Faction == 0 or 1 → apply :FactionSplit() or :AutoFactionSplit() as appropriate; look for counterpart ID (typically ±1)
  • Reward_lang starts with "Title" → add :Title()
  • Reward_lang non-empty without "Title" prefix → lookup the specific reward type on Wowhead
  • recordsFiltered == 0 → ID not in this build; try alternate build or ask user to confirm ID
  • Title_lang differs from inline comment → correct the comment to match DB name

Build selection: Retail files → wow build (e.g. 12.0.5.67602). Classic files → wow_classic (e.g. 5.5.3.67509 for Cata/MoP Classic) or wow_classic_era. Probe the DB with a known ID to confirm. See API.md for full build table.

Wowhead (secondary — reward and description detail)

Use Wowhead when Reward_lang is ambiguous, empty but a reward is suspected, or you need to see the exact reward item/mount/pet name.

ClientURL pattern
Retailhttps://www.wowhead.com/achievement=ID
Cata / MoP Classichttps://www.wowhead.com/classic/achievement=ID
WotLK Classichttps://www.wowhead.com/wotlk/achievement=ID

On the Wowhead page, look for:

Wowhead sectionMaps to
Title Reward:Title()
Mount in rewards:Mount()
Battle Pet in rewards:Pet()
Toy in rewards:Toy()
Tabard in rewards:Tabard()
Appearance / Transmog set in rewards:Transmog()
Unlocks for purchase (vendor item, not directly awarded):NotCategorized()
Unlock travel method:Mount()
Housing decoration:HousingDecor()
Warband Campsite:WarbandCampsite()
No reward sectionSimple Ach(id)

Tip: Wowhead also shows faction restrictions, category (PvP / Dungeon & Raids / etc.), and "unavailable" banners — use these to confirm :IsPvP(), :FactionSplit(), and :Obtainable() needs.

1. Parse Achievement ID

Extract numeric ID from each entry. IDs must be valid positive integers.

2. Extract Comment

Capture the comment after --. Comments contain:

  • Achievement name (required)
  • Reward type hint in parentheses (optional)
  • Season/Event references (optional)
  • Faction indicator (optional)

3. Reward Type Detection

Map comment text to AchBuilder method names:

Keyword in CommentMethod
"Mount:", "Mount: ":Mount()
"Title:", "Title: ":Title()
"Pet:", "Pet: ":Pet()
"Toy:":Toy()
"Tabard:":Tabard()
"Transmog:":Transmog()
"Unlock ..., for purchase":NotCategorized()
"Unlock ... travel method":Mount()
"Unlock ... decor":HousingDecor()
"Character Unlock:", "Character Title:", "Seasonal Character Title:":Title()
"Shop Sign":HousingDecor()
Bronze Cache:RemixBronze()
Allied Race unlock:AlliedRace()
Warband Campsite:WarbandCampsite()
(no clear match)Ask for clarification

Reward type methods (all 17): :NotCategorized() :Other() :AlliedRace() :Garrison() :Mount() :Pet() :RemixBronze() :Tabard() :Teleport() :Title() :Toy() :TradersTender() :Transmog() :WarbandCampsite() :RemixInfiniteKnowledge() :HousingDecor() :KeystoneResilience()

Additional (non-reward) methods: :IsPvP() :PvP(N) :PvE(N) :IsRealmFirst() :Obtainable(...) :Anniv20() :FactionSplit(faction, altId) :AutoFactionSplit(faction, altId)

Rules:

  • If multiple reward types apply (e.g., "Title and Mount"), chain both: Ach(id):Title():Mount()
  • If comment contains "Reward:" but no recognizable keyword, ask user for clarification
  • If no reward hint in comment, use simple form: Ach(id), -- Comment

4. Season/Event Reference Detection

Extract from comment text:

PatternAction
"Season X" (X = number)Detect context (PvP or PvE) from surrounding text
"PvE Season", "Keystone", "Raid", "Dungeon"Use :PvE(X) where X is the game season number (e.g., 13 for TWW S1)
"PvP Season", "Gladiator", "Duelist", "Rival", "Combatant", "Challenger"Use :PvP(X) where X is the arena season number
PvP context but no season number (e.g., "Battleground", "Tour of Duty")Use :IsPvP() (sets PvP flag only, no season reference)
"Realm First!" in nameUse :IsRealmFirst():Obtainable("Once")
Event name (e.g., "Remix Event", "Anniversary")Try to find matching event ID in codebase or ask user

:IsPvP() vs :PvP(N):

  • :PvP(N) — Achievement is PvP AND tied to a specific season (e.g., gladiator titles, seasonal mounts)
  • :IsPvP() — Achievement is PvP but NOT tied to a specific season (e.g., battleground wins, tour of duty, conquest accumulation)
  • Both can be combined with reward type methods: Ach(id):Pet():IsPvP()

5. Faction Detection

Scan comment for faction keywords:

TextAction
Contains "Alliance"Use :AutoFactionSplit(faction.Alliance, HORDE_ID)
Contains "Horde"Use :AutoFactionSplit(faction.Horde, ALLIANCE_ID)
Faction-specific with no counterpartUse :FactionSplit(faction.X, nil)
No faction keywordDefault to faction-neutral (no FactionSplit)

:FactionSplit(faction.X, nil) — faction-only, no paired achievement: Use when an achievement exists only for one faction with no counterpart (e.g., some Allied Race unlocks):

Ach(12242):FactionSplit(faction.Alliance, nil):AlliedRace(),

Faction Pairing: If detecting either faction variant, automatically look for the counterpart (typically ID+1 or ID-1). Collapse both into a single entry on the lower-ID achievement. Comment order follows the entry: lower-ID name first, higher-ID name second, separated by /:

-- Same name on both sides:
Ach(LOWER_ID):AutoFactionSplit(faction.X, HIGHER_ID), -- Achievement Name

-- Different names:
Ach(LOWER_ID):AutoFactionSplit(faction.X, HIGHER_ID), -- Lower-ID Name / Higher-ID Name

-- Shared prefix and/or suffix — merge them, keep only the unique parts in the middle:
Ach(40234):AutoFactionSplit(faction.Horde, 40235):Title():PvP(38), -- Forged Warlord / Marshal: The War Within Season 1

Use :FactionSplit() (two explicit lines) only when the two achievements have different reward types (e.g., one faction gets a reward the other doesn't).

6. Generate Lua Entry

Build the Ach() call based on


Content truncated.

Search skills

Search the agent skills registry