[Cheat] Stop time in Temples and Dungeons (#700)

* add cheat to stop time in temples

* better tooltip

* adds option to stop time in dungeons

* clean up

* add other pirate fortress scenes

* add new hook

* update tooltips

* rename hook

* add clarification

Co-authored-by: Archez <Archez@users.noreply.github.com>

* clean combobox

---------

Co-authored-by: Archez <Archez@users.noreply.github.com>
This commit is contained in:
balloondude2 2024-08-05 13:12:08 -06:00 committed by GitHub
parent 51af06463f
commit d0caa0f78c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 106 additions and 0 deletions

View File

@ -57,6 +57,12 @@ static const std::unordered_map<int32_t, const char*> alwaysWinDoggyraceOptions
{ ALWAYS_WIN_DOGGY_RACE_ALWAYS, "Always" },
};
static const std::unordered_map<int32_t, const char*> timeStopOptions = {
{ TIME_STOP_OFF, "Off" },
{ TIME_STOP_TEMPLES, "Temples" },
{ TIME_STOP_TEMPLES_DUNGEONS, "Temples + Mini Dungeons" },
};
namespace BenGui {
std::shared_ptr<std::vector<Ship::WindowBackend>> availableWindowBackends;
std::unordered_map<Ship::WindowBackend, const char*> availableWindowBackendsMap;
@ -678,6 +684,14 @@ void DrawCheatsMenu() {
{ .tooltip = "Holding L makes you float into the air" })) {
RegisterMoonJumpOnL();
}
UIWidgets::CVarCombobox(
"Stop Time in Dungeons", "gCheats.TempleTimeStop", timeStopOptions,
{ .tooltip = "Stops time from advancing in selected areas. Requires a room change to update.\n\n"
"- Off: Vanilla behaviour.\n"
"- Temples: Stops time in Woodfall, Snowhead, Great Bay, and Stone Tower Temples.\n"
"- Temples + Mini Dungeons: In addition to the above temples, stops time in both Spider "
"Houses, Pirate's Fortress, Beneath the Well, Ancient Castle of Ikana, and Secret Shrine.",
.defaultIndex = TIME_STOP_OFF });
ImGui::EndMenu();
}

View File

@ -0,0 +1,65 @@
#include <libultraship/libultraship.h>
#include "BenPort.h"
#include "Enhancements/GameInteractor/GameInteractor.h"
#include "Enhancements/Enhancements.h"
extern "C" {
#include <variables.h>
#include <functions.h>
}
void RegisterTimeStopInTemples() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::AfterRoomSceneCommands>([](s16 sceneId, s8 roomNum) {
uint8_t selectedOption = CVarGetInteger("gCheats.TempleTimeStop", TIME_STOP_OFF);
switch (selectedOption) {
case TIME_STOP_TEMPLES_DUNGEONS:
switch (gPlayState->sceneId) {
// Swamp + Ocean Spider House
case SCENE_KINSTA1:
case SCENE_KINDAN2:
// Pirates' Fortress
case SCENE_KAIZOKU:
case SCENE_PIRATE:
case SCENE_TORIDE:
// Beneath the Well
case SCENE_REDEAD:
// Ancient Castle of Ikana + Igos's Lair
case SCENE_CASTLE:
case SCENE_IKNINSIDE:
// Secret Shrine
case SCENE_RANDOM:
R_TIME_SPEED = 0;
break;
default:
break;
}
// fallthrough
case TIME_STOP_TEMPLES:
switch (gPlayState->sceneId) {
// Woodfall Temple + Odolwa
case SCENE_MITURIN:
case SCENE_MITURIN_BS:
// Snowhead Temple + Goht
case SCENE_HAKUGIN:
case SCENE_HAKUGIN_BS:
// Great Bay Temple + Gyorg
case SCENE_SEA:
case SCENE_SEA_BS:
// Stone Tower Temple (+ inverted) + Twinmold
case SCENE_INISIE_N:
case SCENE_INISIE_R:
case SCENE_INISIE_BS:
R_TIME_SPEED = 0;
break;
default:
break;
}
break;
case TIME_STOP_OFF:
break;
default:
break;
}
});
}

View File

@ -0,0 +1,6 @@
#ifndef CHEATS_TIME_STOPS_H
#define CHEATS_TIME_STOPS_H
void RegisterTimeStopInTemples();
#endif // CHEATS_TIME_STOPS_H

View File

@ -12,6 +12,7 @@ void InitEnhancements() {
RegisterMoonJumpOnL();
RegisterUnbreakableRazorSword();
RegisterUnrestrictedItems();
RegisterTimeStopInTemples();
// Clock
RegisterTextBasedClock();

View File

@ -11,6 +11,7 @@
#include "Cheats/Cheats.h"
#include "Cheats/UnbreakableRazorSword.h"
#include "Cheats/UnrestrictedItems.h"
#include "Cheats/TimeStop.h"
#include "Cycle/EndOfCycle.h"
#include "Equipment/SkipMagicArrowEquip.h"
#include "Masks/BlastMaskKeg.h"
@ -37,6 +38,12 @@ enum AlwaysWinDoggyRaceOptions {
ALWAYS_WIN_DOGGY_RACE_ALWAYS,
};
enum TimeStopOptions {
TIME_STOP_OFF,
TIME_STOP_TEMPLES,
TIME_STOP_TEMPLES_DUNGEONS,
};
enum ClockTypeOptions {
CLOCK_TYPE_ORIGINAL,
CLOCK_TYPE_TEXT_BASED,

View File

@ -57,6 +57,13 @@ void GameInteractor_ExecuteOnRoomInit(s16 sceneId, s8 roomNum) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnRoomInit>(sceneId, roomNum);
}
void GameInteractor_ExecuteAfterRoomSceneCommands(s16 sceneId, s8 roomNum) {
SPDLOG_DEBUG("AfterRoomSceneCommands: sceneId: {}, roomNum: {}", sceneId, roomNum);
GameInteractor::Instance->ExecuteHooks<GameInteractor::AfterRoomSceneCommands>(sceneId, roomNum);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::AfterRoomSceneCommands>(sceneId, sceneId, roomNum);
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::AfterRoomSceneCommands>(sceneId, roomNum);
}
void GameInteractor_ExecuteOnPlayDestroy() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayDestroy>();
}

View File

@ -267,6 +267,7 @@ class GameInteractor {
DEFINE_HOOK(OnSceneInit, (s8 sceneId, s8 spawnNum));
DEFINE_HOOK(OnRoomInit, (s8 sceneId, s8 roomNum));
DEFINE_HOOK(AfterRoomSceneCommands, (s8 sceneId, s8 roomNum));
DEFINE_HOOK(OnPlayDestroy, ());
DEFINE_HOOK(ShouldActorInit, (Actor * actor, bool* should));
@ -311,6 +312,7 @@ void GameInteractor_ExecuteBeforeMoonCrashSaveReset();
void GameInteractor_ExecuteOnSceneInit(s16 sceneId, s8 spawnNum);
void GameInteractor_ExecuteOnRoomInit(s16 sceneId, s8 roomNum);
void GameInteractor_ExecuteAfterRoomSceneCommands(s16 sceneId, s8 roomNum);
void GameInteractor_ExecuteOnPlayDestroy();
bool GameInteractor_ShouldActorInit(Actor* actor);

View File

@ -3,6 +3,8 @@
#include "2s2h/resource/type/Scene.h"
#include <utils/StringHelper.h>
#include <Vertex.h>
#include "2s2h/Enhancements/GameInteractor/GameInteractor.h"
extern "C" {
#include "global.h"
extern uintptr_t gSegments[NUM_SEGMENTS];
@ -71,6 +73,8 @@ extern "C" s32 OTRfunc_800973FC(PlayState* play, RoomContext* roomCtx) {
if (Environment_GetStormState(play) == STORM_STATE_OFF) {
Environment_StopStormNatureAmbience(play);
}
// Insert hook
GameInteractor_ExecuteAfterRoomSceneCommands(play->sceneId, roomCtx->curRoom.num);
return 1;
}