diff --git a/soh/soh/Enhancements/Fixes/FixFlexDrops.cpp b/soh/soh/Enhancements/Fixes/FixFlexDrops.cpp new file mode 100644 index 0000000000..6efcbf5650 --- /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 c59ccc6037..265dc6e352 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 2abd666af0..f0b91582c1 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -791,6 +791,14 @@ typedef enum { // - None VB_FLASH_SCREEN_FOR_FINISHING_BLOW, + // #### `result` + // ```c + // varies + // ``` + // #### `args` + // - `s32` (drop id) + VB_FLEX_DROP_AMMO, + // #### `result` // ```c // true diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 74bcc7757e..086e0f023a 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 237745a016..cd2e0bd17d 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;