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

@ -11,12 +11,12 @@ public sealed class CombatUiControllerTests
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
[Fact]
public void CombatMode_ShowsOnlyTargetedModes_AndSelectsMediumByDefault()
public void CombatMode_ShowsPhysicalAndMagicPages_AndSelectsMediumByDefault()
{
double now = 0d;
var combat = new CombatState();
using var attacks = CreateAttacks(combat, () => now, []);
var (layout, _, _, power, high, medium, low) = BuildLayout();
var (layout, basic, spellcasting, power, high, medium, low) = BuildLayout();
var visibility = new List<bool>();
GameplaySettings gameplay = GameplaySettings.Default;
using var controller = CombatUiController.Bind(
@ -27,7 +27,9 @@ public sealed class CombatUiControllerTests
combat.SetCombatMode(CombatMode.Melee);
combat.SetCombatMode(CombatMode.Magic);
Assert.Equal([false, true, false], visibility);
Assert.Equal([false, true, true], visibility);
Assert.False(basic.Visible);
Assert.True(spellcasting.Visible);
Assert.False(high.Selected);
Assert.True(medium.Selected);
Assert.False(low.Selected);