v0 complete

This commit is contained in:
Pepper0ni 2025-04-23 22:44:24 +01:00
parent 01800f74c6
commit 5b42fb1e4e
6 changed files with 537 additions and 290 deletions

View file

@ -213,126 +213,176 @@ bool Here(const RandomizerRegion region, ConditionFn condition) {
uint8_t SpiritExplosiveLogic() {
return logic->SpiritBrokenWallToStatue() ? 1 : ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() ? 2 : 3;
}
// RANDOTODO basically every condition here will need climb or longshot.
// clang-format off
std::map<RandomizerRegion, SpiritLogicData> Region::spiritLogicData = {
{RR_SPIRIT_TEMPLE_WEST_CLIMB_BASE, SpiritLogicData(5, 5, 3, []{return true;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_BROKEN_WALL, SpiritLogicData(5, 5, 3, []{return true /*logic->CanClimbHigh()*/;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_2F_MIRROR, SpiritLogicData(5, 5, 3, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritBrokenWallToStatue();} , []{return true/*logic->CanClimbHigh()*/;} , []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);})},
{RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue();} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_GS_LEDGE, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue() && logic->SpiritWestToSkull();} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic()) && logic->SpiritWestToSkull()
/* && logic->CanClimbHigh() && str0*/;} , []{return logic->SpiritWestToSkull()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_STATUE_ROOM, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue();} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true;})},
{RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue()/* && str0*/;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*(logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0*/;})},
{RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue()/* && str0*/;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*(logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0*/;})},
{RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, SpiritLogicData(5, 5, 3, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritBrokenWallToStatue();} , []{return true/*logic->CanClimbHigh() && str0*/;} , []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);})},
{RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, SpiritLogicData(5, 5, 3, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritBrokenWallToStatue() && logic->SpiritEastToSwitch();}, []{return logic->SpiritEastToSwitch()/* && logic->CanClimbHigh() && str0*/;} , []{return logic->SpiritEastToSwitch() && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));})},
{RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, SpiritLogicData(7, 6, 7, []{return true;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6) && logic->CanHitSwitch()/* && logic->Climb*/;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6) && logic->CanHitSwitch()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, SpiritLogicData(7, 6, 7, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6)/* && logic->Climb*/;} , []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6)/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;} , []{return true/*logic->Climb*/;} , []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;} , []{return true;} , []{return true;})},
{RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch() && logic->MQSpiritStatueToSunBlock()/* && logic->CanClimbHigh()*/;} , []{return logic->MQSpiritStatueToSunBlock()/* && logic->Climb*/;} , []{return logic->MQSpiritStatueToSunBlock()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch() &&
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH].Here([]{return logic->MQSpiritStatueSouthDoor();})
/* && logic->CanClimbHigh()*/;} , []{return false;} , []{return areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH].Here([]{return logic->MQSpiritStatueSouthDoor();});})},
};
// clang-format on
/*
* This logic covers checks that exist in the shared areas of Spirit from a glitchless standpoint.
* This logic covers checks that exist in the shared areas of Spirit
* This code will fail if any glitch allows Adult to go in the Child spirit door first or vice versa as it relies on
specific ages
* There are 4 possibilities for passing a check, but first I have to talk about parallel universes.
* In order to pass a check, we must either determine that Access is certain,
or that it is always possible to get a check somehow.
* But first I have to talk about parallel universes.
* In the first universe, the player enters spirit as child, and spends as many keys as they can to lock adult out
* In the second, they enter as adult and spend as many keys as they can to lock child out.
* When an Age can no longer be kept out by the other age, that age is said to have Certain Access to a region
* Additionally, if it is possible to enter spirit in reverse, there are 2 more universes:
* In the third universe, adult enters in reverse, and wastes all the keys so noone can enter through the front
* In the forth, child manages to do the same, and lock people out of the front
* All access from the boss door in shared areas is Certain
* While other universes exist, such as both ages entering in reverse or
child using their key, getting stuck, then coming back to do the dungeon as adult, these
are all sub-possibilities of these 4 universes
* As we do not know which universe we are in until the player chooses one in-game,
we must be able to collect the check in both universes
* When an Age can no longer be kept out by conflicting universes, that age is said to have Certain Access to a region
* If both ages have access to a region with a certain number of keys, but there is no Certain Access,
* then a check is only in logic if both ages can collect the check independently
* then a check is only in logic if all possible universes can collect the check independently
* If an age has Certain Access then that age can collect checks alone,
* and there is no reason to check the other age untile the universes converge.
* The universes converge when the player has all the keys, giving both ages Certain Access.
* The universes converge when the player has all the keys, giving both ages Certain Access everywhere.
* We must check for these universes manually as we allow technical access with minimum keys for
* technical reasons as otherwise the code will never run
*/
* technical reasons as otherwise the logic code will never run
* The first and 3rd column list how many keys are needed for each age to have Certain Access
* the second column is child keys in case there's Child reverse access, due to an edge case in MQ spirit logic
* where the broken wall room can be reached with 6 keys if you can hit switches and have reverse Child access
* The first condition is the combined conditions needed to move from the 1F child lock to the area being checks
* the second condition is the same for adult 1F lock, and the third is the access from the boss door.
*/
// clang-format off
std::map<RandomizerRegion, SpiritLogicData> Region::spiritLogicData = {
//Vanilla
{RR_SPIRIT_TEMPLE_WEST_CLIMB_BASE, SpiritLogicData(5, 5, 3, []{return true;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_BROKEN_WALL, SpiritLogicData(5, 5, 3, []{return true /*logic->CanClimbHigh()*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_2F_MIRROR, SpiritLogicData(5, 5, 3, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritBrokenWallToStatue();}, []{return true/*logic->CanClimbHigh()*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);})},
{RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue()/* && logic->CanClimbHigh()*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_INNER_WEST_HAND, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue()/* && logic->CanClimbHigh()*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_GS_LEDGE, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue() && logic->SpiritWestToSkull()/* && logic->CanClimbHigh()*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic()) && logic->SpiritWestToSkull()
/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritWestToSkull()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_STATUE_ROOM, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue()/* && logic->CanClimbHigh()*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true;})},
//Assumes SpiritSunBlockSouthLedge() for all access
{RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*(logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0*/;})},
{RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, SpiritLogicData(5, 5, 3, []{return logic->SpiritBrokenWallToStatue()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, SpiritExplosiveLogic())/* && logic->CanClimbHigh() && str0*/;}, []{return true/*(logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)) && str0*/;})},
{RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, SpiritLogicData(5, 5, 3, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritBrokenWallToStatue()/* && logic->CanClimbHigh()*/;}, []{return true/*logic->CanClimbHigh() && str0*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);})},
{RR_SPIRIT_TEMPLE_INNER_EAST_HAND, SpiritLogicData(5, 5, 3, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritBrokenWallToStatue()/* && logic->CanClimbHigh()*/;}, []{return true/*logic->CanClimbHigh() && str0*/;}, []{return logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS);})},
{RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, SpiritLogicData(5, 5, 3, []{return logic->CanUse(RG_HOOKSHOT) && logic->SpiritBrokenWallToStatue() && logic->SpiritEastToSwitch();}, []{return logic->SpiritEastToSwitch()/* && logic->CanClimbHigh() && str0*/;}, []{return logic->SpiritEastToSwitch() && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS));})},
//MQ /*&& logic->CanClimbHigh()*/
{RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, SpiritLogicData(7, 6, 7, []{return true;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6) && logic->CanHitSwitch()/* && logic->Climb*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6) && logic->CanHitSwitch()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, SpiritLogicData(7, 6, 7, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6)/* && logic->Climb*/;}, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6)/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;}, []{return true/*logic->Climb*/;}, []{return true/*logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS)*/;})},
{RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots()/* && logic->CanClimbHigh()*/;}, []{return logic->MQSpiritWestToPots()/* && logic->Climb*/;}, []{return /*logic->CanUse(RG_HOVER_BOOTS) || (logic->CanClimb() && */logic->MQSpiritWestToPots()/*)*/;})},
{RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch() && logic->MQSpiritWestToPots()/* && logic->CanClimbHigh()*/;}, []{return logic->MQSpiritWestToPots()/* && logic->Climb*/;}, []{return /*logic->CanUse(RG_HOVER_BOOTS) || (logic->CanClimb() && */logic->MQSpiritWestToPots()/*)*/;})},
{RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch()/* && logic->CanClimbHigh()*/;}, []{return true;}, []{return true;})},
{RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch() && logic->MQSpiritStatueToSunBlock()/* && logic->CanClimbHigh()*/;} , []{return logic->MQSpiritStatueToSunBlock()/* && logic->Climb*/;}, []{return logic->MQSpiritStatueToSunBlock()/* && (logic->CanClimb() || logic->CanUse(RG_HOVER_BOOTS))*/;})},
{RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, SpiritLogicData(7, 7, 0, []{return logic->CanHitSwitch() &&
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH].Here([]{return logic->MQSpiritStatueSouthDoor();})
/* && logic->CanClimbHigh()*/;}, []{return true;}, []{return areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH].Here([]{return logic->MQSpiritStatueSouthDoor();});})},
};
// clang-format on
bool SpiritShared(RandomizerRegion region, ConditionFn condition, bool anyAge, RandomizerRegion otherRegion, ConditionFn otherCondition){
/*
* Spirit Shared can take up to 3 regions, this is because checks can exist in many regions at the same time
and the logic needs to be able to check the access logic from those regions to check the other universes properly.
*anyAge is equivalent to a self referencing Here, used for events and any check where that is relevent.
*/
bool SpiritShared(RandomizerRegion region, ConditionFn condition, bool anyAge,
RandomizerRegion otherRegion, ConditionFn otherCondition,
RandomizerRegion thirdRegion, ConditionFn thirdCondition){
SpiritLogicData curRegionData = Region::spiritLogicData[region];
uint8_t childKeys = logic->ReverseSpiritChild ? curRegionData.childReverseKeys : curRegionData.childKeys;
bool result = false;
// store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
// If child enters in reverse, then they have access to Certain Access to Broken Wall room in 6 keys,
// the ability to hit switches and the ability to climb because only child can reach the initial child lock
// without opening the Statue room to Broken Wall Room lock first
logic->IsChild = true;
logic->IsAdult = false;
uint8_t childKeys = (logic->ReverseSpiritChild && logic->CanHitSwitch()/* && CanClimbHigh()*/) ? curRegionData.childReverseKeys : curRegionData.childKeys;
// If we have enough keys that an age cannot be kept out, we have Certain Access
// otherwise if we have entered in reverse and can reach from the face, we have Certain Access
bool ChildCertainAccess = (logic->ReverseSpiritChild && curRegionData.reverseAccess) || logic->SmallKeys(RR_SPIRIT_TEMPLE, childKeys);
bool AdultCertainAccess = (logic->ReverseSpiritAdult && curRegionData.reverseAccess) || logic->SmallKeys(RR_SPIRIT_TEMPLE, curRegionData.adultKeys);
// If both ages have certain access, we can test with Either age
if (ChildCertainAccess && AdultCertainAccess) {
if (anyAge) {
return areaTable[region].Here(condition);
}
return condition();
// otherwise, we have to check the current age and...
} else if (areaTable[region].Child() && logic->IsChild) {
bool result = condition();
// If we have Certain Access, we just run the condition.
if (ChildCertainAccess) {
return result;
// Otherwise, if we have the keys to know either age can reach, we need to see if we could reach as Adult too
} else if (result) {
SpiritLogicData otherRegionData = Region::spiritLogicData[otherRegion];
// store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
bool ChildCertainAccess = (logic->ReverseSpiritChild && curRegionData.reverseAccess()) || logic->SmallKeys(RR_SPIRIT_TEMPLE, childKeys);
//Switch back to adult to check adult access
logic->IsChild = false;
logic->IsAdult = true;
bool AdultCertainAccess = (logic->ReverseSpiritAdult && curRegionData.reverseAccess()) || logic->SmallKeys(RR_SPIRIT_TEMPLE, curRegionData.adultKeys);
// If we are AnyAge and have any CeratinAccess, then we can check those ages
//we don't need to check ambiguity here as if this fails, then 1 of the ages has failed
if (anyAge && (ChildCertainAccess || AdultCertainAccess)){
// set age access to the Certain Access
logic->IsChild = ChildCertainAccess;
logic->IsAdult = AdultCertainAccess;
// check condition as well as having at least child or adult access
result = condition();
// otherwise, we have to check the current age and...
} else if (areaTable[region].Child() && pastChild) {
//Switch to Child
logic->IsChild = true;
logic->IsAdult = false;
result = condition();
// If we have Certain Access, we just run the condition.
// Otherwise, if we have the keys to know either age can reach, we need to see if we could reach as Adult
// and if needed, in reverse
if (!ChildCertainAccess && result && (!logic->IsReverseAccessPossible() || Region::spiritLogicData[otherRegion].reverseAccess())) {
//Switch to Adult
logic->IsChild = false;
logic->IsAdult = true;
// If Adult can get there and get the check, we can get the check in logic
// If reverse spirit is also possible, we need to make sure Adult can get it via reverse entry too
result = (curRegionData.adultAccess && (!logic->IsReverseAccessPossible() || curRegionData.reverseAccess) && condition()) ||
result = (curRegionData.adultAccess() && (!logic->IsReverseAccessPossible() || curRegionData.reverseAccess) && condition()) ||
(otherRegion != RR_NONE &&
(otherRegionData.adultAccess && (!logic->IsReverseAccessPossible() || otherRegionData.reverseAccess) && otherCondition()));
logic->IsChild = pastChild;
logic->IsAdult = pastAdult;
return result;
(Region::spiritLogicData[otherRegion].adultAccess() &&
(!logic->IsReverseAccessPossible() || Region::spiritLogicData[otherRegion].reverseAccess()) &&
otherCondition())) ||
(thirdRegion != RR_NONE &&
(Region::spiritLogicData[thirdRegion].adultAccess() &&
(!logic->IsReverseAccessPossible() || Region::spiritLogicData[thirdRegion].reverseAccess()) &&
thirdCondition()));
}
} else if (areaTable[region].Adult() && logic->IsAdult) {
bool result = condition();
} else if (areaTable[region].Adult() && pastAdult) {
result = condition();
// if we have enough keys to have Certain Access, we just run the condition
// Alternatively, if we have entered in reverse and can reach from the face, we have Certain Access
if (AdultCertainAccess) {
return result;
// Otherwise, if we have the keys to know either age can reach, we need to see if we could reach as Child too
} else if (result){
SpiritLogicData otherRegionData = Region::spiritLogicData[otherRegion];
// store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
// Otherwise, if we have the keys to know either age can reach, we need to see if we could reach as Child
// and if needed, in reverse
if (!AdultCertainAccess && result && (!logic->IsReverseAccessPossible() || Region::spiritLogicData[otherRegion].reverseAccess)){
//Switch to Child
logic->IsChild = true;
logic->IsAdult = false;
// If Child can get there and get the check, we can get the check in logic
// If reverse spirit is also possible, we need to make sure Child can get it via reverse entry too
result = (curRegionData.childAccess && (!logic->IsReverseAccessPossible() || curRegionData.reverseAccess) && condition()) ||
result = (curRegionData.childAccess() && (!logic->IsReverseAccessPossible() || curRegionData.reverseAccess()) && condition()) ||
(otherRegion != RR_NONE &&
(otherRegionData.childAccess && (!logic->IsReverseAccessPossible() || otherRegionData.reverseAccess) && otherCondition()));
logic->IsChild = pastChild;
logic->IsAdult = pastAdult;
return result;
(Region::spiritLogicData[otherRegion].childAccess() &&
(!logic->IsReverseAccessPossible() || Region::spiritLogicData[otherRegion].reverseAccess()) &&
otherCondition())) ||
(thirdRegion != RR_NONE &&
(Region::spiritLogicData[thirdRegion].childAccess() &&
(!logic->IsReverseAccessPossible() || Region::spiritLogicData[thirdRegion].reverseAccess()) &&
thirdCondition()));
}
}
return false;
// set back age variables
logic->IsChild = pastChild;
logic->IsAdult = pastAdult;
return result;
}
bool BeanPlanted(const RandomizerRegion region) {

View file

@ -252,9 +252,6 @@ class Region {
}
static std::map<RandomizerRegion, SpiritLogicData> spiritLogicData;
bool SpiritShared(ConditionFn condition, ConditionFn childAccess, ConditionFn adultAccess, ConditionFn ReverseAccess,
uint8_t childKeys, uint8_t adultKeys, uint8_t eitherKeys, bool anyAge);
};
extern std::array<Region, RR_MAX> areaTable;
@ -264,7 +261,8 @@ bool Here(const RandomizerRegion region,
ConditionFn
condition); // RANDOTODO make a less stupid way to check own at either age than self referencing with this
bool SpiritShared(RandomizerRegion region, ConditionFn condition, bool anyAge = false,
RandomizerRegion otherRegion = RR_NONE, ConditionFn otherCondition = []{return false;});
RandomizerRegion otherRegion = RR_NONE, ConditionFn otherCondition = []{return false;},
RandomizerRegion thirdRegion = RR_NONE, ConditionFn thirdCondition = []{return false;});
bool CanPlantBean(const RandomizerRegion region);
bool BothAges(const RandomizerRegion region);
bool ChildCanAccess(const RandomizerRegion region);

View file

@ -23,7 +23,7 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_1F_WEST, []{return logic->IsChild;}),
Entrance(RR_SPIRIT_TEMPLE_1F_WEST, []{return logic->IsChild/*CanUse(RG_CRAWL)*/;}),
Entrance(RR_SPIRIT_TEMPLE_1F_EAST, []{return logic->CanUse(RG_SILVER_GAUNTLETS);}),
});
@ -32,15 +32,15 @@ void RegionTable_Init_SpiritTemple() {
EventAccess(&logic->NutCrate, []{return true;}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_LOBBY, []{return logic->IsChild;}),
Entrance(RR_SPIRIT_TEMPLE_1F_BOXES, []{return logic->IsChild;}),
Entrance(RR_SPIRIT_TEMPLE_LOBBY, []{return logic->IsChild/*CanUse(RG_CRAWL)*/;}),
Entrance(RR_SPIRIT_TEMPLE_1F_BOXES, []{return logic->IsChild/*CanUse(RG_CRAWL)*/;}),
Entrance(RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_1F_WEST, []{return logic->CanKillEnemy(RE_ARMOS) && logic->CanKillEnemy(RE_KEESE);});}),
Entrance(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_1F_WEST, []{return logic->CanKillEnemy(RE_ARMOS) && logic->CanKillEnemy(RE_KEESE);});}),
});
areaTable[RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_SOUTH] = Region("Spirit Temple Switch Bridge South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//RANDOTODO a version od CanHitSwitch that takes WallOrFloor
//RANDOTODO a version of CanHitSwitch that takes WallOrFloor
EventAccess(&logic->SpiritChildSwitchBridge, []{return logic->CanUse(RG_BOOMERANG) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || (logic->CanUse(RG_BOMBCHU_5) && ctx->GetTrickOption(RT_SPIRIT_CHILD_CHU));}),
}, {}, {
//Exits
@ -74,13 +74,13 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_NORTH] = Region("Spirit Temple Rupee Bridge North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->SpiritRupeeBridge, []{return true;}),
EventAccess(&logic->SpiritRupeeBridge, []{return true/*CanClimb()*/;}),
}, {
//Locations
// these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust
LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch()),
// possible to collect without lowering fence, should be a trick
LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)),
LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->SpiritRupeeBridge && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH, []{return logic->SpiritRupeeBridge;}),
@ -102,7 +102,7 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2, logic->CanBreakSmallCrates()),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_1F_WEST, []{return logic->IsChild;}),
Entrance(RR_SPIRIT_TEMPLE_1F_WEST, []{return logic->IsChild/*CanUse(RG_CRAWL)*/;}),
Entrance(RR_SPIRIT_TEMPLE_BROKEN_WALL, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}),
});
@ -113,7 +113,7 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_1F_BOXES, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}),
Entrance(RR_SPIRIT_TEMPLE_BROKEN_WALL, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_BROKEN_WALL, []{return true/*CanClimbHigh()*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_BROKEN_WALL] = Region("Spirit Temple Broken Wall", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -160,7 +160,7 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanKillEnemy(RE_GOLD_SKULLTULA)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_ABOVE_BOULDERS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_ABOVE_BOULDERS, []{return true/*CanClimb()*/;}),
//Jump slash is possible as child, but pretty tight. Jumpslash as late as you can
//A damage boost off the boulder is also possible, but you need
Entrance(RR_SPIRIT_TEMPLE_PAST_BOULDERS, []{return logic->SpiritBouldersSilvers;}),
@ -178,56 +178,71 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_EAST_CLIMB_BASE] = Region("Spirit Temple East Climb Base", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_1F_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}),
Entrance(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true/*CanClimbHigh()*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_2F_MIRROR] = Region("Spirit Temple 2F Mirror", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true;})),
LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true;})),
LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true/*str0 || SunlightArrows()*/;})),
LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true/*str0 || SunlightArrows()*/;})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_EAST_CLIMB_BASE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return true/*str0 || SunlightArrows()*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST] = Region("Spirit Temple Statue Rooom West", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM access
LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));})),
//Current and N64 logic doesn't need scarecrow, you can hit the skull with normal hookshot from a specific spot on the forearm
//Child can get this with hook by backflipping onto the upper arm and standing in a precise place
LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE) ? ED_BOOMERANG : ED_HOOKSHOT);}, false,
RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);})),
LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));}, false,
RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();})),
LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT);}, false,
RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE) ? ED_BOOMERANG : ED_HOOKSHOT);},
RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_BROKEN_WALL, []{return true;}),
//(IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_SCARECROW)
Entrance(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->SpiritWestToSkull();}),
Entrance(RR_SPIRIT_TEMPLE_BROKEN_WALL, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SCARECROW);}),
// RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}),
Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}),
Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return true/*str0*/;}),
//!QUANTUM LOGIC!
//When child enters spirit in reverse, has 4 keys, and dungeon entrance shuffle is off,
//Child cannot lock themselves out of desert colossus access as if they save the west hand lock for last
//they will be able to exit the dungeon through the intended entrance and vice versa
//for needing to open the west hand lock to block the intended child route
Entrance(RR_DESERT_COLOSSUS, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->ReverseSpiritChild &&
logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanKillEnemy(RE_IRON_KNUCKLE);}),
Entrance(RR_DESERT_COLOSSUS, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->ReverseSpiritChild && /*str0 &&*/
logic->IsChild/*CanUse(RG_CRAWL)*/ && logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanKillEnemy(RE_IRON_KNUCKLE);}),
});
areaTable[RR_SPIRIT_TEMPLE_INNER_WEST_HAND] = Region("Spirit Temple Inner West Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//You can hit the skull with normal hookshot from a specific spot on the forearm, which is in logic on N64 and 3DS, pretty questionable though
LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE) ? ED_BOOMERANG : ED_HOOKSHOT);}, false,
RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);},
RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT);})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP);})
});
areaTable[RR_SPIRIT_TEMPLE_GS_LEDGE] = Region("Spirit Temple GS ledge", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);})),
LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, SpiritShared(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);}, false,
RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE) ? ED_BOOMERANG : ED_HOOKSHOT);},
RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_LONGSHOT);})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return true;})
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return true;})
});
areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM] = Region("Spirit Temple Statue Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();}, false,
LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();}, false,
RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW));})),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})),
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})),
@ -237,7 +252,7 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return true/*CanClimb()*/;}),
// RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}),
@ -252,15 +267,29 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM] = Region("Spirit Temple Sun Block Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM] = Region("Spirit Temple Sun Block Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return true/*str0 || SunlightArrows*/;}),
//The blocks can be used to get onto this ledge itemless
//true/*str0 || IsAdult || CanKillEnemy(RE_BEAMOS) || BunnyHovers() ||
//((HasFireSource() || (SpiritSunBlockTorch && (logic->CanUse(STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))))) && CanUse(RG_HOOKSHOT))*/
Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE, []{return logic->SpiritSunBlockSouthLedge();}),
Entrance(RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, []{return true/*str0 || SunlightArrows*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE] = Region("Spirit Temple Sun Block South ledge", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//Assumes RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM access
EventAccess(&logic->SpiritSunBlockTorch, []{return SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE, []{return true;}, true);}),
}, {
//Locations
//the blocks can be used to get all the silver rupees and the chest itemless
LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM,
[]{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW));})),
//Spawning the chest to get here is accounted for in movement logic, so we only need to confirm it can be spawned here
LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE,
[]{return logic->HasFireSource() ||
(logic->SpiritSunBlockTorch && (logic->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))));})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS] = Region("Spirit Temple Skulltula Stairs", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -283,10 +312,10 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_WEST_HAND_EXIT] = Region("Spirit Temple West Hand Exit", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_WEST_THRONE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_WEST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_OUTER_WEST_HAND, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_WEST_HAND] = Region("Spirit Temple West Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_OUTER_WEST_HAND] = Region("Spirit Temple West Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true),
}, {
@ -295,11 +324,7 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_DESERT_COLOSSUS, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST] = Region("Spirit Temple Statue Room East", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST access. WARNING: ZL spawning chests here is a temp flag
LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)),
}, {
areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST] = Region("Spirit Temple Statue Room East", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}),
@ -307,14 +332,40 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->SpiritEastToSwitch();}),
Entrance(RR_SPIRIT_TEMPLE_POT_STAIRS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4);}),
//!QUANTUM LOGIC!
//With 3 keys, you cannot lock adult out of longshotting to the west hand as you would have to
//open the west hand door and then adult could climb through sun block room
//With 3 keys, you cannot lock adult out of leaving spirit onto the hands and jumping down, as you would have to
//open the west hand door and then adult could climb through sun block room to jump down from there
//This requires that adult can complete both routes
//Implies CanKillEnemy(RE_IRON_KNUCKLE)
Entrance(RR_SPIRIT_TEMPLE_WEST_HAND, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_LONGSHOT) && logic->CanKillEnemy(RE_BEAMOS);}),
//Similarly, we can gurantee jumping into desert colossus the same way
//except this does not need the longshot as we don't care which hand we jump down from
Entrance(RR_DESERT_COLOSSUS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanKillEnemy(RE_BEAMOS);}),
Entrance(RR_DESERT_COLOSSUS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanKillEnemy(RE_BEAMOS)/* && CanClimb() && str0*/;}),
//!QUANTUM LOGIC!
//Continuing from above, if you also have the Longshot, then you can always reach the outer west hand, as you can longshot from east hand
Entrance(RR_SPIRIT_TEMPLE_OUTER_WEST_HAND, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanUse(RG_LONGSHOT) && logic->CanKillEnemy(RE_BEAMOS)/* && CanClimb() && str0*/;}),
//!QUANTUM LOGIC!
//A variant of the above, if dungeon entrance randomiser is off, Adult entered spirit in reverse, and they have str 2 to get there from the front,
//it is always possible for them to reach 1F_EAST with only 2 keys. This is because you can only waste 1 key (on the first child side lock)
//before you either allow you to climb down through 2F mirror room, or give yourself access to a hand to jump down from.
//If for whatever reason you can reach east hand but not west hand, this becomes possible with 3 keys instead.
//If for whatever reason you can reach west hand but not east hand, this becomes possible with 4 keys instead.
Entrance(RR_SPIRIT_TEMPLE_1F_EAST, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) &&
logic->CanUse(RG_SILVER_GAUNTLETS) &&
((logic->CanKillEnemy(RE_BEAMOS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, /*CanClimb() && str0 ?*/ 2 /*: 3*/)) ||
(/*CanClimb() && str0 && */logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 4)));}),
//RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}),
});
areaTable[RR_SPIRIT_TEMPLE_INNER_EAST_HAND] = Region("Spirit Temple Inner East Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//Assumes RR_SPIRIT_TEMPLE_INNER_WEST_HAND access via RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST and RR_SPIRIT_TEMPLE_STATUE_ROOM.
LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_HAND_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_INNER_EAST_HAND, []{return logic->CanUse(RG_ZELDAS_LULLABY)/* && CanClimb()*/;})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return logic->CanUse(RG_HOVER_BOOTS);}),
//Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST access via RR_SPIRIT_TEMPLE_STATUE_ROOM
Entrance(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)) ||
(logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanUse(RG_HOOKSHOT));}),
});
areaTable[RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH] = Region("Spirit Temple Shortcut Switch", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
@ -322,21 +373,21 @@ void RegionTable_Init_SpiritTemple() {
EventAccess(&logic->SpiritStatueRoomSouthDoor, []{return SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_MEGATON_HAMMER);});}),
}, {
//Locations
//Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST access
LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)),
//Assumes RR_SPIRIT_TEMPLE_INNER_EAST_HAND access
LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_ZELDAS_LULLABY);})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_SHORTCUT] = Region("Spirit Temple Shortcut", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//If child can ever use silver gauntlets and adult items, there needs to be an event here to account for child entering in reverse
//If child can ever use silver gauntlets, there needs to be an event here to account for child entering in reverse
//opening the way for adult entering via the front.
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_LOBBY, []{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_MEGATON_HAMMER);}),
});
areaTable[RR_SPIRIT_TEMPLE_POT_STAIRS] = Region("Spirit Temple Stairs to Beamos Pits", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_POT_STAIRS] = Region("Spirit Temple Pot Stairs", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
LOCATION(RC_SPIRIT_TEMPLE_BEAMOS_HALL_POT_1, logic->CanBreakPots()),
}, {
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4);}),
@ -346,18 +397,18 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_BEAMOS_PITS] = Region("Spirit Temple Beamos Pits", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
//Implies killing the anubis with the fire ring, doing so itemless requires voiding out, which can lock hardcore + OHKO seeds
Entrance(RR_SPIRIT_TEMPLE_POT_STAIRS, []{return logic->CanKillEnemy(RE_BEAMOS);}),
Entrance(RR_SPIRIT_TEMPLE_FOUR_ARMOS, []{return logic->CanKillEnemy(RE_BEAMOS);}),
Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_LOWER, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}),
Entrance(RR_SPIRIT_TEMPLE_POT_STAIRS, []{return logic->CanKillEnemy(RE_BEAMOS);}),
Entrance(RR_SPIRIT_TEMPLE_FOUR_ARMOS, []{return logic->CanKillEnemy(RE_BEAMOS);}),
Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_BASE, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}),
});
areaTable[RR_SPIRIT_TEMPLE_FOUR_ARMOS] = Region("Spirit Temple Four Armos", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->HasExplosives()),
LOCATION(RC_SPIRIT_TEMPLE_NEAR_FOUR_ARMOS_CHEST, (logic->CanUse(RG_MIRROR_SHIELD) || logic->SunlightArrows()) && logic->HasExplosives()),
LOCATION(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, logic->HasExplosives() && logic->CanUse(RG_SUNS_SONG)),
}, {
Entrance(RR_SPIRIT_TEMPLE_BEAMOS_PITS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_FOUR_ARMOS_SIDE_ROOM, []{return logic->CanUse(RG_MIRROR_SHIELD) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}),
Entrance(RR_SPIRIT_TEMPLE_FOUR_ARMOS_SIDE_ROOM, []{return logic->CanUse(RG_MIRROR_SHIELD) || logic->SunlightArrows();}),
Entrance(RR_SPIRIT_TEMPLE_CHEST_STAIRS, []{return true;}),
});
@ -387,24 +438,25 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_EAST_HAND_EXIT] = Region("Spirit Temple East hand Exit", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_EAST_THRONE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_EAST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_EAST_THRONE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_OUTER_EAST_HAND, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_EAST_HAND] = Region("Spirit Temple East Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_OUTER_EAST_HAND] = Region("Spirit Temple Outer East Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_EAST_HAND_EXIT, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_DESERT_COLOSSUS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_EAST_HAND_EXIT, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_OUTER_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_DESERT_COLOSSUS, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_BIG_WALL_LOWER] = Region("Spirit Temple Big Wall Lower", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SPIRIT_TEMPLE_BIG_WALL_BASE] = Region("Spirit Temple Big Wall Base", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_BEAMOS_PITS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_UPPER, []{return ctx->GetTrickOption(RT_SPIRIT_WALL) || (logic->CanAvoidEnemy(RE_BEAMOS, true, 2) && logic->CanPassEnemy(RE_WALLTULA));}),
Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_UPPER, []{return (ctx->GetTrickOption(RT_SPIRIT_WALL) || (logic->CanAvoidEnemy(RE_BEAMOS, true, 2) && logic->CanPassEnemy(RE_WALLTULA)))
/*&& CanClimbHigh()*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_BIG_WALL_UPPER] = Region("Spirit Temple Big Wall Upper", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -414,8 +466,8 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_ADULT_CLIMB_RIGHT_HEART, logic->CanUse(RG_HOOKSHOT)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_LOWER, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_BASE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_4F_CENTRAL] = Region("Spirit Temple 4F Central", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@ -439,27 +491,27 @@ void RegionTable_Init_SpiritTemple() {
//Events
EventAccess(&logic->Spirit4FSwitch, []{return logic->CanJumpslash() || logic->HasExplosives();}),
//Needs the mirror in the cave to be a perm flag and event for doorsanity
EventAccess(&logic->SpiritPlatformLowered, []{return (Here(RR_SPIRIT_TEMPLE_BIG_MIRROR_ROOM, []{return logic->CanJumpslash() || logic->HasExplosives();}) || logic->CanUse(RG_MIRROR_SHIELD)) ||
(ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}),
EventAccess(&logic->SpiritPlatformLowered, []{return (logic->SpiritPushed4FMirrors && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows();}),
}, {}, {
Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}),
//Rang can hit the switch on the way back but that's a trick
Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE, []{return logic->Spirit4FSwitch;}),
//Assumes RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE access
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return (logic->CanUse(RG_MIRROR_SHIELD) && logic->HasExplosives() && logic->Spirit4FSwitch) ||
(ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}),
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered;}),
});
areaTable[RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE] = Region("Spirit Temple Big Mirror Cave", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->Spirit4FSwitch, []{return logic->HasExplosives();}),
EventAccess(&logic->Spirit4FSwitch, []{return logic->HasExplosives();}),
//WARNING: not currently a permanent flag, needs to be one for doorsanity
EventAccess(&logic->SpiritPushed4FMirrors, []{return logic->HasExplosives()/*&& str0*/;}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))),
LOCATION(RC_SPIRIT_TEMPLE_TOPMOST_CHEST, (logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows()),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_ROOM, []{return true;}),
});
//Assumes a SpiritPlatformLowered check on entry
@ -467,9 +519,10 @@ void RegionTable_Init_SpiritTemple() {
//Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_HEAD, []{return Here(RR_SPIRIT_TEMPLE_STATUE_HEAD, []{return logic->CanUse(RG_MIRROR_SHIELD) && logic->HasExplosives() && logic->Spirit4FSwitch;})
&& logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_INNER_EAST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_HEAD, []{return logic->SpiritPushed4FMirrors && logic->CanUse(RG_HOOKSHOT);}),
});
areaTable[RR_SPIRIT_TEMPLE_STATUE_HEAD] = Region("Spirit Temple Statue Head", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
@ -480,8 +533,8 @@ void RegionTable_Init_SpiritTemple() {
}, {}, {
// Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{return logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_INNER_WEST_HAND, []{return logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_INNER_EAST_HAND, []{return logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
});
@ -503,7 +556,7 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild/*logic->CanUse(RG_CRAWL) && logic->HasSoul(RG_NABOORU_SOUL)*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return false;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH, []{return logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_BOMBCHU_5);}),
});
@ -520,9 +573,11 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_RIGHT_HEART, logic->CanHitEyeTargets()),
}, {
//Exits
//Nabooru's legs are technically visible one way collision here, but I'm not sure if this counts
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->IsChild/*logic->CanUse(RG_CRAWL)*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return Here(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->CanKillEnemy(RE_TORCH_SLUG);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->IsChild && logic->MQSpiritCrawlBoulder;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->IsChild/*logic->CanUse(RG_CRAWL)*/ && logic->MQSpiritCrawlBoulder;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_SOUTH] = Region("Spirit Temple MQ 1F Gibdo Room South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
@ -531,7 +586,7 @@ void RegionTable_Init_SpiritTemple() {
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH, []{return logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets();}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH, []{return logic->CanUse(RG_BOMBCHU_5) && logic->CanHitEyeTargets()/* && str0*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH] = Region("Spirit Temple MQ Gibdo Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -543,7 +598,7 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->MQSpiritGibdosCleared;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM] = Region("Spirit Temple Turntable Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
areaTable[RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM] = Region("Spirit Temple MQ Turntable Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->FairyPot, []{return Here(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
}, {
@ -561,7 +616,8 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_NORTH] = Region("Spirit Temple MQ Map Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQSpiritMapRoomEnemies, []{return logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE);}),
EventAccess(&logic->MQSpiritMapRoomEnemies, []{return /*(*/logic->CanKillEnemy(RE_ANUBIS) && logic->CanKillEnemy(RE_KEESE)/*) && (str0 || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT)) ||
logic->CanKillEnemy(RE_ANUBIS, ED_BOOMERANG) && logic->CanKillEnemy(RE_KEESE, ED_FAR)*/;}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->MQSpiritMapRoomEnemies),
@ -569,7 +625,7 @@ void RegionTable_Init_SpiritTemple() {
//Exits
//Stalfos room blocks you in with fire until you kill the stalfos, which won't spawn from behind the fire
Entrance(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return false;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH, []{return true/*str0 || CanUse(RG_HOVER_BOOTS) || CanUse(RG_HOOKSHOT)*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_MAP_ROOM_SOUTH] = Region("Spirit Temple MQ Map Room South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
@ -592,7 +648,7 @@ void RegionTable_Init_SpiritTemple() {
EventAccess(&logic->MQSpiritCrawlBoulder, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild && logic->MQSpiritCrawlBoulder;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return logic->IsChild/*logic->CanUse(RG_CRAWL)*/ && logic->MQSpiritCrawlBoulder;}),
//This tracks possible child access, if adult has not entered STATUE_ROOM. Certain Child Access is checked for separately as 7 Keys
Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}),
});
@ -602,9 +658,9 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_LIKE_LIKE_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanBreakPots();})),
}, {
//Exits
//This covers adult access only, as child arrives here from the other side of this door
//This covers adult and reverse access only, as child going forwards arrives here from the other side of this door
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanHitSwitch();}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanHitSwitch()/* && CanClimbHigh()*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM] = Region("Spirit Temple MQ Broken Wall Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -612,37 +668,81 @@ void RegionTable_Init_SpiritTemple() {
//Implies CanKillEnemy(RE_LIKE_LIKE)
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_NORTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->CanKillEnemy(RE_BEAMOS);})),
//Sunlights only temp spawn this chest, which is unintuitive/a bug.
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return (logic->HasExplosives() || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS))) && logic->CanUse(RG_HOOKSHOT);})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_CLIMB_SOUTH_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return (logic->HasExplosives() || logic->SunlightArrows()) && logic->CanUse(RG_HOOKSHOT);})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanHitSwitch();}),
//This exit only governs child possible access, adult access starts on the other side so never checks this
//This exit only governs child forwards access, adult and reverse access starts on the other side so never checks this
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 2);}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST] = Region("Spirit Temple MQ Statue Room West", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->SpiritStatueRoomSouthDoor, []{return SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return ctx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME);});}),
}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST] = Region("Spirit Temple MQ Statue Room West", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_EAST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return ((logic->IsAdult || logic->CanJumpslash()) && logic->CanUse(RG_BOOMERANG)) ||
((logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) && logic->CanBreakPots());})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_WEST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return ((logic->IsAdult || logic->CanJumpslash()) && logic->CanUse(RG_BOOMERANG) && ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE)) ||
(logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)) && logic->CanBreakPots());})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_SMALL_CRATE, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return logic->CanBreakSmallCrates();})),
}, {
//Exits
//Minimal entry, real key logic handled in Shared functions
Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6);}),
//IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || CanUse(RG_SONG_OF_TIME)
Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, []{return logic->MQSpiritStatueToSunBlock();}),
//!QUANTUM LOGIC!
//If we entered in reverse and dungeon entrances are off, we only need 6 keys, access to Gauntlets Hand and the ability to crawl to reach colossus
//This is because with 6 keys it becomes impossible to avoid opening either the west hand lock or the first child side lock
//and either direction lets child reach colossus. CanHitSwitch and CanKillEnemy(RE_IRON_KNUCKLE) is implied.
//Logic can then allow child back into spirit, putting 1F west in logic with only 6 keys without forwards entry
Entrance(RR_DESERT_COLOSSUS, []{return logic->IsChild/*CanUse(RG_CRAWL)*/ && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) &&
logic->ReverseSpiritChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 6) && /*(str0 || SunlightArrows())&&*/
(logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER)));}),
//!QUANTUM LOGIC!
//If we have 6 keys and Child reverse spirit entry, we can gurantee broken wall room access for Child
//as long as we can hit a switch and because Adult cannot reach the initial child lock without
//first opening the Statue Room to Broken Wall Room lock. The details of this are handled in SpiritShared.
//if adult can ever cross crawlspaces this becomes more complicated.
Entrance(RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND, []{return logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS);}),
//(IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || CanUse(RG_SONG_OF_TIME)) && str0
Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, []{return logic->MQSpiritStatueToSunBlock();}),
//explicit adult check here is a precaution against possible child logic leaking, child with a hookshot can do this
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return logic->IsAdult && logic->CanUse(RG_HOOKSHOT);}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_POT_LEDGE] = Region("Spirit Temple MQ Pot Ledge", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//This event does not need handling in SpiritShared as it only affects navigation, adult access here is always Certain, and Child has no way through that Adult does not.
EventAccess(&logic->SpiritStatueRoomSouthDoor, []{return ctx->GetTrickOption(RT_SPIRIT_MQ_FROZEN_EYE) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_SONG_OF_TIME);}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_EAST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE , []{return logic->CanBreakPots();}, false,
RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND , []{return logic->CanUse(RG_BOOMERANG);})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_WEST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE , []{return logic->CanBreakPots();}, false,
RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND , []{return ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE) && logic->CanUse(RG_BOOMERANG);})),
}, {
//Exits
//This is pretty tight to reach the SoT block, but you can just go via the hand...
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND] = Region("Spirit Temple MQ Inner West Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_EAST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND, []{return logic->CanUse(RG_BOOMERANG);}, false,
RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, []{return logic->CanBreakPots();})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_3F_WEST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND, []{return logic->CanUse(RG_BOOMERANG) && ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE);}, false,
RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, []{return logic->CanBreakPots();})),
}, {
//Exits
//Land on the SoT block
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_POT_LEDGE, []{return logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP);}),
// RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled
Entrance(RR_SPIRIT_TEMPLE_MQ_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM] = Region("Spirit Temple MQ Statue Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->SpiritStatueRoomSouthDoor, []{return SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->HasFireSource();});}),
//This event does not need handling in SpiritShared as it only affects navigation, Adult access here is always Certain, and Child has no way through that adult does not.
EventAccess(&logic->SpiritStatueRoomSouthDoor, []{return logic->HasFireSource();}),
//Assuming all higher areas filter down to here for this despite there being many good angles to use FAs
EventAccess(&logic->MQSpiritStatueRoomTorches, []{return logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE));}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets();})),
@ -651,15 +751,16 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_2F_EASTMOST_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakPots();})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_CRATE_1, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakCrates();})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_CRATE_2, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanBreakCrates();})),
//the drop sometimes flies off the block when the crate is blown up, but not always, so I added a rang requirement
//a trick to reload for it is plausible
//The drop sometimes flies off the block when the crate is blown up, but not always, so I added a rang requirement
//A trick to reload for it is plausible
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_SMALL_CRATE, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return (logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()) ||
(logic->CanUse(RG_BOOMERANG) && logic->HasExplosives());})),
(logic->CanUse(RG_BOOMERANG) && logic->HasExplosives());})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return true/*logic->CanClimb()*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return logic->SpiritStatueRoomSouthDoor;}),
//explicit adult check here is a precaution against possible child logic leaking, child with a hookshot can do this
//explicit adult check here is a precaution against possible Child logic leaking, Child with a hookshot can do this
//It's possible to climb the legs of the statue to line up a longshot hit, but you can just go via West
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return logic->IsAdult && logic->CanUse(RG_SCARECROW);}),
});
@ -672,14 +773,14 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM] = Region("Spirit Temple MQ Sun Block Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//We don't need Shared here because If we are checking as child, universe 2 adult access needs nothing so it always passes, and if we are checking as adult, it is Certain Access
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritMQSharedSunBlockRoom([]{return true/*str0*/;})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, SpiritMQSharedSunBlockRoom([]{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_1, SpiritMQSharedSunBlockRoom([]{return logic->CanBreakPots();})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_2, SpiritMQSharedSunBlockRoom([]{return logic->CanBreakPots();})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return true/*str0*/;})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SUN_BLOCK_ROOM, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanUse(RG_HOOKSHOT) || (ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_GS) && logic->CanUse(RG_BOOMERANG));})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_1, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})),
LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_2, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, []{return true/*str0*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS, []{return true/*str0*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS, []{return true/*str0 || SunlightArrows()*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS , []{return true/*str0 || SunlightArrows()*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS] = Region("Spirit Temple MQ Skulltula Stairs", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@ -697,11 +798,11 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_HAND_EXIT] = Region("Spirit Temple MQ West Hand Exit", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_THRONE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_THRONE , []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_WEST_HAND, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_HAND] = Region("Spirit Temple MQ West Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_WEST_HAND] = Region("Spirit Temple MQ Outer West Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true),
}, {
@ -716,44 +817,77 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return true;}),
//The block here is unusual in that it is a permanent flag, but reset anyway as child. This is because there's a check that would be blocked off by pushing them otherwise
//It may be worth considering making this always temp in future so adult doesn't have the same issue
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return logic->IsChild ? logic->CanUse(RG_SILVER_GAUNTLETS) : Here(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanUse(RG_SILVER_GAUNTLETS);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return logic->IsChild ? logic->CanUse(RG_SILVER_GAUNTLETS) : Here(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH, []{return logic->CanUse(RG_SILVER_GAUNTLETS);});}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH] = Region("Spirit Temple MQ Block Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//Dhard child locked because adult pushing the block is a permanent flag that blocks the eye target and cannot be undone
LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, SpiritMQSharedBigBlock([]{return logic->IsChild && logic->CanHitEyeTargets();})),
//Hard child locked because pushing the block is a permanent flag that blocks the eye target and cannot be undone
//but it resets as Child as a rando QoL feature
LOCATION(RC_SPIRIT_TEMPLE_MQ_SILVER_BLOCK_HALLWAY_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return logic->IsChild && logic->CanHitEyeTargets();})),
}, {
//Exits
//if going to RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH from here is ever relevant, there needs to be an event to handle the block
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST] = Region("Spirit Temple MQ Statue Room East", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_HOOKSHOT) & logic->CanUse(RG_ZELDAS_LULLABY) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))),
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))),
}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST] = Region("Spirit Temple MQ Statue Room East", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_EAST_HAND, []{return logic->IsAdult || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) ||
((ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_LONGSHOT));}),
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, []{return logic->MQSpiritStatueRoomTorches;}),
//!QUANTUM LOGIC!
//We only need 4 keys, access to Shield hand and longshot to reach Gauntlets hand, as if we waste the 5th key we have given ourselves Gauntlets hand access through child climb
//This exit handles that possibility as cleanly as possible without quantum logic, but will not survive glitch logic
//We only need 4 keys and the ability to reach both hands for adult to logically be able to drop down onto Desert Colossus
//This is because there are only 3 keys that can be wasted without opening up either this lock to East hand, or the West Hand lock through Sun Block Room
//and both directions allow you to drop onto colossus
//logic->CanKillEnemy(RE_FLOORMASTER) is implied
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_HAND, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) &&
Entrance(RR_DESERT_COLOSSUS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) &&
logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) &&
logic->CanJumpslash() &&
logic->CanJumpslash() && /*(str0 || SunlightArrows) &&*/
(ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) &&
logic->CanKillEnemy(RE_IRON_KNUCKLE) &&
logic->CanUse(RG_LONGSHOT);}),
logic->CanUse(RG_HOOKSHOT);}),
//!QUANTUM LOGIC!
//Continuing from above, if we also have a longshot, we can go from the East hand to the West hand, meaning we always have access to East Hand
Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_WEST_HAND, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) &&
logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) &&
logic->CanJumpslash() && /*(str0 || SunlightArrows) &&*/
(ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) &&
logic->CanKillEnemy(RE_IRON_KNUCKLE) &&
logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, []{return logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MQ_LOWER_ADULT) && logic->CanUse(RG_DINS_FIRE));}),
// RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled
Entrance(RR_SPIRIT_TEMPLE_MQ_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_INNER_EAST_HAND] = Region("Spirit Temple MQ Inner East Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_LULLABY_CHEST, logic->CanUse(RG_ZELDAS_LULLABY) && logic->CanBreakCrates()),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE, []{return ((logic->IsAdult || ctx->GetTrickOption(RT_SPIRIT_WEST_LEDGE)) && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT))
|| (logic->IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP));}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE] = Region("Spirit Temple MQ Chest Ledge", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_ROOM_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_EAST_HAND, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F] = Region("Spirit Temple MQ Three Suns Room 2F", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//implies logic->CanKillEnemy(RE_WALLMASTER). If we have lights, we can kill stalfos and wallmasters with bow
EventAccess(&logic->MQSpirit3SunsEnemies, []{return (logic->CanUse(RG_MIRROR_SHIELD) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)) || (ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}),
EventAccess(&logic->MQSpirit3SunsEnemies, []{return (logic->CanUse(RG_MIRROR_SHIELD) && logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2)) || logic->SunlightArrows();}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return true;}),
@ -762,7 +896,8 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F] = Region("Spirit Temple MQ Three Suns Room 1F", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, []{return logic->MQSpirit3SunsEnemies;}),
//It is possible to clip through here with longshot by aiming high enough
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F, []{return logic->MQSpirit3SunsEnemies/* && CanClimbHigh()*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return true;}),
});
@ -776,10 +911,10 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_POT_2, logic->CanBreakPots()),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SAND_PIT, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SAND_PIT, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SAND_PIT] = Region("Spirit Temple MQ Sand Pit", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -791,11 +926,22 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM] = Region("Spirit Temple MQ Symphony Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER] = Region("Spirit Temple MQ Symphony Room Upper", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQSpiritSymphonyRoomDoor, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) &&
logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY);}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
//Implies CanPassEnemy(RE_MOBLIN_CHIEF)
Entrance(RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_EPONAS_SONG) && logic->CanUse(RG_SUNS_SONG) && logic->CanUse(RG_SONG_OF_STORMS) && logic->CanUse(RG_ZELDAS_LULLABY);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_LOWER, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_LOWER] = Region("Spirit Temple MQ Symphony Room Lower", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER, []{return true/*CanClimb()*/;}),
//Implies CanPassEnemy(RE_MOBLIN_CHIEF)
Entrance(RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM, []{return logic->MQSpiritSymphonyRoomDoor;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM] = Region("Spirit Temple MQ After Symphony Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -804,7 +950,7 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER] = Region("Spirit Temple MQ Fire Wall Stairs Lower", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@ -816,17 +962,17 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER] = Region("Spirit Temple MQ Fire Wall Stairs Upper", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER, []{return logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM] = Region("Spirit Temple MQ Four Beamos Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS] = Region("Spirit Temple MQ Beamos Pits", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS)),
LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanKillEnemy(RE_BEAMOS) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()),
LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_SMALL_CRATE, logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME) && logic->CanBreakSmallCrates()),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME)/* && str0*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return logic->CanAvoidEnemy(RE_BEAMOS, true, 4) && logic->CanUse(RG_SONG_OF_TIME)/* && str0*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_LOWER, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6);}),
});
@ -836,36 +982,36 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return logic->CanJumpslash();}),
Entrance(RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM, []{return Here(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return (logic->IsAdult || logic->CanUse(RG_SONG_OF_TIME)) && logic->CanUse(RG_MIRROR_SHIELD);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_FLOORMASTER_STAIRS, []{return logic->CanJumpslash();}),
Entrance(RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM, []{return Here(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return (logic->IsAdult || logic->CanUse(RG_SONG_OF_TIME)) && logic->CanUse(RG_MIRROR_SHIELD);});}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND] = Region("Spirit Temple MQ East Stairs to Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_FLOORMASTER_STAIRS] = Region("Spirit Temple MQ Floormaster Stairs", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, []{return (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && Here(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return logic->CanKillEnemy(RE_FLOORMASTER);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_THRONE, []{return (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && Here(RR_SPIRIT_TEMPLE_MQ_FLOORMASTER_STAIRS, []{return logic->CanKillEnemy(RE_FLOORMASTER);});}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE] = Region("Spirit Temple MQ East Iron Knuckle", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_EAST_THRONE] = Region("Spirit Temple MQ East Throne", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EXIT_TO_MIRROR_SHIELD_HAND, []{return Here(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_FLOORMASTER_STAIRS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_HAND_EXIT, []{return Here(RR_SPIRIT_TEMPLE_MQ_EAST_THRONE, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);});}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_EXIT_TO_MIRROR_SHIELD_HAND] = Region("Spirit Temple MQ Exit To Mirror Shield Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, []{return true;}),
areaTable[RR_SPIRIT_TEMPLE_MQ_EAST_HAND_EXIT] = Region("Spirit Temple MQ East Hand Exit", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_THRONE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_EAST_HAND, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND] = Region("Spirit Temple MQ Mirror Shield Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_OUTER_EAST_HAND] = Region("Spirit Temple MQ Outer East Hand", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, []{return true;}),
Entrance(RR_DESERT_COLOSSUS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_THRONE, []{return true;}),
Entrance(RR_DESERT_COLOSSUS, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM] = Region("Spirit Temple MQ 3F Gibdo Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -882,16 +1028,19 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_LONG_CLIMB_POT_2, logic->CanBreakPots()),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS, []{return true;}),
//technically we only need to avoid them, but the sheer height and the moving walls makes getting to the top after only stunning them very difficult/impossible
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return logic->CanKillEnemy(RE_KEESE);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return /*(*/logic->CanKillEnemy(RE_KEESE)/*|| CanUse(RG_SKULL_MASK)) && CanClimbHigh()*/;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER] = Region("Spirit Temple MQ Big Wall Upper", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER] = Region("Spirit Temple MQ Big Wall Upper", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//Getting some of these with just climbing downwards is theoretically possible but definitly a trick
EventAccess(&logic->MQSpiritBigWallSilvers, []{return /*(*/logic->CanKillEnemy(RE_KEESE)/*|| CanUse(RG_SKULL_MASK)) && CanClimbHigh()*/;}),
}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_LOWER, []{return true;}),
//The silver rupees are irrelevant without silver shuffle
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, []{return logic->MQSpiritBigWallSilvers;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL] = Region("Spirit Temple MQ 4F Central", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -900,12 +1049,12 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_BEFORE_MIRROR_POT_2, logic->CanBreakPots()),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_NINE_THRONES_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM] = Region("Spirit Temple MQ Nine Chairs Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_NINE_THRONES_ROOM] = Region("Spirit Temple MQ Nine Thrones Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
//These skulls rely on the iron knuckle existing without a trick to shoot through the chairs
LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_NINE_THRONES_ROOM_WEST, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
@ -917,7 +1066,8 @@ void RegionTable_Init_SpiritTemple() {
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM] = Region("Spirit Temple MQ Big Mirror Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
EventAccess(&logic->MQSpiritOpenedBigMirrorCave, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
//Needs the mirror in the cave to be a perm flag and event for doorsanity
EventAccess(&logic->SpiritPlatformLowered, []{return (logic->SpiritPushed4FMirrors && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows();}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_BIG_MIRROR_POT_1, logic->CanBreakPots()),
@ -931,18 +1081,31 @@ void RegionTable_Init_SpiritTemple() {
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, []{return logic->MQSpiritOpenedBigMirrorCave;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, []{return Here(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_PLATFORM, []{return logic->SpiritPlatformLowered;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE] = Region("Spirit Temple MQ Big Mirror Cave", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE] = Region("Spirit Temple MQ Big Mirror Cave", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events
//WARNING: Not currently a permanent flag, needs to be one for doorsanity
EventAccess(&logic->SpiritPushed4FMirrors, []{return ((logic->IsAdult && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows())/* && str0*/;}),
}, {
//Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)),
}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return logic->MQSpiritOpenedBigMirrorCave;}),
//If it's ever relevant to longshot into head from lobby, this needs to be an event access
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD, []{return Here(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, []{return logic->CanUse(RG_MIRROR_SHIELD);}) && logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return Here(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, []{return logic->CanUse(RG_MIRROR_SHIELD);});}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return true;}),
});
//Assumes SpiritPlatformLowered is checked on entry
areaTable[RR_SPIRIT_TEMPLE_MQ_PLATFORM] = Region("Spirit Temple MQ Platform", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD, []{return logic->SpiritPushed4FMirrors && logic->CanUse(RG_MIRROR_SHIELD) && logic->CanUse(RG_HOOKSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_EAST_HAND, []{return true;}),
});
areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD] = Region("Spirit Temple MQ Statue Head", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
@ -952,8 +1115,11 @@ void RegionTable_Init_SpiritTemple() {
EventAccess(&logic->ReverseSpiritAdult, []{return logic->IsAdult;}),
}, {}, {
// Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND, []{return logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_INNER_EAST_HAND, []{return logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_PLATFORM, []{return logic->SpiritPlatformLowered && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT));}),
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
});
#pragma endregion

View file

@ -1286,6 +1286,10 @@ bool Logic::HasFireSourceWithTorch() {
return HasFireSource() || CanUse(RG_STICKS);
}
bool Logic::SunlightArrows() {
return ctx->GetOption(RSK_SUNLIGHT_ARROWS) && CanUse(RG_LIGHT_ARROWS);
}
// Is this best off signaling what you have already traded, or what step you are currently on?
bool Logic::TradeQuestStep(RandomizerGet rg) {
if (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE)) {
@ -2376,8 +2380,19 @@ bool Logic::SpiritWestToSkull() {
return (IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_SCARECROW);
}
bool Logic::SpiritSunBlockSouthLedge() {
return true/*str0 || IsAdult || CanKillEnemy(RE_BEAMOS) || BunnyHovers() ||
(CanUse(RG_HOOKSHOT) && (HasFireSource() ||
(SpiritSunBlockTorch && (logic->CanUse(STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))))))*/;
}
//Combines crossing the ledge directly and the jump from the hand
bool Logic::MQSpiritWestToPots() {
return (IsAdult && ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)) || CanUse(RG_HOVER_BOOTS) || CanUse(RG_SONG_OF_TIME);
}
bool Logic::MQSpiritStatueToSunBlock() {
return IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || CanUse(RG_SONG_OF_TIME);
return (IsAdult || ctx->GetTrickOption(RT_SPIRIT_MQ_SUN_BLOCK_SOT) || CanUse(RG_SONG_OF_TIME))/* && str0*/;
}
bool Logic::MQSpiritStatueSouthDoor() {
@ -2570,18 +2585,20 @@ void Logic::Reset() {
MQSpiritCrawlBoulder = false;
MQSpiritMapRoomEnemies = false;
MQSpiritTimeTravelChest = false;
MQSpiritStatueRoomTorches = false;
MQSpirit3SunsEnemies = false;
MQSpiritOpenedBigMirrorCave = false;
MQSpiritSymphonyRoomDoor = false;
MQSpiritBigWallSilvers = false;
Spirit1FSilverRupees = false;
SpiritChildSwitchBridge = false;
SpiritRupeeBridge = false;
SpiritBouldersSilvers = false;
SpiritPlatformLowered = false;
Spirit4FSwitch = false;
SpiritPushed4FMirrors = false;
ReverseSpiritChild = false;
ReverseSpiritAdult = false;
StopPerformanceTimer(PT_LOGIC_RESET);
}
} // namespace Rando

View file

@ -180,15 +180,19 @@ class Logic {
bool MQSpiritCrawlBoulder = false;
bool MQSpiritMapRoomEnemies = false;
bool MQSpiritTimeTravelChest = false;
bool MQSpiritStatueRoomTorches = false;
bool MQSpirit3SunsEnemies = false;
bool MQSpiritOpenedBigMirrorCave = false;
bool MQSpiritSymphonyRoomDoor = false;
bool MQSpiritBigWallSilvers = false;
bool Spirit1FSilverRupees = false;
bool SpiritChildSwitchBridge = false;
bool SpiritRupeeBridge = false;
bool SpiritSunBlockTorch = false;
bool SpiritBouldersSilvers = false;
bool SpiritStatueRoomSouthDoor = false;
bool SpiritPlatformLowered = false;
bool Spirit4FSwitch = false;
bool SpiritPushed4FMirrors = false;
bool ReverseSpiritChild = false;
bool ReverseSpiritAdult = true;
@ -258,6 +262,7 @@ class Logic {
bool CanBreakSmallCrates();
bool HasFireSource();
bool HasFireSourceWithTorch();
bool SunlightArrows();
bool TradeQuestStep(RandomizerGet rg);
bool CanFinishGerudoFortress();
bool CanStandingShield();
@ -299,12 +304,14 @@ class Logic {
static std::map<uint32_t, uint32_t> RandoGetToDungeonScene;
static std::map<RandomizerGet, uint32_t> RandoGetToEquipFlag;
static std::map<RandomizerGet, uint32_t> RandoGetToRandInf;
bool Logic::IsReverseAccessPossible();
bool Logic::SpiritBrokenWallToStatue();
bool Logic::SpiritEastToSwitch();
bool Logic::SpiritWestToSkull();
bool Logic::MQSpiritStatueToSunBlock();
bool Logic::MQSpiritStatueSouthDoor();
bool IsReverseAccessPossible();
bool SpiritBrokenWallToStatue();
bool SpiritEastToSwitch();
bool SpiritWestToSkull();
bool SpiritSunBlockSouthLedge();
bool MQSpiritWestToPots();
bool MQSpiritStatueToSunBlock();
bool MQSpiritStatueSouthDoor();
private:
std::shared_ptr<Context> ctx;

View file

@ -864,16 +864,19 @@ typedef enum {
RR_SPIRIT_TEMPLE_2F_MIRROR,
RR_SPIRIT_TEMPLE_STATUE_ROOM,
RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST,
RR_SPIRIT_TEMPLE_INNER_WEST_HAND,
RR_SPIRIT_TEMPLE_GS_LEDGE,
RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST,
RR_SPIRIT_TEMPLE_INNER_EAST_HAND,
RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH,
RR_SPIRIT_TEMPLE_SHORTCUT,
RR_SPIRIT_TEMPLE_EMPTY_STAIRS,
RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM,
RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE,
RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS,
RR_SPIRIT_TEMPLE_WEST_THRONE,
RR_SPIRIT_TEMPLE_WEST_HAND_EXIT,
RR_SPIRIT_TEMPLE_WEST_HAND,
RR_SPIRIT_TEMPLE_OUTER_WEST_HAND,
RR_SPIRIT_TEMPLE_POT_STAIRS,
RR_SPIRIT_TEMPLE_BEAMOS_PITS,
RR_SPIRIT_TEMPLE_FOUR_ARMOS,
@ -881,8 +884,8 @@ typedef enum {
RR_SPIRIT_TEMPLE_CHEST_STAIRS,
RR_SPIRIT_TEMPLE_EAST_THRONE,
RR_SPIRIT_TEMPLE_EAST_HAND_EXIT,
RR_SPIRIT_TEMPLE_EAST_HAND,
RR_SPIRIT_TEMPLE_BIG_WALL_LOWER,
RR_SPIRIT_TEMPLE_OUTER_EAST_HAND,
RR_SPIRIT_TEMPLE_BIG_WALL_BASE,
RR_SPIRIT_TEMPLE_BIG_WALL_UPPER,
RR_SPIRIT_TEMPLE_4F_CENTRAL,
RR_SPIRIT_TEMPLE_FAKE_DOORS_ROOM,
@ -901,38 +904,44 @@ typedef enum {
RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH,
RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE,
RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST,
RR_SPIRIT_TEMPLE_MQ_INNER_WEST_HAND,
RR_SPIRIT_TEMPLE_MQ_POT_LEDGE,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM,
RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_STAIRS,
RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM,
RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS,
RR_SPIRIT_TEMPLE_MQ_WEST_THRONE,
RR_SPIRIT_TEMPLE_MQ_WEST_HAND_EXIT,
RR_SPIRIT_TEMPLE_MQ_WEST_HAND,
RR_SPIRIT_TEMPLE_MQ_OUTER_WEST_HAND,
RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH,
RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST,
RR_SPIRIT_TEMPLE_MQ_INNER_EAST_HAND,
RR_SPIRIT_TEMPLE_MQ_CHEST_LEDGE,
RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_2F,
RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F,
RR_SPIRIT_TEMPLE_MQ_1F_EAST,
RR_SPIRIT_TEMPLE_MQ_SAND_PIT,
RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM,
RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_UPPER,
RR_SPIRIT_TEMPLE_MQ_SYMPHONY_ROOM_LOWER,
RR_SPIRIT_TEMPLE_MQ_AFTER_SYMPHONY_ROOM,
RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER,
RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER,
RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM,
RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS,
RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM,
RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND,
RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE,
RR_SPIRIT_TEMPLE_MQ_EXIT_TO_MIRROR_SHIELD_HAND,
RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND,
RR_SPIRIT_TEMPLE_MQ_FLOORMASTER_STAIRS,
RR_SPIRIT_TEMPLE_MQ_EAST_THRONE,
RR_SPIRIT_TEMPLE_MQ_EAST_HAND_EXIT,
RR_SPIRIT_TEMPLE_MQ_OUTER_EAST_HAND,
RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_WALL_LOWER,
RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER,
RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL,
RR_SPIRIT_TEMPLE_MQ_NINE_CHAIRS_ROOM,
RR_SPIRIT_TEMPLE_MQ_NINE_THRONES_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE,
RR_SPIRIT_TEMPLE_MQ_PLATFORM,
RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD,
RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY,