diff --git a/soh/soh/Enhancements/Presets/PresetEntries.cpp b/soh/soh/Enhancements/Presets/PresetEntries.cpp index c9ca5c24f..d94323d08 100644 --- a/soh/soh/Enhancements/Presets/PresetEntries.cpp +++ b/soh/soh/Enhancements/Presets/PresetEntries.cpp @@ -316,7 +316,7 @@ const std::vector randomizerBeginnerPresetEntries = { // Gamplay tab PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1), - PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1), @@ -387,7 +387,7 @@ const std::vector randomizerStandardPresetEntries = { // Gamplay tab PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1), - PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1), @@ -469,7 +469,7 @@ const std::vector randomizerAdvancedPresetEntries = { // Gamplay tab PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1), - PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipChildZelda"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), 1), @@ -568,7 +568,7 @@ const std::vector hellModePresetEntries = { // Gamplay tab PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("CuccosToReturn"), 1), - PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 0), + PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("SkipEponaRace"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("BombchuBag"), 1), PRESET_ENTRY_S32(CVAR_RANDOMIZER_SETTING("EnableBombchuDrops"), 1), diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index e7c559857..3bcbaf7b0 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -162,6 +162,7 @@ typedef enum { TEXT_ANJU_THANKS_FOR_FINDING_MY_CUCCOS = 0x503B, TEXT_ANJU_ROUND_THEM_UP_OR_YOULL_PAY = 0x503C, TEXT_ANJU_DONT_TEASE_MY_CUCCOS = 0x503D, + TEXT_BIG_POE_COLLECTED_RANDO = 0x5090, TEXT_HBA_NOT_ON_HORSE = 0x603F, TEXT_HBA_INITIAL_EXPLAINATION = 0x6040, TEXT_HBA_WANT_TO_TRY_AGAIN_YES_NO = 0x6041, diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index d57d5029a..d9ffca0d4 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -228,6 +228,14 @@ typedef enum { // - `*Actor` (interactRangeActor) VB_BOTTLE_ACTOR, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnPoField` + VB_BOTTLE_BIG_POE, + // #### `result` // ```c // ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) || @@ -1663,6 +1671,14 @@ typedef enum { // - `*EnRu1` VB_RUTO_WANT_TO_BE_TOSSED_TO_SAPPHIRE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnGb` + VB_SELL_POES_TO_POE_COLLECTOR, + // #### `result` // ```c // true diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index dcae4842c..4339c930b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -159,11 +159,6 @@ static void ValidateOtherEntrance(GetAccessibleLocationsStruct& gals) { ApplyStartingInventory(); // RANDOTODO when proper ammo logic is done, this could be moved to the start } } - // If we are not shuffling the guard house, add the key so we can properly check for poe merchant access - if (gals.validatedStartingRegion && gals.foundTempleOfTime && - ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) { - Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect(); - } } // Apply all items that are necessary for checking all location access @@ -180,10 +175,7 @@ static void ApplyAllAdvancmentItems() { static void ValidateSphereZero(GetAccessibleLocationsStruct& gals) { auto ctx = Rando::Context::GetInstance(); // Condition for verifying everything required for sphere 0, expanding search to all locations - if ((!logic->AreCheckingBigPoes || logic->CanEmptyBigPoes) && gals.validatedStartingRegion && - gals.foundTempleOfTime && gals.haveTimeAccess) { - // stop checking for big poes - logic->AreCheckingBigPoes = false; + if (gals.validatedStartingRegion && gals.foundTempleOfTime && gals.haveTimeAccess) { // Apply all items that are necessary for checking all location access ApplyAllAdvancmentItems(); // Reset access as the non-starting age @@ -213,7 +205,7 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer // Update Time of Day Access for the exit if (UpdateToDAccess(&exit, exitRegion)) { gals.logicUpdated = true; - if (!gals.sphereZeroComplete || logic->AreCheckingBigPoes) { + if (!gals.sphereZeroComplete) { if (!gals.foundTempleOfTime || !gals.validatedStartingRegion) { ValidateOtherEntrance(gals); } @@ -596,15 +588,12 @@ bool CheckBeatable(RandomizerGet ignore /* = RG_NONE*/) { } // Check if the currently randomised set of entrances is a valid game map. -void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess) { +void ValidateEntrances(bool checkOtherEntranceAccess) { auto ctx = Rando::Context::GetInstance(); GetAccessibleLocationsStruct gals(0); ResetLogic(ctx, gals, !checkOtherEntranceAccess); ctx->allLocationsReachable = false; - if (checkPoeCollectorAccess) { - logic->AreCheckingBigPoes = true; - } if (checkOtherEntranceAccess) { gals.foundTempleOfTime = false; @@ -620,11 +609,6 @@ void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAcce RegionTable(RR_ROOT)->adultNight = true; RegionTable(RR_ROOT)->childDay = true; RegionTable(RR_ROOT)->adultDay = true; - } else if (checkPoeCollectorAccess) { - // If we are not shuffling the guard house, add the key so we can properly check for poe merchant access - if (ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF)) { - Rando::StaticData::RetrieveItem(RG_GUARD_HOUSE_KEY).ApplyEffect(); - } } else { ApplyAllAdvancmentItems(); } diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.hpp b/soh/soh/Enhancements/randomizer/3drando/fill.hpp index f2028e05d..4e6f4ab90 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.hpp @@ -72,4 +72,4 @@ void GeneratePlaythrough(); bool CheckBeatable(RandomizerGet ignore = RG_NONE); -void ValidateEntrances(bool checkPoeCollectorAccess, bool checkOtherEntranceAccess); \ No newline at end of file +void ValidateEntrances(bool checkOtherEntranceAccess); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 8e928185f..9a4e312ba 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -273,8 +273,8 @@ std::vector>> conditionalAlways std::make_pair(RC_MARKET_10_BIG_POES, []() { auto ctx = Rando::Context::GetInstance(); - return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT); - }), // Remember, the option's value being 3 means 4 are required + return ctx->GetOption(RSK_BIG_POE_COUNT).Get() > 3 && !ctx->GetOption(RSK_BIG_POES_HINT); + }), std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { auto ctx = Rando::Context::GetInstance(); diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 40eaca212..962ee5a77 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -441,12 +441,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) { type = entrancePlaced->GetType(); } - bool checkPoeCollectorAccess = - (ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || - ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL)) && - (entrancePlaced == nullptr || ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS) || type == EntranceType::Interior || - type == EntranceType::SpecialInterior || type == EntranceType::Overworld || type == EntranceType::Spawn || - type == EntranceType::WarpSong || type == EntranceType::OwlDrop); bool checkOtherEntranceAccess = (ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) || @@ -459,7 +453,7 @@ static bool ValidateWorld(Entrance* entrancePlaced) { // Conditions will be checked during the search and any that fail will be figured out // afterwards ctx->GetLogic()->Reset(); - ValidateEntrances(checkPoeCollectorAccess, checkOtherEntranceAccess); + ValidateEntrances(checkOtherEntranceAccess); if (!ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { // Unless entrances are decoupled, we don't want the player to end up through certain entrances as the wrong age @@ -544,15 +538,6 @@ static bool ValidateWorld(Entrance* entrancePlaced) { } } - // The Big Poe shop should always be accessible as adult without the need to use any bottles - // This is important to ensure that players can never lock their only bottles by filling them with Big Poes they - // can't sell - if (checkPoeCollectorAccess) { - if (!RegionTable(RR_MARKET_GUARD_HOUSE)->Adult()) { - SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n"); - return false; - } - } SPDLOG_DEBUG("All Locations NOT REACHABLE\n"); return false; } diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index bd267aebe..b4dc286a7 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -29,6 +29,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h" #include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" #include "src/overlays/actors/ovl_En_Gb/z_en_gb.h" +#include "src/overlays/actors/ovl_En_Po_Field/z_en_po_field.h" #include "src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h" #include "src/overlays/actors/ovl_En_Ko/z_en_ko.h" #include "src/overlays/actors/ovl_En_Mk/z_en_mk.h" @@ -1080,12 +1081,35 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should = false; break; } + case VB_BOTTLE_BIG_POE: { + EnPoField* enPoe = va_arg(args, EnPoField*); + enPoe->actor.textId = 0x5090; + Flags_SetSwitch(gPlayState, enPoe->actor.params & 0xFF); + HIGH_SCORE(HS_POE_POINTS) += 100; + if (HIGH_SCORE(HS_POE_POINTS) > 1100) { + HIGH_SCORE(HS_POE_POINTS) = 1100; + } + *should = false; + break; + } + case VB_SELL_POES_TO_POE_COLLECTOR: { + if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES) && HIGH_SCORE(HS_POE_POINTS) >= 1000) { + EnGb* enGb = va_arg(args, EnGb*); + enGb->textId = 0x70F8; + Message_ContinueTextbox(gPlayState, enGb->textId); + enGb->actionFunc = func_80A2FB40; + *should = false; + } + break; + } case VB_GIVE_ITEM_FROM_POE_COLLECTOR: { EnGb* enGb = va_arg(args, EnGb*); if (!Flags_GetRandomizerInf(RAND_INF_10_BIG_POES)) { + Flags_SetInfTable(INFTABLE_SPOKE_TO_POE_COLLECTOR_IN_RUINED_MARKET); Flags_SetRandomizerInf(RAND_INF_10_BIG_POES); + enGb->textId = 0x70F5; enGb->dyna.actor.parent = NULL; - enGb->actionFunc = func_80A2FC0C; + enGb->actionFunc = func_80A2F83C; *should = false; } break; diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 6cf2aa2ab..28ec0e037 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -324,9 +324,6 @@ void RegionTable_Init() { areaTable[RR_ROOT] = Region("Root", "", {RA_LINKS_POCKET}, NO_DAY_NIGHT_CYCLE, { //Events EventAccess(&logic->KakarikoVillageGateOpen, []{return ctx->GetOption(RSK_KAK_GATE).Is(RO_KAK_GATE_OPEN);}), - //The big poes bottle softlock safety check does not account for the guard house lock if the guard house is not shuffled, so the key is needed before we can safely allow bottle use in logic - //RANDOTODO a setting that lets you drink/dump big poes so we don't need this logic - EventAccess(&logic->CouldEmptyBigPoes, []{return !ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES).Is(RO_INTERIOR_ENTRANCE_SHUFFLE_OFF) || logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}), }, { //Locations LOCATION(RC_LINKS_POCKET, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 0314bfde0..7a5d229f1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -54,7 +54,7 @@ void RegionTable_Init_Market() { EventAccess(&logic->CanEmptyBigPoes, []{return logic->IsAdult;}), }, { //Locations - LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes > ctx->GetOption(RSK_BIG_POE_COUNT).Get())), + LOCATION(RC_MARKET_10_BIG_POES, logic->IsAdult && (logic->BigPoeKill || logic->BigPoes >= ctx->GetOption(RSK_BIG_POE_COUNT).Get())), LOCATION(RC_MARKET_GS_GUARD_HOUSE, logic->IsChild), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_1, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_MK_GUARD_HOUSE_CHILD_POT_2, logic->IsChild && logic->CanBreakPots()), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 0c4ed2e89..69a8c4ea8 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -1013,26 +1013,24 @@ Logic::Logic() { uint8_t Logic::BottleCount() { uint8_t count = 0; - if (CouldEmptyBigPoes && !AreCheckingBigPoes) { - for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) { - uint8_t item = GetSaveContext()->inventory.items[i]; - switch (item) { - case ITEM_LETTER_RUTO: - if (DeliverLetter) { - count++; - } - break; - case ITEM_BIG_POE: - if (CanEmptyBigPoes) { - count++; - } - break; - case ITEM_NONE: - break; - default: + for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_4; i++) { + uint8_t item = GetSaveContext()->inventory.items[i]; + switch (item) { + case ITEM_LETTER_RUTO: + if (DeliverLetter) { count++; - break; - } + } + break; + case ITEM_BIG_POE: + if (CanEmptyBigPoes) { + count++; + } + break; + case ITEM_NONE: + break; + default: + count++; + break; } } return count; @@ -2408,7 +2406,6 @@ void Logic::Reset() { Bottles = 0; NumBottles = 0; CanEmptyBigPoes = false; - CouldEmptyBigPoes = false; // Drops and Bottle Contents Access NutPot = false; diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index 4f966f5de..6c3698f18 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -66,12 +66,6 @@ class Logic { uint8_t NumBottles = 0; // this event covers if the player can currently empty big poes in logic bool CanEmptyBigPoes = false; - // this event covers if the player could, if they filled their bottle with big poes in field, empty them at the poe - // merchant. Works in tandem with the big poes safety check during entrance validation - bool CouldEmptyBigPoes = false; - // this check is used to tell logic that we are checking big poes accessibility in logic, to ensure it's not - // bottle-locked. - bool AreCheckingBigPoes = false; // Drops and Bottle Contents Access bool NutPot = false; diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index cb8c7eaef..46b0d98b5 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -334,7 +334,7 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_TOT_MASTER_SWORD); } - HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * (Randomizer_GetSettingValue(RSK_BIG_POE_COUNT) + 1)); + HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT)); if (Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) { Flags_SetEventChkInf(EVENTCHKINF_EPONA_OBTAINED); diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index c5d0c23d8..68ec26a29 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -268,7 +268,7 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_SKIP_CHILD_ZELDA, "Skip Child Zelda", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipChildZelda"), mOptionDescriptions[RSK_SKIP_CHILD_ZELDA], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); - OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(1, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 9); + OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 10); OPT_U8(RSK_CUCCO_COUNT, "Cuccos to return", {NumOpts(0, 7)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CuccosToReturn"), mOptionDescriptions[RSK_CUCCO_COUNT], WidgetType::Slider, 7); OPT_BOOL(RSK_COMPLETE_MASK_QUEST, "Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]); OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 72030657e..16af054b5 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2426,6 +2426,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); } else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) { messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } else if (textId == TEXT_BIG_POE_COLLECTED_RANDO) { + messageEntry = + CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); } } 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 bcd301627..ea849af05 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -172,4 +172,7 @@ extern "C" void OTRMessage_Init() { CustomMessage("I'm sorry I can't sell you these fine specimens, they need an #experienced owner#.^" "Come back when you have had #Bombchus# of your own.", { QM_RED, QM_GREEN })); + CustomMessageManager::Instance->CreateMessage( + customMessageTableID, TEXT_BIG_POE_COLLECTED_RANDO, + CustomMessage("You have #" + CustomMessage::POINTS("\x01") + "# points.", { QM_RED })); } diff --git a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c index 40239a1e3..372962042 100644 --- a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c +++ b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.c @@ -288,19 +288,21 @@ void func_80A2F83C(EnGb* this, PlayState* play) { } } if (Actor_ProcessTalkRequest(&this->dyna.actor, play)) { - switch (func_8002F368(play)) { - case EXCH_ITEM_NONE: - func_80A2F180(this); - this->actionFunc = func_80A2F94C; - break; - case EXCH_ITEM_POE: - player->actor.textId = 0x70F6; - this->actionFunc = func_80A2F9C0; - break; - case EXCH_ITEM_BIG_POE: - player->actor.textId = 0x70F7; - this->actionFunc = func_80A2FA50; - break; + if (GameInteractor_Should(VB_SELL_POES_TO_POE_COLLECTOR, true, this)) { + switch (func_8002F368(play)) { + case EXCH_ITEM_NONE: + func_80A2F180(this); + this->actionFunc = func_80A2F94C; + break; + case EXCH_ITEM_POE: + player->actor.textId = 0x70F6; + this->actionFunc = func_80A2F9C0; + break; + case EXCH_ITEM_BIG_POE: + player->actor.textId = 0x70F7; + this->actionFunc = func_80A2FA50; + break; + } } return; } diff --git a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.h b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.h index 6df73808e..2ff4f64ff 100644 --- a/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.h +++ b/soh/src/overlays/actors/ovl_En_Gb/z_en_gb.h @@ -47,6 +47,7 @@ typedef struct EnGb { /* 0x0388 */ EnGbCagedSoul cagedSouls[4]; } EnGb; // size = 0x0438 -void func_80A2FC0C(EnGb* actor, PlayState* play); +void func_80A2FB40(EnGb* actor, PlayState* play); +void func_80A2F83C(EnGb* actor, PlayState* play); #endif diff --git a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c index 4d42cd39a..ac13107cf 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c +++ b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c @@ -712,7 +712,7 @@ void EnPoField_SoulInteract(EnPoField* this, PlayState* play) { if (this->actor.params == 0) { Item_Give(play, ITEM_POE); this->actor.textId = 0x5008; - } else { + } else if (GameInteractor_Should(VB_BOTTLE_BIG_POE, true, this)) { this->actor.textId = 0x508F; Item_Give(play, ITEM_BIG_POE); Flags_SetSwitch(play, sEnPoFieldSpawnSwitchFlags[this->spawnFlagIndex]);