feat(ui): port retail selected-stack quantity
Bind the authored stack count entry and horizontal slider to one Core split-quantity owner, preserve retail count-first naming and exact 1000-step rounding, refresh on stack changes, and consume the selected amount during merges. Conformance covers the production DAT fixture and retained pointer/focus paths. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
dc1649c493
commit
a20e5c68c7
19 changed files with 595 additions and 51 deletions
|
|
@ -463,10 +463,10 @@ AttemptMerge(sourceId, targetId, quiet): // 0x005878F0
|
|||
return true
|
||||
```
|
||||
|
||||
acdream's selected-object stack entry/slider is still absent under AP-101, so the
|
||||
current inventory merge path requests the whole source stack and lets the same
|
||||
retail capacity clamp limit the transfer. Once the shared split-quantity owner
|
||||
lands, it supplies `requested` without changing legality or wire ordering.
|
||||
acdream now has one Core-owned split-quantity state shared by the selected-object
|
||||
entry/slider and inventory merge. A selected source supplies that quantity to
|
||||
`AttemptMerge`; an unselected source retains retail's full-source default. Legality,
|
||||
capacity clamping, and wire ordering are unchanged.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -507,7 +507,7 @@ HandleSelectionChanged(): // 0x004BF380
|
|||
if object missing: return
|
||||
|
||||
set selected name:
|
||||
normal object: name, or formatted name + count when stacked
|
||||
normal object: name, or `"%d %hs"` (count then name) when stacked
|
||||
owned coinstack: formatted coin total/name path
|
||||
|
||||
splitSize = 1
|
||||
|
|
@ -567,13 +567,22 @@ RecvNotice_UpdateItemMana(id, fraction, valid): // 0x004BD0C0
|
|||
- On entry deactivation, parse unsigned text, clamp to `1..maxSplitSize`, rewrite
|
||||
the text if clamped, update `GenItemHolder::splitSize`, update slider attribute
|
||||
`0x86 = splitSize/maxSplitSize`, and broadcast the stack-slider notice.
|
||||
- Slider message `0xA` maps its normalized value to an integer in
|
||||
`1..maxSplitSize`, stores it, rewrites the entry, and broadcasts the notice.
|
||||
- `UIElement_Scrollbar::SetScrollbarPosition @ 0x00470EC0` clamps the normalized
|
||||
position to `[0,1]`, multiplies by `1000.0f`, truncates through `_ftol2`, and
|
||||
broadcasts that integer as message `0xA` parameter 1.
|
||||
- `gmToolbarUI::ListenToElementMessage @ 0x004BEFE0..0x004BF041` converts the
|
||||
message exactly as follows, stores it, rewrites the entry, and broadcasts the
|
||||
stack-slider notice:
|
||||
|
||||
**Unresolved:** Binary Ninja lost the exact floating expression immediately before
|
||||
the slider's `1 - _ftol2()` conversion at `0x004BF02D`. The clamp, endpoints, and
|
||||
text update are exact, but the intermediate rounding direction must be recovered
|
||||
from Ghidra/disassembly before writing conformance vectors.
|
||||
```text
|
||||
positionMillis = truncate(clamp01(sliderRatio) * 1000)
|
||||
splitSize = clamp(1 + floor(positionMillis * maxSplitSize / 1000),
|
||||
1, maxSplitSize)
|
||||
```
|
||||
|
||||
The apparently odd extra one is verbatim retail behavior. Static cdb disassembly
|
||||
of the matching v11.4186 binary also pins the stack-name format string at
|
||||
`0x007B4738` to `"%d %hs"` and the numeric-entry format at `0x007A0184` to `"%d"`.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue