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
This commit is contained in:
Philip Dubé
2026-04-23 12:34:26 +00:00
committed by GitHub
parent 3221d8a988
commit 806398a65b
5 changed files with 43 additions and 45 deletions
-1
View File
@@ -1,7 +1,6 @@
#pragma once
#include <string>
#include <variant>
#include <memory>
#include "3drando/text.hpp"
@@ -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;
+9 -6
View File
@@ -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;
-1
View File
@@ -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"
@@ -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) {