fix(ui): preserve retail item titles and spacing
Carry PublicWeenieDesc material type into the live object model so examination titles use the DAT-authored material prefix. Preserve retail AddItemInfo empty appends and embedded armor separator, restoring the deliberate blank rows between appraisal sections. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
d78d09cfbc
commit
6718ee45a0
19 changed files with 341 additions and 46 deletions
|
|
@ -132,6 +132,16 @@ AP-110 retains only item preview, live player/localization projections,
|
|||
character detail, and creature FontInfo state; the connected item visual is
|
||||
the remaining acceptance gate.
|
||||
|
||||
The next connected boots comparison exposed two final shared-path omissions.
|
||||
CreateObject walked past `PublicWeenieDesc.MaterialType`, so
|
||||
`ACCWeenieObject::GetObjectName(NAME_APPROPRIATE)` could not decorate the
|
||||
authored base name, and the retained report builder discarded empty strings
|
||||
even though retail `AddItemInfo` still appends their separator. Material type
|
||||
now survives CreateObject -> EntitySpawn -> WeenieData -> ClientObject and the
|
||||
DAT resolver prefixes it exactly once. Empty append fragments now preserve
|
||||
retail's intentional blank section rows, including the blank after
|
||||
Workmanship and the literal leading newline before Armor Level.
|
||||
|
||||
**Files:** `src/AcDream.Core.Net/Messages/AppraiseInfoParser.cs`;
|
||||
`src/AcDream.App/UI/RetailUiRuntime.cs`;
|
||||
`src/AcDream.App/UI/Layout/AppraisalUiController.cs`;
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ AP-94..AP-112 for the confirmed retail-UI completion gaps.
|
|||
| ~~AP-107~~ | **RETIRED 2026-07-11 (Wave 3.3 / #197)** — typed `OfferPrimaryClick` returns `NotActive`, `ConsumedSuccess`, or `ConsumedRejected`; every retained item surface plus radar/world offers active target mode before local selection/open/use fallback. Rejections are consumed and cannot drift selection. | `src/AcDream.App/UI/ItemInteractionController.cs`; inventory/paperdoll/toolbar/radar/world call sites | — | — | `UIElement_ItemList::HandleTargetedUseLeftClick @ 0x004E24D0` |
|
||||
| AP-108 | Paperdoll/AutoWield still omit the remaining missile/held restrictions and corrupt-mask branch of full `AutoWieldIsLegal`, dual-wield/off-hand rules, double-click examine/drag from the doll, body-part selection lighting, and retail's synchronous `" - cannot unwield the %s"` failure suffix (the current send seam reports rejection asynchronously). **AutoWear legality retired from this row 2026-07-23:** inventory activation and paperdoll drops now apply the retail clothing-priority/location blocker lookup and exact `"You must remove your %s to wear that"` system notice. **Primary replacement retired 2026-07-14; Aetheria retired 2026-07-13.** | `src/AcDream.App/UI/Layout/PaperdollController.cs`; `src/AcDream.App/UI/AutoWieldController.cs` | Basic equip slots, Aetheria, live doll, AutoWear conflict reporting, and primary weapon/incompatible shield/mismatched ammo blocker sequencing work in peace and war | Remaining illegal/off-hand cases, asynchronous dequip rejection wording, doll examine/drag, and selection lighting still differ functionally | `CPlayerSystem::AutoWieldIsLegal @ 0x0055ED60`; `CPlayerSystem::AutoWearIsLegal @ 0x0055EF40`; `CPlayerSystem::AutoWield @ 0x00560A60`; `gmPaperDollUI @ 0x004A3590..0x004A5F90` |
|
||||
| AP-109 | Character Titles page is inert and live displayed-title/luminance state is absent | `src/AcDream.App/UI/Layout/CharacterStatController.cs`; `CharacterSheetProvider.cs` | Attributes/skills core output is user-accepted | Titles cannot be selected/displayed and level-200 luminance fields are missing | `gmCharacterTitleUI @ 0x0049A610`; `gmStatManagementUI::UpdateExperience @ 0x004F0A70` |
|
||||
| AP-110 | Remaining retained gameplay panels and world HUD are absent: advanced-combat powerbar, residual social/floating chat, quests/map/options/smartbox, vendor/trade/salvage/tinkering, mini-game gameplay, Link Status NAK/retransmission packet-loss averaging, and D.6 nameplates/floaters. Examination has its independent authored floaty layout, inscription transaction, retail creature stat/rating/animated-preview presentation, default selection-follow, and the full EoR item-report dispatch: appraisal-only unknowns; exact equipment-set/rating/tinkering/weapon/armor/caster/requirement/XP/healer/rare prose; ordinary/enchantment DAT spell descriptions; DAT material and creature names; expiry, decorated material/gem descriptions; and portal/PK restrictions with authored item colors. It still lacks item-object preview, player-dependent effective shield projection, live cooldown-remaining projection, localized augmentation-cost `StringInfo`, exhaustive character detail regions, and exact creature appraisal FontInfo-list selection. | `src/AcDream.App/UI/RetailUiRuntime.cs`; `src/AcDream.App/UI/Layout/AppraisalUiController.cs`; `src/AcDream.App/UI/Layout/ItemAppraisalTextFormatter.cs`; `src/AcDream.App/UI/Layout/RetailAppraisalNameResolver.cs`; `src/AcDream.App/UI/Layout/CreatureAppraisalRows.cs`; `src/AcDream.App/Rendering/CreatureAppraisalPresentation.cs`; `src/AcDream.Core.Net/LinkStatusSnapshot.cs`; D.5/D.6 roadmap | Basic combat, M3 magic/Link/Vitae surfaces, and the core examination request/presentation/inscription/creature-preview/item-report loop cover the active loops; the residual examination mechanisms require live player/enchantment/localization state or object-preview ownership rather than fabricated content | Item assessments omit only the listed live/localized/preview projections; enchanted/incomplete creature appraisal rows use the normal authored font until the exact FontInfo list is bound; other absent panels remain unavailable; real packet loss is displayed as 0.00% instead of retail's moving average | `BasicCreatureExamineUI::Init @ 0x004AB9C0`; `CreatureExamineUI::SetAppraiseInfo @ 0x004B3FF0`; `gmExaminationUI::RecvNotice_SelectionChanged @ 0x004AB3D0`; `AttributeInfoRegion::Update @ 0x004F1D90`; `gmExaminationUI::SetAppraiseInfo @ 0x004ADAE0`; `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`; `ItemExamineUI::AddItemInfo @ 0x004AC050`; `ItemExamineUI::Appraisal_ShowCapacity @ 0x004B2680`; `ItemExamineUI::Appraisal_ShowSpecialProperties @ 0x004B0140`; `ItemExamineUI::Appraisal_ShowWeaponAndArmorData @ 0x004B10E0`; `ItemExamineUI::Appraisal_ShowMagicInfo @ 0x004B2E10`; `ItemExamineUI::Appraisal_ShowDescription @ 0x004B6990`; `MaterialTypeEnumMapper::MaterialTypeToString @ 0x005CD500`; `ItemExamineUI::SetInscription @ 0x004AE2F0`; `CM_Writing::Event_SetInscription @ 0x006A98B0`; `CLinkStatusAverages::GetAveragePacketLoss @ 0x00546610`; LayoutDesc catalog |
|
||||
| AP-110 | Remaining retained gameplay panels and world HUD are absent: advanced-combat powerbar, residual social/floating chat, quests/map/options/smartbox, vendor/trade/salvage/tinkering, mini-game gameplay, Link Status NAK/retransmission packet-loss averaging, and D.6 nameplates/floaters. Examination has its independent authored floaty layout, inscription transaction, retail creature stat/rating/animated-preview presentation, default selection-follow, and the full EoR item-report dispatch: appraisal-only unknowns; exact equipment-set/rating/tinkering/weapon/armor/caster/requirement/XP/healer/rare prose and intentional blank section rows; ordinary/enchantment DAT spell descriptions; live material-decorated appropriate titles plus DAT material and creature names; expiry, decorated material/gem descriptions; and portal/PK restrictions with authored item colors. It still lacks item-object preview, player-dependent effective shield projection, live cooldown-remaining projection, localized augmentation-cost `StringInfo`, exhaustive character detail regions, and exact creature appraisal FontInfo-list selection. | `src/AcDream.App/UI/RetailUiRuntime.cs`; `src/AcDream.App/UI/Layout/AppraisalUiController.cs`; `src/AcDream.App/UI/Layout/ItemAppraisalTextFormatter.cs`; `src/AcDream.App/UI/Layout/RetailAppraisalNameResolver.cs`; `src/AcDream.App/UI/Layout/CreatureAppraisalRows.cs`; `src/AcDream.App/Rendering/CreatureAppraisalPresentation.cs`; `src/AcDream.Core.Net/LinkStatusSnapshot.cs`; D.5/D.6 roadmap | Basic combat, M3 magic/Link/Vitae surfaces, and the core examination request/presentation/inscription/creature-preview/item-report loop cover the active loops; the residual examination mechanisms require live player/enchantment/localization state or object-preview ownership rather than fabricated content | Item assessments omit only the listed live/localized/preview projections; enchanted/incomplete creature appraisal rows use the normal authored font until the exact FontInfo list is bound; other absent panels remain unavailable; real packet loss is displayed as 0.00% instead of retail's moving average | `BasicCreatureExamineUI::Init @ 0x004AB9C0`; `CreatureExamineUI::SetAppraiseInfo @ 0x004B3FF0`; `gmExaminationUI::RecvNotice_SelectionChanged @ 0x004AB3D0`; `AttributeInfoRegion::Update @ 0x004F1D90`; `gmExaminationUI::SetAppraiseInfo @ 0x004ADAE0`; `ACCWeenieObject::GetObjectName @ 0x0058E6E0`; `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`; `ItemExamineUI::AddItemInfo @ 0x004AC050`; `ItemExamineUI::Appraisal_ShowCapacity @ 0x004B2680`; `ItemExamineUI::Appraisal_ShowSpecialProperties @ 0x004B0140`; `ItemExamineUI::Appraisal_ShowWeaponAndArmorData @ 0x004B10E0`; `ItemExamineUI::Appraisal_ShowMagicInfo @ 0x004B2E10`; `ItemExamineUI::Appraisal_ShowDescription @ 0x004B6990`; `MaterialTypeEnumMapper::MaterialTypeToString @ 0x005CD500`; `ItemExamineUI::SetInscription @ 0x004AE2F0`; `CM_Writing::Event_SetInscription @ 0x006A98B0`; `CLinkStatusAverages::GetAveragePacketLoss @ 0x00546610`; LayoutDesc catalog |
|
||||
| ~~AP-111~~ | **RETIRED 2026-07-11 (M2 held-object parenting)** — equipped hand items are no longer omitted from the render world. CreateObject now preserves Placement/Parent/position timestamp bootstrap; live `0xF749` ParentEvent is parsed with retail sequence freshness; a focused render controller resolves `Setup.HoldingLocations`, applies the child's placement frame, and recomposes the separate child entity after every parent animation tick. Pickup retains the weenie's visual metadata for a later wield. | `src/AcDream.Core.Net/Messages/{CreateObject,ParentEvent}.cs`; `src/AcDream.Core/Meshing/EquippedChildAttachment.cs`; `src/AcDream.App/Rendering/EquippedChildRenderController.cs` | — | — | `ClientCombatSystem::GetDefaultCombatMode @ 0x0056B310`; `SmartBox::HandleParentEvent @ 0x004535D0`; `CPhysicsObj::set_parent @ 0x00515A90`; `CPhysicsObj::UpdateChild @ 0x00512D50` |
|
||||
| AP-112 | The basic combat bar ports visibility, height selection, desired-power slider, exact 1.0/0.8-second charge, ready-stance gating, request/release, `MaybeStopCompletely`, server-response queueing, and auto-repeat, but still omits `StartAttackRequest`'s `FinishJump` call and exact trained-Recklessness visibility semantics (IA-20 keeps the dark range as the accepted baseline) | `src/AcDream.App/Combat/CombatAttackController.cs`; `src/AcDream.App/UI/Layout/CombatUiController.cs` | The shared player movement owner now performs retail's server-control-gated full stop and movement report before an attack build; the remaining seams require the jump owner and a distinct Recklessness treatment | Starting an attack while charging a jump may not finish that jump exactly when retail does; trained/untrained Recklessness presentation is identical | `ClientCombatSystem::StartAttackRequest @ 0x0056C040`; `CommandInterpreter::MaybeStopCompletely @ 0x006B3B90`; `gmCombatUI::ListenToElementMessage @ 0x004CC430` |
|
||||
| AP-113 | Invalid lifestone-command arguments display the local text `Usage: /lifestone`; retail definitely emits a local usage/error line but Binary Ninja misidentifies the referenced wide-string address, so its exact wording is not yet recovered | `src/AcDream.UI.Abstractions/Panels/Chat/ChatCommandRouter.cs`; `RetailClientCommandCatalog.cs` | The behavior boundary is exact (handled locally, no chat and no game action); only a low-impact diagnostic sentence differs | `/ls now` can show different wording/color from retail while still refusing the invalid request correctly | `ClientCommunicationSystem::DoLifestone @ 0x0056FC70` |
|
||||
|
|
|
|||
|
|
@ -213,6 +213,19 @@ The focused item formatter suite passes 21/21, App Release passes 3,531 tests /
|
|||
3 skips, and the complete Release solution passes 7,952 tests / 5 skips. The
|
||||
connected item-report comparison is the remaining Slice 3 gate.
|
||||
|
||||
The material-title and section-boundary correction carries
|
||||
`PublicWeenieDesc.MaterialType` from CreateObject through the canonical object
|
||||
table and resolves `ACCWeenieObject::GetObjectName(NAME_APPROPRIATE)` through
|
||||
the installed DAT material map. Examination titles now produce names such as
|
||||
`Reed Shark Hide Steel Toed Boots` without duplicating a material already
|
||||
present in the authored base name. Empty `AddItemInfo` calls are retained as
|
||||
real report fragments, restoring retail's intentional blank rows after
|
||||
workmanship, before armor level, around rating/special-property blocks, and at
|
||||
the later use/item-level boundaries. Focused wire, projection, object-table,
|
||||
title, and boots-layout fixtures protect the full path. The Release solution
|
||||
build and 3,533 App tests / 3 skips plus 7,956 complete-solution tests /
|
||||
5 skips pass; the connected boots comparison is the remaining visual gate.
|
||||
|
||||
## Slice 1 — spell-bar overflow arrows
|
||||
|
||||
### Retail oracle
|
||||
|
|
|
|||
|
|
@ -181,6 +181,23 @@ SetAppraiseInfo(guid, profile):
|
|||
show examination window
|
||||
```
|
||||
|
||||
`ACCWeenieObject::GetObjectName @ 0x0058E6E0` does more than pluralize:
|
||||
|
||||
```text
|
||||
baseName = singular or plural name selected for the live stack size
|
||||
if PublicWeenieDesc.MaterialType > 0:
|
||||
material = AppraisalSystem.InqMaterialName(MaterialType)
|
||||
remove material from baseName when it is already authored there
|
||||
trim the remaining baseName
|
||||
baseName = material + " " + remaining baseName
|
||||
return baseName
|
||||
```
|
||||
|
||||
The title therefore uses the live CreateObject material field. For example,
|
||||
an authored `Steel Toed Boots` object whose material is `Reed Shark Hide`
|
||||
is titled `Reed Shark Hide Steel Toed Boots`; appraisal property 131 is for
|
||||
description decoration and is not a substitute for this live name field.
|
||||
|
||||
Only the first response to an explicit request forces the window visible.
|
||||
Background refreshes update the current object without reopening a closed
|
||||
window.
|
||||
|
|
@ -348,6 +365,9 @@ AddItemInfo(text, fontColorIndex, sameParagraph):
|
|||
append sameParagraph ? "\n" : "\n\n"
|
||||
append text with font-list index 0 and the requested color-list index
|
||||
|
||||
# Empty text is meaningful. The separator is still appended, so
|
||||
# AddItemInfo("", ..., true) preserves an intentional blank row.
|
||||
|
||||
ShowValueAndBurden(profile):
|
||||
if profile contains int 19:
|
||||
append "Value: <grouped value>"
|
||||
|
|
@ -537,6 +557,7 @@ ShowTinkering:
|
|||
"Workmanship: <adjective of rounded average> (<average, two decimals>)"
|
||||
blank line
|
||||
"Salvaged from %d items."
|
||||
append an empty same-paragraph entry unconditionally
|
||||
|
||||
ShowSet:
|
||||
EquipmentSetId (265) selects the literal EoR set-name table.
|
||||
|
|
@ -550,6 +571,9 @@ ShowRatings:
|
|||
render as "Ratings: Dam 3, Crit 2" (there is no plus sign)
|
||||
positive Vitality (379) is a separate
|
||||
"This item adds %d Vitality."
|
||||
if any rating or Vitality was emitted:
|
||||
append an empty same-paragraph entry
|
||||
SetAppraiseInfo appends one more empty entry when Set or Ratings emitted
|
||||
|
||||
ShowWeaponAndArmorData:
|
||||
only interpret WeaponProfile inside weapon/shield valid-location bits
|
||||
|
|
@ -559,6 +583,16 @@ ShowWeaponAndArmorData:
|
|||
Upper Legs, Lower Legs, Feet"
|
||||
selecting the names from ClothingPriority bits in that exact order
|
||||
|
||||
ShowArmorModsData:
|
||||
the first "Armor Level" string itself begins with "\n"
|
||||
AddItemInfo also contributes its ordinary separator, leaving one blank
|
||||
row between clothing coverage and Armor Level
|
||||
|
||||
ShowSpecialProperties:
|
||||
begin with an empty same-paragraph entry
|
||||
carry-limit text has another empty entry before it
|
||||
shared cooldown metadata and cleave have their retail trailing empty entry
|
||||
|
||||
ShowShortMagic:
|
||||
list only ordinary spell ids (high bit clear)
|
||||
a failed appraisal prints "Spells: unknown."
|
||||
|
|
@ -583,6 +617,7 @@ ShowItemLevel:
|
|||
nextThreshold = ItemLevelToTotalXP(min(currentLevel + 1, maxLevel), ...)
|
||||
"Item Level: <displayedLevel> / <maxLevel>"
|
||||
"Item XP: <grouped total> / <grouped nextThreshold>"
|
||||
append an empty same-paragraph entry after Item XP
|
||||
|
||||
ItemLevelToTotalXP(level, base, max, style):
|
||||
clamp level to [0, max]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue