mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-08-12 12:18:32 -04:00
Fix Save Editor inventory edits leaving C/D-pad buttons desynced (#7008)
The Save Editor's Inventory tab writes gSaveContext.inventory.items[] directly, but a C/D-pad item button mirrors the slot it points at (buttonItems[i] == items[cButtonSlots[i-1]]). That derived value was never refreshed, so e.g. emptying a bottle assigned to a button left the button showing its old contents -- a desync the game's equip/inventory consistency then trips on at the next age swap or bottle update. Re-sync any button pointing at an edited slot after the write. Equipment assigned to a button stores an equipment-page index in cButtonSlots (>= inventory size), so it never matches an inventory slot and is left untouched. Includes a default-on "Keep C/D-pad buttons in sync" checkbox (mirroring "Restrict to valid items") so inventory edits can intentionally leave a slot desynced from its button for RBA practice/debugging. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -522,6 +522,19 @@ void DrawBGSItemFlag(uint8_t itemID) {
|
||||
ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1));
|
||||
}
|
||||
|
||||
// Re-sync any C/D-pad button that mirrors an edited inventory slot (buttonItems[i] == items[cButtonSlots[i-1]]),
|
||||
// so a raw item edit doesn't leave the button showing stale contents.
|
||||
static void SyncButtonItemsForSlot(uint8_t slot) {
|
||||
for (size_t i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||
if (gSaveContext.equips.cButtonSlots[i - 1] == slot) {
|
||||
gSaveContext.equips.buttonItems[i] = gSaveContext.inventory.items[slot];
|
||||
if (gPlayState != nullptr) {
|
||||
Interface_LoadItemIcon1(gPlayState, static_cast<u16>(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawInventoryTab() {
|
||||
static bool restrictToValid = true;
|
||||
|
||||
@@ -529,6 +542,11 @@ void DrawInventoryTab() {
|
||||
"Restrict to valid items", &restrictToValid,
|
||||
checkboxOptionsBase.Tooltip("Restricts items and ammo to only what is possible to legally acquire in-game"));
|
||||
|
||||
static bool syncButtons = true;
|
||||
Checkbox("Keep C/D-pad buttons in sync", &syncButtons,
|
||||
checkboxOptionsBase.Tooltip("Refresh a C or D-pad button when its inventory slot is edited. Disable to "
|
||||
"leave a slot and its button out of sync (e.g. to set up RBA)."));
|
||||
|
||||
for (int y = 0; y < 4; y++) {
|
||||
for (int x = 0; x < 6; x++) {
|
||||
static_assert(5 + 3 * 6 < sizeof(gSaveContext.inventory.items) / sizeof(gSaveContext.inventory.items[0]));
|
||||
@@ -579,8 +597,12 @@ void DrawInventoryTab() {
|
||||
PushStyleButton(Colors::DarkGray);
|
||||
if (ImGui::Button("##itemNonePicker",
|
||||
ImVec2(IMAGE_SIZE, IMAGE_SIZE) + ImGui::GetStyle().FramePadding * 2)) {
|
||||
if (selectedIndex != SLOT_NONE)
|
||||
if (selectedIndex != SLOT_NONE) {
|
||||
gSaveContext.inventory.items[selectedIndex] = ITEM_NONE;
|
||||
if (syncButtons) {
|
||||
SyncButtonItemsForSlot(selectedIndex);
|
||||
}
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
PopStyleButton();
|
||||
@@ -619,6 +641,9 @@ void DrawInventoryTab() {
|
||||
PopStyleButton();
|
||||
if (ret) {
|
||||
gSaveContext.inventory.items[selectedIndex] = slotEntry.id;
|
||||
if (syncButtons) {
|
||||
SyncButtonItemsForSlot(selectedIndex);
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
UIWidgets::Tooltip(SohUtils::GetItemName(slotEntry.id).c_str());
|
||||
|
||||
Reference in New Issue
Block a user