summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Dubé <159546+serprex@users.noreply.github.com>2026-08-09 15:46:51 +0000
committerGitHub <noreply@github.com>2026-08-09 15:46:51 +0000
commitbf7177256a0b0e774fc9b468f3e5da599f461d8f (patch)
tree6c1df0d262b2d36fcc8b85027b35edcb0720e354
parent0254c1f3a4893ad724e6806748f1323f24c60ab7 (diff)
FixFlexDrops (#7047)
-rw-r--r--soh/soh/Enhancements/Fixes/FixFlexDrops.cpp21
-rw-r--r--soh/soh/Enhancements/TimeSavers/FasterShadowShip.cpp2
-rw-r--r--soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h8
-rw-r--r--soh/soh/SohGui/SohMenuEnhancements.cpp5
-rw-r--r--soh/src/code/z_en_item00.c8
5 files changed, 40 insertions, 4 deletions
diff --git a/soh/soh/Enhancements/Fixes/FixFlexDrops.cpp b/soh/soh/Enhancements/Fixes/FixFlexDrops.cpp
new file mode 100644
index 000000000..6efcbf565
--- /dev/null
+++ b/soh/soh/Enhancements/Fixes/FixFlexDrops.cpp
@@ -0,0 +1,21 @@
+#include "soh/Enhancements/game-interactor/GameInteractor.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+#include "z64.h"
+// Converts a drop id based on age, health and owned items. Returns -1 when the drop can't be given.
+s16 func_8001F404(s16 dropId);
+}
+
+static void RegisterFixFlexDrops() {
+ // The flex drop picks the first thing you're low on, but doesn't check that you own the item to hold it,
+ // so the drop is thrown away instead of falling through to the next candidate.
+ COND_VB_SHOULD(VB_FLEX_DROP_AMMO, CVarGetInteger(CVAR_ENHANCEMENT("FixFlexDrops"), 0), {
+ s16 dropId = va_arg(args, s32);
+ if (*should && func_8001F404(dropId) == -1) {
+ *should = false;
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterFixFlexDrops, { CVAR_ENHANCEMENT("FixFlexDrops") });
diff --git a/soh/soh/Enhancements/TimeSavers/FasterShadowShip.cpp b/soh/soh/Enhancements/TimeSavers/FasterShadowShip.cpp
index c59ccc603..265dc6e35 100644
--- a/soh/soh/Enhancements/TimeSavers/FasterShadowShip.cpp
+++ b/soh/soh/Enhancements/TimeSavers/FasterShadowShip.cpp
@@ -6,7 +6,7 @@ extern "C" {
#include "src/overlays/actors/ovl_Bg_Haka_Ship/z_bg_haka_ship.h"
}
-void RegisterFasterShadowShip() {
+static void RegisterFasterShadowShip() {
COND_VB_SHOULD(VB_SHADOW_SHIP_SET_SPEED, CVarGetInteger(CVAR_ENHANCEMENT("FasterShadowShip"), 0), {
BgHakaShip* ship = va_arg(args, BgHakaShip*);
PlayState* play = va_arg(args, PlayState*);
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index 2abd666af..f0b91582c 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -793,6 +793,14 @@ typedef enum {
// #### `result`
// ```c
+ // varies
+ // ```
+ // #### `args`
+ // - `s32` (drop id)
+ VB_FLEX_DROP_AMMO,
+
+ // #### `result`
+ // ```c
// true
// ```
// #### `args`
diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp
index 74bcc7757..086e0f023 100644
--- a/soh/soh/SohGui/SohMenuEnhancements.cpp
+++ b/soh/soh/SohGui/SohMenuEnhancements.cpp
@@ -1079,6 +1079,11 @@ void SohMenu::AddMenuEnhancements() {
.CVar(CVAR_ENHANCEMENT("BushDropFix"))
.Options(CheckboxOptions().Tooltip(
"Fixes the bushes to drop items correctly rather than spawning undefined items."));
+ AddWidget(path, "Fix Flex Drops", WIDGET_CVAR_CHECKBOX)
+ .CVar(CVAR_ENHANCEMENT("FixFlexDrops"))
+ .Options(CheckboxOptions().Tooltip(
+ "The flex drop gives whichever ammo you are lowest on, but doesn't check that you own the item to hold "
+ "it, so the drop is lost. This makes it skip ammo you can't carry."));
AddWidget(path, "Fix Enemies not Spawning Near Water", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("EnemySpawnsOverWaterboxes"))
.Options(CheckboxOptions().Tooltip(
diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c
index 237745a01..cd2e0bd17 100644
--- a/soh/src/code/z_en_item00.c
+++ b/soh/src/code/z_en_item00.c
@@ -1727,15 +1727,17 @@ void Item_DropCollectibleRandom(PlayState* play, Actor* fromActor, Vec3f* spawnP
params = 0xA * 0x10;
dropTableIndex = 0x0;
dropId = ITEM00_MAGIC_SMALL;
- } else if (!LINK_IS_ADULT && (AMMO(ITEM_SLINGSHOT) < 6)) {
+ } else if (GameInteractor_Should(VB_FLEX_DROP_AMMO, !LINK_IS_ADULT && (AMMO(ITEM_SLINGSHOT) < 6),
+ ITEM00_SEEDS)) {
params = 0xA * 0x10;
dropTableIndex = 0x0;
dropId = ITEM00_SEEDS;
- } else if (LINK_IS_ADULT && (AMMO(ITEM_BOW) < 6)) {
+ } else if (GameInteractor_Should(VB_FLEX_DROP_AMMO, LINK_IS_ADULT && (AMMO(ITEM_BOW) < 6),
+ ITEM00_ARROWS_MEDIUM)) {
params = 0xA * 0x10;
dropTableIndex = 0x0;
dropId = ITEM00_ARROWS_MEDIUM;
- } else if (AMMO(ITEM_BOMB) < 6) {
+ } else if (GameInteractor_Should(VB_FLEX_DROP_AMMO, AMMO(ITEM_BOMB) < 6, ITEM00_BOMBS_A)) {
params = 0xD * 0x10;
dropTableIndex = 0x0;
dropId = ITEM00_BOMBS_A;