feat(spells): #11 SpellTable - hydrate metadata from spells.csv at startup
New SpellMetadata + SpellTable. Loads docs/research/data/spells.csv at GameWindow construction (3,956 spells x 11 useful fields including Family for buff stacking which issue #6 needs). The CSV is copied to bin/<config>/net10.0/data/spells.csv via the csproj <None Include> entry; SpellTable.LoadFromCsv resolves relative to AppContext.BaseDirectory. Hand-rolled CSV parser handles RFC 4180 quoted fields with embedded commas (the Description column) + escaped double-quotes ("" -> "). No external CsvHelper dep. Falls back to SpellTable.Empty + console warning if the file is missing (tooling contexts). Spellbook now accepts an optional SpellTable in its constructor + exposes TryGetMetadata(spellId, out SpellMetadata). When the table is absent (legacy `new Spellbook()` calls), TryGetMetadata returns false gracefully so existing tests keep passing. GameWindow: - SpellTable field initialized via LoadSpellTable() helper that handles the missing-file case + emits the spells: loaded N entries log line. - SpellBook field constructor-initialized with the loaded SpellTable so TryGetMetadata works for the live session. 10 new tests (SpellTableTests): - Empty table behavior - Header-only loads to empty - Single row populates all metadata - Quoted Description with embedded commas - Blank lines skipped - Bad-spell-id rows silently skipped (third-party data is messy) - Unknown spell-id lookup returns false - ParseRow primitive: simple comma split, quoted-field with comma, escaped double-quote. Total tests: 818 -> 828. Closes #11. Phase G (issue #6 — fold enchantment buffs into vital max via EnchantmentMath using SpellTable.Family for stacking) unblocked. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
83b020499b
commit
4ceac5cb40
7 changed files with 463 additions and 23 deletions
|
|
@ -19,6 +19,32 @@ public sealed class Spellbook
|
|||
{
|
||||
private readonly HashSet<uint> _learnedSpells = new();
|
||||
private readonly ConcurrentDictionary<uint, ActiveEnchantmentRecord> _activeByLayer = new();
|
||||
private readonly SpellTable _table;
|
||||
|
||||
/// <summary>
|
||||
/// Build a Spellbook with an optional <see cref="SpellTable"/>
|
||||
/// metadata source. When provided, <see cref="TryGetMetadata"/>
|
||||
/// returns the static spell descriptor (name / school / family /
|
||||
/// icon / mana / duration / etc.). When absent (back-compat for
|
||||
/// existing constructors / tests), <see cref="TryGetMetadata"/>
|
||||
/// always returns <c>false</c>.
|
||||
/// </summary>
|
||||
public Spellbook(SpellTable? table = null)
|
||||
{
|
||||
_table = table ?? SpellTable.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look up static spell metadata. Closes ISSUES.md #11 — feeds the
|
||||
/// buff bar UI labels + icons + the family-stacking aggregation in
|
||||
/// <c>EnchantmentMath</c> (issue #6).
|
||||
/// </summary>
|
||||
public bool TryGetMetadata(uint spellId, out SpellMetadata meta) =>
|
||||
_table.TryGet(spellId, out meta);
|
||||
|
||||
/// <summary>The spell-metadata table this spellbook was built with.
|
||||
/// Returns <see cref="SpellTable.Empty"/> if none was provided.</summary>
|
||||
public SpellTable Metadata => _table;
|
||||
|
||||
/// <summary>Fires when a spell is added to the player's spellbook.</summary>
|
||||
public event Action<uint>? SpellLearned;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue