fix up logic, split out sage/zelda block as a separate option

This commit is contained in:
Demur Rumed 2025-01-29 02:54:59 +00:00
parent 16c776a98e
commit 8294bc5839
18 changed files with 132 additions and 105 deletions

View File

@ -1095,7 +1095,7 @@ void GenerateItemPool() {
}
if (ctx->GetOption(RSK_SHUFFLE_NPC_SOULS)) {
for (int rg = RG_ANJU_SOUL; rg <= RG_KAEPORA_SOUL; rg++) {
for (int rg = RG_ANJU_SOUL; rg <= RG_ZELDA_SOUL; rg++) {
AddItemToMainPool((RandomizerGet)rg);
}
}

View File

@ -826,15 +826,12 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
// This behavior is replicated for randomizer in RandomizerOnItemReceiveHandler
*should = false;
break;
case VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER: {
*should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL) && !Flags_GetTreasure(gPlayState, 0x2);
break;
}
case VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER:
*should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER) && Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL) && Flags_GetTreasure(gPlayState, 0x2);
break;
case VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT:
*should = !Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL);
case VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER:
case VB_BE_ELIGIBLE_FOR_SERENADE_OF_WATER:
if (RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) && !Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL)) {
*should = false;
}
break;
case VB_MIDO_SPAWN:
if (RAND_GET_OPTION(RSK_FOREST) != RO_CLOSED_FOREST_OFF && !Flags_GetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD)) {
@ -856,7 +853,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
*should = !Flags_GetRandomizerInf(RAND_INF_DARUNIAS_JOY);
break;
case VB_BE_ELIGIBLE_FOR_OCARINA_OF_TIME:
if (!Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL) || !Flags_GetRandomizerInf(RAND_INF_IMPA_SOUL)) {
if (RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) && (!Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL) || !Flags_GetRandomizerInf(RAND_INF_IMPA_SOUL))) {
*should = false;
}
break;
@ -865,7 +862,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
LINK_IS_ADULT &&
(gEntranceTable[gSaveContext.entranceIndex].scene == SCENE_TEMPLE_OF_TIME) &&
!Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) &&
Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL) &&
(RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) != RO_NPC_SOULS_ON_PLUS_SAGES || Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL)) &&
MeetsLACSRequirements();
break;
case VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW:
@ -876,7 +873,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) &&
Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL);
(!RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) || Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL));
break;
case VB_BE_ELIGIBLE_FOR_CHILD_ROLLING_GORON_REWARD: {
// Don't require a bomb bag to get prize in rando
@ -1449,15 +1446,17 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
break;
}
case VB_PLAY_BLUE_WARP_CS: {
if (RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS)) {
if (RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) == RO_NPC_SOULS_ON_PLUS_SAGES) {
bool hasSoul = true;
switch (gPlayState->sceneNum) {
case SCENE_FOREST_TEMPLE_BOSS:
hasSoul = Flags_GetRandomizerInf(RAND_INF_SARIA_SOUL);
break;
case SCENE_DODONGOS_CAVERN_BOSS:
case SCENE_FIRE_TEMPLE_BOSS:
hasSoul = Flags_GetRandomizerInf(RAND_INF_DARUNIA_SOUL);
break;
case SCENE_JABU_JABU_BOSS:
case SCENE_WATER_TEMPLE_BOSS:
hasSoul = Flags_GetRandomizerInf(RAND_INF_RUTO_SOUL);
break;
@ -1778,7 +1777,11 @@ void RandomizerOnSceneInitHandler(int16_t sceneNum) {
) return;
updateHook = GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && LINK_IS_ADULT && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL) && gPlayState->roomCtx.curRoom.num == 0) {
if (!Flags_GetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT) && LINK_IS_ADULT &&
CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) &&
(!RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) || Flags_GetRandomizerInf(RAND_INF_ZELDA_SOUL)) &&
gPlayState->roomCtx.curRoom.num == 0
) {
Flags_SetEventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT);
}
@ -2195,14 +2198,21 @@ void RandomizerOnActorInitHandler(void* actorRef) {
case ACTOR_EN_RU2:
inf = RAND_INF_RUTO_SOUL;
break;
case ACTOR_EN_NB:
inf = RAND_INF_NABOORU_SOUL;
break;
case ACTOR_EN_XC:
case ACTOR_EN_ZL1:
case ACTOR_EN_ZL4:
inf = RAND_INF_ZELDA_SOUL;
break;
case ACTOR_EN_ZL2:
case ACTOR_EN_ZL3:
case ACTOR_EN_ZL4:
case ACTOR_BOSS_GANON:
case ACTOR_BOSS_GANON2:
inf = RAND_INF_ZELDA_SOUL;
if (RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) == RO_NPC_SOULS_ON_PLUS_SAGES) {
inf = RAND_INF_ZELDA_SOUL;
}
break;
case ACTOR_EN_HY:
inf = RAND_INF_BEGGAR_SOUL;

View File

@ -369,20 +369,6 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_MAN_ON_ROOF_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_MALON_SOUL] = Item(RG_MALON_SOUL, Text{ "Malon's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_MALON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_MALON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_RAURU_SOUL] = Item(RG_RAURU_SOUL, Text{ "Rauru's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_RAURU_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_RAURU_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_SARIA_SOUL] = Item(RG_SARIA_SOUL, Text{ "Saria's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_SARIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_SARIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_DARUNIA_SOUL] = Item(RG_DARUNIA_SOUL, Text{ "Darunia's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_DARUNIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_DARUNIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_RUTO_SOUL] = Item(RG_RUTO_SOUL, Text{ "Ruto's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_RUTO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_RUTO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_NABOORU_SOUL] = Item(RG_NABOORU_SOUL, Text{ "Nabooru's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_NABOORU_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_NABOORU_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_IMPA_SOUL] = Item(RG_IMPA_SOUL, Text{ "Impa's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_IMPA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_IMPA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_ZELDA_SOUL] = Item(RG_ZELDA_SOUL, Text{ "Zelda's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_ZELDA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_ZELDA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_ARMS_DEALER_SOUL] = Item(RG_ARMS_DEALER_SOUL, Text{ "Arms Dealer's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_ARMS_DEALER_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_ARMS_DEALER_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_BEAN_SALESMAN_SOUL] = Item(RG_BEAN_SALESMAN_SOUL, Text{ "Bean Salesman's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_BEAN_SALESMAN_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
@ -413,6 +399,20 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_SCIENTIST_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_KAEPORA_SOUL] = Item(RG_KAEPORA_SOUL, Text{ "Kaepora's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_KAEPORA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_KAEPORA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_RAURU_SOUL] = Item(RG_RAURU_SOUL, Text{ "Rauru's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_RAURU_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_RAURU_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_SARIA_SOUL] = Item(RG_SARIA_SOUL, Text{ "Saria's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_SARIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_SARIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_DARUNIA_SOUL] = Item(RG_DARUNIA_SOUL, Text{ "Darunia's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_DARUNIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_DARUNIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_RUTO_SOUL] = Item(RG_RUTO_SOUL, Text{ "Ruto's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_RUTO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_RUTO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_NABOORU_SOUL] = Item(RG_NABOORU_SOUL, Text{ "Nabooru's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_NABOORU_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_NABOORU_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_IMPA_SOUL] = Item(RG_IMPA_SOUL, Text{ "Impa's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_IMPA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_IMPA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
itemTable[RG_ZELDA_SOUL] = Item(RG_ZELDA_SOUL, Text{ "Zelda's Soul" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_ZELDA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_ZELDA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul);
// Misc.
itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Angelrute" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
itemTable[RG_FISHING_POLE].SetCustomDrawFunc(Randomizer_DrawFishingPoleGI);

View File

@ -528,15 +528,16 @@ void RegionTable_Init_DodongosCavern() {
areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] = Region("Dodongos Cavern Boss Room", "Dodongos Cavern", {}, NO_DAY_NIGHT_CYCLE, {
// Events
EventAccess(&logic->DodongosCavernClear, []{return logic->DodongosCavernClear || (logic->HasSoul(RG_KING_DODONGO_SOUL) && (Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || (logic->CanUse(RG_MEGATON_HAMMER) && ctx->GetTrickOption(RT_DC_HAMMER_FLOOR));}) && (logic->CanUse(RG_BOMB_BAG) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CanJumpslashExceptHammer())); /*todo add chu kill to tricks*/}),
EventAccess(&logic->DodongosCavernWin, []{return logic->DodongosCavernWin || (logic->HasSoul(RG_KING_DODONGO_SOUL) && (Here(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return logic->HasExplosives() || (logic->CanUse(RG_MEGATON_HAMMER) && ctx->GetTrickOption(RT_DC_HAMMER_FLOOR));}) && (logic->CanUse(RG_BOMB_BAG) || logic->HasItem(RG_GORONS_BRACELET)) && logic->CanJumpslashExceptHammer())); /*todo add chu kill to tricks*/}),
EventAccess(&logic->DodongosCavernClear, []{return logic->DodongosCavernWin && logic->HasSage(RG_DARUNIA_SOUL);}),
}, {
// Locations
LOCATION(RC_DODONGOS_CAVERN_BOSS_ROOM_CHEST, true),
LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->DodongosCavernClear),
LOCATION(RC_DODONGOS_CAVERN_KING_DODONGO_HEART, logic->DodongosCavernWin),
LOCATION(RC_KING_DODONGO, logic->DodongosCavernClear),
}, {
// Exits
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return true;}),
Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->DodongosCavernClear;}, false),
Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->DodongosCavernWin;}, false),
});
}

View File

@ -706,7 +706,7 @@ void RegionTable_Init_FireTemple() {
areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", "Fire Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events
EventAccess(&logic->FireTempleWin, []{return logic->FireTempleWin || (logic->HasSoul(RG_VOLVAGIA_SOUL) && (logic->FireTimer() >= 64 && logic->CanUse(RG_MEGATON_HAMMER)));}),
EventAccess(&logic->FireTempleClear, []{return logic->FireTempleWin && logic->HasSoul(RG_DARUNIA_SOUL);}),
EventAccess(&logic->FireTempleClear, []{return logic->FireTempleWin && logic->HasSage(RG_DARUNIA_SOUL);}),
}, {
// Locations
LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->FireTempleWin),

View File

@ -601,7 +601,7 @@ void RegionTable_Init_ForestTemple() {
areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Region("Forest Temple Boss Room", "Forest Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events
EventAccess(&logic->ForestTempleWin, []{return logic->ForestTempleWin || (logic->HasSoul(RG_PHANTOM_GANON_SOUL) && ((logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))));}),
EventAccess(&logic->ForestTempleClear, []{return logic->ForestTempleWin && logic->HasSoul(RG_SARIA_SOUL);}),
EventAccess(&logic->ForestTempleClear, []{return logic->ForestTempleWin && logic->HasSage(RG_SARIA_SOUL);}),
}, {
// Locations
LOCATION(RC_FOREST_TEMPLE_PHANTOM_GANON_HEART, logic->ForestTempleWin),

View File

@ -341,7 +341,8 @@ void RegionTable_Init_JabuJabusBelly() {
areaTable[RR_JABU_JABUS_BELLY_BOSS_ROOM] = Region("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", {}, NO_DAY_NIGHT_CYCLE, {
// Events //todo: add pot kill trick
EventAccess(&logic->JabuJabusBellyClear, []{return logic->JabuJabusBellyClear || (logic->HasSoul(RG_BARINADE_SOUL) && (logic->CanUse(RG_BOOMERANG) && logic->CanJumpslashExceptHammer()));}),
EventAccess(&logic->JabuJabusBellyWin, []{return logic->JabuJabusBellyWin || (logic->HasSoul(RG_BARINADE_SOUL) && (logic->CanUse(RG_BOOMERANG) && logic->CanJumpslashExceptHammer()));}),
EventAccess(&logic->JabuJabusBellyClear, []{return logic->JabuJabusBellyWin && logic->HasSage(RG_RUTO_SOUL);}),
}, {
// Locations
LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_1, logic->CanBreakPots()),
@ -350,11 +351,11 @@ void RegionTable_Init_JabuJabusBelly() {
LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_4, logic->CanBreakPots()),
LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_5, logic->CanBreakPots()),
LOCATION(RC_JABU_JABUS_BELLY_BARINADE_POT_6, logic->CanBreakPots()),
LOCATION(RC_JABU_JABUS_BELLY_BARINADE_HEART, logic->JabuJabusBellyClear),
LOCATION(RC_JABU_JABUS_BELLY_BARINADE_HEART, logic->JabuJabusBellyWin),
LOCATION(RC_BARINADE, logic->JabuJabusBellyClear),
}, {
// Exits
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return false;}),
Entrance(RR_ZORAS_FOUNTAIN, []{return logic->JabuJabusBellyClear;}, false),
Entrance(RR_ZORAS_FOUNTAIN, []{return logic->JabuJabusBellyWin;}, false),
});
}

View File

@ -404,7 +404,7 @@ void RegionTable_Init_ShadowTemple() {
(logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD)) &&
(logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT) || ctx->GetTrickOption(RT_SHADOW_BONGO))));
}),
EventAccess(&logic->ShadowTempleClear, []{ return logic->ShadowTempleWin && logic->HasSoul(RG_IMPA_SOUL); }),
EventAccess(&logic->ShadowTempleClear, []{ return logic->ShadowTempleWin && logic->HasSage(RG_IMPA_SOUL); }),
}, {
// Locations
LOCATION(RC_SHADOW_TEMPLE_BONGO_BONGO_HEART, logic->ShadowTempleWin),

View File

@ -545,7 +545,7 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_BOSS_ROOM] = Region("Spirit Temple Boss Room", "Spirit Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events
EventAccess(&logic->SpiritTempleWin, []{return logic->SpiritTempleWin || (logic->HasSoul(RG_TWINROVA_SOUL) && (logic->CanUse(RG_MIRROR_SHIELD) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))));}),
EventAccess(&logic->SpiritTempleClear, []{return logic->SpiritTempleWin && logic->HasSoul(RG_NABOORU_SOUL);}),
EventAccess(&logic->SpiritTempleClear, []{return logic->SpiritTempleWin && logic->HasSage(RG_NABOORU_SOUL);}),
}, {
// Locations
LOCATION(RC_SPIRIT_TEMPLE_TWINROVA_HEART, logic->SpiritTempleWin),

View File

@ -726,7 +726,7 @@ void RegionTable_Init_WaterTemple() {
areaTable[RR_WATER_TEMPLE_BOSS_ROOM] = Region("Water Temple Boss Room", "Water Temple", {}, NO_DAY_NIGHT_CYCLE, {
// Events
EventAccess(&logic->WaterTempleWin, []{return logic->WaterTempleWin || (logic->HasSoul(RG_MORPHA_SOUL) && (logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD))));}),
EventAccess(&logic->WaterTempleClear, []{return logic->WaterTempleWin && logic->HasSoul(RG_RUTO_SOUL);}),
EventAccess(&logic->WaterTempleClear, []{return logic->WaterTempleWin && logic->HasSage(RG_RUTO_SOUL);}),
}, {
// Locations
LOCATION(RC_WATER_TEMPLE_MORPHA_HEART, logic->WaterTempleWin),

View File

@ -469,13 +469,6 @@ namespace Rando {
case RG_WINDMILL_MAN_SOUL:
case RG_MAN_ON_ROOF_SOUL:
case RG_MALON_SOUL:
case RG_RAURU_SOUL:
case RG_SARIA_SOUL:
case RG_DARUNIA_SOUL:
case RG_RUTO_SOUL:
case RG_NABOORU_SOUL:
case RG_IMPA_SOUL:
case RG_ZELDA_SOUL:
case RG_BEGGAR_SOUL:
case RG_ARMS_DEALER_SOUL:
case RG_BEAN_SALESMAN_SOUL:
@ -492,12 +485,23 @@ namespace Rando {
case RG_DIVING_SOUL:
case RG_SCIENTIST_SOUL:
case RG_KAEPORA_SOUL:
case RG_RAURU_SOUL:
case RG_SARIA_SOUL:
case RG_DARUNIA_SOUL:
case RG_RUTO_SOUL:
case RG_NABOORU_SOUL:
case RG_IMPA_SOUL:
case RG_ZELDA_SOUL:
return !ctx->GetOption(RSK_SHUFFLE_NPC_SOULS) || HasItem(itemName);
default:
return false;
}
}
bool Logic::HasSage(RandomizerGet itemName) {
return ctx->GetOption(RSK_SHUFFLE_NPC_SOULS).Is(RO_NPC_SOULS_ON_PLUS_SAGES) && HasItem(itemName);
}
bool Logic::CanOpenOverworldDoor(RandomizerGet key) {
if (!ctx->GetOption(RSK_LOCK_OVERWORLD_DOORS)) {
return true;

View File

@ -42,7 +42,6 @@ class Logic {
bool WakeUpAdultTalon = false;
// Dungeon Clears
bool DekuTreeWin = false;
bool DodongosCavernWin = false;
bool JabuJabusBellyWin = false;
bool ForestTempleWin = false;
@ -194,6 +193,7 @@ class Logic {
bool HasProjectile(HasProjectileAge age);
bool HasItem(RandomizerGet itemName);
bool HasSoul(RandomizerGet itemName);
bool HasSage(RandomizerGet itemName);
bool CanOpenOverworldDoor(RandomizerGet itemName);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);

View File

@ -699,7 +699,8 @@ void Settings::CreateOptionDescriptions() {
"required items and locations to beat the game "
"will be guaranteed reachable.";
mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS] = "Shuffles 8 boss souls (one for each blue warp dungeon). A boss will not appear until you collect its respective soul."
"\n\"On + Ganon\" will also hide Ganon and Ganondorf behind a boss soul.";
mOptionDescriptions[RSK_SHUFFLE_NPC_SOULS] = "Shuffles souls of NPCs. An NPC will not appear until you collect its respective soul.";
"\n\"On + Ganon\" also hide Ganon and Ganondorf behind a boss soul.";
mOptionDescriptions[RSK_SHUFFLE_NPC_SOULS] = "Shuffles souls of NPCs. An NPC will not appear until you collect its respective soul."
"\n\"On + Sages\" requires sage souls to receive blue warp reward. Zelda is required to defeat Ganon.";
}
} // namespace Rando

View File

@ -3344,13 +3344,6 @@ typedef enum {
RG_WINDMILL_MAN_SOUL,
RG_MAN_ON_ROOF_SOUL,
RG_MALON_SOUL,
RG_RAURU_SOUL,
RG_SARIA_SOUL,
RG_DARUNIA_SOUL,
RG_RUTO_SOUL,
RG_NABOORU_SOUL,
RG_IMPA_SOUL,
RG_ZELDA_SOUL,
RG_BEGGAR_SOUL,
RG_ARMS_DEALER_SOUL,
RG_BEAN_SALESMAN_SOUL,
@ -3366,7 +3359,14 @@ typedef enum {
RG_BOMBCHU_LADY_SOUL,
RG_DIVING_SOUL,
RG_SCIENTIST_SOUL,
RG_KAEPORA_SOUL, // used by loop, must be last NPC soul
RG_KAEPORA_SOUL, // used by loop, must be last non-sage NPC soul
RG_RAURU_SOUL,
RG_SARIA_SOUL,
RG_DARUNIA_SOUL,
RG_RUTO_SOUL,
RG_NABOORU_SOUL,
RG_IMPA_SOUL,
RG_ZELDA_SOUL, // used by loop, must be last NPC soul
RG_OCARINA_A_BUTTON,
RG_OCARINA_C_UP_BUTTON,
RG_OCARINA_C_DOWN_BUTTON,
@ -5406,6 +5406,12 @@ typedef enum {
RO_BOSS_SOULS_ON_PLUS_GANON,
} RandoOptionBossSouls;
typedef enum {
RO_NPC_SOULS_OFF,
RO_NPC_SOULS_ON,
RO_NPC_SOULS_ON_PLUS_SAGES,
} RandoOptionNpcSouls;
//Fishsanity settings (off, loach only, pond only, grottos only, both)
typedef enum {
RO_FISHSANITY_OFF,

View File

@ -541,42 +541,46 @@ void CheckTrackerTransition(uint32_t sceneNum) {
doAreaScroll = true;
previousArea = currentArea;
currentArea = GetCheckArea();
switch (sceneNum) {
case SCENE_KOKIRI_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_KOKIRI_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_BAZAAR:
if (Flags_GetRandomizerInf(RAND_INF_BAZAAR_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_POTION_SHOP_MARKET:
if (Flags_GetRandomizerInf(RAND_INF_POTION_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_BOMBCHU_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_BOMBCHU_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_POTION_SHOP_KAKARIKO:
if (Flags_GetRandomizerInf(RAND_INF_POTION_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_GORON_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_GORON_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_ZORA_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_ZORA_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_NPC_SOULS) == RO_NPC_SOULS_OFF) {
SetShopSeen(sceneNum, false);
} else {
switch (sceneNum) {
case SCENE_KOKIRI_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_KOKIRI_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_BAZAAR:
if (Flags_GetRandomizerInf(RAND_INF_BAZAAR_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_POTION_SHOP_MARKET:
if (Flags_GetRandomizerInf(RAND_INF_POTION_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_BOMBCHU_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_BOMBCHU_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_POTION_SHOP_KAKARIKO:
if (Flags_GetRandomizerInf(RAND_INF_POTION_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_GORON_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_GORON_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
case SCENE_ZORA_SHOP:
if (Flags_GetRandomizerInf(RAND_INF_ZORA_SHOPKEEPER_SOUL)) {
SetShopSeen(sceneNum, false);
}
break;
}
}
if (!IsAreaSpoiled(currentArea) && (RandomizerCheckObjects::AreaIsOverworld(currentArea) || std::find(spoilingEntrances.begin(), spoilingEntrances.end(), gPlayState->nextEntranceIndex) != spoilingEntrances.end())) {
SetAreaSpoiled(currentArea);

View File

@ -1348,13 +1348,6 @@ typedef enum {
RAND_INF_WINDMILL_MAN_SOUL,
RAND_INF_MAN_ON_ROOF_SOUL,
RAND_INF_MALON_SOUL,
RAND_INF_RAURU_SOUL,
RAND_INF_SARIA_SOUL,
RAND_INF_DARUNIA_SOUL,
RAND_INF_RUTO_SOUL,
RAND_INF_NABOORU_SOUL,
RAND_INF_IMPA_SOUL,
RAND_INF_ZELDA_SOUL,
RAND_INF_BEGGAR_SOUL,
RAND_INF_ARMS_DEALER_SOUL,
RAND_INF_BEAN_SALESMAN_SOUL,
@ -1370,7 +1363,14 @@ typedef enum {
RAND_INF_TREASURE_MAN_SOUL,
RAND_INF_DIVING_SOUL,
RAND_INF_SCIENTIST_SOUL,
RAND_INF_KAEPORA_SOUL, // used by loop, must be last NPC soul
RAND_INF_KAEPORA_SOUL, // used by loop, must be last non-sage NPC soul
RAND_INF_RAURU_SOUL,
RAND_INF_SARIA_SOUL,
RAND_INF_DARUNIA_SOUL,
RAND_INF_RUTO_SOUL,
RAND_INF_NABOORU_SOUL,
RAND_INF_IMPA_SOUL,
RAND_INF_ZELDA_SOUL, // used by loop, must be last NPC soul
RAND_INF_MAX,
} RandomizerInf;

View File

@ -226,7 +226,7 @@ void Settings::CreateOptions() {
OPT_U8(RSK_SHUFFLE_CHEST_MINIGAME, "Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"});
OPT_BOOL(RSK_SHUFFLE_100_GS_REWARD, "Shuffle 100 GS Reward", CVAR_RANDOMIZER_SETTING("Shuffle100GSReward"), mOptionDescriptions[RSK_SHUFFLE_100_GS_REWARD], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
OPT_U8(RSK_SHUFFLE_BOSS_SOULS, "Shuffle Boss Souls", {"Off", "On", "On + Ganon"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleBossSouls"), mOptionDescriptions[RSK_SHUFFLE_BOSS_SOULS], WidgetType::Combobox);
OPT_BOOL(RSK_SHUFFLE_NPC_SOULS, "Shuffle NPC Souls", CVAR_RANDOMIZER_SETTING("ShuffleNpcSouls"), mOptionDescriptions[RSK_SHUFFLE_NPC_SOULS]);
OPT_U8(RSK_SHUFFLE_NPC_SOULS, "Shuffle NPC Souls", {"Off", "On", "On + Sages"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleNpcSouls"), mOptionDescriptions[RSK_SHUFFLE_NPC_SOULS], WidgetType::Combobox);
OPT_BOOL(RSK_SHUFFLE_DEKU_STICK_BAG, "Shuffle Deku Stick Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuStickBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_STICK_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
OPT_BOOL(RSK_SHUFFLE_DEKU_NUT_BAG, "Shuffle Deku Nut Bag", CVAR_RANDOMIZER_SETTING("ShuffleDekuNutBag"), mOptionDescriptions[RSK_SHUFFLE_DEKU_NUT_BAG], IMFLAG_SEPARATOR_BOTTOM, WidgetType::Checkbox, RO_GENERIC_OFF);
OPT_U8(RSK_SHUFFLE_FREESTANDING, "Shuffle Freestanding Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), mOptionDescriptions[RSK_SHUFFLE_FREESTANDING], WidgetType::Combobox, RO_SHUFFLE_FREESTANDING_OFF);

View File

@ -406,7 +406,7 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
Flags_SetEventChkInf(EVENTCHKINF_PULLED_MASTER_SWORD_FROM_PEDESTAL);
Flags_SetEventChkInf(EVENTCHKINF_ENTERED_MASTER_SWORD_CHAMBER);
Flags_SetEventChkInf(EVENTCHKINF_SHEIK_SPAWNED_AT_MASTER_SWORD_PEDESTAL);
if (!IS_RANDO || !RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) || Flags_GetRandomizerInf(RAND_INF_RAURU_SOUL)) {
if (!IS_RANDO || RAND_GET_OPTION(RSK_SHUFFLE_NPC_SOULS) != RO_NPC_SOULS_ON_PLUS_SAGES || Flags_GetRandomizerInf(RAND_INF_RAURU_SOUL)) {
Flags_SetEventChkInf(EVENTCHKINF_TIME_TRAVELED_TO_ADULT);
if (GameInteractor_Should(VB_GIVE_ITEM_LIGHT_MEDALLION, true)) {
Item_Give(gPlayState, ITEM_MEDALLION_LIGHT);