feat: port retail magic lifecycle and retained spell UI

Complete the retail cast-intent, target, component, enchantment, and busy-state paths; mount the DAT-authored spell bar, spellbook, component book, effects panels, and shared panel lifecycle; and add scoped input plus conformance coverage.

Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
Erik 2026-07-15 10:55:22 +02:00
parent 7b7ffcd278
commit 07be994d97
84 changed files with 17822 additions and 1051 deletions

View file

@ -22,6 +22,7 @@ public sealed class RetailLayoutFixtureGenerator
(0x21000024u, "paperdoll_21000024.json"),
(0x2100002Eu, "character_2100002E.json"),
(0x2100006Cu, "vitals_2100006C.json"),
(EffectsIndicatorController.LayoutId, "indicators_21000071.json"),
(0x21000072u, "powerbar_21000072.json"),
(0x21000073u, "combat_21000073.json"),
(0x21000074u, "radar_21000074.json"),
@ -73,7 +74,7 @@ public sealed class RetailLayoutFixtureGenerator
Assert.Equal(0x4000001Au, fps!.FontDid);
var fpsStrings = new DatStringResolver(dats);
Assert.Equal("FPS: ", fpsStrings.Resolve(0x23000001u, 0x0DCFFF73u, 0));
Assert.Equal("\nDEG: ", fpsStrings.Resolve(0x23000001u, 0x0DCFFF73u, 1));
Assert.Equal(@"\nDEG: ", fpsStrings.Resolve(0x23000001u, 0x0DCFFF73u, 1));
var fpsJson = JsonSerializer.Serialize(fps, new JsonSerializerOptions
{
IncludeFields = true,
@ -83,6 +84,23 @@ public sealed class RetailLayoutFixtureGenerator
Path.Combine(FixtureDirectory(), $"smartbox_fps_{smartboxLayoutDid:X8}.json"),
fpsJson);
foreach ((uint rootId, string fileName) in new[]
{
(EffectsUiController.PositiveRootId, "effects_positive_2100001B.json"),
(EffectsUiController.NegativeRootId, "effects_negative_2100001B.json"),
})
{
ElementInfo? effects = LayoutImporter.ImportInfos(
dats, EffectsUiController.LayoutId, rootId);
Assert.NotNull(effects);
var effectsJson = JsonSerializer.Serialize(effects, new JsonSerializerOptions
{
IncludeFields = true,
WriteIndented = true,
});
File.WriteAllText(Path.Combine(FixtureDirectory(), fileName), effectsJson);
}
foreach (var (layoutId, fileName) in Layouts)
{
var info = LayoutImporter.ImportInfos(dats, layoutId);