diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 2e5ecce26..4d6de4071 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -25,6 +25,7 @@ typedef enum { TEXT_HUGE_RUPEE = 0xF2, TEXT_BEAN_SALESMAN = 0x405E, TEXT_MEDIGORON = 0x304C, + TEXT_GRANNYS_SHOP = 0x500C, TEXT_CARPET_SALESMAN_1 = 0x6077, TEXT_CARPET_SALESMAN_2 = 0x6078, TEXT_MARKET_GUARD_NIGHT = 0x7003, diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index f8e692ee4..8ed825b10 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -488,8 +488,9 @@ const std::vector flagTables = { { RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7, "SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7" }, { RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8, "SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8" }, - { RAND_INF_MERCHANTS_MEDIGORON, "RAND_INF_MERCHANTS_MEDIGORON" }, { RAND_INF_MERCHANTS_CARPET_SALESMAN, "RAND_INF_MERCHANTS_CARPET_SALESMAN" }, + { RAND_INF_MERCHANTS_MEDIGORON, "RAND_INF_MERCHANTS_MEDIGORON" }, + { RAND_INF_MERCHANTS_GRANNYS_SHOP, "RAND_INF_MERCHANTS_GRANNY_SHOP"}, { RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, "ADULT_TRADES_LW_TRADE_COJIRO" }, { RAND_INF_ADULT_TRADES_GV_TRADE_SAW, "ADULT_TRADES_GV_TRADE_SAW" }, @@ -498,5 +499,6 @@ const std::vector flagTables = { { RAND_INF_ADULT_TRADES_DMT_TRADE_EYEDROPS, "ADULT_TRADES_DMT_TRADE_EYEDROPS" }, { RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD, "KAK_100_GOLD_SKULLTULA_REWARD" }, + { RAND_INF_GREG_FOUND, "RAND_INF_GREG_FOUND" }, } }, -}; \ No newline at end of file +}; diff --git a/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp b/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp index acd247312..59f157d9e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/custom_messages.cpp @@ -432,6 +432,32 @@ constexpr std::array DungeonColors = { textStr->replace(carrotSymbol, 1, INSTANT_TEXT_OFF()+WAIT_FOR_INPUT()+INSTANT_TEXT_ON()); carrotSymbol = textStr->find('^'); } + + //If there's a two-way choice and only 1 newline before it in the same text box, add another one + size_t choice = textStr->find(TWO_WAY_CHOICE()); + if (choice != std::string::npos) { + size_t newLinesCount = 0; + size_t lastBoxBreak = textStr->rfind(WAIT_FOR_INPUT(), choice); + lastNewline = choice; + + if (lastBoxBreak == std::string::npos) { + lastBoxBreak = 0; + } + + while ((lastNewline != std::string::npos)) { + lastNewline = textStr->rfind(NEWLINE(), lastNewline - 1); + if (lastNewline != std::string::npos && lastNewline > lastBoxBreak) { + newLinesCount++; + } else { + break; + } + } + + if (newLinesCount <= 1) { + textStr->replace(choice, TWO_WAY_CHOICE().length(), NEWLINE()+TWO_WAY_CHOICE()); + } + } + //add colors for (auto color : colors) { size_t firstHashtag = textStr->find('#'); diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index d080411ff..358ae285d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -3126,6 +3126,13 @@ void HintTable_Init() { /*spanish*/ "!#^La marca que te guiará al #Templo del&Espíritu# es la #bandera que está a la&" + IF_NOT_MQ() + "izquierda" + MQ_ELSE() + "derecha" + MQ_END() + "# al salir de aquí. ¡Nos vemos!" }, }); + + hintTable[GRANNY_DIALOG] = HintText::MerchantsDialogs({ + // obscure text + Text{ "! How about #100 Rupees#?&" + TWO_WAY_CHOICE() + "#Buy&Don't buy#", + /*french*/ "! Que dis-tu de #100 rubis#?&" + TWO_WAY_CHOICE() + "#Acheter&Ne pas acheter#", + /*spanish*/ ". Vendo por #100 rupias#.&" + TWO_WAY_CHOICE() + "#Comprar&No comprar#" }, + }); } int32_t StonesRequiredBySettings() { diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index f69bf3502..68454769a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -739,14 +739,19 @@ void CreateAltarText() { void CreateMerchantsHints() { Text medigoronItemText = Location(GC_MEDIGORON)->GetPlacedItem().GetHint().GetText(); + Text grannyItemText = Location(KAK_GRANNYS_SHOP)->GetPlacedItem().GetHint().GetText(); Text carpetSalesmanItemText = Location(WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetText(); Text carpetSalesmanItemClearText = Location(WASTELAND_BOMBCHU_SALESMAN)->GetPlacedItem().GetHint().GetClear(); + Text grannyCapitalItemText = grannyItemText.Capitalize(); + Text medigoronText = Hint(MEDIGORON_DIALOG_FIRST).GetText()+medigoronItemText+Hint(MEDIGORON_DIALOG_SECOND).GetText(); + Text grannyText = grannyCapitalItemText+Hint(GRANNY_DIALOG).GetText(); Text carpetSalesmanTextOne = Hint(CARPET_SALESMAN_DIALOG_FIRST).GetText()+carpetSalesmanItemText+Hint(CARPET_SALESMAN_DIALOG_SECOND).GetText(); Text carpetSalesmanTextTwo = Hint(CARPET_SALESMAN_DIALOG_THIRD).GetText()+carpetSalesmanItemClearText+Hint(CARPET_SALESMAN_DIALOG_FOURTH).GetText(); CreateMessageFromTextObject(0x9120, 0, 2, 3, AddColorsAndFormat(medigoronText, {QM_RED, QM_GREEN})); + CreateMessageFromTextObject(0x9121, 0, 2, 3, AddColorsAndFormat(grannyText, {QM_RED, QM_GREEN})); CreateMessageFromTextObject(0x6077, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextOne, {QM_RED, QM_GREEN})); CreateMessageFromTextObject(0x6078, 0, 2, 3, AddColorsAndFormat(carpetSalesmanTextTwo, {QM_RED, QM_YELLOW, QM_RED})); } diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp index ec7e4a9a7..bf0257064 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp @@ -120,6 +120,7 @@ void LocationTable_Init() { locationTable[KAK_MAN_ON_ROOF] = ItemLocation::Base (RC_KAK_MAN_ON_ROOF, 0x52, 0x3E, "Kak Man on Roof", KAK_MAN_ON_ROOF, PIECE_OF_HEART, {Category::cKakarikoVillage, Category::cKakariko,}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); locationTable[KAK_SHOOTING_GALLERY_REWARD] = ItemLocation::Base (RC_KAK_SHOOTING_GALLERY_REWARD, 0x42, 0x30, "Kak Shooting Gallery Reward", KAK_SHOOTING_GALLERY_REWARD, PROGRESSIVE_BOW, {Category::cKakarikoVillage, Category::cKakariko, Category::cMinigame}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); locationTable[KAK_TRADE_ODD_MUSHROOM] = ItemLocation::Base (RC_KAK_TRADE_ODD_MUSHROOM, 0x4E, 0x20, "Kak Trade Odd Mushroom", KAK_TRADE_ODD_MUSHROOM, ODD_POTION, {Category::cKakarikoVillage, Category::cKakariko, Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(56), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); + locationTable[KAK_GRANNYS_SHOP] = ItemLocation::Base (RC_KAK_GRANNYS_SHOP, 0x4E, 0x10, "Kak Granny's Shop", KAK_GRANNYS_SHOP, BLUE_POTION_REFILL, {Category::cKakarikoVillage, Category::cKakariko, Category::cMerchant}, SpoilerCollectionCheck::EventChkInf(0x32), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); locationTable[KAK_ANJU_AS_ADULT] = ItemLocation::Base (RC_KAK_ANJU_AS_ADULT, 0x52, 0x1D, "Kak Anju as Adult", KAK_ANJU_AS_ADULT, CLAIM_CHECK, {Category::cKakarikoVillage, Category::cKakariko,}, SpoilerCollectionCheck::ItemGetInf(36), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); locationTable[KAK_ANJU_AS_CHILD] = ItemLocation::Base (RC_KAK_ANJU_AS_CHILD, 0x52, 0x0F, "Kak Anju as Child", KAK_ANJU_AS_CHILD, EMPTY_BOTTLE, {Category::cKakarikoVillage, Category::cKakariko, Category::cMinigame}, SpoilerCollectionCheck::ItemGetInf(4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); locationTable[KAK_TRADE_POCKET_CUCCO] = ItemLocation::Base (RC_KAK_TRADE_POCKET_CUCCO, 0x52, 0x0E, "Kak Trade Pocket Cucco", KAK_TRADE_POCKET_CUCCO, COJIRO, {Category::cKakarikoVillage, Category::cKakariko, Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(38), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); @@ -1281,6 +1282,7 @@ std::vector overworldLocations = { KAK_MAN_ON_ROOF, KAK_SHOOTING_GALLERY_REWARD, KAK_TRADE_ODD_MUSHROOM, + KAK_GRANNYS_SHOP, KAK_ANJU_AS_CHILD, KAK_ANJU_AS_ADULT, KAK_TRADE_POCKET_CUCCO, diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 39cf5f479..348733620 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -725,6 +725,7 @@ void GenerateItemPool() { AddItemToMainPool(BOMBCHU_10); } } else { + PlaceItemInLocation(KAK_GRANNYS_SHOP, BOTTLE_WITH_BLUE_POTION, false, true); PlaceItemInLocation(GC_MEDIGORON, GIANTS_KNIFE, false, true); PlaceItemInLocation(WASTELAND_BOMBCHU_SALESMAN, BOMBCHU_10, false, true); } @@ -1071,7 +1072,11 @@ void GenerateItemPool() { IceTrapModels.push_back(ItemTable(RandomElement(bottles)).GetItemID()); //Get one random bottle type for ice traps for (uint8_t i = 0; i < bottleCount; i++) { if (i >= rutoBottles) { - AddRandomBottle(bottles); + if ((i == bottleCount - 1) && ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) { + AddItemToMainPool(BOTTLE_WITH_BLUE_POTION); + } else { + AddRandomBottle(bottles); + } } else { AddItemToMainPool(RUTOS_LETTER); } diff --git a/soh/soh/Enhancements/randomizer/3drando/keys.hpp b/soh/soh/Enhancements/randomizer/3drando/keys.hpp index 5536265b3..cc72e6235 100644 --- a/soh/soh/Enhancements/randomizer/3drando/keys.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/keys.hpp @@ -388,6 +388,7 @@ typedef enum { KAK_REDEAD_GROTTO_CHEST, KAK_SHOOTING_GALLERY_REWARD, KAK_TRADE_ODD_MUSHROOM, + KAK_GRANNYS_SHOP, KAK_10_GOLD_SKULLTULA_REWARD, KAK_20_GOLD_SKULLTULA_REWARD, KAK_30_GOLD_SKULLTULA_REWARD, @@ -1821,6 +1822,7 @@ typedef enum { CARPET_SALESMAN_DIALOG_SECOND, CARPET_SALESMAN_DIALOG_THIRD, CARPET_SALESMAN_DIALOG_FOURTH, + GRANNY_DIALOG, KEY_ENUM_MAX, } Key; \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp index d75b06f84..611827f1a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_kakariko.cpp @@ -191,6 +191,7 @@ void AreaTable_Init_Kakariko() { EventAccess(&OddPoulticeAccess, {[]{return OddPoulticeAccess || (IsAdult && (OddMushroomAccess || (OddMushroom && DisableTradeRevert)));}}), }, { LocationAccess(KAK_TRADE_ODD_MUSHROOM, {[]{return IsAdult && OddMushroom;}}), + LocationAccess(KAK_GRANNYS_SHOP, {[]{return IsAdult && OddMushroom && AdultsWallet;}}), }, { //Exits Entrance(KAK_BACKYARD, {[]{return true;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp index eabfe7ccf..0a9a3b411 100644 --- a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp @@ -447,15 +447,16 @@ string_view magicBeansDesc = "Enabling this adds a pack of 10 beans t /*------------------------------ // | SHUFFLE MERCHANTS | // ------------------------------*/ // -string_view merchantsDesc = "Enabling this adds a Giant's Knife and a pack\n" // - "of Bombchus to the item pool and changes both\n" // - "Medigoron and the Haunted Wasteland Carpet\n" // - "Salesman to sell a random item once at the price\n" - "of 200 rupees."; // -string_view merchantsHintsDesc = "These hints will make Medigoron and the Carpet\n" // - "Salesman tell you which item they're selling.\n" // +string_view merchantsDesc = "Enabling this changes Medigoron, Granny and the\n"// + "Carpet Salesman to sell a random item once at a\n"// + "high price (100 for Granny, 200 for the others).\n\n" + "A Giant's Knife and a pack of Bombchus will be\n" // + "added to the item pool, and one of the bottles\n" // + "will contain a Blue Potion"; // +string_view merchantsHintsDesc = "These hints will make the merchants tell you\n" // + "which item they're selling.\n" // "\n" // - "The Clearer Hints setting will affect how they\n" // + "The Hint Clarity setting will affect how they\n" // "refer to the item."; // /*------------------------------ // | SHUFFLE FROG SONG RUPEES | // diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 7d61fd71f..3cba56b08 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -1792,12 +1792,14 @@ namespace Settings { IncludeAndHide({ZR_MAGIC_BEAN_SALESMAN}); } - //Force include Medigoron and Carpet salesman if Shuffle Merchants is off + //Force include Medigoron, Granny and Carpet salesman if Shuffle Merchants is off if (ShuffleMerchants.IsNot(SHUFFLEMERCHANTS_OFF)) { Unhide({GC_MEDIGORON}); + Unhide({KAK_GRANNYS_SHOP}); Unhide({WASTELAND_BOMBCHU_SALESMAN}); } else { IncludeAndHide({GC_MEDIGORON}); + IncludeAndHide({KAK_GRANNYS_SHOP}); IncludeAndHide({WASTELAND_BOMBCHU_SALESMAN}); } diff --git a/soh/soh/Enhancements/randomizer/3drando/text.hpp b/soh/soh/Enhancements/randomizer/3drando/text.hpp index 7abc56b5d..c1e32ddfd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/text.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/text.hpp @@ -58,6 +58,15 @@ public: } } + // Convert first char to upper case + Text Capitalize(void) const { + Text cap = *this + ""; + for (std::string* str : {&cap.english, &cap.french, &cap.spanish}) { + (*str)[0] = std::toupper((*str)[0]); + } + return cap; + } + //find the appropriate bars that separate singular from plural void SetForm(int form) { for (std::string* str : {&english, &french, &spanish}) { diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ba7fa20ba..30347c308 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -540,7 +540,19 @@ void Randomizer::LoadMerchantMessages(const char* spoilerFileName) { "Wie wäre es mit %r&{{item}}%w für %g200 Rubine?%w\x1B&%gJa!&Nein!%w", "Veux-tu acheter %r&{{item}}%w pour %g200 rubis?%w\x1B&%gOui&Non&w" }); - + + //Granny Shopy + //RANDOTODO: Implement obscure/ambiguous hints + CustomMessageManager::Instance->CreateMessage( + Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP, + { + TEXTBOX_TYPE_BLACK, + TEXTBOX_POS_BOTTOM, + "%r{{item}}%w!&How about %g100 rupees%w?\x1B&%gYes&No%w", + "%r{{item}}%w!&Wie wäre es mit %g100 Rubine?%w\x1B&%gJa!&Nein!%w", + "%r{{item}}%w!&Que dis-tu de %g100 rubis?%w\x1B&%gOui&Non&w" + }); + //Carpet Salesman //RANDOTODO: Implement obscure/ambiguous hints std::vector cgBoxTwoText; @@ -2591,7 +2603,8 @@ std::map rcToRandomizerInf = { { RC_MARKET_BOMBCHU_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7 }, { RC_MARKET_BOMBCHU_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8 }, { RC_GC_MEDIGORON, RAND_INF_MERCHANTS_MEDIGORON }, - { RC_WASTELAND_BOMBCHU_SALESMAN, RAND_INF_MERCHANTS_CARPET_SALESMAN }, + { RC_KAK_GRANNYS_SHOP, RAND_INF_MERCHANTS_GRANNYS_SHOP }, + { RC_WASTELAND_BOMBCHU_SALESMAN, RAND_INF_MERCHANTS_CARPET_SALESMAN }, { RC_LW_TRADE_COJIRO, RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO }, { RC_GV_TRADE_SAW, RAND_INF_ADULT_TRADES_GV_TRADE_SAW }, { RC_DMT_TRADE_BROKEN_SWORD, RAND_INF_ADULT_TRADES_DMT_TRADE_BROKEN_SWORD }, @@ -3776,9 +3789,10 @@ void DrawRandoEditor(bool& open) { // Shuffle Merchants ImGui::Text(Settings::ShuffleMerchants.GetName().c_str()); UIWidgets::InsertHelpHoverText( - "Enabling this adds a Giant's Knife and a pack of Bombchus to the item pool " - "and changes both Medigoron and the Haunted Wasteland Carpet Salesman to sell " - "a random item once at the price of 200 rupees.\n\n" + "Enabling this changes Medigoron, Granny and the Carpet Salesman to sell a random item " + "once at a high price (100 for Granny, 200 for the others).\n" + "A Giant's Knife and a pack of Bombchus will be added to the item pool, and " + "one of the bottles will contain a Blue Potion.\n\n" "On (no hints) - Salesmen will be included but won't tell you what you'll get.\n" "On (with hints) - Salesmen will be included and you'll know what you're buying." ); @@ -4664,6 +4678,11 @@ CustomMessageEntry Randomizer::GetMerchantMessage(RandomizerInf randomizerInf, u if (textId == TEXT_SCRUB_RANDOM && shopItemPrice == 0) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM_FREE); + } else if (textId == TEXT_GRANNYS_SHOP) { + // Capitalize the first letter for the item in Granny's text as the item is the first word presented + for (auto &itemName : shopItemName) { + itemName[0] = std::toupper(itemName[0]); + } } CustomMessageManager::ReplaceStringInMessage(messageEntry, "{{item}}", shopItemName[0], shopItemName[1], shopItemName[2]); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index b52f44e73..13a1af3bd 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -158,6 +158,7 @@ typedef enum { RC_KAK_REDEAD_GROTTO_CHEST, RC_KAK_SHOOTING_GALLERY_REWARD, RC_KAK_TRADE_ODD_MUSHROOM, + RC_KAK_GRANNYS_SHOP, RC_KAK_TRADE_POCKET_CUCCO, RC_KAK_10_GOLD_SKULLTULA_REWARD, RC_KAK_20_GOLD_SKULLTULA_REWARD, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index a921dfd70..9dc1ce081 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -224,6 +224,7 @@ std::map rcObjects = { RC_OBJECT(RC_KAK_MAN_ON_ROOF, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Man on Roof", "Kak Man on Roof"), RC_OBJECT(RC_KAK_SHOOTING_GALLERY_REWARD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SYATEKIJYOU, 0x00, GI_NONE, "Shooting Gallery Reward", "Kak Shooting Gallery Reward"), RC_OBJECT(RC_KAK_TRADE_ODD_MUSHROOM, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_MAHOUYA, 0x00, GI_NONE, "Trade Odd Mushroom", "Kak Trade Odd Mushroom"), + RC_OBJECT(RC_KAK_GRANNYS_SHOP, RCVORMQ_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_MAHOUYA, 0x00, GI_POTION_BLUE, "Granny's Shop", "Kak Granny's Shop"), RC_OBJECT(RC_KAK_ANJU_AS_ADULT, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Anju as Adult", "Kak Anju as Adult"), RC_OBJECT(RC_KAK_ANJU_AS_CHILD, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Anju as Child", "Kak Anju as Child"), RC_OBJECT(RC_KAK_TRADE_POCKET_CUCCO, RCVORMQ_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SPOT01, 0x00, GI_NONE, "Trade Pocket Cucco", "Kak Trade Pocket Cucco"), diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 3595cf3dc..70157d3e1 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -142,6 +142,7 @@ typedef enum { RAND_INF_MERCHANTS_CARPET_SALESMAN, RAND_INF_MERCHANTS_MEDIGORON, + RAND_INF_MERCHANTS_GRANNYS_SHOP, RAND_INF_ADULT_TRADES_LW_TRADE_COJIRO, RAND_INF_ADULT_TRADES_GV_TRADE_SAW, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 854aac30e..541326b28 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1773,11 +1773,20 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId); } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN); - } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && (textId == TEXT_MEDIGORON || + } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && (textId == TEXT_MEDIGORON || + (textId == TEXT_GRANNYS_SHOP && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && + (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) || (textId == TEXT_CARPET_SALESMAN_1 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) || (textId == TEXT_CARPET_SALESMAN_2 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)))) { - RandomizerInf randoInf = (RandomizerInf)(textId == TEXT_MEDIGORON ? RAND_INF_MERCHANTS_MEDIGORON : RAND_INF_MERCHANTS_CARPET_SALESMAN); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_ON_HINT); + RandomizerInf randoInf; + if (textId == TEXT_MEDIGORON) { + randoInf = RAND_INF_MERCHANTS_MEDIGORON; + } else if (textId == TEXT_GRANNYS_SHOP) { + randoInf = RAND_INF_MERCHANTS_GRANNYS_SHOP; + } else { + randoInf = RAND_INF_MERCHANTS_CARPET_SALESMAN; + } + messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_ON_HINT); } 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); 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 92605c680..84b4cd816 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 @@ -174,6 +174,9 @@ void EnDs_OfferOddPotion(EnDs* this, PlayState* play) { s32 EnDs_CheckRupeesAndBottle() { if (gSaveContext.rupees < 100) { return 0; + } else if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP)) { + return 2; } else if (Inventory_HasEmptyBottle() == 0) { return 1; } else { @@ -183,10 +186,23 @@ s32 EnDs_CheckRupeesAndBottle() { void EnDs_GiveBluePotion(EnDs* this, PlayState* play) { if (Actor_HasParent(&this->actor, play)) { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP)) { + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP); + } + this->actor.parent = NULL; this->actionFunc = EnDs_Talk; } else { - func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP)) { + GetItemEntry entry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE); + GiveItemEntryFromActor(&this->actor, play, entry, 10000.0f, 50.0f); + } else { + func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + } } } @@ -205,10 +221,20 @@ void EnDs_OfferBluePotion(EnDs* this, PlayState* play) { case 2: // have 100 rupees and empty bottle Rupees_ChangeBy(-100); this->actor.flags &= ~ACTOR_FLAG_16; - GetItemEntry entry = ItemTable_Retrieve(GI_POTION_BLUE); - gSaveContext.pendingSale = entry.itemId; - gSaveContext.pendingSaleMod = entry.modIndex; - func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + GetItemEntry itemEntry; + + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != RO_SHUFFLE_MERCHANTS_OFF && + (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP)) { + itemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_GRANNYS_SHOP, GI_POTION_BLUE); + GiveItemEntryFromActor(&this->actor, play, itemEntry, 10000.0f, 50.0f); + } else { + itemEntry = ItemTable_Retrieve(GI_POTION_BLUE); + func_8002F434(&this->actor, play, GI_POTION_BLUE, 10000.0f, 50.0f); + } + + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; this->actionFunc = EnDs_GiveBluePotion; return; } @@ -229,7 +255,8 @@ void EnDs_Wait(EnDs* this, PlayState* play) { Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); player->actor.textId = 0x504A; this->actionFunc = EnDs_OfferOddPotion; - } else if (gSaveContext.itemGetInf[3] & 1) { + } else if ((gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF) || + gSaveContext.itemGetInf[3] & 1) { player->actor.textId = 0x500C; this->actionFunc = EnDs_OfferBluePotion; } else { 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 414c35d3a..2519fcb1e 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 @@ -251,18 +251,21 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { Message_ContinueTextbox(play, 0xC8); this->actionFunc = func_80A3DD7C; } else { + GetItemEntry itemEntry; + 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; + itemEntry = Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE); GiveItemEntryFromActor(&this->actor, play, itemEntry, 415.0f, 10.0f); gSaveContext.infTable[11] |= 2; - this->actionFunc = func_80A3DF00; } else { - gSaveContext.pendingSale = ItemTable_Retrieve(GI_SWORD_KNIFE).itemId; + itemEntry = ItemTable_Retrieve(GI_SWORD_KNIFE); func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); - this->actionFunc = func_80A3DF00; } + + gSaveContext.pendingSale = itemEntry.itemId; + gSaveContext.pendingSaleMod = itemEntry.modIndex; + this->actionFunc = func_80A3DF00; } break; case 1: // no @@ -283,15 +286,13 @@ 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) && + 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); 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); } }