diff --git a/resources/unix/easyrpg-player.6.adoc b/resources/unix/easyrpg-player.6.adoc index 0a4081d08e7..e1872577468 100644 --- a/resources/unix/easyrpg-player.6.adoc +++ b/resources/unix/easyrpg-player.6.adoc @@ -78,16 +78,21 @@ NOTE: For games that only use ASCII (English games) use '1252'. Disable support for the Runtime Package (RTP). Will lead to checkerboard graphics and silent music/sound effects in games depending on the RTP. -*--patch-anti-lag-switch*:: _SWITCH_ +*--patch-antilag-switch*:: _SWITCH_ Disables event page refreshing when the switch 'SWITCH' is set to 'ON'. *--patch-common-this*:: Enable usage of __This Event__ in common events in any version of the engine. By default, this behaviour is only enabled for RPG Maker 2003 v1.12. +*--patch-direct-menu*:: _VAR_ + Directly access subscreens of the default menu by setting VAR. + See also: https://dev.makerpendium.de/docs/patch_db/main-en.htm?page=direct_menu + *--patch-dynrpg*:: Enable limited support for the DynRPG patch from Cherry. The patches are not - loaded from DLL files, but re-implemented by the engine. + loaded from DLL files, but re-implemented by the engine. See also: + https://rpg-maker.cherrytree.at/dynrpg/getting_started.html *--patch-easyrpg*:: Enable EasyRPG extensions such as support for 32 bit images and large charsets. diff --git a/src/game_config_game.cpp b/src/game_config_game.cpp index c297936e5fa..3be97069732 100644 --- a/src/game_config_game.cpp +++ b/src/game_config_game.cpp @@ -17,6 +17,7 @@ #include "game_config_game.h" #include "cmdline_parser.h" +#include "directory_tree.h" #include "filefinder.h" #include "options.h" #include "output.h" @@ -85,7 +86,8 @@ void Game_ConfigGame::LoadFromArgs(CmdlineParser& cp) { patch_common_this_event.Lock(false); patch_key_patch.Lock(false); patch_rpg2k3_commands.Lock(false); - patch_anti_lag_switch.Lock(false); + patch_anti_lag_switch.Lock(0); + patch_direct_menu.Lock(0); patch_override = true; continue; } @@ -129,16 +131,28 @@ void Game_ConfigGame::LoadFromArgs(CmdlineParser& cp) { patch_override = true; continue; } - if (cp.ParseNext(arg, 1, "--patch-antilag-switch")) { - if (arg.ParseValue(0, li_value)) { + if (cp.ParseNext(arg, 1, {"--patch-antilag-switch", "--no-patch-antilag-switch"})) { + if (arg.ArgIsOn() && arg.ParseValue(0, li_value)) { patch_anti_lag_switch.Set(li_value); patch_override = true; } + + if (arg.ArgIsOff()) { + patch_anti_lag_switch.Set(0); + patch_override = true; + } continue; } - if (cp.ParseNext(arg, 0, "--no-patch-antilag-switch")) { - patch_anti_lag_switch.Set(0); - patch_override = true; + if (cp.ParseNext(arg, 1, {"--patch-direct-menu", "--no-patch-direct-menu"})) { + if (arg.ArgIsOn() && arg.ParseValue(0, li_value)) { + patch_direct_menu.Set(li_value); + patch_override = true; + } + + if (arg.ArgIsOff()) { + patch_direct_menu.Set(0); + patch_override = true; + } continue; } if (cp.ParseNext(arg, 6, "--patch")) { @@ -211,4 +225,46 @@ void Game_ConfigGame::LoadFromStream(Filesystem_Stream::InputStream& is) { if (patch_anti_lag_switch.FromIni(ini)) { patch_override = true; } + + if (patch_direct_menu.FromIni(ini)) { + patch_override = true; + } +} + +void Game_ConfigGame::PrintActivePatches() { + std::vector patches; + + auto add_bool = [&](auto& patch) { + if (patch.Get()) { + patches.push_back(ToString(patch.GetName())); + } + }; + + add_bool(patch_easyrpg); + add_bool(patch_dynrpg); + add_bool(patch_maniac); + add_bool(patch_common_this_event); + add_bool(patch_unlock_pics); + add_bool(patch_key_patch); + add_bool(patch_rpg2k3_commands); + + auto add_int = [&](auto& patch) { + if (patch.Get() > 0) { + patches.push_back(fmt::format("{} ({})", patch.GetName(), patch.Get())); + } + }; + + add_int(patch_anti_lag_switch); + add_int(patch_direct_menu); + + if (patches.empty()) { + Output::Debug("Patch configuration: None"); + } else { + std::string out = "Patch configuration: "; + for (const auto& s: patches) { + out += s + " "; + } + out.pop_back(); + Output::DebugStr(out); + } } diff --git a/src/game_config_game.h b/src/game_config_game.h index 0106d67b287..ef8e70d5673 100644 --- a/src/game_config_game.h +++ b/src/game_config_game.h @@ -46,6 +46,7 @@ struct Game_ConfigGame { BoolConfigParam patch_key_patch{ "Ineluki Key Patch", "Support \"Ineluki Key Patch\"", "Patch", "KeyPatch", false }; BoolConfigParam patch_rpg2k3_commands{ "RPG2k3 Event Commands", "Enable support for RPG2k3 event commands", "Patch", "RPG2k3Commands", false }; ConfigParam patch_anti_lag_switch{ "Anti-Lag Switch", "Disable event page refreshes when switch is set", "Patch", "AntiLagSwitch", 0 }; + ConfigParam patch_direct_menu{ "Direct Menu", " Allows direct access to subscreens of the default menu", "Patch", "DirectMenu", 0 }; // Command line only BoolConfigParam patch_support{ "Support patches", "When OFF all patch support is disabled", "", "", true }; @@ -75,6 +76,9 @@ struct Game_ConfigGame { * @post values of this are updated with values found in command line args. */ void LoadFromArgs(CmdlineParser& cp); + + /** Outputs a list of active patches */ + void PrintActivePatches(); }; #endif diff --git a/src/game_interpreter_map.cpp b/src/game_interpreter_map.cpp index 6c01d1a6bca..a4efc6d85ed 100644 --- a/src/game_interpreter_map.cpp +++ b/src/game_interpreter_map.cpp @@ -23,6 +23,7 @@ #include #include #include "audio.h" +#include "feature.h" #include "game_map.h" #include "game_battle.h" #include "game_event.h" @@ -38,8 +39,13 @@ #include "sprite_character.h" #include "scene_map.h" #include "scene_battle.h" +#include "scene_equip.h" +#include "scene_item.h" #include "scene_menu.h" +#include "scene_order.h" #include "scene_save.h" +#include "scene_status.h" +#include "scene_skill.h" #include "scene_load.h" #include "scene_name.h" #include "scene_shop.h" @@ -83,6 +89,82 @@ void Game_Interpreter_Map::OnMapChange() { } } +bool Game_Interpreter_Map::RequestMainMenuScene(int subscreen_id, int actor_index, bool is_db_actor) { + + if (Player::game_config.patch_direct_menu.Get() && subscreen_id == -1) { + subscreen_id = Main_Data::game_variables->Get(Player::game_config.patch_direct_menu.Get()); + actor_index = Main_Data::game_variables->Get(Player::game_config.patch_direct_menu.Get() + 1); + is_db_actor = (actor_index < 0); + actor_index = std::abs(actor_index); + } + + switch (subscreen_id) + { + case 1: // Inventory + Scene::instance->SetRequestedScene(std::make_shared()); + return true; + case 2: // Skills + case 3: // Equipment + case 4: // Status + if (!is_db_actor) { + if (actor_index == 0 || actor_index > 4) { + actor_index = 1; + } + actor_index--; + } + + if (is_db_actor && !Main_Data::game_actors->GetActor(actor_index)) { + Output::Warning("Invalid actor ID {}", actor_index); + return false; + } + + if (subscreen_id == 2) { + Scene::instance->SetRequestedScene(std::make_shared(actor_index, 0, is_db_actor)); + } + else if (subscreen_id == 3) { + Game_Actor* actor; + if (!is_db_actor) { + actor = Main_Data::game_party->GetActors()[actor_index]; + } + else { + actor = Main_Data::game_actors->GetActor(actor_index); + } + Scene::instance->SetRequestedScene(std::make_shared(*actor)); + } + else if (subscreen_id == 4) { + Scene::instance->SetRequestedScene(std::make_shared(actor_index, is_db_actor)); + } + return true; + case 5: // Order + if (!Feature::HasRow()) { + break; + } + + if (Main_Data::game_party->GetActors().size() <= 1) { + Output::Warning("Party size must exceed '1' for 'Order' subscreen to be opened"); + return false; + } + else { + Scene::instance->SetRequestedScene(std::make_shared()); + return true; + } + /* + case 6: // Settings + Scene::instance->SetRequestedScene(std::make_shared()); + return true; + case 7: // Language + Scene::instance->SetRequestedScene(std::make_shared()); + return true; + case 8: // Debug + Scene::instance->SetRequestedScene(std::make_shared()); + return true; + */ + } + + Scene::instance->SetRequestedScene(std::make_shared()); + return true; +} + /** * Execute Command. */ @@ -638,7 +720,7 @@ bool Game_Interpreter_Map::CommandOpenSaveMenu(lcf::rpg::EventCommand const& /* return false; } -bool Game_Interpreter_Map::CommandOpenMainMenu(lcf::rpg::EventCommand const& /* com */) { // code 11950 +bool Game_Interpreter_Map::CommandOpenMainMenu(lcf::rpg::EventCommand const& com) { // code 11950 auto& frame = GetFrame(); auto& index = frame.current_command; @@ -646,9 +728,14 @@ bool Game_Interpreter_Map::CommandOpenMainMenu(lcf::rpg::EventCommand const& /* return false; } - Scene::instance->SetRequestedScene(std::make_shared()); - ++index; - return false; + int subscreen_id = -1, actor_index = 0; + bool is_db_actor = false; + + if (RequestMainMenuScene(subscreen_id, actor_index, is_db_actor)) { + ++index; + return false; + } + return true; } bool Game_Interpreter_Map::CommandOpenLoadMenu(lcf::rpg::EventCommand const& /* com */) { diff --git a/src/game_interpreter_map.h b/src/game_interpreter_map.h index a52e7da0ae6..1bdb89de103 100644 --- a/src/game_interpreter_map.h +++ b/src/game_interpreter_map.h @@ -51,6 +51,8 @@ class Game_Interpreter_Map : public Game_Interpreter */ void OnMapChange(); + bool RequestMainMenuScene(int subscreen_id = -1, int actor_index = 0, bool is_db_actor = false); + bool ExecuteCommand(lcf::rpg::EventCommand const& com) override; private: diff --git a/src/game_player.cpp b/src/game_player.cpp index c20a02a9ef6..48091e9677b 100644 --- a/src/game_player.cpp +++ b/src/game_player.cpp @@ -295,7 +295,7 @@ void Game_Player::UpdateNextMovementAction() { ResetAnimation(); Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision)); - Scene::instance->SetRequestedScene(std::make_shared()); + Game_Map::GetInterpreter().RequestMainMenuScene(); return; } diff --git a/src/player.cpp b/src/player.cpp index 46e20d9de9e..5f69eec6ab5 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -825,9 +825,7 @@ void Player::CreateGameObjects() { } } - Output::Debug("Patch configuration: easyrpg={} dynrpg={} maniac={} key-patch={} common-this={} pic-unlock={} 2k3-commands={} anti-lag-switch={}", - Player::HasEasyRpgExtensions(), Player::IsPatchDynRpg(), Player::IsPatchManiac(), Player::IsPatchKeyPatch(), game_config.patch_common_this_event.Get(), - game_config.patch_unlock_pics.Get(), game_config.patch_rpg2k3_commands.Get(), game_config.patch_anti_lag_switch.Get()); + game_config.PrintActivePatches(); ResetGameObjects(); @@ -1394,11 +1392,14 @@ Engine options: --new-game Skip the title scene and start a new game directly. --no-log-color Disable colors in terminal log. --no-rtp Disable support for the Runtime Package (RTP). - --patch-anti-lag-switch SWITCH + --patch-antilag-switch SWITCH Disables event page refreshing when the switch SWITCH is enabled. --patch-common-this Enable usage of "This Event" in common events in any version of the engine. + --patch-direct-menu VAR + Directly access subscreens of the default menu by setting + VAR. --patch-dynrpg Enable support of DynRPG patch by Cherry (very limited). --patch-easyrpg Enable EasyRPG extensions. --patch-key-patch Enable Key Patch by Ineluki. diff --git a/src/scene_equip.cpp b/src/scene_equip.cpp index 6dc13f8d2ff..e258207615c 100644 --- a/src/scene_equip.cpp +++ b/src/scene_equip.cpp @@ -179,13 +179,17 @@ void Scene_Equip::UpdateEquipSelection() { } else if (Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::RIGHT)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); int actor_index = Main_Data::game_party->GetActorPositionInParty(actor.GetId()); - actor_index = (actor_index + 1) % Main_Data::game_party->GetActors().size(); - Scene::Push(std::make_shared((*Main_Data::game_party)[actor_index], equip_window->GetIndex()), true); + if (actor_index != -1) { + actor_index = (actor_index + 1) % Main_Data::game_party->GetActors().size(); + Scene::Push(std::make_shared((*Main_Data::game_party)[actor_index], equip_window->GetIndex()), true); + } } else if (Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::LEFT)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); int actor_index = Main_Data::game_party->GetActorPositionInParty(actor.GetId()); - actor_index = (actor_index + Main_Data::game_party->GetActors().size() - 1) % Main_Data::game_party->GetActors().size(); - Scene::Push(std::make_shared((*Main_Data::game_party)[actor_index], equip_window->GetIndex()), true); + if (actor_index != -1) { + actor_index = (actor_index + Main_Data::game_party->GetActors().size() - 1) % Main_Data::game_party->GetActors().size(); + Scene::Push(std::make_shared((*Main_Data::game_party)[actor_index], equip_window->GetIndex()), true); + } } } diff --git a/src/scene_skill.cpp b/src/scene_skill.cpp index 21e9bcb1fad..1066fcb19ec 100644 --- a/src/scene_skill.cpp +++ b/src/scene_skill.cpp @@ -18,6 +18,7 @@ // Headers #include "scene_skill.h" #include "algo.h" +#include "game_actors.h" #include "game_map.h" #include "game_party.h" #include "game_player.h" @@ -28,8 +29,8 @@ #include "scene_teleport.h" #include "transition.h" -Scene_Skill::Scene_Skill(int actor_index, int skill_index) : - actor_index(actor_index), skill_index(skill_index) { +Scene_Skill::Scene_Skill(int actor_index, int skill_index, bool is_db_actor) : + actor_index(actor_index), skill_index(skill_index), is_db_actor(is_db_actor) { Scene::type = Scene::Skill; } @@ -41,9 +42,16 @@ void Scene_Skill::Start() { skillstatus_window.reset(new Window_SkillStatus(Player::menu_offset_x, Player::menu_offset_y + window_help_height, MENU_WIDTH, window_skillstatus_height)); skill_window.reset(new Window_Skill(Player::menu_offset_x, Player::menu_offset_y + window_help_height + window_skillstatus_height, MENU_WIDTH, MENU_HEIGHT - (window_help_height + window_skillstatus_height))); + Game_Actor* actor; + if (!is_db_actor) { + actor = Main_Data::game_party->GetActors()[actor_index]; + } + else { + actor = Main_Data::game_actors->GetActor(actor_index); + } // Assign actors and help to windows - skill_window->SetActor(Main_Data::game_party->GetActors()[actor_index]->GetId()); - skillstatus_window->SetActor(Main_Data::game_party->GetActors()[actor_index]->GetId()); + skill_window->SetActor(actor->GetId()); + skillstatus_window->SetActor(actor->GetId()); skill_window->SetIndex(skill_index); skill_window->SetHelpWindow(help_window.get()); } @@ -65,7 +73,13 @@ void Scene_Skill::vUpdate() { const lcf::rpg::Skill* skill = skill_window->GetSkill(); int skill_id = skill ? skill->ID : 0; - Game_Actor* actor = Main_Data::game_party->GetActors()[actor_index]; + Game_Actor* actor; + if (!is_db_actor) { + actor = Main_Data::game_party->GetActors()[actor_index]; + } + else { + actor = Main_Data::game_actors->GetActor(actor_index); + } if (skill && skill_window->CheckEnable(skill_id)) { if (skill->type == lcf::rpg::Skill::Type_switch) { @@ -74,6 +88,10 @@ void Scene_Skill::vUpdate() { Scene::PopUntil(Scene::Map); Game_Map::SetNeedRefresh(true); } else if (Algo::IsNormalOrSubskill(*skill)) { + int actor_target_index = actor_index; + if (is_db_actor) { + actor_index = 0; + } Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision)); Scene::Push(std::make_shared(skill_id, actor_index)); skill_index = skill_window->GetIndex(); diff --git a/src/scene_skill.h b/src/scene_skill.h index 8fc921eff9c..81ce93ba5b6 100644 --- a/src/scene_skill.h +++ b/src/scene_skill.h @@ -33,7 +33,7 @@ class Scene_Skill : public Scene { /** * Constructor. */ - Scene_Skill(int actor_index, int skill_index = 0); + Scene_Skill(int actor_index, int skill_index = 0, bool is_db_actor = false); void Start() override; void Continue(SceneType prev_scene) override; @@ -45,6 +45,8 @@ class Scene_Skill : public Scene { int actor_index; /** Skill to select at startup. */ int skill_index; + /** Given actor index refers to a database actor instead of a party member index. */ + bool is_db_actor; /** Displays available skills. */ std::unique_ptr skill_window; /** Displays information about the actor. */ diff --git a/src/scene_status.cpp b/src/scene_status.cpp index bc6d529da07..2bcfdac0dc7 100644 --- a/src/scene_status.cpp +++ b/src/scene_status.cpp @@ -19,13 +19,14 @@ #include #include #include "scene_status.h" +#include "game_actors.h" #include "game_party.h" #include "game_system.h" #include "input.h" #include -Scene_Status::Scene_Status(int actor_index) : - actor_index(actor_index) { +Scene_Status::Scene_Status(int actor_index, bool is_db_actor) : + actor_index(actor_index), is_db_actor(is_db_actor) { type = Scene::Status; } @@ -41,8 +42,14 @@ void Scene_Status::Start() { int window_equip_width = 196; int window_equip_height = 96; - int actor = Main_Data::game_party->GetActors()[actor_index]->GetId(); + int actor; + if (!is_db_actor) { + actor = Main_Data::game_party->GetActors()[actor_index]->GetId(); + } + else { + actor = Main_Data::game_actors->GetActor(actor_index)->GetId(); + } actorinfo_window.reset(new Window_ActorInfo(Player::menu_offset_x, Player::menu_offset_y, window_actor_info_width, window_actor_info_height, actor)); gold_window.reset(new Window_Gold(Player::menu_offset_x, Player::menu_offset_y + window_actor_info_height, window_gold_width, window_gold_height)); actorstatus_window.reset(new Window_ActorStatus(Player::menu_offset_x + window_actor_info_width, Player::menu_offset_y, window_actor_status_width, window_actor_status_height, actor)); @@ -63,11 +70,11 @@ void Scene_Status::vUpdate() { if (Input::IsTriggered(Input::CANCEL)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cancel)); Scene::Pop(); - } else if (Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::RIGHT)) { + } else if (!is_db_actor && Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::RIGHT)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); actor_index = (actor_index + 1) % Main_Data::game_party->GetActors().size(); Scene::Push(std::make_shared(actor_index), true); - } else if (Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::LEFT)) { + } else if (!is_db_actor && Main_Data::game_party->GetActors().size() > 1 && Input::IsTriggered(Input::LEFT)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); actor_index = (actor_index + Main_Data::game_party->GetActors().size() - 1) % Main_Data::game_party->GetActors().size(); Scene::Push(std::make_shared(actor_index), true); diff --git a/src/scene_status.h b/src/scene_status.h index 4db7ce8a6eb..2f9260d4b6b 100644 --- a/src/scene_status.h +++ b/src/scene_status.h @@ -37,13 +37,15 @@ class Scene_Status : public Scene { * * @param actor_index party index of the actor. */ - Scene_Status(int actor_index); + Scene_Status(int actor_index, bool is_db_actor = false); void Start() override; void vUpdate() override; private: int actor_index; + /** Given actor index refers to a database actor instead of a party member index. */ + bool is_db_actor; std::unique_ptr actorinfo_window; std::unique_ptr actorstatus_window;