fix #234: port retail appraisal floaty and inscriptions
This commit is contained in:
parent
643cdfe66e
commit
f1a7912160
23 changed files with 1310 additions and 106 deletions
|
|
@ -74,6 +74,44 @@ Copy this block when adding a new issue:
|
|||
|
||||
---
|
||||
|
||||
## #234 — Monster assessment held busy and examination used the shared panel
|
||||
|
||||
**Status:** DONE — 2026-07-23, corrective connected gate pending
|
||||
**Severity:** HIGH
|
||||
**Filed:** 2026-07-23
|
||||
**Component:** appraisal protocol / retained examination UI / item writing
|
||||
|
||||
**Description:** Assessing a monster appeared to hang the UI with the busy
|
||||
cursor. Examination also replaced Inventory/Skills in the shared primary
|
||||
panel, while retail opens its own floaty window. Assessed item inscriptions
|
||||
were display-only.
|
||||
|
||||
**Root cause / status:** The local IdentifyResponse enum did not match
|
||||
ACE/retail: creature profile bit `0x0100` was labeled WeaponProfile. The strict
|
||||
parser consequently rejected normal creature responses before the appraisal
|
||||
owner could release its balanced busy reference. The examination LayoutDesc
|
||||
had also been incorrectly registered as synthetic main-panel id
|
||||
`0x80000001`; retail's concrete root is `gmFloatyExaminationUI`. Exact response
|
||||
bits/order are now pinned by literal packet tests, the floaty is registered as
|
||||
an independent top-level window, and the imported multiline field sends
|
||||
retail's CP-1252 `SetInscription (0x00BF)` under its ownership/authorship rules.
|
||||
|
||||
**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/UiField.cs`;
|
||||
`src/AcDream.Core.Net/Messages/InventoryActions.cs`.
|
||||
|
||||
**Research:**
|
||||
[`research/2026-07-23-retail-appraisal-ui-pseudocode.md`](research/2026-07-23-retail-appraisal-ui-pseudocode.md).
|
||||
|
||||
**Acceptance:** Monster/NPC/player assessment opens and clears busy; the
|
||||
examination window coexists with the shared primary panel; an owned
|
||||
inscribable weapon can be edited/cleared and reassessed; foreign/nonowned/
|
||||
noninscribable cases show retail's exact permission messages.
|
||||
|
||||
---
|
||||
|
||||
## #235 — Capped/RDP jump presentation aliases the 30 Hz object clock
|
||||
|
||||
**Status:** OPEN
|
||||
|
|
|
|||
|
|
@ -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 now has its authored outer layout and basic item/creature/character reports, but still lacks the exact 3D preview and exhaustive specialized detail regions, conditional inscription-write transaction, and selection-follow preference. | `src/AcDream.App/UI/RetailUiRuntime.cs`; `src/AcDream.App/UI/Layout/AppraisalUiController.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 loop cover the active loops; the remaining examination mechanisms require additional render and item-write owners rather than fabricated content | Specialized assessments omit some retail fields/3D preview and inscriptions are display-only; other absent panels remain unavailable; real packet loss is displayed as 0.00% instead of retail's moving average | `gmExaminationUI::SetAppraiseInfo @ 0x004ADAE0`; `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`; `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 now has its independent authored floaty layout, item/creature/character reports, and conditional inscription-write transaction, but still lacks the exact 3D preview, exhaustive specialized detail regions, and selection-follow preference. | `src/AcDream.App/UI/RetailUiRuntime.cs`; `src/AcDream.App/UI/Layout/AppraisalUiController.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 loop cover the active loops; the remaining examination mechanisms require the retail preview render owner and additional field projections rather than fabricated content | Specialized assessments omit some retail fields/3D preview; other absent panels remain unavailable; real packet loss is displayed as 0.00% instead of retail's moving average | `gmExaminationUI::SetAppraiseInfo @ 0x004ADAE0`; `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`; `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` |
|
||||
|
|
|
|||
|
|
@ -30,11 +30,15 @@ ports the optional public shared-cooldown metadata, the authoritative
|
|||
cooldown-enchantment lookup, the exact ten-step bucket formula, and DAT
|
||||
sprites `0x060067CF..0x060067D8` through the shared retained `UiItemSlot`
|
||||
presentation; its connected gate passed. The existing magnifying-glass Assess
|
||||
command was already retail-faithful. Slice 3 is now code-complete: the complete
|
||||
appraisal response reaches a balanced pending/current request owner and the
|
||||
imported 310 x 400 examination layout through the canonical shared main-panel
|
||||
host. Item, creature, and character views, authored scrollbars, first-response
|
||||
visibility, and visible-combat refresh are pinned; the connected examination
|
||||
command was already retail-faithful. Slice 3's first connected gate exposed
|
||||
three deeper defects, now corrected: the response enum mislabeled ACE's
|
||||
creature bit `0x0100` and dropped monster packets while retaining the busy
|
||||
cursor; the imported 310 x 400 examination layout was incorrectly hosted as
|
||||
shared main-panel content; and inscription was display-only. Exact flag
|
||||
decoding now reaches the balanced request owner, retail's
|
||||
`gmFloatyExaminationUI` has an independent top-level lifetime, and the
|
||||
imported multiline field sends the exact `SetInscription (0x00BF)`
|
||||
transaction under retail ownership/authorship rules. The corrective connected
|
||||
gate is next.
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -97,11 +97,15 @@ AutoWear blockers, and carried-use delivery is user-confirmed. The requested
|
|||
adjacent cooldown follow-up now preserves the item's shared group/duration,
|
||||
projects the authoritative cooldown-enchantment bucket, and draws retail's ten
|
||||
DAT-authored radial steps across all item-slot surfaces; its connected gate
|
||||
passed. The pre-existing Assess command has been reconciled against retail and
|
||||
Slice 3 is code-complete: strict full appraisal parsing, balanced
|
||||
pending/current request ownership, and LayoutDesc `0x2100006B` item,
|
||||
creature, and character views now live in the canonical shared main-panel
|
||||
host. Its connected examination gate is next.
|
||||
passed. The pre-existing Assess command has been reconciled against retail.
|
||||
Slice 3's first connected gate found and corrected the real remaining defects:
|
||||
ACE creature flag `0x0100` was mislabeled as a weapon profile and left the
|
||||
appraisal busy reference held, retail's examination UI had been mounted as a
|
||||
shared main-panel page rather than its own floaty window, and inscription was
|
||||
display-only. Exact response flags, the independent
|
||||
`gmFloatyExaminationUI` lifetime, and the retail `SetInscription (0x00BF)`
|
||||
edit transaction are now ported. The corrective connected
|
||||
examination/inscription gate is next.
|
||||
|
||||
Carried:
|
||||
#153 far-teleport residual, #116 slide-response, the remaining R6 ownership cleanup plus
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
**Status:** Slice 1 user-accepted 2026-07-23. Slice 2 Use-hand selection,
|
||||
zero-useability, carried direct-use, AutoWear correction, and the requested
|
||||
shared item-cooldown follow-up passed their connected gates. The existing
|
||||
retail Assess command has been reconciled and Slice 3's examination panel is
|
||||
code-complete; its connected visual gate is next.
|
||||
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; the independent floaty examination window awaits its corrective
|
||||
connected gate.
|
||||
**Milestone:** M4 prerequisite/preamble.
|
||||
**Architecture:** retained gameplay UI over shared selection, object, and
|
||||
interaction state. `GameWindow` remains a composition/callback shell.
|
||||
|
|
@ -19,7 +21,7 @@ quest/emote/character-creation bodies begin:
|
|||
2. The status bar's hand and magnifying-glass controls invoke the same Use and
|
||||
Assess commands as their keyboard paths.
|
||||
3. Assessing a creature, player, NPC, or object opens its retail information in
|
||||
the canonical shared main-panel host.
|
||||
the independent movable/resizable retail floaty examination window.
|
||||
4. World picking can resolve visible equipped children, such as a character's
|
||||
wielded weapon, while selection markers remain anchored to the picked child.
|
||||
5. Vendor use opens the authored vendor surface, publishes its inventory, and
|
||||
|
|
@ -38,7 +40,7 @@ selection state, or optimistic inventory outcomes.
|
|||
|---|---|---|
|
||||
| 1 | Spell-bar overflow arrows | `SpellcastingUiController` + generic retained scrollbar/list |
|
||||
| 2 | Status Use/Assess commands | focused status-bar controller binding to the existing action router |
|
||||
| 3 | Assessment information panel | new retained panel controller mounted by the canonical main-panel host |
|
||||
| 3 | Assessment information panel | retained controller in an independent floaty examination window |
|
||||
| 4 | Equipped-child world picking | pure world-query/picking policy plus presentation anchor |
|
||||
| 5 | Vendor browse lifecycle | vendor session/controller plus authored panel |
|
||||
| 6 | Vendor transactions | server-authoritative buy/sell command and reconciliation owner |
|
||||
|
|
@ -114,19 +116,29 @@ retail response owner around it. One shared UI-busy reference covers the
|
|||
latest pending GUID, stale replies are rejected, the accepted reply becomes
|
||||
the current appraisal, and combat-time creature/player refreshes occur every
|
||||
0.75 seconds only while the examination window is visible. Complete
|
||||
`IdentifyObjectResponse` parsing now includes the three-word HookProfile and
|
||||
rejects truncated gated payloads rather than continuing from a corrupt cursor.
|
||||
`IdentifyObjectResponse` parsing now uses ACE/retail's exact flag values and
|
||||
positional order, includes the three-word HookProfile, and rejects truncated
|
||||
gated payloads rather than continuing from a corrupt cursor. The first live
|
||||
monster gate found that `0x0100` had been mislabeled WeaponProfile; the parser
|
||||
dropped every creature response before response acceptance, leaving the one
|
||||
busy reference held. A literal ACE `0x0100` creature fixture now protects that
|
||||
packet-to-controller path.
|
||||
|
||||
LayoutDesc `0x2100006B`, root `0x100005F2`, supplies the complete 310 x 400
|
||||
floaty chrome, title, item/creature/character subviews, close control, and
|
||||
authored scrollbars. The panel participates in the canonical one-active
|
||||
main-panel geometry/lifecycle rather than owning a parallel location. Basic
|
||||
item, creature, and player reports are live; exact 3D preview/specialized
|
||||
detail regions, conditional inscription editing, and selection-follow remain
|
||||
the narrowed AP-110 residual. Research:
|
||||
authored scrollbars. `gmFloatyExaminationUI` is an independent top-level
|
||||
window, so Inventory/Skills/Spellbook no longer replace it or inherit its
|
||||
geometry. The imported multiline inscription field now ports
|
||||
`ItemExamineUI`'s public/hook inscribability, inventory ownership and
|
||||
same-scribe permission rules, placeholder/signature presentation, exact
|
||||
failure notices, focus commit behavior, and CP-1252 `SetInscription (0x00BF)`
|
||||
transaction. Basic item, creature, and player reports are live; exact 3D
|
||||
preview/specialized detail regions and selection-follow remain the narrowed
|
||||
AP-110 residual. Research:
|
||||
[`../research/2026-07-23-retail-appraisal-ui-pseudocode.md`](../research/2026-07-23-retail-appraisal-ui-pseudocode.md).
|
||||
The focused parser/router/request/controller/fixture tests pass, as do the
|
||||
Release solution build with 17 pre-existing tracked test warnings, 3,488 App
|
||||
tests / 3 skips, and 7,885 complete-solution tests / 5 skips.
|
||||
Release solution build with 17 pre-existing tracked test warnings, 3,496 App
|
||||
tests / 3 skips, and 7,913 complete-solution tests / 5 skips.
|
||||
|
||||
## Slice 1 — spell-bar overflow arrows
|
||||
|
||||
|
|
@ -224,20 +236,27 @@ Named retail references and executable pseudocode are recorded in
|
|||
3. `AppraisalUiController` owns response acceptance, item/creature/character
|
||||
subview selection, report projection, scroll preservation, first-response
|
||||
visibility, and visible-combat refresh.
|
||||
4. `RetailUiRuntime` imports the retail layout and registers it with
|
||||
`RetailPanelUiController`, so Inventory, Skills, Spellbook, effects, and
|
||||
Examination remain views of the same movable/resizable main panel.
|
||||
4. `RetailUiRuntime` imports and registers retail's
|
||||
`gmFloatyExaminationUI` as its own top-level window. It deliberately does
|
||||
not enter `RetailPanelUiController`; Inventory, Skills, Spellbook, and
|
||||
effects keep their shared main-panel geometry while Examination coexists.
|
||||
5. Network workers deliver immutable parsed data through the existing
|
||||
session router; retained state changes remain on the update thread.
|
||||
6. `AppraisalUiController` owns inscription presentation and optimistic field
|
||||
state; `WorldSession` owns the exact `0x00BF` GameAction send. Authoritative
|
||||
inventory/appraisal data remains the source on the next response.
|
||||
|
||||
### Connected gate
|
||||
|
||||
- Select an item and click the magnifying glass (or press Assess): the shared
|
||||
panel should show its name, available properties, descriptions,
|
||||
inscription/signature, retail chrome, and working scrollbar.
|
||||
- Select an item and click the magnifying glass (or press Assess): a separate
|
||||
floaty window should show its name, available properties, descriptions,
|
||||
inscription/signature, retail chrome, and working scrollbars.
|
||||
- Assess a monster, NPC, and player: the correct creature/character page
|
||||
should appear and the busy cursor should clear.
|
||||
- In combat, leave a creature assessment open long enough to observe a health
|
||||
refresh; closing it or opening another shared panel must stop refreshes.
|
||||
- Move/resize Examination, switch to Inventory or Skills, and confirm the
|
||||
shared rectangle is retained.
|
||||
refresh; closing the examination window must stop refreshes.
|
||||
- Keep Examination open while opening/moving Inventory or Skills and confirm
|
||||
both windows coexist with independent rectangles.
|
||||
- Assess an owned inscribable weapon. Edit and clear its inscription by
|
||||
clicking elsewhere, then reassess it. An item authored by another player is
|
||||
read-only and reports the exact retail permission line when clicked.
|
||||
|
|
|
|||
|
|
@ -17,13 +17,25 @@ retained examination window.
|
|||
- `CreatureExamineUI::SetAppraiseInfo @ 0x004B3FF0`
|
||||
- `CharExamineUI::SetAppraiseInfo @ 0x004B45F0`
|
||||
- `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`
|
||||
- `ItemExamineUI::HandleInscriptionGainingFocus @ 0x004AC0E0`
|
||||
- `ItemExamineUI::HandleInscriptionMousePresses @ 0x004AC230`
|
||||
- `ItemExamineUI::SetInscriptionEditableState @ 0x004AC720`
|
||||
- `ItemExamineUI::SetInscription @ 0x004AE2F0`
|
||||
- `ItemExamineUI::HandleInscriptionLosingFocus @ 0x004AE620`
|
||||
- `gmFloatyExaminationUI::ResizeTo @ 0x004D4470`
|
||||
- `AppraisalProfile::IsHookedItemInscribable @ 0x005B2F90`
|
||||
- `HookAppraisalProfile::IsInscribable @ 0x005B64C0`
|
||||
- `CM_Writing::Event_SetInscription @ 0x006A98B0`
|
||||
- `PublicWeenieDesc::BF_INSCRIBABLE` in `acclient.h:6434`
|
||||
- Retail LayoutDesc `0x2100006B`, root `0x100005F2`
|
||||
(`gmFloatyExaminationUI`, authored size 310 x 400 pixels).
|
||||
- ACE:
|
||||
- `IdentifyResponseFlags`
|
||||
- `GameEventIdentifyObjectResponse`
|
||||
- `AppraiseInfo.Write`
|
||||
- `HookProfile.Write`
|
||||
- `GameActionSetInscription`
|
||||
- `Player.HandleActionSetInscription`
|
||||
- ACViewer's `HookAppraisalProfile` representation, used as a second
|
||||
interpretation check for the three-field hook profile.
|
||||
|
||||
|
|
@ -63,6 +75,30 @@ for the current pending GUID releases that one reference.
|
|||
|
||||
## IdentifyObjectResponse packet order
|
||||
|
||||
The flag values are part of the wire contract and are not the field-order
|
||||
indices:
|
||||
|
||||
```text
|
||||
IntStatsTable 0x0001
|
||||
BoolStatsTable 0x0002
|
||||
FloatStatsTable 0x0004
|
||||
StringStatsTable 0x0008
|
||||
SpellBook 0x0010
|
||||
WeaponProfile 0x0020
|
||||
HookProfile 0x0040
|
||||
ArmorProfile 0x0080
|
||||
CreatureProfile 0x0100
|
||||
ArmorEnchantmentBitfield 0x0200
|
||||
ResistEnchantmentBitfield 0x0400
|
||||
WeaponEnchantmentBitfield 0x0800
|
||||
DidStatsTable 0x1000
|
||||
Int64StatsTable 0x2000
|
||||
ArmorLevels 0x4000
|
||||
```
|
||||
|
||||
ACE writes the gated bodies in the order below, independent of the numerical
|
||||
position of each flag.
|
||||
|
||||
```text
|
||||
read guid
|
||||
read flags
|
||||
|
|
@ -178,16 +214,126 @@ same object preserves the user's position.
|
|||
|
||||
The LayoutDesc root already contains retail's complete floaty window chrome,
|
||||
close control, item/creature/character/spell subviews, and scrollbars.
|
||||
The root's concrete retail type is `gmFloatyExaminationUI`, not a child of
|
||||
`gmPanelUI`. It is mounted and persisted as its own top-level retained window.
|
||||
Showing it must not hide, replace, resize, or reposition the shared
|
||||
Inventory/Skills/Spellbook panel.
|
||||
`gmFloatyExaminationUI::ResizeTo` delegates to ordinary `UIElement::ResizeTo`
|
||||
and persists width/height; it adds no special resize algorithm.
|
||||
|
||||
## Slice boundary
|
||||
## Inscription presentation and eligibility
|
||||
|
||||
This slice ports the request lifetime, packet integrity, subview choice,
|
||||
authored outer layout, basic report content, scrollbar ownership, and combat
|
||||
refresh. Retail's exact 3D object/creature preview, all specialized
|
||||
`ItemExamineUI` detail branches, selection-follow preference, and
|
||||
`SetInscriptionEditableState` plus inscription submission remain explicit
|
||||
AP-110 work. Until that permission/write transaction exists, the imported
|
||||
inscription field is display-only rather than accepting edits that cannot be
|
||||
sent.
|
||||
```text
|
||||
SetInscription(profile):
|
||||
reset inscription field to its unfocused state
|
||||
clear displayed text, signature, old inscription, scribe name/account
|
||||
|
||||
inscribable = object.PublicWeenieDesc has BF_INSCRIBABLE
|
||||
if object is a hook:
|
||||
inscribable = profile.HookProfile exists
|
||||
and (HookProfile.Flags & 1) != 0
|
||||
|
||||
if not inscribable:
|
||||
hide inscription field and signature
|
||||
return
|
||||
|
||||
scribe = profile string property 8, or empty
|
||||
oldInscription = profile string property 7, or empty
|
||||
|
||||
if scribe is empty:
|
||||
field = "<Inscribe here>"
|
||||
signature = ""
|
||||
else:
|
||||
field = oldInscription
|
||||
signature = "--" + scribe
|
||||
if local player is a PSR and scribe-account property 0x17 exists:
|
||||
signature += " <" + scribeAccount + ">"
|
||||
|
||||
show field and signature
|
||||
SetInscriptionEditableState()
|
||||
|
||||
SetInscriptionEditableState:
|
||||
editable = object exists
|
||||
and object has BF_INSCRIBABLE
|
||||
and object is owned by the local player
|
||||
and (scribe is empty
|
||||
or case-insensitive scribe == local player name)
|
||||
PSR may override the ownership/scribe restriction
|
||||
field.Editable = editable
|
||||
field.Selectable = editable
|
||||
inscription background receives mouse presses only when not editable
|
||||
```
|
||||
|
||||
The ordinary-player port does not fabricate PSR status. It applies the exact
|
||||
ownership/name rule; an eventual PSR player-description capability can add the
|
||||
retail override without changing this transaction.
|
||||
|
||||
For hooks, the appraisal HookProfile is the source of truth for presentation:
|
||||
`AppraisalProfile::IsHookedItemInscribable` returns false when it is absent and
|
||||
otherwise returns bit 0. The live public description remains the source used by
|
||||
`SetInscriptionEditableState`, matching the two retail functions rather than
|
||||
merging them into one guessed rule.
|
||||
|
||||
Noneditable mouse presses report retail's exact reason:
|
||||
|
||||
```text
|
||||
if scribe is nonempty and differs from local player:
|
||||
"Only <scribe> can change the inscription"
|
||||
else if object is absent or not owned:
|
||||
"Item must be in your inventory to inscribe."
|
||||
else if BF_INSCRIBABLE is absent:
|
||||
"This item is not inscribable."
|
||||
```
|
||||
|
||||
## Inscription edit transaction
|
||||
|
||||
```text
|
||||
on inscription focus gained:
|
||||
if scribe is empty:
|
||||
switch to the normal editing state
|
||||
clear "<Inscribe here>"
|
||||
signature = "--" + local player name
|
||||
|
||||
on inscription focus lost:
|
||||
if current object id == 0:
|
||||
return
|
||||
|
||||
text = current field text
|
||||
skipSend = text is empty and original scribe is empty
|
||||
if not skipSend and text != oldInscription:
|
||||
send CM_Writing.Event_SetInscription(object id, text)
|
||||
|
||||
if text is empty:
|
||||
restore unfocused state
|
||||
field = "<Inscribe here>"
|
||||
signature = ""
|
||||
scribe name/account = ""
|
||||
else:
|
||||
scribe name = local player name
|
||||
signature = "--" + local player name
|
||||
|
||||
oldInscription = text
|
||||
```
|
||||
|
||||
`CM_Writing::Event_SetInscription` sends a normal UI-counter GameAction:
|
||||
|
||||
```text
|
||||
u32 0xF7B1 GameAction envelope
|
||||
u32 uiCounter
|
||||
u32 0x00BF SetInscription
|
||||
u32 objectGuid
|
||||
String16L text CP-1252, padded to a four-byte boundary
|
||||
```
|
||||
|
||||
There is no successful server reply in retail captures. The client therefore
|
||||
updates its field/signature optimistically after sending; ACE deliberately
|
||||
implements the same behavior.
|
||||
|
||||
## Remaining slice boundary
|
||||
|
||||
The request lifetime, exact packet flags, independent floaty window,
|
||||
inscription permission/edit/write transaction, subview choice, authored outer
|
||||
layout, basic report content, scrollbar ownership, and combat refresh are in
|
||||
scope. Retail's exact 3D object/creature preview, exhaustive specialized
|
||||
`ItemExamineUI` detail branches, selection-follow preference, and PSR-only
|
||||
scribe-account/override behavior remain explicit AP-110 work.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue