diff --git a/soh/soh/Enhancements/ReworkedTargeting.cpp b/soh/soh/Enhancements/ReworkedTargeting.cpp new file mode 100644 index 000000000..aa2b5f06c --- /dev/null +++ b/soh/soh/Enhancements/ReworkedTargeting.cpp @@ -0,0 +1,57 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ShipInit.hpp" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "z64.h" +#include "macros.h" +#include "functions.h" +extern PlayState* gPlayState; +} + +#define CVAR_REWORKED_TARGETING_NAME CVAR_ENHANCEMENT("ReworkedTargeting.Enabled") +#define CVAR_REWORKED_TARGETING_VALUE CVarGetInteger(CVAR_REWORKED_TARGETING_NAME, 0) + +static bool sTriggeredByButtonCombo = false; + +void RegisterReworkedTargeting() { + + COND_VB_SHOULD(VB_TOGGLE_Z_TARGET_SWITCH_TARGETS, CVAR_REWORKED_TARGETING_VALUE, { + Player* player = GET_PLAYER(gPlayState); + if (player->focusActor != NULL && !sTriggeredByButtonCombo) { + *should = false; + } + sTriggeredByButtonCombo = false; + }); + + COND_VB_SHOULD(VB_TOGGLE_Z_TARGET_SWITCH_DIRECTION, CVAR_REWORKED_TARGETING_VALUE, { + if (*should) + return; + + Player* player = GET_PLAYER(gPlayState); + + if (player->focusActor != NULL) { + Input* input = &gPlayState->state.input[0]; + + static bool wasButtonComboActive = false; + + const s32 targetSwitchMask = CVarGetInteger(CVAR_ENHANCEMENT("ReworkedTargeting.Btn"), 0); + bool isButtonComboActive = CHECK_BTN_ANY(input->press.button, targetSwitchMask); + + if (isButtonComboActive && !wasButtonComboActive) { + Actor* nextTarget = gPlayState->actorCtx.targetCtx.unk_94; + if (nextTarget != NULL) { + sTriggeredByButtonCombo = true; + *should = true; + } else { + *should = false; + } + } + + wasButtonComboActive = isButtonComboActive; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterReworkedTargeting, { CVAR_REWORKED_TARGETING_NAME }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 4959f7f23..2065c929d 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2623,6 +2623,22 @@ typedef enum { // - `double` (temp - promoted from `f32`) VB_RUMBLE_FOR_SECRET, + // #### `result` + // ```c + // false + // ``` + // #### `args` + // - None + VB_TOGGLE_Z_TARGET_SWITCH_DIRECTION, + + // #### `result` + // ```c + // !usingHoldTargeting + // ``` + // #### `args` + // - `int32_t` (usingHoldTargeting - promoted from `s32`) + VB_TOGGLE_Z_TARGET_SWITCH_TARGETS, + // #### `result` // ```c // (uint8_t)font->msgBuf[msgCtx->msgBufPos + 1] >= ITEM_CUSTOM diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index e0574ca53..aab8c4d04 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -268,6 +268,17 @@ void SohMenu::AddMenuEnhancements() { .DefaultValue(0) .Format("%d frames") .Tooltip("Buffers your inputs to be executed a specified amount of frames later.")); + AddWidget(path, "Reworked Targeting", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("ReworkedTargeting.Enabled")) + .Options(CheckboxOptions().Tooltip("Reworks targeting functionality\n" + "- Press Z while locked always untargets (in Toggle mode)\n" + "- Use the configured button combo to switch between targets")); + AddWidget(path, "Target Switch Button Combination:", WIDGET_CVAR_BTN_SELECTOR) + .PreFunc([](WidgetInfo& info) { + info.isHidden = CVarGetInteger(CVAR_ENHANCEMENT("ReworkedTargeting.Enabled"), 0) == 0; + }) + .CVar(CVAR_ENHANCEMENT("ReworkedTargeting.Btn")) + .Options(BtnSelectorOptions().Tooltip("Buttons to activate target switching.")); AddWidget(path, "Item Count Messages", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Gold Skulltula Tokens", WIDGET_CVAR_CHECKBOX) 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 3c707383c..130644968 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -3829,7 +3829,8 @@ void Player_UpdateZTargeting(Player* this, PlayState* play) { if (!isTalking) { if (!(this->stateFlags1 & PLAYER_STATE1_BOOMERANG_THROWN) && ((this->heldItemAction != PLAYER_IA_FISHING_POLE) || (this->unk_860 == 0)) && - CHECK_BTN_ALL(sControlInput->press.button, BTN_Z)) { + GameInteractor_Should(VB_TOGGLE_Z_TARGET_SWITCH_DIRECTION, + CHECK_BTN_ALL(sControlInput->press.button, BTN_Z))) { if (this->actor.category == ACTORCAT_PLAYER) { // The next lock-on actor defaults to the actor Navi is hovering over. @@ -3855,7 +3856,7 @@ void Player_UpdateZTargeting(Player* this, PlayState* play) { nextLockOnActor = play->actorCtx.targetCtx.unk_94; } - if (nextLockOnActor != this->focusActor) { + if (GameInteractor_Should(VB_TOGGLE_Z_TARGET_SWITCH_TARGETS, nextLockOnActor != this->focusActor)) { // Set new lock-on if (!usingHoldTargeting) {