build-binaries / build-binaries (push) Successful in 2m26s
Closes #94. Generates the racial radial rows at build time from the `UsableFeat` column in the race feats tables, replacing the hand-maintained racial block in `sow-topdata` `data/classes/feats/global.json`. ## Why Racial spell-like abilities reach the in-game radial only via an `OnMenu` row in every `cls_feat_<class>.2da`. Racial feats are granted by race, never by a class, so nothing adds them automatically — they were hand-written and prepended into every class table. The list drifts: this build already had **24** usable racial feats in the race tables but only **23** hand rows, so one activatable feat was silently missing. ## What - `racialUsableFeatRules()` scans `race_feat_*.2da` datasets, collects `UsableFeat=1` feats, emits one rule each: `List=3, GrantedOnLevel=99, OnMenu=1`. Deduped across races, sorted for deterministic output. - Row shape is exactly the in-game-verified hand rows. `List=3` keeps it off every level-up selection list; `GrantedOnLevel=99` is above the level cap so no class ever actually grants it (`nLevelGranted` is `uint8_t`); `OnMenu=1` renders the button once the creature possesses the feat. Possession stays chargen / the login racial-feat sync (`sow-codebase#359`). - Reuses the existing `globalRules` injection path (same dedup, feat-existence check, label lookup) but applies **unconditionally**, so a leftover hand row in `global.json` deduplicates to a no-op — the `sow-topdata` cleanup lands separately. - Not sourced from `feat.2da`: a global feat flag would inject unrelated class abilities (e.g. a shadowdancer ability) into every class radial via multiclass. ## Tests - `racial_feat_rules_test.go`: usable-only, non-usable excluded, cross-race dedup, non-`race_feat_` ignored, deterministic order. - Existing `cls_feat` global-injection build tests still pass with the new parameter. - End-to-end: with the racial block removed from `global.json`, a real `build-topdata` emits `TieflingDarkness 3 99 1` once per table across all 21, 24 racial rows total. ## Merge order The `sow-topdata` `global.json` racial-row deletion depends on this — it must ship first (or the racial radial vanishes on the next topdata build with the released tool). 🤖 Generated with [Claude Code](https://claude.com/claude-code)Reviewed-on: #95 Co-authored-by: vickydotbat <vickydotbat@tutamail.com>