diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 5342374f0..3048602c4 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -174,6 +174,7 @@ source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__s set(Header_Files__soh__Enhancements__randomizer "soh/Enhancements/randomizer/randomizer.h" "soh/Enhancements/randomizer/randomizer_item_tracker.h" + "soh/Enhancements/randomizer/adult_trade_shuffle.h" ) source_group("Header Files\\soh\\Enhancements\\randomizer" FILES ${Header_Files__soh__Enhancements__randomizer}) @@ -266,6 +267,7 @@ source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__s set(Source_Files__soh__Enhancements__randomizer "soh/Enhancements/randomizer/randomizer.cpp" "soh/Enhancements/randomizer/randomizer_item_tracker.cpp" + "soh/Enhancements/randomizer/adult_trade_shuffle.c" ) source_group("Source Files\\soh\\Enhancements\\randomizer" FILES ${Source_Files__soh__Enhancements__randomizer}) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index b6069475e..8b434d81c 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -186,6 +186,7 @@ typedef struct { u8 trialsDone[6]; u8 cowsMilked[10]; u8 temporaryWeapon; + u16 adultTradeItems; } SaveContext; // size = 0x1428 typedef enum { diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 48c9c4695..9acf3d1cc 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1,5 +1,6 @@ #include "debugSaveEditor.h" #include "../../util.h" +#include "../../OTRGlobals.h" #include "../libultraship/ImGuiImpl.h" #include "ImGuiHelpers.h" @@ -525,6 +526,20 @@ void DrawInfoTab() { ImGui::PopItemWidth(); } +void DrawBGSItemFlag(uint8_t itemID) { + const ItemMapEntry& slotEntry = itemMapping[itemID]; + ImGui::Image(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1)); + ImGui::SameLine(); + int tradeIndex = itemID - ITEM_POCKET_EGG; + bool hasItem = (gSaveContext.adultTradeItems & (1 << tradeIndex)) != 0; + ImGui::Checkbox(("##adultTradeFlag" + std::to_string(itemID)).c_str(), &hasItem); + if (hasItem) { + gSaveContext.adultTradeItems |= (1 << tradeIndex); + } else { + gSaveContext.adultTradeItems &= ~(1 << tradeIndex); + } +} + void DrawInventoryTab() { static bool restrictToValid = true; @@ -632,6 +647,16 @@ void DrawInventoryTab() { ImGui::PopID(); } } + + // Trade quest flags are only used when shuffling the trade sequence, so + // don't show this if it isn't needed. + if (gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) + && ImGui::TreeNode("Adult trade quest items")) { + for (int i = ITEM_POCKET_EGG; i <= ITEM_CLAIM_CHECK; i++) { + DrawBGSItemFlag(i); + } + ImGui::TreePop(); + } } // Draw a flag bitfield as an grid of checkboxes diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 1f8d4437f..ec6890cfb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2537,6 +2537,8 @@ namespace Settings { ShuffleGerudoToken.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]); + ShuffleAdultTradeQuest.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_ADULT_TRADE]); + // the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina" StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]); diff --git a/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c new file mode 100644 index 000000000..1bddf0c2f --- /dev/null +++ b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c @@ -0,0 +1,33 @@ +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "functions.h" +#include "variables.h" +#include "macros.h" + +void Randomizer_ConsumeAdultTradeItem(GlobalContext* globalCtx, u8 itemId) { + gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(itemId); + Inventory_ReplaceItem(globalCtx, itemId, Randomizer_GetNextAdultTradeItem()); +} + +u8 Randomizer_GetNextAdultTradeItem() { + const u8 numTradeItems = ITEM_CLAIM_CHECK - ITEM_POCKET_EGG + 1; + u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG; + for (int i = 0; i < numTradeItems; i++) { + u8 tradeIndex = (currentTradeItemIndex + i + 1) % numTradeItems; + if (gSaveContext.adultTradeItems & (1 << tradeIndex)) { + return ITEM_POCKET_EGG + tradeIndex; + } + } + return ITEM_NONE; +} + +u8 Randomizer_GetPrevAdultTradeItem() { + const u8 numTradeItems = ITEM_CLAIM_CHECK - ITEM_POCKET_EGG + 1; + u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG; + for (int i = 0; i < numTradeItems; i++) { + u8 tradeIndex = (currentTradeItemIndex - i - 1 + numTradeItems) % numTradeItems; + if (gSaveContext.adultTradeItems & (1 << tradeIndex)) { + return ITEM_POCKET_EGG + tradeIndex; + } + } + return ITEM_NONE; +} diff --git a/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h new file mode 100644 index 000000000..c5199e50a --- /dev/null +++ b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h @@ -0,0 +1,12 @@ +#ifndef Z_ADULT_TRADE_SHUFFLE_H +#define Z_ADULT_TRADE_SHUFFLE_H + +#include + +#define ADULT_TRADE_FLAG(itemId) (1 << (itemId - ITEM_POCKET_EGG)) + +void Randomizer_ConsumeAdultTradeItem(GlobalContext* globalCtx, u8 itemId); +u8 Randomizer_GetNextAdultTradeItem(); +u8 Randomizer_GetPrevAdultTradeItem(); + +#endif diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 250f4e3f1..214e1d8be 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1407,6 +1407,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "Open Settings:Trial Count", RSK_TRIAL_COUNT }, { "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS }, { "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS }, + { "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, @@ -1638,6 +1639,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = std::stoi(numericValueString); break; case RSK_SHUFFLE_COWS: + case RSK_SHUFFLE_ADULT_TRADE: case RSK_RANDOM_TRIALS: if(it.value() == "Off") { gSaveContext.randoSettings[index].value = 0; @@ -3434,6 +3436,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0); cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0); cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0); + cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); // if we skip child zelda, we start with zelda's letter, and malon starts @@ -3962,6 +3965,20 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); PaddedSeparator(); + // Shuffle Adult Trade Quest + SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), "gRandomizeShuffleAdultTrade"); + InsertHelpHoverText( + "Adds all of the adult trade quest items into the pool, each of which " + "can be traded for a unique reward.\n" + "\n" + "You will be able to choose which of your owned adult trade items is visible " + "in the inventory by selecting the item with A and using the control stick or " + "D-pad.\n" + "\n" + "If disabled, only the Claim Check will be found in the pool." + ); + PaddedSeparator(); + if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { // Shuffle Kokiri Sword SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword"); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 5aa89fbca..8b0897da1 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1001,5 +1001,6 @@ typedef enum { RSK_BIG_POE_COUNT, RSK_SKIP_EPONA_RACE, RSK_SKIP_TOWER_ESCAPE, - RSK_SKULLS_SUNS_SONG + RSK_SKULLS_SUNS_SONG, + RSK_SHUFFLE_ADULT_TRADE } RandomizerSettingKey; diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index fa3ff4e88..30a559fb7 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -88,6 +88,8 @@ void SaveManager::LoadRandomizerVersion1() { for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonText); i++) { SaveManager::Instance->LoadData("gt" + std::to_string(i), gSaveContext.ganonText[i]); } + + SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems); } void SaveManager::SaveRandomizer() { @@ -130,6 +132,8 @@ void SaveManager::SaveRandomizer() { for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonText); i++) { SaveManager::Instance->SaveData("gt" + std::to_string(i), gSaveContext.ganonText[i]); } + + SaveManager::Instance->SaveData("adultTradeItems", gSaveContext.adultTradeItems); } void SaveManager::Init() { diff --git a/soh/src/code/z_game_over.c b/soh/src/code/z_game_over.c index 86ba7c6e1..bb4be8711 100644 --- a/soh/src/code/z_game_over.c +++ b/soh/src/code/z_game_over.c @@ -33,19 +33,21 @@ void GameOver_Update(GlobalContext* globalCtx) { gSaveContext.eventInf[1] &= ~1; // search inventory for spoiling items and revert if necessary - for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { - if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) { - INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; + if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) { + for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { + if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) { + INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; - // search c buttons for the found spoiling item and revert if necessary - for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { - if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { - gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; - Interface_LoadItemIcon1(globalCtx, j); + // search c buttons for the found spoiling item and revert if necessary + for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { + if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { + gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + Interface_LoadItemIcon1(globalCtx, j); + } } } } - } + } // restore "temporary B" to the B Button if not a sword item if (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI && diff --git a/soh/src/code/z_kankyo.c b/soh/src/code/z_kankyo.c index 7fd9a7480..f59a9c70d 100644 --- a/soh/src/code/z_kankyo.c +++ b/soh/src/code/z_kankyo.c @@ -4,6 +4,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" typedef enum { /* 0 */ LENS_FLARE_CIRCLE0, @@ -2048,6 +2049,21 @@ void Environment_PlaySceneSequence(GlobalContext* globalCtx) { Audio_SetEnvReverb(globalCtx->roomCtx.curRoom.echo); } +bool HatchPocketEgg(GlobalContext* globalCtx) { + if (!gSaveContext.n64ddFlag) { + return Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); + } + + if (!(gSaveContext.adultTradeItems & ADULT_TRADE_FLAG(ITEM_POCKET_EGG))) { + return 0; + } + + // Swap the flags, then replace the item if it's selected + gSaveContext.adultTradeItems ^= ADULT_TRADE_FLAG(ITEM_POCKET_EGG) | ADULT_TRADE_FLAG(ITEM_POCKET_CUCCO); + Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); + return 1; +} + // updates bgm/sfx and other things as the day progresses void func_80075B44(GlobalContext* globalCtx) { switch (globalCtx->envCtx.unk_E0) { @@ -2101,7 +2117,7 @@ void func_80075B44(GlobalContext* globalCtx) { gSaveContext.dogIsLost = true; func_80078884(NA_SE_EV_CHICKEN_CRY_M); if ((Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) || - Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) && + HatchPocketEgg(globalCtx)) && globalCtx->csCtx.state == 0 && !Player_InCsMode(globalCtx)) { Message_StartTextbox(globalCtx, 0x3066, NULL); } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 24211c590..eb166bddd 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3,6 +3,7 @@ #include "textures/parameter_static/parameter_static.h" #include "textures/do_action_static/do_action_static.h" #include "textures/icon_item_static/icon_item_static.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #ifdef _MSC_VER #include @@ -2164,6 +2165,10 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { gSaveContext.itemGetInf[1] |= 0x8000; } + if (item >= ITEM_POCKET_EGG) { + gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item); + } + temp = INV_CONTENT(item); INV_CONTENT(item) = item; diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 8aa46ceb4..d93da4f6d 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -563,13 +563,15 @@ void Sram_OpenSave() { gSaveContext.equips.equipment |= 2; } - for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) { - INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; + if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) { + for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) { + INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; - for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { - if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { - gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { + if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { + gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + } } } } @@ -878,6 +880,11 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { GiveLinkGerudoCard(); } } + + // shuffle adult trade quest + if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { + gSaveContext.adultTradeItems = 0; + } } Save_SaveFile(); 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 14e193f36..97e58b30a 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 @@ -6,6 +6,7 @@ #include "z_en_ds.h" #include "objects/object_ds/object_ds.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -91,7 +92,12 @@ void EnDs_GiveOddPotion(EnDs* this, GlobalContext* globalCtx) { this->actionFunc = EnDs_DisplayOddPotionText; gSaveContext.timer2State = 0; } else { - func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f); + u32 itemId = GI_ODD_POTION; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); } } @@ -99,7 +105,12 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) { Message_CloseTextbox(globalCtx); this->actionFunc = EnDs_GiveOddPotion; - func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f); + u32 itemId = GI_ODD_POTION; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); } } @@ -120,7 +131,7 @@ void EnDs_BrewOddPotion2(EnDs* this, GlobalContext* globalCtx) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion3; - this->brewTimer = 60; + this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60; Flags_UnsetSwitch(globalCtx, 0x3F); } } @@ -130,7 +141,7 @@ void EnDs_BrewOddPotion1(EnDs* this, GlobalContext* globalCtx) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion2; - this->brewTimer = 20; + this->brewTimer = gSaveContext.n64ddFlag ? 0 : 20; } Math_StepToF(&this->unk_1E4, 1.0f, 0.01f); @@ -144,7 +155,7 @@ void EnDs_OfferOddPotion(EnDs* this, GlobalContext* globalCtx) { switch (globalCtx->msgCtx.choiceIndex) { case 0: // yes this->actionFunc = EnDs_BrewOddPotion1; - this->brewTimer = 60; + this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60; Flags_SetSwitch(globalCtx, 0x3F); globalCtx->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index e1179fe1b..c51090221 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5) @@ -961,9 +962,17 @@ void EnGo_GetItem(EnGo* this, GlobalContext* globalCtx) { } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { getItemId = GI_CLAIM_CHECK; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS); + } } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) { getItemId = GI_PRESCRIPTION; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN); + } } } diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 22c19f5f0..97a6fd3a8 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5) @@ -652,7 +653,12 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { if (Message_ShouldAdvance(globalCtx)) { if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) { if (globalCtx->msgCtx.choiceIndex == 0) { - EnGo2_GetItem(this, globalCtx, GI_PRESCRIPTION); + u32 getItemId = GI_PRESCRIPTION; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN); + } + EnGo2_GetItem(this, globalCtx, getItemId); this->actionFunc = EnGo2_SetupGetItem; return 2; } @@ -1847,12 +1853,14 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) { this->actor.flags &= ~ACTOR_FLAG_0; this->actor.shape.rot.y += 0x5B0; this->unk_26E = 1; - this->animTimer = this->skelAnime.endFrame + 60.0f + 60.0f; // eyeDrops animation timer + this->animTimer = gSaveContext.n64ddFlag ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer this->eyeMouthTexState = 2; this->unk_20C = 0; this->goronState++; func_800F483C(0x28, 5); - OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM); + if (!gSaveContext.n64ddFlag) { + OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM); + } break; case 1: if (DECR(this->animTimer)) { @@ -1879,7 +1887,12 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) { this->unk_26E = 2; this->skelAnime.playSpeed = 0.0f; this->skelAnime.curFrame = this->skelAnime.endFrame; - EnGo2_GetItem(this, globalCtx, GI_CLAIM_CHECK); + u32 getItemId = GI_CLAIM_CHECK; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS); + } + EnGo2_GetItem(this, globalCtx, getItemId); this->actionFunc = EnGo2_SetupGetItem; this->goronState = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c index efdbbdef8..3fe2c9851 100644 --- a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c +++ b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c @@ -7,6 +7,7 @@ #include "z_en_hs.h" #include "vt.h" #include "objects/object_hs/object_hs.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -78,7 +79,14 @@ void EnHs_Init(Actor* thisx, GlobalContext* globalCtx) { // "chicken shop (adult era)" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST); func_80A6E3A0(this, func_80A6E9AC); - if (gSaveContext.itemGetInf[3] & 1) { + bool shouldDespawn; + bool tradedMushroom = gSaveContext.itemGetInf[3] & 1; + if (gSaveContext.n64ddFlag) { + shouldDespawn = tradedMushroom && !(gSaveContext.adultTradeItems & ADULT_TRADE_FLAG(ITEM_COJIRO)); + } else { + shouldDespawn = tradedMushroom; + } + if (shouldDespawn) { // "chicken shop closed" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST); Actor_Kill(&this->actor); @@ -127,7 +135,9 @@ void func_80A6E5EC(EnHs* this, GlobalContext* globalCtx) { void func_80A6E630(EnHs* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) { - func_80088AA0(180); + if (!gSaveContext.n64ddFlag) { + func_80088AA0(180); + } func_80A6E3A0(this, func_80A6E6B0); gSaveContext.eventInf[1] &= ~1; } @@ -156,7 +166,12 @@ void func_80A6E740(EnHs* this, GlobalContext* globalCtx) { this->actor.parent = NULL; func_80A6E3A0(this, func_80A6E630); } else { - func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f); + s32 itemId = GI_ODD_MUSHROOM; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); } this->unk_2A8 |= 1; @@ -167,7 +182,12 @@ void func_80A6E7BC(EnHs* this, GlobalContext* globalCtx) { switch (globalCtx->msgCtx.choiceIndex) { case 0: func_80A6E3A0(this, func_80A6E740); - func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f); + s32 itemId = GI_ODD_MUSHROOM; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); break; case 1: Message_ContinueTextbox(globalCtx, 0x10B4); diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 50dc8d1d9..4b9bc1f2b 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -10,6 +10,7 @@ #include "objects/object_km1/object_km1.h" #include "objects/object_kw1/object_kw1.h" #include "vt.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4) @@ -1216,7 +1217,12 @@ void func_80A99504(EnKo* this, GlobalContext* globalCtx) { this->actor.parent = NULL; this->actionFunc = func_80A99560; } else { - func_8002F434(&this->actor, globalCtx, GI_SAW, 120.0f, 10.0f); + s32 itemId = GI_SAW; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_ODD_POTION, GI_SAW); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_POTION); + } + func_8002F434(&this->actor, globalCtx, itemId, 120.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index cda6e476d..25bc987ab 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -6,6 +6,7 @@ #include "z_en_kz.h" #include "objects/object_kz/object_kz.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -465,6 +466,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) { if (gSaveContext.n64ddFlag) { if (this->isTrading) { getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_PRESCRIPTION); Flags_SetTreasure(globalCtx, 0x1F); } else { getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA); @@ -480,7 +482,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) { void EnKz_StartTimer(EnKz* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && !gSaveContext.n64ddFlag) { func_80088AA0(180); // start timer2 with 3 minutes gSaveContext.eventInf[1] &= ~1; } diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index f42e09522..dd853ac06 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -6,6 +6,7 @@ #include "z_en_mk.h" #include "objects/object_mk/object_mk.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4) @@ -93,17 +94,29 @@ void func_80AACA94(EnMk* this, GlobalContext* globalCtx) { if (Actor_HasParent(&this->actor, globalCtx) != 0) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; - func_80088AA0(240); - gSaveContext.eventInf[1] &= ~1; + if (!gSaveContext.n64ddFlag) { + func_80088AA0(240); + gSaveContext.eventInf[1] &= ~1; + } } else { - func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f); + s32 getItemID = GI_EYEDROPS; + if (gSaveContext.n64ddFlag) { + getItemID = Randomizer_GetItemIdFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG); + } + func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f); } } void func_80AACB14(EnMk* this, GlobalContext* globalCtx) { if (Actor_TextboxIsClosing(&this->actor, globalCtx)) { this->actionFunc = func_80AACA94; - func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f); + s32 getItemID = GI_EYEDROPS; + if (gSaveContext.n64ddFlag) { + getItemID = Randomizer_GetItemIdFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG); + } + func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f); } } @@ -129,7 +142,7 @@ void func_80AACC04(EnMk* this, GlobalContext* globalCtx) { if (this->timer > 0) { this->timer--; } else { - this->timer = 16; + this->timer = gSaveContext.n64ddFlag ? 0 : 16; this->actionFunc = func_80AACBAC; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); @@ -142,7 +155,7 @@ void func_80AACCA0(EnMk* this, GlobalContext* globalCtx) { this->timer--; this->actor.shape.rot.y += 0x800; } else { - this->timer = 120; + this->timer = gSaveContext.n64ddFlag ? 0 : 120; this->actionFunc = func_80AACC04; Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f); @@ -158,7 +171,7 @@ void func_80AACD48(EnMk* this, GlobalContext* globalCtx) { this->actionFunc = func_80AACCA0; globalCtx->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; - this->timer = 16; + this->timer = gSaveContext.n64ddFlag ? 0 : 16; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); this->flags &= ~2; diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index c31f2b923..23584cc19 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -3,6 +3,7 @@ #include "objects/object_os_anime/object_os_anime.h" #include "overlays/actors/ovl_En_Niw/z_en_niw.h" #include "vt.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4) @@ -454,8 +455,13 @@ void func_80ABAC00(EnNiwLady* this, GlobalContext* globalCtx) { if (LINK_IS_ADULT) { getItemId = !(gSaveContext.itemGetInf[2] & 0x1000) ? GI_POCKET_EGG : GI_COJIRO; - if (gSaveContext.n64ddFlag && getItemId == GI_POCKET_EGG) { - getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); + if (gSaveContext.n64ddFlag) { + if (getItemId == GI_POCKET_EGG) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); + } else { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_POCKET_CUCCO, GI_COJIRO); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_POCKET_CUCCO); + } } } func_8002F434(&this->actor, globalCtx, getItemId, 200.0f, 100.0f); diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index 425e07421..c6ca4cad7 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -6,6 +6,7 @@ #include "z_en_toryo.h" #include "objects/object_toryo/object_toryo.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -313,7 +314,12 @@ void func_80B20768(EnToryo* this, GlobalContext* globalCtx) { this->actor.parent = NULL; this->unk_1E4 = 5; } else { - func_8002F434(&this->actor, globalCtx, GI_SWORD_BROKEN, 100.0f, 10.0f); + s32 itemId = GI_SWORD_BROKEN; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_GV_TRADE_SAW, GI_SWORD_BROKEN); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SAW); + } + func_8002F434(&this->actor, globalCtx, itemId, 100.0f, 10.0f); } return; } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 675fc1191..fe57289fa 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -1,5 +1,7 @@ #include "z_kaleido_scope.h" #include "textures/parameter_static/parameter_static.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" u8 gAmmoItems[] = { ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE, @@ -10,6 +12,7 @@ static s16 sEquipState = 0; static s16 sEquipAnimTimer = 0; static s16 sEquipMoveTimer = 10; bool gSelectingMask; +bool gSelectingAdultTrade; static s16 sAmmoVtxOffset[] = { 0, 2, 4, 6, 99, 99, 8, 99, 10, 99, 99, 99, 99, 99, 12, @@ -109,7 +112,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { pauseCtx->nameColorSet = 0; if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM)) { - moveCursorResult = 0 || gSelectingMask; + moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade; oldCursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM]; cursorItem = pauseCtx->cursorItem[PAUSE_ITEM]; @@ -283,7 +286,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { if (pauseCtx->cursorSpecialPos == 0) { if (cursorItem != PAUSE_ITEM_NONE) { if ((ABS(pauseCtx->stickRelY) > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) { - moveCursorResult = 0 || gSelectingMask; + moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade; cursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM]; cursorY = pauseCtx->cursorY[PAUSE_ITEM]; @@ -385,6 +388,24 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { } gSelectingMask = cursorSlot == SLOT_TRADE_CHILD; } + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && + cursorSlot == SLOT_TRADE_ADULT && CHECK_BTN_ALL(input->press.button, BTN_A)) { + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + gSelectingAdultTrade = !gSelectingAdultTrade; + } + if (gSelectingAdultTrade) { + pauseCtx->cursorColorSet = 8; + if (((pauseCtx->stickRelX > 30 || pauseCtx->stickRelY > 30) || + dpad && CHECK_BTN_ANY(input->press.button, BTN_DRIGHT | BTN_DUP))) { + Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetNextAdultTradeItem()); + } else if (((pauseCtx->stickRelX < -30 || pauseCtx->stickRelY < -30) || + dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DDOWN))) { + Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetPrevAdultTradeItem()); + } + gSelectingAdultTrade = cursorSlot == SLOT_TRADE_ADULT; + } u16 buttonsToCheck = BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT; if (CVar_GetS32("gDpadEquips", 0) && (!CVar_GetS32("gDpadPauseName", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; @@ -510,6 +531,7 @@ void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s Input* input = &globalCtx->state.input[0]; PauseContext* pauseCtx = &globalCtx->pauseCtx; gSelectingMask = false; + gSelectingAdultTrade = false; if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { pauseCtx->equipTargetCBtn = 0;