fix(spells): load complete retail DAT catalog

Replace the incomplete 3,956-row production CSV with one immutable projection of all 6,266 records in portal.dat. Preserve retail formula targeting, shared Spellbook/MagicRuntime metadata ownership, and fail startup when the required SpellTable is absent.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-15 21:17:13 +02:00
parent 09612f9981
commit 0eab7497c1
19 changed files with 633 additions and 114 deletions

View file

@ -44,6 +44,37 @@ public static class RetailSpellFormula
};
}
/// <summary>
/// Retail <c>SpellFormula::GetTargetingType @ 0x005BC910</c> followed by
/// <c>SpellComponentTable::GetTargetTypeFromComponentID @ 0x005BBF50</c>.
/// The native <c>SpellFormula</c> has a vtable before its eight components.
/// Retail starts at native offset index 5 (component slot 4), scans slots
/// 5 through 7 for the end of the formula, then maps the final populated
/// component. This deliberately does not search for the first recognized
/// target component.
/// </summary>
public static uint GetTargetingType(IReadOnlyList<uint> components)
{
ArgumentNullException.ThrowIfNull(components);
if (components.Count <= 4)
return 0u;
int last = 4;
while (last < 7 && last + 1 < components.Count && components[last + 1] != 0u)
last++;
return GetTargetTypeFromComponentId(components[last]);
}
/// <summary>Retail target-component ID to ItemType mask mapping.</summary>
public static uint GetTargetTypeFromComponentId(uint componentId) => componentId switch
{
0x31u or 0x32u or 0x33u or 0x34u or 0x35u or 0x36u
or 0x37u or 0x38u or 0x3Cu or 0x3Du or 0x3Eu or 0xBEu => 0x10u,
0x39u => 0x00088B8Fu,
0x3Bu => 0x10010000u,
_ => 0u,
};
/// <summary>
/// Retail <c>CSpellBase::InqScarabOnlyFormula</c> (0x00597050).
/// Foci and the infused-magic augmentations replace the ordinary taper