diff --git a/.gitignore b/.gitignore index 3aa34d9c5..2b7352d95 100644 --- a/.gitignore +++ b/.gitignore @@ -457,3 +457,4 @@ soh/properties.h # Tools /clang-format /clang-format.exe +*.o2r 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 00a7a5adb..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 { @@ -276,8 +273,8 @@ void SetAllEntrancesData() { { EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } }, { { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE }, { EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } }, - { { EntranceType::Dungeon, RR_GF_OUTSIDE_GTG, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE }, - { EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GF_OUTSIDE_GTG, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } }, + { { EntranceType::Dungeon, RR_GF_TO_GTG, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE }, + { EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GF_EXITING_GTG, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } }, { { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE }, { EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } }, diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 3171c1cf8..cf8669136 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 4e4cf1215..45e6c7600 100644 --- a/soh/soh/Enhancements/randomizer/location_access.h +++ b/soh/soh/Enhancements/randomizer/location_access.h @@ -35,17 +35,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; @@ -232,7 +222,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 @@ -244,23 +234,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); - } - - static std::map spiritLogicData; + void printAgeTimeAccess(); }; extern std::array areaTable; diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 2eb8764e1..6c891abc0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp @@ -11,7 +11,7 @@ void RegionTable_Init_GerudoTrainingGround() { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsVanilla();}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsMQ();}), - Entrance(RR_GF_OUTSIDE_GTG, []{return true;}), + Entrance(RR_GF_EXITING_GTG, []{return true;}), }); #pragma region Vanilla diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp index e26e841f0..3929faf86 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -49,15 +49,26 @@ void RegionTable_Init_GerudoFortress() { EventAccess(&logic->GtG_GateOpen, []{return (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}), }, {}, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}), + Entrance(RR_GF_TO_GTG, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}), //Jail + Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_GF_OUTSKIRTS, []{return true;}), + Entrance(RR_GF_NEAR_GROTTO, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), + // RANDTODO: Add tricks for getting past the gerudo guarding the hba range + Entrance(RR_GF_ABOVE_GTG, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), + Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_GF_HBA_RANGE, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), + }); + + areaTable[RR_GF_TO_GTG] = Region("GF to GTG", SCENE_GERUDOS_FORTRESS, {}, {}, { + Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return true;}), + }); + + // Split out to handle adult being immediately captured without card + areaTable[RR_GF_EXITING_GTG] = Region("GF Exiting GTG", SCENE_GERUDOS_FORTRESS, {}, {}, { + Entrance(RR_GF_OUTSIDE_GTG, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_OUTSKIRTS, []{return true;}), - Entrance(RR_GF_NEAR_GROTTO, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), - // RANDTODO: Add tricks for getting past the gerudo guarding the hba range - Entrance(RR_GF_ABOVE_GTG, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), - Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_GF_HBA_RANGE, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), }); #pragma endregion @@ -123,6 +134,7 @@ void RegionTable_Init_GerudoFortress() { Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return true /* logic->CanClimb() */;}), + Entrance(RR_GF_TO_GTG, []{return logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get();}), }); areaTable[RR_GF_TOP_OF_UPPER_VINES] = Region("GF Top of Upper Vines", SCENE_GERUDOS_FORTRESS, {}, { diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 47d534f0f..4104c3d23 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -423,6 +423,8 @@ typedef enum { RR_GF_OUTSKIRTS, RR_GF_NEAR_GROTTO, RR_GF_OUTSIDE_GTG, + RR_GF_TO_GTG, + RR_GF_EXITING_GTG, RR_GF_ABOVE_GTG, RR_GF_BOTTOM_OF_LOWER_VINES, RR_GF_TOP_OF_LOWER_VINES, @@ -3634,6 +3636,7 @@ typedef enum { RT_PASS_GUARDS_WITH_NOTHING, RT_GF_JUMP, RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, + RT_GF_LEDGE_CLIP_INTO_GTG, RT_HW_BUNNY_CROSSING, RT_HW_CROSSING, RT_LENS_HW, diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 6284d7121..fcace1017 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -696,9 +696,9 @@ void DrawQuest(ItemTrackerItem item) { bool hasQuestItem = HasQuestItem(item); float iconSize = static_cast(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); ImGui::BeginGroup(); - ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( - hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), - ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); + ImGui::ImageWithBg(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( + hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), + ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); if (item.id == QUEST_SKULL_TOKEN) { DrawItemCount(item, false); @@ -1231,7 +1231,7 @@ void DrawItemsInACircle(std::vector items) { float radius = (iconSize + iconSpacing) * 2.0f; for (int i = 0; i < items.size(); i++) { - float angle = static_cast(i / items.size() * 2.0f * M_PI); + float angle = static_cast(i) / items.size() * 2.0f * M_PIf; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; ImGui::SetCursorPos(ImVec2(x - (CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36) - 8) / 2.0f, y + 4)); diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 7e7e68589..22f5a0264 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -595,6 +595,9 @@ void Settings::CreateOptions() { OPT_TRICK(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE }, "Gerudo\'s Fortress Warriors with Difficult Weapons", "Warriors can be defeated with Slingshot or Bombchus."); + OPT_TRICK(RT_GF_LEDGE_CLIP_INTO_GTG, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, + "Ledge Clip into Training Ground", + "Adult Link can use a ledge clip to enter Gerudo Training Ground without Gerudo Card."); // disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely // decoupled from rando OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::NOVICE}, // "Wasteland Crossing with Bunny Hood", "You can beat the quicksand by using the increased speed of the Bunny Hood. 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