fix(inventory): sequence secondary wield blockers
Preserve retail AmmoType from CreateObject and port BlocksUseOfShield so bow, caster, and two-handed switches remove incompatible shields, while mismatched missile ammo is also returned to the pack. Each blocker remains server-confirmed before AutoWield re-enters. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
17b5712d53
commit
815ce0dec4
14 changed files with 206 additions and 16 deletions
|
|
@ -211,7 +211,7 @@ AP-94..AP-112 for the confirmed retail-UI completion gaps.
|
|||
| AP-105 | **PARTIAL 2026-07-10 (Wave 2.2)** — inherited scrollbar media/roles now come from DAT (decrement/top `0x06004C69`, increment/bottom `0x06004C6C`). Retained chat still lacks complete tab/filter/unread, social availability, squelch, and focus-opacity behavior; a second ChatVM still loses FPS/position providers. | `src/AcDream.App/UI/Layout/DatWidgetFactory.cs`; `ChatWindowController.cs`; chat mount in `GameWindow.cs` | Shared log/send path, wrapping, scrollbar roles, and outer maximize geometry work; Wave 5 consolidates remaining chat state | Commands degrade, tabs are no-ops, moderation/channel state is wrong, and focus visuals diverge | `gmMainChatUI @ 0x004CCCC0..0x004CE2A0`; `UIElement_Scrollbar::OnSetAttribute @ 0x004714D0`; `ChatInterface` methods |
|
||||
| AP-106 | The retained UI has no external/ground-container window lifecycle, while the original owned-side-bag `NoLongerViewingContents` premise was incorrect (#196) | `src/AcDream.App/UI`; window runtime; absent external-container controller | Owned inventory navigation remains usable and must not gain an unproven `0x0195` send; Wave 2/6 adds lifecycle ownership and the separate external surface | External container replacement/close cannot notify the server exactly once; adding the packet to owned bag close would itself diverge from the named retail call graph | `ClientUISystem.groundObject`; `CM_Inventory::Event_NoLongerViewingContents @ 0x006ABC50`; `docs/research/2026-07-10-retail-panel-behavior-pseudocode.md` |
|
||||
| ~~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 Aetheria, full `AutoWieldIsLegal`/dual-wield rules, incompatible-shield/ammo blocker sequencing, double-click examine/drag from the doll, and body-part selection lighting | `src/AcDream.App/UI/Layout/PaperdollController.cs`; `src/AcDream.App/UI/AutoWieldController.cs` | Basic equip slots and live doll work; inventory double-click now faithfully replaces the occupied primary weapon-ready group through server-confirmed dequip→wield in both peace and war | Special slots, illegal/off-hand cases, incompatible shield/ammo auto-removal, doll examine/drag, and selection lighting still differ functionally | `CPlayerSystem::AutoWield @ 0x00560A60`; `gmPaperDollUI @ 0x004A3590..0x004A5F90`; `InventoryPlacement::DetermineHigherPriority` |
|
||||
| AP-108 | Paperdoll/AutoWield still omit Aetheria, full `AutoWieldIsLegal`/dual-wield rules, double-click examine/drag from the doll, and body-part selection lighting | `src/AcDream.App/UI/Layout/PaperdollController.cs`; `src/AcDream.App/UI/AutoWieldController.cs` | Basic equip slots and live doll work; inventory double-click now faithfully sequences the primary weapon, incompatible shield, and mismatched ammo blockers through server-confirmed dequip→wield in both peace and war | Special slots, illegal/off-hand cases, doll examine/drag, and selection lighting still differ functionally | `CPlayerSystem::AutoWield @ 0x00560A60`; `ACCWeenieObject::BlocksUseOfShield @ 0x0055D3E0`; `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, spellbook/effects/favorite spell bars, residual social/examine/floating chat, quests/map/vitae/options/smartbox, vendor/trade/salvage/tinkering, and D.6 nameplates/floaters | D.5/D.6 roadmap; retained layout registration set | Basic `gmCombatUI` now covers the active M2 melee/missile loop; Wave 10 lands each remaining surface against authoritative state | Large portions of retail gameplay still have no production UI | Named `gm*UI::PostInit` methods and 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` |
|
||||
|
|
|
|||
|
|
@ -495,7 +495,7 @@ behavior. Estimated 17–26 days focused work, 3–5 weeks calendar.
|
|||
- **✓ SHIPPED — Wave 4.4c exact selected-health policy.** Core ports `ObjectIsAttackable @ 0x0056A600`; CreateObject preserves second-header PetOwner; toolbar player/pet composition is exact. Self, pets, and Free-PK creatures now query health while friendly NPCs and attackable non-creatures remain name-only. AP-46 retired. The world/radar policy matrix and exact DAT paperdoll body-map + upper-item-priority route passed live 2026-07-11.
|
||||
- **✓ SHIPPED — Wave 4.4d toolbar launchers + Use/Examine.** All seven authored launchers are discovered through their DAT panel-id attribute; mounted Inventory/Character panels toggle through the registry and the other five buttons are ghosted. Typed window-visibility events own Highlight/Normal state. Use and Examine act on selection or enter their one-shot retail target modes, with exact Appraise wire dispatch and retail cursors. Warning-free App build and 4,747-pass / 5-skip Release suite are green; the connected live gate passed 2026-07-11. AP-101 is narrowed to the remaining ammo-number display.
|
||||
- **Wave 4.4e implemented — exact missile ammo number (live gate pending).** Pure Core reproduces retail's thrown-weapon-vs-separate-ammo resolution over the ordered player equipment list and its zero-to-one count normalization. Relevant equipment/stack events update authored missile indicator `0x10000194` with the DAT font. Warning-free Release build and 4,754-pass / 5-skip suite are green; AP-101 is retired.
|
||||
- **Wave 4.5 implemented — retail primary-weapon switching (live gate pending).** Inventory double-click now routes through a focused `AutoWieldController`: the occupied `0x03500000` weapon-ready group is returned to the player container, the controller waits for authoritative `InventoryPutObjInContainer`, then sends `GetAndWieldItem` for the requested bow/sword/caster/two-hander. The same transaction runs in peace and war; ACE owns the latter's old-stance → peace → new-stance motion chain. Player PropertyInt 40 now updates `CombatState`, keeping toolbar/combat UI synchronized with ACE's selected Melee/Missile/Magic stance. Research: `docs/research/2026-07-12-retail-weapon-switch-pseudocode.md`.
|
||||
- **Wave 4.5 implemented — retail primary-weapon switching (live gate pending).** Inventory double-click now routes through a focused `AutoWieldController`: the occupied `0x03500000` weapon-ready group is returned to the player container, followed when necessary by an incompatible shield or mismatched ammo; each blocker waits for authoritative `InventoryPutObjInContainer` before the next step, then `GetAndWieldItem` equips the requested bow/sword/caster/two-hander. `CreateObject` retains exact `AmmoType` for the compatibility decision. The same transaction runs in peace and war; ACE owns the latter's old-stance → peace → new-stance motion chain. Player PropertyInt 40 now updates `CombatState`, keeping toolbar/combat UI synchronized with ACE's selected Melee/Missile/Magic stance. Research: `docs/research/2026-07-12-retail-weapon-switch-pseudocode.md`.
|
||||
- **M2 held-object parenting shipped and live-gated 2026-07-11.** The combat toggle now ports `GetDefaultCombatMode` over ordered equipped contents, so a bow requests Missile instead of the old hardcoded Melee. CreateObject preserves parent/placement/timestamp fields, `0xF749` ParentEvent is handled, and `EquippedChildRenderController` renders the weapon as a separate child composed from the animated hand part + holding frame + child placement frame. Live gate passed: bow selected missile stance, rendered in-hand, followed animation, unequipped cleanly, and melee remained correct. App Release builds with zero warnings; the full 4,765-pass / 5-skip suite is green. AP-111 is retired; research: `docs/research/2026-07-11-combat-default-and-parent-event-pseudocode.md`.
|
||||
- **M2 local attack receive funnel implemented 2026-07-11; live gate pending.** Retail `ExecuteAttack` only sends the request; ACE chooses the concrete melee/missile action and returns it in a non-autonomous mt-0 `UpdateMotion`. The local branch now runs that state through the same constructor-defaulted `MoveToInterpretedState` funnel and 15-bit action-stamp gate as remotes, then applies sticky/long-jump tails. The old local-only direct `Commands[]` replay is deleted. Shared conversion lives in `InboundInterpretedMotionFactory`; research: `docs/research/2026-07-11-local-combat-motion-pseudocode.md`.
|
||||
- **M2 basic retail combat bar implemented 2026-07-11; corrective live visual gate pending.** Production mounts authored `gmCombatUI` LayoutDesc `0x21000073`, shows it only for Melee/Missile, and routes mouse plus keyboard through one `CombatAttackController`. Corrections include the authored wider centered dark-red child range (accepted IA-20), full-width left-to-right bright live attack-charge feedback, exact Speed-left/Power-right justification, silent control-only `AttackDone(ActionCancelled)`, target-frame Keep in View with manual orbit, and persistent corpse motion: the AP-80 velocity-only NPC adaptation can now replace only Ready/Walk/Run, never authoritative Dead/actions. `CombatTargetController` ports the selection-cleared AutoTarget consumer, so a selected creature's authoritative Dead motion clears it and selects the nearest eligible creature when enabled. The 2026-07-12 replacement-corpse correction unifies both multi-frame and static/reactive spawns behind retail's CreateObject lifecycle: apply the wire's Dead state while detached, then `MotionTableManager::HandleEnterWorld` strips Ready→Dead links before the first in-world tick; multiple corpses remaining fallen passed the live user gate that day. Follow-up #205 makes the toolbar read the final canonical selection after a reentrant Auto Target notice and restricts automatic candidates to hostile non-player monsters (intentional PK-edge divergence IA-19); that live gate also passed 2026-07-12. Research: `docs/research/2026-07-11-retail-combat-bar-pseudocode.md`, `docs/research/2026-07-11-combat-target-camera-pseudocode.md`, `docs/research/2026-07-12-death-and-auto-target-pseudocode.md`; AP-24/AP-95 retired, AP-80 narrowed, AP-110 narrowed, AP-112 records the remaining attack-start and exact trained-Recklessness seams.
|
||||
|
|
|
|||
|
|
@ -456,8 +456,9 @@ include dungeons.
|
|||
CreateObject/ParentEvent child attachment and per-frame hand-follow rendering.
|
||||
- **L.1c inventory weapon switching (implemented 2026-07-12; live gate pending)** —
|
||||
inventory double-click ports retail's two-stage `AutoWield`: return the occupied
|
||||
primary weapon to the main pack, wait for the server move confirmation, then
|
||||
wield the requested bow/sword/caster/two-hander. The shared transaction works
|
||||
primary weapon to the main pack, then any incompatible shield/ammo, waiting
|
||||
for every server move confirmation before wielding the requested
|
||||
bow/sword/caster/two-hander. The shared transaction works
|
||||
in peace and war; ACE owns stance-specific motions and its PropertyInt 40 update
|
||||
now drives the client `CombatState`.
|
||||
- **L.1c local attack receive path (implemented 2026-07-11; live gate pending)** —
|
||||
|
|
|
|||
|
|
@ -64,6 +64,13 @@ auto_wield(item):
|
|||
send PutItemInContainer(blocker.id, player.id, placement = 0)
|
||||
return true
|
||||
|
||||
if BlocksUseOfShield(item) and a shield is equipped:
|
||||
begin the same confirmed blocker transaction for the shield
|
||||
|
||||
if item.ammoType is not AMMO_NONE
|
||||
and equipped ammo has a different ammoType:
|
||||
begin the same confirmed blocker transaction for the ammo
|
||||
|
||||
send_wield(item, desiredMask)
|
||||
return true
|
||||
|
||||
|
|
@ -101,8 +108,8 @@ render paths consume the server events.
|
|||
|
||||
## Known remaining retail surface
|
||||
|
||||
This port covers the primary weapon-ready group requested here. Retail
|
||||
`AutoWield` also has extra blocker logic for incompatible shields and missile
|
||||
ammo, plus its full `AutoWieldIsLegal` requirement checks. Those pre-existing
|
||||
paperdoll/auto-wield gaps remain tracked by divergence row AP-108 rather than
|
||||
being guessed from incomplete item properties.
|
||||
This port covers the primary weapon-ready group plus retail's secondary
|
||||
incompatible-shield and mismatched-ammo blockers. `CreateObject` now retains
|
||||
the exact `AmmoType` needed for those decisions. Full `AutoWieldIsLegal`,
|
||||
Aetheria, and dual-wield/off-hand rules remain tracked by divergence row
|
||||
AP-108.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue