v0 complete

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

View file

@ -213,127 +213,177 @@ bool Here(const RandomizerRegion region, ConditionFn condition) {
uint8_t SpiritExplosiveLogic() { uint8_t SpiritExplosiveLogic() {
return logic->SpiritBrokenWallToStatue() ? 1 : ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() ? 2 : 3; 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 * 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 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 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. * 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, * 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, * The universes converge when the player has all the keys, giving both ages Certain Access everywhere.
* 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.
* We must check for these universes manually as we allow technical access with minimum keys for * 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]; SpiritLogicData curRegionData = Region::spiritLogicData[region];
uint8_t childKeys = logic->ReverseSpiritChild ? curRegionData.childReverseKeys : curRegionData.childKeys; bool result = false;
// 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 // store current age variables
bool pastAdult = logic->IsAdult; bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild; 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);
//Switch back to adult to check adult access
logic->IsChild = false; logic->IsChild = false;
logic->IsAdult = true; 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 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 // 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 && (otherRegion != RR_NONE &&
(otherRegionData.adultAccess && (!logic->IsReverseAccessPossible() || otherRegionData.reverseAccess) && otherCondition())); (Region::spiritLogicData[otherRegion].adultAccess() &&
(!logic->IsReverseAccessPossible() || Region::spiritLogicData[otherRegion].reverseAccess()) &&
logic->IsChild = pastChild; otherCondition())) ||
logic->IsAdult = pastAdult; (thirdRegion != RR_NONE &&
(Region::spiritLogicData[thirdRegion].adultAccess() &&
return result; (!logic->IsReverseAccessPossible() || Region::spiritLogicData[thirdRegion].reverseAccess()) &&
thirdCondition()));
} }
} else if (areaTable[region].Adult() && logic->IsAdult) { } else if (areaTable[region].Adult() && pastAdult) {
bool result = condition(); result = condition();
// if we have enough keys to have Certain Access, we just run the 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 // Alternatively, if we have entered in reverse and can reach from the face, we have Certain Access
if (AdultCertainAccess) { // Otherwise, if we have the keys to know either age can reach, we need to see if we could reach as Child
return result; // and if needed, in reverse
// Otherwise, if we have the keys to know either age can reach, we need to see if we could reach as Child too if (!AdultCertainAccess && result && (!logic->IsReverseAccessPossible() || Region::spiritLogicData[otherRegion].reverseAccess)){
} else if (result){ //Switch to Child
SpiritLogicData otherRegionData = Region::spiritLogicData[otherRegion];
// store current age variables
bool pastAdult = logic->IsAdult;
bool pastChild = logic->IsChild;
logic->IsChild = true; logic->IsChild = true;
logic->IsAdult = false; logic->IsAdult = false;
// If Child can get there and get the check, we can get the check in logic // 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 // 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 && (otherRegion != RR_NONE &&
(otherRegionData.childAccess && (!logic->IsReverseAccessPossible() || otherRegionData.reverseAccess) && otherCondition())); (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()));
}
}
// set back age variables
logic->IsChild = pastChild; logic->IsChild = pastChild;
logic->IsAdult = pastAdult; logic->IsAdult = pastAdult;
return result; return result;
} }
}
return false;
}
bool BeanPlanted(const RandomizerRegion region) { bool BeanPlanted(const RandomizerRegion region) {
// swchFlag found using the Actor Viewer to get the Obj_Bean parameters & 0x3F // swchFlag found using the Actor Viewer to get the Obj_Bean parameters & 0x3F

View file

@ -252,9 +252,6 @@ class Region {
} }
static std::map<RandomizerRegion, SpiritLogicData> spiritLogicData; 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; extern std::array<Region, RR_MAX> areaTable;
@ -264,7 +261,8 @@ bool Here(const RandomizerRegion region,
ConditionFn ConditionFn
condition); // RANDOTODO make a less stupid way to check own at either age than self referencing with this 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, 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 CanPlantBean(const RandomizerRegion region);
bool BothAges(const RandomizerRegion region); bool BothAges(const RandomizerRegion region);
bool ChildCanAccess(const RandomizerRegion region); bool ChildCanAccess(const RandomizerRegion region);

View file

@ -23,7 +23,7 @@ void RegionTable_Init_SpiritTemple() {
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}), 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);}), 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;}), EventAccess(&logic->NutCrate, []{return true;}),
}, {}, { }, {}, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_LOBBY, []{return logic->IsChild;}), Entrance(RR_SPIRIT_TEMPLE_LOBBY, []{return logic->IsChild/*CanUse(RG_CRAWL)*/;}),
Entrance(RR_SPIRIT_TEMPLE_1F_BOXES, []{return logic->IsChild;}), 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_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);});}), 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, { areaTable[RR_SPIRIT_TEMPLE_SWITCH_BRIDGE_SOUTH] = Region("Spirit Temple Switch Bridge South", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //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));}), 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 //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, { areaTable[RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_NORTH] = Region("Spirit Temple Rupee Bridge North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //Events
EventAccess(&logic->SpiritRupeeBridge, []{return true;}), EventAccess(&logic->SpiritRupeeBridge, []{return true/*CanClimb()*/;}),
}, { }, {
//Locations //Locations
// these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust // these assume SpiritRupeeBridge, silver rupee shuffle & shuffle climb will want to adjust
LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch()), LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->HasFireSourceWithTorch()),
// possible to collect without lowering fence, should be a trick // 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH, []{return logic->SpiritRupeeBridge;}), 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()), LOCATION(RC_SPIRIT_TEMPLE_BEFORE_CHILD_CLIMB_SMALL_CRATE_2, logic->CanBreakSmallCrates()),
}, { }, {
//Exits //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);}), Entrance(RR_SPIRIT_TEMPLE_BROKEN_WALL, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 1);}),
}); });
@ -113,7 +113,7 @@ void RegionTable_Init_SpiritTemple() {
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_1F_BOXES, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}), 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, {}, { 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)), LOCATION(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanKillEnemy(RE_GOLD_SKULLTULA)),
}, { }, {
//Exits //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 //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 //A damage boost off the boulder is also possible, but you need
Entrance(RR_SPIRIT_TEMPLE_PAST_BOULDERS, []{return logic->SpiritBouldersSilvers;}), Entrance(RR_SPIRIT_TEMPLE_PAST_BOULDERS, []{return logic->SpiritBouldersSilvers;}),
@ -178,51 +178,66 @@ 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, {}, {}, { areaTable[RR_SPIRIT_TEMPLE_EAST_CLIMB_BASE] = Region("Spirit Temple East Climb Base", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_1F_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 5);}), 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, {}, { areaTable[RR_SPIRIT_TEMPLE_2F_MIRROR] = Region("Spirit Temple 2F Mirror", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_LEFT_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;})), LOCATION(RC_SPIRIT_TEMPLE_FIRST_MIRROR_RIGHT_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true/*str0 || SunlightArrows()*/;})),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_EAST_CLIMB_BASE, []{return true;}), 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, {}, { areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST] = Region("Spirit Temple Statue Rooom West", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //Locations
//Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM access //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));})), 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,
//Current and N64 logic doesn't need scarecrow, you can hit the skull with normal hookshot from a specific spot on the forearm RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->HasFireSource();})),
//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, ED_LONGSHOT);}, false,
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_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);})), RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanKillEnemy(RE_GOLD_SKULLTULA);})),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_BROKEN_WALL, []{return true;}), 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_INNER_WEST_HAND, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->SpiritWestToSkull();}), Entrance(RR_SPIRIT_TEMPLE_GS_LEDGE, []{return logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SCARECROW);}),
// RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled // RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered && Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}), (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_EMPTY_STAIRS, []{return true/*str0*/;}),
//!QUANTUM LOGIC! //!QUANTUM LOGIC!
//When child enters spirit in reverse, has 4 keys, and dungeon entrance shuffle is off, //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 //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 //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 //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 && Entrance(RR_DESERT_COLOSSUS, []{return ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF) && logic->ReverseSpiritChild && /*str0 &&*/
logic->IsChild && logic->SmallKeys(RR_SPIRIT_TEMPLE, 4) && logic->CanKillEnemy(RE_IRON_KNUCKLE);}), 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, {}, { areaTable[RR_SPIRIT_TEMPLE_GS_LEDGE] = Region("Spirit Temple GS ledge", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //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 //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, {}, { areaTable[RR_SPIRIT_TEMPLE_STATUE_ROOM] = Region("Spirit Temple Statue Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -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();})), LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, SpiritShared(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return logic->CanBreakPots();})),
}, { }, {
//Exits //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 // RT_SPIRIT_PLATFORM_HOOKSHOT is currently disabled
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered && Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered &&
(logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_SPIRIT_PLATFORM_HOOKSHOT) && logic->CanUse(RG_HOOKSHOT)));}), (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;}), 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 //Locations
//the blocks can be used to get all the silver rupees and the chest itemless //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_ROOM, LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE,
[]{return logic->HasFireSourceWithTorch() || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW));})), []{return logic->HasFireSource() ||
(logic->SpiritSunBlockTorch && (logic->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))));})),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, []{return true;}),
}); });
areaTable[RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS] = Region("Spirit Temple Skulltula Stairs", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { 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, {}, {}, { areaTable[RR_SPIRIT_TEMPLE_WEST_HAND_EXIT] = Region("Spirit Temple West Hand Exit", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_WEST_THRONE, []{return true;}), 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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true), LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true),
}, { }, {
@ -295,11 +324,7 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_DESERT_COLOSSUS, []{return true;}), 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, {}, { 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)),
}, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_2F_MIRROR, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{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_SHORTCUT_SWITCH, []{return logic->SpiritEastToSwitch();}),
Entrance(RR_SPIRIT_TEMPLE_POT_STAIRS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4);}), Entrance(RR_SPIRIT_TEMPLE_POT_STAIRS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4);}),
//!QUANTUM LOGIC! //!QUANTUM LOGIC!
//With 3 keys, you cannot lock adult out of longshotting to the west hand as you would have to //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 //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 //This requires that adult can complete both routes
//Implies CanKillEnemy(RE_IRON_KNUCKLE) //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);}), Entrance(RR_DESERT_COLOSSUS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanKillEnemy(RE_BEAMOS)/* && CanClimb() && str0*/;}),
//Similarly, we can gurantee jumping into desert colossus the same way //!QUANTUM LOGIC!
//except this does not need the longshot as we don't care which hand we jump down from //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_DESERT_COLOSSUS, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && logic->CanKillEnemy(RE_BEAMOS);}), 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, { 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);});}), EventAccess(&logic->SpiritStatueRoomSouthDoor, []{return SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_MEGATON_HAMMER);});}),
}, { }, {
//Locations //Locations
//Assumes RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST access //Assumes RR_SPIRIT_TEMPLE_INNER_EAST_HAND access
LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, logic->CanUse(RG_ZELDAS_LULLABY)), LOCATION(RC_SPIRIT_TEMPLE_STATUE_ROOM_NORTHEAST_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, []{return logic->CanUse(RG_ZELDAS_LULLABY);})),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return true;}), 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, {}, {}, { 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. //opening the way for adult entering via the front.
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_LOBBY, []{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->CanUse(RG_MEGATON_HAMMER);}), 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()), LOCATION(RC_SPIRIT_TEMPLE_BEAMOS_HALL_POT_1, logic->CanBreakPots()),
}, { }, {
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4);}), Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 4);}),
@ -348,16 +399,16 @@ void RegionTable_Init_SpiritTemple() {
//Implies killing the anubis with the fire ring, doing so itemless requires voiding out, which can lock hardcore + OHKO seeds //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_POT_STAIRS, []{return logic->CanKillEnemy(RE_BEAMOS);}),
Entrance(RR_SPIRIT_TEMPLE_FOUR_ARMOS, []{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_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, {}, { areaTable[RR_SPIRIT_TEMPLE_FOUR_ARMOS] = Region("Spirit Temple Four Armos", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations //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)), 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_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;}), Entrance(RR_SPIRIT_TEMPLE_CHEST_STAIRS, []{return true;}),
}); });
@ -388,23 +439,24 @@ 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, {}, {}, { areaTable[RR_SPIRIT_TEMPLE_EAST_HAND_EXIT] = Region("Spirit Temple East hand Exit", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_EAST_THRONE, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_EAST_THRONE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_EAST_HAND, []{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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_EAST_HAND_EXIT, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_EAST_HAND_EXIT, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}), Entrance(RR_SPIRIT_TEMPLE_OUTER_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_DESERT_COLOSSUS, []{return true;}), 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_BEAMOS_PITS, []{return true;}), 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, {}, { areaTable[RR_SPIRIT_TEMPLE_BIG_WALL_UPPER] = Region("Spirit Temple Big Wall Upper", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -414,7 +466,7 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_ADULT_CLIMB_RIGHT_HEART, logic->CanUse(RG_HOOKSHOT)), LOCATION(RC_SPIRIT_TEMPLE_ADULT_CLIMB_RIGHT_HEART, logic->CanUse(RG_HOOKSHOT)),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_LOWER, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_BIG_WALL_BASE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}),
}); });
@ -439,24 +491,24 @@ void RegionTable_Init_SpiritTemple() {
//Events //Events
EventAccess(&logic->Spirit4FSwitch, []{return logic->CanJumpslash() || logic->HasExplosives();}), EventAccess(&logic->Spirit4FSwitch, []{return logic->CanJumpslash() || logic->HasExplosives();}),
//Needs the mirror in the cave to be a perm flag and event for doorsanity //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)) || EventAccess(&logic->SpiritPlatformLowered, []{return (logic->SpiritPushed4FMirrors && logic->CanUse(RG_MIRROR_SHIELD)) || logic->SunlightArrows();}),
(ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}),
}, {}, { }, {}, {
Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_4F_CENTRAL, []{return true;}),
//Rang can hit the switch on the way back but that's a trick //Rang can hit the switch on the way back but that's a trick
Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE, []{return logic->Spirit4FSwitch;}), Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE, []{return logic->Spirit4FSwitch;}),
//Assumes RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE access //Assumes RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE access
Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return (logic->CanUse(RG_MIRROR_SHIELD) && logic->HasExplosives() && logic->Spirit4FSwitch) || Entrance(RR_SPIRIT_TEMPLE_PLATFORM, []{return logic->SpiritPlatformLowered;}),
(ctx->GetOption(RSK_SUNLIGHT_ARROWS) && logic->CanUse(RG_LIGHT_ARROWS));}),
}); });
areaTable[RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE] = Region("Spirit Temple Big Mirror Cave", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, { areaTable[RR_SPIRIT_TEMPLE_BIG_MIRROR_CAVE] = Region("Spirit Temple Big Mirror Cave", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //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 //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 //Exits
Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_ROOM, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_BIG_MIRROR_ROOM, []{return true;}),
@ -467,9 +519,10 @@ void RegionTable_Init_SpiritTemple() {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, []{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_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;}) Entrance(RR_SPIRIT_TEMPLE_INNER_EAST_HAND, []{return true;}),
&& logic->CanUse(RG_HOOKSHOT);}), 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, { 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 // Exits
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM, []{return true;}), 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_INNER_WEST_HAND, []{return logic->CanUse(RG_HOVER_BOOTS);}),
Entrance(RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, []{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_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);}), Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
}); });
@ -503,7 +556,7 @@ void RegionTable_Init_SpiritTemple() {
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_ENTRYWAY, []{return true;}), 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_1F_EAST, []{return false;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_SOUTH, []{return logic->CanUse(RG_LONGSHOT) && logic->CanUse(RG_BOMBCHU_5);}), 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()), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_RIGHT_HEART, logic->CanHitEyeTargets()),
}, { }, {
//Exits //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_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_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, { 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_WEST, []{return true;}), 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, {}, { 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;}), 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 //Events
EventAccess(&logic->FairyPot, []{return Here(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}), 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, { 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 //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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->MQSpiritMapRoomEnemies), LOCATION(RC_SPIRIT_TEMPLE_MQ_MAP_ROOM_ENEMY_CHEST, logic->MQSpiritMapRoomEnemies),
@ -569,7 +625,7 @@ void RegionTable_Init_SpiritTemple() {
//Exits //Exits
//Stalfos room blocks you in with fire until you kill the stalfos, which won't spawn from behind the fire //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_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, { 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));}), EventAccess(&logic->MQSpiritCrawlBoulder, []{return logic->CanUse(RG_BOMBCHU_5) || (ctx->GetTrickOption(RT_RUSTED_SWITCHES) && logic->CanUse(RG_MEGATON_HAMMER));}),
}, {}, { }, {}, {
//Exits //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 //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);}), 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();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_LIKE_LIKE_POT, SpiritShared(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanBreakPots();})),
}, { }, {
//Exits //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_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, {}, { 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) //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);})), 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. //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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, []{return logic->CanHitSwitch();}), 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);}), 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, { 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);});}),
}, {
//Locations //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();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_STATUE_SMALL_CRATE, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return logic->CanBreakSmallCrates();})),
}, { }, {
//Exits //Exits
//Minimal entry, real key logic handled in Shared functions //!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_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_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();}), 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 //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, { areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM] = Region("Spirit Temple MQ Statue Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
//Events //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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_COMPASS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return logic->CanHitEyeTargets();})), 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_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_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();})), 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 //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 //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()) || 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return true/*logic->CanClimb()*/;}), Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, []{return true/*logic->CanClimb()*/;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, []{return logic->SpiritStatueRoomSouthDoor;}), 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);}), 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, {}, { 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 //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 //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_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{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_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, SpiritMQSharedSunBlockRoom([]{return logic->CanBreakPots();})), 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, SpiritMQSharedSunBlockRoom([]{return logic->CanBreakPots();})), LOCATION(RC_SPIRIT_TEMPLE_MQ_SUN_BLOCKS_POT_2, SpiritShared(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->CanBreakPots();})),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FLAMETHROWER_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*/;}), 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, {}, {}, { areaTable[RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS] = Region("Spirit Temple MQ Skulltula Stairs", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@ -698,10 +799,10 @@ 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, {}, {}, { 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_THRONE , []{return true;}), Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_THRONE , []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_HAND, []{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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true), LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, true),
}, { }, {
@ -716,44 +817,77 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return true;}), 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 //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 //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, {}, { 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 //Locations
//Dhard child locked because adult pushing the block is a permanent flag that blocks the eye target and cannot be undone //Hard child locked because 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();})), //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 //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 //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;}), 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, {}, { 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))),
}, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM, []{return true;}), 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! //!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 //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 exit handles that possibility as cleanly as possible without quantum logic, but will not survive glitch logic //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 //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->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_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)) && (ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) &&
logic->CanKillEnemy(RE_IRON_KNUCKLE) && logic->CanKillEnemy(RE_IRON_KNUCKLE) &&
logic->CanUse(RG_LONGSHOT);}), 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_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, { 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 //Events
//implies logic->CanKillEnemy(RE_WALLMASTER). If we have lights, we can kill stalfos and wallmasters with bow //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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, []{return true;}), 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, {}, {}, { 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 //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;}), Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return true;}),
}); });
@ -779,7 +914,7 @@ void RegionTable_Init_SpiritTemple() {
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return logic->CanUse(RG_MEGATON_HAMMER);}), 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_THREE_SUNS_ROOM_1F, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_SAND_PIT, []{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_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, {}, { 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);}), 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}), Entrance(RR_SPIRIT_TEMPLE_MQ_1F_EAST, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
//Implies CanPassEnemy(RE_MOBLIN_CHIEF) //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, {}, { 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)), LOCATION(RC_SPIRIT_TEMPLE_MQ_GS_SYMPHONY_ROOM, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOOMERANG)),
}, { }, {
//Exits //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, {}, {}, { 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, {}, {}, { 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER, []{return logic->CanUse(RG_HOOKSHOT);}), 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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_BEAMOS_ROOM_CHEST, logic->CanKillEnemy(RE_BEAMOS)), 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 //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_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);}), 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);}), Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_LOWER, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 6);}),
}); });
@ -836,35 +982,35 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), LOCATION(RC_SPIRIT_TEMPLE_MQ_DINALFOS_ROOM_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_FOUR_BEAMOS_ROOM, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return logic->CanJumpslash();}), 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);});}), 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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_SOT_SUN_ROOM, []{return true;}), 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_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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_MQ_FLOORMASTER_STAIRS, []{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_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, {}, {}, { 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_IRON_KNUCKLE, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_THRONE, []{return true;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, []{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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true), LOCATION(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, true),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}), Entrance(RR_SPIRIT_TEMPLE_MQ_OUTER_WEST_HAND, []{return logic->CanUse(RG_LONGSHOT);}),
Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, []{return true;}), Entrance(RR_SPIRIT_TEMPLE_MQ_EAST_THRONE, []{return true;}),
Entrance(RR_DESERT_COLOSSUS, []{return true;}), Entrance(RR_DESERT_COLOSSUS, []{return true;}),
}); });
@ -882,16 +1028,19 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_MQ_LONG_CLIMB_POT_2, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_LONG_CLIMB_POT_2, logic->CanBreakPots()),
}, { }, {
//Exits //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 //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 //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_LOWER, []{return true;}), 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 logic->MQSpiritBigWallSilvers;}),
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, []{return true;}),
}); });
areaTable[RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL] = Region("Spirit Temple MQ 4F Central", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, { areaTable[RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL] = Region("Spirit Temple MQ 4F Central", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
@ -901,11 +1050,11 @@ void RegionTable_Init_SpiritTemple() {
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, []{return true;}), 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_NINE_THRONES_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_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 //Locations
//These skulls rely on the iron knuckle existing without a trick to shoot through the chairs //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)), 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, { 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 //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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_BIG_MIRROR_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_BIG_MIRROR_POT_1, logic->CanBreakPots()),
@ -931,18 +1081,31 @@ void RegionTable_Init_SpiritTemple() {
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, []{return true;}), 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 //Locations
LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), LOCATION(RC_SPIRIT_TEMPLE_MQ_MIRROR_PUZZLE_INVISIBLE_CHEST, ctx->GetTrickOption(RT_LENS_SPIRIT_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)),
}, { }, {
//Exits //Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return logic->MQSpiritOpenedBigMirrorCave;}), Entrance(RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_ROOM, []{return true;}),
//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);});}), //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, { areaTable[RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD] = Region("Spirit Temple MQ Statue Head", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
@ -952,7 +1115,10 @@ void RegionTable_Init_SpiritTemple() {
EventAccess(&logic->ReverseSpiritAdult, []{return logic->IsAdult;}), EventAccess(&logic->ReverseSpiritAdult, []{return logic->IsAdult;}),
}, {}, { }, {}, {
// Exits // Exits
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return true;}), 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);}), Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
}); });

View file

@ -1286,6 +1286,10 @@ bool Logic::HasFireSourceWithTorch() {
return HasFireSource() || CanUse(RG_STICKS); 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? // Is this best off signaling what you have already traded, or what step you are currently on?
bool Logic::TradeQuestStep(RandomizerGet rg) { bool Logic::TradeQuestStep(RandomizerGet rg) {
if (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE)) { 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); 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() { 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() { bool Logic::MQSpiritStatueSouthDoor() {
@ -2570,18 +2585,20 @@ void Logic::Reset() {
MQSpiritCrawlBoulder = false; MQSpiritCrawlBoulder = false;
MQSpiritMapRoomEnemies = false; MQSpiritMapRoomEnemies = false;
MQSpiritTimeTravelChest = false; MQSpiritTimeTravelChest = false;
MQSpiritStatueRoomTorches = false;
MQSpirit3SunsEnemies = false; MQSpirit3SunsEnemies = false;
MQSpiritOpenedBigMirrorCave = false; MQSpiritSymphonyRoomDoor = false;
MQSpiritBigWallSilvers = false;
Spirit1FSilverRupees = false; Spirit1FSilverRupees = false;
SpiritChildSwitchBridge = false; SpiritChildSwitchBridge = false;
SpiritRupeeBridge = false; SpiritRupeeBridge = false;
SpiritBouldersSilvers = false; SpiritBouldersSilvers = false;
SpiritPlatformLowered = false; SpiritPlatformLowered = false;
Spirit4FSwitch = false; Spirit4FSwitch = false;
SpiritPushed4FMirrors = false;
ReverseSpiritChild = false; ReverseSpiritChild = false;
ReverseSpiritAdult = false; ReverseSpiritAdult = false;
StopPerformanceTimer(PT_LOGIC_RESET); StopPerformanceTimer(PT_LOGIC_RESET);
} }
} // namespace Rando } // namespace Rando

View file

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

View file

@ -864,16 +864,19 @@ typedef enum {
RR_SPIRIT_TEMPLE_2F_MIRROR, RR_SPIRIT_TEMPLE_2F_MIRROR,
RR_SPIRIT_TEMPLE_STATUE_ROOM, RR_SPIRIT_TEMPLE_STATUE_ROOM,
RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST, RR_SPIRIT_TEMPLE_STATUE_ROOM_WEST,
RR_SPIRIT_TEMPLE_INNER_WEST_HAND,
RR_SPIRIT_TEMPLE_GS_LEDGE, RR_SPIRIT_TEMPLE_GS_LEDGE,
RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST, RR_SPIRIT_TEMPLE_STATUE_ROOM_EAST,
RR_SPIRIT_TEMPLE_INNER_EAST_HAND,
RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH, RR_SPIRIT_TEMPLE_SHORTCUT_SWITCH,
RR_SPIRIT_TEMPLE_SHORTCUT, RR_SPIRIT_TEMPLE_SHORTCUT,
RR_SPIRIT_TEMPLE_EMPTY_STAIRS, RR_SPIRIT_TEMPLE_EMPTY_STAIRS,
RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM,
RR_SPIRIT_TEMPLE_SUN_BLOCK_SOUTH_LEDGE,
RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS, RR_SPIRIT_TEMPLE_SKULLTULA_STAIRS,
RR_SPIRIT_TEMPLE_WEST_THRONE, RR_SPIRIT_TEMPLE_WEST_THRONE,
RR_SPIRIT_TEMPLE_WEST_HAND_EXIT, 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_POT_STAIRS,
RR_SPIRIT_TEMPLE_BEAMOS_PITS, RR_SPIRIT_TEMPLE_BEAMOS_PITS,
RR_SPIRIT_TEMPLE_FOUR_ARMOS, RR_SPIRIT_TEMPLE_FOUR_ARMOS,
@ -881,8 +884,8 @@ typedef enum {
RR_SPIRIT_TEMPLE_CHEST_STAIRS, RR_SPIRIT_TEMPLE_CHEST_STAIRS,
RR_SPIRIT_TEMPLE_EAST_THRONE, RR_SPIRIT_TEMPLE_EAST_THRONE,
RR_SPIRIT_TEMPLE_EAST_HAND_EXIT, RR_SPIRIT_TEMPLE_EAST_HAND_EXIT,
RR_SPIRIT_TEMPLE_EAST_HAND, RR_SPIRIT_TEMPLE_OUTER_EAST_HAND,
RR_SPIRIT_TEMPLE_BIG_WALL_LOWER, RR_SPIRIT_TEMPLE_BIG_WALL_BASE,
RR_SPIRIT_TEMPLE_BIG_WALL_UPPER, RR_SPIRIT_TEMPLE_BIG_WALL_UPPER,
RR_SPIRIT_TEMPLE_4F_CENTRAL, RR_SPIRIT_TEMPLE_4F_CENTRAL,
RR_SPIRIT_TEMPLE_FAKE_DOORS_ROOM, RR_SPIRIT_TEMPLE_FAKE_DOORS_ROOM,
@ -901,38 +904,44 @@ typedef enum {
RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH, RR_SPIRIT_TEMPLE_MQ_WEST_1F_RUSTED_SWITCH,
RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE, RR_SPIRIT_TEMPLE_MQ_UNDER_LIKE_LIKE,
RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM, RR_SPIRIT_TEMPLE_MQ_BROKEN_WALL_ROOM,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_WEST, 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_FLAMETHROWER_STAIRS,
RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM,
RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS, RR_SPIRIT_TEMPLE_MQ_SKULLTULA_STAIRS,
RR_SPIRIT_TEMPLE_MQ_WEST_THRONE, RR_SPIRIT_TEMPLE_MQ_WEST_THRONE,
RR_SPIRIT_TEMPLE_MQ_WEST_HAND_EXIT, 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_SOUTH,
RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH, RR_SPIRIT_TEMPLE_MQ_BIG_BLOCK_ROOM_NORTH,
RR_SPIRIT_TEMPLE_MQ_STATUE_ROOM_EAST, 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_2F,
RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F, RR_SPIRIT_TEMPLE_MQ_THREE_SUNS_ROOM_1F,
RR_SPIRIT_TEMPLE_MQ_1F_EAST, RR_SPIRIT_TEMPLE_MQ_1F_EAST,
RR_SPIRIT_TEMPLE_MQ_SAND_PIT, 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_AFTER_SYMPHONY_ROOM,
RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER, RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_LOWER,
RR_SPIRIT_TEMPLE_MQ_FIRE_WALL_STAIRS_UPPER, 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_SOT_SUN_ROOM,
RR_SPIRIT_TEMPLE_MQ_EAST_STAIRS_TO_HAND, RR_SPIRIT_TEMPLE_MQ_FLOORMASTER_STAIRS,
RR_SPIRIT_TEMPLE_MQ_EAST_IRON_KNUCKLE, RR_SPIRIT_TEMPLE_MQ_EAST_THRONE,
RR_SPIRIT_TEMPLE_MQ_EXIT_TO_MIRROR_SHIELD_HAND, RR_SPIRIT_TEMPLE_MQ_EAST_HAND_EXIT,
RR_SPIRIT_TEMPLE_MQ_MIRROR_SHIELD_HAND, RR_SPIRIT_TEMPLE_MQ_OUTER_EAST_HAND,
RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM, RR_SPIRIT_TEMPLE_MQ_3F_GIBDO_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_WALL_LOWER, RR_SPIRIT_TEMPLE_MQ_BIG_WALL_LOWER,
RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER, RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER,
RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, 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_ROOM,
RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE, RR_SPIRIT_TEMPLE_MQ_BIG_MIRROR_CAVE,
RR_SPIRIT_TEMPLE_MQ_PLATFORM,
RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD, RR_SPIRIT_TEMPLE_MQ_STATUE_HEAD,
RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY,