diff --git a/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp b/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp index d078316c9..aca55d714 100644 --- a/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp +++ b/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp @@ -1,9 +1,10 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" -#include "z64save.h" -extern "C" SaveContext gSaveContext; +extern "C" { +#include "z64save.h" +extern SaveContext gSaveContext; +} #define CVAR_INFINITE_MAGIC_NAME CVAR_CHEAT("InfiniteMagic") #define CVAR_INFINITE_MAGIC_DEFAULT 0 diff --git a/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp b/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp index 3e7660b84..277868b20 100644 --- a/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp +++ b/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp @@ -1,11 +1,12 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" + +extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" - -extern "C" PlayState* gPlayState; +extern PlayState* gPlayState; +} static constexpr int32_t CVAR_RUPEE_DASH_DEFAULT = 0; #define CVAR_RUPEE_DASH_NAME CVAR_ENHANCEMENT("RupeeDash") diff --git a/soh/soh/Enhancements/FileSelectEnhancements.cpp b/soh/soh/Enhancements/FileSelectEnhancements.cpp index ec8810d02..d2671f20e 100644 --- a/soh/soh/Enhancements/FileSelectEnhancements.cpp +++ b/soh/soh/Enhancements/FileSelectEnhancements.cpp @@ -4,7 +4,6 @@ #include #include -#include std::array RandomizerSettingsMenuText[RSM_MAX] = { { diff --git a/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp b/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp index 6d21d812b..1bde4e50c 100644 --- a/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp +++ b/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp @@ -1,12 +1,13 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" + +extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" #include "z64save.h" - -extern "C" PlayState* gPlayState; +extern PlayState* gPlayState; +} static constexpr int32_t CVAR_BGS_FIX_DEFAULT = 0; #define CVAR_BGS_FIX_NAME CVAR_ENHANCEMENT("FixBrokenGiantsKnife") diff --git a/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp b/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp index 2e095c59f..8096f2075 100644 --- a/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp +++ b/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp @@ -1,12 +1,13 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" + +extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" #include "z64save.h" - -extern "C" PlayState* gPlayState; +extern PlayState* gPlayState; +} static constexpr int32_t CVAR_NUT_UPGRADE_FIX_DEFAULT = 0; #define CVAR_NUT_UPGRADE_FIX_NAME CVAR_ENHANCEMENT("DekuNutUpgradeFix") diff --git a/soh/soh/Enhancements/QoL/DaytimeGS.cpp b/soh/soh/Enhancements/QoL/DaytimeGS.cpp index 869945cb5..fabf7457b 100644 --- a/soh/soh/Enhancements/QoL/DaytimeGS.cpp +++ b/soh/soh/Enhancements/QoL/DaytimeGS.cpp @@ -1,10 +1,9 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" -#include "functions.h" -#include "macros.h" extern "C" { +#include "functions.h" +#include "macros.h" extern PlayState* gPlayState; extern SaveContext gSaveContext; } diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index dde827ec5..b9838cf66 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -1,15 +1,7 @@ -#include "bootcommands.h" -#include "gameconsole.h" -#include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include "soh/OTRGlobals.h" +#include "bootcommands.h" #include "soh/cvar_prefixes.h" void BootCommands_Init() { diff --git a/soh/soh/Enhancements/bootcommands.h b/soh/soh/Enhancements/bootcommands.h index 5c6cb8c8c..48b361b13 100644 --- a/soh/soh/Enhancements/bootcommands.h +++ b/soh/soh/Enhancements/bootcommands.h @@ -1,7 +1,5 @@ #ifndef _BOOTCOMMANDS_H_ #define _BOOTCOMMANDS_H_ -#include -#include void BootCommands_Init(); diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index 88e943f87..e180e93ef 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -6,8 +6,6 @@ #include #include #include -#include -#include #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index b9cc0b10b..b17718b65 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -1,13 +1,17 @@ -#include #include "draw.h" -#include "z64.h" -#include "macros.h" -#include "functions.h" -#include "variables.h" #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" #include "randomizerTypes.h" #include +#include "soh_assets.h" +#include "soh/Enhancements/cosmetics/cosmeticsTypes.h" + +extern "C" { +#include "z64.h" +#include "macros.h" +#include "functions.h" +#include "variables.h" +#include "dungeon.h" #include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h" #include "objects/object_gi_compass/object_gi_compass.h" @@ -30,11 +34,6 @@ #include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h" #include "objects/object_tw/object_tw.h" #include "objects/object_ganon2/object_ganon2.h" -#include "soh_assets.h" -#include "dungeon.h" -#include "soh/Enhancements/cosmetics/cosmeticsTypes.h" - -extern "C" { extern PlayState* gPlayState; extern SaveContext gSaveContext; } diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index b9a8fe4d3..d4a027ee5 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -45,8 +45,6 @@ std::string Entrance::GetName() const { } void Entrance::printAgeTimeAccess() { - // CitraPrint("Name: "); - // CitraPrint(name); auto message = "Child Day: " + std::to_string(CheckConditionAtAgeTime(logic->IsChild, logic->AtDay)) + "\t" "Child Night: " + @@ -57,7 +55,6 @@ void Entrance::printAgeTimeAccess() { "\t" "Adult Night: " + std::to_string(CheckConditionAtAgeTime(logic->IsAdult, logic->AtNight)); - // CitraPrint(message); } bool Entrance::ConditionsMet(bool allAgeTimes) const { diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 2fb04dccd..fceb6c08f 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -20,6 +20,18 @@ extern PlayState* gPlayState; // generic grotto event list std::vector grottoEvents; +bool EventAccess::CheckConditionAtAgeTime(bool& age, bool& time) { + logic->IsChild = false; + logic->IsAdult = false; + logic->AtDay = false; + logic->AtNight = false; + + time = true; + age = true; + + return ConditionsMet(); +} + // set the logic to be a specific age and time of day and see if the condition still holds bool LocationAccess::CheckConditionAtAgeTime(bool& age, bool& time) const { logic->IsChild = false; @@ -466,7 +478,7 @@ bool Region::UpdateEvents() { } void Region::AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition) { - Rando::Entrance newExit = Rando::Entrance(newExitKey, { condition }); + Rando::Entrance newExit = Rando::Entrance(newExitKey, condition); newExit.SetParentRegion(parentKey); exits.push_front(newExit); } @@ -551,6 +563,110 @@ void Region::ResetVariables() { } } +/* + * This logic covers checks that exist in the shared areas of MQ spirit from a glitchless standpoint. + * This room has Quantum logic that I am currently handling with this function, however this is NOT suitable for + glitch logic as it relies on specific ages + * In this chunk there are 3 possibilities for passing a check, but first I have to talk about parallel universes. + + * In MQ Spirit key logic, we mostly care about 2 possibilities for how the player can spend keys, creating 2 + Parralel universes + * In the first universe, the player did not enter spirit as adult until after climbing as child, thus child spends + keys linearly, only needing 2 to reach statue room. + * In the second universe, the player went in as adult, possibly out of logic, and started wasting the keys to lock + child out. + * These Universes converge when the player has 7 keys (meaning adult can no longer lock child out) and adult is + known to be able to reach Statue room. This creates "Certain Access", which is tracked seperatly for each age. + * Child Certain Access is simple, if we have 7 keys and child access, it's Certain Access. + * Adult Certain Access is also simple, adult is not key locked, so if they make it to a location, it's Certain + Access. + * Things get complicated when we handle the overlap of the 2 universes, + * though an important detail is that if we have Certain Access as either age, we don't need to checked the overlap + because overlap logic is strictly stricter than either Certain Access. + + * In order to track the first universe, the logic allows technical child access with the minimum number of keys, + and then checks in this function for if we have 7 keys to determine if that is Certain or not. + * This is for technical reasons, as areas with no access at all will simply not be checked. + * Normally we would need to do similar shenanigans to track the second universe, however adult must have go through + statue room to waste keys, + * so can go back there and get new keys for Child to use if they do, and the navigation logic for shared MQ spirit + from Statue Room is very simple for Adult. + * Additionally, we don't need to know if adult can actually reach spirit temple or climb to statue room, because if + the player can't do that, then universe 2 can't happen anyway, + * and if the player does so out of logic, they can do it again, as the only consumable used sets a permanent flag. + + * The Adult Navigation logic is as such: + * - Broken Wall room is 6 key locked, because if the player tries to spend 6 keys in a way that would block adults + access, they would have to give child access instead. + * - The child side hammer switch for the time travelling chest is 7 key locked for adult + * - Reaching gauntlets hand is 7 key locked + * - Going back into big block room is complex, but the only check there is child only so not a concern + * - Everything else is possible with basic adult movement, or is impossible for child to reach glitchlessly + * Anything 7 key locked does not need to be checked as shared, as all child access is Certain and because of this + workaround we don't need to fake Adult access, meaning that is also Certain. + * All of this combined means that when checking if adult can reach a location in universe 2, we only have to ask if + it is a 6 key locked location or not. + + * Knowing all of this this, we can confirm things are logical in 3 different ways: + * - If we have Adult Access, we know it is Certain Access, so they can get checks alone. + * - If we have 7 keys, child has Certain Access as we know they cannot be locked out, so can get checks alone, + otherwise we check the logical overlap + * - If Child and Adult can get the check (ignoring actual adult access to the location), and the location is either + not 6 key locked or we have 6 keys, we can get the check with the overlap + */ +bool Region::MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge) { + // if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if + // adult is here it's also Certain Access + if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) { + if (anyAge) { + return Here(condition); + } + return condition(); + // else, if we are here as adult, we have Certain Access from that and don't need special handling for + // checking adult + } else if (Adult() && logic->IsAdult) { + return condition(); + // if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and + // meet the adult universe's access condition We only need to do it as child, as only child access matters + // for this check, as adult access is assumed based on keys + } else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) { + bool result = false; + // store current age variables + bool pastAdult = logic->IsAdult; + bool pastChild = logic->IsChild; + + // First check if the check is possible as child + logic->IsChild = true; + logic->IsAdult = false; + result = condition(); + // If so, check again as adult. both have to be true for result to be true + if (result) { + logic->IsChild = false; + logic->IsAdult = true; + result = condition(); + } + + // set back age variables + logic->IsChild = pastChild; + logic->IsAdult = pastAdult; + return result; + } + return false; +} + +void Region::printAgeTimeAccess() { + auto message = "Child Day: " + std::to_string(childDay) + + "\t" + "Child Night: " + + std::to_string(childNight) + + "\t" + "Adult Day: " + + std::to_string(adultDay) + + "\t" + "Adult Night: " + + std::to_string(adultNight); +} + std::array areaTable; bool Here(const RandomizerRegion region, ConditionFn condition) { diff --git a/soh/soh/Enhancements/randomizer/location_access.h b/soh/soh/Enhancements/randomizer/location_access.h index 547000ce5..5cbc84060 100644 --- a/soh/soh/Enhancements/randomizer/location_access.h +++ b/soh/soh/Enhancements/randomizer/location_access.h @@ -34,17 +34,7 @@ class EventAccess { return true; } - bool CheckConditionAtAgeTime(bool& age, bool& time) { - logic->IsChild = false; - logic->IsAdult = false; - logic->AtDay = false; - logic->AtNight = false; - - time = true; - age = true; - - return ConditionsMet(); - } + bool CheckConditionAtAgeTime(bool& age, bool& time); void EventOccurred() { *event = true; @@ -210,7 +200,7 @@ class Region { logic->IsChild = Child(); logic->IsAdult = Adult(); - // heck condition as well as having at least child or adult access + // check condition as well as having at least child or adult access bool hereVal = condition() && (logic->IsAdult || logic->IsChild); // set back age variables @@ -222,112 +212,11 @@ class Region { bool CanPlantBeanCheck() const; bool AllAccountedFor() const; + bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false); void ResetVariables(); - void printAgeTimeAccess() const { - auto message = "Child Day: " + std::to_string(childDay) + - "\t" - "Child Night: " + - std::to_string(childNight) + - "\t" - "Adult Day: " + - std::to_string(adultDay) + - "\t" - "Adult Night: " + - std::to_string(adultNight); - } - - /* - * This logic covers checks that exist in the shared areas of MQ spirit from a glitchless standpoint. - * This room has Quantum logic that I am currently handling with this function, however this is NOT suitable for - glitch logic as it relies on specific ages - * In this chunk there are 3 possibilities for passing a check, but first I have to talk about parallel universes. - - * In MQ Spirit key logic, we mostly care about 2 possibilities for how the player can spend keys, creating 2 - Parralel universes - * In the first universe, the player did not enter spirit as adult until after climbing as child, thus child spends - keys linearly, only needing 2 to reach statue room. - * In the second universe, the player went in as adult, possibly out of logic, and started wasting the keys to lock - child out. - * These Universes converge when the player has 7 keys (meaning adult can no longer lock child out) and adult is - known to be able to reach Statue room. This creates "Certain Access", which is tracked seperatly for each age. - * Child Certain Access is simple, if we have 7 keys and child access, it's Certain Access. - * Adult Certain Access is also simple, adult is not key locked, so if they make it to a location, it's Certain - Access. - * Things get complicated when we handle the overlap of the 2 universes, - * though an important detail is that if we have Certain Access as either age, we don't need to checked the overlap - because overlap logic is strictly stricter than either Certain Access. - - * In order to track the first universe, the logic allows technical child access with the minimum number of keys, - and then checks in this function for if we have 7 keys to determine if that is Certain or not. - * This is for technical reasons, as areas with no access at all will simply not be checked. - * Normally we would need to do similar shenanigans to track the second universe, however adult must have go through - statue room to waste keys, - * so can go back there and get new keys for Child to use if they do, and the navigation logic for shared MQ spirit - from Statue Room is very simple for Adult. - * Additionally, we don't need to know if adult can actually reach spirit temple or climb to statue room, because if - the player can't do that, then universe 2 can't happen anyway, - * and if the player does so out of logic, they can do it again, as the only consumable used sets a permanent flag. - - * The Adult Navigation logic is as such: - * - Broken Wall room is 6 key locked, because if the player tries to spend 6 keys in a way that would block adults - access, they would have to give child access instead. - * - The child side hammer switch for the time travelling chest is 7 key locked for adult - * - Reaching gauntlets hand is 7 key locked - * - Going back into big block room is complex, but the only check there is child only so not a concern - * - Everything else is possible with basic adult movement, or is impossible for child to reach glitchlessly - * Anything 7 key locked does not need to be checked as shared, as all child access is Certain and because of this - workaround we don't need to fake Adult access, meaning that is also Certain. - * All of this combined means that when checking if adult can reach a location in universe 2, we only have to ask if - it is a 6 key locked location or not. - - * Knowing all of this this, we can confirm things are logical in 3 different ways: - * - If we have Adult Access, we know it is Certain Access, so they can get checks alone. - * - If we have 7 keys, child has Certain Access as we know they cannot be locked out, so can get checks alone, - otherwise we check the logical overlap - * - If Child and Adult can get the check (ignoring actual adult access to the location), and the location is either - not 6 key locked or we have 6 keys, we can get the check with the overlap - */ - bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false) { - // if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if - // adult is here it's also Certain Access - if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) { - if (anyAge) { - return Here(condition); - } - return condition(); - // else, if we are here as adult, we have Certain Access from that and don't need special handling for - // checking adult - } else if (Adult() && logic->IsAdult) { - return condition(); - // if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and - // meet the adult universe's access condition We only need to do it as child, as only child access matters - // for this check, as adult access is assumed based on keys - } else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) { - bool result = false; - // store current age variables - bool pastAdult = logic->IsAdult; - bool pastChild = logic->IsChild; - - // First check if the check is possible as child - logic->IsChild = true; - logic->IsAdult = false; - result = condition(); - // If so, check again as adult. both have to be true for result to be true - if (result) { - logic->IsChild = false; - logic->IsAdult = true; - result = condition(); - } - - // set back age variables - logic->IsChild = pastChild; - logic->IsAdult = pastAdult; - return result; - } - return false; - } + void printAgeTimeAccess(); }; extern std::array areaTable; diff --git a/soh/soh/Enhancements/timesplits/TimeSplits.cpp b/soh/soh/Enhancements/timesplits/TimeSplits.cpp index f08235970..047a6f502 100644 --- a/soh/soh/Enhancements/timesplits/TimeSplits.cpp +++ b/soh/soh/Enhancements/timesplits/TimeSplits.cpp @@ -1,12 +1,11 @@ +#include +#include +#include + #include "TimeSplits.h" #include "soh/Enhancements/gameplaystats.h" #include "soh/SaveManager.h" #include "soh/util.h" -#include -#include "include/z64item.h" - -#include -#include #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" @@ -17,6 +16,7 @@ #include "soh/SohGui/UIWidgets.hpp" extern "C" { +#include "z64item.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } diff --git a/soh/soh/Enhancements/timesplits/TimeSplits.h b/soh/soh/Enhancements/timesplits/TimeSplits.h index 8644d6010..2d4a4ba3f 100644 --- a/soh/soh/Enhancements/timesplits/TimeSplits.h +++ b/soh/soh/Enhancements/timesplits/TimeSplits.h @@ -3,17 +3,6 @@ #define TIMESPLITS_H #include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif // TIMESPLITS_H - #include #ifdef __cplusplus @@ -66,3 +55,5 @@ typedef struct { } SplitObject; #endif + +#endif // TIMESPLITS_H