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:
parent
09612f9981
commit
0eab7497c1
19 changed files with 633 additions and 114 deletions
|
|
@ -6,10 +6,9 @@ using System.IO;
|
|||
namespace AcDream.Core.Spells;
|
||||
|
||||
/// <summary>
|
||||
/// Loads + queries <see cref="SpellMetadata"/> from a CSV at startup.
|
||||
/// Source: <c>docs/research/data/spells.csv</c> (RFC 4180-ish, 35
|
||||
/// columns, 3,956 rows). Loaded once, used by panels + by
|
||||
/// <c>EnchantmentMath</c> for buff stacking aggregation.
|
||||
/// Immutable lookup of retail spell metadata. Production builds create this
|
||||
/// table from portal.dat through the App-layer <c>MagicCatalog</c>. The CSV
|
||||
/// parser below remains for historical tooling and small synthetic tests.
|
||||
///
|
||||
/// <para>
|
||||
/// Hand-rolled CSV parser — the only complication is the
|
||||
|
|
@ -35,6 +34,21 @@ public sealed class SpellTable
|
|||
_byId = byId;
|
||||
}
|
||||
|
||||
/// <summary>Create a canonical immutable lookup from projected metadata.</summary>
|
||||
public static SpellTable Create(IEnumerable<SpellMetadata> metadata)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(metadata);
|
||||
var byId = new Dictionary<uint, SpellMetadata>();
|
||||
foreach (SpellMetadata spell in metadata)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(spell);
|
||||
if (!byId.TryAdd(spell.SpellId, spell))
|
||||
throw new ArgumentException(
|
||||
$"Duplicate spell id 0x{spell.SpellId:X8}.", nameof(metadata));
|
||||
}
|
||||
return new SpellTable(byId);
|
||||
}
|
||||
|
||||
/// <summary>Number of spells loaded.</summary>
|
||||
public int Count => _byId.Count;
|
||||
|
||||
|
|
@ -154,7 +168,10 @@ public sealed class SpellTable
|
|||
spellId, name, school, family, iconId, words, duration,
|
||||
mana, isDebuff, isFellow, description, sortKey, difficulty,
|
||||
flags, generation, fastWindup, offensive, untargeted, speed,
|
||||
casterEffect, targetEffect, targetMask, spellType);
|
||||
casterEffect, targetEffect, targetMask, spellType)
|
||||
{
|
||||
SchoolId = ParseSchool(school),
|
||||
};
|
||||
}
|
||||
|
||||
return new SpellTable(byId);
|
||||
|
|
@ -187,6 +204,16 @@ public sealed class SpellTable
|
|||
return string.Equals(fields[i], "True", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static MagicSchool ParseSchool(string school) => school switch
|
||||
{
|
||||
"War Magic" => MagicSchool.WarMagic,
|
||||
"Life Magic" => MagicSchool.LifeMagic,
|
||||
"Item Enchantment" => MagicSchool.ItemEnchantment,
|
||||
"Creature Enchantment" => MagicSchool.CreatureEnchantment,
|
||||
"Void Magic" => MagicSchool.VoidMagic,
|
||||
_ => MagicSchool.None,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Hand-rolled RFC 4180-ish CSV row parser. Handles double-quoted
|
||||
/// fields with embedded commas (the Description column). Embedded
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue