summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Dubé <159546+serprex@users.noreply.github.com>2026-04-23 12:34:26 +0000
committerGitHub <noreply@github.com>2026-04-23 12:34:26 +0000
commit806398a65b04c994d6472eb482e0de400d48cc72 (patch)
tree43015bcde22593d8074302bb6dd41dbcb38c330d
parent3221d8a988513618986423f36c8c02c8f4dc2435 (diff)
Fix OGC great fairy reward in vanilla with skip misc interactions when fish is not obtainable (#6556)
Item_CheckObtainability should only be called with MOD_NONE GI For RG_DOUBLE_DEFENSE that became ITEM_FISH. Nonsense ensued To reproduce issue, create debug save & go straight to OGC great fairy with only magic/ocarina/lullaby
-rw-r--r--soh/soh/Enhancements/randomizer/item.h1
-rw-r--r--soh/soh/Enhancements/timesaver_hook_handlers.cpp62
-rw-r--r--soh/src/code/z_actor.c15
-rw-r--r--soh/src/code/z_player_lib.c1
-rw-r--r--soh/src/overlays/actors/ovl_player_actor/z_player.c9
5 files changed, 43 insertions, 45 deletions
diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h
index ab4b3c119..f48415910 100644
--- a/soh/soh/Enhancements/randomizer/item.h
+++ b/soh/soh/Enhancements/randomizer/item.h
@@ -1,7 +1,6 @@
#pragma once
#include <string>
-#include <variant>
#include <memory>
#include "3drando/text.hpp"
diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp
index b60922434..204de040f 100644
--- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp
+++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp
@@ -24,7 +24,6 @@ extern "C" {
#include "src/overlays/actors/ovl_En_Jj/z_en_jj.h"
#include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h"
#include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h"
-#include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h"
#include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h"
#include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h"
#include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h"
@@ -1241,41 +1240,41 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
case FLAG_EVENT_CHECK_INF:
switch (flag) {
case EVENTCHKINF_SPOKE_TO_SARIA_ON_BRIDGE:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FAIRY_OCARINA).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_FAIRY_OCARINA);
break;
case EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_KOKIRI_EMERALD).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_KOKIRI_EMERALD);
break;
case EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_GORON_RUBY).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_GORON_RUBY);
break;
case EVENTCHKINF_USED_JABU_JABUS_BELLY_BLUE_WARP:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZORA_SAPPHIRE).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_ZORA_SAPPHIRE);
break;
case EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FOREST_MEDALLION).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_FOREST_MEDALLION);
break;
case EVENTCHKINF_USED_FIRE_TEMPLE_BLUE_WARP:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FIRE_MEDALLION).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_FIRE_MEDALLION);
break;
case EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_WATER_MEDALLION).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_WATER_MEDALLION);
break;
case EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_ARROWS).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_LIGHT_ARROWS);
break;
case EVENTCHKINF_TIME_TRAVELED_TO_ADULT:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_LIGHT_MEDALLION).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_LIGHT_MEDALLION);
break;
}
break;
case FLAG_RANDOMIZER_INF:
switch (flag) {
case RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SHADOW_MEDALLION).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_SHADOW_MEDALLION);
break;
case RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SPIRIT_MEDALLION).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_SPIRIT_MEDALLION);
break;
}
break;
@@ -1287,22 +1286,22 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
case FLAG_RANDOMIZER_INF:
switch (flag) {
case RAND_INF_ZF_GREAT_FAIRY_REWARD:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_FARORES_WIND).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_FARORES_WIND);
break;
case RAND_INF_HC_GREAT_FAIRY_REWARD:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DINS_FIRE).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_DINS_FIRE);
break;
case RAND_INF_COLOSSUS_GREAT_FAIRY_REWARD:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_NAYRUS_LOVE).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_NAYRUS_LOVE);
break;
case RAND_INF_DMT_GREAT_FAIRY_REWARD:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_SINGLE).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_MAGIC_SINGLE);
break;
case RAND_INF_DMC_GREAT_FAIRY_REWARD:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MAGIC_DOUBLE).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_MAGIC_DOUBLE);
break;
case RAND_INF_OGC_GREAT_FAIRY_REWARD:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_DOUBLE_DEFENSE).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_DOUBLE_DEFENSE);
break;
}
break;
@@ -1328,47 +1327,44 @@ void TimeSaverOnFlagSetHandler(int16_t flagType, int16_t flag) {
case FLAG_EVENT_CHECK_INF:
switch (flag) {
case EVENTCHKINF_LEARNED_ZELDAS_LULLABY:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_ZELDAS_LULLABY).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_ZELDAS_LULLABY);
break;
case EVENTCHKINF_LEARNED_MINUET_OF_FOREST:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_MINUET_OF_FOREST).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_MINUET_OF_FOREST);
break;
case EVENTCHKINF_LEARNED_BOLERO_OF_FIRE:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_BOLERO_OF_FIRE).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_BOLERO_OF_FIRE);
break;
case EVENTCHKINF_LEARNED_SERENADE_OF_WATER:
- vanillaQueuedItemEntry =
- Rando::StaticData::RetrieveItem(RG_SERENADE_OF_WATER).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_SERENADE_OF_WATER);
break;
case EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT:
- vanillaQueuedItemEntry =
- Rando::StaticData::RetrieveItem(RG_REQUIEM_OF_SPIRIT).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_REQUIEM_OF_SPIRIT);
break;
case EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL:
- vanillaQueuedItemEntry =
- Rando::StaticData::RetrieveItem(RG_NOCTURNE_OF_SHADOW).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_NOCTURNE_OF_SHADOW);
break;
case EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_PRELUDE_OF_LIGHT).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_PRELUDE_OF_LIGHT);
break;
case EVENTCHKINF_LEARNED_SARIAS_SONG:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SARIAS_SONG).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_SARIAS_SONG);
break;
case EVENTCHKINF_LEARNED_SONG_OF_TIME:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_TIME).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_SONG_OF_TIME);
break;
case EVENTCHKINF_LEARNED_SONG_OF_STORMS:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SONG_OF_STORMS).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_SONG_OF_STORMS);
break;
case EVENTCHKINF_LEARNED_SUNS_SONG:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_SUNS_SONG).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_SUNS_SONG);
break;
}
break;
case FLAG_RANDOMIZER_INF:
switch (flag) {
case RAND_INF_LEARNED_EPONA_SONG:
- vanillaQueuedItemEntry = Rando::StaticData::RetrieveItem(RG_EPONAS_SONG).GetGIEntry_Copy();
+ TimeSaverQueueItem(RG_EPONAS_SONG);
break;
}
break;
diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c
index 54c33e2cf..f69a7ea8c 100644
--- a/soh/src/code/z_actor.c
+++ b/soh/src/code/z_actor.c
@@ -2032,8 +2032,10 @@ s32 GiveItemEntryWithoutActor(PlayState* play, GetItemEntry getItemEntry) {
PLAYER_STATE1_CLIMBING_LEDGE | PLAYER_STATE1_JUMPING | PLAYER_STATE1_FREEFALL | PLAYER_STATE1_FIRST_PERSON |
PLAYER_STATE1_CLIMBING_LADDER)) &&
Player_GetExplosiveHeld(player) < 0) {
- if (((player->heldActor != NULL) && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX)) ||
- (IS_RANDO && (getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))) ||
+ if (((player->heldActor != NULL && (getItemEntry.modIndex == MOD_NONE && getItemEntry.getItemId > GI_NONE &&
+ getItemEntry.getItemId < GI_MAX)) ||
+ (getItemEntry.modIndex == MOD_RANDOMIZER && getItemEntry.getItemId > RG_NONE &&
+ getItemEntry.getItemId < RG_MAX)) ||
(!(player->stateFlags1 & (PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE)))) {
if ((getItemEntry.getItemId != GI_NONE)) {
player->getItemEntry = getItemEntry;
@@ -2073,8 +2075,10 @@ s32 GiveItemEntryFromActor(Actor* actor, PlayState* play, GetItemEntry getItemEn
PLAYER_STATE1_CLIMBING_LADDER)) &&
Player_GetExplosiveHeld(player) < 0) {
if ((((player->heldActor != NULL) || (actor == player->talkActor)) &&
- ((!IS_RANDO && ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX))) ||
- (IS_RANDO && ((getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))))) ||
+ ((getItemEntry.getItemId == MOD_NONE &&
+ ((getItemEntry.getItemId > GI_NONE) && (getItemEntry.getItemId < GI_MAX))) ||
+ (getItemEntry.getItemId == MOD_RANDOMIZER &&
+ ((getItemEntry.getItemId > RG_NONE) && (getItemEntry.getItemId < RG_MAX))))) ||
(!(player->stateFlags1 & (PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE)))) {
if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) {
s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y;
@@ -2118,8 +2122,7 @@ s32 Actor_OfferGetItem(Actor* actor, PlayState* play, s32 getItemId, f32 xzRange
PLAYER_STATE1_CLIMBING_LADDER)) &&
Player_GetExplosiveHeld(player) < 0) {
if ((((player->heldActor != NULL) || (actor == player->talkActor)) &&
- ((!IS_RANDO && ((getItemId > GI_NONE) && (getItemId < GI_MAX))) ||
- (IS_RANDO && ((getItemId > RG_NONE) && (getItemId < RG_MAX))))) ||
+ ((getItemId > GI_NONE) && (getItemId < GI_MAX))) ||
(!(player->stateFlags1 & (PLAYER_STATE1_CARRYING_ACTOR | PLAYER_STATE1_IN_CUTSCENE)))) {
if ((actor->xzDistToPlayer < xzRange) && (fabsf(actor->yDistToPlayer) < yRange)) {
s16 yawDiff = actor->yawTowardsPlayer - player->actor.shape.rot.y;
diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c
index 83dfd7608..79bf0bfb6 100644
--- a/soh/src/code/z_player_lib.c
+++ b/soh/src/code/z_player_lib.c
@@ -3,7 +3,6 @@
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
#include "objects/object_link_boy/object_link_boy.h"
#include "objects/object_link_child/object_link_child.h"
-#include "objects/object_triforce_spot/object_triforce_spot.h"
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
#include "soh/Enhancements/game-interactor/GameInteractor.h"
diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c
index 5aa9d9470..804292a78 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -7339,8 +7339,9 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) {
// getting bombchus need to show the cutscene) and whenever the player doesn't have the item yet. In
// rando, we're overruling this because we need to keep showing the cutscene because those items can be
// randomized and thus it's important to keep showing the cutscene.
- uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY ||
- Item_CheckObtainability(giEntry.itemId) == ITEM_NONE || IS_RANDO;
+ uint8_t showItemCutscene = play->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY || IS_RANDO ||
+ giEntry.modIndex == MOD_RANDOMIZER ||
+ Item_CheckObtainability(giEntry.itemId) == ITEM_NONE;
// Only skip cutscenes for drops when they're items/consumables from bushes/rocks/enemies.
uint8_t isDropToSkip =
@@ -7359,8 +7360,8 @@ s32 Player_ActionHandler_2(Player* this, PlayState* play) {
// the player already has because those items could be a randomized item coming from scrubs,
// freestanding PoH's and keys. So we need to once again overrule this specifically for items coming
// from bushes/rocks/enemies when the player has already picked that item up.
- uint8_t skipItemCutsceneRando =
- IS_RANDO && Item_CheckObtainability(giEntry.itemId) != ITEM_NONE && isDropToSkip;
+ uint8_t skipItemCutsceneRando = IS_RANDO && giEntry.modIndex == MOD_NONE &&
+ Item_CheckObtainability(giEntry.itemId) != ITEM_NONE && isDropToSkip;
// Show cutscene when picking up a item.
if (showItemCutscene && !skipItemCutscene && !skipItemCutsceneRando) {