mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-20 05:16:24 -04:00
Gamemode service improvements. Disable achievements on custom gamemodes (for now)
This commit is contained in:
+34
-42
@@ -699,7 +699,7 @@ const GamemodeDesc gamemodeDesc = {
|
||||
.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
|
||||
.onNewSaveSelectFunction = nullptr, // Called while the flow before the file name select is ran (see below)
|
||||
.onNewSaveSelectFunction = nullptr, // Called during the flow before the file name select is ran (see below)
|
||||
.onGameResetFunction = nullptr, // Called when the game is reset
|
||||
.onTickFunction = nullptr, // Called every game tick while the gamemode is active
|
||||
};
|
||||
@@ -710,55 +710,47 @@ Within the gamemode service, a gamemode can also request to load a UI for per-sa
|
||||
create a new file is pressed.
|
||||
|
||||
```cpp
|
||||
#include "d/d_file_select.h" // Requires game feature
|
||||
IMPORT_SERVICE(GamemodeService, svc_gamemode);
|
||||
IMPORT_SERVICE(UiService, svc_ui);
|
||||
|
||||
bool proceedUI = false;
|
||||
UiWindowHandle windowHandle;
|
||||
void onNewSaveSelect(bool *out_proceedToNameSelect, bool *out_returnToFileSelect) {
|
||||
static bool *proceedToNameSelect;
|
||||
static bool *returnToFileSelect;
|
||||
static UiWindowHandle windowHandle;
|
||||
|
||||
bool onNewSaveSelect(dFile_select_c *fileSelect) {
|
||||
if (fileSelect->mGamemodeSaveStartBuildUi) {
|
||||
proceedUI = false;
|
||||
UiTabDesc tabs[1]{};
|
||||
// Used within callbacks as needed
|
||||
proceedToNameSelect = out_proceedToNameSelect;
|
||||
returnToFileSelect = out_returnToFileSelect;
|
||||
|
||||
tabs[0].struct_size = sizeof(UiTabDesc);
|
||||
tabs[0].title = "Play";
|
||||
tabs[0].build = [](ModContext* ctx, UiWindowHandle, UiElementHandle leftPane, UiElementHandle rightPane, void*, ModError*) {
|
||||
UiControlDesc desc = UI_CONTROL_DESC_INIT;
|
||||
desc.kind = UI_CONTROL_BUTTON;
|
||||
desc.label = "Play";
|
||||
desc.help_rml = "Play Button";
|
||||
desc.on_pressed = [](ModContext* ctx, void* userdata) {
|
||||
proceedUI = true;
|
||||
svc_ui->window_close(ctx, *static_cast<UiWindowHandle*>(userdata));
|
||||
};
|
||||
desc.user_data = &windowHandle;
|
||||
svc_ui->pane_add_control(mod_ctx, leftPane, &desc, nullptr);
|
||||
return MOD_OK;
|
||||
UiTabDesc tabs[1]{};
|
||||
|
||||
tabs[0].struct_size = sizeof(UiTabDesc);
|
||||
tabs[0].title = "Play";
|
||||
tabs[0].build = [](ModContext* ctx, UiWindowHandle, UiElementHandle leftPane, UiElementHandle rightPane, void*, ModError*) {
|
||||
UiControlDesc desc = UI_CONTROL_DESC_INIT;
|
||||
desc.kind = UI_CONTROL_BUTTON;
|
||||
desc.label = "Play";
|
||||
desc.help_rml = "Play Button";
|
||||
desc.on_pressed = [](ModContext* ctx, void* userdata) {
|
||||
*proceedToNameSelect = true;
|
||||
svc_ui->window_close(ctx, *static_cast<UiWindowHandle*>(userdata));
|
||||
};
|
||||
desc.user_data = &windowHandle;
|
||||
svc_ui->pane_add_control(mod_ctx, leftPane, &desc, nullptr);
|
||||
return MOD_OK;
|
||||
};
|
||||
|
||||
UiWindowDesc desc = UI_WINDOW_DESC_INIT;
|
||||
desc.tabs = tabs;
|
||||
desc.tab_count = 1;
|
||||
desc.user_data = fileSelect;
|
||||
desc.on_closed = [](ModContext *, UiWindowHandle, void *userdata) {
|
||||
dFile_select_c *i_this = static_cast<dFile_select_c *>(userdata);
|
||||
UiWindowDesc desc = UI_WINDOW_DESC_INIT;
|
||||
desc.tabs = tabs;
|
||||
desc.tab_count = 1;
|
||||
desc.on_closed = [](ModContext *, UiWindowHandle, void *userdata) {
|
||||
// If closing the window through backing out, return to file select
|
||||
if (*proceedToNameSelect == false) {
|
||||
*returnToFileSelect = true;
|
||||
}
|
||||
};
|
||||
|
||||
// if closing the window through backing out, return to file select
|
||||
if (!proceedUI) {
|
||||
i_this->backToDataSelectMove();
|
||||
}
|
||||
};
|
||||
|
||||
svc_ui->window_push(mod_ctx, &desc, &windowHandle);
|
||||
}
|
||||
|
||||
// When we hit play in the UI, return true (tells the file select that we can proceed)
|
||||
if (proceedUI) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
svc_ui->window_push(mod_ctx, &desc, &windowHandle);
|
||||
}
|
||||
|
||||
const GamemodeDesc gamemodeDesc = {
|
||||
|
||||
@@ -426,7 +426,6 @@ public:
|
||||
nameMoveAnmInitSet(0xd29, 0xd1f);
|
||||
modoruTxtDispAnmInit(0);
|
||||
mDataSelProc = DATASELPROC_NAME_TO_DATA_SELECT_MOVE;
|
||||
mGamemodeSaveStartBuildUi = true;
|
||||
}
|
||||
#endif
|
||||
void _draw();
|
||||
@@ -742,6 +741,8 @@ public:
|
||||
#ifdef TARGET_PC
|
||||
dDlst_FileSelFade_c mFadeDlst;
|
||||
bool mGamemodeSaveStartBuildUi = true;
|
||||
bool mGamemodeProceedToNameSelect = false;
|
||||
bool mGamemodeReturnToFileSelect = false;
|
||||
#endif
|
||||
|
||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||
|
||||
@@ -10,15 +10,17 @@
|
||||
typedef struct {
|
||||
const char* gamemodeId;
|
||||
const char* fullName;
|
||||
const char saveName[32]; // GCI Filenames are limited to 31 characters
|
||||
void (*onActivatedFunction)();
|
||||
void (*onDeactivatedFunction)();
|
||||
void (*onPlayFunction)();
|
||||
void (*onSaveLoadedFunction)();
|
||||
void (*onNewSaveFunction)();
|
||||
bool (*onNewSaveSelectFunction)(struct dFile_select_c* fileSelect); // Should return true when any custom options flows are finished
|
||||
void (*onGameResetFunction)();
|
||||
void (*onTickFunction)();
|
||||
const char saveName[32]; // Should be unique. GCI Filenames are limited to 31 characters
|
||||
void (*onActivatedFunction)(); // Called when the gamemode is selected
|
||||
void (*onDeactivatedFunction)(); // Called when the gamemode is deselected
|
||||
void (*onPlayFunction)(); // Called when play is pressed on the prelaunch menu
|
||||
void (*onSaveLoadedFunction)(); // Called whenever a savefile is loaded
|
||||
void (*onNewSaveFunction)(); // Called when a new save is created
|
||||
void (*onNewSaveSelectFunction)(bool* out_proceedToNameSelect,
|
||||
bool* out_returnToFileSelect); // Set out_proceedToNameSelect to true once any UI flows are
|
||||
// completed
|
||||
void (*onGameResetFunction)(); // Called when the game is reset
|
||||
void (*onTickFunction)(); // Called on every tick
|
||||
} GamemodeDesc;
|
||||
|
||||
typedef struct GamemodeService {
|
||||
|
||||
+15
-4
@@ -1318,18 +1318,24 @@ void dFile_select_c::selectDataNameMove() {
|
||||
const dusk::gamemode::Gamemode* gamemode = dusk::gamemode::getGamemodeManager().getCurrentGamemode();
|
||||
if (gamemode) {
|
||||
if (isHeaderTxtChange == true && isFileRecScale == true && isModoruTxtDisp == true) {
|
||||
bool gamemodeFlowClosed = gamemode->invokeOnNewSaveSelectFunction(this);
|
||||
if (mGamemodeSaveStartBuildUi == true) {
|
||||
if (mGamemodeSaveStartBuildUi) {
|
||||
gamemode->invokeOnNewSaveSelectFunction(&mGamemodeProceedToNameSelect, &mGamemodeReturnToFileSelect);
|
||||
mGamemodeSaveStartBuildUi = false;
|
||||
}
|
||||
if (!gamemodeFlowClosed) {
|
||||
if (mGamemodeReturnToFileSelect) {
|
||||
backToDataSelectMove();
|
||||
mGamemodeSaveStartBuildUi = true;
|
||||
mGamemodeProceedToNameSelect = false;
|
||||
mGamemodeReturnToFileSelect = false;
|
||||
return;
|
||||
}
|
||||
if (!mGamemodeProceedToNameSelect) {
|
||||
return;
|
||||
}
|
||||
}else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mGamemodeSaveStartBuildUi = true;
|
||||
#endif
|
||||
|
||||
IF_DUSK(bool isNameMove = nameMoveAnm();)
|
||||
@@ -1337,6 +1343,11 @@ void dFile_select_c::selectDataNameMove() {
|
||||
if (isHeaderTxtChange == true && isFileRecScale == true && isNameMove == true &&
|
||||
isModoruTxtDisp == true)
|
||||
{
|
||||
#ifdef TARGET_PC
|
||||
mGamemodeSaveStartBuildUi = true;
|
||||
mGamemodeProceedToNameSelect = false;
|
||||
mGamemodeReturnToFileSelect = false;
|
||||
#endif
|
||||
mDataSelProc = DATASELPROC_NAME_INPUT_WAIT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "f_op/f_op_actor_mng.h"
|
||||
#include "f_pc/f_pc_name.h"
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/gamemode.hpp"
|
||||
#include "dusk/speedrun.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
@@ -1302,6 +1304,12 @@ void AchievementSystem::processEntry(Entry& e) {
|
||||
}
|
||||
|
||||
void AchievementSystem::tick() {
|
||||
// Until we implement an AchievementService, achievements will be unavailible in custom gamemodes
|
||||
if (dusk::gamemode::getGamemodeManager().isCurrentGamemode(dusk::gamemode::kVanillaGamemodeId) == false
|
||||
&& dusk::gamemode::getGamemodeManager().isCurrentGamemode(dusk::speedrun::kSpeedrunGamemodeId) == false) {
|
||||
m_signals.clear();
|
||||
return;
|
||||
}
|
||||
if (!m_loaded) {
|
||||
load();
|
||||
}
|
||||
|
||||
@@ -12,16 +12,15 @@ GamemodeManager g_GamemodeManager;
|
||||
aurora::Module DuskGamemodeLog("dusk::gamemode");
|
||||
|
||||
GamemodeManager::GamemodeManager() {
|
||||
registerGamemode(Gamemode("vanilla","Vanilla","gczelda2"));
|
||||
|
||||
mCurrentGamemodeId = "vanilla";
|
||||
registerGamemode(Gamemode(kVanillaGamemodeId,"Vanilla","gczelda2"));
|
||||
mCurrentGamemodeId = kVanillaGamemodeId;
|
||||
}
|
||||
|
||||
void GamemodeManager::setGamemodeToPrevious() {
|
||||
// Gets the value from the settings of the last played gamemode id and sets that to the current gamemode (if registered)
|
||||
GamemodeId id = dusk::getSettings().game.lastSelectedGamemodeId;
|
||||
if (mRegisteredGamemodes.find(id) == mRegisteredGamemodes.end()) {
|
||||
setCurrentGamemode("vanilla");
|
||||
setCurrentGamemode(kVanillaGamemodeId);
|
||||
return;
|
||||
}
|
||||
setCurrentGamemode(id);
|
||||
@@ -60,7 +59,7 @@ void GamemodeManager::unregisterGamemode(const GamemodeId& gamemodeId) {
|
||||
// to reset the game back to title as vanilla;
|
||||
ui::prelaunch_state().showPrelaunchOnReset = true;
|
||||
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
|
||||
setCurrentGamemode("vanilla");
|
||||
setCurrentGamemode(kVanillaGamemodeId);
|
||||
}
|
||||
mRegisteredGamemodes.erase(it);
|
||||
dusk::ui::Prelaunch::rebuild_menu_buttons();
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
namespace dusk::gamemode {
|
||||
using GamemodeId = std::string;
|
||||
|
||||
constexpr const char* kVanillaGamemodeId = "vanilla";
|
||||
|
||||
// This class holds the definition for the gamemode and various function pointers to call
|
||||
class Gamemode {
|
||||
public:
|
||||
@@ -52,11 +54,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool invokeOnNewSaveSelectFunction(dFile_select_c* fileSelect) const {
|
||||
void invokeOnNewSaveSelectFunction(bool* out_proceedToNameSelect, bool* out_returnToFileSelect) const {
|
||||
if (mOnNewSaveSelectFunction) {
|
||||
return mOnNewSaveSelectFunction(fileSelect);
|
||||
mOnNewSaveSelectFunction(out_proceedToNameSelect, out_returnToFileSelect);
|
||||
}else {
|
||||
*out_proceedToNameSelect = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void invokeOnGameResetFunction() const {
|
||||
@@ -76,7 +79,7 @@ public:
|
||||
std::function<void()> mOnPlayFunction;
|
||||
std::function<void()> mOnSaveLoadedFunction;
|
||||
std::function<void()> mOnNewSaveFunction;
|
||||
std::function<bool(dFile_select_c* fileSelect)> mOnNewSaveSelectFunction;
|
||||
std::function<void(bool* out_proceedToNameSelect, bool* out_returnToFileSelect)> mOnNewSaveSelectFunction;
|
||||
std::function<void()> mOnGameResetFunction;
|
||||
std::function<void()> mOnTickFunction;
|
||||
};
|
||||
@@ -89,7 +92,7 @@ public:
|
||||
|
||||
const Gamemode* getCurrentGamemode() const {
|
||||
const auto& it = mRegisteredGamemodes.find(mCurrentGamemodeId);
|
||||
return it != mRegisteredGamemodes.end() ? &it->second : &mRegisteredGamemodes.at("vanilla");
|
||||
return it != mRegisteredGamemodes.end() ? &it->second : &mRegisteredGamemodes.at(kVanillaGamemodeId);
|
||||
}
|
||||
bool isCurrentGamemode(const GamemodeId& id) const {
|
||||
const Gamemode* gamemode = getCurrentGamemode();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/config.hpp"
|
||||
#include "dusk/gamemode.hpp"
|
||||
#include <aurora/aurora.h>
|
||||
|
||||
namespace dusk {
|
||||
@@ -157,7 +158,7 @@ UserSettings g_userSettings = {
|
||||
.removeQuestMapMarkers {"game.removeQuestMapMarkers", false},
|
||||
.showInputViewer {"game.showInputViewer", false},
|
||||
.showInputViewerGyro {"game.showInputViewerGyro", false},
|
||||
.lastSelectedGamemodeId {"game.lastSelectedGamemodeId", "vanilla"}
|
||||
.lastSelectedGamemodeId {"game.lastSelectedGamemodeId", gamemode::kVanillaGamemodeId}
|
||||
},
|
||||
|
||||
.backend = {
|
||||
|
||||
@@ -22,7 +22,7 @@ static void onSpeedrunModeDeactive() {
|
||||
}
|
||||
|
||||
void registerSpeedrunGamemode() {
|
||||
dusk::gamemode::Gamemode speedrunGamemode(DUSK_SPEEDRUN_GAMEMODE_ID,"Speedrun","gczelda2-speedrun");
|
||||
dusk::gamemode::Gamemode speedrunGamemode(kSpeedrunGamemodeId,"Speedrun","gczelda2-speedrun");
|
||||
speedrunGamemode.mOnSaveLoadedFunction = dusk::speedrun::start;
|
||||
speedrunGamemode.mOnActivatedFunction = onSpeedrunModeActive;
|
||||
speedrunGamemode.mOnDeactivatedFunction = onSpeedrunModeDeactive;
|
||||
@@ -32,7 +32,7 @@ void registerSpeedrunGamemode() {
|
||||
}
|
||||
|
||||
void unregisterSpeedrunGamemode() {
|
||||
dusk::gamemode::getGamemodeManager().unregisterGamemode(DUSK_SPEEDRUN_GAMEMODE_ID);
|
||||
dusk::gamemode::getGamemodeManager().unregisterGamemode(kSpeedrunGamemodeId);
|
||||
}
|
||||
|
||||
void resetForSpeedrunMode() {
|
||||
|
||||
+4
-2
@@ -2,11 +2,13 @@
|
||||
#include <aurora/aurora.h>
|
||||
#include "dusk/gamemode.hpp"
|
||||
|
||||
#define DUSK_SPEEDRUN_GAMEMODE_ID "vanilla_speedrun"
|
||||
|
||||
namespace dusk::speedrun {
|
||||
|
||||
constexpr const char* kSpeedrunGamemodeId = "vanilla_speedrun";
|
||||
|
||||
struct SpeedrunInfo {
|
||||
|
||||
void startRun() {
|
||||
m_isRunStarted = true;
|
||||
m_rtaStartTimestamp = OSGetNativeTime();
|
||||
@@ -51,7 +53,7 @@ void resetForSpeedrunMode();
|
||||
void restoreFromSpeedrunMode();
|
||||
|
||||
inline bool isActive() {
|
||||
return dusk::gamemode::getGamemodeManager().isCurrentGamemode(DUSK_SPEEDRUN_GAMEMODE_ID);
|
||||
return dusk::gamemode::getGamemodeManager().isCurrentGamemode(kSpeedrunGamemodeId);
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
|
||||
@@ -63,7 +63,11 @@ MenuBar::MenuBar()
|
||||
mTabBar->add_tab("Editor", [this] { push(std::make_unique<EditorWindow>()); });
|
||||
}
|
||||
|
||||
mTabBar->add_tab("Achievements", [this] { push(std::make_unique<AchievementsWindow>()); });
|
||||
// Only allow us to access achievements if we are playing on a gamemode that uses them
|
||||
if (dusk::gamemode::getGamemodeManager().isCurrentGamemode(dusk::gamemode::kVanillaGamemodeId)
|
||||
|| dusk::gamemode::getGamemodeManager().isCurrentGamemode(dusk::speedrun::kSpeedrunGamemodeId)) {
|
||||
mTabBar->add_tab("Achievements", [this] { push(std::make_unique<AchievementsWindow>()); });
|
||||
}
|
||||
mTabBar->add_tab("Mods", [this] { push(std::make_unique<ModsWindow>()); });
|
||||
for (auto& tab : mods::svc::ui_mod_menu_tabs()) {
|
||||
mTabBar->add_tab(tab.label, std::move(tab.onSelected));
|
||||
|
||||
@@ -337,7 +337,7 @@ void Overlay::update() {
|
||||
rtaElapsedTime = speedrun::g_speedrunInfo.m_rtaTimer;
|
||||
}
|
||||
|
||||
if (speedrun::g_speedrunInfo.m_isRunStarted && !speedrun::g_speedrunInfo.m_isRunStarted) {
|
||||
if (speedrun::g_speedrunInfo.m_isRunStarted && !speedrun::g_speedrunInfo.m_isPauseIGT) {
|
||||
speedrun::g_speedrunInfo.m_igtTimer = OSGetTime() - speedrun::g_speedrunInfo.m_igtStartTimestamp -
|
||||
speedrun::g_speedrunInfo.m_totalLoadTime;
|
||||
}
|
||||
|
||||
@@ -769,7 +769,7 @@ static std::string get_playbutton_text() {
|
||||
const dusk::gamemode::Gamemode* currentGameMode =
|
||||
dusk::gamemode::getGamemodeManager().getCurrentGamemode();
|
||||
if (currentGameMode != nullptr) {
|
||||
return currentGameMode->getId() == "vanilla" ? "Play" :
|
||||
return currentGameMode->getId() == dusk::gamemode::kVanillaGamemodeId ? "Play" :
|
||||
"Play " + currentGameMode->getFullName();
|
||||
}
|
||||
return "Play";
|
||||
@@ -880,14 +880,14 @@ void Prelaunch::build_menu_buttons() {
|
||||
gamemodeActions.push_back(dusk::ui::ModalAction{
|
||||
.label = "Vanilla", .onPressed = [this](dusk::ui::Modal& modal) {
|
||||
mDoAud_seStartMenu(kSoundClick);
|
||||
dusk::gamemode::getGamemodeManager().setCurrentGamemode("vanilla");
|
||||
dusk::gamemode::getGamemodeManager().setCurrentGamemode(dusk::gamemode::kVanillaGamemodeId);
|
||||
modal.pop();
|
||||
update();
|
||||
}});
|
||||
for (const auto& [id, gamemode] :
|
||||
dusk::gamemode::getGamemodeManager().getRegisteredGamemodes())
|
||||
{
|
||||
if (id == "vanilla") {
|
||||
if (id == dusk::gamemode::kVanillaGamemodeId) {
|
||||
// Force vanilla to the top
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user