From f431f7df724bcd3eddb6882589b2772f480b1ff3 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Sun, 14 Aug 2022 12:29:56 -0500 Subject: [PATCH 01/20] Add Bombchus in Logic rando setting and implement progressive chus --- .../Enhancements/randomizer/randomizer.cpp | 25 ++++++++++++++++++- .../Enhancements/randomizer/randomizerTypes.h | 3 ++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ca86793cc..100d36c17 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1452,6 +1452,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "Shuffle Dungeon Items:Gerudo Fortress Keys", RSK_GERUDO_KEYS }, { "Shuffle Dungeon Items:Boss Keys", RSK_BOSS_KEYSANITY }, { "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY }, + { "World Settings:Bombchus in Logic", RSK_BOMBCHUS_IN_LOGIC }, { "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS }, { "Misc Settings:Hint Clarity", RSK_HINT_CLARITY }, { "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION }, @@ -2229,7 +2230,13 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) return GI_RUPEE_BLUE; case RG_PROGRESSIVE_BOMBCHUS: - return GI_BOMBCHUS_20; //todo progressive? + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + return GI_BOMBCHUS_20; + } + if (AMMO(ITEM_BOMBCHU) < 5) { + return GI_BOMBCHUS_10; + } + return GI_BOMBCHUS_5; case RG_PROGRESSIVE_MAGIC_METER: switch (gSaveContext.magicLevel) { @@ -3540,6 +3547,7 @@ void GenerateRandomizerImgui() { 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_BOMBCHUS_IN_LOGIC] = CVar_GetS32("gRandomizeBombchusInLogic", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); // if we skip child zelda, we start with zelda's letter, and malon starts @@ -4153,6 +4161,21 @@ void DrawRandoEditor(bool& open) { "This setting does not effect the item earned from playing\n" "the Song of Storms and the frog song minigame." ); + PaddedSeparator(); + + // Bombchus in Logic + // TODO: add to world settings after entrance rando gets merged + SohImGui::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), "gRandomizeBombchusInLogic"); + InsertHelpHoverText( + "Bombchus are properly considered in logic.\n" + "\n" + "The first Bombchu pack will always be 20, and subsequent packs will be" + "5 or 10 based on how many you have.\n" + "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu" + "shop.\n" + "\n" + "Bombchu Bowling is opened by obtaining Bombchus." + ); } ImGui::PopItemWidth(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index b09b9dab2..420976615 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1008,5 +1008,6 @@ typedef enum { RSK_COMPLETE_MASK_QUEST, RSK_ENABLE_GLITCH_CUTSCENES, RSK_SKULLS_SUNS_SONG, - RSK_SHUFFLE_ADULT_TRADE + RSK_SHUFFLE_ADULT_TRADE, + RSK_BOMBCHUS_IN_LOGIC } RandomizerSettingKey; From 8cb50a2ee16ff205e4fcd8fd58b98e8eb88fefc1 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Sun, 14 Aug 2022 12:30:22 -0500 Subject: [PATCH 02/20] Open Bombchu Bowling with chus --- .../randomizer/3drando/settings.cpp | 2 ++ .../Enhancements/randomizer/randomizer.cpp | 5 ++-- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 26 ++++++++++++------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 71aa70b32..1482a5cdb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2551,6 +2551,8 @@ namespace Settings { MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); + BombchusInLogic.SetSelectedIndex(cvarSettings[RSK_BOMBCHUS_IN_LOGIC]); + StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]); StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 100d36c17..95401a34e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1688,6 +1688,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_STARTING_KOKIRI_SWORD: case RSK_COMPLETE_MASK_QUEST: case RSK_ENABLE_GLITCH_CUTSCENES: + case RSK_BOMBCHUS_IN_LOGIC: if(it.value() == "Off") { gSaveContext.randoSettings[index].value = 0; } else if(it.value() == "On") { @@ -4169,9 +4170,9 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText( "Bombchus are properly considered in logic.\n" "\n" - "The first Bombchu pack will always be 20, and subsequent packs will be" + "The first Bombchu pack will always be 20, and subsequent packs will be " "5 or 10 based on how many you have.\n" - "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu" + "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu " "shop.\n" "\n" "Bombchu Bowling is opened by obtaining Bombchus." diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index dc22f9dab..28a63bbf6 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -143,13 +143,14 @@ void EnBomBowMan_BlinkAwake(EnBomBowlMan* this, GlobalContext* globalCtx) { } } - // Check for Bomb Bag if Rando is enabled - // RANDOTODO: Check for bombchu pack instead of bomb bag if bombchus are in logic + // Check for Bomb Bag or Bombchus if Rando is enabled, depending on whether bombchus are considered in logic if (gSaveContext.n64ddFlag) { - if (INV_CONTENT(ITEM_BOMB) != ITEM_NONE) { - this->actor.textId = 0xBF; - } else { + u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC); + if ((!bombchusInLogic && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) || + (bombchusInLogic && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) { this->actor.textId = 0x7058; + } else { + this->actor.textId = 0xBF; } } } @@ -177,11 +178,16 @@ void EnBomBowMan_CheckBeatenDC(EnBomBowlMan* this, GlobalContext* globalCtx) { this->eyeMode = CHU_GIRL_EYES_AWAKE; this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; - // Check for beaten Dodongo's Cavern if not rando'd - // check for bomb bag if rando'd - if ((!gSaveContext.n64ddFlag && - !((gSaveContext.eventChkInf[2] & 0x20) || BREG(2))) || - (gSaveContext.n64ddFlag && (INV_CONTENT(ITEM_BOMB) == ITEM_NONE))) { + // Check if beaten Dodongo's Cavern if not rando'd + // check for bomb bag or bombchus if rando'd depending on whether chus are in logic + bool bombchuBowlingClosed; + if (gSaveContext.n64ddFlag) { + u8 explosive = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) ? ITEM_BOMBCHU : ITEM_BOMB; + bombchuBowlingClosed = (INV_CONTENT(explosive) == ITEM_NONE); + } else { + bombchuBowlingClosed = !((gSaveContext.eventChkInf[2] & 0x20) || BREG(2)); + } + if (bombchuBowlingClosed) { this->actionFunc = EnBomBowMan_WaitNotBeatenDC; } else { this->actor.textId = 0x18; From e8df2f2e470719b5d2efd9e83eca0d73605fa456 Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Wed, 17 Aug 2022 11:36:41 -0500 Subject: [PATCH 03/20] Open bombchu shop with chus --- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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 5a1a36be7..f32404cc1 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 @@ -633,8 +633,16 @@ s32 EnGirlA_CanBuy_Unk20(GlobalContext* globalCtx, EnGirlA* this) { } s32 EnGirlA_CanBuy_Bombchus(GlobalContext* globalCtx, EnGirlA* this) { - // When in rando, don't allow buying bombchus when the player doesn't have a bomb bag - if (AMMO(ITEM_BOMBCHU) >= 50 || (gSaveContext.n64ddFlag && CUR_CAPACITY(UPG_BOMB_BAG) == 0)) { + // When in rando, don't allow buying bombchus when the player doesn't have required explosives + // If bombchus are in logic, the player needs to have bombchus; otherwise they need a bomb bag + if (gSaveContext.n64ddFlag) { + u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC); + if ((!bombchusInLogic && CUR_CAPACITY(UPG_BOMB_BAG) == 0) || + (bombchusInLogic && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) { + return CANBUY_RESULT_CANT_GET_NOW; + } + } + if (AMMO(ITEM_BOMBCHU) >= 50) { return CANBUY_RESULT_CANT_GET_NOW; } if (gSaveContext.rupees < this->basePrice) { @@ -861,6 +869,11 @@ void EnGirlA_BuyEvent_ZoraTunic(GlobalContext* globalCtx, EnGirlA* this) { } void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this) { + Rupees_ChangeBy(-this->basePrice); + + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { + return; + } switch (this->actor.params) { case SI_BOMBCHU_10_2: gSaveContext.itemGetInf[0] |= 0x40; @@ -887,7 +900,6 @@ void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this) gSaveContext.itemGetInf[0] |= 0x20; break; } - Rupees_ChangeBy(-this->basePrice); } void EnGirlA_Noop(EnGirlA* this, GlobalContext* globalCtx) { From 170b7595725936692bc429518de2c999ea46ffe7 Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Thu, 18 Aug 2022 10:38:49 -0500 Subject: [PATCH 04/20] Make Bombchus buyable without a wallet --- .../custom-message/CustomMessageTypes.h | 2 ++ soh/soh/OTRGlobals.cpp | 3 +++ soh/soh/z_message_OTR.cpp | 22 ++++++++++++++++++- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 7 +++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 1859e83a5..f9a4f7936 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -1,6 +1,8 @@ #pragma once typedef enum { + TEXT_BUY_BOMBCHU_10_PROMPT = 0x8C, + TEXT_BUY_BOMBCHU_10_DESC = 0xBC, TEXT_GS_NO_FREEZE = 0xB4, TEXT_GS_FREEZE = 0xB5, TEXT_RANDOMIZER_CUSTOM_ITEM = 0xF8, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 3611c97de..699c3f103 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1540,6 +1540,9 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) { } } else if (textId == TEXT_SCRUB_POH || textId == TEXT_SCRUB_STICK_UPGRADE || textId == TEXT_SCRUB_NUT_UPGRADE) { messageEntry = Randomizer_GetScrubMessage(textId); + } else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && + (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index c6be43964..5cfc99395 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -111,5 +111,25 @@ extern "C" void OTRMessage_Init() TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, "You got a %rGold Skulltula Token%w!&You've collected %r\x19%w tokens&in total!", "Du erhälst ein %rGoldene&Skulltula-Symbol%w! Du hast&insgesamt %r\x19%w symbol gesammelt!", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!" }); + "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!" + } + ); + CustomMessageManager::Instance->CreateMessage( + customMessageTableID, TEXT_BUY_BOMBCHU_10_DESC, + { + TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, + "\x08%rBombchu (10 pieces) 99 Rupees&%wThis looks like a toy mouse, but&it's actually a self-propelled time&bomb!\x09\x0A", + "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als Distanzwaffe&einsetzen kannst!\x09\x0A", + "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est &destructrice!!!\x09\x0A", + } + ); + CustomMessageManager::Instance->CreateMessage( + customMessageTableID, TEXT_BUY_BOMBCHU_10_PROMPT, + { + TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, + "\x08\Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", + "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", + "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w", + } + ); } 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 f32404cc1..54af786a6 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 @@ -1065,7 +1065,12 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, GlobalContext* globalCtx) { this->canBuyFunc = itemEntry->canBuyFunc; this->itemGiveFunc = itemEntry->itemGiveFunc; this->buyEventFunc = itemEntry->buyEventFunc; - this->basePrice = itemEntry->price; + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && + this->getItemId == GI_BOMBCHUS_10) { + this->basePrice = 99; + } else { + this->basePrice = itemEntry->price; + } this->itemCount = itemEntry->count; this->hiliteFunc = itemEntry->hiliteFunc; this->giDrawId = itemEntry->giDrawId; From 58aed3dc07fef3a98a208ac377529fa13f83ea99 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Mon, 22 Aug 2022 10:41:59 -0500 Subject: [PATCH 05/20] Correct bombchus in logic description to only include chu shop --- soh/soh/Enhancements/randomizer/randomizer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 95401a34e..8616208d3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4172,8 +4172,7 @@ void DrawRandoEditor(bool& open) { "\n" "The first Bombchu pack will always be 20, and subsequent packs will be " "5 or 10 based on how many you have.\n" - "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu " - "shop.\n" + "Once found, they can be replenished at the Bombchu shop.\n" "\n" "Bombchu Bowling is opened by obtaining Bombchus." ); From 6a900022c07c470b7d5471e2993181b5b6d91b0f Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Tue, 23 Aug 2022 07:47:21 -0500 Subject: [PATCH 06/20] Pass vanilla ammo drops to logic --- soh/soh/Enhancements/randomizer/3drando/settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 1482a5cdb..9bff10b1c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2552,6 +2552,7 @@ namespace Settings { MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); BombchusInLogic.SetSelectedIndex(cvarSettings[RSK_BOMBCHUS_IN_LOGIC]); + AmmoDrops.SetSelectedIndex(AMMODROPS_VANILLA); // Ensure logic knows bombchu drops aren't implemented yet StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]); StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]); From 05136c13b7cc9e4a0431e5b8adf33d38cf198902 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Fri, 26 Aug 2022 20:46:19 -0400 Subject: [PATCH 07/20] Fixes Link getting Song as pocket item (#1326) --- soh/src/code/z_sram.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 952ce8e3c..c71bb4def 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -703,6 +703,8 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { if (getItem.modIndex == MOD_NONE) { if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) { GiveLinkDungeonReward(getItem.getItemId); + } else if (getItem.itemId >= ITEM_SONG_MINUET && getItem.itemId <= ITEM_SONG_STORMS) { + GiveLinkSong(getItem.getItemId); } else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED || giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) { GiveLinkRupeesByGetItemId(giid); From a572c11f4f41a011733507296189161b758df7d0 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 27 Aug 2022 03:27:20 -0400 Subject: [PATCH 08/20] Fixes ice trap gidata not getting cleared after trap is sprung. (#1322) --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index cd2950d65..e2c823012 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6121,6 +6121,8 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) { this->actor.colChkInfo.damage = 0; func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20); Player_SetPendingFlag(this, globalCtx); + this->getItemId == GI_NONE; + this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; return 1; } @@ -12866,6 +12868,8 @@ void func_8084E6D4(Player* this, GlobalContext* globalCtx) { } else { this->actor.colChkInfo.damage = 0; func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20); + this->getItemId == GI_NONE; + this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; } return; } From 11618730442b0a8737e79739e7484932c855922a Mon Sep 17 00:00:00 2001 From: aMannus Date: Mon, 29 Aug 2022 21:51:42 +0200 Subject: [PATCH 09/20] Moar names --- .../Enhancements/randomizer/randomizer.cpp | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8f4ef7d3b..fd018ff7b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -36,17 +36,23 @@ const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; -static const char* englishRupeeNames[44] = { - "Rupees", "Bitcoin", "Bananas", "Cornflakes", "Gummybears", "Floopies", "Dollars", "Lemmings", - "Emeralds", "Bucks", "Rubles", "Diamonds", "Moons", "Stars", "Mana", "Doll Hairs", - "Dogecoin", "Mushrooms", "Experience", "Friends", "Coins", "Rings", "Gil", "Pokédollars", - "Bells", "Orbs", "Bottle Caps", "Simoleons", "Pokémon", "Toys", "Smackaroos", "Zorkmids", - "Zenny", "Bones", "Souls", "Studs", "Munny", "Rubies", "Gald", "Gold", - "Shillings", "Pounds", "Glimmer", "Potch" +static const char* englishRupeeNames[52] = { + "Rupees", "Bitcoin", "Bananas", "Cornflakes", "Gummybears", "Floopies", "Dollars", "Lemmings", + "Emeralds", "Bucks", "Rubles", "Diamonds", "Moons", "Stars", "Mana", "Doll Hairs", + "Dogecoin", "Mushrooms", "Experience", "Friends", "Coins", "Rings", "Gil", "Pokédollars", + "Bells", "Orbs", "Bottle Caps", "Simoleons", "Pokémon", "Toys", "Smackaroos", "Zorkmids", + "Zenny", "Bones", "Souls", "Studs", "Munny", "Rubies", "Gald", "Gold", + "Shillings", "Pounds", "Glimmer", "Potch", "Robux", "V-Bucks", "Bratwürste", "Mesetas", + "Bath Salts", "Coal", "Euro", "Spoons" }; -static const char* germanRupeeNames[1] = { - "Rubine" +static const char* germanRupeeNames[41] = { + "Rubine", "Mäuse", "Kröten", "Münzen", "Euro", "Mark", "Bananen", + "Gummibären", "Bonbons", "Diamanten", "Bratwürste", "Bitcoin", "Dogecoin", "Monde", + "Sterne", "Brause UFOs", "Taler", "Sternis", "Schillinge", "Freunde", "Seelen", + "Gil", "Zenny", "Pfandflaschen", "Knochen", "Pilze", "Smaragde", "Kronkorken", + "Pokédollar", "Brötchen", "EXP", "Wagenchips", "Moos", "Knete", "Kohle", + "Kies", "Radieschen", "Diridari", "Steine", "Kartoffeln", "Penunze" }; static const char* frenchRupeeNames[36] = { From 776219fb52730541c402c1fd63b7b9bd470cdb22 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 31 Aug 2022 09:25:47 -0400 Subject: [PATCH 10/20] Backports a fix for sheik checks from rando-next (#1340) * Fixes some Sheik checks I had accidentally set the wrong flag for. * Removes duplicate switch case from cherry-pick --- soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 90e401f06..30ab5d06e 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -298,7 +298,7 @@ void GivePlayerRandoRewardSheikSong(EnXc* sheik, GlobalContext* globalCtx, Rando } } else if (check != RC_SHEIK_AT_TEMPLE) { if (GiveItemEntryFromActor(&sheik->actor, globalCtx, getItemEntry, 10000.0f, 100.0f)) { - player->pendingFlag.flagID = 0x55; + player->pendingFlag.flagID = (0x5 << 4) | (sheikType & 0xF) >> 1; player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; } } From bf505dba5cef0aaffb4576c9b4c4f430e9bceb43 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 31 Aug 2022 09:25:58 -0400 Subject: [PATCH 11/20] Fixes keys, maps, and compasses on develop-zhora rando (#1338) * Fixes keys, maps, and compasses on develop-zhora rando. * Adds randotodo comment as a note to adapt for the keysanity situation. --- .../Enhancements/randomizer/randomizer.cpp | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 1fc95a04f..495850361 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2209,6 +2209,42 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BUY_BOMBS_535: case RG_BUY_RED_POTION_40: case RG_BUY_RED_POTION_50: + //RANDO TODO: Fix this to return false if keysanity is on. + case RG_FOREST_TEMPLE_SMALL_KEY: + case RG_FIRE_TEMPLE_SMALL_KEY: + case RG_WATER_TEMPLE_SMALL_KEY: + case RG_SPIRIT_TEMPLE_SMALL_KEY: + case RG_SHADOW_TEMPLE_SMALL_KEY: + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + case RG_GERUDO_FORTRESS_SMALL_KEY: + case RG_GANONS_CASTLE_SMALL_KEY: + case RG_FOREST_TEMPLE_BOSS_KEY: + case RG_FIRE_TEMPLE_BOSS_KEY: + case RG_WATER_TEMPLE_BOSS_KEY: + case RG_SPIRIT_TEMPLE_BOSS_KEY: + case RG_SHADOW_TEMPLE_BOSS_KEY: + case RG_GANONS_CASTLE_BOSS_KEY: + case RG_DEKU_TREE_COMPASS: + case RG_DODONGOS_CAVERN_COMPASS: + case RG_JABU_JABUS_BELLY_COMPASS: + case RG_FOREST_TEMPLE_COMPASS: + case RG_FIRE_TEMPLE_COMPASS: + case RG_WATER_TEMPLE_COMPASS: + case RG_SPIRIT_TEMPLE_COMPASS: + case RG_SHADOW_TEMPLE_COMPASS: + case RG_BOTTOM_OF_THE_WELL_COMPASS: + case RG_ICE_CAVERN_COMPASS: + case RG_DEKU_TREE_MAP: + case RG_DODONGOS_CAVERN_MAP: + case RG_JABU_JABUS_BELLY_MAP: + case RG_FOREST_TEMPLE_MAP: + case RG_FIRE_TEMPLE_MAP: + case RG_WATER_TEMPLE_MAP: + case RG_SPIRIT_TEMPLE_MAP: + case RG_SHADOW_TEMPLE_MAP: + case RG_BOTTOM_OF_THE_WELL_MAP: + case RG_ICE_CAVERN_MAP: return true; default: return false; From 1f12caa5c9e02f108560ffe3f73f624ce42f4422 Mon Sep 17 00:00:00 2001 From: briaguya Date: Wed, 31 Aug 2022 18:15:09 -0400 Subject: [PATCH 12/20] fix oot ice trap check optimization issues --- soh/soh/OTRGlobals.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7d7a86268..886786260 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1652,15 +1652,14 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomi return ItemTable_RetrieveEntry(getItemModIndex, itemID); } -extern "C" bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor) { - return gSaveContext.n64ddFlag && (actor->parent != NULL) && - Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP; -} - extern "C" bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId) { return gSaveContext.n64ddFlag && Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP; } +extern "C" bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor) { + return Randomizer_ItemIsIceTrap(randomizerCheck, ogId) && actor->parent != NULL; +} + extern "C" CustomMessageEntry Randomizer_GetCustomGetItemMessage(Player* player) { s16 giid; if (player->getItemEntry.objectId != OBJECT_INVALID) { From 584a4ad818df3046c2e13d0ab1c2e6a7f6c67fa6 Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Wed, 31 Aug 2022 22:59:38 -0400 Subject: [PATCH 13/20] Linux crash handler (#1209) * crash handler linux * cleanups * missing underscore * more cleanups * cleanups * 32 bit --- .gitignore | 2 + libultraship/libultraship/CMakeLists.txt | 7 + libultraship/libultraship/CrashHandler.cpp | 172 +++++++++++++++++++++ libultraship/libultraship/CrashHandler.h | 18 +++ soh/include/functions.h | 2 +- soh/include/segment_symbols.h | 12 +- soh/soh/OTRGlobals.h | 2 + soh/src/code/fault.c | 2 +- soh/src/code/main.c | 12 +- 9 files changed, 218 insertions(+), 11 deletions(-) create mode 100644 libultraship/libultraship/CrashHandler.cpp create mode 100644 libultraship/libultraship/CrashHandler.h diff --git a/.gitignore b/.gitignore index 1df76208d..98fe2b637 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ __pycache__/ .idea/ cmake-build-debug venv/ +.cache/ # Project-specific ignores build/ @@ -410,6 +411,7 @@ oot.otr *.sav shipofharkinian.ini shipofharkinian.json +imgui.ini # Switch Stuff diff --git a/libultraship/libultraship/CMakeLists.txt b/libultraship/libultraship/CMakeLists.txt index b59993660..aec229bfb 100644 --- a/libultraship/libultraship/CMakeLists.txt +++ b/libultraship/libultraship/CMakeLists.txt @@ -334,6 +334,12 @@ set(Source_Files__Resources__mpq ) source_group("Source Files\\Resources\\mpq" FILES ${Source_Files__Resources__mpq}) +set(Source_Files__Crash_Handler + "CrashHandler.cpp" + "CrashHandler.h" +) +source_group("Source Files\\Crash Handler" FILES ${Source_Files__Crash_Handler}) + if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(Source_Files__Darwin "OSXFolderManager.mm" @@ -388,6 +394,7 @@ set(ALL_FILES ${Source_Files__Resources__Factories} ${Source_Files__Resources__Files} ${Source_Files__Resources__mpq} + ${Source_Files__Crash_Handler} ${Source_Files__Darwin} ${Source_Files__NintendoSwitch} ${Source_Files__CafeOS} diff --git a/libultraship/libultraship/CrashHandler.cpp b/libultraship/libultraship/CrashHandler.cpp new file mode 100644 index 000000000..f8d66beab --- /dev/null +++ b/libultraship/libultraship/CrashHandler.cpp @@ -0,0 +1,172 @@ +#include "spdlog/spdlog.h" +#include "Utils/StringHelper.h" +#include "CrashHandler.h" + +#if defined(__linux__) +#include +#include +#include // for __cxa_demangle +#include // for dladdr +#include +#include + +extern "C" void DeinitOTR(void); + + +static void PrintRegisters(ucontext_t* ctx) { + char regbuffer[1024]; + SPDLOG_CRITICAL("Registers:"); +#if defined(__x86_64__) + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); + SPDLOG_CRITICAL("RAX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); + SPDLOG_CRITICAL("RDI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); + SPDLOG_CRITICAL("RSI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); + SPDLOG_CRITICAL("RDX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); + SPDLOG_CRITICAL("RCX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); + SPDLOG_CRITICAL("R8 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); + SPDLOG_CRITICAL("R9 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); + SPDLOG_CRITICAL("R10: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); + SPDLOG_CRITICAL("R11: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); + SPDLOG_CRITICAL("RSP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); + SPDLOG_CRITICAL("RBX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); + SPDLOG_CRITICAL("RBP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); + SPDLOG_CRITICAL("R12: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); + SPDLOG_CRITICAL("R13: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); + SPDLOG_CRITICAL("R14: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); + SPDLOG_CRITICAL("R15: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); + SPDLOG_CRITICAL("RIP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); +#else + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); + SPDLOG_CRITICAL("EDI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); + SPDLOG_CRITICAL("ESI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); + SPDLOG_CRITICAL("EBP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); + SPDLOG_CRITICAL("ESP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); + SPDLOG_CRITICAL("EBX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); + SPDLOG_CRITICAL("EDX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); + SPDLOG_CRITICAL("ECX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); + SPDLOG_CRITICAL("EAX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); + SPDLOG_CRITICAL("EIP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFL : {} ", regbuffer); +#endif +} + +static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) +{ + std::array arr; + ucontext_t* ctx = static_cast(data); + constexpr size_t nMaxFrames = arr.size(); + size_t size = backtrace(arr.data(), nMaxFrames); + char** symbols = backtrace_symbols(arr.data(), nMaxFrames); + + SPDLOG_CRITICAL("(Signal: {})\n", sig); + + switch (sig) { + case SIGILL: + SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); + break; + case SIGABRT: + SPDLOG_CRITICAL("ABORT"); + break; + case SIGFPE: + SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); + break; + case SIGSEGV: + SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); + break; + } + + PrintRegisters(ctx); + + SPDLOG_CRITICAL("Traceback:\n"); + for (size_t i = 1; i < size; i++) + { + Dl_info info; + int gotAddress = dladdr(arr[i], &info); + std::string functionName(symbols[i]); + + if (gotAddress != 0 && info.dli_sname != nullptr) + { + FILE* pipe; + int32_t status; + char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); + const char* nameFound = info.dli_sname; + + if (status == 0) + { + nameFound = demangled; + } + #if 0 + char command[256]; + char addrLine[128]; + snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr); + pipe = popen(command, "r"); + fgets(addrLine, 128, pipe); + #endif + + functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound, + (char*)arr[i] - (char*)info.dli_saddr); + free(demangled); + } + + SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); + } + + free(symbols); + DeinitOTR(); + exit(1); +} + +static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) { + DeinitOTR(); + exit(1); +} + +extern "C" void SetupHandlerLinux() { + struct sigaction action; + struct sigaction shutdownAction; + + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = ErrorHandler; + + sigaction(SIGILL, &action, nullptr); + sigaction(SIGABRT, &action, nullptr); + sigaction(SIGFPE, &action, nullptr); + sigaction(SIGSEGV, &action, nullptr); + + shutdownAction.sa_flags = SA_SIGINFO; + shutdownAction.sa_sigaction = ShutdownHandler; + sigaction(SIGINT, &shutdownAction, nullptr); + sigaction(SIGTERM, &shutdownAction, nullptr); + sigaction(SIGQUIT, &shutdownAction, nullptr); + sigaction(SIGKILL, &shutdownAction, nullptr); + + +} +#endif diff --git a/libultraship/libultraship/CrashHandler.h b/libultraship/libultraship/CrashHandler.h new file mode 100644 index 000000000..e068a4e38 --- /dev/null +++ b/libultraship/libultraship/CrashHandler.h @@ -0,0 +1,18 @@ +#ifndef CRASH_HANDLER_H +#define CRASH_HANDLER_H + +#ifdef __linux__ + +#ifdef __cplusplus +extern "C" { +#endif + +void SetupHandlerLinux(void); + +#ifdef __cplusplus +} +#endif + +#endif // __linux__ + +#endif // CRASH_HANDLER_H \ No newline at end of file diff --git a/soh/include/functions.h b/soh/include/functions.h index a336cb1ef..6339cff64 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1656,7 +1656,7 @@ void PadMgr_HandleRetraceMsg(PadMgr* padmgr); void PadMgr_HandlePreNMI(PadMgr* padmgr); // This function must remain commented out, because it is called incorrectly in // fault.c (actual bug in game), and the compiler notices and won't compile it -// void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode); +void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode); void PadMgr_Init(PadMgr* padmgr, OSMesgQueue* siIntMsgQ, IrqMgr* irqMgr, OSId id, OSPri priority, void* stack); void Sched_SwapFrameBuffer(CfbInfo* cfbInfo); void func_800C84E4(SchedContext* sc, CfbInfo* cfbInfo); diff --git a/soh/include/segment_symbols.h b/soh/include/segment_symbols.h index 81fe34801..3b50b4eaa 100644 --- a/soh/include/segment_symbols.h +++ b/soh/include/segment_symbols.h @@ -3,20 +3,20 @@ #include "z64.h" -#define DECLARE_SEGMENT(name) \ - //extern u8 _##name##SegmentStart[]; \ +#define DECLARE_SEGMENT(name) + //extern u8 _##name##SegmentStart[]; //extern u8 _##name##SegmentEnd[]; -#define DECLARE_ROM_SEGMENT(name) \ - //extern u8 _##name##SegmentRomStart[]; \ +#define DECLARE_ROM_SEGMENT(name) + //extern u8 _##name##SegmentRomStart[]; //extern u8 _##name##SegmentRomEnd[]; #define DECLARE_BSS_SEGMENT(name) \ extern u8 _##name##SegmentBssStart[]; \ extern u8 _##name##SegmentBssEnd[]; -#define DECLARE_OVERLAY_SEGMENT(name) \ - //DECLARE_SEGMENT(ovl_##name) \ +#define DECLARE_OVERLAY_SEGMENT(name) + //DECLARE_SEGMENT(ovl_##name) //DECLARE_ROM_SEGMENT(ovl_##name) DECLARE_SEGMENT(boot) diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index dc304358d..089394e33 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -32,6 +32,8 @@ private: #endif #ifndef __cplusplus +void InitOTR(void); +void DeinitOTR(void); void VanillaItemTable_Init(); void OTRAudio_Init(); void InitAudio(); diff --git a/soh/src/code/fault.c b/soh/src/code/fault.c index c55a63a00..f7414766a 100644 --- a/soh/src/code/fault.c +++ b/soh/src/code/fault.c @@ -293,7 +293,7 @@ void Fault_Sleep(u32 duration) { void Fault_PadCallback(Input* input) { //! @bug This function is not called correctly and thus will crash from reading a bad pointer at 0x800C7E4C - PadMgr_RequestPadData(input, 0); + PadMgr_RequestPadData(&gPadMgr, input, 0); } void Fault_UpdatePadImpl() diff --git a/soh/src/code/main.c b/soh/src/code/main.c index ccfdc2019..8e9fe1776 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -3,6 +3,8 @@ #include #include "soh/OTRGlobals.h" +#include "../libultraship/CrashHandler.h" + s32 gScreenWidth = SCREEN_WIDTH; s32 gScreenHeight = SCREEN_HEIGHT; @@ -38,6 +40,10 @@ void Main_LogSystemHeap(void) { int main(int argc, char** argv) { +#ifdef __linux__ + SetupHandlerLinux(); +#endif + GameConsole_Init(); InitOTR(); BootCommands_Init(); @@ -64,14 +70,14 @@ void Main(void* arg) { Fault_Init(); SysCfb_Init(0); Heaps_Alloc(); - sysHeap = gSystemHeap; + sysHeap = (uintptr_t)gSystemHeap; fb = SysCfb_GetFbPtr(0); gSystemHeapSize = 1024 * 1024 * 4; // "System heap initalization" osSyncPrintf("システムヒープ初期化 %08x-%08x %08x\n", sysHeap, fb, gSystemHeapSize); - SystemHeap_Init(sysHeap, gSystemHeapSize); // initializes the system heap + SystemHeap_Init((void*)sysHeap, gSystemHeapSize); // initializes the system heap if (osMemSize >= 0x800000) { - debugHeap = SysCfb_GetFbEnd(); + debugHeap = (void*)SysCfb_GetFbEnd(); debugHeapSize = (0x80600000 - (uintptr_t)debugHeap); } else { debugHeapSize = 0x400; From cfaed3ded0ea32d63b6efe9f6b8eed9f021391e5 Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Wed, 31 Aug 2022 22:07:34 -0500 Subject: [PATCH 14/20] Make Biggoron ignore whether you have BGS in rando --- soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 4 ++-- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) 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 58124ef23..3cadd6afe 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 @@ -95,7 +95,7 @@ u16 EnGo_GetTextID(GlobalContext* globalCtx, Actor* thisx) { switch (thisx->params & 0xF0) { case 0x90: - if (gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { @@ -859,7 +859,7 @@ void func_80A405CC(EnGo* this, GlobalContext* globalCtx) { void EnGo_BiggoronActionFunc(EnGo* this, GlobalContext* globalCtx) { if (((this->actor.params & 0xF0) == 0x90) && (this->unk_1E0.unk_00 == 2)) { - if (gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { this->unk_1E0.unk_00 = 0; } else { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { 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 9f6ff147e..db1154961 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 @@ -595,7 +595,7 @@ s16 EnGo2_GetStateGoronCityLink(GlobalContext* globalCtx, EnGo2* this) { u16 EnGo2_GetTextIdGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { Player* player = GET_PLAYER(globalCtx); - if (gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK; return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { @@ -622,10 +622,6 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { } if(gSaveContext.n64ddFlag) { - if (INV_CONTENT(ITEM_CLAIM_CHECK) != ITEM_CLAIM_CHECK) { - return 0; - } - EnGo2_GetItemEntry(this, globalCtx, Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS)); Flags_SetTreasure(globalCtx, 0x1F); } else { @@ -1063,7 +1059,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, GlobalContext* globalCtx, Player* play u16 textId; if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) { - if (gSaveContext.bgsFlag) { + if ((!gSaveContext.n64ddFlag && gSaveContext.bgsFlag)) { if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) { this->actor.textId = 0x3003; } else { @@ -1071,16 +1067,20 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, GlobalContext* globalCtx, Player* play } player->actor.textId = this->actor.textId; - } else if (!gSaveContext.bgsFlag && (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK)) { + } else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) { - if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { + if (gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F)) { + textId = 0x3003; + } else if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { textId = 0x305E; } else { textId = 0x305D; } this->actor.textId = textId; } else { - if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { + if (gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F)) { + textId = 0x305E; + } else if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { textId = 0x3002; } else { textId = 0x305D; From 354905fb7dd6a9a89410f0129429b5ee419ebc39 Mon Sep 17 00:00:00 2001 From: aMannus Date: Thu, 1 Sep 2022 11:06:05 +0200 Subject: [PATCH 15/20] Added 1 more name --- soh/soh/Enhancements/randomizer/randomizer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index fd018ff7b..b46fbb4d2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -36,14 +36,14 @@ const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; -static const char* englishRupeeNames[52] = { +static const char* englishRupeeNames[53] = { "Rupees", "Bitcoin", "Bananas", "Cornflakes", "Gummybears", "Floopies", "Dollars", "Lemmings", "Emeralds", "Bucks", "Rubles", "Diamonds", "Moons", "Stars", "Mana", "Doll Hairs", "Dogecoin", "Mushrooms", "Experience", "Friends", "Coins", "Rings", "Gil", "Pokédollars", "Bells", "Orbs", "Bottle Caps", "Simoleons", "Pokémon", "Toys", "Smackaroos", "Zorkmids", "Zenny", "Bones", "Souls", "Studs", "Munny", "Rubies", "Gald", "Gold", "Shillings", "Pounds", "Glimmer", "Potch", "Robux", "V-Bucks", "Bratwürste", "Mesetas", - "Bath Salts", "Coal", "Euro", "Spoons" + "Bath Salts", "Coal", "Euro", "Spoons", "Cucumbers" }; static const char* germanRupeeNames[41] = { From 0a744cde0132dd7ad5de27e1e6d849bba24b4720 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 1 Sep 2022 08:11:17 -0500 Subject: [PATCH 16/20] Clarify comments --- .../actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 8 +++++--- soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 28a63bbf6..6bb097d89 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -143,7 +143,8 @@ void EnBomBowMan_BlinkAwake(EnBomBowlMan* this, GlobalContext* globalCtx) { } } - // Check for Bomb Bag or Bombchus if Rando is enabled, depending on whether bombchus are considered in logic + // In randomizer, only check for bomb bag when bombchus aren't in logic + // and only check for bombchus when bombchus are in logic if (gSaveContext.n64ddFlag) { u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC); if ((!bombchusInLogic && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) || @@ -178,13 +179,14 @@ void EnBomBowMan_CheckBeatenDC(EnBomBowlMan* this, GlobalContext* globalCtx) { this->eyeMode = CHU_GIRL_EYES_AWAKE; this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; - // Check if beaten Dodongo's Cavern if not rando'd - // check for bomb bag or bombchus if rando'd depending on whether chus are in logic bool bombchuBowlingClosed; if (gSaveContext.n64ddFlag) { + // when rando'd, check if we have bombchus if chus are in logic + // and check if we have a bomb bag if chus aren't in logic u8 explosive = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) ? ITEM_BOMBCHU : ITEM_BOMB; bombchuBowlingClosed = (INV_CONTENT(explosive) == ITEM_NONE); } else { + // if not rando'd, check if we have beaten Dodongo's Cavern bombchuBowlingClosed = !((gSaveContext.eventChkInf[2] & 0x20) || BREG(2)); } if (bombchuBowlingClosed) { 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 54af786a6..cbc2e9749 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 @@ -871,9 +871,12 @@ void EnGirlA_BuyEvent_ZoraTunic(GlobalContext* globalCtx, EnGirlA* this) { void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this) { Rupees_ChangeBy(-this->basePrice); + // Normally, buying a bombchu pack sets a flag indicating the pack is now sold out + // If they're in logic for rando, skip setting that flag so they can be purchased repeatedly if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { return; } + switch (this->actor.params) { case SI_BOMBCHU_10_2: gSaveContext.itemGetInf[0] |= 0x40; @@ -1065,6 +1068,7 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, GlobalContext* globalCtx) { this->canBuyFunc = itemEntry->canBuyFunc; this->itemGiveFunc = itemEntry->itemGiveFunc; this->buyEventFunc = itemEntry->buyEventFunc; + // If chus are in logic, make the 10 pack affordable without a wallet upgrade if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && this->getItemId == GI_BOMBCHUS_10) { this->basePrice = 99; From c84654b202a84159b028f78a3e64d0a605d5a46a Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 1 Sep 2022 09:23:08 -0500 Subject: [PATCH 17/20] Always check n64ddFlag before bgsFlag that order is consistent with the existing condition in EnGo2_GetStateGoronDmtBiggoron --- soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 4 ++-- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 3cadd6afe..4e803af0a 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 @@ -95,7 +95,7 @@ u16 EnGo_GetTextID(GlobalContext* globalCtx, Actor* thisx) { switch (thisx->params & 0xF0) { case 0x90: - if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { + if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) { return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { @@ -859,7 +859,7 @@ void func_80A405CC(EnGo* this, GlobalContext* globalCtx) { void EnGo_BiggoronActionFunc(EnGo* this, GlobalContext* globalCtx) { if (((this->actor.params & 0xF0) == 0x90) && (this->unk_1E0.unk_00 == 2)) { - if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { + if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) { this->unk_1E0.unk_00 = 0; } else { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { 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 db1154961..c8b635902 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 @@ -595,7 +595,7 @@ s16 EnGo2_GetStateGoronCityLink(GlobalContext* globalCtx, EnGo2* this) { u16 EnGo2_GetTextIdGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { Player* player = GET_PLAYER(globalCtx); - if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { + if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) { player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK; return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { From a55eb572db92b04565d3bb58bad02591bff01f65 Mon Sep 17 00:00:00 2001 From: briaguya Date: Thu, 1 Sep 2022 12:06:41 -0400 Subject: [PATCH 18/20] fix keysanity related build issue --- .../Enhancements/randomizer/randomizer.cpp | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5af2cb9e7..d1548ea9b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1701,43 +1701,6 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BUY_BOMBS_535: case RG_BUY_RED_POTION_40: case RG_BUY_RED_POTION_50: - //RANDO TODO: Fix this to return false if keysanity is on. - case RG_FOREST_TEMPLE_SMALL_KEY: - case RG_FIRE_TEMPLE_SMALL_KEY: - case RG_WATER_TEMPLE_SMALL_KEY: - case RG_SPIRIT_TEMPLE_SMALL_KEY: - case RG_SHADOW_TEMPLE_SMALL_KEY: - case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: - case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: - case RG_GERUDO_FORTRESS_SMALL_KEY: - case RG_GANONS_CASTLE_SMALL_KEY: - case RG_FOREST_TEMPLE_BOSS_KEY: - case RG_FIRE_TEMPLE_BOSS_KEY: - case RG_WATER_TEMPLE_BOSS_KEY: - case RG_SPIRIT_TEMPLE_BOSS_KEY: - case RG_SHADOW_TEMPLE_BOSS_KEY: - case RG_GANONS_CASTLE_BOSS_KEY: - case RG_DEKU_TREE_COMPASS: - case RG_DODONGOS_CAVERN_COMPASS: - case RG_JABU_JABUS_BELLY_COMPASS: - case RG_FOREST_TEMPLE_COMPASS: - case RG_FIRE_TEMPLE_COMPASS: - case RG_WATER_TEMPLE_COMPASS: - case RG_SPIRIT_TEMPLE_COMPASS: - case RG_SHADOW_TEMPLE_COMPASS: - case RG_BOTTOM_OF_THE_WELL_COMPASS: - case RG_ICE_CAVERN_COMPASS: - case RG_DEKU_TREE_MAP: - case RG_DODONGOS_CAVERN_MAP: - case RG_JABU_JABUS_BELLY_MAP: - case RG_FOREST_TEMPLE_MAP: - case RG_FIRE_TEMPLE_MAP: - case RG_WATER_TEMPLE_MAP: - case RG_SPIRIT_TEMPLE_MAP: - case RG_SHADOW_TEMPLE_MAP: - case RG_BOTTOM_OF_THE_WELL_MAP: - case RG_ICE_CAVERN_MAP: - return true; case RG_FOREST_TEMPLE_SMALL_KEY: case RG_FIRE_TEMPLE_SMALL_KEY: case RG_WATER_TEMPLE_SMALL_KEY: From 1e13879c6b844e38ca2f67a0bec38d350133860a Mon Sep 17 00:00:00 2001 From: aMannus Date: Thu, 1 Sep 2022 19:43:08 +0200 Subject: [PATCH 19/20] Removed name --- soh/soh/Enhancements/randomizer/randomizer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b46fbb4d2..e999c0442 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -36,14 +36,14 @@ const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; -static const char* englishRupeeNames[53] = { - "Rupees", "Bitcoin", "Bananas", "Cornflakes", "Gummybears", "Floopies", "Dollars", "Lemmings", - "Emeralds", "Bucks", "Rubles", "Diamonds", "Moons", "Stars", "Mana", "Doll Hairs", - "Dogecoin", "Mushrooms", "Experience", "Friends", "Coins", "Rings", "Gil", "Pokédollars", - "Bells", "Orbs", "Bottle Caps", "Simoleons", "Pokémon", "Toys", "Smackaroos", "Zorkmids", - "Zenny", "Bones", "Souls", "Studs", "Munny", "Rubies", "Gald", "Gold", - "Shillings", "Pounds", "Glimmer", "Potch", "Robux", "V-Bucks", "Bratwürste", "Mesetas", - "Bath Salts", "Coal", "Euro", "Spoons", "Cucumbers" +static const char* englishRupeeNames[52] = { + "Rupees", "Bitcoin", "Bananas", "Cornflakes", "Gummybears", "Floopies", "Dollars", "Lemmings", + "Emeralds", "Bucks", "Rubles", "Diamonds", "Moons", "Stars", "Mana", "Doll Hairs", + "Dogecoin", "Mushrooms", "Experience", "Friends", "Coins", "Rings", "Gil", "Pokédollars", + "Bells", "Orbs", "Bottle Caps", "Simoleons", "Pokémon", "Toys", "Smackaroos", "Zorkmids", + "Zenny", "Bones", "Souls", "Studs", "Munny", "Rubies", "Gald", "Gold", + "Shillings", "Pounds", "Glimmer", "Potch", "Robux", "V-Bucks", "Bratwürste", "Mesetas", + "Coal", "Euro", "Spoons", "Cucumbers" }; static const char* germanRupeeNames[41] = { From 812a1e79705d2249d66737148ca1b88de3bd30e8 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 1 Sep 2022 17:50:12 -0400 Subject: [PATCH 20/20] Added return statement in IsVanillaItem before keys. --- soh/soh/Enhancements/randomizer/randomizer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 9a4f9fa1b..9bf46e430 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1707,6 +1707,7 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BUY_BOMBS_535: case RG_BUY_RED_POTION_40: case RG_BUY_RED_POTION_50: + return true; case RG_FOREST_TEMPLE_SMALL_KEY: case RG_FIRE_TEMPLE_SMALL_KEY: case RG_WATER_TEMPLE_SMALL_KEY: