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
|
|
@ -803,12 +803,9 @@ public sealed class GameWindow : IDisposable
|
|||
public readonly AcDream.Core.Social.SquelchState Squelch = new();
|
||||
public IReadOnlyList<(uint Id, uint Amount)> DesiredComponents { get; private set; }
|
||||
= System.Array.Empty<(uint Id, uint Amount)>();
|
||||
// Issue #11 — load static spell metadata from data/spells.csv at startup.
|
||||
// Provides Family for buff stacking (issue #6) + names + icons + tooltips
|
||||
// for the future Spellbook panel. The CSV is copied to bin/<config>/net10.0/data/
|
||||
// by the csproj <None Include="...spells.csv"> entry. Loads silently to
|
||||
// SpellTable.Empty if the file is missing (e.g. tooling contexts).
|
||||
public readonly AcDream.Core.Spells.SpellTable SpellTable = LoadSpellTable();
|
||||
// Retail resolves learned IDs through portal.dat's CSpellTable. MagicCatalog
|
||||
// installs that immutable table once DatCollection opens in OnLoad.
|
||||
public AcDream.Core.Spells.SpellTable SpellTable => SpellBook.Metadata;
|
||||
public readonly AcDream.Core.Spells.Spellbook SpellBook = null!;
|
||||
public readonly AcDream.Core.Items.ClientObjectTable Objects = new();
|
||||
/// <summary>Persisted hotbar shortcuts from the last PlayerDescription (D.5.1 toolbar source).</summary>
|
||||
|
|
@ -838,6 +835,7 @@ public sealed class GameWindow : IDisposable
|
|||
private AcDream.App.Combat.CombatTargetController? _combatTargetController;
|
||||
private AcDream.App.UI.ItemInteractionController? _itemInteractionController;
|
||||
private AcDream.App.Spells.MagicRuntime? _magicRuntime;
|
||||
private AcDream.App.Spells.MagicCatalog? _magicCatalog;
|
||||
private readonly AcDream.Core.Items.StackSplitQuantityState _stackSplitQuantity = new();
|
||||
// Phase D.2b Sub-phase C Slice 2 — the 3-D doll viewport: an off-screen RTT renderer, the UiViewport
|
||||
// widget that blits it, the inventory frame (for the open-gate), and a dirty flag (re-dress on 0xF625).
|
||||
|
|
@ -1175,7 +1173,7 @@ public sealed class GameWindow : IDisposable
|
|||
_uiRegistry = uiRegistry;
|
||||
_animatedEntities = new LiveEntityAnimationRuntimeView<AnimatedEntity>(() => _liveEntities);
|
||||
_remoteDeadReckon = new LiveEntityRemoteMotionRuntimeView<RemoteMotion>(() => _liveEntities);
|
||||
SpellBook = new AcDream.Core.Spells.Spellbook(SpellTable);
|
||||
SpellBook = new AcDream.Core.Spells.Spellbook();
|
||||
LocalPlayer = new AcDream.Core.Player.LocalPlayerState(SpellBook);
|
||||
// #184 Slice 2a: the extracted per-remote DR tick. Shares GameWindow's
|
||||
// PhysicsEngine; the two helpers it also needs but that have callers
|
||||
|
|
@ -1186,33 +1184,6 @@ public sealed class GameWindow : IDisposable
|
|||
_physicsEngine, GetSetupCylinder, ApplyServerControlledVelocityCycle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issue #11 — load <c>data/spells.csv</c> from the bin output (copied
|
||||
/// there by the csproj). Returns <c>SpellTable.Empty</c> + logs a
|
||||
/// warning if the file is missing (e.g. when GameWindow is instantiated
|
||||
/// from tooling contexts that don't include the data folder).
|
||||
/// </summary>
|
||||
private static AcDream.Core.Spells.SpellTable LoadSpellTable()
|
||||
{
|
||||
string path = System.IO.Path.Combine(
|
||||
System.AppContext.BaseDirectory, "data", "spells.csv");
|
||||
try
|
||||
{
|
||||
if (System.IO.File.Exists(path))
|
||||
{
|
||||
var t = AcDream.Core.Spells.SpellTable.LoadFromCsv(path);
|
||||
Console.WriteLine($"spells: loaded {t.Count} entries from spells.csv");
|
||||
return t;
|
||||
}
|
||||
Console.WriteLine($"spells: data/spells.csv not found at {path}; using empty table");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"spells: load failed ({ex.Message}); using empty table");
|
||||
}
|
||||
return AcDream.Core.Spells.SpellTable.Empty;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
// A.5 T22.5: resolve quality preset BEFORE creating the window so
|
||||
|
|
@ -1506,6 +1477,9 @@ public sealed class GameWindow : IDisposable
|
|||
_cameraController.ModeChanged += OnCameraModeChanged;
|
||||
|
||||
_dats = new DatCollection(_datDir, DatAccessType.Read);
|
||||
_magicCatalog = AcDream.App.Spells.MagicCatalog.Load(_dats);
|
||||
SpellBook.InstallMetadata(_magicCatalog.SpellTable);
|
||||
Console.WriteLine($"spells: loaded {SpellTable.Count} entries from portal.dat");
|
||||
_animLoader = new AcDream.Content.Vfx.RetailAnimationLoader(_dats);
|
||||
_emitterRegistry = new AcDream.Core.Vfx.EmitterDescRegistry(_dats);
|
||||
|
||||
|
|
@ -2092,8 +2066,7 @@ public sealed class GameWindow : IDisposable
|
|||
_vitalsVm ??= new AcDream.UI.Abstractions.Panels.Vitals.VitalsVM(Combat, LocalPlayer);
|
||||
_uiHost = new AcDream.App.UI.UiHost(_gl, shadersDir, _debugFont);
|
||||
_uiHost.Root.UiLocked = _persistedGameplay.LockUI;
|
||||
AcDream.App.Spells.MagicCatalog magicCatalog =
|
||||
AcDream.App.Spells.MagicCatalog.Load(_dats!);
|
||||
AcDream.App.Spells.MagicCatalog magicCatalog = _magicCatalog!;
|
||||
_itemInteractionController = new AcDream.App.UI.ItemInteractionController(
|
||||
Objects,
|
||||
playerGuid: () => _playerServerGuid,
|
||||
|
|
@ -14648,6 +14621,7 @@ public sealed class GameWindow : IDisposable
|
|||
_itemInteractionController?.Dispose();
|
||||
_itemInteractionController = null;
|
||||
_magicRuntime = null;
|
||||
_magicCatalog = null;
|
||||
|
||||
// Phase A.1: join the streamer worker thread before tearing down GL
|
||||
// state. The worker may still be processing a load job that references
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue