diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index 2cceebc4845..3b5dd5692c7 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -58,6 +58,11 @@ DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list or DEFINE_HOOK(OnSaveFile, (int32_t fileNum, int32_t sectionID)); DEFINE_HOOK(OnLoadFile, (int32_t fileNum)); DEFINE_HOOK(OnDeleteFile, (int32_t fileNum)); +DEFINE_HOOK(OnLinkAnimEnd, (SkelAnime * skelAnime)); +DEFINE_HOOK(OnQPADamage, (uint32_t * dmgFlags)); +DEFINE_HOOK(OnESS, ()); +DEFINE_HOOK(OnWaitForPutaway, ()); +DEFINE_HOOK(OnAnimationSetLoadFrame, (LinkAnimationHeader * animation, int32_t* frame)); DEFINE_HOOK(OnDialogMessage, ()); DEFINE_HOOK(OnPresentTitleCard, ()); @@ -85,6 +90,7 @@ DEFINE_HOOK(OnGenerationCompletion, ()); DEFINE_HOOK(OnSetGameLanguage, ()); DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnKaleidoUpdate, ()); +DEFINE_HOOK(OnKaleidoMoveCursorFromSpecialPos, (PauseContext * pauseCtx, uint16_t* cursorItem)); // Messages DEFINE_HOOK(OnOpenText, (uint16_t * textId, bool* loadFromMessageTable)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index b754e9c949c..4c02f8d7da2 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -122,6 +122,26 @@ void GameInteractor_ExecuteOnCuccoOrChickenHatch() { GameInteractor::Instance->ExecuteHooks(); } +void GameInteractor_ExecuteOnLinkAnimEnd(SkelAnime* skelAnime) { + GameInteractor::Instance->ExecuteHooks(skelAnime); +} + +void GameInteractor_ExecuteOnQPADamage(uint32_t* dmgFlags) { + GameInteractor::Instance->ExecuteHooks(dmgFlags); +} + +void GameInteractor_ExecuteOnESS() { + GameInteractor::Instance->ExecuteHooks(); +} + +void GameInteractor_ExecuteOnWaitForPutaway() { + GameInteractor::Instance->ExecuteHooks(); +} + +void GameInteractor_ExecuteOnAnimationSetLoadFrame(LinkAnimationHeader* animation, int32_t* frame) { + GameInteractor::Instance->ExecuteHooks(animation, frame); +} + void GameInteractor_ExecuteOnShopSlotChangeHooks(uint8_t cursorIndex, int16_t price) { GameInteractor::Instance->ExecuteHooks(cursorIndex, price); } @@ -383,6 +403,10 @@ void GameInteractor_ExecuteOnKaleidoUpdate() { GameInteractor::Instance->ExecuteHooks(); } +void GameInteractor_ExecuteOnKaleidoMoveCursorFromSpecialPos(PauseContext* pauseCtx, uint16_t* cursorItem) { + GameInteractor::Instance->ExecuteHooks(pauseCtx, cursorItem); +} + // MARK: Messages void GameInteractor_ExecuteOnOpenText(uint16_t* textId, bool* loadFromMessageTable) { GameInteractor::Instance->ExecuteHooks(textId, loadFromMessageTable); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index c93568712bf..3f1f3101685 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -34,6 +34,11 @@ void GameInteractor_ExecuteOnPlayerSfx(u16 sfxId); void GameInteractor_ExecuteOnOcarinaSongAction(); void GameInteractor_ExecuteOnOcarinaNote(uint8_t note, float modulator, int8_t bend); void GameInteractor_ExecuteOnCuccoOrChickenHatch(); +void GameInteractor_ExecuteOnLinkAnimEnd(SkelAnime* skelAnime); +void GameInteractor_ExecuteOnQPADamage(uint32_t* dmgFlags); +void GameInteractor_ExecuteOnESS(); +void GameInteractor_ExecuteOnWaitForPutaway(); +void GameInteractor_ExecuteOnAnimationSetLoadFrame(LinkAnimationHeader* animation, int32_t* frame); bool GameInteractor_ShouldActorInit(void* actor); void GameInteractor_ExecuteOnActorInit(void* actor); void GameInteractor_ExecuteOnActorSpawn(void* actor); @@ -96,6 +101,7 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)); // Mark: - Pause Menu void GameInteractor_ExecuteOnKaleidoUpdate(); +void GameInteractor_ExecuteOnKaleidoMoveCursorFromSpecialPos(PauseContext* pauseCtx, uint16_t* cursorItem); // MARK: - Messages void GameInteractor_ExecuteOnOpenText(uint16_t* textId, bool* loadFromMessageTable); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index d1ed4534100..a36b1de945f 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2965,7 +2965,23 @@ typedef enum { // ``` // #### `args` // - `*int32_t (camId)` - VB_SHOULD_LOAD_BG_IMAGE + VB_SHOULD_LOAD_BG_IMAGE, + + // #### `result` + // ```c + // false + // ``` + // #### `args` + // - None + VB_SKIP_FORCE_PLAY_OCARINA, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - None + VB_HOVER_WITH_ISG, } GIVanillaBehavior; #endif diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index 2b2fd83f100..e53d78bfc9c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2154,6 +2154,80 @@ void StaticData::HintTable_Init_Item() { CustomMessage("a four legged friend", /*german*/"ein vierbeiniger Freund", /*french*/"un puissant animal")}); // /*spanish*/una amiga cuadrúpeda + hintTextTable[RHT_ABILITY_ISG] = HintText(CustomMessage("ISG", /*german*/"ISG", /*french*/"ISG"), + // /*spanish*/ISG + { + CustomMessage("a flashy weapon", /*german*/"ISG", /*french*/"ISG") + // /*spanish*/ISG + }, { + CustomMessage("a permanent hitbox", /*german*/"ISG", /*french*/"ISG")}); + // /*spanish*/ISG + + hintTextTable[RHT_ABILITY_OI] = HintText(CustomMessage("OI", /*german*/"OI", /*french*/"OI"), + // /*spanish*/OI + { + CustomMessage("a musical bottle", /*german*/"OI", /*french*/"OI") + // /*spanish*/OI + }, { + CustomMessage("a potato of any color", /*german*/"OI", /*french*/"OI")}); + // /*spanish*/OI + hintTextTable[RHT_ABILITY_QPA] = HintText(CustomMessage("QPA", /*german*/"QPA", /*french*/"QPA"), + // /*spanish*/QPA + { + CustomMessage("some funky damage", /*german*/"QPA", /*french*/"QPA") + // /*spanish*/QPA + }, { + CustomMessage("some fast hands", /*german*/"QPA", /*french*/"QPA")}); + // /*spanish*/QPA + hintTextTable[RHT_ABILITY_HESS] = HintText(CustomMessage("Extended Superslide", /*german*/"Extended Superslide", /*french*/"Extended Superslide"), + // /*spanish*/Extended Superslide + { + CustomMessage("some explosive speed", /*german*/"Extended Superslide", /*french*/"Extended Superslide") + // /*spanish*/Extended Superslide + }, { + CustomMessage("some slick feet", /*german*/"Extended Superslide", /*french*/"Extended Superslide")}); + // /*spanish*/Extended Superslide + hintTextTable[RHT_ABILITY_SUPERSLIDE] = HintText(CustomMessage("Superslide", /*german*/"Superslide", /*french*/"Superslide"), + // /*spanish*/Superslide + { + CustomMessage("some straight line speed", /*german*/"Superslide", /*french*/"Superslide") + // /*spanish*/Superslide + }, { + CustomMessage("some shield power", /*german*/"Superslide", /*french*/"Superslide")}); + // /*spanish*/Superslide + hintTextTable[RHT_ABILITY_HOVER] = HintText(CustomMessage("Hovering", /*german*/"Hovering", /*french*/"Hovering"), + // /*spanish*/Hovering + { + CustomMessage("a weightless trick", /*german*/"Hovering", /*french*/"Hovering") + // /*spanish*/Hovering + }, { + CustomMessage("gravityn't", /*german*/"Hovering", /*french*/"Hovering")}); + // /*spanish*/Hovering + hintTextTable[RHT_ABILITY_EQUIP_SWAP] = HintText(CustomMessage("Equip Swap", /*german*/"Equip Swap", /*french*/"Equip Swap"), + // /*spanish*/Equip Swap + { + CustomMessage("an unbufferable ability", /*german*/"Equip Swap", /*french*/"Equip Swap") + // /*spanish*/Equip Swap + }, { + CustomMessage("a timeless talent", /*german*/"Equip Swap", /*french*/"Equip Swap")}); + // /*spanish*/Equip Swap + hintTextTable[RHT_ABILITY_GROUND_JUMP] = HintText(CustomMessage("Ground Jump", /*german*/"Ground Jump", /*french*/"Ground Jump"), + // /*spanish*/Ground Jump + { + CustomMessage("a little leap", /*german*/"Ground Jump", /*french*/"Ground Jump") + // /*spanish*/Ground Jump + }, { + CustomMessage("a beginner's trick", /*german*/"Ground Jump", /*french*/"Ground Jump")}); + // /*spanish*/Ground Jump + hintTextTable[RHT_ABILITY_WEIRDSHOT] = HintText(CustomMessage("Weirdshot", /*german*/"Weirdshot", /*french*/"Weirdshot"), + // /*spanish*/Weirdshot + { + CustomMessage("a weird shot", /*german*/"Weirdshot", /*french*/"Weirdshot") + // /*spanish*/Weirdshot + }, { + CustomMessage("a mangled animation", /*german*/"Weirdshot", /*french*/"Weirdshot")}); + // /*spanish*/Weirdshot + //What is this used for? hintTextTable[RHT_HINT_MYSTERIOUS] = HintText(CustomMessage("something mysterious", /*german*/"etwas Mysteriöses", /*french*/"un sacré mystère")); // /*spanish*/algo misterioso diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 0e5adf76437..05c2ecfcfe5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -406,6 +406,34 @@ void GenerateItemPool() { int powerBracelet = ctx->GetOption(RSK_SHUFFLE_GRAB) ? 1 : 0; AddItemToPool(RG_PROGRESSIVE_STRENGTH, 4 + powerBracelet, 3 + powerBracelet, 3 + powerBracelet, 3 + powerBracelet); + if (ctx->GetOption(RSK_SHUFFLE_ISG)) { + AddItemToPool(RG_ABILITY_ISG, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_OI)) { + AddItemToPool(RG_ABILITY_OI, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_QPA)) { + AddItemToPool(RG_ABILITY_QPA, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_HESS)) { + AddItemToPool(RG_ABILITY_HESS, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_SUPERSLIDE)) { + AddItemToPool(RG_ABILITY_SUPERSLIDE, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_HOVER)) { + AddItemToPool(RG_ABILITY_HOVER, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_EQUIP_SWAP)) { + AddItemToPool(RG_ABILITY_EQUIP_SWAP, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_GROUND_JUMP)) { + AddItemToPool(RG_ABILITY_GROUND_JUMP, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_WEIRDSHOT)) { + AddItemToPool(RG_ABILITY_WEIRDSHOT, 2, 1, 1, 1, false); + } + if (ctx->GetOption(RSK_SHUFFLE_CLIMB)) { AddItemToPool(RG_CLIMB, 2, 1, 1, 1); } diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 70371153179..47d5bf31590 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -77,6 +77,12 @@ extern void EnGe1_Wait_Archery(EnGe1* enGe1, PlayState* play); extern void EnGe1_SetAnimationIdle(EnGe1* enGe1); extern void EnGe1_SetAnimationIdle(EnGe1* enGe1); extern void EnGe2_SetupCapturePlayer(EnGe2* enGe2, PlayState* play); +extern void func_80832318(Player* player); +extern void Player_SetupActionPreserveItemAction(PlayState* play, Player* player, PlayerActionFunc actionFunc, + s32 flags); +extern void Player_Action_Idle(Player* player, PlayState* play); +extern s32 Player_DecelerateToZero(Player* player); +extern s32 func_80834BD4(Player* player, PlayState* play); } bool LocMatchesQuest(Rando::Location loc) { @@ -2648,6 +2654,15 @@ void RandomizerOnPlayerUpdateHandler() { GameInteractor::State::TriforceHuntPieceGiven = 0; } } + + if (!Flags_GetRandomizerInf(RAND_INF_CAN_GROUND_JUMP)) { + if (GET_PLAYER(gPlayState)->stateFlags1 & PLAYER_STATE1_CARRYING_ACTOR && + GET_PLAYER(gPlayState)->stateFlags1 & PLAYER_STATE1_SHIELDING) { + if (GET_PLAYER(gPlayState)->upperActionFunc == func_80834BD4 && GET_PLAYER(gPlayState)->heldActor == NULL) { + GET_PLAYER(gPlayState)->stateFlags1 &= ~PLAYER_STATE1_CARRYING_ACTOR; + } + } + } } void RandomizerOnSceneSpawnActorsHandler() { @@ -2709,6 +2724,83 @@ void RandomizerOnCuccoOrChickenHatch() { } } +void RandomizerOnLinkAnimEnd(SkelAnime* skelAnime) { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_ISG)) { + Player* player = GET_PLAYER(gPlayState); + + // Make sure we are only checking for the end of link's animation + // TODO: Use gPlayerAnim_link_normal_defense_kiru? + if (skelAnime == &player->skelAnime && player->meleeWeaponAnimation == PLAYER_MWA_STAB_1H) { + func_80832318(player); + } + } +} + +void RandomizerShouldSkipForcePlayOcarina(bool* should) { + + if (!Flags_GetRandomizerInf(RAND_INF_CAN_OI)) { + Player* player = GET_PLAYER(gPlayState); + + if (player->itemAction != PLAYER_IA_OCARINA_FAIRY && player->itemAction != PLAYER_IA_OCARINA_OF_TIME) { + player->unk_6AD = 0; + Sfx_PlaySfxCentered(NA_SE_SY_ERROR); + Player_SetupActionPreserveItemAction(gPlayState, player, Player_Action_Idle, 0); + player->stateFlags1 &= ~PLAYER_STATE1_IN_CUTSCENE; + *should = true; + } + } +} + +void RandomizerOnQPADamage(uint32_t* dmgFlags) { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_QPA)) { + *dmgFlags = 0; + } +} + +void RandomizerOnESS() { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_HESS)) { + Player_DecelerateToZero(GET_PLAYER(gPlayState)); + } +} + +void RandomizerOnWaitForPutaway() { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_SUPERSLIDE)) { + Player_DecelerateToZero(GET_PLAYER(gPlayState)); + } +} + +void RandomizerShouldHover(bool* should) { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_HOVER)) { + *should = false; + } +} + +void RandomizerOnKaleidoMoveCursorFromSpecialPos(PauseContext* pauseCtx, uint16_t* cursorItem) { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_EQUIP_SWAP)) { + *cursorItem = PAUSE_ITEM_NONE; + // PAUSE_ITEM_NONE feels more accurate to intended behaviour, but alternative here also works + // *cursorItem = gSaveContext.inventory.items[pauseCtx->cursorPoint[PAUSE_ITEM]]; + } +} + +void RandomizerOnAnimationSetLoadFrame(LinkAnimationHeader* animation, int32_t* frame) { + if (!Flags_GetRandomizerInf(RAND_INF_CAN_WEIRDSHOT)) { + std::optional animationName; + + if (ResourceMgr_OTRSigCheck(reinterpret_cast(animation)) != 0) { + animationName = reinterpret_cast(animation); + animation = reinterpret_cast(ResourceMgr_LoadAnimByName(*animationName)); + } + + const auto playerAnimHeader = + static_cast(SEGMENTED_TO_VIRTUAL(static_cast(animation))); + + if (*frame < 0 || *frame >= playerAnimHeader->common.frameCount) { + *frame = 0; + } + } +} + static void RandomizerRegisterHooks() { static uint32_t onFlagSetHook = 0; static uint32_t onSceneFlagSetHook = 0; @@ -2728,6 +2820,12 @@ static void RandomizerRegisterHooks() { static uint32_t onExitGameHook = 0; static uint32_t onKaleidoUpdateHook = 0; static uint32_t onCuccoOrChickenHatchHook = 0; + static uint32_t onLinkAnimEndHook = 0; + static uint32_t onQPADamageHook = 0; + static uint32_t onESSHook = 0; + static uint32_t onWaitForPutawayHook = 0; + static uint32_t onKaleidoMoveCursorFromSpecialPosHook = 0; + static uint32_t onAnimationSetLoadFrameHook = 0; // register this outside OnLoadGame as VB is invoked before OnLoadGame COND_VB_SHOULD(VB_REVERT_SPOILING_ITEMS, true, { @@ -2761,6 +2859,14 @@ static void RandomizerRegisterHooks() { GameInteractor::Instance->UnregisterGameHook(onExitGameHook); GameInteractor::Instance->UnregisterGameHook(onKaleidoUpdateHook); GameInteractor::Instance->UnregisterGameHook(onCuccoOrChickenHatchHook); + GameInteractor::Instance->UnregisterGameHook(onLinkAnimEndHook); + GameInteractor::Instance->UnregisterGameHook(onQPADamageHook); + GameInteractor::Instance->UnregisterGameHook(onESSHook); + GameInteractor::Instance->UnregisterGameHook(onWaitForPutawayHook); + GameInteractor::Instance->UnregisterGameHook( + onKaleidoMoveCursorFromSpecialPosHook); + GameInteractor::Instance->UnregisterGameHook( + onAnimationSetLoadFrameHook); onFlagSetHook = 0; onSceneFlagSetHook = 0; @@ -2780,6 +2886,7 @@ static void RandomizerRegisterHooks() { onExitGameHook = 0; onKaleidoUpdateHook = 0; onCuccoOrChickenHatchHook = 0; + onLinkAnimEndHook = 0; if (!IS_RANDO) return; @@ -2829,6 +2936,27 @@ static void RandomizerRegisterHooks() { RandomizerOnKaleidoscopeUpdateHandler); onCuccoOrChickenHatchHook = GameInteractor::Instance->RegisterGameHook( RandomizerOnCuccoOrChickenHatch); + onLinkAnimEndHook = GameInteractor::Instance->RegisterGameHook( + [](SkelAnime* skelAnime) { RandomizerOnLinkAnimEnd(skelAnime); }); + onQPADamageHook = GameInteractor::Instance->RegisterGameHook( + [](uint32_t* dmgFlags) { RandomizerOnQPADamage(dmgFlags); }); + onESSHook = GameInteractor::Instance->RegisterGameHook(RandomizerOnESS); + onWaitForPutawayHook = + GameInteractor::Instance->RegisterGameHook(RandomizerOnWaitForPutaway); + onKaleidoMoveCursorFromSpecialPosHook = + GameInteractor::Instance->RegisterGameHook( + [](PauseContext* pauseCtx, uint16_t* cursorItem) { + RandomizerOnKaleidoMoveCursorFromSpecialPos(pauseCtx, cursorItem); + }); + onAnimationSetLoadFrameHook = + GameInteractor::Instance->RegisterGameHook( + [](LinkAnimationHeader* animation, int32_t* frame) { + RandomizerOnAnimationSetLoadFrame(animation, frame); + }); + + COND_VB_SHOULD(VB_SKIP_FORCE_PLAY_OCARINA, true, { RandomizerShouldSkipForcePlayOcarina(should); }); + + COND_VB_SHOULD(VB_HOVER_WITH_ISG, true, { RandomizerShouldHover(should); }); if (RAND_GET_OPTION(RSK_FISHSANITY).IsNot(RO_FISHSANITY_OFF)) { OTRGlobals::Instance->gRandoContext->GetFishsanity()->InitializeFromSave(); diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 339ff6135f9..8b342412bb7 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -402,6 +402,25 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_OPEN_CHEST] = Item(RG_OPEN_CHEST, Text{ "Open Chests", "Ouvrir des coffres", TODO_TRANSLATE }, ITEMTYPE_ITEM, GI_KEY_SMALL, true, LOGIC_NONE, RHT_OPEN_CHEST, RG_OPEN_CHEST, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OPEN_CHEST].SetCustomDrawFunc(Randomizer_DrawOpenChest); + itemTable[RG_ABILITY_ISG] = Item(RG_ABILITY_ISG, Text{ "ISG", "ISG", "ISG" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_ISG, RG_ABILITY_ISG, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconSwordMasterTex); + itemTable[RG_ABILITY_ISG].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_OI] = Item(RG_ABILITY_OI, Text{ "OI", "OI", "OI" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_OI, RG_ABILITY_OI, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconOcarinaOfTimeTex); + itemTable[RG_ABILITY_OI].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_QPA] = Item(RG_ABILITY_QPA, Text{ "QPA", "QPA", "QPA" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_QPA, RG_ABILITY_QPA, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconBottleBlueFireTex); + itemTable[RG_ABILITY_QPA].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_HESS] = Item(RG_ABILITY_HESS, Text{ "Extended Superslide", "Extended Superslide", "Extended Superslide" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_HESS, RG_ABILITY_HESS, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconBootsHoverTex); + itemTable[RG_ABILITY_HESS].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_SUPERSLIDE] = Item(RG_ABILITY_SUPERSLIDE, Text{ "Superslide", "Superslide", "Superslide" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_SUPERSLIDE, RG_ABILITY_SUPERSLIDE, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconBootsHoverTex); + itemTable[RG_ABILITY_SUPERSLIDE].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_HOVER] = Item(RG_ABILITY_HOVER, Text{ "Hovering", "Hovering", "Hovering" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_HOVER, RG_ABILITY_HOVER, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconBootsHoverTex); + itemTable[RG_ABILITY_HOVER].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_EQUIP_SWAP] = Item(RG_ABILITY_EQUIP_SWAP, Text{ "Equip Swap", "Equip Swap", "Equip Swap" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_EQUIP_SWAP, RG_ABILITY_EQUIP_SWAP, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconDinsFireTex); + itemTable[RG_ABILITY_EQUIP_SWAP].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_GROUND_JUMP] = Item(RG_ABILITY_GROUND_JUMP, Text{ "Ground Jump", "Ground Jump", "Ground Jump" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_GROUND_JUMP, RG_ABILITY_GROUND_JUMP, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconShieldHylianTex); + itemTable[RG_ABILITY_GROUND_JUMP].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_ABILITY_WEIRDSHOT] = Item(RG_ABILITY_WEIRDSHOT, Text{ "Weirdshot", "Weirdshot", "Weirdshot" }, ITEMTYPE_ITEM, GI_NONE, true, LOGIC_NONE, RHT_ABILITY_WEIRDSHOT, RG_ABILITY_WEIRDSHOT, OBJECT_GI_COIN, GID_NCOIN_YELLOW, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER).CustomIcon(gItemIconHookshotTex); + itemTable[RG_ABILITY_WEIRDSHOT].SetCustomDrawFunc(Randomizer_DrawMysteryItem); + itemTable[RG_PROGRESSIVE_BOMBCHU_BAG] = Item(RG_PROGRESSIVE_BOMBCHU_BAG, Text{ "Bombchu Bag", "Sac de Missiles Teigneux", "Krabbelminentasche" }, ITEMTYPE_ITEM, RG_PROGRESSIVE_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_PROGRESSIVE_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "un ", "eine "}).CustomIcon(gItemIconBombchuTex); itemTable[RG_PROGRESSIVE_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 8b714759e6f..015cb2b2e60 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -2075,6 +2075,33 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case RG_BOMBCHU_20: SetInventory(ITEM_BOMBCHU, (!state ? ITEM_NONE : ITEM_BOMBCHU)); break; + case RG_ABILITY_ISG: + SetRandoInf(RAND_INF_CAN_ISG, state); + break; + case RG_ABILITY_OI: + SetRandoInf(RAND_INF_CAN_OI, state); + break; + case RG_ABILITY_QPA: + SetRandoInf(RAND_INF_CAN_QPA, state); + break; + case RG_ABILITY_HESS: + SetRandoInf(RAND_INF_CAN_HESS, state); + break; + case RG_ABILITY_SUPERSLIDE: + SetRandoInf(RAND_INF_CAN_SUPERSLIDE, state); + break; + case RG_ABILITY_HOVER: + SetRandoInf(RAND_INF_CAN_HOVER, state); + break; + case RG_ABILITY_EQUIP_SWAP: + SetRandoInf(RAND_INF_CAN_EQUIP_SWAP, state); + break; + case RG_ABILITY_GROUND_JUMP: + SetRandoInf(RAND_INF_CAN_GROUND_JUMP, state); + break; + case RG_ABILITY_WEIRDSHOT: + SetRandoInf(RAND_INF_CAN_WEIRDSHOT, state); + break; default: break; } @@ -2717,6 +2744,34 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { SetRandoInf(RAND_INF_CAN_SWIM, true); } + if (ctx->GetOption(RSK_SHUFFLE_ISG).Is(false)) { + SetRandoInf(RAND_INF_CAN_ISG, true); + } + if (ctx->GetOption(RSK_SHUFFLE_OI).Is(false)) { + SetRandoInf(RAND_INF_CAN_OI, true); + } + if (ctx->GetOption(RSK_SHUFFLE_QPA).Is(false)) { + SetRandoInf(RAND_INF_CAN_QPA, true); + } + if (ctx->GetOption(RSK_SHUFFLE_HESS).Is(false)) { + SetRandoInf(RAND_INF_CAN_HESS, true); + } + if (ctx->GetOption(RSK_SHUFFLE_SUPERSLIDE).Is(false)) { + SetRandoInf(RAND_INF_CAN_SUPERSLIDE, true); + } + if (ctx->GetOption(RSK_SHUFFLE_HOVER).Is(false)) { + SetRandoInf(RAND_INF_CAN_HOVER, true); + } + if (ctx->GetOption(RSK_SHUFFLE_EQUIP_SWAP).Is(false)) { + SetRandoInf(RAND_INF_CAN_EQUIP_SWAP, true); + } + if (ctx->GetOption(RSK_SHUFFLE_GROUND_JUMP).Is(false)) { + SetRandoInf(RAND_INF_CAN_GROUND_JUMP, true); + } + if (ctx->GetOption(RSK_SHUFFLE_WEIRDSHOT).Is(false)) { + SetRandoInf(RAND_INF_CAN_WEIRDSHOT, true); + } + if (ctx->GetOption(RSK_SHUFFLE_GRAB).Is(false)) { SetRandoInf(RAND_INF_CAN_GRAB, true); } diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index d4b9d41f172..5a1e5ebf3ad 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -850,5 +850,18 @@ void Settings::CreateOptionDescriptions() { "Shuffles 8 boss souls (one for each blue warp dungeon). A boss will not appear until you collect its " "respective soul." "\n\"On + Ganon\" will also hide Ganon and Ganondorf behind a boss soul."; + + mOptionDescriptions[RSK_SHUFFLE_ISG] = + "Shuffles the ability to use the Infinite Sword Glitch (ISG) into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_OI] = "Shuffles the ability to use the glitch Ocarina Items into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_QPA] = + "Shuffles the ability to use Quick Putaway Glitched Damage into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_HESS] = + "Shuffles the ability to perform an Extended Superslide into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_SUPERSLIDE] = "Shuffles the ability to Superslide into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_HOVER] = "Shuffles the ability to Hover into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_EQUIP_SWAP] = "Shuffles the ability to Equip Swap into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_GROUND_JUMP] = "Shuffles the ability to Ground Jump into the item pool."; + mOptionDescriptions[RSK_SHUFFLE_WEIRDSHOT] = "Shuffles the ability to Weirdshot into the item pool."; } } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8fad3d16fa1..0144b5dc5a4 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -156,6 +156,15 @@ std::unordered_map randomizerGetToRandInf = { { RG_BONGO_BONGO_SOUL, RAND_INF_BONGO_BONGO_SOUL }, { RG_TWINROVA_SOUL, RAND_INF_TWINROVA_SOUL }, { RG_GANON_SOUL, RAND_INF_GANON_SOUL }, + { RG_ABILITY_ISG, RAND_INF_CAN_ISG }, + { RG_ABILITY_OI, RAND_INF_CAN_OI }, + { RG_ABILITY_QPA, RAND_INF_CAN_QPA }, + { RG_ABILITY_HESS, RAND_INF_CAN_HESS }, + { RG_ABILITY_SUPERSLIDE, RAND_INF_CAN_SUPERSLIDE }, + { RG_ABILITY_HOVER, RAND_INF_CAN_HOVER }, + { RG_ABILITY_EQUIP_SWAP, RAND_INF_CAN_EQUIP_SWAP }, + { RG_ABILITY_GROUND_JUMP, RAND_INF_CAN_GROUND_JUMP }, + { RG_ABILITY_WEIRDSHOT, RAND_INF_CAN_WEIRDSHOT }, }; #ifdef _MSC_VER diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h index 3b7806385f6..3394b34db05 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h @@ -316,6 +316,15 @@ RANDO_ENUM_ITEM(RG_STABLES_KEY) RANDO_ENUM_ITEM(RG_BACK_TOWER_KEY) RANDO_ENUM_ITEM(RG_HYLIA_LAB_KEY) RANDO_ENUM_ITEM(RG_FISHING_HOLE_KEY) +RANDO_ENUM_ITEM(RG_ABILITY_ISG) +RANDO_ENUM_ITEM(RG_ABILITY_OI) +RANDO_ENUM_ITEM(RG_ABILITY_QPA) +RANDO_ENUM_ITEM(RG_ABILITY_HESS) +RANDO_ENUM_ITEM(RG_ABILITY_SUPERSLIDE) +RANDO_ENUM_ITEM(RG_ABILITY_HOVER) +RANDO_ENUM_ITEM(RG_ABILITY_EQUIP_SWAP) +RANDO_ENUM_ITEM(RG_ABILITY_GROUND_JUMP) +RANDO_ENUM_ITEM(RG_ABILITY_WEIRDSHOT) // Custom Items RANDO_ENUM_ITEM(RG_ROCS_FEATHER) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h index 75c70674bb0..8153bede656 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h @@ -1660,6 +1660,16 @@ RANDO_ENUM_ITEM(RHT_RED_ICE_ZORAS_DOMAIN) RANDO_ENUM_ITEM(RHT_GERUDO_TRAINING_GROUND_RED_ICE) RANDO_ENUM_ITEM(RHT_ICE_CAVERN_RED_ICE) RANDO_ENUM_ITEM(RHT_GANONS_CASTLE_RED_ICE) +// GLITCHES +RANDO_ENUM_ITEM(RHT_ABILITY_ISG) +RANDO_ENUM_ITEM(RHT_ABILITY_OI) +RANDO_ENUM_ITEM(RHT_ABILITY_QPA) +RANDO_ENUM_ITEM(RHT_ABILITY_HESS) +RANDO_ENUM_ITEM(RHT_ABILITY_SUPERSLIDE) +RANDO_ENUM_ITEM(RHT_ABILITY_HOVER) +RANDO_ENUM_ITEM(RHT_ABILITY_EQUIP_SWAP) +RANDO_ENUM_ITEM(RHT_ABILITY_GROUND_JUMP) +RANDO_ENUM_ITEM(RHT_ABILITY_WEIRDSHOT) // MAX RANDO_ENUM_ITEM(RHT_MAX) RANDO_ENUM_END(RandomizerHintTextKey) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h index d2e461d7ea6..8fb6143bca8 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h @@ -1452,6 +1452,16 @@ RANDO_ENUM_ITEM(RAND_INF_CAN_SPEAK_ZORA) RANDO_ENUM_ITEM(RAND_INF_HAS_WALLET) +RANDO_ENUM_ITEM(RAND_INF_CAN_ISG) +RANDO_ENUM_ITEM(RAND_INF_CAN_OI) +RANDO_ENUM_ITEM(RAND_INF_CAN_QPA) +RANDO_ENUM_ITEM(RAND_INF_CAN_HESS) +RANDO_ENUM_ITEM(RAND_INF_CAN_SUPERSLIDE) +RANDO_ENUM_ITEM(RAND_INF_CAN_HOVER) +RANDO_ENUM_ITEM(RAND_INF_CAN_EQUIP_SWAP) +RANDO_ENUM_ITEM(RAND_INF_CAN_GROUND_JUMP) +RANDO_ENUM_ITEM(RAND_INF_CAN_WEIRDSHOT) + RANDO_ENUM_ITEM(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_LEFT) RANDO_ENUM_ITEM(RAND_INF_BEEHIVE_KF_STORMS_GROTTO_RIGHT) RANDO_ENUM_ITEM(RAND_INF_BEEHIVE_LW_NEAR_SHORTCUTS_GROTTO_LEFT) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h index 08d489e3db2..fb76a3ce9ea 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h @@ -252,6 +252,15 @@ RANDO_ENUM_ITEM(RSK_SHUFFLE_SIGNS) RANDO_ENUM_ITEM(RSK_ROCS_FEATHER) RANDO_ENUM_ITEM(RSK_SHUFFLE_ICICLES) RANDO_ENUM_ITEM(RSK_SHUFFLE_RED_ICE) +RANDO_ENUM_ITEM(RSK_SHUFFLE_ISG) +RANDO_ENUM_ITEM(RSK_SHUFFLE_OI) +RANDO_ENUM_ITEM(RSK_SHUFFLE_QPA) +RANDO_ENUM_ITEM(RSK_SHUFFLE_HESS) +RANDO_ENUM_ITEM(RSK_SHUFFLE_SUPERSLIDE) +RANDO_ENUM_ITEM(RSK_SHUFFLE_HOVER) +RANDO_ENUM_ITEM(RSK_SHUFFLE_EQUIP_SWAP) +RANDO_ENUM_ITEM(RSK_SHUFFLE_GROUND_JUMP) +RANDO_ENUM_ITEM(RSK_SHUFFLE_WEIRDSHOT) RANDO_ENUM_ITEM(RSK_MAX) RANDO_ENUM_END(RandomizerSettingKey) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 064eabff646..acb952357db 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -314,6 +314,34 @@ extern "C" void Randomizer_InitSaveFile() { Flags_SetRandomizerInf(RAND_INF_CAN_SWIM); } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_ISG) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_ISG); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_OI) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_OI); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_QPA) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_QPA); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_HESS) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_HESS); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_SUPERSLIDE) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_SUPERSLIDE); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_HOVER) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_HOVER); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_EQUIP_SWAP) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_EQUIP_SWAP); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_GROUND_JUMP) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_GROUND_JUMP); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_WEIRDSHOT) == RO_GENERIC_OFF) { + Flags_SetRandomizerInf(RAND_INF_CAN_WEIRDSHOT); + } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_GRAB) == RO_GENERIC_OFF) { Flags_SetRandomizerInf(RAND_INF_CAN_GRAB); } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 1acb4d78a8a..8e875d78aa8 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -843,6 +843,15 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_SHUFFLE_OPEN_CHEST, "Shuffle Open Chest", CVAR_RANDOMIZER_SETTING("ShuffleOpenChest"), mOptionDescriptions[RSK_SHUFFLE_OPEN_CHEST]); OPT_BOOL(RSK_SHUFFLE_WEIRD_EGG, "Shuffle Weird Egg", CVAR_RANDOMIZER_SETTING("ShuffleWeirdEgg"), mOptionDescriptions[RSK_SHUFFLE_WEIRD_EGG]); OPT_BOOL(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, "Shuffle Gerudo Membership Card", CVAR_RANDOMIZER_SETTING("ShuffleGerudoToken"), mOptionDescriptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); + OPT_BOOL(RSK_SHUFFLE_ISG, "Shuffle ISG", CVAR_RANDOMIZER_SETTING("ShuffleISG"), mOptionDescriptions[RSK_SHUFFLE_ISG]); + OPT_BOOL(RSK_SHUFFLE_OI, "Shuffle OI", CVAR_RANDOMIZER_SETTING("ShuffleOI"), mOptionDescriptions[RSK_SHUFFLE_OI]); + OPT_BOOL(RSK_SHUFFLE_QPA, "Shuffle QPA", CVAR_RANDOMIZER_SETTING("ShuffleQPA"), mOptionDescriptions[RSK_SHUFFLE_QPA]); + OPT_BOOL(RSK_SHUFFLE_HESS, "Shuffle HESS", CVAR_RANDOMIZER_SETTING("ShuffleHESS"), mOptionDescriptions[RSK_SHUFFLE_HESS]); + OPT_BOOL(RSK_SHUFFLE_SUPERSLIDE, "Shuffle Superslide", CVAR_RANDOMIZER_SETTING("ShuffleSuperslide"), mOptionDescriptions[RSK_SHUFFLE_SUPERSLIDE]); + OPT_BOOL(RSK_SHUFFLE_HOVER, "Shuffle Hovering", CVAR_RANDOMIZER_SETTING("ShuffleHover"), mOptionDescriptions[RSK_SHUFFLE_HOVER]); + OPT_BOOL(RSK_SHUFFLE_EQUIP_SWAP, "Shuffle Equip Swap", CVAR_RANDOMIZER_SETTING("ShuffleEquipSwap"), mOptionDescriptions[RSK_SHUFFLE_EQUIP_SWAP]); + OPT_BOOL(RSK_SHUFFLE_GROUND_JUMP, "Shuffle Ground Jump", CVAR_RANDOMIZER_SETTING("ShuffleGroundJump"), mOptionDescriptions[RSK_SHUFFLE_GROUND_JUMP]); + OPT_BOOL(RSK_SHUFFLE_WEIRDSHOT, "Shuffle Weirdshot", CVAR_RANDOMIZER_SETTING("ShuffleWeirdshot"), mOptionDescriptions[RSK_SHUFFLE_WEIRDSHOT]); OPT_U8(RSK_SHUFFLE_POTS, "Shuffle Pots", {"Off", "Dungeons", "Overworld", "All Pots"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShufflePots"), mOptionDescriptions[RSK_SHUFFLE_POTS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_POTS_OFF); OPT_U8(RSK_SHUFFLE_GRASS, "Shuffle Grass", {"Off", "Dungeons", "Overworld", "All Grass"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleGrass"), mOptionDescriptions[RSK_SHUFFLE_GRASS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_GRASS_OFF); OPT_U8(RSK_SHUFFLE_CRATES, "Shuffle Crates", {"Off", "Dungeons", "Overworld", "All Crates"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleCrates"), mOptionDescriptions[RSK_SHUFFLE_CRATES], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_CRATES_OFF); @@ -1887,6 +1896,15 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], &mOptions[RSK_SHUFFLE_SONG_FAIRIES], &mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES], + &mOptions[RSK_SHUFFLE_ISG], + &mOptions[RSK_SHUFFLE_OI], + &mOptions[RSK_SHUFFLE_QPA], + &mOptions[RSK_SHUFFLE_HESS], + &mOptions[RSK_SHUFFLE_SUPERSLIDE], + &mOptions[RSK_SHUFFLE_HOVER], + &mOptions[RSK_SHUFFLE_EQUIP_SWAP], + &mOptions[RSK_SHUFFLE_GROUND_JUMP], + &mOptions[RSK_SHUFFLE_WEIRDSHOT], }, WidgetContainerType::SECTION); mOptionGroups[RSG_MENU_COLUMN_BASIC_SHUFFLES] = @@ -2205,6 +2223,15 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], &mOptions[RSK_SHUFFLE_SONG_FAIRIES], &mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES], + &mOptions[RSK_SHUFFLE_ISG], + &mOptions[RSK_SHUFFLE_OI], + &mOptions[RSK_SHUFFLE_QPA], + &mOptions[RSK_SHUFFLE_HESS], + &mOptions[RSK_SHUFFLE_SUPERSLIDE], + &mOptions[RSK_SHUFFLE_HOVER], + &mOptions[RSK_SHUFFLE_EQUIP_SWAP], + &mOptions[RSK_SHUFFLE_GROUND_JUMP], + &mOptions[RSK_SHUFFLE_WEIRDSHOT], }); mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS] = OptionGroup("Shuffle Dungeon Items", { diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 3449c2ed91a..fbf09670c2d 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -889,6 +889,8 @@ void AnimationContext_SetLoadFrame(PlayState* play, LinkAnimationHeader* animati Vec3s* frameTable) { AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_LOADFRAME); + GameInteractor_ExecuteOnAnimationSetLoadFrame(animation, &frame); + if (GameInteractor_Should(VB_LOAD_PLAYER_ANIMATION_FRAME, entry != NULL, entry, animation, frame, limbCount, frameTable)) { if (ResourceMgr_OTRSigCheck(animation) != 0) @@ -1231,6 +1233,7 @@ s32 LinkAnimation_Once(PlayState* play, SkelAnime* skelAnime) { if (skelAnime->curFrame == skelAnime->endFrame) { LinkAnimation_AnimateFrame(play, skelAnime); + GameInteractor_ExecuteOnLinkAnimEnd(skelAnime); return 1; } skelAnime->curFrame += skelAnime->playSpeed * updateRate; 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 7ffe8af7f43..e401f4b2c0c 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -4455,6 +4455,7 @@ void func_80837948(PlayState* play, Player* this, s32 arg2) { if ((arg2 >= PLAYER_MWA_FLIPSLASH_START) && (arg2 <= PLAYER_MWA_JUMPSLASH_FINISH)) { if (CVarGetInteger(CVAR_GENERAL("RestoreQPA"), 1) && temp == -1) { dmgFlags = 0x16171617; + GameInteractor_ExecuteOnQPADamage(&dmgFlags); } else { dmgFlags = D_80854488[temp][1]; } @@ -5793,7 +5794,8 @@ void func_8083AA10(Player* this, PlayState* play) { if (!(this->stateFlags3 & PLAYER_STATE3_MIDAIR) && !(this->skelAnime.movementFlags & 0x80) && (Player_Action_8084411C != this->actionFunc) && (Player_Action_80844A44 != this->actionFunc)) { - if ((sPrevFloorProperty == 7) || (this->meleeWeaponState != 0)) { + if ((sPrevFloorProperty == 7) || + (GameInteractor_Should(VB_HOVER_WITH_ISG, true) && (this->meleeWeaponState != 0))) { Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.prevPos); Player_ZeroSpeedXZ(this); return; @@ -6110,6 +6112,9 @@ s32 Player_ActionHandler_13(Player* this, PlayState* play) { func_80835EA4(play, 2); } } else { + if (GameInteractor_Should(VB_SKIP_FORCE_PLAY_OCARINA, false)) { + return 0; + } Player_SetupActionPreserveItemAction(play, this, Player_Action_8084E3C4, 0); Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_normal_okarina_start); this->stateFlags2 |= PLAYER_STATE2_OCARINA_PLAYING; @@ -8746,6 +8751,8 @@ void Player_Action_TurnInPlace(Player* this, PlayState* play) { this->skelAnime.morphTable, sUpperBodyLimbCopyMap); } + GameInteractor_ExecuteOnESS(); + Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play); //! @bug This action does not handle xzSpeed in any capacity. @@ -10237,6 +10244,8 @@ void Player_Action_WaitForPutAway(Player* this, PlayState* play) { this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_Z_TARGET | PLAYER_STATE2_DISABLE_ROTATION_ALWAYS; LinkAnimation_Update(play, &this->skelAnime); + GameInteractor_ExecuteOnWaitForPutaway(); + // Wait for the held item put away process to complete. // Determining if the put away process is complete is a bit complicated: // `Player_UpdateUpperBody` will only return false if the current UpperAction returns false. diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 16cfd8742d3..58d1d612006 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -564,6 +564,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->cursorX[PAUSE_ITEM] = cursorX; pauseCtx->cursorY[PAUSE_ITEM] = cursorY; moveCursorResult = 1; + GameInteractor_ExecuteOnKaleidoMoveCursorFromSpecialPos(pauseCtx, &cursorItem); break; } @@ -600,6 +601,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { pauseCtx->cursorX[PAUSE_ITEM] = cursorX; pauseCtx->cursorY[PAUSE_ITEM] = cursorY; moveCursorResult = 1; + GameInteractor_ExecuteOnKaleidoMoveCursorFromSpecialPos(pauseCtx, &cursorItem); break; }