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

@ -131,8 +131,9 @@ public sealed class ElementInfo
public string DefaultStateName = "";
/// <summary>
/// Resolved child elements (populated by the importer in Task 5).
/// Children come from the derived element's own tree, not the base element's.
/// Resolved child elements. The importer ports retail child-table incorporation:
/// base-only children remain, same-ID children merge recursively, and derived-only
/// children append after the retained inherited entries.
/// </summary>
public List<ElementInfo> Children = new();
@ -264,7 +265,9 @@ public static class ElementReader
/// base entries are the default; derived entries override (or add) per state name key.
/// </description></item>
/// <item><description>
/// <see cref="ElementInfo.Children"/>: come from the derived element's own tree only.
/// <see cref="ElementInfo.Children"/>: are not combined by this scalar merge helper;
/// <see cref="LayoutImporter"/> separately ports retail's recursive child-table
/// incorporation.
/// </description></item>
/// </list>
/// </para>
@ -306,10 +309,9 @@ public static class ElementReader
FontColor = derived.FontColor ?? base_.FontColor,
// DefaultStateName: derived wins if set; otherwise inherit the base's default.
DefaultStateName = !string.IsNullOrEmpty(derived.DefaultStateName) ? derived.DefaultStateName : base_.DefaultStateName,
// Children come from the derived element's own tree, not the base prototype's.
// Defensive copy: prevent a later mutation of either the merged result or the input
// from corrupting the other. Safe because derived.Children is fully
// populated by the recursive importer BEFORE Merge is called and never mutated after).
// This helper merges one element snapshot only. LayoutImporter separately
// incorporates the child tables after the scalar/state merge.
// Defensive copy prevents later mutation of either input.
Children = new List<ElementInfo>(derived.Children),
};
// Start with base StateMedia as defaults, then let derived entries override.