diff --git a/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL
new file mode 100644
index 000000000..8ab80efae
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/gRandoTreeDLTriforceTexture32.rgba16 b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDLTriforceTexture32.rgba16
new file mode 100644
index 000000000..256efd65a
Binary files /dev/null and b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDLTriforceTexture32.rgba16 differ
diff --git a/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_tri_0 b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_tri_0
new file mode 100644
index 000000000..16bbada99
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_tri_0
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_tri_1 b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_tri_1
new file mode 100644
index 000000000..136154b4c
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_tri_1
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_0 b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_0
new file mode 100644
index 000000000..e92b51e78
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_0
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_1 b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_1
new file mode 100644
index 000000000..adf256fc1
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_1
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_cull b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_cull
new file mode 100644
index 000000000..ea47c02e0
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/gRandoTreeDL_vtx_cull
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/mat_gRandoTreeDL_treeTexMaterial b/soh/assets/custom/objects/object_rando_tree/mat_gRandoTreeDL_treeTexMaterial
new file mode 100644
index 000000000..219a71f77
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/mat_gRandoTreeDL_treeTexMaterial
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/mat_gRandoTreeDL_triforceTexMaterial b/soh/assets/custom/objects/object_rando_tree/mat_gRandoTreeDL_triforceTexMaterial
new file mode 100644
index 000000000..a95fff2b0
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/mat_gRandoTreeDL_triforceTexMaterial
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/mat_revert_gRandoTreeDL_treeTexMaterial b/soh/assets/custom/objects/object_rando_tree/mat_revert_gRandoTreeDL_treeTexMaterial
new file mode 100644
index 000000000..ee8de0c37
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/mat_revert_gRandoTreeDL_treeTexMaterial
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_rando_tree/mat_revert_gRandoTreeDL_triforceTexMaterial b/soh/assets/custom/objects/object_rando_tree/mat_revert_gRandoTreeDL_triforceTexMaterial
new file mode 100644
index 000000000..ee8de0c37
--- /dev/null
+++ b/soh/assets/custom/objects/object_rando_tree/mat_revert_gRandoTreeDL_triforceTexMaterial
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h
index 3c3ddcf5a..e3e2f4780 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -77,6 +77,9 @@ static const ALIGN_ASSET(2) char gBossSoulSkullDL[] = dgBossSoulSkullDL;
#define dgRandoPotDL "__OTR__objects/gameplay_dangeon_keep/gRandoPotDL"
static const ALIGN_ASSET(2) char gRandoPotDL[] = dgRandoPotDL;
+#define dgRandoTreeDL "__OTR__objects/object_rando_tree/gRandoTreeDL"
+static const ALIGN_ASSET(2) char gRandoTreeDL[] = dgRandoTreeDL;
+
#define dgRandoBushDL "__OTR__objects/gameplay_field_keep/gFieldBushRandomDL"
static const ALIGN_ASSET(2) char gRandoBushDL[] = dgRandoBushDL;
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index 186307aed..ea20b398f 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -2155,6 +2155,22 @@ typedef enum {
// - `*EnWood02`
VB_TREE_DROP_COLLECTIBLE,
+ // ```c
+ // true
+ // ```
+ // #### `args`
+ // - `*ObjWood02`
+ VB_TREE_SETUP_DRAW,
+
+ // #### `result`
+ // ```c
+ // true
+ // ```
+ // #### `args`
+ // - `*ObjWood02`
+ VB_TREE_DROP_ITEM,
+
+ // #### `result`
// ```c
// true
// ```
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 a8afd7cb2..3314d6872 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
@@ -2081,6 +2081,30 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
/*german*/ "Man erzählt sich, daß eine #Kiste im Labor am See# #[[1]]# enthielte.",
/*french*/ "Selon moi, une #caisse dans un laboratoire# contient #[[1]]#.", {QM_RED, QM_GREEN}));
+ hintTextTable[RHT_TREE_HYRULE_FIELD] =
+ HintText(CustomMessage("They say that a #tree in Hyrule Field# contains #[[1]]#.",
+ /*german*/ "",
+ /*french*/ "", { QM_RED, QM_GREEN }));
+ hintTextTable[RHT_TREE_MARKET] =
+ HintText(CustomMessage("They say that a #tree in Hyrule Market# contains #[[1]]#.",
+ /*german*/ "",
+ /*french*/ "", { QM_RED, QM_GREEN }));
+ hintTextTable[RHT_TREE_HYRULE_CASTLE] =
+ HintText(CustomMessage("They say that a #tree in Hyrule Castle# contains #[[1]]#.",
+ /*german*/ "",
+ /*french*/ "", { QM_RED, QM_GREEN }));
+ hintTextTable[RHT_TREE_ZORAS_RIVER] =
+ HintText(CustomMessage("They say that a #tree in Zora's River# contains #[[1]]#.",
+ /*german*/ "",
+ /*french*/ "", { QM_RED, QM_GREEN }));
+ hintTextTable[RHT_TREE_ZORAS_FOUNTAIN] =
+ HintText(CustomMessage("They say that a #tree in Zora's Fountain# contains #[[1]]#.",
+ /*german*/ "",
+ /*french*/ "", { QM_RED, QM_GREEN }));
+ hintTextTable[RHT_TREE_LON_LON_RANCH] =
+ HintText(CustomMessage("They say that a #tree in Lon Lon Ranch# contains #[[1]]#.",
+ /*german*/ "",
+ /*french*/ "", { 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 c97ae35ce..ef8585e4b 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -604,6 +604,10 @@ void GenerateItemPool() {
ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL);
PlaceItemsForType(RCTYPE_POT, overworldPotsActive, dungeonPotsActive);
+ // Shuffle Trees
+ bool treesActive = (bool)ctx->GetOption(RSK_SHUFFLE_TREES);
+ PlaceItemsForType(RCTYPE_TREE, treesActive, 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
new file mode 100644
index 000000000..c5db4b352
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/ShuffleTrees.cpp
@@ -0,0 +1,203 @@
+#include
+#include "soh_assets.h"
+#include "static_data.h"
+
+extern "C" {
+#include "variables.h"
+#include "src/overlays/actors/ovl_En_Wood02/z_en_wood02.h"
+#include "objects/object_wood02/object_wood02.h"
+extern PlayState* gPlayState;
+void EnWood02_Draw(Actor*, PlayState*);
+}
+
+static Gfx* D_80B3BF54[] = {
+ (Gfx*)object_wood02_DL_0078D0, (Gfx*)object_wood02_DL_007CA0, (Gfx*)object_wood02_DL_0080D0,
+ (Gfx*)object_wood02_DL_000090, (Gfx*)object_wood02_DL_000340, (Gfx*)object_wood02_DL_000340,
+ (Gfx*)object_wood02_DL_000700,
+};
+
+static Gfx* D_80B3BF70[] = {
+ (Gfx*)object_wood02_DL_007968,
+ (Gfx*)object_wood02_DL_007D38,
+ (Gfx*)object_wood02_DL_0081A8,
+ NULL,
+ NULL,
+ NULL,
+ (Gfx*)object_wood02_DL_007AD0,
+ (Gfx*)object_wood02_DL_007E20,
+ (Gfx*)object_wood02_DL_008350,
+ (Gfx*)object_wood02_DL_000160,
+ (Gfx*)object_wood02_DL_000440,
+ (Gfx*)object_wood02_DL_000700,
+};
+
+extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play);
+
+uint8_t EnWood02_RandomizerHoldsItem(EnWood02* treeActor, PlayState* play) {
+ // 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(treeActor->treeId.randomizerInf) &&
+ treeActor->treeId.randomizerCheck != RC_UNKNOWN_CHECK;
+}
+
+extern "C" void EnWood02_RandomizerDraw(Actor* thisx, PlayState* play) {
+ EnWood02* thisy = (EnWood02*)thisx;
+ s16 type = thisy->actor.params;
+ u8 red;
+ u8 green;
+ u8 blue;
+
+ if ((type == WOOD_TREE_OVAL_GREEN_SPAWNER) || (type == WOOD_TREE_OVAL_GREEN_SPAWNED) ||
+ (type == WOOD_TREE_OVAL_GREEN) || (type == WOOD_LEAF_GREEN)) {
+ red = 50;
+ green = 170;
+ blue = 70;
+ } else if ((type == WOOD_TREE_OVAL_YELLOW_SPAWNER) || (type == WOOD_TREE_OVAL_YELLOW_SPAWNED) ||
+ (type == WOOD_LEAF_YELLOW)) {
+ red = 180;
+ green = 155;
+ blue = 0;
+ } else {
+ red = green = blue = 255;
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+ Gfx_SetupDL_25Xlu(play->state.gfxCtx);
+ if ((thisy->actor.params == WOOD_LEAF_GREEN) || (thisy->actor.params == WOOD_LEAF_YELLOW)) {
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, red, green, blue, 127);
+ Gfx_DrawDListOpa(play, (Gfx*)gRandoTreeDL);
+ } else if (D_80B3BF70[thisy->drawType & 0xF] != NULL) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, red, green, blue, 0);
+ Gfx_DrawDListOpa(play, (Gfx*)gRandoTreeDL);
+ gDPSetEnvColor(POLY_XLU_DISP++, red, green, blue, 0);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, D_80B3BF70[thisy->drawType & 0xF]);
+ }
+ CLOSE_DISPS(play->state.gfxCtx);
+
+ if (!EnWood02_RandomizerHoldsItem(thisy, gPlayState)) {
+ thisy->actor.draw = (ActorFunc)EnWood02_Draw;
+ }
+}
+
+void EnWood02_RandomizerSpawnCollectible(EnWood02* treeActor, PlayState* play) {
+ EnItem00* item00 = (EnItem00*)Item_DropCollectible2(play, &treeActor->actor.world.pos, ITEM00_SOH_DUMMY);
+ item00->randoInf = treeActor->treeId.randomizerInf;
+ item00->itemEntry =
+ Rando::Context::GetInstance()->GetFinalGIEntry(treeActor->treeId.randomizerCheck, true, GI_NONE);
+ item00->actor.draw = (ActorFunc)EnItem00_DrawRandomizedItem;
+ item00->actor.velocity.y = 0.0f;
+ item00->actor.world.pos.y += 120.0f;
+ item00->actor.speedXZ = 2.0f;
+ item00->actor.world.rot.y = Rand_CenteredFloat(65536.0f);
+ // clear randomizerCheck to prevent multiple bonks,
+ // reloading area without collecting drop won't persist this
+ treeActor->treeId.randomizerCheck = RC_UNKNOWN_CHECK;
+}
+
+void EnWood02_RandomizerInit(void* actorRef) {
+ EnWood02* treeActor = static_cast(actorRef);
+ if (treeActor->actor.params <= WOOD_TREE_KAKARIKO_ADULT) {
+ treeActor->treeId = OTRGlobals::Instance->gRandomizer->IdentifyTree(
+ gPlayState->sceneNum, (s16)treeActor->actor.world.pos.x, (s16)treeActor->actor.world.pos.z);
+ if (treeActor->treeId.randomizerCheck == RC_UNKNOWN_CHECK) {
+ LUSLOG_WARN("TREE %d,%d", (int)treeActor->actor.world.pos.x, (int)treeActor->actor.world.pos.z);
+ }
+ }
+}
+
+void RegisterShuffleTrees() {
+ bool shouldRegister = IS_RANDO && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TREES).Get();
+
+ COND_ID_HOOK(OnActorInit, ACTOR_EN_WOOD02, shouldRegister, EnWood02_RandomizerInit);
+
+ COND_VB_SHOULD(VB_TREE_SETUP_DRAW, shouldRegister, {
+ EnWood02* treeActor = va_arg(args, EnWood02*);
+ if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) {
+ treeActor->actor.draw = (ActorFunc)EnWood02_RandomizerDraw;
+ *should = false;
+ }
+ });
+
+ COND_VB_SHOULD(VB_TREE_DROP_ITEM, shouldRegister, {
+ EnWood02* treeActor = va_arg(args, EnWood02*);
+ if (EnWood02_RandomizerHoldsItem(treeActor, gPlayState)) {
+ EnWood02_RandomizerSpawnCollectible(treeActor, gPlayState);
+ *should = false;
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterShuffleTrees, { "IS_RANDO" });
+
+void Rando::StaticData::RegisterTreeLocations() {
+ // clang-format off
+ // Trees
+ // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check
+ locationTable[RC_MARKET_DAY_TREE] = Location::Tree(RC_MARKET_DAY_TREE, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_DAY, TWO_ACTOR_PARAMS(-100, 240), "Tree in Hyrule Market (Day)", RHT_TREE_MARKET, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MARKET_DAY_TREE));
+ locationTable[RC_HC_NEAR_GUARDS_TREE_1] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1209, 2242), "Tree Near Guards 1", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_1));
+ locationTable[RC_HC_NEAR_GUARDS_TREE_2] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(943, 2051), "Tree Near Guards 2", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_2));
+ locationTable[RC_HC_NEAR_GUARDS_TREE_3] = Location::Tree(RC_HC_NEAR_GUARDS_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(827, 1428), "Tree Near Guards 3", RHT_TREE_HYRULE_CASTLE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_GUARDS_TREE_3));
+ 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_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_HF_NEAR_KAK_TREE] = Location::Tree(RC_HF_NEAR_KAK_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3276, 971), "Tree Outside Kakariko", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_KAK_TREE));
+ locationTable[RC_HF_NEAR_KAK_SMALL_TREE] = Location::Tree(RC_HF_NEAR_KAK_SMALL_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2076, -91), "Small Tree Outside Kakariko", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_KAK_SMALL_TREE));
+ locationTable[RC_HF_TREE_NEAR_HC_GROTTO_1] = Location::Tree(RC_HF_TREE_NEAR_HC_GROTTO_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1041, 1022), "Tree Near HC Entrance Grotto 1", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_TREE_NEAR_HC_GROTTO_1));
+ locationTable[RC_HF_TREE_NEAR_HC_GROTTO_2] = Location::Tree(RC_HF_TREE_NEAR_HC_GROTTO_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1244, 819), "Tree Near HC Entrance Grotto 2", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_TREE_NEAR_HC_GROTTO_2));
+ locationTable[RC_HF_TREE_NEAR_HC_GROTTO_3] = Location::Tree(RC_HF_TREE_NEAR_HC_GROTTO_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1448, 620), "Tree Near HC Entrance Grotto 3", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_TREE_NEAR_HC_GROTTO_3));
+ locationTable[RC_HF_NEAR_LLR_TREE] = Location::Tree(RC_HF_NEAR_LLR_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-1907, 5409), "Tree Outside Lon Lon Ranch", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_LLR_TREE));
+ locationTable[RC_HF_NEAR_LH_TREE] = Location::Tree(RC_HF_NEAR_LH_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4377, 13662), "Tree Outside Lake Hylia", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_LH_TREE));
+ locationTable[RC_HF_CHILD_NEAR_GV_TREE] = Location::Tree(RC_HF_CHILD_NEAR_GV_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6270, 8579), "Child Near Gerudo Valley Tree", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_NEAR_GV_TREE));
+ locationTable[RC_HF_ADULT_NEAR_GV_TREE] = Location::Tree(RC_HF_ADULT_NEAR_GV_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-6241, 7097), "Adult Near Gerudo Valley Tree", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_ADULT_NEAR_GV_TREE));
+ locationTable[RC_HF_NEAR_ZR_TREE] = Location::Tree(RC_HF_NEAR_ZR_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3117, 4239), "Tree Outside Zora's River", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NEAR_ZR_TREE));
+ locationTable[RC_HF_NORTHWEST_TREE_1] = Location::Tree(RC_HF_NORTHWEST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4777, 136), "Tree in Northwest 1", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_1));
+ locationTable[RC_HF_NORTHWEST_TREE_2] = Location::Tree(RC_HF_NORTHWEST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4188, 263), "Tree in Northwest 2", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_2));
+ locationTable[RC_HF_NORTHWEST_TREE_3] = Location::Tree(RC_HF_NORTHWEST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5000, -147), "Tree in Northwest 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_3));
+ locationTable[RC_HF_NORTHWEST_TREE_4] = Location::Tree(RC_HF_NORTHWEST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4463, -182), "Tree in Northwest 4", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_4));
+ locationTable[RC_HF_NORTHWEST_TREE_5] = Location::Tree(RC_HF_NORTHWEST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-5262, 398), "Tree in Northwest 5", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_5));
+ locationTable[RC_HF_NORTHWEST_TREE_6] = Location::Tree(RC_HF_NORTHWEST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4391, 891), "Tree in Northwest 6", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_NORTHWEST_TREE_6));
+ locationTable[RC_HF_EAST_TREE_1] = Location::Tree(RC_HF_EAST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3817, 7119), "Tree in East 1", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_1));
+ locationTable[RC_HF_EAST_TREE_2] = Location::Tree(RC_HF_EAST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(4365, 7182), "Tree in East 2", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_2));
+ locationTable[RC_HF_EAST_TREE_3] = Location::Tree(RC_HF_EAST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3837, 7479), "Tree in East 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_3));
+ locationTable[RC_HF_EAST_TREE_4] = Location::Tree(RC_HF_EAST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3377, 7201), "Tree in East 4", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_4));
+ locationTable[RC_HF_EAST_TREE_5] = Location::Tree(RC_HF_EAST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3408, 6676), "Tree in East 5", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_5));
+ locationTable[RC_HF_EAST_TREE_6] = Location::Tree(RC_HF_EAST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(3935, 6279), "Tree in East 6", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_EAST_TREE_6));
+ locationTable[RC_HF_SOUTHEAST_TREE_1] = Location::Tree(RC_HF_SOUTHEAST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(915, 12557), "Tree in Southeast 1", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_1));
+ locationTable[RC_HF_SOUTHEAST_TREE_2] = Location::Tree(RC_HF_SOUTHEAST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(350, 11605), "Tree in Southeast 2", RHT_TREE_HYRULE_FIELD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_2));
+ locationTable[RC_HF_SOUTHEAST_TREE_3] = Location::Tree(RC_HF_SOUTHEAST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(470, 12494), "Tree in Southeast 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_3));
+ locationTable[RC_HF_SOUTHEAST_TREE_4] = Location::Tree(RC_HF_SOUTHEAST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(614, 12357), "Tree in Southeast 4", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_4));
+ locationTable[RC_HF_SOUTHEAST_TREE_5] = Location::Tree(RC_HF_SOUTHEAST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1114, 12156), "Tree in Southeast 5", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_5));
+ locationTable[RC_HF_SOUTHEAST_TREE_6] = Location::Tree(RC_HF_SOUTHEAST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(549, 11204), "Tree in Southeast 6", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_6));
+ locationTable[RC_HF_SOUTHEAST_TREE_7] = Location::Tree(RC_HF_SOUTHEAST_TREE_7, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(49, 11405), "Tree in Southeast 7", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_7));
+ locationTable[RC_HF_SOUTHEAST_TREE_8] = Location::Tree(RC_HF_SOUTHEAST_TREE_8, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-29, 12005), "Tree in Southeast 8", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_8));
+ locationTable[RC_HF_SOUTHEAST_TREE_9] = Location::Tree(RC_HF_SOUTHEAST_TREE_9, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1514,13157), "Tree in Southeast 9", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_9));
+ locationTable[RC_HF_SOUTHEAST_TREE_10] = Location::Tree(RC_HF_SOUTHEAST_TREE_10, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-509,12954), "Tree in Southeast 10", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_10));
+ locationTable[RC_HF_SOUTHEAST_TREE_11] = Location::Tree(RC_HF_SOUTHEAST_TREE_11, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-430,12354), "Tree in Southeast 11", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_11));
+ locationTable[RC_HF_SOUTHEAST_TREE_12] = Location::Tree(RC_HF_SOUTHEAST_TREE_12, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(69,12153), "Tree in Southeast 12", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_12));
+ locationTable[RC_HF_SOUTHEAST_TREE_13] = Location::Tree(RC_HF_SOUTHEAST_TREE_13, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-129,12554), "Tree in Southeast 13", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_13));
+ locationTable[RC_HF_SOUTHEAST_TREE_14] = Location::Tree(RC_HF_SOUTHEAST_TREE_14, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(950,11545), "Tree in Southeast 14", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_14));
+ locationTable[RC_HF_SOUTHEAST_TREE_15] = Location::Tree(RC_HF_SOUTHEAST_TREE_15, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(949,12205), "Tree in Southeast 15", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_15));
+ locationTable[RC_HF_SOUTHEAST_TREE_16] = Location::Tree(RC_HF_SOUTHEAST_TREE_16, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(469,13154), "Tree in Southeast 16", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_16));
+ locationTable[RC_HF_SOUTHEAST_TREE_17] = Location::Tree(RC_HF_SOUTHEAST_TREE_17, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(535,12957), "Tree in Southeast 17", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_17));
+ locationTable[RC_HF_SOUTHEAST_TREE_18] = Location::Tree(RC_HF_SOUTHEAST_TREE_18, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1515,12497), "Tree in Southeast 18", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_18));
+ locationTable[RC_HF_SOUTHEAST_TREE_19] = Location::Tree(RC_HF_SOUTHEAST_TREE_19, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-786,11293), "Tree in Southeast 19", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_SOUTHEAST_TREE_19));
+ locationTable[RC_HF_CHILD_SOUTHEAST_TREE_1] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1535, 11943), "Child Tree in Southeast Corner 1", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_1));
+ locationTable[RC_HF_CHILD_SOUTHEAST_TREE_2] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2135,11883), "Child Tree in Southeast Corner 2", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_2));
+ locationTable[RC_HF_CHILD_SOUTHEAST_TREE_3] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_3, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(2134,12543), "Child Tree in Southeast Corner 3", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_3));
+ locationTable[RC_HF_CHILD_SOUTHEAST_TREE_4] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_4, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1734,11542), "Child Tree in Southeast Corner 4", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_4));
+ locationTable[RC_HF_CHILD_SOUTHEAST_TREE_5] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_5, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1234,11743), "Child Tree in Southeast Corner 5", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_5));
+ locationTable[RC_HF_CHILD_SOUTHEAST_TREE_6] = Location::Tree(RC_HF_CHILD_SOUTHEAST_TREE_6, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(1155,12343), "Child Tree in Southeast Corner 6", RHT_TREE_HYRULE_FIELD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_CHILD_SOUTHEAST_TREE_6));
+ locationTable[RC_HF_TEKTITE_GROTTO_TREE] = Location::Tree(RC_HF_TEKTITE_GROTTO_TREE, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_HYRULE_FIELD, TWO_ACTOR_PARAMS(-4976, 2812), "Tektite Grotto Tree", RHT_TREE_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_TEKTITE_GROTTO_TREE));
+ locationTable[RC_ZF_TREE] = Location::Tree(RC_ZF_TREE, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(186, 2222), "Tree in Zora's Fountain", RHT_TREE_ZORAS_FOUNTAIN, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_TREE));
+ 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));
+ // clang-format on
+}
+
+static RegisterShipInitFunc registerFunc(Rando::StaticData::RegisterTreeLocations);
diff --git a/soh/soh/Enhancements/randomizer/context.cpp b/soh/soh/Enhancements/randomizer/context.cpp
index 2ee39006d..a8a397827 100644
--- a/soh/soh/Enhancements/randomizer/context.cpp
+++ b/soh/soh/Enhancements/randomizer/context.cpp
@@ -192,6 +192,7 @@ void Context::GenerateLocationPool() {
!mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_NO_LOGIC))) ||
(location.GetRCType() == RCTYPE_SMALL_CRATE && mOptions[RSK_SHUFFLE_CRATES].Is(RO_SHUFFLE_CRATES_OFF)) ||
(location.GetRCType() == RCTYPE_FAIRY && !mOptions[RSK_SHUFFLE_FAIRIES]) ||
+ (location.GetRCType() == RCTYPE_TREE && !mOptions[RSK_SHUFFLE_TREES]) ||
(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 f474397aa..c82724180 100644
--- a/soh/soh/Enhancements/randomizer/location.cpp
+++ b/soh/soh/Enhancements/randomizer/location.cpp
@@ -566,6 +566,15 @@ Rando::Location Rando::Location::SmallCrate(RandomizerCheck rc, RandomizerCheckQ
false, collectionCheck };
}
+Rando::Location Rando::Location::Tree(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_,
+ SceneID scene_, int32_t actorParams_, std::string&& shortName_,
+ RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
+ SpoilerCollectionCheck collectionCheck) {
+ return { rc, quest_, RCTYPE_TREE, 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 f99499652..6de26bc41 100644
--- a/soh/soh/Enhancements/randomizer/location.h
+++ b/soh/soh/Enhancements/randomizer/location.h
@@ -246,6 +246,10 @@ class Location {
RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
SpoilerCollectionCheck collectionCheck);
+ static Location Tree(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/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
index b9525386c..d88e6acff 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp
@@ -24,7 +24,7 @@ void RegionTable_Init_CastleGrounds() {
}, {
//Locations
LOCATION(RC_HC_MALON_EGG, true),
- LOCATION(RC_HC_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)),
+ LOCATION(RC_HC_GS_TREE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanBonkTrees()),
LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()),
LOCATION(RC_HC_MALON_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE_FAIRY, logic->CallGossipFairy()),
@@ -33,6 +33,14 @@ void RegionTable_Init_CastleGrounds() {
LOCATION(RC_HC_ROCK_WALL_GOSSIP_STONE, true),
LOCATION(RC_HC_GRASS_1, logic->CanCutShrubs()),
LOCATION(RC_HC_GRASS_2, logic->CanCutShrubs()),
+ LOCATION(RC_HC_GROTTO_TREE, logic->CanBonkTrees()),
+ LOCATION(RC_HC_SKULLTULA_TREE, logic->CanBonkTrees()),
+ LOCATION(RC_HC_NEAR_GUARDS_TREE_1, logic->CanBonkTrees()),
+ LOCATION(RC_HC_NEAR_GUARDS_TREE_2, logic->CanBonkTrees()),
+ LOCATION(RC_HC_NEAR_GUARDS_TREE_3, logic->CanBonkTrees()),
+ LOCATION(RC_HC_NEAR_GUARDS_TREE_4, logic->CanBonkTrees()),
+ LOCATION(RC_HC_NEAR_GUARDS_TREE_5, logic->CanBonkTrees()),
+ LOCATION(RC_HC_NEAR_GUARDS_TREE_6, logic->CanBonkTrees()),
}, {
//Exits
Entrance(RR_CASTLE_GROUNDS, []{return true;}),
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 5bc3aeb26..98b904cc6 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp
@@ -61,6 +61,54 @@ void RegionTable_Init_HyruleField() {
LOCATION(RC_HF_NEAR_KF_GRASS_10, logic->CanCutShrubs()),
LOCATION(RC_HF_NEAR_KF_GRASS_11, logic->CanCutShrubs()),
LOCATION(RC_HF_NEAR_KF_GRASS_12, logic->CanCutShrubs()),
+ LOCATION(RC_HF_NEAR_LLR_TREE, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NEAR_LH_TREE, logic->CanBonkTrees()),
+ LOCATION(RC_HF_CHILD_NEAR_GV_TREE, logic->IsChild && logic->CanBonkTrees()),
+ LOCATION(RC_HF_ADULT_NEAR_GV_TREE, logic->IsAdult && logic->CanBonkTrees()),
+ LOCATION(RC_HF_NEAR_ZR_TREE, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NEAR_KAK_TREE, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NEAR_KAK_SMALL_TREE, logic->CanBonkTrees()),
+ LOCATION(RC_HF_TREE_NEAR_HC_GROTTO_1, logic->CanBonkTrees()),
+ LOCATION(RC_HF_TREE_NEAR_HC_GROTTO_2, logic->CanBonkTrees()),
+ LOCATION(RC_HF_TREE_NEAR_HC_GROTTO_3, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NORTHWEST_TREE_1, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NORTHWEST_TREE_2, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NORTHWEST_TREE_3, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NORTHWEST_TREE_4, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NORTHWEST_TREE_5, logic->CanBonkTrees()),
+ LOCATION(RC_HF_NORTHWEST_TREE_6, logic->CanBonkTrees()),
+ LOCATION(RC_HF_EAST_TREE_1, logic->CanBonkTrees()),
+ LOCATION(RC_HF_EAST_TREE_2, logic->CanBonkTrees()),
+ LOCATION(RC_HF_EAST_TREE_3, logic->CanBonkTrees()),
+ LOCATION(RC_HF_EAST_TREE_4, logic->CanBonkTrees()),
+ LOCATION(RC_HF_EAST_TREE_5, logic->CanBonkTrees()),
+ LOCATION(RC_HF_EAST_TREE_6, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_1, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_2, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_3, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_4, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_5, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_6, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_7, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_8, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_9, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_10, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_11, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_12, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_13, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_14, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_15, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_16, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_17, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_18, logic->CanBonkTrees()),
+ LOCATION(RC_HF_SOUTHEAST_TREE_19, logic->CanBonkTrees()),
+ LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_1, logic->IsChild && logic->CanBonkTrees()),
+ LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_2, logic->IsChild && logic->CanBonkTrees()),
+ LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_3, logic->IsChild && logic->CanBonkTrees()),
+ LOCATION(RC_HF_CHILD_SOUTHEAST_TREE_4, logic->IsChild && logic->CanBonkTrees()),
+ 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()),
}, {
//Exits
Entrance(RR_LW_BRIDGE, []{return true;}),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
index 13490c9a4..9ca3fd266 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
@@ -20,7 +20,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION, logic->IsChild && logic->CanGetNightTimeGS()),
LOCATION(RC_KAK_GS_SKULLTULA_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()),
LOCATION(RC_KAK_GS_GUARDS_HOUSE, logic->IsChild && logic->CanGetNightTimeGS()),
- LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->CanGetNightTimeGS()),
+ LOCATION(RC_KAK_GS_TREE, logic->IsChild && logic->CanGetNightTimeGS() && logic->CanBonkTrees()),
LOCATION(RC_KAK_GS_WATCHTOWER, logic->IsChild && (logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer())) && logic->CanGetNightTimeGS()),
LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_1, logic->IsChild && logic->CanBreakPots()),
LOCATION(RC_KAK_NEAR_POTION_SHOP_POT_2, logic->IsChild && logic->CanBreakPots()),
@@ -57,6 +57,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_NEAR_FENCE_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()),
LOCATION(RC_KAK_NEAR_BOARDING_HOUSE_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()),
LOCATION(RC_KAK_NEAR_BAZAAR_CHILD_CRATE, logic->IsChild && logic->CanBreakCrates()),
+ LOCATION(RC_KAK_TREE, logic->IsChild && logic->CanBonkTrees()),
}, {
//Exits
Entrance(RR_HYRULE_FIELD, []{return true;}),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
index c29a5924e..e6c29e425 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
@@ -12,7 +12,7 @@ void RegionTable_Init_LonLonRanch() {
}, {
//Locations
LOCATION(RC_SONG_FROM_MALON, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER) && logic->HasItem(RG_FAIRY_OCARINA) && logic->AtDay),
- LOCATION(RC_LLR_GS_TREE, logic->IsChild),
+ LOCATION(RC_LLR_GS_TREE, logic->IsChild && logic->CanBonkTrees()),
LOCATION(RC_LLR_GS_RAIN_SHED, logic->IsChild && logic->CanGetNightTimeGS()),
LOCATION(RC_LLR_GS_HOUSE_WINDOW, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()),
LOCATION(RC_LLR_GS_BACK_WALL, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()),
@@ -24,6 +24,7 @@ void RegionTable_Init_LonLonRanch() {
LOCATION(RC_LLR_RAIN_SHED_POT_2, logic->IsChild && logic->CanBreakPots()),
LOCATION(RC_LLR_RAIN_SHED_POT_3, logic->IsChild && logic->CanBreakPots()),
LOCATION(RC_LLR_NEAR_TREE_CRATE, logic->IsChild && logic->CanBreakCrates()),
+ LOCATION(RC_LLR_TREE, logic->IsChild && logic->CanBonkTrees()),
}, {
//Exits
Entrance(RR_HYRULE_FIELD, []{return true;}),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
index 7d7655ef0..63e2570ad 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
@@ -27,6 +27,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/),
LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/),
LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/),
+ LOCATION(RC_MARKET_DAY_TREE, logic->IsChild && logic->CanBonkTrees() && logic->AtDay),
}, {
//Exits
Entrance(RR_MARKET_ENTRANCE, []{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 cfd2125c1..b0b3ab8b5 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp
@@ -11,7 +11,7 @@ void RegionTable_Init_ZorasFountain() {
EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}),
}, {
//Locations
- LOCATION(RC_ZF_GS_TREE, logic->IsChild),
+ LOCATION(RC_ZF_GS_TREE, logic->IsChild && logic->CanBonkTrees()),
LOCATION(RC_ZF_GS_ABOVE_THE_LOG, logic->IsChild && logic->HookshotOrBoomerang() && logic->CanGetNightTimeGS()),
LOCATION(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY, logic->CallGossipFairyExceptSuns()),
LOCATION(RC_ZF_FAIRY_GOSSIP_STONE_FAIRY_BIG, logic->CanUse(RG_SONG_OF_STORMS)),
@@ -23,6 +23,7 @@ void RegionTable_Init_ZorasFountain() {
LOCATION(RC_ZF_NEAR_JABU_POT_2, logic->IsChild && logic->CanBreakPots()),
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()),
}, {
//Exits
Entrance(RR_ZD_BEHIND_KING_ZORA, []{return true;}),
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
index 5473ee2ca..c8f24b85a 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp
@@ -7,7 +7,7 @@ void RegionTable_Init_ZoraRiver() {
// clang-format off
areaTable[RR_ZR_FRONT] = Region("ZR Front", SCENE_ZORAS_RIVER, {}, {
//Locations
- LOCATION(RC_ZR_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE)),
+ LOCATION(RC_ZR_GS_TREE, logic->IsChild && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_CLOSE) && logic->CanBonkTrees()),
LOCATION(RC_ZR_GRASS_1, logic->CanCutShrubs()),
LOCATION(RC_ZR_GRASS_2, logic->CanCutShrubs()),
LOCATION(RC_ZR_GRASS_3, logic->CanCutShrubs()),
@@ -20,6 +20,7 @@ void RegionTable_Init_ZoraRiver() {
LOCATION(RC_ZR_GRASS_10, logic->CanCutShrubs()),
LOCATION(RC_ZR_GRASS_11, logic->CanCutShrubs()),
LOCATION(RC_ZR_GRASS_12, logic->CanCutShrubs()),
+ LOCATION(RC_ZR_TREE, logic->IsChild && logic->CanBonkTrees()),
}, {
//Exits
Entrance(RR_ZORAS_RIVER, []{return logic->IsAdult || logic->BlastOrSmash();}),
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index 442f2b23b..61057944d 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -1152,6 +1152,10 @@ bool Logic::CanBreakSmallCrates() {
return true;
}
+bool Logic::CanBonkTrees() {
+ return true;
+}
+
bool Logic::HasExplosives() {
return CanUse(RG_BOMB_BAG) || CanUse(RG_BOMBCHU_5);
}
diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h
index ba9ab60d0..2a339b34b 100644
--- a/soh/soh/Enhancements/randomizer/logic.h
+++ b/soh/soh/Enhancements/randomizer/logic.h
@@ -247,6 +247,7 @@ class Logic {
bool CanBreakPots();
bool CanBreakCrates();
bool CanBreakSmallCrates();
+ bool CanBonkTrees();
bool HasFireSource();
bool HasFireSourceWithTorch();
bool TradeQuestStep(RandomizerGet rg);
diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
index 16c89a1c4..a86ac3281 100644
--- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp
+++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
@@ -288,6 +288,10 @@ void Settings::CreateOptionDescriptions() {
"Overworld - Only shuffle crates that are outside of dungeons.\n"
"\n"
"All Crates - Shuffle all crates.";
+ mOptionDescriptions[RSK_SHUFFLE_TREES] =
+ "Trees will contain randomized items which are dropped the first time the player rolls into one.\n"
+ "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.";
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 abfa8f3b6..bcec85029 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -3258,6 +3258,67 @@ std::map rcToRandomizerInf = {
RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE,
RAND_INF_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE,
},
+ { RC_MARKET_DAY_TREE, RAND_INF_MARKET_DAY_TREE },
+ { RC_HC_NEAR_GUARDS_TREE_1, RAND_INF_HC_NEAR_GUARDS_TREE_1 },
+ { RC_HC_NEAR_GUARDS_TREE_2, RAND_INF_HC_NEAR_GUARDS_TREE_2 },
+ { RC_HC_NEAR_GUARDS_TREE_3, RAND_INF_HC_NEAR_GUARDS_TREE_3 },
+ { RC_HC_NEAR_GUARDS_TREE_4, RAND_INF_HC_NEAR_GUARDS_TREE_4 },
+ { RC_HC_NEAR_GUARDS_TREE_5, RAND_INF_HC_NEAR_GUARDS_TREE_5 },
+ { RC_HC_NEAR_GUARDS_TREE_6, RAND_INF_HC_NEAR_GUARDS_TREE_6 },
+ { RC_HC_SKULLTULA_TREE, RAND_INF_HC_SKULLTULA_TREE },
+ { RC_HC_GROTTO_TREE, RAND_INF_HC_GROTTO_TREE },
+ { RC_HF_NEAR_KAK_TREE, RAND_INF_HF_NEAR_KAK_TREE },
+ { RC_HF_NEAR_KAK_SMALL_TREE, RAND_INF_HF_NEAR_KAK_SMALL_TREE },
+ { RC_HF_TREE_NEAR_HC_GROTTO_1, RAND_INF_HF_TREE_NEAR_HC_GROTTO_1 },
+ { RC_HF_TREE_NEAR_HC_GROTTO_2, RAND_INF_HF_TREE_NEAR_HC_GROTTO_2 },
+ { RC_HF_TREE_NEAR_HC_GROTTO_3, RAND_INF_HF_TREE_NEAR_HC_GROTTO_3 },
+ { RC_HF_NEAR_LLR_TREE, RAND_INF_HF_NEAR_LLR_TREE },
+ { RC_HF_NEAR_LH_TREE, RAND_INF_HF_NEAR_LH_TREE },
+ { RC_HF_CHILD_NEAR_GV_TREE, RAND_INF_HF_CHILD_NEAR_GV_TREE },
+ { RC_HF_ADULT_NEAR_GV_TREE, RAND_INF_HF_ADULT_NEAR_GV_TREE },
+ { RC_HF_NEAR_ZR_TREE, RAND_INF_HF_NEAR_ZR_TREE },
+ { RC_HF_NORTHWEST_TREE_1, RAND_INF_HF_NORTHWEST_TREE_1 },
+ { RC_HF_NORTHWEST_TREE_2, RAND_INF_HF_NORTHWEST_TREE_2 },
+ { RC_HF_NORTHWEST_TREE_3, RAND_INF_HF_NORTHWEST_TREE_3 },
+ { RC_HF_NORTHWEST_TREE_4, RAND_INF_HF_NORTHWEST_TREE_4 },
+ { RC_HF_NORTHWEST_TREE_5, RAND_INF_HF_NORTHWEST_TREE_5 },
+ { RC_HF_NORTHWEST_TREE_6, RAND_INF_HF_NORTHWEST_TREE_6 },
+ { RC_HF_EAST_TREE_1, RAND_INF_HF_EAST_TREE_1 },
+ { RC_HF_EAST_TREE_2, RAND_INF_HF_EAST_TREE_2 },
+ { RC_HF_EAST_TREE_3, RAND_INF_HF_EAST_TREE_3 },
+ { RC_HF_EAST_TREE_4, RAND_INF_HF_EAST_TREE_4 },
+ { RC_HF_EAST_TREE_5, RAND_INF_HF_EAST_TREE_5 },
+ { RC_HF_EAST_TREE_6, RAND_INF_HF_EAST_TREE_6 },
+ { RC_HF_SOUTHEAST_TREE_1, RAND_INF_HF_SOUTHEAST_TREE_1 },
+ { RC_HF_SOUTHEAST_TREE_2, RAND_INF_HF_SOUTHEAST_TREE_2 },
+ { RC_HF_SOUTHEAST_TREE_3, RAND_INF_HF_SOUTHEAST_TREE_3 },
+ { RC_HF_SOUTHEAST_TREE_4, RAND_INF_HF_SOUTHEAST_TREE_4 },
+ { RC_HF_SOUTHEAST_TREE_5, RAND_INF_HF_SOUTHEAST_TREE_5 },
+ { RC_HF_SOUTHEAST_TREE_6, RAND_INF_HF_SOUTHEAST_TREE_6 },
+ { RC_HF_SOUTHEAST_TREE_7, RAND_INF_HF_SOUTHEAST_TREE_7 },
+ { RC_HF_SOUTHEAST_TREE_8, RAND_INF_HF_SOUTHEAST_TREE_8 },
+ { RC_HF_SOUTHEAST_TREE_9, RAND_INF_HF_SOUTHEAST_TREE_9 },
+ { RC_HF_SOUTHEAST_TREE_10, RAND_INF_HF_SOUTHEAST_TREE_10 },
+ { RC_HF_SOUTHEAST_TREE_11, RAND_INF_HF_SOUTHEAST_TREE_11 },
+ { RC_HF_SOUTHEAST_TREE_12, RAND_INF_HF_SOUTHEAST_TREE_12 },
+ { RC_HF_SOUTHEAST_TREE_13, RAND_INF_HF_SOUTHEAST_TREE_13 },
+ { RC_HF_SOUTHEAST_TREE_14, RAND_INF_HF_SOUTHEAST_TREE_14 },
+ { RC_HF_SOUTHEAST_TREE_15, RAND_INF_HF_SOUTHEAST_TREE_15 },
+ { RC_HF_SOUTHEAST_TREE_16, RAND_INF_HF_SOUTHEAST_TREE_16 },
+ { RC_HF_SOUTHEAST_TREE_17, RAND_INF_HF_SOUTHEAST_TREE_17 },
+ { RC_HF_SOUTHEAST_TREE_18, RAND_INF_HF_SOUTHEAST_TREE_18 },
+ { RC_HF_SOUTHEAST_TREE_19, RAND_INF_HF_SOUTHEAST_TREE_19 },
+ { RC_HF_CHILD_SOUTHEAST_TREE_1, RAND_INF_HF_CHILD_SOUTHEAST_TREE_1 },
+ { RC_HF_CHILD_SOUTHEAST_TREE_2, RAND_INF_HF_CHILD_SOUTHEAST_TREE_2 },
+ { RC_HF_CHILD_SOUTHEAST_TREE_3, RAND_INF_HF_CHILD_SOUTHEAST_TREE_3 },
+ { RC_HF_CHILD_SOUTHEAST_TREE_4, RAND_INF_HF_CHILD_SOUTHEAST_TREE_4 },
+ { RC_HF_CHILD_SOUTHEAST_TREE_5, RAND_INF_HF_CHILD_SOUTHEAST_TREE_5 },
+ { RC_HF_CHILD_SOUTHEAST_TREE_6, RAND_INF_HF_CHILD_SOUTHEAST_TREE_6 },
+ { RC_HF_TEKTITE_GROTTO_TREE, RAND_INF_HF_TEKTITE_GROTTO_TREE },
+ { RC_ZF_TREE, RAND_INF_ZF_TREE },
+ { RC_ZR_TREE, RAND_INF_ZR_TREE },
+ { RC_KAK_TREE, RAND_INF_KAK_TREE },
+ { RC_LLR_TREE, RAND_INF_LLR_TREE },
};
BeehiveIdentity Randomizer::IdentifyBeehive(s32 sceneNum, s16 xPosition, s32 respawnData) {
@@ -3679,6 +3740,26 @@ SmallCrateIdentity Randomizer::IdentifySmallCrate(s32 sceneNum, s32 posX, s32 po
return smallCrateIdentity;
}
+TreeIdentity Randomizer::IdentifyTree(s32 sceneNum, s32 posX, s32 posZ) {
+ struct TreeIdentity treeIdentity;
+
+ for (int x = -1; x <= 1; x++) {
+ for (int z = -1; z <= 1; z++) {
+ s32 actorParams = TWO_ACTOR_PARAMS(posX + x, posZ + z);
+ Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_WOOD02, sceneNum, actorParams);
+ if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) {
+ treeIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()];
+ treeIdentity.randomizerCheck = location->GetRandomizerCheck();
+ return treeIdentity;
+ }
+ }
+ }
+
+ treeIdentity.randomizerInf = RAND_INF_MAX;
+ treeIdentity.randomizerCheck = RC_UNKNOWN_CHECK;
+ return treeIdentity;
+}
+
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
return Rando::Context::GetInstance()->GetOption(randoSettingKey).Get();
}
diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h
index 78f48b01c..54c85307b 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.h
+++ b/soh/soh/Enhancements/randomizer/randomizer.h
@@ -57,6 +57,7 @@ class Randomizer {
GrassIdentity IdentifyGrass(s32 sceneNum, s32 posX, s32 posZ, s32 respawnData, s32 linkAge);
CrateIdentity IdentifyCrate(s32 sceneNum, s32 posX, s32 posZ);
SmallCrateIdentity IdentifySmallCrate(s32 sceneNum, s32 posX, s32 posZ);
+ TreeIdentity IdentifyTree(s32 sceneNum, s32 posX, s32 posZ);
GetItemEntry GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId,
bool checkObtainability = true);
GetItemEntry GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId,
diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h
index 8295eb6cd..a1611dd7c 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -299,6 +299,7 @@ typedef enum {
RCTYPE_CRATE, // Crates
RCTYPE_NLCRATE, // NL Crates
RCTYPE_SMALL_CRATE, // Small crates
+ RCTYPE_TREE, // Trees
RCTYPE_DUNGEON_REWARD, // Dungeon rewards (blue warps)
RCTYPE_OCARINA, // Ocarina locations
RCTYPE_BEEHIVE, // Beehives
@@ -2645,6 +2646,70 @@ typedef enum {
RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE,
// End Crates
+ // Start Trees
+ RC_MARKET_DAY_TREE,
+ RC_HC_NEAR_GUARDS_TREE_1,
+ RC_HC_NEAR_GUARDS_TREE_2,
+ RC_HC_NEAR_GUARDS_TREE_3,
+ RC_HC_NEAR_GUARDS_TREE_4,
+ RC_HC_NEAR_GUARDS_TREE_5,
+ RC_HC_NEAR_GUARDS_TREE_6,
+ RC_HC_SKULLTULA_TREE,
+ RC_HC_GROTTO_TREE,
+ RC_HF_NEAR_LLR_TREE,
+ RC_HF_NEAR_LH_TREE,
+ RC_HF_CHILD_NEAR_GV_TREE,
+ RC_HF_ADULT_NEAR_GV_TREE,
+ RC_HF_NEAR_ZR_TREE,
+ RC_HF_NEAR_KAK_TREE,
+ RC_HF_NEAR_KAK_SMALL_TREE,
+ RC_HF_TREE_NEAR_HC_GROTTO_1,
+ RC_HF_TREE_NEAR_HC_GROTTO_2,
+ RC_HF_TREE_NEAR_HC_GROTTO_3,
+ RC_HF_NORTHWEST_TREE_1,
+ RC_HF_NORTHWEST_TREE_2,
+ RC_HF_NORTHWEST_TREE_3,
+ RC_HF_NORTHWEST_TREE_4,
+ RC_HF_NORTHWEST_TREE_5,
+ RC_HF_NORTHWEST_TREE_6,
+ RC_HF_EAST_TREE_1,
+ RC_HF_EAST_TREE_2,
+ RC_HF_EAST_TREE_3,
+ RC_HF_EAST_TREE_4,
+ RC_HF_EAST_TREE_5,
+ RC_HF_EAST_TREE_6,
+ RC_HF_SOUTHEAST_TREE_1,
+ RC_HF_SOUTHEAST_TREE_2,
+ RC_HF_SOUTHEAST_TREE_3,
+ RC_HF_SOUTHEAST_TREE_4,
+ RC_HF_SOUTHEAST_TREE_5,
+ RC_HF_SOUTHEAST_TREE_6,
+ RC_HF_SOUTHEAST_TREE_7,
+ RC_HF_SOUTHEAST_TREE_8,
+ RC_HF_SOUTHEAST_TREE_9,
+ RC_HF_SOUTHEAST_TREE_10,
+ RC_HF_SOUTHEAST_TREE_11,
+ RC_HF_SOUTHEAST_TREE_12,
+ RC_HF_SOUTHEAST_TREE_13,
+ RC_HF_SOUTHEAST_TREE_14,
+ RC_HF_SOUTHEAST_TREE_15,
+ RC_HF_SOUTHEAST_TREE_16,
+ RC_HF_SOUTHEAST_TREE_17,
+ RC_HF_SOUTHEAST_TREE_18,
+ RC_HF_SOUTHEAST_TREE_19,
+ RC_HF_CHILD_SOUTHEAST_TREE_1,
+ RC_HF_CHILD_SOUTHEAST_TREE_2,
+ RC_HF_CHILD_SOUTHEAST_TREE_3,
+ RC_HF_CHILD_SOUTHEAST_TREE_4,
+ RC_HF_CHILD_SOUTHEAST_TREE_5,
+ RC_HF_CHILD_SOUTHEAST_TREE_6,
+ RC_HF_TEKTITE_GROTTO_TREE,
+ RC_ZF_TREE,
+ RC_ZR_TREE,
+ RC_KAK_TREE,
+ RC_LLR_TREE,
+ // End Trees
+
RC_PIERRE,
RC_DELIVER_RUTOS_LETTER,
RC_MASTER_SWORD_PEDESTAL,
@@ -5477,6 +5542,14 @@ typedef enum {
RHT_CRATE_SPIRIT_TEMPLE,
RHT_CRATE_SHADOW_TEMPLE,
RHT_CRATE_GERUDO_TRAINING_GROUND,
+ // Shuffle Trees
+ RHT_TREE_HYRULE_FIELD,
+ RHT_TREE_MARKET,
+ RHT_TREE_HYRULE_CASTLE,
+ RHT_TREE_ZORAS_FOUNTAIN,
+ RHT_TREE_ZORAS_RIVER,
+ RHT_TREE_LON_LON_RANCH,
+ RHT_TREE_KAKARIKO,
// Ganon Line
RHT_GANON_JOKE01,
RHT_GANON_JOKE02,
@@ -5815,6 +5888,7 @@ typedef enum {
RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD,
RSK_SHUFFLE_POTS,
RSK_SHUFFLE_CRATES,
+ RSK_SHUFFLE_TREES,
RSK_SHUFFLE_FROG_SONG_RUPEES,
RSK_ITEM_POOL,
RSK_ICE_TRAPS,
@@ -6426,6 +6500,11 @@ typedef struct SmallCrateIdentity {
RandomizerCheck randomizerCheck;
} SmallCrateIdentity;
+typedef struct TreeIdentity {
+ RandomizerInf randomizerInf;
+ RandomizerCheck randomizerCheck;
+} TreeIdentity;
+
typedef enum {
TRACKER_WINDOW_FLOATING,
TRACKER_WINDOW_WINDOW,
diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp
index da05ee508..29e0fae7a 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp
@@ -189,6 +189,8 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() {
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCrates"), RO_GENERIC_NO)) &&
(location.GetRCType() != RCTYPE_SMALL_CRATE ||
CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleCrates"), RO_GENERIC_NO)) &&
+ (location.GetRCType() != RCTYPE_TREE ||
+ CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleTrees"), RO_GENERIC_NO)) &&
(location.GetRCType() != RCTYPE_FISH ||
ctx->GetFishsanity()->GetFishLocationIncluded(&location, FSO_SOURCE_CVARS)) &&
(location.GetRCType() != RCTYPE_ADULT_TRADE ||
diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
index d460c6daf..56480079b 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp
@@ -68,6 +68,7 @@ bool showOverworldGrass;
bool showDungeonGrass;
bool showOverworldCrates;
bool showDungeonCrates;
+bool showTrees;
bool showFrogSongRupees;
bool showFairies;
bool showStartingMapsCompasses;
@@ -1448,6 +1449,7 @@ void LoadSettings() {
showDungeonCrates = false;
break;
}
+ showTrees = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TREES);
} else { // Vanilla
showOverworldTokens = true;
showDungeonTokens = true;
@@ -1457,6 +1459,7 @@ void LoadSettings() {
showDungeonGrass = false;
showOverworldCrates = false;
showDungeonCrates = false;
+ showTrees = false;
}
fortressFast = false;
@@ -1569,7 +1572,7 @@ bool IsCheckShuffled(RandomizerCheck rc) {
(loc->GetRCType() != RCTYPE_SMALL_CRATE ||
(showOverworldCrates && RandomizerCheckObjects::AreaIsOverworld(loc->GetArea())) ||
(showDungeonCrates && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))) &&
- (loc->GetRCType() != RCTYPE_COW || showCows) &&
+ (loc->GetRCType() != RCTYPE_TREE || showTrees) && (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 cf2f83d3a..1349b27df 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_inf.h
+++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h
@@ -997,6 +997,67 @@ DEFINE_RAND_INF(RAND_INF_SHADOW_TEMPLE_MQ_TRUTH_SPINNER_SMALL_CRATE_3)
DEFINE_RAND_INF(RAND_INF_SHADOW_TEMPLE_MQ_TRUTH_SPINNER_SMALL_CRATE_4)
DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_STATUE_SMALL_CRATE)
DEFINE_RAND_INF(RAND_INF_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE)
+DEFINE_RAND_INF(RAND_INF_MARKET_DAY_TREE)
+DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_1)
+DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_2)
+DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_3)
+DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_4)
+DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_5)
+DEFINE_RAND_INF(RAND_INF_HC_NEAR_GUARDS_TREE_6)
+DEFINE_RAND_INF(RAND_INF_HC_SKULLTULA_TREE)
+DEFINE_RAND_INF(RAND_INF_HC_GROTTO_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_NEAR_LLR_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_NEAR_LH_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_CHILD_NEAR_GV_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_ADULT_NEAR_GV_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_NEAR_ZR_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_NEAR_KAK_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_NEAR_KAK_SMALL_TREE)
+DEFINE_RAND_INF(RAND_INF_HF_TREE_NEAR_HC_GROTTO_1)
+DEFINE_RAND_INF(RAND_INF_HF_TREE_NEAR_HC_GROTTO_2)
+DEFINE_RAND_INF(RAND_INF_HF_TREE_NEAR_HC_GROTTO_3)
+DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_1)
+DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_2)
+DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_3)
+DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_4)
+DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_5)
+DEFINE_RAND_INF(RAND_INF_HF_NORTHWEST_TREE_6)
+DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_1)
+DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_2)
+DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_3)
+DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_4)
+DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_5)
+DEFINE_RAND_INF(RAND_INF_HF_EAST_TREE_6)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_1)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_2)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_3)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_4)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_5)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_6)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_7)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_8)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_9)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_10)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_11)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_12)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_13)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_14)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_15)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_16)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_17)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_18)
+DEFINE_RAND_INF(RAND_INF_HF_SOUTHEAST_TREE_19)
+DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_1)
+DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_2)
+DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_3)
+DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_4)
+DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_5)
+DEFINE_RAND_INF(RAND_INF_HF_CHILD_SOUTHEAST_TREE_6)
+DEFINE_RAND_INF(RAND_INF_HF_TEKTITE_GROTTO_TREE)
+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_CAUGHT_LOACH)
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index 52add036e..c99947f6b 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -216,6 +216,7 @@ void Settings::CreateOptions() {
OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WidgetType::Combobox, RO_SHUFFLE_POTS_OFF);
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_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);
@@ -1277,6 +1278,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_COWS],
&mOptions[RSK_SHUFFLE_POTS],
&mOptions[RSK_SHUFFLE_CRATES],
+ &mOptions[RSK_SHUFFLE_TREES],
&mOptions[RSK_SHUFFLE_MERCHANTS],
&mOptions[RSK_MERCHANT_PRICES],
&mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE],
@@ -1509,6 +1511,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_SHUFFLE_COWS],
&mOptions[RSK_SHUFFLE_POTS],
&mOptions[RSK_SHUFFLE_CRATES],
+ &mOptions[RSK_SHUFFLE_TREES],
&mOptions[RSK_SHUFFLE_KOKIRI_SWORD],
&mOptions[RSK_SHUFFLE_OCARINA],
&mOptions[RSK_SHUFFLE_OCARINA_BUTTONS],
diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h
index 7bdec17c1..d6a151391 100644
--- a/soh/soh/Enhancements/randomizer/static_data.h
+++ b/soh/soh/Enhancements/randomizer/static_data.h
@@ -58,6 +58,7 @@ class StaticData {
static void RegisterFreestandingLocations();
static void RegisterGrassLocations();
static void RegisterCrateLocations();
+ static void RegisterTreeLocations();
static void InitHashMaps();
static std::array, 17> randomizerFishingPondFish;
static std::unordered_map randomizerGrottoFishMap;
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 2fe2445a6..1fe96d38c 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
@@ -357,16 +357,18 @@ void EnWood02_Update(Actor* thisx, PlayState* play2) {
dropsSpawnPt = this->actor.world.pos;
dropsSpawnPt.y += 200.0f;
- if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) {
- if (GameInteractor_Should(VB_TREE_DROP_COLLECTIBLE, true, this)) {
- Item_DropCollectibleRandom(play, &this->actor, &dropsSpawnPt, this->unk_14C << 4);
+ if (GameInteractor_Should(VB_TREE_DROP_ITEM, true, this)) {
+ if ((this->unk_14C >= 0) && (this->unk_14C < 0x64)) {
+ if (GameInteractor_Should(VB_TREE_DROP_COLLECTIBLE, true, this)) {
+ Item_DropCollectibleRandom(play, &this->actor, &dropsSpawnPt, this->unk_14C << 4);
+ }
+ } else if (this->actor.home.rot.z != 0) {
+ this->actor.home.rot.z &= 0x1FFF;
+ this->actor.home.rot.z |= 0xE000;
+ Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SW, dropsSpawnPt.x, dropsSpawnPt.y, dropsSpawnPt.z, 0,
+ this->actor.world.rot.y, 0, this->actor.home.rot.z, true);
+ this->actor.home.rot.z = 0;
}
- } else if (this->actor.home.rot.z != 0) {
- this->actor.home.rot.z &= 0x1FFF;
- this->actor.home.rot.z |= 0xE000;
- Actor_Spawn(&play->actorCtx, play, ACTOR_EN_SW, dropsSpawnPt.x, dropsSpawnPt.y, dropsSpawnPt.z, 0,
- this->actor.world.rot.y, 0, this->actor.home.rot.z, true);
- this->actor.home.rot.z = 0;
}
// Spawn falling leaves
@@ -457,12 +459,13 @@ void EnWood02_Draw(Actor* thisx, PlayState* play) {
}
Gfx_SetupDL_25Xlu(gfxCtx);
-
- if ((this->actor.params == WOOD_LEAF_GREEN) || (this->actor.params == WOOD_LEAF_YELLOW)) {
+ if (GameInteractor_Should(VB_TREE_SETUP_DRAW,
+ (this->actor.params == WOOD_LEAF_GREEN) || (this->actor.params == WOOD_LEAF_YELLOW),
+ this)) {
Gfx_SetupDL_25Opa(gfxCtx);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, red, green, blue, 127);
Gfx_DrawDListOpa(play, object_wood02_DL_000700);
- } else if (D_80B3BF70[this->drawType & 0xF] != NULL) {
+ } else if (GameInteractor_Should(VB_TREE_SETUP_DRAW, D_80B3BF70[this->drawType & 0xF] != NULL, this)) {
Gfx_DrawDListOpa(play, D_80B3BF54[this->drawType & 0xF]);
gDPSetEnvColor(POLY_XLU_DISP++, red, green, blue, 0);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.h b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.h
index 96746c0af..6cc2cdae1 100644
--- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.h
+++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.h
@@ -13,6 +13,7 @@ typedef struct EnWood02 {
/* 0x0153 */ u8 spawnType;
/* 0x0154 */ u8 drawType;
/* 0x0158 */ ColliderCylinder collider;
+ /* */ TreeIdentity treeId;
} EnWood02; // size = 0x01A4
// Types with SPAWNED in the name are those that can be managed by a spawner, however the actor allows you to spawn them