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>
102 lines
4 KiB
C#
102 lines
4 KiB
C#
using AcDream.App.UI;
|
|
using AcDream.App.UI.Layout;
|
|
using AcDream.Core.Spells;
|
|
|
|
namespace AcDream.App.Tests.UI.Layout;
|
|
|
|
public sealed class EffectsIndicatorControllerTests
|
|
{
|
|
private static (uint, int, int) NoTex(uint _) => (0u, 0, 0);
|
|
|
|
[Fact]
|
|
public void AuthoredFixture_BuildsRetailIndicatorButtons()
|
|
{
|
|
ElementInfo info = FixtureLoader.LoadIndicatorsInfos();
|
|
Assert.Equal(0x10000610u, info.Id);
|
|
Assert.Equal(150f, info.Width);
|
|
Assert.Equal(30f, info.Height);
|
|
|
|
ImportedLayout layout = LayoutImporter.Build(info, NoTex, datFont: null);
|
|
Assert.IsType<UiButton>(layout.FindElement(EffectsIndicatorController.HelpfulButtonId));
|
|
Assert.IsType<UiButton>(layout.FindElement(EffectsIndicatorController.HarmfulButtonId));
|
|
}
|
|
|
|
[Fact]
|
|
public void Enchantments_GhostAndEnableMatchingIndicator_ThenClickCorrectPanel()
|
|
{
|
|
var table = SpellTable.LoadFromReader(new StringReader(
|
|
"Spell ID,Name,Flags [Hex]\n42,Boon,0x4\n43,Bane,0x0\n"));
|
|
var spellbook = new Spellbook(table);
|
|
ImportedLayout layout = BuildSyntheticLayout();
|
|
var toggled = new List<uint>();
|
|
using EffectsIndicatorController controller = EffectsIndicatorController.Bind(
|
|
layout, spellbook, toggled.Add)!;
|
|
UiButton helpful = Assert.IsType<UiButton>(
|
|
layout.FindElement(EffectsIndicatorController.HelpfulButtonId));
|
|
UiButton harmful = Assert.IsType<UiButton>(
|
|
layout.FindElement(EffectsIndicatorController.HarmfulButtonId));
|
|
|
|
Assert.False(helpful.Enabled);
|
|
Assert.False(harmful.Enabled);
|
|
|
|
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
|
|
42u, 10u, 60f, 1u, Bucket: 4u, SpellCategory: 42u));
|
|
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
|
|
43u, 11u, 60f, 2u, Bucket: 8u, SpellCategory: 43u));
|
|
Assert.False(helpful.Enabled);
|
|
Assert.False(harmful.Enabled);
|
|
|
|
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
|
|
42u, 1u, 60f, 1u, Bucket: 1u, SpellCategory: 99u, PowerLevel: 1u));
|
|
Assert.True(helpful.Enabled);
|
|
Assert.False(harmful.Enabled);
|
|
helpful.OnEvent(new UiEvent(0, helpful, UiEventType.Click));
|
|
Assert.Equal([RetailPanelCatalog.PositiveEffects], toggled);
|
|
|
|
spellbook.OnEnchantmentAdded(new ActiveEnchantmentRecord(
|
|
43u, 1u, 60f, 2u, Bucket: 2u, SpellCategory: 99u, PowerLevel: 7u));
|
|
// The harmful spell wins the shared category in the effects list, but
|
|
// retail's raw registry counters keep both indicator types enabled.
|
|
Assert.True(helpful.Enabled);
|
|
Assert.True(harmful.Enabled);
|
|
harmful.OnEvent(new UiEvent(0, harmful, UiEventType.Click));
|
|
Assert.Equal(
|
|
[RetailPanelCatalog.PositiveEffects, RetailPanelCatalog.NegativeEffects],
|
|
toggled);
|
|
|
|
spellbook.OnEnchantmentRemoved(1u, 42u);
|
|
Assert.False(helpful.Enabled);
|
|
Assert.True(harmful.Enabled);
|
|
}
|
|
|
|
private static ImportedLayout BuildSyntheticLayout()
|
|
{
|
|
var root = new ElementInfo { Id = 1u, Type = 3u, Width = 150f, Height = 30f };
|
|
var helpful = ButtonInfo(EffectsIndicatorController.HelpfulButtonId);
|
|
var harmful = ButtonInfo(EffectsIndicatorController.HarmfulButtonId);
|
|
return LayoutImporter.BuildFromInfos(root, [helpful, harmful], NoTex, null);
|
|
}
|
|
|
|
private static ElementInfo ButtonInfo(uint id)
|
|
{
|
|
var info = new ElementInfo
|
|
{
|
|
Id = id,
|
|
Type = EffectsIndicatorController.RetailClassId,
|
|
Width = 20f,
|
|
Height = 20f,
|
|
DefaultStateId = UiButtonStateMachine.Normal,
|
|
};
|
|
info.States[UiButtonStateMachine.Normal] = new UiStateInfo
|
|
{
|
|
Id = UiButtonStateMachine.Normal,
|
|
Name = "Normal",
|
|
};
|
|
info.States[UiButtonStateMachine.Ghosted] = new UiStateInfo
|
|
{
|
|
Id = UiButtonStateMachine.Ghosted,
|
|
Name = "Ghosted",
|
|
};
|
|
return info;
|
|
}
|
|
}
|