From ef64ac08f82d43708966b799e0ae07c4cd1f8509 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Sun, 12 Apr 2026 11:22:16 -0400 Subject: [PATCH] No Heart Drops --- include/dusk/settings.h | 1 + src/dusk/imgui/ImGuiMenuEnhancements.cpp | 6 ++++++ src/dusk/settings.cpp | 2 ++ src/f_op/f_op_actor_mng.cpp | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/include/dusk/settings.h b/include/dusk/settings.h index 8418602251..a5642d6036 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -40,6 +40,7 @@ struct UserSettings { ConfigVar disableRupeeCutscenes; ConfigVar noSwordRecoil; ConfigVar damageMultiplier; + ConfigVar noHeartDrops; ConfigVar instantDeath; ConfigVar fastClimbing; ConfigVar noMissClimbing; diff --git a/src/dusk/imgui/ImGuiMenuEnhancements.cpp b/src/dusk/imgui/ImGuiMenuEnhancements.cpp index b505d84345..bef252467d 100644 --- a/src/dusk/imgui/ImGuiMenuEnhancements.cpp +++ b/src/dusk/imgui/ImGuiMenuEnhancements.cpp @@ -131,6 +131,12 @@ namespace dusk { if (ImGui::BeginMenu("Difficulty")) { config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d"); + config::ImGuiCheckbox("No Heart Drops", getSettings().game.noHeartDrops); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Hearts will never drop from enemies,\n" + "pots and various other places."); + } + config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath); if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Any hit will instantly kill you."); diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index dabed72f19..cc55403ddd 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -28,6 +28,7 @@ UserSettings g_userSettings = { .disableRupeeCutscenes {"game.disableRupeeCutscenes", false}, .noSwordRecoil {"game.noSwordRecoil", false}, .damageMultiplier {"game.damageMultiplier", 1}, + .noHeartDrops{"game.noHeartDrops", false}, .instantDeath {"game.instantDeath", false}, .fastClimbing {"game.fastClimbing", false}, .noMissClimbing {"game.noMissClimbing", false}, @@ -96,6 +97,7 @@ void registerSettings() { Register(g_userSettings.game.disableRupeeCutscenes); Register(g_userSettings.game.noSwordRecoil); Register(g_userSettings.game.damageMultiplier); + Register(g_userSettings.game.noHeartDrops); Register(g_userSettings.game.instantDeath); Register(g_userSettings.game.fastClimbing); Register(g_userSettings.game.fastTears); diff --git a/src/f_op/f_op_actor_mng.cpp b/src/f_op/f_op_actor_mng.cpp index dca07f98ba..60d21123cb 100644 --- a/src/f_op/f_op_actor_mng.cpp +++ b/src/f_op/f_op_actor_mng.cpp @@ -1631,6 +1631,12 @@ fpc_ProcID fopAcM_createItem(const cXyz* i_pos, int i_itemNo, int i_itemBitNo, i JUT_ASSERT(4067, 0 <= i_itemNo && i_itemNo < 256 && (-1 <= i_itemBitNo && i_itemBitNo < (dSv_info_c::DAN_ITEM + dSv_info_c::MEMORY_ITEM + dSv_info_c::ZONE_ITEM )) || i_itemBitNo == 255); // clang-format on + #if TARGET_PC + if (dusk::getSettings().game.noHeartDrops && isHeart(i_itemNo)) { + return fpcM_ERROR_PROCESS_ID_e; + } + #endif + if (i_itemNo == dItemNo_NONE_e) { return fpcM_ERROR_PROCESS_ID_e; } @@ -1695,6 +1701,12 @@ fopAc_ac_c* fopAcM_fastCreateItem2(const cXyz* i_pos, int i_itemNo, int i_itemBi JUT_ASSERT(4202, 0 <= i_itemNo && i_itemNo < 256 && (-1 <= i_itemBitNo && i_itemBitNo < (dSv_info_c::DAN_ITEM + dSv_info_c::MEMORY_ITEM + dSv_info_c::ZONE_ITEM )) || i_itemBitNo == 255); // clang-format on + #if TARGET_PC + if (dusk::getSettings().game.noHeartDrops && isHeart(i_itemNo)) { + return NULL; + } + #endif + csXyz item_angle(csXyz::Zero); if (i_itemNo == dItemNo_NONE_e) { @@ -1761,6 +1773,12 @@ fopAc_ac_c* fopAcM_fastCreateItem(const cXyz* i_pos, int i_itemNo, int i_roomNo, f32* i_speedY, int i_itemBitNo, int param_9, createFunc i_createFunc) { JUT_ASSERT(4324, 0 <= i_itemNo && i_itemNo < 256); + + #if TARGET_PC + if (dusk::getSettings().game.noHeartDrops && isHeart(i_itemNo)) { + return NULL; + } + #endif csXyz angle; if (i_itemNo == dItemNo_NONE_e) {