fix: expansion-aware SpellRange.dbc loading and Classic spell tooltip fields

SpellRange.dbc layout fix:
- Classic 1.12 uses field 2 (MaxRange), TBC/WotLK use field 4 (MaxRangeHostile)
- Add SpellRange layout to each expansion's dbc_layouts.json
- Replace hardcoded field 5 with layout-driven lookup in SpellRange loading
- Corrects previously wrong range values in WotLK spellbook tooltips

Classic 1.12 Spell.dbc field additions:
- Add CastingTimeIndex=15, PowerType=28, ManaCost=29, RangeIndex=33 to
  classic/dbc_layouts.json so Classic spellbook shows mana cost, cast time,
  and range in tooltips

Trainer fieldCount guard:
- Lower Trainer::loadSpellNameCache() Spell.dbc fieldCount threshold from
  154 to 148 so Classic trainers correctly resolve spell names from Spell.dbc
This commit is contained in:
Kelsi 2026-03-10 18:09:21 -07:00
parent 2f3f9f1a21
commit 53d144c51e
5 changed files with 23 additions and 6 deletions

View file

@ -66,15 +66,26 @@ void SpellbookScreen::loadSpellDBC(pipeline::AssetManager* assetManager) {
}
}
// Load SpellRange.dbc: field 0=ID, field 5=MaxRangeHostile (float)
// Load SpellRange.dbc. Field layout differs by expansion:
// Classic 1.12: 0=ID, 1=MinRange, 2=MaxRange, 3=Flags, 4+=strings
// TBC / WotLK: 0=ID, 1=MinRangeFriendly, 2=MinRangeHostile,
// 3=MaxRangeFriendly, 4=MaxRangeHostile, 5=Flags, 6+=strings
// The correct field is declared in each expansion's dbc_layouts.json.
uint32_t spellRangeMaxField = 4; // WotLK / TBC default: MaxRangeHostile
const auto* spellRangeL = pipeline::getActiveDBCLayout()
? pipeline::getActiveDBCLayout()->getLayout("SpellRange")
: nullptr;
if (spellRangeL) {
try { spellRangeMaxField = (*spellRangeL)["MaxRange"]; } catch (...) {}
}
std::unordered_map<uint32_t, float> rangeMap; // index → max yards
auto rangeDbc = assetManager->loadDBC("SpellRange.dbc");
if (rangeDbc && rangeDbc->isLoaded()) {
uint32_t rangeFieldCount = rangeDbc->getFieldCount();
if (rangeFieldCount >= 6) {
if (rangeFieldCount > spellRangeMaxField) {
for (uint32_t i = 0; i < rangeDbc->getRecordCount(); ++i) {
uint32_t id = rangeDbc->getUInt32(i, 0);
float maxRange = rangeDbc->getFloat(i, 5);
float maxRange = rangeDbc->getFloat(i, spellRangeMaxField);
if (id > 0 && maxRange > 0.0f)
rangeMap[id] = maxRange;
}