From bea3c6dae04b92b0c10991ccaf387051adec396b Mon Sep 17 00:00:00 2001 From: Taw Date: Fri, 9 Feb 2024 14:17:17 -0800 Subject: [PATCH] GameInteractor hooks for adult and child shooting gallery --- .../game-interactor/GameInteractor.h | 6 +++ .../Enhancements/randomizer/hook_handlers.cpp | 21 ++++++++++ .../Enhancements/randomizer/location_list.cpp | 4 +- .../ovl_En_Syateki_Man/z_en_syateki_man.c | 39 +++++-------------- .../ovl_En_Syateki_Man/z_en_syateki_man.h | 1 - 5 files changed, 39 insertions(+), 32 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index c6fb7c721..bffed5458 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -203,6 +203,9 @@ typedef enum { GI_VB_OVERRIDE_LINK_THE_GORON_DIALOGUE, // Opt: *EnGo2 GI_VB_EN_GO2_RESET_AFTER_GET_ITEM, + // Opt: *EnSyatekiMan + // Vanilla condition: (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50) + GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, /*** Play Cutscenes ***/ @@ -269,6 +272,9 @@ typedef enum { // Opt: *EnFr GI_VB_GIVE_ITEM_FROM_FROGS, + // Opt: *EnSyatekiMan + GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, + GI_VB_GIVE_ITEM_FAIRY_OCARINA, GI_VB_GIVE_ITEM_WEIRD_EGG, GI_VB_GIVE_ITEM_LIGHT_ARROW, diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index bf236a3ba..6e9a6809a 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -23,6 +23,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Go2/z_en_go2.h" #include "src/overlays/actors/ovl_En_Ms/z_en_ms.h" #include "src/overlays/actors/ovl_En_Fr/z_en_fr.h" +#include "src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h" #include "adult_trade_shuffle.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; @@ -775,6 +776,26 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should &= !EnDs_RandoCanGetGrannyItem(); break; } + case GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY: { + EnSyatekiMan* enSyatekiMan = static_cast(optionalArg); + enSyatekiMan->getItemId = GI_RUPEE_PURPLE; + if (LINK_IS_ADULT) { + // Give purple rupee if we've already obtained the reward OR we don't have a bow + *should = Flags_GetItemGetInf(ITEMGETINF_0E) || CUR_UPG_VALUE(UPG_QUIVER) == 0; + } else { + // Give purple rupee if we've already obtained the reward + *should = Flags_GetItemGetInf(ITEMGETINF_0D); + } + break; + } + case GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD: { + *should = CUR_UPG_VALUE(UPG_QUIVER) > 0; + if (!*should) { + // In Rando without a quiver, display a message reminding the player to come back with a bow + Message_StartTextbox(gPlayState, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, NULL); + } + break; + } case GI_VB_TRADE_CLAIM_CHECK: case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: diff --git a/soh/soh/Enhancements/randomizer/location_list.cpp b/soh/soh/Enhancements/randomizer/location_list.cpp index 28ca3b85a..67b2b35ed 100644 --- a/soh/soh/Enhancements/randomizer/location_list.cpp +++ b/soh/soh/Enhancements/randomizer/location_list.cpp @@ -672,7 +672,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x3E, "Bombchu Bowling Second Prize", "MK Bombchu Bowling Second Prize", RHT_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS] = Location::Base(RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_BOMBCHU_BOWLING_ALLEY, 0x00, 0x00, "Bombchu Bowling Bombchus", "MK Bombchu Bowling Bombchus", RHT_MARKET_BOMBCHU_BOWLING_BOMBCHUS, RG_BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); locationTable[RC_MARKET_LOST_DOG] = Location::Base(RC_MARKET_LOST_DOG, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_DOG_LADY_HOUSE, 0x00, 0x3E, "Lost Dog", "MK Lost Dog", RHT_MARKET_LOST_DOG, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); - locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(13), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); + locationTable[RC_MARKET_SHOOTING_GALLERY_REWARD] = Location::Base(RC_MARKET_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x60, "Shooting Gallery", "MK Shooting Gallery", RHT_MARKET_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0D), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_10_BIG_POES] = Location::Base(RC_MARKET_10_BIG_POES, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_MARKET, ACTOR_ID_MAX, SCENE_MARKET_GUARD_HOUSE, 0x00, 0x0F, "10 Big Poes", "MK 10 Big Poes", RHT_MARKET_10_BIG_POES, RG_EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_10_BIG_POES), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE, true); locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_1] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x01, "Chest Game First Room Chest", "MK Chest Game First Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_1, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); locationTable[RC_MARKET_TREASURE_CHEST_GAME_ITEM_2] = Location::Chest(RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, RCQUEST_BOTH, RCTYPE_CHEST_GAME, RCAREA_MARKET, ACTOR_EN_BOX, SCENE_TREASURE_BOX_SHOP, 0x00, 0x03, "Chest Game Second Room Chest", "MK Chest Game Second Room Chest", RHT_MARKET_TREASURE_CHEST_GAME_ITEM_2, RG_TREASURE_GAME_SMALL_KEY, { Category::cChestMinigame }, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE); @@ -692,7 +692,7 @@ void Rando::StaticData::InitLocationTable() { // locationTable[RC_KAK_50_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_50_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "50 Gold Skulltula Reward", "Kak 50 Gold Skulltula Reward", RHT_KAK_50_GOLD_SKULLTULA_REWARD, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_100_GOLD_SKULLTULA_REWARD] = Location::Base(RC_KAK_100_GOLD_SKULLTULA_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_HOUSE_OF_SKULLTULA, 0x00, 0x3E, "100 Gold Skulltula Reward", "Kak 100 Gold Skulltula Reward", RHT_KAK_100_GOLD_SKULLTULA_REWARD, RG_HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO); locationTable[RC_KAK_MAN_ON_ROOF] = Location::Base(RC_KAK_MAN_ON_ROOF, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x3E, "Man on Roof", "Kak Man on Roof", RHT_KAK_MAN_ON_ROOF, RG_PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); - locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); + locationTable[RC_KAK_SHOOTING_GALLERY_REWARD] = Location::Base(RC_KAK_SHOOTING_GALLERY_REWARD, RCQUEST_BOTH, RCTYPE_STANDARD, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_SHOOTING_GALLERY, 0x00, 0x30, "Shooting Gallery Reward", "Kak Shooting Gallery Reward", RHT_KAK_SHOOTING_GALLERY_REWARD, RG_PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(ITEMGETINF_0E), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_TRADE_ODD_MUSHROOM] = Location::Base(RC_KAK_TRADE_ODD_MUSHROOM, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x20, "Trade Odd Mushroom", "Kak Trade Odd Mushroom", RHT_KAK_TRADE_ODD_MUSHROOM, RG_ODD_POTION, { Category::cAdultTrade }, SpoilerCollectionCheck::ItemGetInf(48), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_GRANNYS_SHOP] = Location::Base(RC_KAK_GRANNYS_SHOP, RCQUEST_BOTH, RCTYPE_MERCHANT, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_POTION_SHOP_GRANNY, 0x00, 0x4E, "Granny's Shop", "Kak Granny's Shop", RHT_KAK_GRANNYS_SHOP, RG_BUY_BLUE_POTION, {}, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); locationTable[RC_KAK_ANJU_AS_ADULT] = Location::Base(RC_KAK_ANJU_AS_ADULT, RCQUEST_BOTH, RCTYPE_ADULT_TRADE, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, 0x1D, "Anju as Adult", "Kak Anju as Adult", RHT_KAK_ANJU_AS_ADULT, RG_CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(44), SpoilerCollectionCheckGroup::GROUP_KAKARIKO, true); diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 6ab91ddc0..d84298800 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -4,6 +4,7 @@ #include "objects/object_ossan/object_ossan.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_LOCKON) @@ -180,7 +181,6 @@ void EnSyatekiMan_Init(Actor* thisx, PlayState* play) { this->blinkFunc = EnSyatekiMan_BlinkWait; this->actor.colChkInfo.cylRadius = 100; this->actionFunc = EnSyatekiMan_Start; - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; } void EnSyatekiMan_Destroy(Actor* thisx, PlayState* play) { @@ -355,11 +355,7 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->tempGallery = this->actor.parent; this->actor.parent = NULL; if (!LINK_IS_ADULT) { - if(IS_RANDO && !Flags_GetTreasure(play, 0x1E)) { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_MARKET_SHOOTING_GALLERY_REWARD, GI_BULLET_BAG_50); - this->getItemId = this->getItemEntry.getItemId; - Flags_SetTreasure(play, 0x1E); - } else if (!IS_RANDO && !Flags_GetItemGetInf(ITEMGETINF_0D)) { + if (!Flags_GetItemGetInf(ITEMGETINF_0D)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Pachinko ☆☆☆☆☆ %d\n" VT_RST, CUR_UPG_VALUE(UPG_BULLET_BAG)); if (CUR_UPG_VALUE(UPG_BULLET_BAG) == 1) { @@ -368,16 +364,11 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { this->getItemId = GI_BULLET_BAG_50; } } else { - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->getItemId = GI_RUPEE_PURPLE; } } else { // Only give the adult rando reward when the player has a quiver - if (IS_RANDO && !Flags_GetTreasure(play, 0x1F) && CUR_UPG_VALUE(UPG_QUIVER) > 0) { - this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_SHOOTING_GALLERY_REWARD, GI_QUIVER_50); - this->getItemId = this->getItemEntry.getItemId; - Flags_SetTreasure(play, 0x1F); - } else if (!IS_RANDO && !Flags_GetItemGetInf(ITEMGETINF_0E)) { + if (!Flags_GetItemGetInf(ITEMGETINF_0E)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ Equip_Bow ☆☆☆☆☆ %d\n" VT_RST, CUR_UPG_VALUE(UPG_QUIVER)); switch (CUR_UPG_VALUE(UPG_QUIVER)) { @@ -392,14 +383,11 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { break; } } else { - this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; this->getItemId = GI_RUPEE_PURPLE; } } - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { + if (GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); } this->actionFunc = EnSyatekiMan_GivePrize; break; @@ -426,33 +414,26 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) { } } } -} +} void EnSyatekiMan_GivePrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if (Actor_HasParent(&this->actor, play)) { + if (Actor_HasParent(&this->actor, play) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { this->actionFunc = EnSyatekiMan_FinishPrize; - } else { - if (!IS_RANDO || this->getItemEntry.getItemId == GI_NONE) { - func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); - } else { - GiveItemEntryFromActor(&this->actor, play, this->getItemEntry, 2000.0f, 1000.0f); - } + } else { + func_8002F434(&this->actor, play, this->getItemId, 2000.0f, 1000.0f); } } void EnSyatekiMan_FinishPrize(EnSyatekiMan* this, PlayState* play) { SkelAnime_Update(&this->skelAnime); - if ((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) { + if (((Message_GetState(&play->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(play)) || !GameInteractor_Should(GI_VB_GIVE_ITEM_FROM_SHOOTING_GALLERY, true, this)) { // "Successful completion" osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 正常終了 ☆☆☆☆☆ \n" VT_RST); if (!LINK_IS_ADULT) { Flags_SetItemGetInf(ITEMGETINF_0D); - } else if ((this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50)) { + } else if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_ADULT_SHOOTING_GAME_REWARD, (this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50), this)) { Flags_SetItemGetInf(ITEMGETINF_0E); - } else if (IS_RANDO && LINK_IS_ADULT && CUR_UPG_VALUE(UPG_QUIVER) == 0) { - // In Rando without a quiver, display a message reminding the player to come back with a bow - Message_StartTextbox(play, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, NULL); } this->gameResult = SYATEKI_RESULT_NONE; this->actor.parent = this->tempGallery; diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h index eaeec0429..b65364ae4 100644 --- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h +++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h @@ -28,7 +28,6 @@ typedef struct EnSyatekiMan { /* 0x0220 */ Actor* tempGallery; /* 0x0224 */ EnSyatekiManOtherFunc blinkFunc; // Seems to be part of a blink system with unk_20C and unk_20E, but it's unused. /* 0x0228 */ s16 csCam; - /* */ GetItemEntry getItemEntry; } EnSyatekiMan; // size = 0x022C #endif