# Retail item useability and AutoWear rejection Date: 2026-07-23 ## Retail anchors - `ItemUses::ItemUses @ 0x004FCCB0` - `ItemUses::IsUseable @ 0x004FCCC0` - `PublicWeenieDesc::Reset @ 0x005ACC70` - `PublicWeenieDesc::UnPack @ 0x005AD470` - `ItemHolder::DetermineUseResult @ 0x00588460` - `ItemHolder::UseObject @ 0x00588A80` - `CPlayerSystem::UsingItem @ 0x00562F70` - `CPlayerSystem::AutoWearIsLegal @ 0x0055EF40` - `CPlayerSystem::AutoWear @ 0x005601C0` - `ACCWeenieObject::GetObjectAtLocation @ 0x0058CE00` The named pseudo-C is the behavioral oracle. The matching v11.4186 binary was also inspected because an older project note interpreted `ItemUses::IsUseable` as a nonzero test. The actual instructions are: ```text 004fccc0 mov eax,[ecx] 004fccc2 not eax 004fccc4 and eax,1 004fccc7 ret ``` Therefore the method tests only `USEABLE_NO` (bit zero). A zero-valued `ITEM_USEABLE` is usable; `USEABLE_NEVER_WALK` is a movement modifier and does not make the object unusable. The literal AutoWear rejection at `0x007CC868` is: ```text You must remove your %s to wear that ``` The staged ACE, holtburger, and ACViewer reference directories are currently empty in this checkout. Their established roles were still checked: ACE owns the authoritative use/wield outcome, while the two client references do not replace the retail UI-side legality and notice oracle. No server behavior is being inferred or moved client-side here. ## Pseudocode ```text ItemUses.IsUseable(): return (useableBitfield & USEABLE_NO) == 0 ``` `PublicWeenieDesc::Reset` zeros the useability field. `UnPack` replaces it only when the optional useability word is present. Consequently an absent wire word and an explicitly packed zero both have retail `USEABLE_UNDEF` value zero and both pass `IsUseable`. For a direct-use item, `ItemHolder::UseObject` then sends `CM_Inventory::Event_UseEvent`, increments the UI busy count, and calls `CPlayerSystem::UsingItem`. `Event_UseEvent` itself is the network send (`0xF7B1/0x36`); the latter function handles local pickup/wield/container presentation. Therefore neither an owned item nor a world object may be held behind a client-side movement completion. ACE owns the authoritative approach chain. ```text AutoWearIsLegal(itemId, out alreadyWorn, silent): alreadyWorn = false if player is not ready for an inventory request: return false item = GetWeenieObject(itemId) if item is null: return false if (item.validLocations & 0x08007FFF) == 0: return false if (item.priority & playerSystem.clothingPriorityMask) == 0: return true player = GetWeenieObject(playerId) if player contains item at a worn location: alreadyWorn = true if not silent: if alreadyWorn: display "The is already being worn" else: occupied = playerSystem.inventoryMask & item.validLocations blocker = player.GetObjectAtLocation(occupied, item.priority) if blocker exists: display "You must remove your to wear that" return false ``` ```text AutoWear(itemId, out alreadyWorn, silent): if not AutoWearIsLegal(itemId, alreadyWorn, silent): return false item = GetWeenieObject(itemId) if item exists: item.UIAttemptWield(item.validLocations) return true ``` ## Port boundary - `ItemUseability.IsUseable` is the one Core implementation of the low-bit rule. Toolbar enablement, item activation, and world interaction consume it. - `ItemInteractionController` remains the shared double-click and toolbar-hand path. A zero-valued carried gem such as Blackmoor's Favor therefore emits the ordinary Use request directly from its inventory identity; it is never sent through the world-approach query. ACE remains authoritative for its spell and consumption outcome. - `SelectionInteractionController` sends accepted ordinary Use immediately for both owned and spatial objects. It does not install speculative local TurnToObject/MoveToObject movement; ACE's authoritative movement packets use the shared retail `MoveToManager`. - `AutoWieldController` remains the shared inventory/paperdoll equip owner. It resolves AutoWear blockers from `ClientObjectTable`'s retail-ordered equipment projection and emits the retail literal through system chat. - Weapon replacement is unchanged. Retail automatically moves primary weapon, incompatible shield, and incompatible ammunition blockers, while AutoWear rejects overlapping clothing/armor and tells the player what to remove.