From d0d7e684c2793cb257037802a04e1d7b2249e620 Mon Sep 17 00:00:00 2001 From: inspectredc Date: Fri, 6 Oct 2023 23:38:16 +0100 Subject: [PATCH 1/2] game interactor example stuff --- CMakeLists.txt | 4 ++ src/game/level_update.c | 5 ++ src/game/mario.c | 7 +++ src/port/Engine.cpp | 5 ++ .../game-interactor/GameInteractor.cpp | 12 +++++ .../game-interactor/GameInteractor.h | 50 +++++++++++++++++++ .../game-interactor/GameInteractor_Hooks.cpp | 12 +++++ .../game-interactor/GameInteractor_Hooks.h | 13 +++++ src/port/Enhancements/mods.cpp | 34 +++++++++++++ src/port/Enhancements/mods.h | 9 ++++ src/port/ui/ImguiUI.cpp | 13 +++++ 11 files changed, 164 insertions(+) create mode 100644 src/port/Enhancements/game-interactor/GameInteractor.cpp create mode 100644 src/port/Enhancements/game-interactor/GameInteractor.h create mode 100644 src/port/Enhancements/game-interactor/GameInteractor_Hooks.cpp create mode 100644 src/port/Enhancements/game-interactor/GameInteractor_Hooks.h create mode 100644 src/port/Enhancements/mods.cpp create mode 100644 src/port/Enhancements/mods.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f6593655..a9210ef0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,10 @@ file(GLOB_RECURSE ALL_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/port/*.h" "src/port/*.c" "src/port/*.cpp" + "src/port/Enhancements/*.h" + "src/port/Enhancements/*.cpp" + "src/port/Enhancements/game-interactor/*.h" + "src/port/Enhancements/game-interactor/*.cpp" "src/port/importer/*.cpp" "src/port/importer/types/*.cpp" "text/*.c" diff --git a/src/game/level_update.c b/src/game/level_update.c index 034a3131..47200701 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -29,6 +29,8 @@ #include "course_table.h" #include "rumble_init.h" +#include "port/Enhancements/game-interactor/GameInteractor_Hooks.h" + #define PLAY_MODE_NORMAL 0 #define PLAY_MODE_PAUSED 2 #define PLAY_MODE_CHANGE_AREA 3 @@ -1153,6 +1155,9 @@ s32 update_level(void) { enable_background_sound(); } + // Updates only when in game, i.e. past the save select screen + GameInteractor_ExecuteOnGameFrameUpdate(); + return changeLevel; } diff --git a/src/game/mario.c b/src/game/mario.c index 7334741e..8224f5e0 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -35,6 +35,8 @@ #include "rumble_init.h" #include "animation_table.h" +#include "port/Enhancements/game-interactor/GameInteractor_Hooks.h" + u32 unused80339F10; u8 unused80339F1C[20]; @@ -1455,6 +1457,7 @@ void update_mario_health(struct MarioState *m) { if ((m->input & INPUT_IN_POISON_GAS) && !(m->action & ACT_FLAG_INTANGIBLE)) { if (!(m->flags & MARIO_METAL_CAP) && !gDebugLevelSelect) { m->health -= 4; + GameInteractor_ExecuteOnHealthChange(m->health); } } else { if ((m->action & ACT_FLAG_SWIMMING) && !(m->action & ACT_FLAG_INTANGIBLE)) { @@ -1465,8 +1468,10 @@ void update_mario_health(struct MarioState *m) { // If using the debug level select, do not lose any HP to water. if ((m->pos[1] >= (m->waterLevel - 140)) && !terrainIsSnow) { m->health += 0x1A; + GameInteractor_ExecuteOnHealthChange(m->health); } else if (!gDebugLevelSelect) { m->health -= (terrainIsSnow ? 3 : 1); + GameInteractor_ExecuteOnHealthChange(m->health); } } } @@ -1475,10 +1480,12 @@ void update_mario_health(struct MarioState *m) { if (m->healCounter > 0) { m->health += 0x40; m->healCounter--; + GameInteractor_ExecuteOnHealthChange(m->health); } if (m->hurtCounter > 0) { m->health -= 0x40; m->hurtCounter--; + GameInteractor_ExecuteOnHealthChange(m->health); } if (m->health > 0x880) { diff --git a/src/port/Engine.cpp b/src/port/Engine.cpp index 45e364a5..d7700d87 100644 --- a/src/port/Engine.cpp +++ b/src/port/Engine.cpp @@ -11,6 +11,8 @@ #include "texts_table.h" #include "port/importer/DialogFactory.h" #include "port/importer/DictionaryFactory.h" +#include "port/Enhancements/game-interactor/GameInteractor.h" +#include "port/Enhancements/mods.h" #include #include @@ -23,6 +25,7 @@ extern "C" { } GameEngine* GameEngine::Instance; +GameInteractor* GameInteractor::Instance; GameEngine::GameEngine(){ std::vector OTRFiles; @@ -58,6 +61,8 @@ GameEngine::GameEngine(){ void GameEngine::Create(){ GameEngine::Instance = new GameEngine(); + GameInteractor::Instance = new GameInteractor(); + InitMods(); GameUI::SetupGuiElements(); } diff --git a/src/port/Enhancements/game-interactor/GameInteractor.cpp b/src/port/Enhancements/game-interactor/GameInteractor.cpp new file mode 100644 index 00000000..92a24a69 --- /dev/null +++ b/src/port/Enhancements/game-interactor/GameInteractor.cpp @@ -0,0 +1,12 @@ +#include "GameInteractor.h" + +bool GameInteractor::IsSaveLoaded() { + // todo + return false; +} + + +bool GameInteractor::IsGameplayPaused() { + // todo + return false; +} diff --git a/src/port/Enhancements/game-interactor/GameInteractor.h b/src/port/Enhancements/game-interactor/GameInteractor.h new file mode 100644 index 00000000..72e7da14 --- /dev/null +++ b/src/port/Enhancements/game-interactor/GameInteractor.h @@ -0,0 +1,50 @@ +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus + +#include +#include + +#define DEFINE_HOOK(name, type) \ + struct name { \ + typedef std::function fn; \ + } + +class GameInteractor { +public: + static GameInteractor* Instance; + + // Game State + class State { + + }; + + // Game Hooks + template struct RegisteredGameHooks { inline static std::vector functions; }; + template void RegisterGameHook(typename H::fn h) { RegisteredGameHooks::functions.push_back(h); } + template void ExecuteHooks(Args&&... args) { + for (auto& fn : RegisteredGameHooks::functions) { + fn(std::forward(args)...); + } + } + + DEFINE_HOOK(OnGameFrameUpdate, void()); + DEFINE_HOOK(OnHealthChange, void(int16_t health)); + + // Helpers + static bool IsSaveLoaded(); + static bool IsGameplayPaused(); + + class RawAction { + + }; + +}; + +#endif // __cplusplus diff --git a/src/port/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/src/port/Enhancements/game-interactor/GameInteractor_Hooks.cpp new file mode 100644 index 00000000..285330c0 --- /dev/null +++ b/src/port/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -0,0 +1,12 @@ +#include "GameInteractor_Hooks.h" + +// Gameplay + +// Updates only when in game, i.e. past the save select screen +void GameInteractor_ExecuteOnGameFrameUpdate() { + GameInteractor::Instance->ExecuteHooks(); +} + +void GameInteractor_ExecuteOnHealthChange(int16_t health) { + GameInteractor::Instance->ExecuteHooks(health); +} diff --git a/src/port/Enhancements/game-interactor/GameInteractor_Hooks.h b/src/port/Enhancements/game-interactor/GameInteractor_Hooks.h new file mode 100644 index 00000000..997ad1f4 --- /dev/null +++ b/src/port/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -0,0 +1,13 @@ +#include "GameInteractor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Gameplay +void GameInteractor_ExecuteOnGameFrameUpdate(); +void GameInteractor_ExecuteOnHealthChange(int16_t health); + +#ifdef __cplusplus +} +#endif diff --git a/src/port/Enhancements/mods.cpp b/src/port/Enhancements/mods.cpp new file mode 100644 index 00000000..0da46ce9 --- /dev/null +++ b/src/port/Enhancements/mods.cpp @@ -0,0 +1,34 @@ +#include "mods.h" +#include +#include "game-interactor/GameInteractor.h" + +#include "game/level_update.h" +extern MarioState* gMarioState; + +#define MARIO_HEALTH_MAX 0x880 + +void RegisterInfiniteHealth() { + GameInteractor::Instance->RegisterGameHook([](int16_t health) { + if (!gMarioState) return; + + if (CVarGetInteger("gInfiniteHealth", 0) != 0) { + gMarioState->health = MARIO_HEALTH_MAX; + } + }); +} + +void RegisterInfiniteLives() { + // There may be a better hook that can be made, rather than doing this every frame + GameInteractor::Instance->RegisterGameHook([]() { + if (!gMarioState) return; + + if (CVarGetInteger("gInfiniteLives", 0) != 0) { + gMarioState->numLives = 100; + } + }); +} + +void InitMods() { + RegisterInfiniteHealth(); + RegisterInfiniteLives(); +} diff --git a/src/port/Enhancements/mods.h b/src/port/Enhancements/mods.h new file mode 100644 index 00000000..f56e68e7 --- /dev/null +++ b/src/port/Enhancements/mods.h @@ -0,0 +1,9 @@ +#ifdef __cplusplus +extern "C" { +#endif + +void InitMods(); + +#ifdef __cplusplus +} +#endif diff --git a/src/port/ui/ImguiUI.cpp b/src/port/ui/ImguiUI.cpp index d2c58248..0f666a6e 100644 --- a/src/port/ui/ImguiUI.cpp +++ b/src/port/ui/ImguiUI.cpp @@ -303,6 +303,15 @@ void DrawEnhancementsMenu() { } } +void DrawCheatsMenu() { + if (ImGui::BeginMenu("Cheats")) { + UIWidgets::PaddedEnhancementCheckbox("Infinite Health", "gInfiniteHealth", true, false); + UIWidgets::PaddedEnhancementCheckbox("Infinite Lives", "gInfiniteLives", true, false); + + ImGui::EndMenu(); + } +} + void GameMenuBar::DrawElement() { if(ImGui::BeginMenuBar()){ DrawMenuBarIcon(); @@ -321,6 +330,10 @@ void GameMenuBar::DrawElement() { DrawEnhancementsMenu(); + ImGui::SetCursorPosY(0.0f); + + DrawCheatsMenu(); + ImGui::PopStyleVar(1); ImGui::EndMenuBar(); } From b731571a92425cbc2ca1b2f1e1597e755e55e74f Mon Sep 17 00:00:00 2001 From: inspectredc Date: Sat, 7 Oct 2023 00:39:43 +0100 Subject: [PATCH 2/2] pause state helper example --- .../game-interactor/GameInteractor.cpp | 16 ++++++++++------ .../game-interactor/GameInteractor.h | 7 ++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/port/Enhancements/game-interactor/GameInteractor.cpp b/src/port/Enhancements/game-interactor/GameInteractor.cpp index 92a24a69..93854f3b 100644 --- a/src/port/Enhancements/game-interactor/GameInteractor.cpp +++ b/src/port/Enhancements/game-interactor/GameInteractor.cpp @@ -1,12 +1,16 @@ #include "GameInteractor.h" -bool GameInteractor::IsSaveLoaded() { - // todo - return false; -} +#include "game/level_update.h" +extern int16_t sCurrPlayMode; + +// Taken from game/level_update.c +#define PLAY_MODE_NORMAL 0 +#define PLAY_MODE_PAUSED 2 +#define PLAY_MODE_CHANGE_AREA 3 +#define PLAY_MODE_CHANGE_LEVEL 4 +#define PLAY_MODE_FRAME_ADVANCE 5 bool GameInteractor::IsGameplayPaused() { - // todo - return false; + return sCurrPlayMode == PLAY_MODE_PAUSED; } diff --git a/src/port/Enhancements/game-interactor/GameInteractor.h b/src/port/Enhancements/game-interactor/GameInteractor.h index 72e7da14..0124557a 100644 --- a/src/port/Enhancements/game-interactor/GameInteractor.h +++ b/src/port/Enhancements/game-interactor/GameInteractor.h @@ -1,3 +1,6 @@ +#ifndef GameInteractor_h +#define GameInteractor_h + #ifdef __cplusplus extern "C" { #endif @@ -38,9 +41,9 @@ public: DEFINE_HOOK(OnHealthChange, void(int16_t health)); // Helpers - static bool IsSaveLoaded(); static bool IsGameplayPaused(); + // Game Actions class RawAction { }; @@ -48,3 +51,5 @@ public: }; #endif // __cplusplus + +#endif // GameInteractor_h