diff --git a/mm/2s2h/BenGui/SearchableMenuItems.h b/mm/2s2h/BenGui/SearchableMenuItems.h index ff8651d8a4..3fd6f95af2 100644 --- a/mm/2s2h/BenGui/SearchableMenuItems.h +++ b/mm/2s2h/BenGui/SearchableMenuItems.h @@ -1064,38 +1064,6 @@ void AddEnhancements() { { 1, 5, 1 } }, { "Dpad Equips", "gEnhancements.Dpad.DpadEquips", "Allows you to equip items to your d-pad", WIDGET_CVAR_CHECKBOX }, - { "Always Win Doggy Race", - "gEnhancements.Minigames.AlwaysWinDoggyRace", - "Makes the Doggy Race easier to win.", - WIDGET_CVAR_COMBOBOX, - { .comboBoxOptions = alwaysWinDoggyraceOptions } }, - { "Milk Run Reward Options", - "gEnhancements.Minigames.CremiaHugs", - "Choose what reward you get for winning the Milk Run minigame after the first time. \n" - "-Vanilla: Reward is Random\n" - "-Hug: Get the hugging cutscene\n" - "-Rupee: Get the rupee reward", - WIDGET_CVAR_COMBOBOX, - { .comboBoxOptions = cremiaRewardOptions } }, - { "Gibdo Trade Sequence Options", - "gEnhancements.Minigames.GibdoTradeSequence", - "Changes the way the Gibdo Trade Sequence works\n" - "-Vanilla: Works normally\n" - "-MM3D: Gibdos will only take one quantity of the item they request, as they do in MM3D. The Gibdo " - "requesting a blue potion will also accept a red potion.\n" - "-No trade: Gibdos will vanish without taking items", - WIDGET_CVAR_COMBOBOX, - { .comboBoxOptions = gibdoTradeSequenceOptions } }, - { "Cucco Shack Cucco Count", - "gEnhancements.Minigames.CuccoShackCuccoCount", - "Choose how many cuccos you need to raise to make Grog happy.", - WIDGET_CVAR_SLIDER_INT, - { 1, 10, 10 } }, - { "Swordsman School Winning Score", - "gEnhancements.Minigames.SwordsmanSchoolScore", - "Sets the score required to win the Swordsman School.", - WIDGET_CVAR_SLIDER_INT, - { 1, 30, 30 } }, { "Fast Magic Arrow Equip Animation", "gEnhancements.Equipment.MagicArrowEquipSpeed", "Removes the animation for equipping Magic Arrows.", WIDGET_CVAR_CHECKBOX }, { "Instant Fin Boomerangs Recall", "gEnhancements.PlayerActions.InstantRecall", @@ -1104,26 +1072,89 @@ void AddEnhancements() { { "Two-Handed Sword Spin Attack", "gEnhancements.Equipment.TwoHandedSwordSpinAttack", "Enables magic spin attacks for the Fierce Deity Sword and Great Fairy's Sword.", WIDGET_CVAR_CHECKBOX } }, - { { .widgetName = "Modes", .widgetType = WIDGET_SEPARATOR_TEXT }, - { "Play as Kafei", "gModes.PlayAsKafei", "Requires scene reload to take effect.", WIDGET_CVAR_CHECKBOX }, - { "Hyrule Warriors Styled Link", "gModes.HyruleWarriorsStyledLink", - "When acquired, places the Keaton and Fierce Deity masks on Link similarly to how he wears them in " - "Hyrule Warriors", - WIDGET_CVAR_CHECKBOX }, - { "Time Moves when you Move", "gModes.TimeMovesWhenYouMove", - "Time only moves when Link is not standing still.", WIDGET_CVAR_CHECKBOX }, - { "Mirrored World", - "gModes.MirroredWorld.Mode", - "Mirrors the world horizontally.", - WIDGET_CVAR_CHECKBOX, - {}, - ([](widgetInfo& info) { - if (CVarGetInteger("gModes.MirroredWorld.Mode", 0)) { - CVarSetInteger("gModes.MirroredWorld.State", 1); - } else { - CVarClear("gModes.MirroredWorld.State"); - } - }) } }, + { + { .widgetName = "Modes", .widgetType = WIDGET_SEPARATOR_TEXT }, + { "Play as Kafei", "gModes.PlayAsKafei", "Requires scene reload to take effect.", + WIDGET_CVAR_CHECKBOX }, + { "Hyrule Warriors Styled Link", "gModes.HyruleWarriorsStyledLink", + "When acquired, places the Keaton and Fierce Deity masks on Link similarly to how he wears them in " + "Hyrule Warriors", + WIDGET_CVAR_CHECKBOX }, + { "Time Moves when you Move", "gModes.TimeMovesWhenYouMove", + "Time only moves when Link is not standing still.", WIDGET_CVAR_CHECKBOX }, + { "Mirrored World", + "gModes.MirroredWorld.Mode", + "Mirrors the world horizontally.", + WIDGET_CVAR_CHECKBOX, + {}, + ([](widgetInfo& info) { + if (CVarGetInteger("gModes.MirroredWorld.Mode", 0)) { + CVarSetInteger("gModes.MirroredWorld.State", 1); + } else { + CVarClear("gModes.MirroredWorld.State"); + } + }) }, + { .widgetName = "Minigames", .widgetType = WIDGET_SEPARATOR_TEXT }, + { "Always Win Doggy Race", + "gEnhancements.Minigames.AlwaysWinDoggyRace", + "Makes the Doggy Race easier to win.", + WIDGET_CVAR_COMBOBOX, + { .comboBoxOptions = alwaysWinDoggyraceOptions } }, + { "Milk Run Reward Options", + "gEnhancements.Minigames.CremiaHugs", + "Choose what reward you get for winning the Milk Run minigame after the first time. \n" + "-Vanilla: Reward is Random\n" + "-Hug: Get the hugging cutscene\n" + "-Rupee: Get the rupee reward", + WIDGET_CVAR_COMBOBOX, + { .comboBoxOptions = cremiaRewardOptions } }, + { "Gibdo Trade Sequence Options", + "gEnhancements.Minigames.GibdoTradeSequence", + "Changes the way the Gibdo Trade Sequence works\n" + "-Vanilla: Works normally\n" + "-MM3D: Gibdos will only take one quantity of the item they request, as they do in MM3D. The Gibdo " + "requesting a blue potion will also accept a red potion.\n" + "-No trade: Gibdos will vanish without taking items", + WIDGET_CVAR_COMBOBOX, + { .comboBoxOptions = gibdoTradeSequenceOptions } }, + { "Cucco Shack Cucco Count", + "gEnhancements.Minigames.CuccoShackCuccoCount", + "Choose how many cuccos you need to raise to make Grog happy.", + WIDGET_CVAR_SLIDER_INT, + { 1, 10, 10 } }, + { "Swordsman School Winning Score", + "gEnhancements.Minigames.SwordsmanSchoolScore", + "Sets the score required to win the Swordsman School.", + WIDGET_CVAR_SLIDER_INT, + { 1, 30, 30 } }, + { "Swamp Archery Perfect Score", + "gEnhancements.Minigames.SwampArcheryScore", + "Sets the score required to win the Swamp Archery minigame, if this is changed it also speeds up the " + "final score counting.", + WIDGET_CVAR_SLIDER_INT, + { 1000, 2180, 2180 } }, + { "Town Archery Perfect Score", + "gEnhancements.Minigames.TownArcheryScore", + "Sets the score required to win the Town Archery minigame. Reaching this score will end the " + "minigame.", + WIDGET_CVAR_SLIDER_INT, + { 1, 50, 50 } }, + { "Honey & Darling Day 1 (Bombchus)", + "gEnhancements.Minigames.HoneyAndDarlingDay1", + "Sets the score required to win the Honey & Darling minigame on Day 1.", + WIDGET_CVAR_SLIDER_INT, + { 1, 8, 8 } }, + { "Honey & Darling Day 2 (Bombs)", + "gEnhancements.Minigames.HoneyAndDarlingDay2", + "Sets the score required to win the Honey & Darling minigame on Day 2.", + WIDGET_CVAR_SLIDER_INT, + { 1, 8, 8 } }, + { "Honey & Darling Day 3 (Bow)", + "gEnhancements.Minigames.HoneyAndDarlingDay3", + "Sets the score required to win the Honey & Darling minigame on Day 3.", + WIDGET_CVAR_SLIDER_INT, + { 1, 16, 16 } }, + }, { { .widgetName = "Saving", .widgetType = WIDGET_SEPARATOR_TEXT }, { "Persistent Owl Saves", "gEnhancements.Saving.PersistentOwlSaves", "Continuing a save will not remove the owl save. Playing Song of " diff --git a/mm/2s2h/Enhancements/Cutscenes/MiscInteractions/SkipOwlInteractions.cpp b/mm/2s2h/Enhancements/Cutscenes/MiscInteractions/SkipOwlInteractions.cpp new file mode 100644 index 0000000000..f00d008bc5 --- /dev/null +++ b/mm/2s2h/Enhancements/Cutscenes/MiscInteractions/SkipOwlInteractions.cpp @@ -0,0 +1,51 @@ +#include +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { +#include "overlays/actors/ovl_En_Owl/z_en_owl.h" +void func_8095AAD0(EnOwl* enOwl, PlayState* play); +void func_8095A920(EnOwl* enOwl, PlayState* play); +void func_8095B9FC(EnOwl* enOwl, PlayState* play); +void func_8095B574(EnOwl* enOwl, PlayState* play); +void func_8095C484(EnOwl* enOwl); +void EnOwl_ChangeMode(EnOwl* enOwl, EnOwlActionFunc actionFunc, EnOwlFunc unkFunc, SkelAnime* skelAnime, + AnimationHeader* animation, f32 morphFrames); +} + +#define CVAR_NAME "gEnhancements.Cutscenes.SkipMiscInteractions" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + +void flyOnApproach(EnOwl* enOwl, PlayState* play) { + func_8095A920(enOwl, play); // Turn to face player + if (enOwl->actor.xzDistToPlayer < 200.0f) { + s32 owlType = ENOWL_GET_TYPE(&enOwl->actor); + if (owlType == ENOWL_GET_TYPE_2) { // Winter Village owl + // Start flying across the invisible platforms + EnOwl_ChangeMode(enOwl, func_8095B9FC, func_8095C484, &enOwl->skelAnimeFlying, + (AnimationHeader*)&gOwlUnfoldWingsAnim, 0.0f); + } else if (owlType == ENOWL_GET_TYPE_3) { // Southern Swamp owl + // Set flag to enable interaction with Song of Soaring engraving + Flags_SetSwitch(gPlayState, ENOWL_GET_SWITCH_FLAG(&enOwl->actor)); + enOwl->actionFunc = func_8095AAD0; // Fly away + } + } +} + +void RegisterSkipOwlInteractions() { + // Quietly change the owl's actionFunc to have it fly away on player proximity + COND_ID_HOOK(OnActorInit, ACTOR_EN_OWL, CVAR, [](Actor* actor) { + EnOwl* enOwl = (EnOwl*)actor; + enOwl->actionFunc = flyOnApproach; + }); + + // Ditto, after the owl has made it across the invisible platforms in the Winter Village + COND_VB_SHOULD(VB_OWL_TELL_ABOUT_SHRINE, CVAR, { + EnOwl* enOwl = va_arg(args, EnOwl*); + EnOwl_ChangeMode(enOwl, flyOnApproach, func_8095C484, &enOwl->skelAnimePerching, + (AnimationHeader*)&gOwlPerchAnim, 0.0f); + *should = false; + }); +} + +static RegisterShipInitFunc initFunc(RegisterSkipOwlInteractions, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp b/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp index cd4a2b8e02..33f5cff4f9 100644 --- a/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp +++ b/mm/2s2h/Enhancements/Masks/PersistentMasks.cpp @@ -50,16 +50,21 @@ void UpdatePersistentMasksState() { // This hook draws the mask on the players head when it's active and they aren't in first person onPlayerPostLimbDrawHook = GameInteractor::Instance->RegisterGameHookForID( PLAYER_LIMB_HEAD, [](Player* player, s32 limbIndex) { - // Ensure they aren't in first person - if (STATE_CVAR && !(player->stateFlags1 & PLAYER_STATE1_100000)) { - OPEN_DISPS(gPlayState->state.gfxCtx); - Matrix_Push(); - Player_DrawBunnyHood(gPlayState); - gSPDisplayList(POLY_OPA_DISP++, - (Gfx*)D_801C0B20[PLAYER_MASK_BUNNY - 1]); // D_801C0B20 is an array of mask DLs - Matrix_Pop(); - CLOSE_DISPS(gPlayState->state.gfxCtx); + if (!STATE_CVAR) { + return; } + + if (player->transformation == PLAYER_FORM_DEKU && player->stateFlags1 & PLAYER_STATE1_100000) { + return; + } + + OPEN_DISPS(gPlayState->state.gfxCtx); + Matrix_Push(); + Player_DrawBunnyHood(gPlayState); + gSPDisplayList(POLY_OPA_DISP++, + (Gfx*)D_801C0B20[PLAYER_MASK_BUNNY - 1]); // D_801C0B20 is an array of mask DLs + Matrix_Pop(); + CLOSE_DISPS(gPlayState->state.gfxCtx); }); // This hook sets up the quad and draws the "active" blue border around the mask in the pause menu diff --git a/mm/2s2h/Enhancements/Minigames/Archery.cpp b/mm/2s2h/Enhancements/Minigames/Archery.cpp new file mode 100644 index 0000000000..067e8d298b --- /dev/null +++ b/mm/2s2h/Enhancements/Minigames/Archery.cpp @@ -0,0 +1,54 @@ +#include +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { +#include "overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.h" + +void EnSyatekiMan_Swamp_RunGame(EnSyatekiMan* enSyatekiMan, PlayState* play); +void EnSyatekiMan_Town_RunGame(EnSyatekiMan* enSyatekiMan, PlayState* play); +} + +#define SWAMP_CVAR_NAME "gEnhancements.Minigames.SwampArcheryScore" +#define SWAMP_CVAR CVarGetInteger(SWAMP_CVAR_NAME, 2180) +#define TOWN_CVAR_NAME "gEnhancements.Minigames.TownArcheryScore" +#define TOWN_CVAR CVarGetInteger(TOWN_CVAR_NAME, 50) + +void RegisterArchery() { + COND_ID_HOOK(ShouldActorUpdate, ACTOR_EN_SYATEKI_MAN, SWAMP_CVAR != 2180, [](Actor* actor, bool* should) { + EnSyatekiMan* enSyatekiMan = (EnSyatekiMan*)actor; + + if (enSyatekiMan->actionFunc == EnSyatekiMan_Swamp_RunGame) { + // This checks if their current score plus the amount of bonus points they would get from the timer is + // greater than or equal to the score required to win + if (enSyatekiMan->score != 0 && + (enSyatekiMan->score + (gSaveContext.timerCurTimes[TIMER_ID_MINIGAME_1] / 10)) >= SWAMP_CVAR) { + enSyatekiMan->score = 2120; + enSyatekiMan->currentWave = 4; + enSyatekiMan->wolfosFlags = 0; + enSyatekiMan->bonusDekuScrubHitCounter = 2; + } + } + }); + + COND_VB_SHOULD(VB_ARCHERY_ADD_BONUS_POINTS, SWAMP_CVAR != 2180, { + Actor* actor = va_arg(args, Actor*); + s32* sBonusTimer = va_arg(args, s32*); + + *sBonusTimer = 11; + *should = true; + }); + + COND_ID_HOOK(ShouldActorUpdate, ACTOR_EN_SYATEKI_MAN, TOWN_CVAR != 50, [](Actor* actor, bool* should) { + EnSyatekiMan* enSyatekiMan = (EnSyatekiMan*)actor; + + if (enSyatekiMan->actionFunc == EnSyatekiMan_Town_RunGame) { + if (enSyatekiMan->score >= TOWN_CVAR) { + enSyatekiMan->score = 50; + gSaveContext.timerCurTimes[TIMER_ID_MINIGAME_1] = 0; + } + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterArchery, { SWAMP_CVAR_NAME, TOWN_CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Minigames/HoneyAndDarling.cpp b/mm/2s2h/Enhancements/Minigames/HoneyAndDarling.cpp new file mode 100644 index 0000000000..d90ca1dc42 --- /dev/null +++ b/mm/2s2h/Enhancements/Minigames/HoneyAndDarling.cpp @@ -0,0 +1,26 @@ +#include +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { +#include "overlays/actors/ovl_En_Fu/z_en_fu.h" +} + +#define DAY1_CVAR_NAME "gEnhancements.Minigames.HoneyAndDarlingDay1" +#define DAY1_CVAR CVarGetInteger(DAY1_CVAR_NAME, 8) +#define DAY2_CVAR_NAME "gEnhancements.Minigames.HoneyAndDarlingDay2" +#define DAY2_CVAR CVarGetInteger(DAY2_CVAR_NAME, 8) +#define DAY3_CVAR_NAME "gEnhancements.Minigames.HoneyAndDarlingDay3" +#define DAY3_CVAR CVarGetInteger(DAY3_CVAR_NAME, 16) + +void RegisterHoneyAndDarling() { + COND_VB_SHOULD(VB_HONEY_AND_DARLING_MINIGAME_FINISH, (DAY1_CVAR != 8 || DAY2_CVAR != 8 || DAY3_CVAR != 16), { + EnFu* enFu = va_arg(args, EnFu*); + if ((CURRENT_DAY == 1 && enFu->unk_548 >= DAY1_CVAR) || (CURRENT_DAY == 2 && enFu->unk_548 >= DAY2_CVAR) || + (CURRENT_DAY == 3 && enFu->unk_548 >= DAY3_CVAR)) { + enFu->unk_548 = enFu->unk_54C; + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterHoneyAndDarling, { DAY1_CVAR_NAME, DAY2_CVAR_NAME, DAY3_CVAR_NAME }); diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h index 406dae6d37..ebc325d96a 100644 --- a/mm/2s2h/GameInteractor/GameInteractor.h +++ b/mm/2s2h/GameInteractor/GameInteractor.h @@ -82,6 +82,9 @@ typedef enum { VB_DEKU_GUARD_SHOW_SEARCH_BALLS, VB_DISPLAY_SONG_OF_DOUBLE_TIME_PROMPT, VB_ALLOW_SONG_DOUBLE_TIME_ON_FINAL_NIGHT, + VB_OWL_TELL_ABOUT_SHRINE, + VB_ARCHERY_ADD_BONUS_POINTS, + VB_HONEY_AND_DARLING_MINIGAME_FINISH, VB_GIBDO_TRADE_SEQUENCE_SUFFICIENT_QUANTITY_PRESENTED, VB_GIBDO_TRADE_SEQUENCE_ACCEPT_RED_POTION, VB_GIBDO_TRADE_SEQUENCE_TAKE_MORE_THAN_ONE_ITEM, diff --git a/mm/src/overlays/actors/ovl_En_Fu/z_en_fu.c b/mm/src/overlays/actors/ovl_En_Fu/z_en_fu.c index 2f5c5495d7..d588adea07 100644 --- a/mm/src/overlays/actors/ovl_En_Fu/z_en_fu.c +++ b/mm/src/overlays/actors/ovl_En_Fu/z_en_fu.c @@ -12,6 +12,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS \ (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_2000000 | ACTOR_FLAG_CANT_LOCK_ON) @@ -802,9 +803,12 @@ void func_80962F4C(EnFu* this, PlayState* play) { Message_StartTextbox(play, 0x288B, &this->actor); } - if ((!DynaPolyActor_IsPlayerAbove((DynaPolyActor*)this->actor.child) && - (player->actor.bgCheckFlags & BGCHECKFLAG_GROUND)) || - (gSaveContext.timerCurTimes[TIMER_ID_MINIGAME_2] <= SECONDS_TO_TIMER(0)) || (this->unk_548 == this->unk_54C)) { + if (GameInteractor_Should(VB_HONEY_AND_DARLING_MINIGAME_FINISH, + (!DynaPolyActor_IsPlayerAbove((DynaPolyActor*)this->actor.child) && + (player->actor.bgCheckFlags & BGCHECKFLAG_GROUND)) || + (gSaveContext.timerCurTimes[TIMER_ID_MINIGAME_2] <= SECONDS_TO_TIMER(0)) || + (this->unk_548 == this->unk_54C), + this)) { player->stateFlags3 &= ~PLAYER_STATE3_400000; func_80961E88(play); player->stateFlags1 |= PLAYER_STATE1_20; diff --git a/mm/src/overlays/actors/ovl_En_Owl/z_en_owl.c b/mm/src/overlays/actors/ovl_En_Owl/z_en_owl.c index 3ab43d6d10..6504449521 100644 --- a/mm/src/overlays/actors/ovl_En_Owl/z_en_owl.c +++ b/mm/src/overlays/actors/ovl_En_Owl/z_en_owl.c @@ -5,6 +5,7 @@ */ #include "z_en_owl.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_10) @@ -522,8 +523,10 @@ void func_8095B574(EnOwl* this, PlayState* play) { void func_8095B650(EnOwl* this, PlayState* play) { if (this->actionFlags & 1) { - EnOwl_ChangeMode(this, func_8095B574, func_8095C484, &this->skelAnimePerching, &gOwlPerchAnim, 0.0f); - this->actor.textId = 0xBF5; + if (GameInteractor_Should(VB_OWL_TELL_ABOUT_SHRINE, true, this)) { + EnOwl_ChangeMode(this, func_8095B574, func_8095C484, &this->skelAnimePerching, &gOwlPerchAnim, 0.0f); + this->actor.textId = 0xBF5; + } this->actionFlags &= ~8; } func_8095B480(this, play); diff --git a/mm/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/mm/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c index 57dba44ff9..8c8d1c0270 100644 --- a/mm/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c +++ b/mm/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c @@ -12,6 +12,7 @@ #include "overlays/actors/ovl_En_Syateki_Dekunuts/z_en_syateki_dekunuts.h" #include "overlays/actors/ovl_En_Syateki_Okuta/z_en_syateki_okuta.h" #include "overlays/actors/ovl_En_Syateki_Wf/z_en_syateki_wf.h" +#include "2s2h/GameInteractor/GameInteractor.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_CANT_LOCK_ON) @@ -1192,7 +1193,7 @@ void EnSyatekiMan_Swamp_AddBonusPoints(EnSyatekiMan* this, PlayState* play) { Player* player = GET_PLAYER(play); player->stateFlags1 |= PLAYER_STATE1_20; - if (!play->interfaceCtx.perfectLettersOn) { + if (GameInteractor_Should(VB_ARCHERY_ADD_BONUS_POINTS, !play->interfaceCtx.perfectLettersOn, this, &sBonusTimer)) { if (gSaveContext.timerCurTimes[TIMER_ID_MINIGAME_1] == SECONDS_TO_TIMER(0)) { gSaveContext.timerCurTimes[TIMER_ID_MINIGAME_1] = SECONDS_TO_TIMER(0); gSaveContext.timerStates[TIMER_ID_MINIGAME_1] = TIMER_STATE_STOP;