LoadAllPromotions builds one PromotionClass per promotion CLASS rune (22,
2504-2526 without 2522) and caches it, then runs the DB loader, which skips
cached ids, so only the CSR/admin rows 2901-2911 still come from
static_rune_promotion (decision: DB fallback). The world server calls it in
place of GET_ALL_PROMOTIONS; the login server now preloads promotions too, so
character load there gets the same cached objects. The SQL loader stays until
task 2.11.
Value changes: Templar 2516 manaMod 14 -> 15 (decision: JSON, D2).
description NULL -> rune_dsc blurb (unread). All other fields unchanged;
final parity before the switch (scripts/p22.py): 22 promotion rows, 0
differences in name, token, health, stamina and the 163 allowed rune tokens.
The static_rune_promotion comparator is removed; it would only compare the
JSON with itself now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>