From 82b279f55e77571d3a57d6ac9ebf69f54519d017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= Date: Tue, 30 Dec 2025 20:24:00 +0000 Subject: [PATCH] bushsanity (#5941) --- .../vanilla-behavior/GIVanillaBehavior.h | 8 + .../hint_list/hint_list_exclude_overworld.cpp | 9 + .../randomizer/3drando/item_pool.cpp | 4 + .../Enhancements/randomizer/ShuffleTrees.cpp | 158 ++++++++++++++---- soh/soh/Enhancements/randomizer/context.cpp | 1 + soh/soh/Enhancements/randomizer/location.cpp | 9 + soh/soh/Enhancements/randomizer/location.h | 4 + .../overworld/hyrule_field.cpp | 58 +++++++ .../overworld/zoras_fountain.cpp | 9 +- .../randomizer/option_descriptions.cpp | 2 + .../Enhancements/randomizer/randomizer.cpp | 64 +++++++ .../Enhancements/randomizer/randomizerTypes.h | 71 ++++++++ .../randomizer/randomizer_check_tracker.cpp | 5 +- .../Enhancements/randomizer/randomizer_inf.h | 64 +++++++ soh/soh/Enhancements/randomizer/settings.cpp | 3 + .../actors/ovl_En_Wood02/z_en_wood02.c | 12 +- 16 files changed, 437 insertions(+), 44 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 572854084..11756cb29 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -244,6 +244,14 @@ typedef enum { // - `*EnPoField` VB_BOTTLE_BIG_POE, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*ObjWood02` + VB_BUSH_DROP_ITEM, + // #### `result` // ```c // ((this->actor.params == DNS_TYPE_HEART_PIECE) && (Flags_GetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE))) || diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp index 0c40dfdb9..487c76158 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_overworld.cpp @@ -2126,6 +2126,15 @@ void StaticData::HintTable_Init_Exclude_Overworld() { HintText(CustomMessage("They say that a #tree in Lon Lon Ranch# contains #[[1]]#.", /*german*/ "", /*french*/ "Selon moi, un #arbre au Ranch Lon Lon# cache #[[1]]#.", { QM_RED, QM_GREEN })); + + hintTextTable[RHT_BUSH_HYRULE_FIELD] = + HintText(CustomMessage("They say that a #bush in Hyrle Field# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #buisson dans la Plaine d'Hyrule# cache #[[1]]#.", { QM_RED, QM_GREEN })); + hintTextTable[RHT_BUSH_ZORAS_FOUNTAIN] = + HintText(CustomMessage("They say that a #bush in Zora's Fountain# contains #[[1]]#.", + /*german*/ "", + /*french*/ "Selon moi, un #buisson à la Fontaine Zora# cache #[[1]]#.", { QM_RED, QM_GREEN })); // clang-format on } } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index ec90b0619..8dc10b94f 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -598,6 +598,10 @@ void GenerateItemPool() { PlaceItemsForType(RCTYPE_NLTREE, treesActive, false); } + // Shuffle Bushes + bool bushesActive = (bool)ctx->GetOption(RSK_SHUFFLE_BUSHES); + PlaceItemsForType(RCTYPE_BUSH, bushesActive, false); + // Shuffle Crates bool overworldCratesActive = ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_OVERWORLD) || ctx->GetOption(RSK_SHUFFLE_CRATES).Is(RO_SHUFFLE_CRATES_ALL); diff --git a/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp b/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp index 7355fc505..6ef305926 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp @@ -36,50 +36,45 @@ static Gfx* D_80B3BF70[] = { extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); uint8_t EnWood02_RandomizerHoldsItem(EnWood02* treeActor, PlayState* play) { - const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); - if (treeIdentity == nullptr) { - return false; - } - // Don't pull randomized item if tree isn't randomized or is already checked - return IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get() && - !Flags_GetRandomizerInf(treeIdentity->randomizerInf) && treeIdentity->randomizerCheck != RC_UNKNOWN_CHECK; + const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); + return treeIdentity != nullptr && treeIdentity->randomizerCheck != RC_UNKNOWN_CHECK && + treeIdentity->randomizerInf != RAND_INF_MAX && !Flags_GetRandomizerInf(treeIdentity->randomizerInf); } extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) { GetItemCategory getItemCategory; - GetItemEntry smallCrateItem; + GetItemEntry treeItem; auto treeActor = (EnWood02*)thisx; - int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); - int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); - - int isVanilla = - csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)); const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); - if (treeIdentity == nullptr) { + if (treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { return; } - if (isVanilla || treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { + int csmc = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeAndTextureMatchContents"), CSMC_DISABLED); + int requiresStoneAgony = CVarGetInteger(CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"), 0); + int isVanilla = + csmc == CSMC_DISABLED || csmc == CSMC_SIZE || (requiresStoneAgony && !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)); + + if (isVanilla) { getItemCategory = ITEM_CATEGORY_JUNK; } else { - smallCrateItem = Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); - getItemCategory = smallCrateItem.getItemCategory; + treeItem = Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); + getItemCategory = treeItem.getItemCategory; // If they have bombchus, don't consider the bombchu item major if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU && - ((smallCrateItem.modIndex == MOD_RANDOMIZER && smallCrateItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) || - (smallCrateItem.modIndex == MOD_NONE && - (smallCrateItem.getItemId == GI_BOMBCHUS_5 || smallCrateItem.getItemId == GI_BOMBCHUS_10 || - smallCrateItem.getItemId == GI_BOMBCHUS_20)))) { + ((treeItem.modIndex == MOD_RANDOMIZER && treeItem.getItemId == RG_PROGRESSIVE_BOMBCHU_BAG) || + (treeItem.modIndex == MOD_NONE && + (treeItem.getItemId == GI_BOMBCHUS_5 || treeItem.getItemId == GI_BOMBCHUS_10 || + treeItem.getItemId == GI_BOMBCHUS_20)))) { getItemCategory = ITEM_CATEGORY_JUNK; // If it's a bottle and they already have one, consider the item lesser - } else if ((smallCrateItem.modIndex == MOD_RANDOMIZER && - smallCrateItem.getItemId >= RG_BOTTLE_WITH_RED_POTION && - smallCrateItem.getItemId <= RG_BOTTLE_WITH_POE) || - (smallCrateItem.modIndex == MOD_NONE && - (smallCrateItem.getItemId == GI_BOTTLE || smallCrateItem.getItemId == GI_MILK_BOTTLE))) { + } else if ((treeItem.modIndex == MOD_RANDOMIZER && treeItem.getItemId >= RG_BOTTLE_WITH_RED_POTION && + treeItem.getItemId <= RG_BOTTLE_WITH_POE) || + (treeItem.modIndex == MOD_NONE && + (treeItem.getItemId == GI_BOTTLE || treeItem.getItemId == GI_MILK_BOTTLE))) { if (gSaveContext.inventory.items[SLOT_BOTTLE_1] != ITEM_NONE) { getItemCategory = ITEM_CATEGORY_LESSER; } @@ -110,7 +105,7 @@ extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) { break; case ITEM_CATEGORY_LESSER: Matrix_Scale(0.1, 0.05, 0.1, MTXMODE_APPLY); - switch (smallCrateItem.itemId) { + switch (treeItem.itemId) { case ITEM_HEART_PIECE: case ITEM_HEART_PIECE_2: case ITEM_HEART_CONTAINER: @@ -133,7 +128,7 @@ extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) { void EnWood02_RandomizerSpawnCollectible(EnWood02* treeActor, PlayState* play) { const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); - if (treeIdentity == nullptr) { + if (treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { return; } @@ -152,26 +147,33 @@ void EnWood02_RandomizerSpawnCollectible(EnWood02* treeActor, PlayState* play) { void EnWood02_RandomizerInit(void* actorRef) { EnWood02* treeActor = static_cast(actorRef); - if (treeActor->actor.params <= WOOD_TREE_KAKARIKO_ADULT) { + if ((treeActor->actor.params <= WOOD_TREE_KAKARIKO_ADULT && + Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get()) || + (treeActor->actor.params > WOOD_TREE_KAKARIKO_ADULT && + treeActor->actor.params <= WOOD_BUSH_BLACK_LARGE_SPAWNED && + Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BUSHES).Get())) { auto treeIdentity = OTRGlobals::Instance->gRandomizer->IdentifyTree( gPlayState->sceneNum, (s16)treeActor->actor.world.pos.x, (s16)treeActor->actor.world.pos.z); - ObjectExtension::GetInstance().Set(actorRef, std::move(treeIdentity)); + if (treeIdentity.randomizerInf != RAND_INF_MAX && treeIdentity.randomizerCheck != RC_UNKNOWN_CHECK) { + ObjectExtension::GetInstance().Set(actorRef, std::move(treeIdentity)); + } } } void RegisterShuffleTrees() { - bool shouldRegister = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get(); + bool shouldRegisterTree = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get(); + bool shouldRegisterBush = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_BUSHES).Get(); - COND_ID_HOOK(OnActorInit, ACTOR_EN_WOOD02, shouldRegister, EnWood02_RandomizerInit); + COND_ID_HOOK(OnActorInit, ACTOR_EN_WOOD02, shouldRegisterTree || shouldRegisterBush, EnWood02_RandomizerInit); - COND_VB_SHOULD(VB_TREE_SETUP_DRAW, shouldRegister, { + COND_VB_SHOULD(VB_TREE_SETUP_DRAW, shouldRegisterTree || shouldRegisterBush, { EnWood02* treeActor = va_arg(args, EnWood02*); if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { EnWood02_RandomizerDraw(&treeActor->actor, gPlayState); } }); - COND_VB_SHOULD(VB_TREE_DROP_ITEM, shouldRegister, { + COND_VB_SHOULD(VB_TREE_DROP_ITEM, shouldRegisterTree, { EnWood02* treeActor = va_arg(args, EnWood02*); if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { EnWood02_RandomizerSpawnCollectible(treeActor, gPlayState); @@ -188,6 +190,25 @@ void RegisterShuffleTrees() { *should = false; } }); + + COND_VB_SHOULD(VB_BUSH_DROP_ITEM, shouldRegisterBush, { + EnWood02* treeActor = va_arg(args, EnWood02*); + if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) { + const auto treeIdentity = ObjectExtension::GetInstance().Get(&treeActor->actor); + if (treeIdentity == nullptr || treeIdentity->randomizerCheck == RC_UNKNOWN_CHECK) { + return; + } + + EnItem00* item00 = + (EnItem00*)Item_DropCollectible2(gPlayState, &treeActor->actor.world.pos, ITEM00_SOH_DUMMY); + item00->randoInf = treeIdentity->randomizerInf; + item00->itemEntry = + Rando::Context::GetInstance()->GetFinalGIEntry(treeIdentity->randomizerCheck, true, GI_NONE); + item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem; + treeIdentity->randomizerCheck = RC_UNKNOWN_CHECK; + treeActor->unk_14C = -0x15; + } + }); } void Rando::StaticData::RegisterTreeLocations() { @@ -201,7 +222,7 @@ void Rando::StaticData::RegisterTreeLocations() { locationTable[RC_HC_NEAR_GUARDS_TREE_4] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(421, 1397), "Tree Near Guards 4", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_4)); locationTable[RC_HC_NEAR_GUARDS_TREE_5] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-73, 1459), "Tree Near Guards 5", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_5)); locationTable[RC_HC_NEAR_GUARDS_TREE_6] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1494, 2108), "Tree Near Guards 6", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_6)); - locationTable[RC_HC_SKULLTULA_TREE] = Location::Tree(RC_HC_SKULLTULA_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-145, 2961), "HC GS Tree", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_SKULLTULA_TREE)); + locationTable[RC_HC_SKULLTULA_TREE] = Location::Tree(RC_HC_SKULLTULA_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-145, 2961), "GS Tree", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_SKULLTULA_TREE)); locationTable[RC_HC_GROTTO_TREE] = Location::Tree(RC_HC_GROTTO_TREE, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(924, 872), "Tree Near Storms Grotto", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_GROTTO_TREE)); locationTable[RC_HC_NL_TREE_1] = Location::NLTree(RC_HC_NL_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(-331, 1438), "NL Tree Near Guards 1", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NL_TREE_1)); locationTable[RC_HC_NL_TREE_2] = Location::NLTree(RC_HC_NL_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1022, 1444), "NL Tree Near Guards 2", RHT_TREE_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NL_TREE_2)); @@ -257,9 +278,74 @@ void Rando::StaticData::RegisterTreeLocations() { locationTable[RC_ZR_TREE] = Location::Tree(RC_ZR_TREE, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(-1690, 554), "Tree in Zoras River", RHT_TREE_ZORAS_RIVER, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_TREE)); locationTable[RC_KAK_TREE] = Location::Tree(RC_KAK_TREE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-860, 522), "Kakariko GS Tree", RHT_TREE_KAKARIKO, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_TREE)); locationTable[RC_LLR_TREE] = Location::Tree(RC_LLR_TREE, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(1309, -2241), "Lon Lon Ranch GS Tree", RHT_TREE_LON_LON_RANCH, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TREE)); + + locationTable[RC_HF_BUSH_NEAR_LAKE_1] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3506,13460), "Bush Near Lake 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_1)); + locationTable[RC_HF_BUSH_NEAR_LAKE_2] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3907,13119), "Bush Near Lake 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_2)); + locationTable[RC_HF_BUSH_NEAR_LAKE_3] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4106,13520), "Bush Near Lake 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_3)); + locationTable[RC_HF_BUSH_NEAR_LAKE_4] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4407,13320), "Bush Near Lake 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_4)); + locationTable[RC_HF_BUSH_NEAR_LAKE_5] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4486,13920), "Bush Near Lake 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_5)); + locationTable[RC_HF_BUSH_NEAR_LAKE_6] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4722,12732), "Bush Near Lake 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_6)); + locationTable[RC_HF_BUSH_NEAR_LAKE_7] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4723,13392), "Bush Near Lake 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_7)); + locationTable[RC_HF_BUSH_NEAR_LAKE_8] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5123,12391), "Bush Near Lake 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_8)); + locationTable[RC_HF_BUSH_NEAR_LAKE_9] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5322,12792), "Bush Near Lake 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_9)); + locationTable[RC_HF_BUSH_NEAR_LAKE_10] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5623,12592), "Bush Near Lake 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_10)); + locationTable[RC_HF_BUSH_NEAR_LAKE_11] = Location::Bush(RC_HF_BUSH_NEAR_LAKE_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5702,13192), "Bush Near Lake 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_NEAR_LAKE_11)); + locationTable[RC_HF_NORTHERN_BUSH_1] = Location::Bush(RC_HF_NORTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4710,1381), "Northern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_1)); + locationTable[RC_HF_NORTHERN_BUSH_2] = Location::Bush(RC_HF_NORTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4711,2041), "Northern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_2)); + locationTable[RC_HF_NORTHERN_BUSH_3] = Location::Bush(RC_HF_NORTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5111,1040), "Northern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_3)); + locationTable[RC_HF_NORTHERN_BUSH_4] = Location::Bush(RC_HF_NORTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5310,1441), "Northern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_4)); + locationTable[RC_HF_NORTHERN_BUSH_5] = Location::Bush(RC_HF_NORTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5611,1241), "Northern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_5)); + locationTable[RC_HF_NORTHERN_BUSH_6] = Location::Bush(RC_HF_NORTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5690,1841), "Northern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHERN_BUSH_6)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_1] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3621,-303), "Child Northern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_1)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_2] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-3622,356), "Child Northern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_2)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_3] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4022,-644), "Child Northern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_3)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_4] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4221,-243), "Child Northern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_4)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_5] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4522,-443), "Child Northern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_5)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_6] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4601,156), "Child Northern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_6)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_7] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4634,-284), "Child Northern Bush 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_7)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_8] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4713,315), "Child Northern Bush 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_8)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_9] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5014,115), "Child Northern Bush 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_9)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_10] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5213,516), "Child Northern Bush 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_10)); + locationTable[RC_HF_CHILD_NORTHERN_BUSH_11] = Location::Bush(RC_HF_CHILD_NORTHERN_BUSH_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5614,175), "Child Northern Bush 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NORTHERN_BUSH_11)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_1] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5792,7022), "Bush By Rocky Path 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_1)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_2] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5793,7682), "Bush By Rocky Path 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_2)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_3] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6193,6681), "Bush By Rocky Path 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_3)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_4] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6392,7082), "Bush By Rocky Path 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_4)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_5] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6693,6882), "Bush By Rocky Path 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_5)); + locationTable[RC_HF_BUSH_BY_ROCKY_PATH_6] = Location::Bush(RC_HF_BUSH_BY_ROCKY_PATH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6772,7482), "Bush By Rocky Path 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_BUSH_BY_ROCKY_PATH_6)); + locationTable[RC_HF_SOUTHERN_BUSH_1] = Location::Bush(RC_HF_SOUTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-270,12633), "Southern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_1)); + locationTable[RC_HF_SOUTHERN_BUSH_2] = Location::Bush(RC_HF_SOUTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-349,13233), "Southern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_2)); + locationTable[RC_HF_SOUTHERN_BUSH_3] = Location::Bush(RC_HF_SOUTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2,11473), "Southern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_3)); + locationTable[RC_HF_SOUTHERN_BUSH_4] = Location::Bush(RC_HF_SOUTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(229,12432), "Southern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_4)); + locationTable[RC_HF_SOUTHERN_BUSH_5] = Location::Bush(RC_HF_SOUTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(30,12833), "Southern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_5)); + locationTable[RC_HF_SOUTHERN_BUSH_6] = Location::Bush(RC_HF_SOUTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(382,11073), "Southern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_6)); + locationTable[RC_HF_SOUTHERN_BUSH_7] = Location::Bush(RC_HF_SOUTHERN_BUSH_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(581,10672), "Southern Bush 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_7)); + locationTable[RC_HF_SOUTHERN_BUSH_8] = Location::Bush(RC_HF_SOUTHERN_BUSH_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(629,13433), "Southern Bush 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_8)); + locationTable[RC_HF_SOUTHERN_BUSH_9] = Location::Bush(RC_HF_SOUTHERN_BUSH_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(630,12773), "Southern Bush 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_9)); + locationTable[RC_HF_SOUTHERN_BUSH_10] = Location::Bush(RC_HF_SOUTHERN_BUSH_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(81,10873), "Southern Bush 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_10)); + locationTable[RC_HF_SOUTHERN_BUSH_11] = Location::Bush(RC_HF_SOUTHERN_BUSH_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(981,11673), "Southern Bush 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_11)); + locationTable[RC_HF_SOUTHERN_BUSH_12] = Location::Bush(RC_HF_SOUTHERN_BUSH_12, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(982,11013), "Southern Bush 12", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHERN_BUSH_12)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_1] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-873,13221), "Child Southern Bush 1", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_1)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_2] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-874,13881), "Child Southern Bush 2", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_2)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_3] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1009,11961), "Child Southern Bush 3", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_3)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_4] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1310,12161), "Child Southern Bush 4", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_4)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_5] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1509,11760), "Child Southern Bush 5", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_5)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_6] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1909,12761), "Child Southern Bush 6", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_6)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_7] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1910,12101), "Child Southern Bush 7", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_7)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_8] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(930,12561), "Child Southern Bush 8", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_8)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_9] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1274,12880), "Child Southern Bush 9", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_9)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_10] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1473,13281), "Child Southern Bush 10", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_10)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_11] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1774,13081), "Child Southern Bush 11", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_11)); + locationTable[RC_HF_CHILD_SOUTHERN_BUSH_12] = Location::Bush(RC_HF_CHILD_SOUTHERN_BUSH_12, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1853,13681), "Child Southern Bush 12", RHT_BUSH_HYRULE_FIELD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHERN_BUSH_12)); + locationTable[RC_ZF_BUSH_1] = Location::Bush(RC_ZF_BUSH_1, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(167,2514), "Bush 1", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_1)); + locationTable[RC_ZF_BUSH_2] = Location::Bush(RC_ZF_BUSH_2, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(394,2510), "Bush 2", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_2)); + locationTable[RC_ZF_BUSH_3] = Location::Bush(RC_ZF_BUSH_3, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(231,2406), "Bush 3", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_3)); + locationTable[RC_ZF_BUSH_4] = Location::Bush(RC_ZF_BUSH_4, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(544,2373), "Bush 4", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_4)); + locationTable[RC_ZF_BUSH_5] = Location::Bush(RC_ZF_BUSH_5, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(386,2265), "Bush 5", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_5)); + locationTable[RC_ZF_BUSH_6] = Location::Bush(RC_ZF_BUSH_6, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(551,2184), "Bush 6", RHT_BUSH_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_BUSH_6)); // clang-format on } -static ObjectExtension::Register RegisterPotIdentity; +static ObjectExtension::Register RegisterTreeIdentity; static RegisterShipInitFunc registerShuffleTrees(RegisterShuffleTrees, { "IS_RANDO" }); static RegisterShipInitFunc registerTreeLocations(Rando::StaticData::RegisterTreeLocations); diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp index f821c8ff7..7dff59ae6 100644 --- a/soh/soh/Enhancements/randomizer/context.cpp +++ b/soh/soh/Enhancements/randomizer/context.cpp @@ -206,6 +206,7 @@ void Context::GenerateLocationPool() { (location.GetRCType() == RCTYPE_TREE && !mOptions[RSK_SHUFFLE_TREES]) || (location.GetRCType() == RCTYPE_NLTREE && (!mOptions[RSK_SHUFFLE_TREES] || mOptions[RSK_LOGIC_RULES].IsNot(RO_LOGIC_NO_LOGIC))) || + (location.GetRCType() == RCTYPE_BUSH && !mOptions[RSK_SHUFFLE_BUSHES]) || (location.GetRCType() == RCTYPE_FREESTANDING && mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OFF)) || (location.GetRCType() == RCTYPE_BEEHIVE && !mOptions[RSK_SHUFFLE_BEEHIVES])) { diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index 847ee9aa9..250af2cfb 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -585,6 +585,15 @@ Rando::Location Rando::Location::NLTree(RandomizerCheck rc, RandomizerCheckQuest false, collectionCheck }; } +Rando::Location Rando::Location::Bush(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, + SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_BUSH, area_, ACTOR_EN_WOOD02, + scene_, actorParams_, std::move(shortName_), hintKey, vanillaItem, + false, collectionCheck }; +} + Rando::Location Rando::Location::HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_) { return { rc, quest_, RCTYPE_GOSSIP_STONE, area_, ACTOR_EN_GS, diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index f118bdcda..955601220 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -254,6 +254,10 @@ class Location { int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + static Location Bush(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, + int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, + RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck); + static Location OtherHint(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, ActorID actorId_, SceneID scene_, std::string&& shortName_, std::string&& spoilerName_); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index 2a9ca1765..8e53dc56f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -110,6 +110,64 @@ void RegionTable_Init_HyruleField() { LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_5, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_6, logic->IsChild && logic->CanBonkTrees()), LOCATION(RC_HF_TEKTITE_GROTTO_TREE, logic->CanBonkTrees()), + LOCATION(RC_HF_BUSH_NEAR_LAKE_1, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_2, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_3, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_4, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_5, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_6, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_7, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_8, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_9, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_10, true), + LOCATION(RC_HF_BUSH_NEAR_LAKE_11, true), + LOCATION(RC_HF_NORTHERN_BUSH_1, true), + LOCATION(RC_HF_NORTHERN_BUSH_2, true), + LOCATION(RC_HF_NORTHERN_BUSH_3, true), + LOCATION(RC_HF_NORTHERN_BUSH_4, true), + LOCATION(RC_HF_NORTHERN_BUSH_5, true), + LOCATION(RC_HF_NORTHERN_BUSH_6, true), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_1, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_2, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_3, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_4, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_5, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_6, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_7, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_8, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_9, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_10, logic->IsChild), + LOCATION(RC_HF_CHILD_NORTHERN_BUSH_11, logic->IsChild), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_1, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_2, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_3, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_4, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_5, true), + LOCATION(RC_HF_BUSH_BY_ROCKY_PATH_6, true), + LOCATION(RC_HF_SOUTHERN_BUSH_1, true), + LOCATION(RC_HF_SOUTHERN_BUSH_2, true), + LOCATION(RC_HF_SOUTHERN_BUSH_3, true), + LOCATION(RC_HF_SOUTHERN_BUSH_4, true), + LOCATION(RC_HF_SOUTHERN_BUSH_5, true), + LOCATION(RC_HF_SOUTHERN_BUSH_6, true), + LOCATION(RC_HF_SOUTHERN_BUSH_7, true), + LOCATION(RC_HF_SOUTHERN_BUSH_8, true), + LOCATION(RC_HF_SOUTHERN_BUSH_9, true), + LOCATION(RC_HF_SOUTHERN_BUSH_10, true), + LOCATION(RC_HF_SOUTHERN_BUSH_11, true), + LOCATION(RC_HF_SOUTHERN_BUSH_12, true), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_1, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_2, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_3, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_4, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_5, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_6, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_7, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_8, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_9, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_10, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_11, logic->IsChild), + LOCATION(RC_HF_CHILD_SOUTHERN_BUSH_12, logic->IsChild), }, { //Exits Entrance(RR_LW_BRIDGE, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index 421221977..bc5fe165e 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -7,8 +7,7 @@ void RegionTable_Init_ZorasFountain() { // clang-format off areaTable[RR_ZORAS_FOUNTAIN] = Region("Zoras Fountain", SCENE_ZORAS_FOUNTAIN, { //Events - EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), + EventAccess(LOGIC_FAIRY_ACCESS, []{return logic->CallGossipFairyExceptSuns() || (logic->CanUse(RG_STICKS) && logic->AtDay);}), }, { //Locations LOCATION(RC_ZF_GS_TREE, logic->IsChild && logic->CanBonkTrees()), @@ -24,6 +23,12 @@ void RegionTable_Init_ZorasFountain() { LOCATION(RC_ZF_NEAR_JABU_POT_3, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_NEAR_JABU_POT_4, logic->IsChild && logic->CanBreakPots()), LOCATION(RC_ZF_TREE, logic->IsChild && logic->CanBonkTrees()), + LOCATION(RC_ZF_BUSH_1, logic->IsChild), + LOCATION(RC_ZF_BUSH_2, logic->IsChild), + LOCATION(RC_ZF_BUSH_3, logic->IsChild), + LOCATION(RC_ZF_BUSH_4, logic->IsChild), + LOCATION(RC_ZF_BUSH_5, logic->IsChild), + LOCATION(RC_ZF_BUSH_6, logic->IsChild), }, { //Exits Entrance(RR_ZD_BEHIND_KING_ZORA, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 1f6b71a88..67513935b 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -297,6 +297,8 @@ void Settings::CreateOptionDescriptions() { "Trees will have a special appearance when carrying randomized items.\n" "\nSome trees are dependant on Link's age, such as some trees in Hyrule Field.\nTwo trees at Hyrule Castle are " "only shuffle with No Logic."; + mOptionDescriptions[RSK_SHUFFLE_BUSHES] = + "Bushes in Hyrule Field & Zora's Fountain will contain randomized items when first walked through."; mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE] = "Shuffles the fishing pole into the item pool.\n" "\n" "The fishing pole is required to play the fishing pond minigame."; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index de17327f1..dd6c78a79 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3422,6 +3422,70 @@ std::map rcToRandomizerInf = { { RC_ZR_TREE, RAND_INF_ZR_TREE }, { RC_KAK_TREE, RAND_INF_KAK_TREE }, { RC_LLR_TREE, RAND_INF_LLR_TREE }, + { RC_HF_BUSH_NEAR_LAKE_1, RAND_INF_HF_BUSH_NEAR_LAKE_1 }, + { RC_HF_BUSH_NEAR_LAKE_2, RAND_INF_HF_BUSH_NEAR_LAKE_2 }, + { RC_HF_BUSH_NEAR_LAKE_3, RAND_INF_HF_BUSH_NEAR_LAKE_3 }, + { RC_HF_BUSH_NEAR_LAKE_4, RAND_INF_HF_BUSH_NEAR_LAKE_4 }, + { RC_HF_BUSH_NEAR_LAKE_5, RAND_INF_HF_BUSH_NEAR_LAKE_5 }, + { RC_HF_BUSH_NEAR_LAKE_6, RAND_INF_HF_BUSH_NEAR_LAKE_6 }, + { RC_HF_BUSH_NEAR_LAKE_7, RAND_INF_HF_BUSH_NEAR_LAKE_7 }, + { RC_HF_BUSH_NEAR_LAKE_8, RAND_INF_HF_BUSH_NEAR_LAKE_8 }, + { RC_HF_BUSH_NEAR_LAKE_9, RAND_INF_HF_BUSH_NEAR_LAKE_9 }, + { RC_HF_BUSH_NEAR_LAKE_10, RAND_INF_HF_BUSH_NEAR_LAKE_10 }, + { RC_HF_BUSH_NEAR_LAKE_11, RAND_INF_HF_BUSH_NEAR_LAKE_11 }, + { RC_HF_NORTHERN_BUSH_1, RAND_INF_HF_NORTHERN_BUSH_1 }, + { RC_HF_NORTHERN_BUSH_2, RAND_INF_HF_NORTHERN_BUSH_2 }, + { RC_HF_NORTHERN_BUSH_3, RAND_INF_HF_NORTHERN_BUSH_3 }, + { RC_HF_NORTHERN_BUSH_4, RAND_INF_HF_NORTHERN_BUSH_4 }, + { RC_HF_NORTHERN_BUSH_5, RAND_INF_HF_NORTHERN_BUSH_5 }, + { RC_HF_NORTHERN_BUSH_6, RAND_INF_HF_NORTHERN_BUSH_6 }, + { RC_HF_CHILD_NORTHERN_BUSH_1, RAND_INF_HF_CHILD_NORTHERN_BUSH_1 }, + { RC_HF_CHILD_NORTHERN_BUSH_2, RAND_INF_HF_CHILD_NORTHERN_BUSH_2 }, + { RC_HF_CHILD_NORTHERN_BUSH_3, RAND_INF_HF_CHILD_NORTHERN_BUSH_3 }, + { RC_HF_CHILD_NORTHERN_BUSH_4, RAND_INF_HF_CHILD_NORTHERN_BUSH_4 }, + { RC_HF_CHILD_NORTHERN_BUSH_5, RAND_INF_HF_CHILD_NORTHERN_BUSH_5 }, + { RC_HF_CHILD_NORTHERN_BUSH_6, RAND_INF_HF_CHILD_NORTHERN_BUSH_6 }, + { RC_HF_CHILD_NORTHERN_BUSH_7, RAND_INF_HF_CHILD_NORTHERN_BUSH_7 }, + { RC_HF_CHILD_NORTHERN_BUSH_8, RAND_INF_HF_CHILD_NORTHERN_BUSH_8 }, + { RC_HF_CHILD_NORTHERN_BUSH_9, RAND_INF_HF_CHILD_NORTHERN_BUSH_9 }, + { RC_HF_CHILD_NORTHERN_BUSH_10, RAND_INF_HF_CHILD_NORTHERN_BUSH_10 }, + { RC_HF_CHILD_NORTHERN_BUSH_11, RAND_INF_HF_CHILD_NORTHERN_BUSH_11 }, + { RC_HF_BUSH_BY_ROCKY_PATH_1, RAND_INF_HF_BUSH_BY_ROCKY_PATH_1 }, + { RC_HF_BUSH_BY_ROCKY_PATH_2, RAND_INF_HF_BUSH_BY_ROCKY_PATH_2 }, + { RC_HF_BUSH_BY_ROCKY_PATH_3, RAND_INF_HF_BUSH_BY_ROCKY_PATH_3 }, + { RC_HF_BUSH_BY_ROCKY_PATH_4, RAND_INF_HF_BUSH_BY_ROCKY_PATH_4 }, + { RC_HF_BUSH_BY_ROCKY_PATH_5, RAND_INF_HF_BUSH_BY_ROCKY_PATH_5 }, + { RC_HF_BUSH_BY_ROCKY_PATH_6, RAND_INF_HF_BUSH_BY_ROCKY_PATH_6 }, + { RC_HF_SOUTHERN_BUSH_1, RAND_INF_HF_SOUTHERN_BUSH_1 }, + { RC_HF_SOUTHERN_BUSH_2, RAND_INF_HF_SOUTHERN_BUSH_2 }, + { RC_HF_SOUTHERN_BUSH_3, RAND_INF_HF_SOUTHERN_BUSH_3 }, + { RC_HF_SOUTHERN_BUSH_4, RAND_INF_HF_SOUTHERN_BUSH_4 }, + { RC_HF_SOUTHERN_BUSH_5, RAND_INF_HF_SOUTHERN_BUSH_5 }, + { RC_HF_SOUTHERN_BUSH_6, RAND_INF_HF_SOUTHERN_BUSH_6 }, + { RC_HF_SOUTHERN_BUSH_7, RAND_INF_HF_SOUTHERN_BUSH_7 }, + { RC_HF_SOUTHERN_BUSH_8, RAND_INF_HF_SOUTHERN_BUSH_8 }, + { RC_HF_SOUTHERN_BUSH_9, RAND_INF_HF_SOUTHERN_BUSH_9 }, + { RC_HF_SOUTHERN_BUSH_10, RAND_INF_HF_SOUTHERN_BUSH_10 }, + { RC_HF_SOUTHERN_BUSH_11, RAND_INF_HF_SOUTHERN_BUSH_11 }, + { RC_HF_SOUTHERN_BUSH_12, RAND_INF_HF_SOUTHERN_BUSH_12 }, + { RC_HF_CHILD_SOUTHERN_BUSH_1, RAND_INF_HF_CHILD_SOUTHERN_BUSH_1 }, + { RC_HF_CHILD_SOUTHERN_BUSH_2, RAND_INF_HF_CHILD_SOUTHERN_BUSH_2 }, + { RC_HF_CHILD_SOUTHERN_BUSH_3, RAND_INF_HF_CHILD_SOUTHERN_BUSH_3 }, + { RC_HF_CHILD_SOUTHERN_BUSH_4, RAND_INF_HF_CHILD_SOUTHERN_BUSH_4 }, + { RC_HF_CHILD_SOUTHERN_BUSH_5, RAND_INF_HF_CHILD_SOUTHERN_BUSH_5 }, + { RC_HF_CHILD_SOUTHERN_BUSH_6, RAND_INF_HF_CHILD_SOUTHERN_BUSH_6 }, + { RC_HF_CHILD_SOUTHERN_BUSH_7, RAND_INF_HF_CHILD_SOUTHERN_BUSH_7 }, + { RC_HF_CHILD_SOUTHERN_BUSH_8, RAND_INF_HF_CHILD_SOUTHERN_BUSH_8 }, + { RC_HF_CHILD_SOUTHERN_BUSH_9, RAND_INF_HF_CHILD_SOUTHERN_BUSH_9 }, + { RC_HF_CHILD_SOUTHERN_BUSH_10, RAND_INF_HF_CHILD_SOUTHERN_BUSH_10 }, + { RC_HF_CHILD_SOUTHERN_BUSH_11, RAND_INF_HF_CHILD_SOUTHERN_BUSH_11 }, + { RC_HF_CHILD_SOUTHERN_BUSH_12, RAND_INF_HF_CHILD_SOUTHERN_BUSH_12 }, + { RC_ZF_BUSH_1, RAND_INF_ZF_BUSH_1 }, + { RC_ZF_BUSH_2, RAND_INF_ZF_BUSH_2 }, + { RC_ZF_BUSH_3, RAND_INF_ZF_BUSH_3 }, + { RC_ZF_BUSH_4, RAND_INF_ZF_BUSH_4 }, + { RC_ZF_BUSH_5, RAND_INF_ZF_BUSH_5 }, + { RC_ZF_BUSH_6, RAND_INF_ZF_BUSH_6 }, }; BeehiveIdentity Randomizer::IdentifyBeehive(s32 sceneNum, s16 xPosition, s32 respawnData) { diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 2d4355015..571cc621f 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -418,6 +418,7 @@ typedef enum { RCTYPE_SMALL_CRATE, // Small crates RCTYPE_TREE, // Trees RCTYPE_NLTREE, // NL Trees + RCTYPE_BUSH, // Bushes RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps) RCTYPE_OCARINA, // Ocarina locations RCTYPE_BEEHIVE, // Beehives @@ -2952,6 +2953,73 @@ typedef enum { RC_LLR_TREE, // End Trees + // Start Bushes + RC_HF_BUSH_NEAR_LAKE_1, + RC_HF_BUSH_NEAR_LAKE_2, + RC_HF_BUSH_NEAR_LAKE_3, + RC_HF_BUSH_NEAR_LAKE_4, + RC_HF_BUSH_NEAR_LAKE_5, + RC_HF_BUSH_NEAR_LAKE_6, + RC_HF_BUSH_NEAR_LAKE_7, + RC_HF_BUSH_NEAR_LAKE_8, + RC_HF_BUSH_NEAR_LAKE_9, + RC_HF_BUSH_NEAR_LAKE_10, + RC_HF_BUSH_NEAR_LAKE_11, + RC_HF_NORTHERN_BUSH_1, + RC_HF_NORTHERN_BUSH_2, + RC_HF_NORTHERN_BUSH_3, + RC_HF_NORTHERN_BUSH_4, + RC_HF_NORTHERN_BUSH_5, + RC_HF_NORTHERN_BUSH_6, + RC_HF_CHILD_NORTHERN_BUSH_1, + RC_HF_CHILD_NORTHERN_BUSH_2, + RC_HF_CHILD_NORTHERN_BUSH_3, + RC_HF_CHILD_NORTHERN_BUSH_4, + RC_HF_CHILD_NORTHERN_BUSH_5, + RC_HF_CHILD_NORTHERN_BUSH_6, + RC_HF_CHILD_NORTHERN_BUSH_7, + RC_HF_CHILD_NORTHERN_BUSH_8, + RC_HF_CHILD_NORTHERN_BUSH_9, + RC_HF_CHILD_NORTHERN_BUSH_10, + RC_HF_CHILD_NORTHERN_BUSH_11, + RC_HF_BUSH_BY_ROCKY_PATH_1, + RC_HF_BUSH_BY_ROCKY_PATH_2, + RC_HF_BUSH_BY_ROCKY_PATH_3, + RC_HF_BUSH_BY_ROCKY_PATH_4, + RC_HF_BUSH_BY_ROCKY_PATH_5, + RC_HF_BUSH_BY_ROCKY_PATH_6, + RC_HF_SOUTHERN_BUSH_1, + RC_HF_SOUTHERN_BUSH_2, + RC_HF_SOUTHERN_BUSH_3, + RC_HF_SOUTHERN_BUSH_4, + RC_HF_SOUTHERN_BUSH_5, + RC_HF_SOUTHERN_BUSH_6, + RC_HF_SOUTHERN_BUSH_7, + RC_HF_SOUTHERN_BUSH_8, + RC_HF_SOUTHERN_BUSH_9, + RC_HF_SOUTHERN_BUSH_10, + RC_HF_SOUTHERN_BUSH_11, + RC_HF_SOUTHERN_BUSH_12, + RC_HF_CHILD_SOUTHERN_BUSH_1, + RC_HF_CHILD_SOUTHERN_BUSH_2, + RC_HF_CHILD_SOUTHERN_BUSH_3, + RC_HF_CHILD_SOUTHERN_BUSH_4, + RC_HF_CHILD_SOUTHERN_BUSH_5, + RC_HF_CHILD_SOUTHERN_BUSH_6, + RC_HF_CHILD_SOUTHERN_BUSH_7, + RC_HF_CHILD_SOUTHERN_BUSH_8, + RC_HF_CHILD_SOUTHERN_BUSH_9, + RC_HF_CHILD_SOUTHERN_BUSH_10, + RC_HF_CHILD_SOUTHERN_BUSH_11, + RC_HF_CHILD_SOUTHERN_BUSH_12, + RC_ZF_BUSH_1, + RC_ZF_BUSH_2, + RC_ZF_BUSH_3, + RC_ZF_BUSH_4, + RC_ZF_BUSH_5, + RC_ZF_BUSH_6, + // End Bushes + RC_PIERRE, RC_DELIVER_RUTOS_LETTER, RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE, @@ -5803,6 +5871,8 @@ typedef enum { RHT_TREE_ZORAS_RIVER, RHT_TREE_LON_LON_RANCH, RHT_TREE_KAKARIKO, + RHT_BUSH_HYRULE_FIELD, + RHT_BUSH_ZORAS_FOUNTAIN, // Ganon Line RHT_GANON_JOKE01, RHT_GANON_JOKE02, @@ -6143,6 +6213,7 @@ typedef enum { RSK_SHUFFLE_POTS, RSK_SHUFFLE_CRATES, RSK_SHUFFLE_TREES, + RSK_SHUFFLE_BUSHES, RSK_SHUFFLE_FROG_SONG_RUPEES, RSK_ITEM_POOL, RSK_ICE_TRAPS, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 9363ace39..913d440cd 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -83,6 +83,7 @@ bool showDungeonGrass; bool showOverworldCrates; bool showDungeonCrates; bool showTrees; +bool showBushes; bool showFrogSongRupees; bool showFountainFairies; bool showStoneFairies; @@ -1494,6 +1495,7 @@ void LoadSettings() { break; } showTrees = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TREES); + showBushes = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BUSHES); } else { // Vanilla showOverworldTokens = true; showDungeonTokens = true; @@ -1504,6 +1506,7 @@ void LoadSettings() { showOverworldCrates = false; showDungeonCrates = false; showTrees = false; + showBushes = false; } fortressFast = false; @@ -1620,7 +1623,7 @@ bool IsCheckShuffled(RandomizerCheck rc) { (loc->GetRCType() != RCTYPE_NLTREE || (showTrees && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOGIC_RULES) == RO_LOGIC_NO_LOGIC)) && - (loc->GetRCType() != RCTYPE_COW || showCows) && + (loc->GetRCType() != RCTYPE_BUSH || showBushes) && (loc->GetRCType() != RCTYPE_COW || showCows) && (loc->GetRCType() != RCTYPE_FISH || OTRGlobals::Instance->gRandoContext->GetFishsanity()->GetFishLocationIncluded(loc)) && (loc->GetRCType() != RCTYPE_FREESTANDING || diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 8742805a6..b7d37725d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1060,6 +1060,70 @@ DEFINE_RAND_INF(RAND_INF_ZF_TREE) DEFINE_RAND_INF(RAND_INF_ZR_TREE) DEFINE_RAND_INF(RAND_INF_KAK_TREE) DEFINE_RAND_INF(RAND_INF_LLR_TREE) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_1) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_2) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_3) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_4) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_5) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_6) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_7) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_8) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_9) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_10) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_NEAR_LAKE_11) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_NORTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_7) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_8) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_9) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_10) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_NORTHERN_BUSH_11) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_1) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_2) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_3) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_4) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_5) +DEFINE_RAND_INF(RAND_INF_HF_BUSH_BY_ROCKY_PATH_6) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_7) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_8) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_9) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_10) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_11) +DEFINE_RAND_INF(RAND_INF_HF_SOUTHERN_BUSH_12) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_1) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_2) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_3) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_4) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_5) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_6) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_7) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_8) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_9) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_10) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_11) +DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHERN_BUSH_12) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_1) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_2) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_3) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_4) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_5) +DEFINE_RAND_INF(RAND_INF_ZF_BUSH_6) DEFINE_RAND_INF(RAND_INF_CAUGHT_LOACH) diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index ba272c0e6..1266cb651 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -220,6 +220,7 @@ void Settings::CreateOptions() { OPT_U8(RSK_SHUFFLE_GRASS, "Shuffle Grass", {"Off", "Dungeons", "Overworld", "All Grass/Bushes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGrass"), mOptionDescriptions[RSK_SHUFFLE_GRASS], WidgetType::Combobox, RO_SHUFFLE_GRASS_OFF); OPT_U8(RSK_SHUFFLE_CRATES, "Shuffle Crates", {"Off", "Dungeons", "Overworld", "All Crates"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleCrates"), mOptionDescriptions[RSK_SHUFFLE_CRATES], WidgetType::Combobox, RO_SHUFFLE_CRATES_OFF); OPT_BOOL(RSK_SHUFFLE_TREES, "Shuffle Trees", CVAR_RANDOMIZER_SETTING("ShuffleTrees"), mOptionDescriptions[RSK_SHUFFLE_TREES]); + OPT_BOOL(RSK_SHUFFLE_BUSHES, "Shuffle Bushes", CVAR_RANDOMIZER_SETTING("ShuffleBushes"), mOptionDescriptions[RSK_SHUFFLE_BUSHES]); OPT_BOOL(RSK_SHUFFLE_FISHING_POLE, "Shuffle Fishing Pole", CVAR_RANDOMIZER_SETTING("ShuffleFishingPole"), mOptionDescriptions[RSK_SHUFFLE_FISHING_POLE]); OPT_U8(RSK_SHUFFLE_MERCHANTS, "Shuffle Merchants", {"Off", "Bean Merchant Only", "All But Beans", "All"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleMerchants"), mOptionDescriptions[RSK_SHUFFLE_MERCHANTS], WidgetType::Combobox, RO_SHUFFLE_MERCHANTS_OFF, IMFLAG_NONE); OPT_U8(RSK_MERCHANT_PRICES, "Merchant Prices", {"Vanilla", "Cheap Balanced", "Balanced", "Fixed", "Range", "Set By Wallet"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("MerchantPrices"), mOptionDescriptions[RSK_MERCHANT_PRICES], WidgetType::Combobox, RO_PRICE_VANILLA, false, IMFLAG_NONE); @@ -1327,6 +1328,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_CRATES], &mOptions[RSK_SHUFFLE_TREES], + &mOptions[RSK_SHUFFLE_BUSHES], &mOptions[RSK_SHUFFLE_MERCHANTS], &mOptions[RSK_MERCHANT_PRICES], &mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE], @@ -1584,6 +1586,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_POTS], &mOptions[RSK_SHUFFLE_CRATES], &mOptions[RSK_SHUFFLE_TREES], + &mOptions[RSK_SHUFFLE_BUSHES], &mOptions[RSK_SHUFFLE_KOKIRI_SWORD], &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_OCARINA_BUTTONS], diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index 1fe96d38c..b83bd3ddd 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -403,12 +403,14 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) { (player->linearVelocity != 0.0f)) || ((player->rideActor != NULL) && (sqrt(this->actor.xyzDistToPlayerSq) < 60.0) && (player->rideActor->speedXZ != 0.0f))) { - if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) { - Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, - ((this->unk_14C << 4) | 0x8000)); + if (GameInteractor_Should(VB_BUSH_DROP_ITEM, true, this)) { + if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) { + Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, + ((this->unk_14C << 4) | 0x8000)); + } + this->unk_14C = -0x15; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_TREE_SWING); } - this->unk_14C = -0x15; - Audio_PlayActorSound2(&this->actor, NA_SE_EV_TREE_SWING); } } } else { // Leaves