From b3c5e4cdb128b50d4bd480b33067015404bffb65 Mon Sep 17 00:00:00 2001 From: Ghabry Date: Mon, 30 Oct 2023 12:32:05 +0100 Subject: [PATCH] DynRpg: Refactor to use a Game_DynRpg instance. This makes cleanup of state easier when switching between games. --- CMakeLists.txt | 4 +- Makefile.am | 4 +- src/dynrpg_easyrpg.cpp | 95 +++++++++++---------- src/dynrpg_easyrpg.h | 8 +- src/dynrpg_textplugin.cpp | 25 ++++-- src/dynrpg_textplugin.h | 6 +- src/{dynrpg.cpp => game_dynrpg.cpp} | 125 ++++++++++------------------ src/{dynrpg.h => game_dynrpg.h} | 69 +++++++++------ src/game_interpreter.cpp | 6 +- src/main_data.cpp | 2 + src/main_data.h | 3 +- src/player.cpp | 7 +- src/scene_map.cpp | 4 +- src/scene_save.cpp | 4 +- src/spriteset_map.cpp | 4 +- tests/dynrpg.cpp | 19 +++-- 16 files changed, 198 insertions(+), 187 deletions(-) rename src/{dynrpg.cpp => game_dynrpg.cpp} (83%) rename src/{dynrpg.h => game_dynrpg.h} (77%) diff --git a/CMakeLists.txt b/CMakeLists.txt index edb60d5de57..eb3d32ad978 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,8 +101,6 @@ add_library(${PROJECT_NAME} OBJECT src/drawable_list.h src/drawable_mgr.cpp src/drawable_mgr.h - src/dynrpg.cpp - src/dynrpg.h src/dynrpg_easyrpg.cpp src/dynrpg_easyrpg.h src/dynrpg_textplugin.cpp @@ -158,6 +156,8 @@ add_library(${PROJECT_NAME} OBJECT src/game_config.h src/game_config_game.cpp src/game_config_game.h + src/game_dynrpg.cpp + src/game_dynrpg.h src/game_enemy.cpp src/game_enemy.h src/game_enemyparty.cpp diff --git a/Makefile.am b/Makefile.am index 2c2c3390150..c06d17d9fa1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,8 +82,6 @@ libeasyrpg_player_a_SOURCES = \ src/drawable_list.h \ src/drawable_mgr.cpp \ src/drawable_mgr.h \ - src/dynrpg.cpp \ - src/dynrpg.h \ src/dynrpg_easyrpg.cpp \ src/dynrpg_easyrpg.h \ src/dynrpg_textplugin.h \ @@ -139,6 +137,8 @@ libeasyrpg_player_a_SOURCES = \ src/game_config.h \ src/game_config_game.cpp \ src/game_config_game.h \ + src/game_dynrpg.cpp \ + src/game_dynrpg.h \ src/game_enemy.cpp \ src/game_enemy.h \ src/game_enemyparty.cpp \ diff --git a/src/dynrpg_easyrpg.cpp b/src/dynrpg_easyrpg.cpp index 6878ae1ff8e..aeae66e257b 100644 --- a/src/dynrpg_easyrpg.cpp +++ b/src/dynrpg_easyrpg.cpp @@ -48,53 +48,23 @@ static bool EasyOput(dyn_arg_list args) { return true; } -static bool EasyRaw(dyn_arg_list args) { - auto func = "raw"; - bool okay = false; - - lcf::rpg::EventCommand outputCommand; - std::vector outputParams = {}; - - for (std::size_t i = 0; i < args.size(); ++i) { - std::string currValue = DynRpg::ParseVarArg(func, args, i, okay); - Output::Warning("{}", currValue); - - if (!okay) return true; - - if (i == 0) outputCommand.code = stoi(currValue); - if (i == 1) outputCommand.string = lcf::DBString(currValue); - else outputParams.push_back(stoi(currValue)); - } - - outputCommand.parameters = lcf::DBArray(outputParams.begin(), outputParams.end()); - - //FIXME: this will crash when you two interpreters run a raw command in parallel. - // The lack to access the current interpreter frame is a lack in the dynrpg API design. - // Have to fix this. The current frame should be easy to access - std::vector cmdList = { outputCommand }; - if (Game_Battle::IsBattleRunning()) Game_Battle::GetInterpreter().Push(cmdList, 0, false); - else Game_Map::GetInterpreter().Push(cmdList, 0, false); +bool DynRpg::EasyRpgPlugin::EasyCall(dyn_arg_list args, bool& do_yield, Game_Interpreter* interpreter) { + auto func_name = std::get<0>(DynRpg::ParseArgs("call", args)); - return true; -} - -static bool EasyCall(dyn_arg_list args) { - auto token = std::get<0>(DynRpg::ParseArgs("call", args)); - - if (token.empty()) { + if (func_name.empty()) { // empty function name Output::Warning("call: Empty RPGSS function name"); return true; } - if (!DynRpg::HasFunction(token)) { - // Not a supported function - Output::Warning("Unsupported RPGSS function: {}", token); - return true; + for (auto& plugin: Main_Data::game_dynrpg->plugins) { + if (plugin->Invoke(func_name, args.subspan(1), do_yield, interpreter)) { + return true; + } } - return DynRpg::Invoke(token, args.subspan(1)); + return false; } static bool EasyAdd(dyn_arg_list args) { @@ -118,11 +88,50 @@ static bool EasyAdd(dyn_arg_list args) { return true; } -void DynRpg::EasyRpgPlugin::RegisterFunctions() { - DynRpg::RegisterFunction("call", EasyCall); - DynRpg::RegisterFunction("easyrpg_output", EasyOput); - DynRpg::RegisterFunction("easyrpg_add", EasyAdd); - DynRpg::RegisterFunction("easyrpg_raw", EasyRaw); +bool DynRpg::EasyRpgPlugin::EasyRaw(dyn_arg_list args, Game_Interpreter* interpreter) { + if (!interpreter) { + return true; + } + + auto func = "raw"; + bool okay = false; + + lcf::rpg::EventCommand outputCommand; + std::vector outputParams = {}; + + for (std::size_t i = 0; i < args.size(); ++i) { + std::string currValue = DynRpg::ParseVarArg(func, args, i, okay); + Output::Warning("{}", currValue); + + if (!okay) return true; + + if (i == 0) outputCommand.code = stoi(currValue); + if (i == 1) outputCommand.string = lcf::DBString(currValue); + else outputParams.push_back(stoi(currValue)); + } + + outputCommand.parameters = lcf::DBArray(outputParams.begin(), outputParams.end()); + + //FIXME: this will crash when you two interpreters run a raw command in parallel. + // The lack to access the current interpreter frame is a lack in the dynrpg API design. + // Have to fix this. The current frame should be easy to access + std::vector cmdList = { outputCommand }; + interpreter->Push(cmdList, 0, false); + + return true; +} + +bool DynRpg::EasyRpgPlugin::Invoke(StringView func, dyn_arg_list args, bool& do_yield, Game_Interpreter* interpreter) { + if (func == "call") { + return EasyCall(args, do_yield, interpreter); + } else if (func == "easyrpg_output") { + return EasyOput(args); + } else if (func == "easyrpg_add") { + return EasyAdd(args); + } else if (func == "easyrpg_raw") { + return EasyRaw(args, interpreter); + } + return false; } void DynRpg::EasyRpgPlugin::Load(const std::vector& buffer) { diff --git a/src/dynrpg_easyrpg.h b/src/dynrpg_easyrpg.h index b4ba98f4569..aebacf858e2 100644 --- a/src/dynrpg_easyrpg.h +++ b/src/dynrpg_easyrpg.h @@ -18,7 +18,7 @@ #ifndef EP_DYNRPG_EASYRPG_H #define EP_DYNRPG_EASYRPG_H -#include "dynrpg.h" +#include "game_dynrpg.h" #include "game_battle.h" #include "game_map.h" @@ -31,9 +31,13 @@ namespace DynRpg { public: EasyRpgPlugin() : DynRpgPlugin("EasyRpgPlugin") {} - void RegisterFunctions() override; + bool Invoke(StringView func, dyn_arg_list args, bool& do_yield, Game_Interpreter* interpreter) override; void Load(const std::vector& buffer) override; std::vector Save() override; + + private: + bool EasyCall(dyn_arg_list args, bool& do_yield, Game_Interpreter* interpreter); + bool EasyRaw(dyn_arg_list args, Game_Interpreter* interpreter); }; } diff --git a/src/dynrpg_textplugin.cpp b/src/dynrpg_textplugin.cpp index 3d98ddb7f76..8c017eb98e6 100644 --- a/src/dynrpg_textplugin.cpp +++ b/src/dynrpg_textplugin.cpp @@ -399,14 +399,23 @@ static bool RemoveAll(dyn_arg_list) { return true; } -void DynRpg::TextPlugin::RegisterFunctions() { - DynRpg::RegisterFunction("write_text", WriteText); - DynRpg::RegisterFunction("append_line", AppendLine); - DynRpg::RegisterFunction("append_text", AppendText); - DynRpg::RegisterFunction("change_text", ChangeText); - DynRpg::RegisterFunction("change_position", ChangePosition); - DynRpg::RegisterFunction("remove_text", RemoveText); - DynRpg::RegisterFunction("remove_all", RemoveAll); +bool DynRpg::TextPlugin::Invoke(StringView func, dyn_arg_list args, bool& do_yield, Game_Interpreter* interpreter) { + if (func == "write_text") { + return WriteText(args); + } else if (func == "append_line") { + return AppendLine(args); + } else if (func == "append_text") { + return AppendText(args); + } else if (func == "change_text") { + return ChangeText(args); + } else if (func == "change_position") { + return ChangePosition(args); + } else if (func == "remove_text") { + return RemoveText(args); + } else if (func == "remove_all") { + return RemoveAll(args); + } + return false; } void DynRpg::TextPlugin::Update() { diff --git a/src/dynrpg_textplugin.h b/src/dynrpg_textplugin.h index 14c2767218f..2c21b30ad95 100644 --- a/src/dynrpg_textplugin.h +++ b/src/dynrpg_textplugin.h @@ -18,15 +18,15 @@ #ifndef EP_DYNRPG_TEXTPLUGIN_H #define EP_DYNRPG_TEXTPLUGIN_H -#include "dynrpg.h" +#include "game_dynrpg.h" namespace DynRpg { class TextPlugin : public DynRpgPlugin { public: TextPlugin() : DynRpgPlugin("DynTextPlugin") {} - ~TextPlugin(); + ~TextPlugin() override; - void RegisterFunctions() override; + bool Invoke(StringView func, dyn_arg_list args, bool& do_yield, Game_Interpreter* interpreter) override; void Update() override; void Load(const std::vector&) override; std::vector Save() override; diff --git a/src/dynrpg.cpp b/src/game_dynrpg.cpp similarity index 83% rename from src/dynrpg.cpp rename to src/game_dynrpg.cpp index 9ecd3cd56e5..5f1ac91bb12 100644 --- a/src/dynrpg.cpp +++ b/src/game_dynrpg.cpp @@ -16,7 +16,7 @@ */ // Headers -#include "dynrpg.h" +#include "game_dynrpg.h" #include "filefinder.h" #include "game_actors.h" #include "game_variables.h" @@ -26,7 +26,6 @@ #include #include -#include #include "dynrpg_easyrpg.h" #include "dynrpg_textplugin.h" @@ -42,33 +41,13 @@ enum DynRpg_ParseMode { ParseMode_Token }; -typedef std::map dyn_rpg_func; - -namespace { - bool init = false; - - // Registered DynRpg Plugins - std::vector> plugins; - - // DynRpg Function table - dyn_rpg_func dyn_rpg_functions; -} - -void DynRpg::RegisterFunction(const std::string& name, dynfunc func) { - dyn_rpg_functions[name] = func; -} - -bool DynRpg::HasFunction(const std::string& name) { - return dyn_rpg_functions.find(name) != dyn_rpg_functions.end(); -} - // Var arg referenced by $n std::string DynRpg::ParseVarArg(StringView func_name, dyn_arg_list args, int index, bool& parse_okay) { parse_okay = true; if (index >= static_cast(args.size())) { parse_okay = false; Output::Warning("{}: Vararg {} out of range", func_name, index); - return ""; + return {}; } std::string::iterator text_index, end; @@ -100,7 +79,7 @@ std::string DynRpg::ParseVarArg(StringView func_name, dyn_arg_list args, int ind // $-ref out of range parse_okay = false; Output::Warning("{}: Vararg $-ref {} out of range", func_name, i); - return ""; + return {}; } ++text_index; @@ -116,11 +95,10 @@ std::string DynRpg::ParseVarArg(StringView func_name, dyn_arg_list args, int ind } -static std::string ParseToken(const std::string& token, const std::string& function_name) { +static std::string ParseToken(std::string token, StringView function_name) { std::string::iterator text_index, end; - std::string text = token; - text_index = text.begin(); - end = text.end(); + text_index = token.begin(); + end = token.end(); char chr = *text_index; @@ -150,7 +128,7 @@ static std::string ParseToken(const std::string& token, const std::string& funct if (*it == 'N') { if (!Main_Data::game_actors->ActorExists(number)) { Output::Warning("{}: Invalid actor id {} in {}", function_name, number, token); - return ""; + return {}; } // N is last @@ -183,36 +161,36 @@ static std::string ParseToken(const std::string& token, const std::string& funct } // Normal token - return Utils::LowerCase(token); + Utils::LowerCaseInPlace(token); + return token; } -void create_all_plugins() { +void Game_DynRpg::InitPlugins() { + if (plugins_loaded) { + return; + } + plugins.emplace_back(new DynRpg::EasyRpgPlugin()); plugins.emplace_back(new DynRpg::TextPlugin()); - - for (auto& plugin : plugins) { - plugin->RegisterFunctions(); - } - init = true; + plugins_loaded = true; } -std::string DynRpg::ParseCommand(const std::string& command, std::vector& args) { +std::string DynRpg::ParseCommand(std::string command, std::vector& args) { if (command.empty()) { // Not a DynRPG function (empty comment) - return ""; + return {}; } std::string::iterator text_index, end; - std::string text = command; - text_index = text.begin(); - end = text.end(); + text_index = command.begin(); + end = command.end(); char chr = *text_index; if (chr != '@') { // Not a DynRPG function, normal comment - return ""; + return {}; } DynRpg_ParseMode mode = ParseMode_Function; @@ -244,7 +222,7 @@ std::string DynRpg::ParseCommand(const std::string& command, std::vector args; - std::string function_name = ParseCommand(command, args); + std::string function_name = DynRpg::ParseCommand(ToString(command), args); if (function_name.empty()) { return true; @@ -391,18 +367,19 @@ bool DynRpg::Invoke(const std::string& command) { return Invoke(function_name, args); } -bool DynRpg::Invoke(const std::string& func, dyn_arg_list args) { - if (!init) { - create_all_plugins(); - } +bool Game_DynRpg::Invoke(StringView func, dyn_arg_list args, Game_Interpreter* interpreter) { + InitPlugins(); - if (!DynRpg::HasFunction(func)) { - // Not a supported function - Output::Warning("Unsupported DynRPG function: {}", func); - return true; + bool yield = false; + + for (auto& plugin: plugins) { + if (plugin->Invoke(func, args, yield, interpreter)) { + return !yield; + } } - return dyn_rpg_functions[func](args); + Output::Warning("Unsupported DynRPG function: {}", func); + return true; } std::string get_filename(int slot) { @@ -419,14 +396,12 @@ std::string get_filename(int slot) { return found; } -void DynRpg::Load(int slot) { +void Game_DynRpg::Load(int slot) { if (!Player::IsPatchDynRpg()) { return; } - if (!init) { - create_all_plugins(); - } + InitPlugins(); std::string filename = get_filename(slot); @@ -460,7 +435,7 @@ void DynRpg::Load(int slot) { bool have_one = false; for (auto &plugin : plugins) { - if (strncmp((char*)in_buffer.data(), plugin->GetIdentifier().c_str(), len) == 0) { + if (strncmp((char*)in_buffer.data(), plugin->GetIdentifier().data(), len) == 0) { // Chunk length in.read((char *) &len, 4); Utils::SwapByteOrder(len); @@ -488,14 +463,12 @@ void DynRpg::Load(int slot) { } } -void DynRpg::Save(int slot) { +void Game_DynRpg::Save(int slot) { if (!Player::IsPatchDynRpg()) { return; } - if (!init) { - create_all_plugins(); - } + InitPlugins(); std::string filename = get_filename(slot); @@ -515,7 +488,7 @@ void DynRpg::Save(int slot) { Utils::SwapByteOrder(len); out.write((char*)&len, 4); - out.write(plugin->GetIdentifier().c_str(), len); + out.write(plugin->GetIdentifier().data(), len); std::vector data = plugin->Save(); len = data.size(); @@ -526,20 +499,14 @@ void DynRpg::Save(int slot) { } } -void DynRpg::Update() { +void Game_DynRpg::Update() { for (auto& plugin : plugins) { plugin->Update(); } } -void DynRpg::Reset() { - init = false; - dyn_rpg_functions.clear(); - plugins.clear(); -} - -bool DynRpg::Whitelist(std::string cmd) { - for (const std::string& whitelistItem : whiteList) { +bool Game_DynRpg::Whitelist(std::string cmd) { + for (const auto& whitelistItem : whiteList) { if (cmd.find(whitelistItem) != std::string::npos) { return true; } diff --git a/src/dynrpg.h b/src/game_dynrpg.h similarity index 77% rename from src/dynrpg.h rename to src/game_dynrpg.h index d921f337178..7dc8f2f52cf 100644 --- a/src/dynrpg.h +++ b/src/game_dynrpg.h @@ -15,8 +15,8 @@ * along with EasyRPG Player. If not, see . */ -#ifndef EP_DYNRPG_H -#define EP_DYNRPG_H +#ifndef EP_GAME_DYNRPG_H +#define EP_GAME_DYNRPG_H #include #include @@ -24,23 +24,28 @@ #include #include #include +#include #include "output.h" #include "utils.h" // Headers -namespace lcf { -namespace rpg { +namespace lcf::rpg { class EventCommand; } -} + +class DynRpgPlugin; +class Game_Interpreter; using dyn_arg_list = const Span; using dynfunc = bool(*)(dyn_arg_list); -/** - * DynRPG namespace - */ +/** Contains helper functions for parsing */ namespace DynRpg { + class EasyRpgPlugin; + + std::string ParseVarArg(StringView func_name, dyn_arg_list args, int index, bool& parse_okay); + std::string ParseCommand(std::string command, std::vector& params); + namespace detail { template inline bool parse_arg(StringView, dyn_arg_list, const int, T&, bool&) { @@ -101,19 +106,6 @@ namespace DynRpg { } } - void RegisterFunction(const std::string& name, dynfunc function); - bool HasFunction(const std::string& name); - std::string ParseVarArg(StringView func_name, dyn_arg_list args, int index, bool& parse_okay); - std::string ParseCommand(const std::string& command, std::vector& params); - bool Invoke(const std::string& command); - bool Invoke(const std::string& func, dyn_arg_list args); - void Update(); - void Reset(); - void Load(int slot); - void Save(int slot); - - bool Whitelist(std::string cmd); - template std::tuple ParseArgs(StringView func_name, dyn_arg_list args, bool* parse_okay = nullptr) { std::tuple t; @@ -131,14 +123,43 @@ namespace DynRpg { } } +/** + * Implements DynRPG Patch (kinda, plugins cannot be executed directly and must be reimplemented) + */ +class Game_DynRpg { +public: + bool Invoke(StringView command, Game_Interpreter* interpreter = nullptr); + void Update(); + void Load(int slot); + void Save(int slot); + bool Whitelist(std::string cmd); + +private: + friend DynRpg::EasyRpgPlugin; + + bool Invoke(StringView func, dyn_arg_list args, Game_Interpreter* interpreter = nullptr); + void InitPlugins(); + + using dyn_rpg_func = std::unordered_map; + + bool plugins_loaded = false; + + // Registered DynRpg Plugins + std::vector> plugins; + + // DynRpg Function table + dyn_rpg_func dyn_rpg_functions; +}; + +/** Base class for implementing a DynRpg Plugins */ class DynRpgPlugin { public: explicit DynRpgPlugin(std::string identifier) : identifier(std::move(identifier)) {} DynRpgPlugin() = delete; - virtual ~DynRpgPlugin() {} + virtual ~DynRpgPlugin() = default; - const std::string& GetIdentifier() const { return identifier; } - virtual void RegisterFunctions() {} + StringView GetIdentifier() const { return identifier; } + virtual bool Invoke(StringView func, dyn_arg_list args, bool& do_yield, Game_Interpreter* interpreter) = 0; virtual void Update() {} virtual void Load(const std::vector&) {} virtual std::vector Save() { return {}; } diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 1798302051e..d08ec0ce1b3 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -26,8 +26,8 @@ #include #include "game_interpreter.h" #include "audio.h" -#include "dynrpg.h" #include "filefinder.h" +#include "game_dynrpg.h" #include "game_map.h" #include "game_event.h" #include "game_enemyparty.h" @@ -2095,7 +2095,7 @@ bool Game_Interpreter::CommandEndEventProcessing(lcf::rpg::EventCommand const& / bool Game_Interpreter::CommandComment(const lcf::rpg::EventCommand &com) { std::string command = ToString(com.string); - if (Player::IsPatchDynRpg() || DynRpg::Whitelist(command)) { + if (Player::IsPatchDynRpg() || Main_Data::game_dynrpg->Whitelist(command)) { if (com.string.empty() || com.string[0] != '@') { // Not a DynRPG command return true; @@ -2116,7 +2116,7 @@ bool Game_Interpreter::CommandComment(const lcf::rpg::EventCommand &com) { } } - return DynRpg::Invoke(command); + return Main_Data::game_dynrpg->Invoke(command, this); } return true; } diff --git a/src/main_data.cpp b/src/main_data.cpp index 8a57dd79fff..cc99c55c8ea 100644 --- a/src/main_data.cpp +++ b/src/main_data.cpp @@ -24,6 +24,7 @@ #include "game_system.h" #include "game_actors.h" #include "game_party.h" +#include "game_dynrpg.h" #include "game_enemyparty.h" #include "game_ineluki.h" #include "game_player.h" @@ -70,6 +71,7 @@ namespace Main_Data { std::unique_ptr game_enemyparty; std::unique_ptr game_targets; std::unique_ptr game_quit; + std::unique_ptr game_dynrpg; std::unique_ptr game_ineluki; std::unique_ptr game_switches_global; std::unique_ptr game_variables_global; diff --git a/src/main_data.h b/src/main_data.h index e2d199eb966..588d99de9a7 100644 --- a/src/main_data.h +++ b/src/main_data.h @@ -39,6 +39,7 @@ class Game_Variables; class Game_Strings; class Game_Targets; class Game_Quit; +class Game_DynRpg; class Game_Ineluki; class FileFinder_RTP; @@ -57,11 +58,11 @@ namespace Main_Data { extern std::unique_ptr game_enemyparty; extern std::unique_ptr game_targets; extern std::unique_ptr game_quit; + extern std::unique_ptr game_dynrpg; extern std::unique_ptr game_ineluki; extern std::unique_ptr game_switches_global; // Used by Global Save command extern std::unique_ptr game_variables_global; - extern std::unique_ptr filefinder_rtp; void Init(); diff --git a/src/player.cpp b/src/player.cpp index 75a8bfd0421..665a9cf2d93 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -38,12 +38,12 @@ #include "cache.h" #include "rand.h" #include "cmdline_parser.h" -#include "dynrpg.h" #include "filefinder.h" #include "filefinder_rtp.h" #include "fileext_guesser.h" #include "game_actors.h" #include "game_battle.h" +#include "game_dynrpg.h" #include "game_map.h" #include "game_message.h" #include "game_enemyparty.h" @@ -410,7 +410,6 @@ void Player::Exit() { #endif Player::ResetGameObjects(); Font::Dispose(); - DynRpg::Reset(); Graphics::Quit(); Output::Quit(); FileFinder::Quit(); @@ -826,7 +825,7 @@ void Player::CreateGameObjects() { if (!FileFinder::Game().FindFile("dynloader.dll").empty()) { game_config.patch_dynrpg.Set(true); - Output::Warning("This game uses DynRPG and will not run properly."); + Output::Debug("This game uses DynRPG. Depending on the plugins used it will not run properly."); } if (!FileFinder::Game().FindFile("accord.dll").empty()) { @@ -927,8 +926,6 @@ void Player::ResetGameObjects() { Main_Data::game_variables_global = std::make_unique(min_var, max_var); Main_Data::game_ineluki = std::make_unique(); - DynRpg::Reset(); - Game_Clock::ResetFrame(Game_Clock::now()); Main_Data::game_system->ReloadSystemGraphic(); diff --git a/src/scene_map.cpp b/src/scene_map.cpp index 4267f4568d1..528b967369a 100644 --- a/src/scene_map.cpp +++ b/src/scene_map.cpp @@ -41,7 +41,7 @@ #include "screen.h" #include "scene_load.h" #include "output.h" -#include "dynrpg.h" +#include "game_dynrpg.h" using namespace std::chrono_literals; @@ -84,7 +84,7 @@ void Scene_Map::Start() { auto current_music = Main_Data::game_system->GetCurrentBGM(); Main_Data::game_system->BgmStop(); Main_Data::game_system->BgmPlay(current_music); - DynRpg::Load(from_save_id); + Main_Data::game_dynrpg->Load(from_save_id); } else { Game_Map::PlayBgm(); } diff --git a/src/scene_save.cpp b/src/scene_save.cpp index d2aa7dfcf4f..20cc3b28f7a 100644 --- a/src/scene_save.cpp +++ b/src/scene_save.cpp @@ -23,9 +23,9 @@ #endif #include -#include "dynrpg.h" #include "filefinder.h" #include "game_actor.h" +#include "game_dynrpg.h" #include "game_map.h" #include "game_party.h" #include "game_switches.h" @@ -156,7 +156,7 @@ bool Scene_Save::Save(std::ostream& os, int slot_id, bool prepare_save) { auto lcf_engine = Player::IsRPG2k3() ? lcf::EngineVersion::e2k3 : lcf::EngineVersion::e2k; bool res = lcf::LSD_Reader::Save(os, save, lcf_engine, Player::encoding); - DynRpg::Save(slot_id); + Main_Data::game_dynrpg->Save(slot_id); AsyncHandler::SaveFilesystem(); return res; diff --git a/src/spriteset_map.cpp b/src/spriteset_map.cpp index 4d19c248315..05f51d2a16e 100644 --- a/src/spriteset_map.cpp +++ b/src/spriteset_map.cpp @@ -18,12 +18,12 @@ // Headers #include "spriteset_map.h" #include "cache.h" -#include "dynrpg.h" #include "game_map.h" #include "main_data.h" #include "sprite_airshipshadow.h" #include "sprite_character.h" #include "game_character.h" +#include "game_dynrpg.h" #include "game_player.h" #include "game_vehicle.h" #include "game_screen.h" @@ -114,7 +114,7 @@ void Spriteset_Map::Update() { shadow->Update(); } - DynRpg::Update(); + Main_Data::game_dynrpg->Update(); } void Spriteset_Map::ChipsetUpdated() { diff --git a/tests/dynrpg.cpp b/tests/dynrpg.cpp index ee5039f80b7..6e70c2be29f 100644 --- a/tests/dynrpg.cpp +++ b/tests/dynrpg.cpp @@ -1,6 +1,6 @@ #include #include "doctest.h" -#include "dynrpg.h" +#include "game_dynrpg.h" #include "game_variables.h" #include "test_mock_actor.h" @@ -148,39 +148,40 @@ TEST_CASE("Arg parse") { } TEST_CASE("easyrpg dynrpg invoke") { + Game_DynRpg dyn; const MockActor m; std::vector vars = {-1}; Main_Data::game_variables->SetData(vars); Main_Data::game_variables->SetWarning(0); - DynRpg::Invoke("@easyrpg_add 1, 2, 4"); + dyn.Invoke("@easyrpg_add 1, 2, 4"); CHECK(Main_Data::game_variables->Get(1) == 6); // Invalid, stays 6 - DynRpg::Invoke("@easyrpg_add 1, 2, a"); + dyn.Invoke("@easyrpg_add 1, 2, a"); CHECK(Main_Data::game_variables->Get(1) == 6); // Not enough args, stays 6 - DynRpg::Invoke("@easyrpg_add 1"); + dyn.Invoke("@easyrpg_add 1"); CHECK(Main_Data::game_variables->Get(1) == 6); - DynRpg::Invoke("@easyrpg_add 1, 2"); + dyn.Invoke("@easyrpg_add 1, 2"); CHECK(Main_Data::game_variables->Get(1) == 2); - DynRpg::Invoke("@call easyrpg_add, 1, 4.3, 7.7"); + dyn.Invoke("@call easyrpg_add, 1, 4.3, 7.7"); CHECK(Main_Data::game_variables->Get(1) == 11); // Extra args ignored - DynRpg::Invoke("@call easyrpg_add, 1, 4, 8, -14.0"); + dyn.Invoke("@call easyrpg_add, 1, 4, 8, -14.0"); CHECK(Main_Data::game_variables->Get(1) == -2); // Invalid func, stays -2 - DynRpg::Invoke("@call easyrpg_xxx, 1, 4, 7"); + dyn.Invoke("@call easyrpg_xxx, 1, 4, 7"); CHECK(Main_Data::game_variables->Get(1) == -2); // does not crash - DynRpg::Invoke("@unknownfunc 1, 2, 3"); + dyn.Invoke("@unknownfunc 1, 2, 3"); } TEST_CASE("Incompatible changes") {