diff --git a/CMakeLists.txt b/CMakeLists.txt index 14cf4b201..f22967641 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") -project(Ship VERSION 9.2.0 LANGUAGES C CXX) +project(Ship VERSION 9.2.1 LANGUAGES C CXX) include(CMake/soh-cvars.cmake) include(CMake/lus-cvars.cmake) set(SPDLOG_LEVEL_TRACE 0) diff --git a/libultraship b/libultraship index 956f10821..fdcaf6336 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 956f1082122f219d536c20483df89469f4b807dc +Subproject commit fdcaf6336776d24a6408d016b0a52243f108f250 diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json b/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json index 04fc1f8f2..8409287b5 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json @@ -172,6 +172,7 @@ "153": "STICK UPGRADE 30", "154": "NUT UPGRADE 30", "155": "NUT UPGRADE 40", + "157": "Roc's Feather", "255": "", "256": "Haunted Wasteland", "257": "Gerudos Fortress", diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json b/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json index 93e0058dc..0e26e8e93 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json @@ -172,6 +172,7 @@ "153": "AMÉLIORATION BÂTON MOJO 30", "154": "AMÉLIORATION NOIX MOJO 30", "155": "AMÉLIORATION NOIX MOJO 40", + "157": "Plume de Roc", "255": "", "256": "Désert Hanté", "257": "Forteresse Gerudo", diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json index 95fb567b6..cafb22d54 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json @@ -172,6 +172,7 @@ "153": "DEKU-STAB-KAPAZITÄT 30", "154": "DEKU-NUẞ-KAPAZITÄT 30", "155": "DEKU-NUẞ-KAPAZITÄT 40", + "157": "Greifenfeder", "255": "", "256": "Gespensterwüste", "257": "Gerudo-Festung", diff --git a/soh/soh/Enhancements/Cheats/Infinite/Ammo.cpp b/soh/soh/Enhancements/Cheats/Infinite/Ammo.cpp index b54b330bf..c5a0297de 100644 --- a/soh/soh/Enhancements/Cheats/Infinite/Ammo.cpp +++ b/soh/soh/Enhancements/Cheats/Infinite/Ammo.cpp @@ -1,5 +1,6 @@ #include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/OTRGlobals.h" #include "soh/ShipInit.hpp" #include "z64save.h" @@ -24,7 +25,11 @@ void OnGameFrameUpdateInfiniteAmmo() { AMMO(ITEM_BOW) = CUR_CAPACITY(UPG_QUIVER); AMMO(ITEM_SLINGSHOT) = CUR_CAPACITY(UPG_BULLET_BAG); if (INV_CONTENT(ITEM_BOMBCHU) != ITEM_NONE) { - AMMO(ITEM_BOMBCHU) = 50; + int chuCapacity = 50; + if (IS_RANDO && RAND_GET_OPTION(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_PROGRESSIVE)) { + chuCapacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity(); + } + AMMO(ITEM_BOMBCHU) = chuCapacity; } } diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index f823d99f6..3c99ea19e 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1,4 +1,5 @@ #include "debugSaveEditor.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/util.h" #include "soh/SohGui/ImGuiUtils.h" #include "soh/OTRGlobals.h" @@ -1392,6 +1393,39 @@ void DrawEquipmentTab() { "40", }; DrawUpgrade("Deku Nut Capacity", UPG_NUTS, nutNames); + + if (IS_RANDO && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_BOMBCHU_BAG) == RO_BOMBCHU_BAG_PROGRESSIVE) { + const std::vector bombchuNames = { + "None", + "20", + "30", + "50", + }; + ImGui::Text("%s", "Bombchu Bag Capacity"); + ImGui::SameLine(); + ImGui::PushID("Bombchu Bag Capacity"); + PushStyleCombobox(THEME_COLOR); + ImGui::AlignTextToFramePadding(); + auto value = gSaveContext.ship.quest.data.randomizer.bombchuUpgradeLevel; + auto name = value < bombchuNames.size() ? bombchuNames[value].c_str() : "Glitched"; + if (ImGui::BeginCombo("##upgrade", name)) { + for (size_t i = 0; i < bombchuNames.size(); i++) { + if (ImGui::Selectable(bombchuNames[i].c_str())) { + gSaveContext.ship.quest.data.randomizer.bombchuUpgradeLevel = i; + if (i > 0) { + INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; + } else { + INV_CONTENT(ITEM_BOMBCHU) = ITEM_NONE; + } + } + } + ImGui::EndCombo(); + } + PopStyleCombobox(); + ImGui::PopID(); + UIWidgets::Tooltip("Bombchu Bag Capapcity"); + } } // Draws a toggleable icon for a quest item that is faded when disabled diff --git a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp index 37e1d07be..730366949 100644 --- a/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp +++ b/soh/soh/Enhancements/randomizer/ShuffleFairies.cpp @@ -106,11 +106,13 @@ void RegisterShuffleFairies() { COND_VB_SHOULD(VB_BOTTLE_ACTOR, shouldRegister, { Actor* actor = va_arg(args, Actor*); - const auto fairyIdentity = ObjectExtension::GetInstance().Get(actor); - if (fairyIdentity != nullptr && fairyIdentity->randomizerInf != RAND_INF_MAX) { - Flags_SetRandomizerInf(fairyIdentity->randomizerInf); - actor->parent = &GET_PLAYER(gPlayState)->actor; - *should = false; + if (actor->id == ACTOR_EN_ELF) { + const auto fairyIdentity = ObjectExtension::GetInstance().Get(actor); + if (fairyIdentity != nullptr && fairyIdentity->randomizerInf != RAND_INF_MAX) { + Flags_SetRandomizerInf(fairyIdentity->randomizerInf); + actor->parent = &GET_PLAYER(gPlayState)->actor; + *should = false; + } } }); diff --git a/soh/soh/Enhancements/randomizer/ShufflePots.cpp b/soh/soh/Enhancements/randomizer/ShufflePots.cpp index dbf278db8..08b7a7c0c 100644 --- a/soh/soh/Enhancements/randomizer/ShufflePots.cpp +++ b/soh/soh/Enhancements/randomizer/ShufflePots.cpp @@ -54,7 +54,7 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) { break; } } else { - gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gPotStandardDL); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gPotMajorDL); } } else { gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gPotDL); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index 7fdfa1954..c63ca54a4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -31,8 +31,8 @@ void RegionTable_Init_BottomOfTheWell() { EVENT_ACCESS(LOGIC_BOTW_LOWERED_WATER, logic->CanUse(RG_ZELDAS_LULLABY)), }, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH) && logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives() && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives() && (ctx->GetTrickOption(RT_LENS_BOTW) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, (logic->Get(LOGIC_BOTW_LOWERED_WATER) && logic->HasItem(RG_OPEN_CHEST)) || logic->CanOpenUnderwaterChest()), @@ -265,11 +265,10 @@ void RegionTable_Init_BottomOfTheWell() { // Fairies are in slingshot wonder item, & pot behind grate. Pot can also be broken with boomerang trick EVENT_ACCESS(LOGIC_FAIRY_ACCESS, (logic->IsChild && logic->CanUse(RG_FAIRY_SLINGSHOT)) || (AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()) || - //Item extension can get a fairy in 1 of 2 ways: we can either shoot the pot through the grate and let the fairy fly through the wall - //or we can shoot the eye target through the boulder, but not as adult with bow. - //The former cannot be done if the pot has an item in it, as it cannot be collected this way. - (ctx->GetTrickOption(RT_ITEM_EXTENSION) && - (logic->IsChild || ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OFF) || ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OVERWORLD)) ? logic->CanHitEyeTargets() : logic->CanUse(RG_FAIRY_SLINGSHOT))), + //Item extension can get a fairy by either shooting the pot through the grate and letting the fairy fly through the wall + //This cannot be done if the pot has an item in it, as it cannot be collected this way. + (ctx->GetTrickOption(RT_ITEM_EXTENSION) && (ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OFF) || ctx->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OVERWORLD)) && logic->CanHitEyeTargets()) || + (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->IsChild ? logic->CanHitEyeTargets() : logic->CanUse(RG_FAIRY_SLINGSHOT))), //It is possible to hit the water switch with a pot from RR_BOTW_MQ_MIDDLE, however the hitbox for making it activate is very unintuitive //You have to throw the pot from further back to hit the switch from the front instead of the top, trying to hit the "fingers" directly //This unintuitiveness means it should be a trick. ZL is needed to get a clear path to carry the pot @@ -282,7 +281,7 @@ void RegionTable_Init_BottomOfTheWell() { //Not even bow extension seems to get adult's bow to work //this would be a trick LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_OUTER_LOBBY_POT, (AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()) || - (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->IsChild ? logic->CanHitEyeTargets() : logic->CanUse(RG_FAIRY_SLINGSHOT))), + (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->IsChild ? logic->CanHitEyeTargets() : logic->CanUse(RG_FAIRY_SLINGSHOT))), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_LEFT_HEART, logic->HasExplosives()), LOCATION(RC_BOTTOM_OF_THE_WELL_MQ_BOMB_RIGHT_HEART, logic->HasExplosives()), }, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp index 3ff361b3d..c77d43cfb 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/fire_temple.cpp @@ -1062,7 +1062,7 @@ void RegionTable_Init_FireTemple() { areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", SCENE_FIRE_TEMPLE_BOSS, { // Events - EVENT_ACCESS(LOGIC_FIRE_TEMPLE_CLEAR, logic->FireTimer() >= 64 && logic->CanKillEnemy(RE_VOLVAGIA)), + EVENT_ACCESS(LOGIC_FIRE_TEMPLE_CLEAR, logic->CanUse(RG_GORON_TUNIC) && logic->CanKillEnemy(RE_VOLVAGIA)), }, { // Locations LOCATION(RC_FIRE_TEMPLE_VOLVAGIA_HEART, logic->Get(LOGIC_FIRE_TEMPLE_CLEAR)), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp index d5c9c4637..24e905aa9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -50,7 +50,8 @@ void RegionTable_Init_IceCavern() { }, { //Locations LOCATION(RC_ICE_CAVERN_MAP_CHEST, logic->BlueFire() && logic->HasItem(RG_OPEN_CHEST)), - // very easy to break pot through ice + // very easy to break pot through ice with most weapons + // Bow extesnion is possible, but very precise: X = 403, Z = 2062-3, Rot = -11475, needs a setup and is its own trick LOCATION(RC_ICE_CAVERN_FROZEN_POT_1, (logic->CanBreakPots() && logic->BlueFire()) || logic->HasExplosives() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && ((logic->CanStandingShield() && logic->CanUse(RG_KOKIRI_SWORD)) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER))) || (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->CanUse(RG_HOOKSHOT))), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp index 14291b212..40ba46fcf 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/castle_grounds.cpp @@ -95,7 +95,7 @@ void RegionTable_Init_CastleGrounds() { //Exits ENTRANCE(RR_HC_GATE, true), ENTRANCE(RR_HC_STORMS_GROTTO, logic->CanOpenStormsGrotto()), - ENTRANCE(RR_HC_GARDEN, (logic->CanUse(RG_WEIRD_EGG) && logic->HasItem(RG_POWER_BRACELET) && logic->HasItem(RG_SPEAK_HYLIAN)) || + ENTRANCE(RR_HC_DRAIN_LEDGE, (logic->CanUse(RG_WEIRD_EGG) && logic->HasItem(RG_POWER_BRACELET) && logic->HasItem(RG_SPEAK_HYLIAN)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->TakeDamage() && logic->HasExplosives() && logic->CanJumpslash())), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp index 2ece82c25..d0194ac67 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_crater.cpp @@ -92,13 +92,13 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 16 || logic->Hearts() >= 3), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->ReachDistantScarecrow() && logic->TakeDamage() && logic->CanClimbLadder())), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT))) || + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && logic->CanClimbLadder()) || (logic->IsAdult && (logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad() && CanPlantBean(RR_DMC_CENTRAL, RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL)) || ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && ctx->GetTrickOption(RT_DMC_HOVER_BEAN_POH) && logic->CanUse(RG_HOVER_BOOTS))), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 48 || logic->Hearts() >= 9) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), }); areaTable[RR_DMC_POTS_ENTRY] = Region("DMC Pots Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { @@ -124,11 +124,11 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_POTS, true), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->TakeDamage() && logic->CanClimbLadder())), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), }); areaTable[RR_DMC_POT_GROTTO_ENTRY] = Region("DMC Pot Grotto Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { @@ -154,11 +154,11 @@ void RegionTable_Init_DeathMountainCrater() { ENTRANCE(RR_DMC_POTS, logic->FireTimer() >= 8 || logic->Hearts() >= 2), ENTRANCE(RR_DMC_POT_GROTTO_EXIT, true), ENTRANCE(RR_DMC_CENTRAL, ((logic->FireTimer() >= 32 || logic->Hearts() >= 6) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), ENTRANCE(RR_DMC_FAR_PLATFORM, (logic->IsAdult && (logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad() && logic->ReachDistantScarecrow()) || - ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->TakeDamage() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->TakeDamage() && logic->CanClimbLadder())), ENTRANCE(RR_DMC_TEMPLE_EXIT, ((logic->FireTimer() >= 40 || logic->Hearts() >= 8) && logic->DMCPotsToPad()) || - (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)))), + (logic->IsAdult && (logic->FireTimer() >= 56 || logic->Hearts() >= 11) && logic->TakeDamage() && logic->ReachDistantScarecrow() && logic->CanClimbLadder())), }); areaTable[RR_DMC_PAD_ENTRY] = Region("DMC Pad Entry", SCENE_DEATH_MOUNTAIN_CRATER, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp index 0a1890ea5..78d406403 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/death_mountain_trail.cpp @@ -37,7 +37,8 @@ void RegionTable_Init_DeathMountainTrail() { //Locations LOCATION(RC_DMT_GS_FALLING_ROCKS_PATH, logic->IsAdult && logic->CanGetNightTimeGS() && (logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanUse(RG_LONGSHOT)) || (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->CanUse(RG_HOOKSHOT)) || - (ctx->GetTrickOption(RT_DMT_UPPER_GS) && (logic->CanJumpslash() || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives() || ((ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) || ctx->GetTrickOption(RT_ITEM_EXTENSION)) && (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_FAIRY_SLINGSHOT))))))), + (ctx->GetTrickOption(RT_DMT_UPPER_GS) && (logic->CanJumpslash() || logic->CanUse(RG_DINS_FIRE) || logic->HasExplosives() || (ctx->GetTrickOption(RT_ITEM_EXTENSION) && logic->CanUse(RG_FAIRY_SLINGSHOT)) || + (ctx->GetTrickOption(RT_DISTANT_BOULDER_COLLISION) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT)))))), }, { //Exits ENTRANCE(RR_DEATH_MOUNTAIN_TRAIL, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index a94cecadd..d93b877d4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -19,7 +19,7 @@ void RegionTable_Init_GerudoValley() { ENTRANCE(RR_GV_CRATE_LEDGE, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_GV_GROTTO_LEDGE, true), ENTRANCE(RR_GV_FORTRESS_SIDE, (logic->IsAdult && (logic->SummonEpona() || logic->CanUse(RG_LONGSHOT) || ctx->GetOption(RSK_GERUDO_FORTRESS).Is(RO_GF_CARPENTERS_FREE) || logic->Get(LOGIC_TH_RESCUED_ALL_CARPENTERS))) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_HOVER_BOOTS)) || - ((logic->IsChild || ctx->GetTrickOption(RT_ITEM_EXTENSION)) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsChild && ctx->GetTrickOption(RT_GV_CHILD_CUCCO_JUMP) && logic->HasItem(RG_POWER_BRACELET) && logic->CanJumpslash())), + ((logic->IsChild || ctx->GetTrickOption(RT_GV_HOOKSHOT_BRIDGE)) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsChild && ctx->GetTrickOption(RT_GV_CHILD_CUCCO_JUMP) && logic->HasItem(RG_POWER_BRACELET) && logic->CanJumpslash())), ENTRANCE(RR_GV_WATERFALL_ALCOVE, logic->IsChild && logic->HasItem(RG_POWER_BRACELET)), ENTRANCE(RR_GV_LOWER_STREAM, logic->IsChild && logic->HasItem(RG_POWER_BRACELET)), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp index 43bb878d8..d0e78f824 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -70,7 +70,9 @@ void RegionTable_Init_KokiriForest() { }, { //Exits ENTRANCE(RR_KF_BOULDER_LOOP, logic->CanUse(RG_CRAWL)), - ENTRANCE(RR_KF_LINKS_PORCH, logic->IsChild ? logic->CanClimbLadder() : logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOVER_BOOTS)), + //The Deku Baba blocks the setup as Adult, and stunning doesn't last long enough to perform it. + ENTRANCE(RR_KF_LINKS_PORCH, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOVER_BOOTS) || + ((logic->IsChild || logic->CanKillEnemy(RE_DEKU_BABA) || logic->Get(LOGIC_FOREST_TEMPLE_CLEAR)) && logic->CanClimbLadder())), ENTRANCE(RR_KF_MIDOS_HOUSE, true), ENTRANCE(RR_KF_SARIAS_HOUSE, true), ENTRANCE(RR_KF_HOUSE_OF_TWINS, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp index e20cf5ea6..6eea34727 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_river.cpp @@ -59,7 +59,7 @@ void RegionTable_Init_ZoraRiver() { }, { //Exits ENTRANCE(RR_ZR_FRONT, logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_POWER_BRACELET) || logic->BlastOrSmash() || logic->HasItem(RG_HOVER_BOOTS)), - ENTRANCE(RR_ZR_ATOP_LADDER, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) && (logic->CanClimbLadder() || CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL))), + ENTRANCE(RR_ZR_ATOP_LADDER, ((logic->IsAdult || logic->HasItem(RG_POWER_BRACELET)) && logic->CanClimbLadder()) || (logic->IsAdult && CanPlantBean(RR_ZORAS_RIVER, RG_ZORAS_RIVER_BEAN_SOUL))), ENTRANCE(RR_ZR_PILLAR, (logic->IsChild && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_ZR_LOWER))), ENTRANCE(RR_ZR_FROM_SHORTCUT, logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS)), ENTRANCE(RR_ZR_STORMS_GROTTO, logic->CanOpenStormsGrotto()), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 427a6c4c2..18366f479 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -1396,9 +1396,20 @@ uint8_t Logic::Hearts() { } uint8_t Logic::DungeonCount() { - return Get(LOGIC_DEKU_TREE_CLEAR) + Get(LOGIC_DODONGOS_CAVERN_CLEAR) + Get(LOGIC_JABU_JABUS_BELLY_CLEAR) + - Get(LOGIC_FOREST_TEMPLE_CLEAR) + Get(LOGIC_FIRE_TEMPLE_CLEAR) + Get(LOGIC_WATER_TEMPLE_CLEAR) + - Get(LOGIC_SPIRIT_TEMPLE_CLEAR) + Get(LOGIC_SHADOW_TEMPLE_CLEAR); + if (CalculatingAvailableChecks) { + return CheckEventChkInf(EVENTCHKINF_USED_DEKU_TREE_BLUE_WARP) + + CheckEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP) + + CheckEventChkInf(EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP) + + CheckEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP) + + CheckEventChkInf(EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP) + + CheckEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP) + + CheckRandoInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE) + + CheckRandoInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); + } else { + return Get(LOGIC_DEKU_TREE_CLEAR) + Get(LOGIC_DODONGOS_CAVERN_CLEAR) + Get(LOGIC_JABU_JABUS_BELLY_CLEAR) + + Get(LOGIC_FOREST_TEMPLE_CLEAR) + Get(LOGIC_FIRE_TEMPLE_CLEAR) + Get(LOGIC_WATER_TEMPLE_CLEAR) + + Get(LOGIC_SPIRIT_TEMPLE_CLEAR) + Get(LOGIC_SHADOW_TEMPLE_CLEAR); + } } uint8_t Logic::StoneCount() { diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h index 687ba9d73..42ecc2bb9 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerTrick.h @@ -76,6 +76,7 @@ RANDO_ENUM_ITEM(RT_LH_WATER_HOOKSHOT) RANDO_ENUM_ITEM(RT_GV_CRATE_HOVERS) RANDO_ENUM_ITEM(RT_GV_CHILD_TENT) RANDO_ENUM_ITEM(RT_GV_CHILD_CUCCO_JUMP) +RANDO_ENUM_ITEM(RT_GV_HOOKSHOT_BRIDGE) RANDO_ENUM_ITEM(RT_PASS_GUARDS_WITH_NOTHING) RANDO_ENUM_ITEM(RT_GF_WASTELAND_GATE_SIDEHOP_SKIP) RANDO_ENUM_ITEM(RT_GF_ADULT_SKIP_WASTELAND_GATE) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index fdd97f669..5c681d307 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1082,13 +1082,21 @@ void CheckTrackerWindow::DrawElement() { } UIWidgets::PushStyleCombobox(THEME_COLOR); if (CVarGetInteger(CVAR_TRACKER_CHECK("SearchInputVisible"), 1)) { - if (checkSearch.Draw("", ImGui::GetContentRegionAvail().x - 6)) { + if (checkSearch.Draw("", ImGui::GetContentRegionAvail().x - 42)) { UpdateFilters(); } - std::string checkSearchText = ""; - checkSearchText = checkSearch.InputBuf; + std::string checkSearchText = checkSearch.InputBuf; checkSearchText.erase(std::remove(checkSearchText.begin(), checkSearchText.end(), ' '), checkSearchText.end()); + ImGui::SameLine(); + if (UIWidgets::Button(ICON_FA_ERASER, UIWidgets::ButtonOptions() + .Size(UIWidgets::Sizes::Inline) + .Color(THEME_COLOR) + .Padding(ImVec2(10.f, 6.f)))) { + checkSearch.Clear(); + UpdateFilters(); + doAreaScroll = true; + } if (checkSearchText.length() < 1) { ImGui::SameLine(20.0f); ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 0.4f), "Search..."); diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index bfa0d2ad1..35a37451b 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1677,6 +1677,10 @@ void Settings::CreateOptions() { OPT_TRICK(RT_GV_CHILD_CUCCO_JUMP, RCQUEST_BOTH, RA_GERUDO_VALLEY, { Tricks::Tag::INTERMEDIATE }, "Gerudo Valley Jump Fence with Cucco", "GVCUC", "Using cucco as child, it's possible to jumpslash over the gate."); + OPT_TRICK(RT_GV_HOOKSHOT_BRIDGE, RCQUEST_BOTH, RA_GERUDO_VALLEY, { Tricks::Tag::ADVANCED }, + "Gerudo Valley Bridge with only Hookshot", "GVHSBrg", + "Using Hookshot Extension and a precise setup, you can cross the broken bridge in Gerudo Valley with " + "only a Hookshot."); OPT_TRICK(RT_PASS_GUARDS_WITH_NOTHING, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE }, "Sneak Past Moving Gerudo Guards with No Items", "Guards", "The logic normally guarantees Bow or Hookshot to stun them from a distance," diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index b1cb15812..fddcb77ce 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include "soh/ShipInit.hpp" #include "message_data_static.h" @@ -37,11 +36,10 @@ nlohmann::json fileChooseMap = nullptr; std::string GetParameritizedText(std::string key, TextBank bank, const char* arg) { switch (bank) { case TEXT_BANK_SCENES: { - return sceneMap[key].get(); - break; + return sceneMap.value(key, "unknown"); } case TEXT_BANK_MISC: { - auto value = miscMap[key].get(); + auto value = miscMap.value(key, "unknown"); std::string searchString = "$0"; size_t index = value.find(searchString); @@ -49,15 +47,11 @@ std::string GetParameritizedText(std::string key, TextBank bank, const char* arg if (index != std::string::npos) { assert(arg != nullptr); value.replace(index, searchString.size(), std::string(arg)); - return value; - } else { - return value; } - - break; + return value; } case TEXT_BANK_KALEIDO: { - auto value = kaleidoMap[key].get(); + auto value = kaleidoMap.value(key, "unknown"); std::string searchString = "$0"; size_t index = value.find(searchString); @@ -65,15 +59,11 @@ std::string GetParameritizedText(std::string key, TextBank bank, const char* arg if (index != std::string::npos) { assert(arg != nullptr); value.replace(index, searchString.size(), std::string(arg)); - return value; - } else { - return value; } - - break; + return value; } case TEXT_BANK_FILECHOOSE: { - auto value = fileChooseMap[key].get(); + auto value = fileChooseMap.value(key, "unknown"); std::string searchString = "$0"; size_t index = value.find(searchString); @@ -81,14 +71,11 @@ std::string GetParameritizedText(std::string key, TextBank bank, const char* arg if (index != std::string::npos) { assert(arg != nullptr); value.replace(index, searchString.size(), std::string(arg)); - return value; - } else { - return value; } - - break; + return value; } } + return "unknown"; } const char* GetLanguageCode() { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7cd67c266..7cfdfc92f 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -445,6 +445,11 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) { std::shared_ptr threadPool = std::make_shared(1); std::optional> extractionTask; + +#if not defined(__SWITCH__) && not defined(__WIIU__) + CheckAndCreateModFolder(); +#endif + while (!extractDone) { if (SohGui::PopupsQueued() > 0 || extractionTask.has_value()) { goto render; @@ -760,10 +765,6 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) { #elif defined(__WIIU__) Ship::WiiU::Init(appShortName); #endif - -#if not defined(__SWITCH__) && not defined(__WIIU__) - CheckAndCreateModFolder(); -#endif } void OTRGlobals::Initialize() { diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 8e9a9059b..c8e6c34d4 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -491,16 +491,18 @@ void SohMenu::AddMenuEnhancements() { AddWidget(path, "Skip Tower Escape", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape")) .Options(CheckboxOptions().Tooltip("Skip the tower escape sequence between Ganondorf and Ganon.")); - AddWidget(path, "Skip Scarecrow's Song", WIDGET_CVAR_CHECKBOX) + AddWidget(path, "Skip Playing Scarecrow's Song", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("InstantScarecrow")) .PreFunc([](WidgetInfo& info) { info.options->disabled = IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_SKIP_SCARECROWS_SONG); - info.options->disabledTooltip = "This setting is forcefully enabled because a randomized " - "save file with the option \"Skip Scarecrow Song\" is currently loaded."; + info.options->disabledTooltip = "This setting is forcefully enabled because a randomized save " + "file with the option \"Skip Scarecrow's Song\" is currently loaded."; }) .Options(CheckboxOptions().Tooltip( - "Pierre appears when an Ocarina is pulled out. Requires learning the Scarecrow's Song first.")); + "Pierre appears when an Ocarina is pulled out. Requires learning the Scarecrow's Song first.\n" + "Without the randomizer option \"Skip Scarecrow's Song\" enabled for a seed, this still requires you " + "to teach the scarecrow the song as both ages before summoning.")); AddWidget(path, "Faster Rupee Accumulator", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("FasterRupeeAccumulator")) .Options(CheckboxOptions().Tooltip("Causes your Wallet to fill and empty faster when you gain or lose money.")); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index f0ca7c0cd..54c33e2cf 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -3491,12 +3491,6 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) { // Execute before actor memory is freed GameInteractor_ExecuteOnActorDestroy(actor); - dbEntry = ActorDB_Retrieve(actor->id); - - if (HREG(20) != 0) { - osSyncPrintf("アクタークラス削除 [%s]\n", dbEntry->name); // "Actor class deleted [%s]" - } - if ((player != NULL) && (actor == player->focusActor)) { Player_ReleaseLockOn(player); Camera_ChangeMode(Play_GetCamera(play, Play_GetActiveCamId(play)), 0); @@ -3517,6 +3511,12 @@ Actor* Actor_Delete(ActorContext* actorCtx, Actor* actor, PlayState* play) { Audio_StopSfxByPos(&actor->projectedPos); Actor_Destroy(actor, play); + dbEntry = ActorDB_Retrieve(actor->id); + + if (HREG(20) != 0) { + osSyncPrintf("アクタークラス削除 [%s]\n", dbEntry->name); // "Actor class deleted [%s]" + } + newHead = Actor_RemoveFromCategory(play, actorCtx, actor); // #region SOH [ObjectExtension]