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
|
|
@ -13,9 +13,15 @@ retained examination window.
|
|||
- `gmExaminationUI::SetActiveExamineUI @ 0x004AB420`
|
||||
- `gmExaminationUI::UseTime @ 0x004AB530`
|
||||
- `gmExaminationUI::SetAppraiseInfo @ 0x004ADAE0`
|
||||
- `BasicCreatureExamineUI::Init @ 0x004AB9C0`
|
||||
- `BasicCreatureExamineUI::BasicCreatureExamineUI @ 0x004ACD30`
|
||||
- `BasicCreatureExamineUI::SetLevelValueText @ 0x004B3E70`
|
||||
- `BasicCreatureExamineUI::SetAppraiseInfo @ 0x004B3F70`
|
||||
- `CreatureExamineUI::SetAppraiseInfo @ 0x004B3FF0`
|
||||
- `CharExamineUI::SetAppraiseInfo @ 0x004B45F0`
|
||||
- `AttributeInfoRegion::Update @ 0x004F1D90`
|
||||
- `Attribute2ndInfoRegion::Update @ 0x004F1E80`
|
||||
- `AppraisalSystem::InqCreatureDisplayName @ 0x005B59E0`
|
||||
- `ItemExamineUI::SetAppraiseInfo @ 0x004B72B0`
|
||||
- `ItemExamineUI::HandleInscriptionGainingFocus @ 0x004AC0E0`
|
||||
- `ItemExamineUI::HandleInscriptionMousePresses @ 0x004AC230`
|
||||
|
|
@ -189,6 +195,79 @@ When the examination window's selection-follow option is active, a selection
|
|||
change appraises the new selected GUID; clearing selection hides the window.
|
||||
That optional retail preference remains outside this slice.
|
||||
|
||||
## Creature presentation
|
||||
|
||||
`BasicCreatureExamineUI` binds viewport `0x10000148`, list box `0x10000149`,
|
||||
level value `0x1000014C`, and creature display name `0x1000014E`. Its stat
|
||||
rows are instances of LayoutDesc `0x2100006B` template `0x10000166`, whose
|
||||
label and value fields are `0x1000012A` and `0x1000012B`.
|
||||
|
||||
```text
|
||||
on creature appraisal:
|
||||
level = int property 25
|
||||
level text = decimal level when positive, otherwise "???"
|
||||
|
||||
creatureType = int property 2
|
||||
display name = EnumMapper 0x2200000E[creatureType]
|
||||
replace underscores in display name with spaces
|
||||
|
||||
clear stat list
|
||||
append rows in this exact order:
|
||||
Strength primary attribute 1
|
||||
Endurance primary attribute 2
|
||||
Coordination primary attribute 4
|
||||
Quickness primary attribute 3
|
||||
Focus primary attribute 5
|
||||
Self primary attribute 6
|
||||
Health current secondary 2 / maximum secondary 1, show percent
|
||||
Stamina current secondary 4 / maximum secondary 3
|
||||
Mana current secondary 6 / maximum secondary 5
|
||||
```
|
||||
|
||||
Successful primary values are decimal integers. Successful Health is
|
||||
`current/max (percent %)`; Stamina and Mana are `current/max`. On a failed
|
||||
assessment, Health still shows the percentage when both values are known,
|
||||
while every other row is `???`. The profile highlight/color bitfields select
|
||||
one of retail's four authored FontInfo entries (normal, beneficial,
|
||||
detrimental, or incomplete); exact FontInfo-list binding remains AP-110.
|
||||
|
||||
The animated preview is a private `CreatureMode`, not the live world object:
|
||||
|
||||
```text
|
||||
clear the previous private creature
|
||||
clone selected CPhysicsObj with makeObject
|
||||
set clone heading to 191.367905 degrees
|
||||
query the clone bounding box
|
||||
|
||||
width = bbox.max.x - bbox.min.x
|
||||
depth = bbox.max.y - bbox.min.y
|
||||
height = bbox.max.z - bbox.min.z
|
||||
viewportHeightOverWidth = viewport.height / viewport.width
|
||||
fittedVerticalSpan = max(height, width * viewportHeightOverWidth)
|
||||
center = (bbox.min + bbox.max) / 2
|
||||
camera.position = (
|
||||
center.x,
|
||||
center.y - (fittedVerticalSpan * 1.20710683 + depth / 2),
|
||||
center.z)
|
||||
camera.direction = identity (+Y)
|
||||
|
||||
viewport light:
|
||||
type = DISTANT_LIGHT
|
||||
intensity = 2
|
||||
direction = (0.3, 1.9, 0.65)
|
||||
|
||||
insert clone into the private CreatureMode
|
||||
```
|
||||
|
||||
ACDream's modern rendering equivalent uses the same isolated render-to-texture
|
||||
owner as the inventory paperdoll. The examination clone has its own stable
|
||||
render identity, fixed heading and retail camera/light, while its mesh-part
|
||||
transforms are refreshed from the live target each frame so its current
|
||||
animation is visible without registering a second gameplay entity. Retail's
|
||||
clone instead advances the motion state copied by
|
||||
`CPhysicsObj::MorphToExistingObject`; that narrow sequencer-ownership
|
||||
adaptation is recorded under AP-92.
|
||||
|
||||
## Item presentation order
|
||||
|
||||
`ItemExamineUI::SetAppraiseInfo` clears and rebuilds the authored item text in
|
||||
|
|
@ -333,7 +412,9 @@ implements the same behavior.
|
|||
|
||||
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.
|
||||
layout, ordered creature stats, animated creature preview, scrollbar
|
||||
ownership, and combat refresh are in scope. Retail's item-object preview,
|
||||
exhaustive specialized `ItemExamineUI` detail branches, creature
|
||||
extra-rating regions, exact appraisal FontInfo-list selection,
|
||||
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