# Retail toolbar ammunition pseudocode ## Named-retail oracle - `gmToolbarUI::UpdateAmmoID @ 0x004BF210` - `gmToolbarUI::UpdateAmmoNumber @ 0x004BE9E0` - `gmToolbarUI::RecvNotice_ServerSaysMoveItem @ 0x004BF2B0` - `gmToolbarUI::RecvNotice_ItemAttributesChanged @ 0x004BF8F0` - `ACCWeenieObject::GetObjectAtLocation @ 0x0058CE00` The Binary Ninja text corrupts the second `GetObjectAtLocation` constant into a string literal. The surrounding branch, retail `INVENTORY_LOC` header, ACE `EquipMask`, and holtburger equipment model agree that the two locations are `MISSILE_WEAPON_LOC = 0x00400000` and `MISSILE_AMMO_LOC = 0x00800000`. ## Literal pseudocode ```text UpdateAmmoID: oldAmmoID = ammoID ammoID = 0 player = GetWeenieObject(playerID) if player exists: weaponID = player.GetObjectAtLocation(MISSILE_WEAPON_LOC, priority=0) if weaponID != 0: weapon = GetWeenieObject(weaponID) if weapon exists and weapon.maxStackSize > 1: ammoID = weaponID if ammoID == 0: ammoID = player.GetObjectAtLocation(MISSILE_AMMO_LOC, priority=0) if ammoID != oldAmmoID: UpdateAmmoNumber() UpdateAmmoNumber: text = "" ammo = GetWeenieObject(ammoID) if ammo exists: count = ammo.stackSize if count == 0: count = 1 text = decimal(count) SetText(toolbarElement 0x10000194, text) ``` `GetObjectAtLocation` walks the player's ordered inventory-placement list and returns the first entry whose location mask intersects the requested mask. Stackable missile weapons therefore display their own count (thrown weapons); ordinary launchers display the separately equipped ammunition stack. Move notices touching player equipment locations `0x00C00000` recompute the ammo object ID. Attribute/stack changes for the current ammo object refresh its number. Player-description arrival also performs an initial resolution. ## Port boundary `ToolbarAmmoPolicy` is pure Core logic over the ordered player placement list. `ToolbarController` owns repository event subscriptions and writes the resulting decimal label into authored element `0x10000194`. Missing ammo is an empty label.