fix(paperdoll): port quest-gated Aetheria slots

Add the three authored blue, yellow, and red sigil backgrounds and drive their visibility from player PropertyInt.AetheriaBitfield bits 1/2/4 at login and on live updates, matching gmPaperDollUI::UpdateAetheria. Include the sigil equip masks in the shared slot table and narrow AP-108.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 09:55:20 +02:00
parent 1be18cc4db
commit edc9be3008
11 changed files with 208 additions and 16 deletions

View file

@ -2,8 +2,8 @@
Date: 2026-07-13
Scope: the empty-cell art for the 21 currently supported equipment lists in
`gmPaperDollUI`. This corrects the earlier visual inference that the slots had no
Scope: the empty-cell art for all 24 equipment lists in `gmPaperDollUI`, including
the three quest-unlocked Aetheria sigil locations. This corrects the earlier visual inference that the slots had no
per-location art. The paperdoll layout elements themselves inherit the same ItemList
base, but retail creates their cells from distinct `UIElement_UIItem` prototypes in
the shared catalog `0x21000037`.
@ -72,6 +72,9 @@ UIItem empty draw:
| `0x100001E3` | UpperLegWear | `0x1000044F` | `0x060032C4` |
| `0x1000058E` | TrinketOne | `0x1000058F` | `0x06006A6C` |
| `0x100005E9` | Cloak | `0x100005EA` | `0x0600708F` |
| `0x10000595` | SigilOne / blue | `0x10000592` | `0x06006BEF` |
| `0x10000596` | SigilTwo / yellow | `0x10000593` | `0x06006BF0` |
| `0x10000597` | SigilThree / red | `0x10000594` | `0x06006BF1` |
| `0x100005AB` | HeadWear | `0x100005B4` | `0x06006D7F` |
| `0x100005AC` | ChestArmor | `0x100005B5` | `0x06006D7B` |
| `0x100005AD` | AbdomenArmor | `0x100005B6` | `0x06006D79` |
@ -82,9 +85,23 @@ UIItem empty draw:
| `0x100005B2` | LowerLegArmor | `0x100005BB` | `0x06006D83` |
| `0x100005B3` | FootWear | `0x100005BD` | `0x06006D85` |
The three Aetheria lists remain outside the current controller scope (AP-108). Their
authored backgrounds are blue/yellow/red prototypes `0x10000592..94`, but this fix
does not make those otherwise unimplemented slots reachable.
## Aetheria unlock visibility
`gmPaperDollUI::UpdateAetheria @ 0x004A3E50` reads player int quality `0x142`
(`PropertyInt.AetheriaBitfield`, 322). `RecvNotice_PlayerDescReceived @ 0x004A43E0`
applies the login value, and `OnQualityChanged @ 0x004A4490` reapplies it after a
live quest-completion update:
```text
bits = player.intQuality(0x142, default=0)
blue.visible = (bits & 1) != 0
yellow.visible = (bits & 2) != 0
red.visible = (bits & 4) != 0
```
ACE independently confirms the property is `[SendOnLogin] AetheriaBitfield = 322`
and defines the same Blue=1, Yellow=2, Red=4 flags. The existing generic private
PropertyInt wire path (`0x02CD`) already stores the live value on the player object.
## Port mapping
@ -94,7 +111,7 @@ does not make those otherwise unimplemented slots reachable.
- `ItemListCellTemplate.ResolvePrototypeEmptySprite` reuses the already-shipped
inheritance-aware `ItemSlot_Empty` resolver instead of hardcoding surface IDs in
the controller.
- `RetailUiRuntime` and UI Studio resolve the 21 surfaces from the live DAT once at
- `RetailUiRuntime` and UI Studio resolve the 24 surfaces from the live DAT once at
bind time and inject them into the controller. A missing authored surface is a startup
error rather than a silently generic slot; the old inventory-grid sprite remains only
for isolated controller bindings that do not supply the paperdoll catalog map.