From 26ec69606a8728bc1b9608be9e5d7ab9e0c506a5 Mon Sep 17 00:00:00 2001 From: Josh Bodner <30329717+jbodner09@users.noreply.github.com> Date: Sat, 10 Dec 2022 12:39:26 -0800 Subject: [PATCH] Don't autosave immediately after purchasing from a shop (#2079) --- soh/include/z64save.h | 1 + soh/soh/SaveManager.cpp | 1 + soh/src/code/z_parameter.c | 8 +++++- soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c | 14 ++++++---- soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c | 1 + .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 23 ++++++++++++++++ soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c | 26 +++++++++++-------- soh/src/overlays/actors/ovl_En_Js/z_en_js.c | 11 ++++---- soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c | 6 +++-- .../overlays/actors/ovl_En_Ossan/z_en_ossan.c | 4 ++- soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c | 1 + 11 files changed, 71 insertions(+), 25 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 042c6c47d..77a25cd9c 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -245,6 +245,7 @@ typedef struct { /* 0x1420 */ s16 worldMapArea; /* 0x1422 */ s16 sunsSongState; // controls the effects of suns song /* 0x1424 */ s16 healthAccumulator; + /* 0x1426 */ u16 pendingSale; // #region SOH [General] // Upstream TODO: Move these to their own struct or name to more obviously specific to SoH /* */ uint32_t isMasterQuest; diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 321c02f35..89a17a8e0 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -542,6 +542,7 @@ void SaveManager::InitFileNormal() { gSaveContext.magicLevel = 0; gSaveContext.infTable[29] = 1; gSaveContext.sceneFlags[5].swch = 0x40000000; + gSaveContext.pendingSale = ITEM_NONE; //RANDOTODO (ADD ITEMLOCATIONS TO GSAVECONTEXT) } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 9e6654f91..78b916729 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2715,8 +2715,9 @@ u8 Item_CheckObtainability(u8 item) { return gSaveContext.inventory.items[slot]; } +// Save when receiving an item, unless it's purchased from a shop void PerformAutosave(PlayState* play, u8 item) { - if (CVar_GetS32("gAutosave", 0) && (play && play->sceneNum != SCENE_KENJYANOMA)) { + if (CVar_GetS32("gAutosave", 0) && (play != NULL) && (play->sceneNum != SCENE_KENJYANOMA) && (gSaveContext.pendingSale == ITEM_NONE)) { if (CVar_GetS32("gAutosaveAllItems", 0)) { Play_PerformSave(play); } else if (CVar_GetS32("gAutosaveMajorItems", 1)) { @@ -6301,6 +6302,11 @@ void Interface_Update(PlayState* play) { gSaveContext.rupees--; Audio_PlaySoundGeneral(NA_SE_SY_RUPY_COUNT, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } + if (gSaveContext.rupeeAccumulator == 0) { + u16 tempSaleItem = gSaveContext.pendingSale; + gSaveContext.pendingSale = ITEM_NONE; + PerformAutosave(play, tempSaleItem); + } } else { gSaveContext.rupeeAccumulator = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c index fb028d2f6..492842d1e 100644 --- a/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c +++ b/soh/src/overlays/actors/ovl_En_Dns/z_en_dns.c @@ -401,24 +401,28 @@ void EnDns_Talk(EnDns* this, PlayState* play) { } void func_809EFDD0(EnDns* this, PlayState* play) { + u16 pendingGetItemId; if (!gSaveContext.n64ddFlag || !this->scrubIdentity.isShuffled) { if (this->actor.params == 0x9) { if (CUR_UPG_VALUE(UPG_STICKS) < 2) { - func_8002F434(&this->actor, play, GI_STICK_UPGRADE_20, 130.0f, 100.0f); + pendingGetItemId = GI_STICK_UPGRADE_20; } else { - func_8002F434(&this->actor, play, GI_STICK_UPGRADE_30, 130.0f, 100.0f); + pendingGetItemId = GI_STICK_UPGRADE_30; } } else if (this->actor.params == 0xA) { if (CUR_UPG_VALUE(UPG_NUTS) < 2) { - func_8002F434(&this->actor, play, GI_NUT_UPGRADE_30, 130.0f, 100.0f); + pendingGetItemId = GI_NUT_UPGRADE_30; } else { - func_8002F434(&this->actor, play, GI_NUT_UPGRADE_40, 130.0f, 100.0f); + pendingGetItemId = GI_NUT_UPGRADE_40; } } else { - func_8002F434(&this->actor, play, this->dnsItemEntry->getItemId, 130.0f, 100.0f); + pendingGetItemId = this->dnsItemEntry->getItemId; } + gSaveContext.pendingSale = ItemTable_Retrieve(pendingGetItemId).itemId; + func_8002F434(&this->actor, play, pendingGetItemId, 130.0f, 100.0f); } else { GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(this->scrubIdentity.randomizerCheck, this->scrubIdentity.getItemId); + gSaveContext.pendingSale = itemEntry.itemId; GiveItemEntryFromActor(&this->actor, play, itemEntry, 130.0f, 100.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index 74ba1a476..11a73f7e6 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -205,6 +205,7 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) { case 2: // have 100 rupees and empty bottle Rupees_ChangeBy(-100); this->actor.flags &= ~ACTOR_FLAG_16; + gSaveContext.pendingSale = ItemTable_Retrieve(GI_POTION_BLUE).itemId; func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); this->actionFunc = EnDs_GiveBluePotion; return; diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 2c96f8f38..faf5f92db 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -794,11 +794,13 @@ s32 EnGirlA_CanBuy_Randomizer(PlayState* play, EnGirlA* this) { } void EnGirlA_ItemGive_Arrows(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Inventory_ChangeAmmo(ITEM_BOW, this->itemCount); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Bombs(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; switch (this->itemCount) { case 5: Item_Give(play, ITEM_BOMBS_5); @@ -817,6 +819,7 @@ void EnGirlA_ItemGive_Bombs(PlayState* play, EnGirlA* this) { } void EnGirlA_ItemGive_DekuNuts(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; switch (this->itemCount) { case 5: Item_Give(play, ITEM_NUTS_5); @@ -829,65 +832,78 @@ void EnGirlA_ItemGive_DekuNuts(PlayState* play, EnGirlA* this) { } void EnGirlA_ItemGive_DekuSticks(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_STICK); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Longsword(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; func_800849EC(play); gSaveContext.swordHealth = 8; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_HylianShield(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_SHIELD_HYLIAN); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_DekuShield(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_SHIELD_DEKU); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_GoronTunic(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_TUNIC_GORON); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_ZoraTunic(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_TUNIC_ZORA); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Health(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Health_ChangeBy(play, this->itemCount); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_MilkBottle(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_MILK_BOTTLE); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_WeirdEgg(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_WEIRD_EGG); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Unk19(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_Unk20(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_DekuSeeds(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Item_Give(play, ITEM_SEEDS_30); Rupees_ChangeBy(-this->basePrice); } void EnGirlA_ItemGive_BottledItem(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; switch (this->actor.params) { case SI_FISH: Item_Give(play, ITEM_FISH); @@ -927,6 +943,7 @@ void EnGirlA_ItemGive_Randomizer(PlayState* play, EnGirlA* this) { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex); GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); + gSaveContext.pendingSale = getItemEntry.itemId; if (getItemEntry.modIndex == MOD_NONE) { // RANDOTOD: Move this into Item_Give() or some other more central location if (getItemEntry.getItemId == GI_SWORD_BGS) { @@ -942,6 +959,7 @@ void EnGirlA_ItemGive_Randomizer(PlayState* play, EnGirlA* this) { } void EnGirlA_BuyEvent_ShieldDiscount(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; if (this->actor.params == SI_HYLIAN_SHIELD) { if (gSaveContext.infTable[7] & 0x40) { Rupees_ChangeBy(-(this->basePrice - sShieldDiscounts[(s32)Rand_ZeroFloat(7.9f)])); @@ -952,14 +970,17 @@ void EnGirlA_BuyEvent_ShieldDiscount(PlayState* play, EnGirlA* this) { } void EnGirlA_BuyEvent_GoronTunic(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_BuyEvent_ZoraTunic(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Rupees_ChangeBy(-this->basePrice); } void EnGirlA_BuyEvent_ObtainBombchuPack(PlayState* play, EnGirlA* this) { + gSaveContext.pendingSale = ItemTable_Retrieve(this->getItemId).itemId; Rupees_ChangeBy(-this->basePrice); // Normally, buying a bombchu pack sets a flag indicating the pack is now sold out @@ -1000,6 +1021,8 @@ void EnGirlA_BuyEvent_ObtainBombchuPack(PlayState* play, EnGirlA* this) { // The giving of the item is handled in ossan.c, and a fanfare is played void EnGirlA_BuyEvent_Randomizer(PlayState* play, EnGirlA* this) { ShopItemIdentity shopItemIdentity = Randomizer_IdentifyShopItem(play->sceneNum, this->randoSlotIndex); + GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheckWithoutObtainabilityCheck(shopItemIdentity.randomizerCheck, shopItemIdentity.ogItemId); + gSaveContext.pendingSale = getItemEntry.itemId; Flags_SetRandomizerInf(shopItemIdentity.randomizerInf); Rupees_ChangeBy(-this->basePrice); } diff --git a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c index abc870d30..c9f95bbfd 100644 --- a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -253,14 +253,16 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { } else { if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - GiveItemEntryFromActor(&this->actor, play, - Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE), 415.0f, 10.0f); - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); - gSaveContext.infTable[11] |= 2; - this->actionFunc = func_80A3DF00; + GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE); + gSaveContext.pendingSale = itemEntry.itemId; + GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f); + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); + gSaveContext.infTable[11] |= 2; + this->actionFunc = func_80A3DF00; } else { - func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); - this->actionFunc = func_80A3DF00; + gSaveContext.pendingSale = ItemTable_Retrieve(GI_SWORD_KNIFE).itemId; + func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); + this->actionFunc = func_80A3DF00; } } break; @@ -277,14 +279,16 @@ void func_80A3DF00(EnGm* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = func_80A3DF60; } else { - if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && - !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { - GiveItemEntryFromActor(&this->actor, play, - Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE), 415.0f, 10.0f); + if (gSaveContext.n64ddFlag && (Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { + GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE); + gSaveContext.pendingSale = itemEntry.itemId; + GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f); Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); gSaveContext.infTable[11] |= 2; } else { + gSaveContext.pendingSale = ItemTable_Retrieve(GI_SWORD_KNIFE).itemId; func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); } diff --git a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c index a41a2ad6c..7aa2013ea 100644 --- a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c +++ b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c @@ -131,13 +131,14 @@ void func_80A89160(EnJs* this, PlayState* play) { } else { if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { - GiveItemEntryFromActor(&this->actor, play, - Randomizer_GetItemFromKnownCheck(RC_WASTELAND_BOMBCHU_SALESMAN, GI_BOMBCHUS_10), 90.0f, 10.0f); - Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); + GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_WASTELAND_BOMBCHU_SALESMAN, GI_BOMBCHUS_10); + gSaveContext.pendingSale = itemEntry.itemId; + GiveItemEntryFromActor(&this->actor, play, itemEntry, 90.0f, 10.0f); + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); } else { - func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); + gSaveContext.pendingSale = ItemTable_Retrieve(GI_BOMBCHUS_10).itemId; + func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); } - } } diff --git a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c index 074b48097..d2b52e0a7 100644 --- a/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c +++ b/soh/src/overlays/actors/ovl_En_Ms/z_en_ms.c @@ -156,10 +156,12 @@ void EnMs_Sell(EnMs* this, PlayState* play) { (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) ? EnMs_Wait : EnMs_TalkAfterPurchase; } else { if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS)) { - GiveItemEntryFromActor(&this->actor, play, - Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN), 90.0f, 10.0f); + GetItemEntry itemEntry = Randomizer_GetItemFromKnownCheck(RC_ZR_MAGIC_BEAN_SALESMAN, GI_BEAN); + gSaveContext.pendingSale = itemEntry.itemId; + GiveItemEntryFromActor(&this->actor, play, itemEntry, 90.0f, 10.0f); BEANS_BOUGHT = 10; } else { + gSaveContext.pendingSale = ItemTable_Retrieve(GI_BEAN).itemId; func_8002F434(&this->actor, play, GI_BEAN, 90.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c index 9dd9ac1e2..9ec5965ba 100644 --- a/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c +++ b/soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c @@ -1716,7 +1716,9 @@ void EnOssan_State_ItemPurchased(EnOssan* this, PlayState* play, Player* player) } else { getItemEntry = ItemTable_Retrieve(this->shelfSlots[this->cursorIndex]->getItemId); } - + if (gSaveContext.pendingSale == ITEM_NONE) { + gSaveContext.pendingSale = getItemEntry.itemId; + } if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { if (this->actor.params == OSSAN_TYPE_MASK) { diff --git a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c index 804e1fdc3..f339e8173 100644 --- a/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c +++ b/soh/src/overlays/actors/ovl_En_Ta/z_en_ta.c @@ -917,6 +917,7 @@ void func_80B15FE8(EnTa* this, PlayState* play) { this->unk_2E0 |= 2; func_80B13AA0(this, func_80B15E80, func_80B16938); Rupees_ChangeBy(-30); + gSaveContext.pendingSale = ItemTable_Retrieve(GI_MILK).itemId; func_8002F434(&this->actor, play, GI_MILK, 10000.0f, 50.0f); break; }