feat(ui): port retail creature appraisal presentation
Render assessed creatures through the shared private viewport with retail heading, bounding-box camera, and light. Build the exact authored nine-row stat list and resolve creature names from the retail EnumMapper while keeping remaining font/sequencer adaptations explicit. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
f1a7912160
commit
7eaa68a5f4
26 changed files with 2780 additions and 237 deletions
|
|
@ -10,6 +10,7 @@ namespace AcDream.App.Tests.UI.Layout;
|
|||
public sealed class AppraisalUiControllerTests
|
||||
{
|
||||
private const uint ObjectId = 0x50000001u;
|
||||
private static (uint, int, int) NoTexture(uint _) => (0u, 0, 0);
|
||||
|
||||
[Fact]
|
||||
public void ItemResponse_UsesAuthoredItemSubviewTitleAndScrollbars()
|
||||
|
|
@ -146,6 +147,114 @@ public sealed class AppraisalUiControllerTests
|
|||
Assert.Equal(1, shown);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreatureResponse_UsesRetailHeaderAndNineOrderedTemplateRows()
|
||||
{
|
||||
ImportedLayout layout = FixtureLoader.LoadExamination();
|
||||
var objects = new ClientObjectTable();
|
||||
objects.AddOrUpdate(new ClientObject
|
||||
{
|
||||
ObjectId = ObjectId,
|
||||
Name = "Specter",
|
||||
Type = ItemType.Creature,
|
||||
});
|
||||
using var interaction = NewInteraction(objects, []);
|
||||
UiText characterLabel = Assert.IsType<UiText>(
|
||||
layout.FindElement(0x1000014Au));
|
||||
UiText levelLabel = Assert.IsType<UiText>(
|
||||
layout.FindElement(0x1000014Bu));
|
||||
characterLabel.LinesProvider = () =>
|
||||
[new UiText.Line("Character", characterLabel.DefaultColor)];
|
||||
levelLabel.LinesProvider = () =>
|
||||
[new UiText.Line("Level", levelLabel.DefaultColor)];
|
||||
var templates = new CreatureAppraisalRowTemplateFactory(
|
||||
FixtureLoader.LoadExaminationRowTemplateInfos(),
|
||||
NoTexture,
|
||||
defaultFont: null);
|
||||
using AppraisalUiController controller = Bind(
|
||||
layout,
|
||||
objects,
|
||||
interaction,
|
||||
new CombatState(),
|
||||
[],
|
||||
[],
|
||||
() => { },
|
||||
() => { },
|
||||
templates,
|
||||
new CreatureDisplayNameResolver(
|
||||
new Dictionary<uint, string> { [77u] = "Ghost" }))!;
|
||||
|
||||
interaction.ExamineSelectedOrEnterMode(ObjectId);
|
||||
var properties = new PropertyBundle();
|
||||
properties.Ints[2u] = 77;
|
||||
properties.Ints[25u] = 80;
|
||||
var profile = new AppraiseInfoParser.CreatureProfile(
|
||||
Flags: 0x08u,
|
||||
Health: 295u,
|
||||
HealthMax: 295u,
|
||||
Strength: 120u,
|
||||
Endurance: 190u,
|
||||
Quickness: 190u,
|
||||
Coordination: 190u,
|
||||
Focus: 330u,
|
||||
Self: 350u,
|
||||
Stamina: 190u,
|
||||
Mana: 550u,
|
||||
StaminaMax: 190u,
|
||||
ManaMax: 550u,
|
||||
AttributeHighlights: (ushort)0,
|
||||
AttributeColors: (ushort)0);
|
||||
|
||||
Assert.True(controller.Apply(Parsed(properties, profile)));
|
||||
|
||||
Assert.Equal(
|
||||
"Character",
|
||||
Assert.Single(characterLabel.LinesProvider()).Text);
|
||||
Assert.Equal("Level", Assert.Single(levelLabel.LinesProvider()).Text);
|
||||
Assert.Equal(
|
||||
"80",
|
||||
Assert.Single(((UiText)layout.FindElement(
|
||||
AppraisalUiController.CreatureLevelValueId)!)
|
||||
.LinesProvider()).Text);
|
||||
Assert.Equal(
|
||||
"Ghost",
|
||||
Assert.Single(((UiText)layout.FindElement(
|
||||
AppraisalUiController.CreatureDisplayNameId)!)
|
||||
.LinesProvider()).Text);
|
||||
|
||||
UiElement host = layout.FindElement(
|
||||
AppraisalUiController.CreatureStatsListId)!;
|
||||
UiItemList list = Assert.Single(host.Children.OfType<UiItemList>());
|
||||
Assert.Equal(9, list.GetNumUIItems());
|
||||
string[] labels = new string[9];
|
||||
string[] values = new string[9];
|
||||
for (int index = 0; index < 9; index++)
|
||||
{
|
||||
UiTemplateListSlot row =
|
||||
Assert.IsType<UiTemplateListSlot>(list.GetItem(index));
|
||||
labels[index] = Assert.Single(
|
||||
((UiText)row.Content.FindElement(
|
||||
CreatureAppraisalRowTemplateFactory.LabelId)!)
|
||||
.LinesProvider()).Text;
|
||||
values[index] = Assert.Single(
|
||||
((UiText)row.Content.FindElement(
|
||||
CreatureAppraisalRowTemplateFactory.ValueId)!)
|
||||
.LinesProvider()).Text;
|
||||
}
|
||||
Assert.Equal(
|
||||
[
|
||||
"Strength", "Endurance", "Coordination", "Quickness",
|
||||
"Focus", "Self", "Health", "Stamina", "Mana",
|
||||
],
|
||||
labels);
|
||||
Assert.Equal(
|
||||
[
|
||||
"120", "190", "190", "190", "330", "350",
|
||||
"295/295 (100 %)", "190/190", "550/550",
|
||||
],
|
||||
values);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResponseForNeitherPendingNorCurrent_IsIgnored()
|
||||
{
|
||||
|
|
@ -429,7 +538,9 @@ public sealed class AppraisalUiControllerTests
|
|||
List<(uint ObjectId, string Text)> inscriptions,
|
||||
List<string> messages,
|
||||
Action show,
|
||||
Action close)
|
||||
Action close,
|
||||
CreatureAppraisalRowTemplateFactory? creatureRows = null,
|
||||
CreatureDisplayNameResolver? creatureNames = null)
|
||||
=> AppraisalUiController.Bind(
|
||||
layout,
|
||||
objects,
|
||||
|
|
@ -440,7 +551,9 @@ public sealed class AppraisalUiControllerTests
|
|||
(objectId, text) => inscriptions.Add((objectId, text)),
|
||||
messages.Add,
|
||||
show,
|
||||
close);
|
||||
close,
|
||||
creatureRows,
|
||||
creatureNames);
|
||||
|
||||
private static ItemInteractionController NewInteraction(
|
||||
ClientObjectTable objects,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue