Merge pull request #6425 from HarbourMasters/develop-ackbar

merge develop-ackbar 9.2.1 to develop
This commit is contained in:
Philip Dubé
2026-03-28 06:26:13 +00:00
committed by GitHub
26 changed files with 135 additions and 74 deletions

View File

@@ -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)

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -1,5 +1,6 @@
#include <libultraship/bridge.h>
#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;
}
}

View File

@@ -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<std::string> 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

View File

@@ -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<CheckIdentity>(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<CheckIdentity>(actor);
if (fairyIdentity != nullptr && fairyIdentity->randomizerInf != RAND_INF_MAX) {
Flags_SetRandomizerInf(fairyIdentity->randomizerInf);
actor->parent = &GET_PLAYER(gPlayState)->actor;
*should = false;
}
}
});

View File

@@ -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);

View File

@@ -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()),
}, {

View File

@@ -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)),

View File

@@ -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))),

View File

@@ -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())),
});

View File

@@ -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, {}, {

View File

@@ -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),

View File

@@ -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)),
});

View File

@@ -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),

View File

@@ -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()),

View File

@@ -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() {

View File

@@ -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)

View File

@@ -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...");

View File

@@ -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,"

View File

@@ -6,7 +6,6 @@
#include <ship/resource/type/Json.h>
#include <libultraship/classes.h>
#include <nlohmann/json.hpp>
#include <spdlog/fmt/fmt.h>
#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<std::string>();
break;
return sceneMap.value(key, "unknown");
}
case TEXT_BANK_MISC: {
auto value = miscMap[key].get<std::string>();
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<std::string>();
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<std::string>();
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() {

View File

@@ -445,6 +445,11 @@ void OTRGlobals::RunExtract(int argc, char* argv[]) {
std::shared_ptr<BS::thread_pool> threadPool = std::make_shared<BS::thread_pool>(1);
std::optional<std::future<void>> 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() {

View File

@@ -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."));

View File

@@ -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]