Skip to content

Commit

Permalink
Merge branch 'arrow_switch' into mod-merge
Browse files Browse the repository at this point in the history
  • Loading branch information
lilDavid committed Jan 18, 2023
2 parents 369c185 + 031064a commit 036f1a4
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 9 deletions.
1 change: 1 addition & 0 deletions soh/include/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,7 @@ s32 Player_ActionToBottle(Player* player, s32 actionParam);
s32 Player_GetBottleHeld(Player* player);
s32 Player_ActionToExplosive(Player* player, s32 actionParam);
s32 Player_GetExplosiveHeld(Player* player);
bool Player_CanSwitchArrows(Player* player);
s32 func_8008F2BC(Player* player, s32 actionParam);
s32 func_8008F2F8(PlayState* play);
void func_8008F470(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListCount, s32 lod, s32 tunic,
Expand Down
24 changes: 23 additions & 1 deletion soh/soh/Enhancements/controls/GameControlEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ namespace GameControlEditor {
static CustomButtonMap ocarinaSharp = {"Pitch up", "gOcarinaSharpBtnMap", BTN_R};
static CustomButtonMap ocarinaFlat = {"Pitch down", "gOcarinaFlatBtnMap", BTN_Z};

// Misc.
static CustomButtonMap arrowSwitch = {"Switch arrows", "gArrowSwitchBtnMap", BTN_R};

void DrawUI(bool&);

void Init() {
Expand Down Expand Up @@ -298,6 +301,7 @@ namespace GameControlEditor {
ImVec2 cursor = ImGui::GetCursorPos();
ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5));
SohImGui::BeginGroupPanel("Misc Controls", ImGui::GetContentRegionAvail());

UIWidgets::PaddedEnhancementCheckbox("Enable walk speed modifiers", "gEnableWalkModify", true, false);
DrawHelpIcon("Hold the assigned button to change the maximum walking speed\nTo change the assigned button, go into the Ports tabs above");
if (CVarGetInteger("gEnableWalkModify", 0)) {
Expand All @@ -313,8 +317,26 @@ namespace GameControlEditor {
DrawHelpIcon("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97");
UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL");
DrawHelpIcon("Speak to Navi with L but enter first-person camera with C-Up");
SohImGui::EndGroupPanel();

float longestLabelWidth = ImGui::CalcTextSize(arrowSwitch.label).x + 10;

// Switch arrows
bool arrowSwitchingEnabled = CVarGetInteger("gArrowSwitching", 0);
if (!arrowSwitchingEnabled) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
}
N64ButtonMask arrowSwitchAllowedButtons = BTN_A | BTN_L | BTN_R | BTN_CUP;
DrawMapping(arrowSwitch, longestLabelWidth, ~arrowSwitchAllowedButtons);
if (!arrowSwitchingEnabled) {
ImGui::PopStyleVar(1);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("%s", "This option is disabled because Arrow Switching from Enhancements > Gameplay > Time Savers is disabled");
}
ImGui::PopItemFlag();
}

SohImGui::EndGroupPanel();
}

void DrawUI(bool& open) {
Expand Down
1 change: 1 addition & 0 deletions soh/soh/Enhancements/presets.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ const std::vector<const char*> enhancementsCvars = {
"gBombchuBowlingNoBigCucco",
"gBombchuBowlingAmmunition",
"gCreditsFix",
"gArrowSwitching",
};

const std::vector<const char*> randomizerCvars = {
Expand Down
3 changes: 3 additions & 0 deletions soh/soh/GameMenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,9 @@ 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("Switch Arrow Types", "gArrowSwitching", true, false);
UIWidgets::Tooltip("Press R with the bow out to switch between normal, fire, ice, and light arrows\n"
"Use the \"Customize Game Controls\" window to switch with a different button");
ImGui::EndMenu();
}

Expand Down
3 changes: 2 additions & 1 deletion soh/src/code/z_map_exp.c
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,8 @@ void Minimap_Draw(PlayState* play) {
minimapToggleBtn = BTN_L;
// If any of these CVars are enabled, disable toggling the minimap with L
enableMapToggle =
!(CVarGetInteger("gDebugEnabled", 0) || CVarGetInteger("gMoonJumpOnL", 0) || CVarGetInteger("gTurboOnL", 0));
!(CVarGetInteger("gDebugEnabled", 0) || CVarGetInteger("gMoonJumpOnL", 0) || CVarGetInteger("gTurboOnL", 0) ||
(Player_CanSwitchArrows(GET_PLAYER(play) && CVarGetInteger("gArrowSwitchBtnMap", BTN_R) & BTN_L)));
}
// If this CVar is set, allow toggling the map despite conflicts
enableMapToggle = enableMapToggle || CVarGetInteger("gEnableMapToggle", 0);
Expand Down
137 changes: 130 additions & 7 deletions soh/src/overlays/actors/ovl_player_actor/z_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,98 @@ s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) {
}
}

typedef struct {
u8 asArrow;
u8 asBowArrow;
} ArrowItems;

static ArrowItems arrowTypeToItem[] = {
/* normal arrows */ { ITEM_BOW, ITEM_BOW },
/* fire arrows */ { ITEM_ARROW_FIRE, ITEM_BOW_ARROW_FIRE },
/* ice arrows */ { ITEM_ARROW_ICE, ITEM_BOW_ARROW_ICE },
/* light arrows */ { ITEM_ARROW_LIGHT, ITEM_BOW_ARROW_LIGHT },
/* unused arrow types are excluded from cycling */
};

static bool gSwitchingArrow = false;

// Returns true if the player is in a state where they can switch arrows.
// Specifically, the gArrowSwitching CVar is enabled, the player is holding the
// bow with normal, fire, ice, or light arrows, and they're either aiming or
// have an arrow notched.
bool Player_CanSwitchArrows(Player* this) {
if (!CVarGetInteger("gArrowSwitching", 0)) {
return false;
}

if (this->heldItemAction < PLAYER_IA_BOW || this->heldItemAction > PLAYER_IA_BOW_LIGHT) {
return false;
}

return this->func_82C == func_808351D4 || this->func_82C == func_808353D8;
}

bool Player_SwitchArrowsIfEnabled(PlayState* play, Player* this) {
if (!CVarGetInteger("gArrowSwitching", 0)) {
return false;
}
if (this->heldItemAction < PLAYER_IA_BOW || this->heldItemAction > PLAYER_IA_BOW_LIGHT) {
return false;
}
if (!CHECK_BTN_ANY(sControlInput->press.button, CVarGetInteger("gArrowSwitchBtnMap", BTN_R))) {
return false;
}

u8 i, newItem, newItemAction;
const u8 arrowCount = ARRAY_COUNT(arrowTypeToItem);
u8 heldArrowAP = this->heldItemAction - PLAYER_IA_BOW;
for (i = 1; i < arrowCount; i++) {
u8 arrowAP = (heldArrowAP + i) % arrowCount;
ArrowItems items = arrowTypeToItem[arrowAP];
if (INV_CONTENT(items.asArrow) != ITEM_NONE) {
newItem = items.asBowArrow;
newItemAction = PLAYER_IA_BOW + arrowAP;
break;
}
}
if (i == arrowCount) {
return false;
}

Inventory_ReplaceItem(play, INV_CONTENT(ITEM_BOW), newItem);
this->heldItemId = newItem;
this->itemAction = newItemAction;
this->heldItemAction = newItemAction;
return true;
}

// Replace previously nocked arrow with the new arrow type
void Player_ReplaceSwitchedArrow(PlayState* play, Player* this) {
s32 item, arrowType;
if (this->unk_860 < 0 || func_80834380(play, this, &item, &arrowType) <= 0) {
return;
}

s32 newMagicArrowType = arrowType - ARROW_FIRE;
s32 arrowCost;
if (newMagicArrowType < 0 || newMagicArrowType > 2) {
arrowCost = 0;
} else {
arrowCost = sMagicArrowCosts[newMagicArrowType];
}

if (arrowCost == 0 || !func_80087708(play, arrowCost, 4)) {
arrowType = ARROW_NORMAL;
}

if (this->heldActor != NULL) {
Actor_Kill(this->heldActor);
}
this->heldActor = Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_ARROW,
this->actor.world.pos.x, this->actor.world.pos.y,
this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, arrowType);
}

// The player has pressed the bow or hookshot button
s32 func_8083442C(Player* this, PlayState* play) {
s32 item;
Expand All @@ -2248,7 +2340,8 @@ s32 func_8083442C(Player* this, PlayState* play) {

if (this->unk_860 >= 0) {
if ((magicArrowType >= 0) && (magicArrowType <= 2) &&
!func_80087708(play, sMagicArrowCosts[magicArrowType], 0)) {
!func_80087708(play, sMagicArrowCosts[magicArrowType],
CVarGetInteger("gArrowSwitching", 0) ? 4 : 0)) {
arrowType = ARROW_NORMAL;
}

Expand Down Expand Up @@ -2315,7 +2408,7 @@ s32 func_80834758(PlayState* play, Player* this) {
if (!(this->stateFlags1 & (PLAYER_STATE1_22 | PLAYER_STATE1_23 | PLAYER_STATE1_29)) &&
(play->shootingGalleryStatus == 0) && (this->heldItemAction == this->itemAction) &&
(this->currentShield != PLAYER_SHIELD_NONE) && !Player_IsChildWithHylianShield(this) && func_80833BCC(this) &&
CHECK_BTN_ALL(sControlInput->cur.button, BTN_R)) {
!Player_CanSwitchArrows(this) && CHECK_BTN_ALL(sControlInput->cur.button, BTN_R)) {

anim = func_808346C4(play, this);
frame = Animation_GetLastFrame(anim);
Expand Down Expand Up @@ -2558,6 +2651,12 @@ s32 func_808350A4(PlayState* play, Player* this) {
}
} else {
Inventory_ChangeAmmo(item, -1);
if (CVarGetInteger("gArrowSwitching", 0) &&
arrowType >= ARROW_FIRE && arrowType <= ARROW_LIGHT
&& this->heldActor->child != NULL) {
gSaveContext.magicState = 0;
func_80087708(play, sMagicArrowCosts[arrowType - ARROW_FIRE], 0);
}
}

if (play->shootingGalleryStatus == 1) {
Expand Down Expand Up @@ -2611,6 +2710,11 @@ s32 func_808351D4(Player* this, PlayState* play) {

func_80834EB8(this, play);

if (gSwitchingArrow) {
Player_ReplaceSwitchedArrow(play, this);
gSwitchingArrow = false;
}

if ((this->unk_836 > 0) && ((this->unk_860 < 0) || (!D_80853618 && !func_80834E7C(play)))) {
func_80833638(this, func_808353D8);
if (this->unk_860 >= 0) {
Expand All @@ -2628,6 +2732,14 @@ s32 func_808351D4(Player* this, PlayState* play) {
this->stateFlags1 |= PLAYER_STATE1_9;
}

gSwitchingArrow = Player_SwitchArrowsIfEnabled(play, this);
if (gSwitchingArrow && this->heldActor != NULL) {
if (this->heldActor->child != NULL) {
Actor_Kill(this->heldActor->child);
}
gSwitchingArrow = true;
}

return 1;
}

Expand All @@ -2638,6 +2750,8 @@ s32 func_808353D8(Player* this, PlayState* play) {
return 1;
}

Player_SwitchArrowsIfEnabled(play, this);

if (!func_80834758(play, this) &&
(D_80853614 || ((this->unk_860 < 0) && D_80853618) || func_80834E44(play))) {
this->unk_860 = ABS(this->unk_860);
Expand Down Expand Up @@ -5213,7 +5327,11 @@ s32 func_8083B644(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_21;
}

if (!CHECK_BTN_ALL(sControlInput->press.button, CVarGetInteger("gNaviOnL", 0) ? BTN_L : BTN_CUP) &&
u16 naviButton = CVarGetInteger("gNaviOnL", 0) ? BTN_L : BTN_CUP;
if (Player_CanSwitchArrows(this)) {
naviButton &= ~CVarGetInteger("gArrowSwitchBtnMap", BTN_R);
}
if (!(naviButton && CHECK_BTN_ALL(sControlInput->press.button, naviButton)) &&
!sp28) {
return 0;
}
Expand Down Expand Up @@ -11436,15 +11554,20 @@ void func_8084B1D8(Player* this, PlayState* play) {
func_80836670(this, play);
}

u16 buttonsToCheck = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP;
u16 itemButtons = BTN_A | BTN_B | BTN_R | BTN_CUP | BTN_CLEFT | BTN_CRIGHT | BTN_CDOWN | BTN_DUP;
if (CVarGetInteger("gDpadEquips", 0) != 0) {
buttonsToCheck |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
itemButtons |= BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT;
}
u16 returnButtons = BTN_A | BTN_B | BTN_R;
if (Player_CanSwitchArrows(this)) {
itemButtons &= ~CVarGetInteger("gArrowSwitchBtnMap", BTN_R);
returnButtons &= ~CVarGetInteger("gArrowSwitchBtnMap", BTN_R);
}
if ((this->csMode != 0) || (this->unk_6AD == 0) || (this->unk_6AD >= 4) || func_80833B54(this) ||
(this->unk_664 != NULL) || !func_8083AD4C(play, this) ||
(((this->unk_6AD == 2) && (CHECK_BTN_ANY(sControlInput->press.button, BTN_A | BTN_B | BTN_R) ||
(((this->unk_6AD == 2) && (CHECK_BTN_ANY(sControlInput->press.button, returnButtons) ||
func_80833B2C(this) || (!func_8002DD78(this) && !func_808334B4(this)))) ||
((this->unk_6AD == 1) && CHECK_BTN_ANY(sControlInput->press.button, buttonsToCheck)))) {
((this->unk_6AD == 1) && CHECK_BTN_ANY(sControlInput->press.button, itemButtons)))) {
func_8083C148(this, play);
func_80078884(NA_SE_SY_CAMERA_ZOOM_UP);
} else if ((DECR(this->unk_850) == 0) || (this->unk_6AD != 2)) {
Expand Down

0 comments on commit 036f1a4

Please sign in to comment.