summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArchez <Archez@users.noreply.github.com>2024-10-05 12:54:00 -0400
committerGitHub <noreply@github.com>2024-10-05 12:54:00 -0400
commit69edc89292dc89e8dacf830b501869f0282efcad (patch)
tree52b77ff9a52a42c45c8ce85ed83c27ced2a84636
parenta93f011253177647cf227669d51df201282c90f6 (diff)
[Enhancement] Keep Express Mail in the same cycle (#791)
* Add enhancement for reusing letter to mama in one cycle * add menu widget item for express mail
-rw-r--r--mm/2s2h/BenGui/BenMenuBar.cpp7
-rw-r--r--mm/2s2h/BenGui/SearchableMenuItems.h11
-rw-r--r--mm/2s2h/Enhancements/Cycle/Cycle.h1
-rw-r--r--mm/2s2h/Enhancements/Cycle/KeepExpressMail.cpp55
-rw-r--r--mm/2s2h/Enhancements/Enhancements.cpp1
-rw-r--r--mm/2s2h/GameInteractor/GameInteractor.h1
-rw-r--r--mm/src/code/z_msgevent.c6
7 files changed, 82 insertions, 0 deletions
diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp
index e8f7d7352..081d13955 100644
--- a/mm/2s2h/BenGui/BenMenuBar.cpp
+++ b/mm/2s2h/BenGui/BenMenuBar.cpp
@@ -476,6 +476,13 @@ void DrawEnhancementsMenu() {
{ .tooltip =
"Playing the Song Of Time will not reset the current time speed set by Inverted Song of Time." });
+ if (UIWidgets::CVarCheckbox(
+ "Keep Express Mail", "gEnhancements.Cycle.KeepExpressMail",
+ { .tooltip = "Allows the player to keep the Express Mail in their inventory after delivering it "
+ "the first time, so that both deliveries can be done within one cycle" })) {
+ RegisterKeepExpressMail();
+ }
+
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 255, 0, 255));
ImGui::SeparatorText("Unstable");
ImGui::PopStyleColor();
diff --git a/mm/2s2h/BenGui/SearchableMenuItems.h b/mm/2s2h/BenGui/SearchableMenuItems.h
index 95785d296..e4279230e 100644
--- a/mm/2s2h/BenGui/SearchableMenuItems.h
+++ b/mm/2s2h/BenGui/SearchableMenuItems.h
@@ -930,6 +930,17 @@ void AddEnhancements() {
"Playing the Song Of Time will not reset the Sword back to Kokiri Sword.", WIDGET_CVAR_CHECKBOX },
{ "Do not reset Rupees", "gEnhancements.Cycle.DoNotResetRupees",
"Playing the Song Of Time will not reset the your rupees.", WIDGET_CVAR_CHECKBOX },
+ { "Do not reset Time Speed", "gEnhancements.Cycle.DoNotResetTimeSpeed",
+ "Playing the Song Of Time will not reset the current time speed set by Inverted Song of Time.",
+ WIDGET_CVAR_CHECKBOX },
+ {
+ .widgetName = "Keep Express Mail",
+ .widgetCVar = "gEnhancements.Cycle.KeepExpressMail",
+ .widgetTooltip = "Allows the player to keep the Express Mail in their inventory after delivering it "
+ "the first time, so that both deliveries can be done within one cycle",
+ .widgetType = WIDGET_CVAR_CHECKBOX,
+ .widgetCallback = [](widgetInfo& info) { RegisterKeepExpressMail(); },
+ },
{ .widgetName = "Unstable",
.widgetType = WIDGET_SEPARATOR_TEXT,
.widgetOptions = { .color = UIWidgets::Colors::Yellow } },
diff --git a/mm/2s2h/Enhancements/Cycle/Cycle.h b/mm/2s2h/Enhancements/Cycle/Cycle.h
index 612ff1991..9c8812743 100644
--- a/mm/2s2h/Enhancements/Cycle/Cycle.h
+++ b/mm/2s2h/Enhancements/Cycle/Cycle.h
@@ -2,5 +2,6 @@
#define CYCLE_H
void RegisterEndOfCycleSaveHooks();
+void RegisterKeepExpressMail();
#endif // CYCLE_H
diff --git a/mm/2s2h/Enhancements/Cycle/KeepExpressMail.cpp b/mm/2s2h/Enhancements/Cycle/KeepExpressMail.cpp
new file mode 100644
index 000000000..196082d86
--- /dev/null
+++ b/mm/2s2h/Enhancements/Cycle/KeepExpressMail.cpp
@@ -0,0 +1,55 @@
+#include "libultraship/bridge.h"
+#include "2s2h/GameInteractor/GameInteractor.h"
+
+extern "C" {
+#include "z64save.h"
+#include "z64scene.h"
+#include "variables.h"
+}
+
+static HOOK_ID onItemDeleteID = 0;
+
+void CheckScene(s16 sceneId) {
+ if (sceneId != SCENE_MILK_BAR && sceneId != SCENE_POSTHOUSE) {
+ return;
+ }
+
+ onItemDeleteID = REGISTER_VB_SHOULD(VB_MSG_SCRIPT_DEL_ITEM, {
+ Actor* actor = va_arg(args, Actor*);
+ ItemId itemId = va_arg(args, ItemId);
+
+ // Keep the express mail only on the first trade for the cycle
+ // Postman checking for Madame Aroma trade cycle flag
+ // Madame Aroma checking for Postman trade cycle flag
+ if (itemId == ITEM_LETTER_MAMA && (actor->id == ACTOR_EN_PM && !CHECK_WEEKEVENTREG(WEEKEVENTREG_57_04)) ||
+ (actor->id == ACTOR_EN_AL && !CHECK_WEEKEVENTREG(WEEKEVENTREG_86_01))) {
+ *should = false;
+ }
+ });
+}
+
+void RegisterKeepExpressMail() {
+ static HOOK_ID onSceneInitID = 0;
+
+ GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::ShouldVanillaBehavior>(onItemDeleteID);
+ GameInteractor::Instance->UnregisterGameHook<GameInteractor::OnSceneInit>(onSceneInitID);
+ onSceneInitID = 0;
+ onItemDeleteID = 0;
+
+ if (!CVarGetInteger("gEnhancements.Cycle.KeepExpressMail", 0)) {
+ return;
+ }
+
+ // Register item hook right away after toggle
+ if (gPlayState != nullptr) {
+ CheckScene(gPlayState->sceneId);
+ }
+
+ onSceneInitID =
+ GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](s16 sceneId, s8 spawnNum) {
+ GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::ShouldVanillaBehavior>(onItemDeleteID);
+ onItemDeleteID = 0;
+
+ CheckScene(sceneId);
+ });
+}
diff --git a/mm/2s2h/Enhancements/Enhancements.cpp b/mm/2s2h/Enhancements/Enhancements.cpp
index 0e014d318..f7f1a4a1a 100644
--- a/mm/2s2h/Enhancements/Enhancements.cpp
+++ b/mm/2s2h/Enhancements/Enhancements.cpp
@@ -22,6 +22,7 @@ void InitEnhancements() {
RegisterEndOfCycleSaveHooks();
RegisterSavingEnhancements();
RegisterAutosave();
+ RegisterKeepExpressMail();
// Dialogue
RegisterFastBankSelection();
diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h
index d73e763ae..e3f79ecb6 100644
--- a/mm/2s2h/GameInteractor/GameInteractor.h
+++ b/mm/2s2h/GameInteractor/GameInteractor.h
@@ -48,6 +48,7 @@ typedef enum {
VB_SONG_AVAILABLE_TO_PLAY,
VB_USE_CUSTOM_CAMERA,
VB_DELETE_OWL_SAVE,
+ VB_MSG_SCRIPT_DEL_ITEM,
VB_CONSIDER_BUNNY_HOOD_EQUIPPED,
VB_USE_ITEM_EQUIP_MASK,
VB_KALEIDO_DISPLAY_ITEM_TEXT,
diff --git a/mm/src/code/z_msgevent.c b/mm/src/code/z_msgevent.c
index 469d46c77..9e8d4cb08 100644
--- a/mm/src/code/z_msgevent.c
+++ b/mm/src/code/z_msgevent.c
@@ -1,5 +1,7 @@
#include "global.h"
+#include "2s2h/GameInteractor/GameInteractor.h"
+
#define MSCRIPT_CONTINUE 0
#define MSCRIPT_STOP 1
@@ -876,6 +878,10 @@ s32 MsgEvent_Cmd42(Actor* actor, PlayState* play, u8** scriptPtr, MsgEventCallba
u8* script = *scriptPtr;
s16 item = MSCRIPT_GET_16(script, 1);
+ if (!GameInteractor_Should(VB_MSG_SCRIPT_DEL_ITEM, true, actor, item)) {
+ return MSCRIPT_CONTINUE;
+ }
+
Inventory_DeleteItem(item, SLOT(item));
return MSCRIPT_CONTINUE;
}