diff --git a/docs/modding.md b/docs/modding.md index f19609757d..558401791d 100644 --- a/docs/modding.md +++ b/docs/modding.md @@ -484,35 +484,43 @@ Note: for any gamemode wishing to use the vanilla set of savefiles, use `gczelda ```cpp IMPORT_SERVICE(GamemodeService, svc_gamemode); -void onSaveLoaded() { - // This function will be invoked by the game as a save is loaded -} - +#define MY_GAMEMODE_ID "gamemodeid" #define ONLY_GAMEMODE(ctx, id) \ { \ bool isGamemodeActive; \ svc_gamemode->is_active(ctx, id, &isGamemodeActive); \ if (!isGamemodeActive) { \ - return; \ + return HOOK_CONTINUE; \ } \ } +#define ONLY_GAMEMODE_MYGAMEMODE ONLY_GAMEMODE(ctx, MY_GAMEMODE_ID) static HookAction myFunctionHook(ModContext *ctx, void *args, void *, void *) { // Note: normal function hooks will need to check if the gamemode is active - ONLY_GAMEMODE(ctx,"id"); // A macro like this can make it easy + ONLY_GAMEMODE_MYGAMEMODE // A macro like this can make it easy + + // Code that runs when only the Gamemode is active + + return HOOK_CONTINUE; +} + +void onSaveLoaded() { + // This function will be invoked by the game as a save is loaded } const GamemodeDesc gamemodeDesc = { - .gamemodeId = "my-unique-gamemode-id", + .gamemodeId = MY_GAMEMODE_ID, .fullName = "Gamemode Name", - .saveName = "my-unique-save-name", - .onActivatedFunction = nullptr, - .onDeactivatedFunction = nullptr, - .onPlayFunction = nullptr, - .onSaveLoadedFunction = onSaveLoaded, - .onNewSaveFunction = nullptr, - .onGameResetFunction = nullptr, - .onTickFunction = nullptr, + // The save name should be something that other gamemodes will not try to use, so appending your name to it + // is reccomended + .saveName = "my-unique-save-name_developer-name", + .onActivatedFunction = nullptr, // Called when the gamemode is selected on the prelaunch menu (or is launched) + .onDeactivatedFunction = nullptr, // Called when the gamemode is deselected on the prelaunch menu (or the mod is disabled) + .onPlayFunction = nullptr, // Called when "Play" is pressed on the prelaunch menu + .onSaveLoadedFunction = onSaveLoaded, // Called when a save is loaded + .onNewSaveFunction = nullptr, // Called after a new savefile is created + .onGameResetFunction = nullptr, // Called when the game is reset + .onTickFunction = nullptr, // Called every game tick while the gamemode is active }; svc_gamemode->register_gamemode(mod_ctx, &gamemodeDesc); ``` diff --git a/src/dusk/mods/svc/gamemode.cpp b/src/dusk/mods/svc/gamemode.cpp index bab07b05c2..d7e6df035b 100644 --- a/src/dusk/mods/svc/gamemode.cpp +++ b/src/dusk/mods/svc/gamemode.cpp @@ -20,7 +20,12 @@ aurora::Module Log("dusk::mods::gamemode"); std::unordered_map> s_gamemodesRegisteredToMods; std::string get_mod_gamemode_id(ModContext* ctx, const std::string& id) { - return id + "_" + ctx->mod->metadata.id; + // Standardize the IDs to include the mod id (to prevent clashes) and set them as lowercase + std::string fullId = id + "_" + ctx->mod->metadata.id; + std::transform(fullId.begin(),fullId.end(),fullId.begin(),[](unsigned char c) { + return std::towlower(c); + }); + return fullId; } void gamemode_remove_mod(LoadedMod& mod) { diff --git a/src/m_Do/m_Do_Reset.cpp b/src/m_Do/m_Do_Reset.cpp index b3ba72d078..db5ffdf735 100644 --- a/src/m_Do/m_Do_Reset.cpp +++ b/src/m_Do/m_Do_Reset.cpp @@ -22,6 +22,7 @@ #ifdef TARGET_PC #include "dusk/ui/prelaunch.hpp" #include "dusk/ui/menu_bar.hpp" +#include "dusk/ui/mods_window.hpp" #include "dusk/gamemode.hpp" #endif @@ -167,6 +168,10 @@ void mDoRst_resetCallBack(int port, void*) { // Hide the menu bar menubar->Document::hide(true); } + if (auto* modwindow = dynamic_cast(doc.get())) { + // Hide the mod window (if we were disasbling or reloading a mod) + modwindow->pop(); + } if (auto* prelaunch = dynamic_cast(doc.get())) { prelaunchExists = true; prelaunch->focus();