feat(ui): complete retail item appraisal reports
Restore the authored examination geometry and top-origin item list, then port retail's ordered weapon, armor, magic, requirement, capacity, cooldown, use, and description branches into a dedicated formatter with DAT spell prose. Keep the remaining specialized display-name and preview gaps explicit in AP-110. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
d96ea2de98
commit
bc47bc4917
9 changed files with 1587 additions and 297 deletions
|
|
@ -101,11 +101,18 @@ animated clone, bounding-box camera, and private-viewport light.
|
|||
Its correction ports the second authored damage/critical/resistance rating
|
||||
list, composites row chrome behind the animated preview and row text in front,
|
||||
adds balanced text inset, and automatically reassesses each new selection
|
||||
while the floaty remains visible.
|
||||
while the floaty remains visible. The next correction restores the authored
|
||||
310 x 400 profile size, insets only foreground row text, lays generated item
|
||||
text out from the top, and replaces the sparse property dump with retail's
|
||||
ordered item-report branches for common weapons, armor, magic and DAT spell
|
||||
descriptions, requirements, capacities, cooldown/special properties, uses,
|
||||
crafting, ratings, rare state, and prose. AP-110 records the remaining
|
||||
specialized/player-dependent/DAT-name/font/object-preview branches explicitly.
|
||||
|
||||
**Files:** `src/AcDream.Core.Net/Messages/AppraiseInfoParser.cs`;
|
||||
`src/AcDream.App/UI/RetailUiRuntime.cs`;
|
||||
`src/AcDream.App/UI/Layout/AppraisalUiController.cs`;
|
||||
`src/AcDream.App/UI/Layout/ItemAppraisalTextFormatter.cs`;
|
||||
`src/AcDream.App/UI/UiField.cs`;
|
||||
`src/AcDream.Core.Net/Messages/InventoryActions.cs`.
|
||||
|
||||
|
|
@ -119,7 +126,9 @@ noninscribable cases show retail's exact permission messages. Monster pages
|
|||
show the animated target, mapped creature type, level, and nine ordered
|
||||
retail stat rows; rated creatures show retail's paired rating rows; the
|
||||
animated target remains above row chrome but below text; changing selection
|
||||
updates the open window without another magnifier click.
|
||||
updates the open window without another magnifier click. Item text begins at
|
||||
the top and assessed melee/missile/armor/magic items show their retail-ordered
|
||||
stats and full DAT spell descriptions.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -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, item/creature/character reports, inscription transaction, retail creature stat/rating/animated-preview presentation, and default selection-follow, but still lacks item-object preview, exhaustive specialized item/character detail regions, and exact appraisal FontInfo-list selection. | `src/AcDream.App/UI/RetailUiRuntime.cs`; `src/AcDream.App/UI/Layout/AppraisalUiController.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 loop cover the active loops; the remaining examination mechanisms require additional retail field/font/object-preview projections rather than fabricated content | Specialized item/character assessments omit some retail fields and item-object presentation; enchanted/incomplete 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::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 retail-ordered item reports covering weapon/armor/caster modifiers, spell names plus DAT descriptions, requirements, capacities, cooldown/special properties, uses, crafting, rare, and description data. It still lacks item-object preview, player-dependent effective shield projection, DAT display-name resolution for equipment sets and slayer creature types, some expiry/material/portal/PK-specialized description branches, exhaustive character detail regions, and exact 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/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 remaining examination mechanisms require player-state or DAT display-name resolvers and object-preview ownership rather than fabricated content | Uncommon item/character assessments may omit the listed specialized branches and item-object presentation; unresolved equipment-set/slayer values use their numeric identity; enchanted/incomplete 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::Appraisal_ShowSpecialProperties @ 0x004B0140`; `ItemExamineUI::Appraisal_ShowWeaponAndArmorData @ 0x004B10E0`; `ItemExamineUI::Appraisal_ShowMagicInfo @ 0x004B2E10`; `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` |
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ shared item-cooldown follow-up passed their connected gates. Slice 3's first
|
|||
connected gate exposed an incorrect IdentifyResponse flag table, a non-retail
|
||||
shared-panel mount, and its missing inscription transaction. All three are
|
||||
corrected and live-confirmed. The creature-page follow-up now has retail's
|
||||
ordered stat rows and animated private preview; its visual gate is pending.
|
||||
ordered stat rows and animated private preview. The follow-up item report and
|
||||
authored 310 x 400 layout correction are implemented; their connected visual
|
||||
gate is pending.
|
||||
**Milestone:** M4 prerequisite/preamble.
|
||||
**Architecture:** retained gameplay UI over shared selection, object, and
|
||||
interaction state. `GameWindow` remains a composition/callback shell.
|
||||
|
|
@ -160,6 +162,24 @@ passes the Release solution build with the 17 warnings already tracked by
|
|||
#228, 3,510 App tests / 3 skips, and 7,927 complete-solution tests / 5 skips.
|
||||
Its corrected connected visual result remains the closeout gate.
|
||||
|
||||
The item-report/layout correction restores the authored 310 x 400 examination
|
||||
size for the connected profile, leaves retail's ordinary resize range intact,
|
||||
keeps row chrome at its LayoutDesc origin while insetting only foreground
|
||||
creature text, and starts generated item prose at the top of its authored
|
||||
scroll surface. `ItemAppraisalTextFormatter` now owns the decomp-ordered item
|
||||
projection outside `GameWindow` and outside the examination controller. It
|
||||
ports common weapon damage ranges/speed/range/ammunition, armor protection
|
||||
bands, defense/caster modifiers, workmanship, ratings, wield/use/activation
|
||||
requirements, item XP/capacity/lock/mana/uses/creator/rare data, cooldown and
|
||||
imbued special properties, and both short spell lists and full DAT spell
|
||||
descriptions. AP-110 now names only the remaining specialized,
|
||||
player-dependent, DAT-display-name, font-state, and object-preview gaps.
|
||||
Focused conformance fixtures cover the geometry layering plus melee, launcher,
|
||||
armor, spell, and special-property reports. The Release solution build passes
|
||||
with the 17 warnings already tracked by #228, 3,514 App tests / 3 skips, and
|
||||
7,931 complete-solution tests / 5 skips. The connected visual result remains
|
||||
the closeout gate.
|
||||
|
||||
## Slice 1 — spell-bar overflow arrows
|
||||
|
||||
### Retail oracle
|
||||
|
|
|
|||
|
|
@ -329,6 +329,143 @@ this order:
|
|||
9. caster/boost/healer/capacity/lock/mana/uses/craftsman details;
|
||||
10. sale restriction, rare status, full magic, and description.
|
||||
|
||||
The individual branches are not a generic property dump. They project the
|
||||
wire profile into retail prose:
|
||||
|
||||
```text
|
||||
ShowWeaponAndArmor(validLocations, profile):
|
||||
ammoType = live PublicWeenieDesc ammo type
|
||||
if object is a hook:
|
||||
ammoType = HookProfile ammo type
|
||||
|
||||
if validLocations contains Shield:
|
||||
append "Base Shield Level: <ArmorLevel>"
|
||||
append the player-dependent effective Shield level when available
|
||||
|
||||
if validLocations contains a weapon location:
|
||||
weapon = profile.WeaponProfile
|
||||
append "Skill: <WeaponSkill>"
|
||||
if WeaponType exists:
|
||||
append the parenthesized weapon subtype
|
||||
|
||||
launcher = validLocations contains MissileWeapon and ammoType != None
|
||||
append launcher ? "Damage Bonus: " : "Damage: "
|
||||
minimum = (1 - DamageVariance) * Damage
|
||||
if Damage - minimum > 0.0002:
|
||||
append "<minimum> - <maximum>"
|
||||
else:
|
||||
append "<maximum>"
|
||||
append damage type for non-launchers
|
||||
|
||||
append Elemental Damage Bonus when present
|
||||
append launcher Damage Modifier when present
|
||||
|
||||
if validLocations contains MeleeWeapon, MissileWeapon, or TwoHanded:
|
||||
append "Speed: <category> (<raw weapon time>)"
|
||||
categories:
|
||||
raw < 11 -> Very Fast
|
||||
raw < 31 -> Fast
|
||||
raw < 50 -> Average
|
||||
raw < 80 -> Slow
|
||||
otherwise -> Very Slow
|
||||
|
||||
if launcher:
|
||||
rangeYards = min(
|
||||
85,
|
||||
2 * MaxVelocity^2 * (1 / 9.8) * 1.094)
|
||||
if rangeYards < 10:
|
||||
displayedRange = ceil(rangeYards)
|
||||
else:
|
||||
displayedRange = truncate down to a multiple of 5
|
||||
append "Range: <displayedRange> yds."
|
||||
if MaxVelocityEstimated:
|
||||
append " (based on STRENGTH 100)"
|
||||
|
||||
if WeaponOffense != 1 and this is not launcher damage:
|
||||
append "Bonus to Attack Skill: <signed percent>."
|
||||
|
||||
append the retail ammunition sentence:
|
||||
ammunition -> "Used as ammunition by bows/crossbows/atlatls."
|
||||
launcher -> "Uses arrows/quarrels/atlatl darts as ammunition."
|
||||
|
||||
ShowArmor(profile):
|
||||
append "Armor Level: <base AL>"
|
||||
for Slashing, Piercing, Bludgeoning, Fire, Cold, Acid, Electric, Nether:
|
||||
adjective from DamageResistanceToString:
|
||||
0.0 -> None
|
||||
(0.0, 0.4) -> Poor
|
||||
[0.4, 0.8) -> Below Average
|
||||
[0.8, 1.2) -> Average
|
||||
[1.2, 1.6) -> Above Average
|
||||
[1.6, 2.0) -> Excellent
|
||||
>= 2.0 -> Unparalleled
|
||||
append "<damage>: <adjective> (<base AL * modifier, rounded>)"
|
||||
|
||||
ShowMagic(profile):
|
||||
if the spellbook exists and appraisal failed:
|
||||
append "Spells: unknown."
|
||||
return
|
||||
|
||||
split spell ids by the high enchantment bit
|
||||
resolve every id with that bit masked through ClientMagicSystem
|
||||
|
||||
for ordinary spells:
|
||||
append Spellcraft, Mana, and Mana Cost when present
|
||||
append "Spell Descriptions:"
|
||||
append each spell name and its DAT description
|
||||
|
||||
for high-bit enchantments:
|
||||
append "Enchantments:"
|
||||
append each spell name and its DAT description
|
||||
|
||||
ShowSpecialProperties(profile):
|
||||
append carry limit and authored cooldown duration when present
|
||||
append cleave count
|
||||
build one "Properties: " line from:
|
||||
creature slayer, Multi-Strike, imbued-effect flags,
|
||||
Magic Absorbing, Unenchantable, Attuned/Bonded/death behavior,
|
||||
Retained, Crushing Blow, Biting Strike, Armor/Resistance Cleaving,
|
||||
Cast on Strike, Ivoryable, and Dyeable
|
||||
if an imbued-effect flag exists:
|
||||
append "This item cannot be further imbued."
|
||||
if AutowieldLeft:
|
||||
append the left-hand tether sentence
|
||||
|
||||
ShowRemainingItemFields(profile):
|
||||
append, in SetAppraiseInfo order:
|
||||
usage text
|
||||
level, direct heritage restriction, and wield requirements
|
||||
(up to four requirement triplets)
|
||||
use restrictions
|
||||
item level and item XP
|
||||
activation requirements
|
||||
caster, boost, healing, capacity, lock, and mana-stone data
|
||||
remaining key/charge counts
|
||||
creator, last tinkerer, and imbuer
|
||||
cannot-be-sold and rare notices
|
||||
short and long descriptions
|
||||
```
|
||||
|
||||
Sources:
|
||||
|
||||
- `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`
|
||||
- `ItemExamineUI::Appraisal_ShowWieldRequirements @ 0x004AF9A0`
|
||||
- `ItemExamineUI::Appraisal_ShowSpecialProperties @ 0x004B0140`
|
||||
- `ItemExamineUI::Appraisal_ShowWeaponAndArmorData @ 0x004B10E0`
|
||||
- `ItemExamineUI::Appraisal_ShowArmorModsData @ 0x004B1F60`
|
||||
- `ItemExamineUI::Appraisal_ShowMagicInfo @ 0x004B2E10`
|
||||
- `ItemExamineUI::Appraisal_ShowActivationRequirements @ 0x004B3270`
|
||||
- `AppraisalSystem::WeaponTimeToString @ 0x005B4970`
|
||||
- `AppraisalSystem::DamageResistanceToString @ 0x005B5490`
|
||||
- `AppraisalSystem::InqWorkmanshipAdjective @ 0x005B48E0`
|
||||
- `ClientUISystem::DeltaTimeToString @ 0x00565E10`
|
||||
|
||||
ACE's `AppraiseInfo` serializer and property enums were used to pin the
|
||||
typed-table IDs carried by the network profile. ACViewer's portal.dat
|
||||
SpellTable path was used as the second reference check that item spell names
|
||||
and descriptions come from DAT spell metadata rather than a hand-maintained
|
||||
client list. Retail's named functions remain the behavioral oracle.
|
||||
|
||||
The main text and inscription areas use their authored scrollbars. A newly
|
||||
selected object resets those scroll positions to the top; a refresh of the
|
||||
same object preserves the user's position.
|
||||
|
|
@ -344,6 +481,14 @@ Inventory/Skills/Spellbook panel.
|
|||
`gmFloatyExaminationUI::ResizeTo` delegates to ordinary `UIElement::ResizeTo`
|
||||
and persists width/height; it adds no special resize algorithm.
|
||||
|
||||
The authored root is exactly 310 by 400 pixels and has 310-by-400 minimum
|
||||
constraints. Its maximum constraints are 2000 by 2000, so 310 by 400 is the
|
||||
retail opening/default size, not a fixed-size panel. The main item report
|
||||
control is authored with bottom vertical justification, but
|
||||
`ItemExamineUI::AddItemInfo` appends rows from the start of the cleared text
|
||||
surface. The retained projection must therefore lay out that generated report
|
||||
from the top while leaving the separate authored inscription behavior intact.
|
||||
|
||||
## Inscription presentation and eligibility
|
||||
|
||||
```text
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue