diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 5e4004033..9345cd609 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2170,6 +2170,14 @@ typedef enum { // - `*BossVa` VB_SPAWN_BLUE_WARP, + // #### `result` + // ```c + // this->timer == 4 + // ``` + // #### `args` + // - `*EnButte` + VB_SPAWN_BUTTERFLY_FAIRY, + // #### `result` // ```c // INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_NONE 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 487c76158..83e04f5e2 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 @@ -2135,6 +2135,30 @@ void StaticData::HintTable_Init_Exclude_Overworld() { 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 })); + + hintTextTable[RHT_BUTTERFLY_FAIRY_HYRULE_CASTLE] = HintText(CustomMessage("They say that a #butterfly near the castle# reveals #[[1]]#.", + /*german*/ "Man erzählt sich, daß ein #Schmetterling in der Nähe des Schlosses# #[[1]]# enthülle.", + /*french*/ "Selon moi, une #un papillon près du château# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_BUTTERFLY_FAIRY_LOST_WOODS] = HintText(CustomMessage("They say that a #butterfly in the woods# reveals #[[1]]#.", + /*german*/ "Man erzählt sich, daß ein #Schmetterling im Wald# #[[1]]# enthülle.", + /*french*/ "Selon moi, une #un papillon dans les bois# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_BUTTERFLY_FAIRY_GRAVEYARD] = HintText(CustomMessage("They say that a #butterfly in the graveyard# reveals #[[1]]#.", + /*german*/ "Man erzählt sich, daß ein #Schmetterling auf dem Friedhof# #[[1]]# enthülle.", + /*french*/ "Selon moi, une #un papillon dans le cimetière# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_BUTTERFLY_FAIRY_ZORAS_RIVER] = HintText(CustomMessage("They say that a #butterfly near a river# reveals #[[1]]#.", + /*german*/ "Man erzählt sich, daß ein #Schmetterling in der Nähe eines Flusses# #[[1]]# enthülle.", + /*french*/ "Selon moi, une #un papillon près d'une rivière# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_BUTTERFLY_FAIRY_ZORAS_FOUNTAIN] = HintText(CustomMessage("They say that a #butterfly on a log# reveals #[[1]]#.", + /*german*/ "Man erzählt sich, daß ein #Schmetterling auf einem Baumstamm# #[[1]]# enthülle.", + /*french*/ "Selon moi, une #un papillon sur une bûche# révèle #[[1]]#.", {QM_RED, QM_GREEN})); + + hintTextTable[RHT_BUTTERFLY_FAIRY_LAKE_HYLIA] = HintText(CustomMessage("They say that a #butterfly near a lake# reveals #[[1]]#.", + /*german*/ "Man erzählt sich, daß ein #Schmetterling in der Nähe eines Sees# #[[1]]# enthülle.", + /*french*/ "Selon moi, une #un papillon près d'un lac# révèle #[[1]]#.", {QM_RED, QM_GREEN})); // clang-format on } } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/SeedContext.cpp b/soh/soh/Enhancements/randomizer/SeedContext.cpp index 089bb5c0a..86eec9e2d 100644 --- a/soh/soh/Enhancements/randomizer/SeedContext.cpp +++ b/soh/soh/Enhancements/randomizer/SeedContext.cpp @@ -211,6 +211,7 @@ void Context::GenerateLocationPool() { (location.GetRCType() == RCTYPE_STONE_FAIRY && !mOptions[RSK_SHUFFLE_STONE_FAIRIES]) || (location.GetRCType() == RCTYPE_BEAN_FAIRY && !mOptions[RSK_SHUFFLE_BEAN_FAIRIES]) || (location.GetRCType() == RCTYPE_SONG_FAIRY && !mOptions[RSK_SHUFFLE_SONG_FAIRIES]) || + (location.GetRCType() == RCTYPE_BUTTERFLY_FAIRY && !mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES]) || (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))) || diff --git a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp index 730366949..e424d54bc 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp @@ -11,6 +11,7 @@ extern "C" { #include "src/overlays/actors/ovl_Obj_Bean/z_obj_bean.h" #include "src/overlays/actors/ovl_En_Gs/z_en_gs.h" #include "src/overlays/actors/ovl_Shot_Sun/z_shot_sun.h" +#include "src/overlays/actors/ovl_En_Butte/z_en_butte.h" } #define FAIRY_FLAG_TIMED (1 << 8) @@ -53,7 +54,7 @@ bool ShuffleFairies_FairyExists(CheckIdentity fairyIdentity) { return false; } -CheckIdentity ShuffleFairies_GetFairyIdentity(int32_t params) { +CheckIdentity ShuffleFairies_GetFairyIdentity(int32_t params, ActorID id) { CheckIdentity fairyIdentity; s16 sceneNum = gPlayState->sceneNum; fairyIdentity.randomizerInf = RAND_INF_MAX; @@ -62,8 +63,7 @@ CheckIdentity ShuffleFairies_GetFairyIdentity(int32_t params) { sceneNum = SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY; } - Rando::Location* location = - OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(ACTOR_EN_ELF, sceneNum, params); + Rando::Location* location = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(id, sceneNum, params); if (location->GetRandomizerCheck() == RC_UNKNOWN_CHECK) { LUSLOG_WARN("FairyGetIdentity did not receive a valid RC value (%d).", location->GetRandomizerCheck()); @@ -76,8 +76,8 @@ CheckIdentity ShuffleFairies_GetFairyIdentity(int32_t params) { return fairyIdentity; } -static bool SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params, FairyType fairyType) { - CheckIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params); +static bool SpawnFairy(f32 posX, f32 posY, f32 posZ, int32_t params, FairyType fairyType, ActorID id) { + CheckIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params, id); if (!Flags_GetRandomizerInf(fairyIdentity.randomizerInf)) { Actor* fairy = Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_ELF, posX, posY - 30.0f, posZ, 0, 0, 0, fairyType); @@ -93,7 +93,9 @@ void RegisterShuffleFairies() { bool shouldRegisterStone = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_STONE_FAIRIES); bool shouldRegisterBean = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_BEAN_FAIRIES); bool shouldRegisterSong = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_SONG_FAIRIES); - bool shouldRegister = shouldRegisterFountain || shouldRegisterStone || shouldRegisterBean || shouldRegisterSong; + bool shouldRegisterButterfly = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_BUTTERFLY_FAIRIES); + bool shouldRegister = shouldRegisterFountain || shouldRegisterStone || shouldRegisterBean || shouldRegisterSong || + shouldRegisterButterfly; // Grant item when picking up fairy. COND_VB_SHOULD(VB_FAIRY_HEAL, shouldRegister, { @@ -123,7 +125,8 @@ void RegisterShuffleFairies() { s16 grottoId = (gPlayState->sceneNum == SCENE_FAIRYS_FOUNTAIN) ? Grotto_CurrentGrotto() : 0; for (s16 index = 0; index < 8; index++) { int32_t params = (grottoId << 8) | index; - if (SpawnFairy(actor->world.pos.x, actor->world.pos.y, actor->world.pos.z, params, FAIRY_HEAL)) { + if (SpawnFairy(actor->world.pos.x, actor->world.pos.y, actor->world.pos.z, params, FAIRY_HEAL, + ACTOR_EN_ELF)) { fairySpawned = true; } } @@ -139,7 +142,7 @@ void RegisterShuffleFairies() { for (s16 index = 0; index < 3; index++) { int32_t params = ((objBean->dyna.actor.params & 0x3F) << 8) | index; if (SpawnFairy(objBean->dyna.actor.world.pos.x, objBean->dyna.actor.world.pos.y, - objBean->dyna.actor.world.pos.z, params, FAIRY_HEAL)) { + objBean->dyna.actor.world.pos.z, params, FAIRY_HEAL, ACTOR_EN_ELF)) { fairySpawned = true; } } @@ -152,7 +155,7 @@ void RegisterShuffleFairies() { COND_VB_SHOULD(VB_SPAWN_SONG_FAIRY, shouldRegisterSong, { ShotSun* shotSun = va_arg(args, ShotSun*); if (SpawnFairy(shotSun->actor.world.pos.x, shotSun->actor.world.pos.y, shotSun->actor.world.pos.z, - TWO_ACTOR_PARAMS(0x1000, (int32_t)shotSun->actor.world.pos.z), FAIRY_HEAL_BIG)) { + TWO_ACTOR_PARAMS(0x1000, (int32_t)shotSun->actor.world.pos.z), FAIRY_HEAL_BIG, ACTOR_EN_ELF)) { *should = false; } }); @@ -185,11 +188,11 @@ void RegisterShuffleFairies() { // stop spawning the vanilla fairy as well when these fairies exist, otherwise both // the randomized and the vanilla fairy will spawn. When the randomized fairy is already // collected, the vanilla code will handle that part automatically. - CheckIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params); + CheckIdentity fairyIdentity = ShuffleFairies_GetFairyIdentity(params, ACTOR_EN_ELF); if (!ShuffleFairies_FairyExists(fairyIdentity)) { Player* player = GET_PLAYER(gPlayState); if (SpawnFairy(player->actor.world.pos.x, (player->actor.world.pos.y + 20), player->actor.world.pos.z, - params, fairyType)) { + params, fairyType, ACTOR_EN_ELF)) { Audio_PlayActorSound2(&gossipStone->actor, NA_SE_EV_BUTTERFRY_TO_FAIRY); // Set vanilla check for fairy spawned so it doesn't spawn the vanilla fairy afterwards as well. gossipStone->unk_19D = 0; @@ -200,6 +203,18 @@ void RegisterShuffleFairies() { } } }); + + // Spawn a fairy from a butterfly + COND_VB_SHOULD(VB_SPAWN_BUTTERFLY_FAIRY, shouldRegisterButterfly, { + if (*should) { + EnButte* enButte = va_arg(args, EnButte*); + if (SpawnFairy(enButte->actor.focus.pos.x, enButte->actor.focus.pos.y, enButte->actor.focus.pos.z, + TWO_ACTOR_PARAMS(enButte->actor.params, (int32_t)enButte->actor.home.pos.y), FAIRY_HEAL, + ACTOR_EN_BUTTE)) { + *should = false; + } + } + }); } void Rando::StaticData::RegisterFairyLocations() { @@ -406,6 +421,17 @@ void Rando::StaticData::RegisterFairyLocations() { locationTable[RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY] = Location::SongFairy(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, 741), "Deku Scrub Grotto Sun's Song Fairy", RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY)); locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY] = Location::SongFairy(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_ROYAL_FAMILYS_TOMB, TWO_ACTOR_PARAMS(0x1000, 1476), "Royal Family's Tomb Sun's Song Fairy", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY)); + locationTable[RC_HC_NEAR_WALL_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_HC_NEAR_WALL_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1, 1476), "Near Wall Butterfly Fairy", RHT_BUTTERFLY_FAIRY_HYRULE_CASTLE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_WALL_BUTTERFLY_FAIRY)); + locationTable[RC_HC_NEAR_STAIRS_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_HC_NEAR_STAIRS_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1, 1493), "Near Stairs Butterfly Fairy", RHT_BUTTERFLY_FAIRY_HYRULE_CASTLE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_STAIRS_BUTTERFLY_FAIRY)); + locationTable[RC_HC_NEAR_BOULDER_PATH_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_HC_NEAR_BOULDER_PATH_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1, 1413), "Near Boulder Path Butterfly Fairy", RHT_BUTTERFLY_FAIRY_HYRULE_CASTLE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_BOULDER_PATH_BUTTERFLY_FAIRY)); + locationTable[RC_HC_NEAR_ARCHWAY_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_HC_NEAR_ARCHWAY_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_HYRULE_CASTLE, TWO_ACTOR_PARAMS(1, 1478), "Near Archway Butterfly Fairy", RHT_BUTTERFLY_FAIRY_HYRULE_CASTLE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_NEAR_ARCHWAY_BUTTERFLY_FAIRY)); + locationTable[RC_LW_MEADOW_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_LW_MEADOW_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS(1, 28), "Meadow Butterfly Fairy", RHT_BUTTERFLY_FAIRY_LOST_WOODS, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_MEADOW_BUTTERFLY_FAIRY)); + locationTable[RC_GY_NEAR_HUT_GRAVE_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_GY_NEAR_HUT_GRAVE_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_GRAVEYARD, TWO_ACTOR_PARAMS(1, 137), "Grave Butterfly Fairy", RHT_BUTTERFLY_FAIRY_GRAVEYARD, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_NEAR_HUT_GRAVE_BUTTERFLY_FAIRY)); + locationTable[RC_ZR_NEAR_ROCK_CIRCLE_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_ZR_NEAR_ROCK_CIRCLE_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(1, 164), "Near Rock Circle Butterfly Fairy", RHT_BUTTERFLY_FAIRY_ZORAS_RIVER, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_NEAR_ROCK_CIRCLE_BUTTERFLY_FAIRY)); + locationTable[RC_ZR_WATERFALL_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_ZR_WATERFALL_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_RIVER, SCENE_ZORAS_RIVER, TWO_ACTOR_PARAMS(1, 1010), "Waterfall Butterfly Fairy", RHT_BUTTERFLY_FAIRY_ZORAS_RIVER, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZR_WATERFALL_BUTTERFLY_FAIRY)); + locationTable[RC_ZF_LOG_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_ZF_LOG_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(1, 169), "Log Butterfly Fairy", RHT_BUTTERFLY_FAIRY_ZORAS_FOUNTAIN, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_LOG_BUTTERFLY_FAIRY)); + locationTable[RC_LH_SCARECROW_BUTTERFLY_FAIRY] = Location::ButterflyFairy(RC_LH_SCARECROW_BUTTERFLY_FAIRY, RCQUEST_BOTH, RCAREA_LAKE_HYLIA, SCENE_LAKE_HYLIA, TWO_ACTOR_PARAMS(1, -1254), "Scarecrow Butterfly Fairy", RHT_BUTTERFLY_FAIRY_LAKE_HYLIA, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LH_SCARECROW_BUTTERFLY_FAIRY)); + locationTable[RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY] = Location::SongFairy(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1896), "After Boulder Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY)); locationTable[RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY] = Location::SongFairy(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -220), "Four Armos Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY)); locationTable[RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY] = Location::SongFairy(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, RCQUEST_VANILLA,RCAREA_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(0x1000, 54), "Beamos Song of Storms Fairy", RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY)); diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index e129a6b26..e17cecac3 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -630,6 +630,15 @@ Rando::Location Rando::Location::SongFairy(RandomizerCheck rc, RandomizerCheckQu false, collectionCheck }; } +Rando::Location Rando::Location::ButterflyFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, + RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, + std::string&& shortName_, RandomizerHintTextKey hintKey, + SpoilerCollectionCheck collectionCheck) { + return { rc, quest_, RCTYPE_BUTTERFLY_FAIRY, area_, ACTOR_EN_BUTTE, + scene_, actorParams_, std::move(shortName_), hintKey, RG_NONE, + false, collectionCheck }; +} + Rando::Location Rando::Location::Grass(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, SceneID scene_, int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, diff --git a/soh/soh/Enhancements/randomizer/location.h b/soh/soh/Enhancements/randomizer/location.h index 24b192cc3..618c00f32 100644 --- a/soh/soh/Enhancements/randomizer/location.h +++ b/soh/soh/Enhancements/randomizer/location.h @@ -282,6 +282,10 @@ class Location { SceneID scene_, int32_t actorParams_, std::string&& shortName_, RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck); + static Location ButterflyFairy(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckArea area_, + SceneID scene_, int32_t actorParams_, std::string&& shortName_, + RandomizerHintTextKey hintKey, SpoilerCollectionCheck collectionCheck); + static Location HintStone(RandomizerCheck rc, RandomizerCheckQuest quest_, SceneID scene_, int32_t actorParams_, std::string&& shortName_); 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 40ba46fcf..c5354ba81 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -56,14 +56,18 @@ void RegionTable_Init_CastleGrounds() { EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->CanUse(RG_STICKS)), }, { //Locations - 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()), - LOCATION(RC_HC_NL_TREE_1, false), - LOCATION(RC_HC_NL_TREE_2, false), + 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()), + LOCATION(RC_HC_NL_TREE_1, false), + LOCATION(RC_HC_NL_TREE_2, false), + LOCATION(RC_HC_NEAR_WALL_BUTTERFLY_FAIRY, logic->CanUse(RG_STICKS)), + LOCATION(RC_HC_NEAR_STAIRS_BUTTERFLY_FAIRY, logic->CanUse(RG_STICKS)), + LOCATION(RC_HC_NEAR_BOULDER_PATH_BUTTERFLY_FAIRY, logic->CanUse(RG_STICKS)), + LOCATION(RC_HC_NEAR_ARCHWAY_BUTTERFLY_FAIRY, logic->CanUse(RG_STICKS)), }, { //Exits ENTRANCE(RR_HC_GATE, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index 77ac0aa44..b34ab2132 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -32,6 +32,7 @@ void RegionTable_Init_Graveyard() { LOCATION(RC_GY_GRASS_11, logic->CanCutShrubs()), LOCATION(RC_GY_GRASS_12, logic->CanCutShrubs()), LOCATION(RC_GRAVEYARD_CRATE, ((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD, RG_GRAVEYARD_BEAN_SOUL)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()), + LOCATION(RC_GY_NEAR_HUT_GRAVE_BUTTERFLY_FAIRY, logic->IsChild && logic->AtDay && logic->CanUse(RG_STICKS)), }, { //Exits ENTRANCE(RR_GRAVEYARD_SHIELD_GRAVE, (logic->IsAdult || logic->AtNight) && logic->HasItem(RG_POWER_BRACELET)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp index cdd106050..7aefb5440 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp @@ -79,6 +79,7 @@ void RegionTable_Init_LakeHylia() { LOCATION(RC_LH_CHILD_GRASS_4, logic->IsChild && logic->CanCutShrubs()), LOCATION(RC_LH_WARP_PAD_GRASS_1, logic->CanCutShrubs()), LOCATION(RC_LH_WARP_PAD_GRASS_2, logic->CanCutShrubs()), + LOCATION(RC_LH_SCARECROW_BUTTERFLY_FAIRY, logic->IsChild && logic->CanUse(RG_STICKS)), }, { //Exits ENTRANCE(RR_HF_TO_LAKE_HYLIA, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index 6df779cf6..e9ccde9ed 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -93,6 +93,7 @@ void RegionTable_Init_LostWoods() { LOCATION(RC_LW_GRASS_7, logic->CanCutShrubs()), LOCATION(RC_LW_GRASS_8, logic->CanCutShrubs()), LOCATION(RC_LW_GRASS_9, logic->CanCutShrubs()), + LOCATION(RC_LW_MEADOW_BUTTERFLY_FAIRY, logic->IsChild && logic->CanUse(RG_STICKS)), }, { //Exits ENTRANCE(RR_LW_FOREST_EXIT, 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 4d861b431..3b68da385 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -29,6 +29,7 @@ void RegionTable_Init_ZorasFountain() { LOCATION(RC_ZF_BUSH_4, logic->IsChild), LOCATION(RC_ZF_BUSH_5, logic->IsChild), LOCATION(RC_ZF_BUSH_6, logic->IsChild), + LOCATION(RC_ZF_LOG_BUTTERFLY_FAIRY, logic->IsChild && logic->AtDay && logic->CanUse(RG_STICKS)), }, { //Exits ENTRANCE(RR_ZD_BEHIND_KING_ZORA, 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 6eea34727..9ee33c325 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -56,6 +56,8 @@ void RegionTable_Init_ZoraRiver() { LOCATION(RC_ZR_BENEATH_WATERFALL_RIGHT_RUPEE, logic->IsAdult && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_BOOMERANG))), LOCATION(RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, true), LOCATION(RC_ZR_NEAR_FREESTANDING_POH_GRASS, logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_ZR_NEAR_ROCK_CIRCLE_BUTTERFLY_FAIRY, logic->IsChild && logic->CanUse(RG_STICKS)), + LOCATION(RC_ZR_WATERFALL_BUTTERFLY_FAIRY, logic->IsChild && logic->CanUse(RG_STICKS)), }, { //Exits ENTRANCE(RR_ZR_FRONT, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_POWER_BRACELET) || logic->BlastOrSmash() || logic->HasItem(RG_HOVER_BOOTS)), diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 049ea8d3e..6fc8dda5e 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -507,6 +507,7 @@ void Settings::CreateOptionDescriptions() { "Shuffle fairy spots. These are spots where a big fairy is revealed by a song." "\n" "This excludes gossip stones and magic bean locations."; + mOptionDescriptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES] = "Shuffle fairies from butterfly locations."; mOptionDescriptions[RSK_SHUFFLE_GRASS] = "Grass will drop a randomized item the first time they're cut and collected. " "Grass will have a different appearance when they hold a randomized item.\n" diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h index c13d37f1b..a525f39c2 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h @@ -2191,6 +2191,16 @@ RANDO_ENUM_ITEM(RC_LW_SHORTCUT_STORMS_FAIRY) RANDO_ENUM_ITEM(RC_TH_KITCHEN_SUN_FAIRY) RANDO_ENUM_ITEM(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY) RANDO_ENUM_ITEM(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY) +RANDO_ENUM_ITEM(RC_HC_NEAR_WALL_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_HC_NEAR_STAIRS_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_HC_NEAR_BOULDER_PATH_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_HC_NEAR_ARCHWAY_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_LW_MEADOW_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_GY_NEAR_HUT_GRAVE_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_ZR_NEAR_ROCK_CIRCLE_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_ZR_WATERFALL_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_ZF_LOG_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RC_LH_SCARECROW_BUTTERFLY_FAIRY) RANDO_ENUM_ITEM(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY) RANDO_ENUM_ITEM(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY) RANDO_ENUM_ITEM(RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h index a57f76355..16ae03a7f 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h @@ -1515,6 +1515,12 @@ RANDO_ENUM_ITEM(RHT_LW_SHORTCUT_STORMS_FAIRY) RANDO_ENUM_ITEM(RHT_TH_KITCHEN_SUN_FAIRY) RANDO_ENUM_ITEM(RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY) RANDO_ENUM_ITEM(RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY) +RANDO_ENUM_ITEM(RHT_BUTTERFLY_FAIRY_HYRULE_CASTLE) +RANDO_ENUM_ITEM(RHT_BUTTERFLY_FAIRY_LOST_WOODS) +RANDO_ENUM_ITEM(RHT_BUTTERFLY_FAIRY_GRAVEYARD) +RANDO_ENUM_ITEM(RHT_BUTTERFLY_FAIRY_ZORAS_RIVER) +RANDO_ENUM_ITEM(RHT_BUTTERFLY_FAIRY_ZORAS_FOUNTAIN) +RANDO_ENUM_ITEM(RHT_BUTTERFLY_FAIRY_LAKE_HYLIA) RANDO_ENUM_ITEM(RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY) RANDO_ENUM_ITEM(RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY) RANDO_ENUM_ITEM(RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h index d679bb223..f19137a46 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h @@ -1680,6 +1680,18 @@ RANDO_ENUM_ITEM(RAND_INF_LW_SHORTCUT_STORMS_FAIRY) RANDO_ENUM_ITEM(RAND_INF_TH_KITCHEN_SUN_FAIRY) RANDO_ENUM_ITEM(RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY) RANDO_ENUM_ITEM(RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY) + +RANDO_ENUM_ITEM(RAND_INF_HC_NEAR_WALL_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_HC_NEAR_STAIRS_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_HC_NEAR_BOULDER_PATH_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_HC_NEAR_ARCHWAY_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_LW_MEADOW_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_GY_NEAR_HUT_GRAVE_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_ZR_NEAR_ROCK_CIRCLE_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_ZR_WATERFALL_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_ZF_LOG_BUTTERFLY_FAIRY) +RANDO_ENUM_ITEM(RAND_INF_LH_SCARECROW_BUTTERFLY_FAIRY) + RANDO_ENUM_ITEM(RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY) RANDO_ENUM_ITEM(RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY) RANDO_ENUM_ITEM(RAND_INF_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h index 78b032c38..eee5b23ee 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h @@ -128,6 +128,7 @@ RANDO_ENUM_ITEM(RCTYPE_FOUNTAIN_FAIRY) // Fairies in Fountains RANDO_ENUM_ITEM(RCTYPE_STONE_FAIRY) // Fairies from Gossip Stones RANDO_ENUM_ITEM(RCTYPE_BEAN_FAIRY) // Fairies from Beans RANDO_ENUM_ITEM(RCTYPE_SONG_FAIRY) // Fairies from Songs +RANDO_ENUM_ITEM(RCTYPE_BUTTERFLY_FAIRY) // Fairies from Butterflies RANDO_ENUM_ITEM(RCTYPE_GRASS) // Grass RANDO_ENUM_END(RandomizerCheckType) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h index 40ebb218d..285c7d408 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h @@ -241,6 +241,7 @@ RANDO_ENUM_ITEM(RSK_SHUFFLE_FOUNTAIN_FAIRIES) RANDO_ENUM_ITEM(RSK_SHUFFLE_STONE_FAIRIES) RANDO_ENUM_ITEM(RSK_SHUFFLE_BEAN_FAIRIES) RANDO_ENUM_ITEM(RSK_SHUFFLE_SONG_FAIRIES) +RANDO_ENUM_ITEM(RSK_SHUFFLE_BUTTERFLY_FAIRIES) RANDO_ENUM_ITEM(RSK_LOCK_OVERWORLD_DOORS) RANDO_ENUM_ITEM(RSK_SHUFFLE_GRASS) RANDO_ENUM_ITEM(RSK_ROCS_FEATHER) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index 35aad1f38..9e097508b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -219,6 +219,8 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeanFairies"), RO_GENERIC_NO)) && (location.GetRCType() != RCTYPE_SONG_FAIRY || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFairySpots"), RO_GENERIC_NO)) && + (location.GetRCType() != RCTYPE_BUTTERFLY_FAIRY || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleButterflyFairies"), RO_GENERIC_NO)) && ((location.GetRCType() != RCTYPE_MAP && location.GetRCType() != RCTYPE_COMPASS) || CVarGetInteger(CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) != RO_DUNGEON_ITEM_LOC_VANILLA) && diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 5c681d307..56a97d705 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -84,6 +84,7 @@ bool showFountainFairies; bool showStoneFairies; bool showBeanFairies; bool showSongFairies; +bool showButterflyFairies; bool showStartingMapsCompasses; bool showKeysanity; bool showGerudoFortressKeys; @@ -1361,6 +1362,10 @@ void LoadSettings() { showSongFairies = IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SONG_FAIRIES) == RO_GENERIC_YES : false; + showButterflyFairies = + IS_RANDO + ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_BUTTERFLY_FAIRIES) == RO_GENERIC_YES + : false; showStartingMapsCompasses = IS_RANDO ? OTRGlobals::Instance->gRandomizer->GetRandoSettingValue( RSK_SHUFFLE_MAPANDCOMPASS) != RO_DUNGEON_ITEM_LOC_VANILLA : false; @@ -1611,6 +1616,7 @@ bool IsCheckShuffled(RandomizerCheck rc) { (loc->GetRCType() != RCTYPE_STONE_FAIRY || showStoneFairies) && (loc->GetRCType() != RCTYPE_BEAN_FAIRY || showBeanFairies) && (loc->GetRCType() != RCTYPE_SONG_FAIRY || showSongFairies) && + (loc->GetRCType() != RCTYPE_BUTTERFLY_FAIRY || showButterflyFairies) && (loc->GetRCType() != RCTYPE_SMALL_KEY || showKeysanity) && (loc->GetRCType() != RCTYPE_BOSS_KEY || showBossKeysanity) && (loc->GetRCType() != RCTYPE_GANON_BOSS_KEY || showGanonBossKey) && diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index b9b0a1f0d..b28ab6956 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1070,6 +1070,7 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_SHUFFLE_STONE_FAIRIES, "Shuffle Gossip Stone Fairies", CVAR_RANDOMIZER_SETTING("ShuffleStoneFairies"), mOptionDescriptions[RSK_SHUFFLE_STONE_FAIRIES]); OPT_BOOL(RSK_SHUFFLE_BEAN_FAIRIES, "Shuffle Bean Fairies", CVAR_RANDOMIZER_SETTING("ShuffleBeanFairies"), mOptionDescriptions[RSK_SHUFFLE_BEAN_FAIRIES]); OPT_BOOL(RSK_SHUFFLE_SONG_FAIRIES, "Shuffle Fairy Spots", CVAR_RANDOMIZER_SETTING("ShuffleFairySpots"), mOptionDescriptions[RSK_SHUFFLE_SONG_FAIRIES]); + OPT_BOOL(RSK_SHUFFLE_BUTTERFLY_FAIRIES, "Shuffle Butterfly Fairies", CVAR_RANDOMIZER_SETTING("ShuffleButterflyFairies"), mOptionDescriptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES]); OPT_U8(RSK_SHUFFLE_MAPANDCOMPASS, "Maps/Compasses", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingMapsCompasses"), mOptionDescriptions[RSK_SHUFFLE_MAPANDCOMPASS], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); OPT_U8(RSK_KEYSANITY, "Small Key Shuffle", {"Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Keysanity"), mOptionDescriptions[RSK_KEYSANITY], WIDGET_CVAR_COMBOBOX, RO_DUNGEON_ITEM_LOC_OWN_DUNGEON); OPT_U8(RSK_GERUDO_KEYS, "Gerudo Fortress Keys", {"Vanilla", "Any Dungeon", "Overworld", "Anywhere"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GerudoKeys"), mOptionDescriptions[RSK_GERUDO_KEYS], WIDGET_CVAR_COMBOBOX, RO_GERUDO_KEYS_VANILLA); @@ -1867,6 +1868,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_STONE_FAIRIES], &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], &mOptions[RSK_SHUFFLE_SONG_FAIRIES], + &mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES], }, WidgetContainerType::SECTION); mOptionGroups[RSG_MENU_COLUMN_BASIC_SHUFFLES] = @@ -2176,6 +2178,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_STONE_FAIRIES], &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], &mOptions[RSK_SHUFFLE_SONG_FAIRIES], + &mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES], }); mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS] = OptionGroup("Shuffle Dungeon Items", { diff --git a/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c b/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c index 4421865d2..f7a171bd0 100644 --- a/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c +++ b/soh/src/overlays/actors/ovl_En_Butte/z_en_butte.c @@ -9,6 +9,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -363,7 +364,7 @@ void EnButte_TransformIntoFairy(EnButte* this, PlayState* play) { if (this->timer == 5) { SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 60, NA_SE_EV_BUTTERFRY_TO_FAIRY); - } else if (this->timer == 4) { + } else if (GameInteractor_Should(VB_SPAWN_BUTTERFLY_FAIRY, this->timer == 4, this)) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_ELF, this->actor.focus.pos.x, this->actor.focus.pos.y, this->actor.focus.pos.z, 0, this->actor.shape.rot.y, 0, FAIRY_HEAL_TIMED); this->drawSkelAnime = false;