feat(editor): add WSCS (Skill Cost) open catalog format

Open replacement for Blizzard's SkillCostsData.dbc plus the
per-rank training cost tables. Defines the tiered progression of
trainable skills: each rank unlocks a skill range, requires a
minimum character level, and costs a fixed amount of gold to
learn.

The canonical 6-tier profession progression captured by the
default preset:
  Apprentice    skill 0-75     lvl 5    1s
  Journeyman    skill 50-150   lvl 10   5s
  Expert        skill 125-225  lvl 20   1g
  Artisan       skill 200-300  lvl 35   5g
  Master        skill 275-375  lvl 50   10g
  Grand Master  skill 350-450  lvl 65   25g

Same shape applies to weapon skills (free, level-gated, capped at
5x char level) and riding skills (canonical Vanilla / TBC / WotLK
gold costs from 90g Apprentice through 5000g Artisan flying down
to 1000g Cold Weather Flying).

Five costKind values cover the full training-skill space
(Profession / WeaponSkill / RidingSkill / ClassSkill / Misc).
Each entry's copperCost stores the cost in copper (1g = 10000c)
which the info renderer pretty-prints as "25g 0s 0c".

Cross-references back to WSKL — skill entries reference costId
here for the tiered training schedule. nextTrainable(currentSkill,
characterLevel) is the engine helper that returns the lowest-rank
tier a character qualifies for and hasn't capped yet — used by
trainer NPCs to populate their offered-skill list.

Three preset emitters: --gen-scs (6 profession tiers), --gen-scs-
weapon (5 weapon skill tiers), --gen-scs-riding (5 riding tiers
with canonical gold costs).

Validation enforces id+name presence, costKind 0..4, no duplicate
ids, min<max range; warns on:
  - requiredLevel > 80 (unreachable at WotLK cap)
  - RidingSkill with requiredLevel < 20 (Apprentice canonically
    unlocks at 20)
  - Profession kind with copperCost=0 (every standard tier costs
    at least a copper — usually a config bug)

Wired through the cross-format table; WSCS appears automatically
in all 15 cross-format utilities. Format count 84 -> 85; CLI
flag count 1010 -> 1015.
This commit is contained in:
Kelsi 2026-05-09 23:04:02 -07:00
parent a7057393eb
commit b10bc2be5d
10 changed files with 689 additions and 0 deletions

View file

@ -1937,6 +1937,16 @@ void printUsage(const char* argv0) {
std::printf(" Export binary .wiqr to a human-editable JSON sidecar (defaults to <base>.wiqr.json). Colors as RGBA uint32, easy to paste hex values\n");
std::printf(" --import-wiqr-json <json-path> [out-base]\n");
std::printf(" Import a .wiqr.json sidecar back into binary .wiqr (canBeDisenchanted accepts bool OR int)\n");
std::printf(" --gen-scs <wscs-base> [name]\n");
std::printf(" Emit .wscs 6 canonical profession tiers (Apprentice/Journeyman/Expert/Artisan/Master/GrandMaster) with standard skill ranges and gold costs\n");
std::printf(" --gen-scs-weapon <wscs-base> [name]\n");
std::printf(" Emit .wscs 5 weapon skill tiers (Beginner/Trained/Skilled/Expert/Master) — free to train, level-gated, capped at 5x char level\n");
std::printf(" --gen-scs-riding <wscs-base> [name]\n");
std::printf(" Emit .wscs 5 riding skill tiers (Apprentice 60%% / Journeyman 100%% / Expert 150%% / Artisan 280%% / Cold Weather Flying) with canonical Vanilla/TBC/WotLK gold costs\n");
std::printf(" --info-wscs <wscs-base> [--json]\n");
std::printf(" Print WSCS entries (id / rank / kind / minSkill / maxSkill / required level / gold cost / name)\n");
std::printf(" --validate-wscs <wscs-base> [--json]\n");
std::printf(" Static checks: id+name required, costKind 0..4, no duplicate ids, min<max; warns on lvl>80, RidingSkill below lvl 20, Profession with cost=0\n");
std::printf(" --gen-weather-temperate <wow-base> [zoneName]\n");
std::printf(" Emit .wow weather schedule: clear-dominant + occasional rain + fog (forest / grassland)\n");
std::printf(" --gen-weather-arctic <wow-base> [zoneName]\n");