[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
This commit is contained in:
Archez
2024-10-05 12:54:00 -04:00
committed by GitHub
parent a93f011253
commit 69edc89292
7 changed files with 82 additions and 0 deletions
+7
View File
@@ -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();
+11
View File
@@ -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 } },
+1
View File
@@ -2,5 +2,6 @@
#define CYCLE_H
void RegisterEndOfCycleSaveHooks();
void RegisterKeepExpressMail();
#endif // CYCLE_H
@@ -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);
});
}
+1
View File
@@ -22,6 +22,7 @@ void InitEnhancements() {
RegisterEndOfCycleSaveHooks();
RegisterSavingEnhancements();
RegisterAutosave();
RegisterKeepExpressMail();
// Dialogue
RegisterFastBankSelection();
+1
View File
@@ -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,
+6
View File
@@ -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;
}