diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index 1220c9aed..1089f147c 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -165,6 +165,11 @@ namespace GameMenuBar { CVar_SetS32("gMaskSelect", 0); // Remember Save Location CVar_SetS32("gRememberSaveLocation", 0); + // Skip Magic Arrow Equip Animation + CVar_SetS32("gSkipArrowAnimation", 0); + + // Equip arrows on multiple slots + CVar_SetS32("gSeparateArrows", 0); // Damage Multiplier (0 to 8) CVar_SetS32("gDamageMul", 0); @@ -428,6 +433,11 @@ namespace GameMenuBar { CVar_SetS32("gGoronPot", 1); // Always Win Dampe Digging CVar_SetS32("gDampeWin", 1); + // Skip Magic Arrow Equip Animation + CVar_SetS32("gSkipArrowAnimation", 1); + + // Equip arrows on multiple slots + CVar_SetS32("gSeparateArrows", 1); // Disable Navi Call Audio CVar_SetS32("gDisableNaviCallAudio", 1); @@ -814,6 +824,7 @@ namespace GameMenuBar { UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" "This doesn't work if the save was made in a grotto."); + UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); ImGui::EndMenu(); @@ -837,6 +848,8 @@ namespace GameMenuBar { UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false); UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers."); + UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false); + UIWidgets::Tooltip("Allow the bow and magic arrows to be equipped at the same time on different slots"); ImGui::EndMenu(); } 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 0eabd2244..7fe844aa3 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -127,8 +127,8 @@ s32 func_80834A2C(Player* this, PlayState* play); s32 func_80834B5C(Player* this, PlayState* play); s32 func_80834C74(Player* this, PlayState* play); s32 func_8083501C(Player* this, PlayState* play); -s32 func_808351D4(Player* this, PlayState* play); -s32 func_808353D8(Player* this, PlayState* play); +s32 func_808351D4(Player* this, PlayState* play); // Arrow nocked +s32 func_808353D8(Player* this, PlayState* play); // Aiming in first person s32 func_80835588(Player* this, PlayState* play); s32 func_808356E8(Player* this, PlayState* play); s32 func_80835800(Player* this, PlayState* play); @@ -2167,6 +2167,7 @@ void func_80834298(Player* this, PlayState* play) { } } +// Determine projectile type for bow or slingshot s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) { if (LINK_IS_ADULT) { *itemPtr = ITEM_BOW; @@ -2189,6 +2190,7 @@ s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) { } } +// The player has pressed the bow or hookshot button s32 func_8083442C(Player* this, PlayState* play) { s32 item; s32 arrowType; @@ -2502,6 +2504,7 @@ s32 func_8083501C(Player* this, PlayState* play) { return 1; } +// Fire the projectile s32 func_808350A4(PlayState* play, Player* this) { s32 item; s32 arrowType; @@ -3012,7 +3015,10 @@ void func_80835F44(PlayState* play, Player* this, s32 item) { if ((this->heldItemActionParam >= 0) && (Player_ActionToMagicSpell(this, actionParam) < 0) && (item != this->heldItemId) && (D_80854164[gPlayerModelTypes[this->modelGroup][PLAYER_MODELGROUPENTRY_ANIM]][nextAnimType] != - PLAYER_D_808540F4_0)) { + PLAYER_D_808540F4_0) && + (!CVar_GetS32("gSeparateArrows", 0) || + actionParam < PLAYER_AP_BOW || actionParam > PLAYER_AP_BOW_0E || + this->heldItemActionParam < PLAYER_AP_BOW || this->heldItemActionParam > PLAYER_AP_BOW_0E)) { this->heldItemId = item; this->stateFlags1 |= PLAYER_STATE1_8; } else { 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 4dd11dcd1..80c816877 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 @@ -577,18 +577,22 @@ void KaleidoScope_SetupItemEquip(PlayState* play, u16 item, u16 slot, s16 animX, sEquipMoveTimer = 10; if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) || (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) || (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) { - u16 index = 0; - if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) { - index = 1; + if (CVar_GetS32("gSkipArrowAnimation", 0)) { + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else { + u16 index = 0; + if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) { + index = 1; + } + if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { + index = 2; + } + Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + pauseCtx->equipTargetItem = 0xBF + index; + sEquipState = 0; + pauseCtx->equipAnimAlpha = 0; + sEquipMoveTimer = 6; } - if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { - index = 2; - } - Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - pauseCtx->equipTargetItem = 0xBF + index; - sEquipState = 0; - pauseCtx->equipAnimAlpha = 0; - sEquipMoveTimer = 6; } else { Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } @@ -784,7 +788,9 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { if (D_8082A488 == 0) { pauseCtx->equipTargetItem -= 0xBF - ITEM_BOW_ARROW_FIRE; - pauseCtx->equipTargetSlot = SLOT_BOW; + if (!CVar_GetS32("gSeparateArrows", 0)) { + pauseCtx->equipTargetSlot = SLOT_BOW; + } sEquipMoveTimer = 6; WREG(90) = 320; WREG(87) = WREG(91); @@ -853,6 +859,26 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { osSyncPrintf("\n================================\n"); + // Skipping the arrow animation: need to change the item's type and + // slot when it hits the button since it didn't get set earlier + if (pauseCtx->equipTargetItem == ITEM_ARROW_FIRE || pauseCtx->equipTargetItem == ITEM_ARROW_ICE || + pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { + switch (pauseCtx->equipTargetItem) { + case ITEM_ARROW_FIRE: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_FIRE; + break; + case ITEM_ARROW_ICE: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_ICE; + break; + case ITEM_ARROW_LIGHT: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_LIGHT; + break; + } + if (!CVar_GetS32("gSeparateArrows", 0)) { + pauseCtx->equipTargetSlot = SLOT_BOW; + } + } + // If the item is on another button already, swap the two uint16_t targetButtonIndex = pauseCtx->equipTargetCBtn + 1; for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots);