more perm flags (#5676)

1. deku tree MQ web
2. dodongo's cavern MQ silver rupees
3. jabu lobby switch
4. forest well, lobby eyes, MQ web
5. fire MQ lobby torches
6. spirit MQ lobby silver rupees

adjusts forest MQ logic
This commit is contained in:
Philip Dubé
2025-12-30 22:31:38 +00:00
committed by GitHub
parent 82b279f55e
commit cd08f343a6
4 changed files with 141 additions and 31 deletions

View File

@@ -263,16 +263,58 @@ void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) {
}
void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t flag) {
if (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF &&
sceneNum == SCENE_GERUDOS_FORTRESS && flagType == FLAG_SCENE_SWITCH && flag == 0x3A) {
Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN);
}
if (flagType == FLAG_SCENE_SWITCH) {
auto dungeonInfo = Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(sceneNum);
bool isVanilla = dungeonInfo == nullptr || dungeonInfo->IsVanilla();
if (sceneNum == SCENE_SPIRIT_TEMPLE && flagType == FLAG_SCENE_SWITCH) {
bool isVanilla =
Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla();
if (isVanilla && flag == 0x23) {
Flags_SetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON);
switch (sceneNum) {
case SCENE_GERUDOS_FORTRESS:
if (RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && flag == 0x3A) {
Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN);
}
break;
case SCENE_DEKU_TREE:
if (!isVanilla && flag == 0x27) {
Flags_SetRandomizerInf(RAND_INF_DEKU_TREE_MQ_TORCH_SWITCH);
}
break;
case SCENE_DODONGOS_CAVERN:
if (!isVanilla && flag == 0x25) {
Flags_SetRandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEES);
}
break;
case SCENE_JABU_JABU:
if (isVanilla && flag == 0x3b) {
Flags_SetRandomizerInf(RAND_INF_JABU_JABUS_BELLY_FIRST_SWITCH);
}
break;
case SCENE_FOREST_TEMPLE:
if (flag == 0x26) {
Flags_SetRandomizerInf(RAND_INF_FOREST_DRAINED_WELL);
} else if (flag == 0x25) {
Flags_SetRandomizerInf(RAND_INF_FOREST_LOBBY_EYES);
if (!isVanilla) {
Flags_SetSwitch(gPlayState, 0x2a);
}
} else if (!isVanilla && flag == 0x2a) {
Flags_SetRandomizerInf(RAND_INF_FOREST_LOBBY_EYES);
Flags_SetSwitch(gPlayState, 0x25);
} else if (!isVanilla && flag == 0x21) {
Flags_SetRandomizerInf(RAND_INF_FOREST_MQ_COURTYARD_WEB_BURNT);
}
break;
case SCENE_FIRE_TEMPLE:
if (!isVanilla && flag == 0x28) {
Flags_SetRandomizerInf(RAND_INF_FIRE_MQ_LOBBY_TORCHES);
}
break;
case SCENE_SPIRIT_TEMPLE:
if (isVanilla && flag == 0x23) {
Flags_SetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON);
} else if (!isVanilla && flag == 0x37) {
Flags_SetRandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEES);
}
break;
}
}
@@ -1931,12 +1973,51 @@ void RandomizerOnActorInitHandler(void* actorRef) {
Actor* actor = static_cast<Actor*>(actorRef);
if (actor->id == ACTOR_PLAYER) {
if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE) {
bool isVanilla =
Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla();
if (isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)) {
Flags_SetSwitch(gPlayState, 0x23);
}
auto dungeonInfo = Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(gPlayState->sceneNum);
bool isVanilla = dungeonInfo == nullptr || dungeonInfo->IsVanilla();
switch (gPlayState->sceneNum) {
case SCENE_DEKU_TREE:
if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_DEKU_TREE_MQ_TORCH_SWITCH)) {
Flags_SetSwitch(gPlayState, 0x27);
}
break;
case SCENE_DODONGOS_CAVERN:
if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEES)) {
Flags_SetSwitch(gPlayState, 0x25);
}
break;
case SCENE_JABU_JABU:
if (isVanilla && Flags_GetRandomizerInf(RAND_INF_JABU_JABUS_BELLY_FIRST_SWITCH)) {
Flags_SetSwitch(gPlayState, 0x3b);
}
break;
case SCENE_FOREST_TEMPLE:
if (Flags_GetRandomizerInf(RAND_INF_FOREST_DRAINED_WELL)) {
Flags_SetSwitch(gPlayState, 0x26);
}
if (Flags_GetRandomizerInf(RAND_INF_FOREST_LOBBY_EYES)) {
Flags_SetSwitch(gPlayState, 0x25);
if (!isVanilla) {
Flags_SetSwitch(gPlayState, 0x2a);
}
}
if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_FOREST_MQ_COURTYARD_WEB_BURNT)) {
Flags_SetSwitch(gPlayState, 0x21);
}
break;
case SCENE_FIRE_TEMPLE:
if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_FIRE_MQ_LOBBY_TORCHES)) {
Flags_SetSwitch(gPlayState, 0x28);
}
break;
case SCENE_SPIRIT_TEMPLE:
if (isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)) {
Flags_SetSwitch(gPlayState, 0x23);
}
if (!isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEES)) {
Flags_SetSwitch(gPlayState, 0x37);
}
break;
}
}

View File

@@ -99,6 +99,7 @@ void RegionTable_Init_ForestTemple() {
Entrance(RR_FOREST_TEMPLE_NW_COURTYARD_UPPER, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}),
Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}),
Entrance(RR_FOREST_TEMPLE_SEWER, []{return logic->HasItem(RG_GOLDEN_SCALE) || logic->CanUse(RG_IRON_BOOTS);}),
Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}),
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return false;}),
});
@@ -132,6 +133,7 @@ void RegionTable_Init_ForestTemple() {
Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_UPPER, []{return logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_VINES) && logic->CanUse(RG_HOOKSHOT));}),
Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, []{return logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_FOREST_TEMPLE_SEWER, []{return (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}),
Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL);}),
});
areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_UPPER] = Region("Forest Temple NE Courtyard Upper", SCENE_FOREST_TEMPLE, {
@@ -139,12 +141,12 @@ void RegionTable_Init_ForestTemple() {
EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}),
EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}),
EventAccess(LOGIC_FOREST_SUMMON_NE_SCARECROW, []{return ctx->GetTrickOption(RT_FOREST_DOORFRAME) && logic->CanJumpslash() && logic->CanUse(RG_HOVER_BOOTS) && logic->ScarecrowsSong();}),
EventAccess(LOGIC_FOREST_DRAINED_WELL, []{return true;}),
}, {}, {
//Exits
Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_LOWER, []{return true;}),
Entrance(RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND, []{return logic->IsAdult && ctx->GetTrickOption(RT_FOREST_COURTYARD_LEDGE) && logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_FOREST_TEMPLE_MAP_ROOM, []{return true;}),
Entrance(RR_FOREST_TEMPLE_DRAINED_SEWER, []{return true;}),
});
areaTable[RR_FOREST_TEMPLE_NE_COURTYARD_ISLAND] = Region("Forest Temple NE Courtyard Island", SCENE_FOREST_TEMPLE, {
@@ -540,7 +542,10 @@ void RegionTable_Init_ForestTemple() {
Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return Here(RR_FOREST_TEMPLE_MQ_REDEAD_ROOM, []{return logic->CanKillEnemy(RE_REDEAD);});}),
});
areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD] = Region("Forest Temple MQ NW Courtyard", SCENE_FOREST_TEMPLE, {}, {
areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD] = Region("Forest Temple MQ NW Courtyard", SCENE_FOREST_TEMPLE, {
//Events
EventAccess(LOGIC_FOREST_MQ_BURNED_WEB, []{return logic->CanUse(RG_FIRE_ARROWS);}),
}, {
//Locations
LOCATION(RC_FOREST_TEMPLE_MQ_GS_LEVEL_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
//the well checks are considered from both areas instead of being a region because the draining is a temp flag and the skull (as well as the chest with hook glitch) has different breath timers from each side
@@ -553,30 +558,43 @@ void RegionTable_Init_ForestTemple() {
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8),
}, {
//Exits
Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, []{return (((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16;}),
Entrance(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, []{return logic->CanUse(RG_FIRE_ARROWS);}), // temp flag, can't be event
Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}),
Entrance(RR_FOREST_TEMPLE_MQ_NE_COURTYARD, []{return logic->Get(LOGIC_FOREST_DRAINED_WELL) || ((((logic->CanUse(RG_IRON_BOOTS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_FOREST_WELL_SWIM) && logic->CanUse(RG_HOOKSHOT))) && logic->HasItem(RG_BRONZE_SCALE)) || logic->HasItem(RG_GOLDEN_SCALE)) && logic->WaterTimer() >= 16);}),
Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, []{return logic->Get(LOGIC_FOREST_MQ_BURNED_WEB) && (logic->CanKillEnemy(RE_BIG_SKULLTULA, ED_LONGSHOT) || logic->CanUse(RG_BOMBCHU_5));}),
Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) && ((ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->HasExplosives()) || (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->IsAdult && logic->CanGroundJump()));}),
});
areaTable[RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE] = Region("Forest Temple MQ North Passage", SCENE_FOREST_TEMPLE, {}, {}, {
Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return logic->HasFireSourceWithTorch();}),
Entrance(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, []{return true;}),
areaTable[RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE] = Region("Forest Temple MQ NW Courtyard Upper Alcove", SCENE_FOREST_TEMPLE, {
//Events
EventAccess(LOGIC_FOREST_MQ_BURNED_WEB, []{return logic->HasFireSource();}),
}, {}, {
//Exits
Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD, []{return logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage();}),
Entrance(RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE, []{return true;}),
});
areaTable[RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE] = Region("Forest Temple MQ North Passage", SCENE_FOREST_TEMPLE, {
//Events
EventAccess(LOGIC_FOREST_MQ_BURNED_WEB, []{return logic->HasFireSourceWithTorch();}),
}, {}, {
//Exits
Entrance(RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE, []{return logic->Get(LOGIC_FOREST_MQ_BURNED_WEB);}),
Entrance(RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES, []{return true;}),
});
//The well only considers the eye target here because the eye target is a temp flag, making it unwieldy to use as an EventAccess to make it it's own room
areaTable[RR_FOREST_TEMPLE_MQ_NE_COURTYARD] = Region("Forest Temple MQ NE Courtyard", SCENE_FOREST_TEMPLE, {
//Events
EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}),
EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}),
EventAccess(LOGIC_STICK_ACCESS, []{return logic->CanGetDekuBabaSticks();}),
EventAccess(LOGIC_NUT_ACCESS, []{return logic->CanGetDekuBabaNuts();}),
EventAccess(LOGIC_FOREST_DRAINED_WELL, []{return logic->CanHitEyeTargets();}),
}, {
//Locations
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->CanHitEyeTargets() || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)),
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_CHEST, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanOpenUnderwaterChest() && logic->WaterTimer() >= 8)),
LOCATION(RC_FOREST_TEMPLE_MQ_GS_RAISED_ISLAND_COURTYARD, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
//implies logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)
LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->CanHitEyeTargets() || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))),
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_WEST_HEART, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanHitEyeTargets()),
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_MIDDLE_HEART, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanHitEyeTargets()),
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8) || logic->CanHitEyeTargets()),
LOCATION(RC_FOREST_TEMPLE_MQ_GS_WELL, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))),
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_WEST_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)),
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_MIDDLE_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)),
LOCATION(RC_FOREST_TEMPLE_MQ_WELL_EAST_HEART, logic->Get(LOGIC_FOREST_DRAINED_WELL) || (logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 8)),
}, {
//Exits
Entrance(RR_FOREST_TEMPLE_MQ_LOBBY, []{return true;}),

View File

@@ -269,8 +269,10 @@ typedef enum {
LOGIC_JABU_LOWERED_PATH,
LOGIC_JABU_MQ_HOLES_ROOM_DOOR,
LOGIC_JABU_MQ_LIFT_ROOM_COW,
LOGIC_FOREST_DRAINED_WELL,
LOGIC_FOREST_SUMMON_NE_SCARECROW,
LOGIC_FOREST_MQ_BLOCK_ROOM_TARGETS,
LOGIC_FOREST_MQ_BURNED_WEB,
LOGIC_FOREST_CAN_TWIST_HALLWAY,
LOGIC_FOREST_CLEAR_BETWEEN_JOELLE_AND_BETH,
LOGIC_FOREST_OPEN_BOSS_HALLWAY,
@@ -870,6 +872,7 @@ typedef enum {
RR_FOREST_TEMPLE_MQ_NW_COURTYARD_LEDGE,
RR_FOREST_TEMPLE_MQ_REDEAD_ROOM,
RR_FOREST_TEMPLE_MQ_NW_COURTYARD,
RR_FOREST_TEMPLE_MQ_NW_COURTYARD_UPPER_ALCOVE,
RR_FOREST_TEMPLE_MQ_NORTH_PASSAGE,
RR_FOREST_TEMPLE_MQ_NE_COURTYARD,
RR_FOREST_TEMPLE_MQ_COURTYARD_TOP_LEDGES,

View File

@@ -1218,8 +1218,16 @@ DEFINE_RAND_INF(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5)
DEFINE_RAND_INF(RAND_INF_TH_ITEM_FROM_LEADER_OF_FORTRESS)
DEFINE_RAND_INF(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN)
DEFINE_RAND_INF(RAND_INF_DEKU_TREE_MQ_TORCH_SWITCH)
DEFINE_RAND_INF(RAND_INF_DODONGOS_CAVERN_MQ_SILVER_RUPEES)
DEFINE_RAND_INF(RAND_INF_JABU_JABUS_BELLY_FIRST_SWITCH)
DEFINE_RAND_INF(RAND_INF_FOREST_LOBBY_EYES)
DEFINE_RAND_INF(RAND_INF_FOREST_DRAINED_WELL)
DEFINE_RAND_INF(RAND_INF_FOREST_MQ_COURTYARD_WEB_BURNT)
DEFINE_RAND_INF(RAND_INF_FIRE_MQ_LOBBY_TORCHES)
DEFINE_RAND_INF(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)
DEFINE_RAND_INF(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED)
DEFINE_RAND_INF(RAND_INF_SPIRIT_MQ_LOBBY_SILVER_RUPEES)
DEFINE_RAND_INF(RAND_INF_ZELDAS_LETTER)
DEFINE_RAND_INF(RAND_INF_WEIRD_EGG)