From b5190cd1ee21d337625bc444945fbb295843cced Mon Sep 17 00:00:00 2001 From: florianessl Date: Sat, 1 Feb 2025 18:13:01 +0100 Subject: [PATCH 1/5] Feature: Implemented & refactored Jetrotal's suggested "GetTime" feature for "ControlVariablesEx" (partly cherry picked from commit f860effceb164d05742316f49c89c870721ef819 @EasyRPG-NewFaturesNewFeatures:NewCommand-GetTime) --- src/game_interpreter.cpp | 58 ++++++++++++++++++---- src/game_interpreter.h | 2 + src/game_interpreter_control_variables.cpp | 58 ++++++++++++++++++++++ src/game_interpreter_control_variables.h | 31 ++++++++++++ 4 files changed, 139 insertions(+), 10 deletions(-) diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 5a5b6dbed7..bec00ebe1c 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -786,6 +786,12 @@ bool Game_Interpreter::ExecuteCommand(lcf::rpg::EventCommand const& com) { return CommandManiacCallCommand(com); case Cmd::Maniac_GetGameInfo: return CommandManiacGetGameInfo(com); + //case static_cast(2020): // EasyRpg_ControlVariablesEx (Not yet implemented) + // return CommandEasyRpgConditionalBranchEx(com); + //case static_cast(2021): // EasyRpg_ControlSwitchesEx (Not yet implemented) + // return CommandEasyRpgControlSwitchesEx(com); + case static_cast(2022): // EasyRpg_ControlVariablesEx + return CommandEasyRpgControlVariablesEx(com); case Cmd::EasyRpg_SetInterpreterFlag: return CommandEasyRpgSetInterpreterFlag(com); case Cmd::EasyRpg_ProcessJson: @@ -1059,13 +1065,20 @@ bool Game_Interpreter::CommandControlSwitches(lcf::rpg::EventCommand const& com) return true; } +template bool Game_Interpreter::CommandControlVariables(lcf::rpg::EventCommand const& com) { // code 10220 int value = 0; int operand = com.parameters[4]; - if (EP_UNLIKELY(operand >= 9 && !Player::IsPatchManiac())) { - Output::Warning("ControlVariables: Unsupported operand {}", operand); - return true; + if constexpr (EasyRpgEx) { + if (EP_UNLIKELY(operand >= 200) && !ControlVariables::EasyRpgExCommand(com, value)) { + return true; + } + } else { + if (EP_UNLIKELY(operand >= 9 && !Player::IsPatchManiac())) { + Output::Warning("ControlVariables: Unsupported operand {}", operand); + return true; + } } switch (operand) { @@ -1235,18 +1248,36 @@ bool Game_Interpreter::CommandControlVariables(lcf::rpg::EventCommand const& com value = ManiacPatch::ParseExpression(MakeSpan(com.parameters).subspan(6, com.parameters[5]), *this); break; default: + if constexpr (EasyRpgEx) { + if (operand >= 200) { + break; + } + } Output::Warning("ControlVariables: Unsupported operand {}", operand); return true; } int start, end; - bool target_eval_result = DecodeTargetEvaluationMode< - /* validate_patches */ true, - /* support_range_indirect */ true, - /* support_expressions */ true, - /* support_bitmask */ false, - /* support_scopes */ false - >(com, start, end); + bool target_eval_result; + + if constexpr (EasyRpgEx) { + target_eval_result = DecodeTargetEvaluationMode < + /* validate_patches */ false, + /* support_range_indirect */ true, + /* support_expressions */ true, + /* support_bitmask */ true, + /* support_scopes */ true, // (Not yet implemented) + /* support_named */ true // (Not yet implemented) + >(com, start, end); + } else { + target_eval_result = DecodeTargetEvaluationMode < + /* validate_patches */ true, + /* support_range_indirect */ true, + /* support_expressions */ true, + /* support_bitmask */ false, + /* support_scopes */ false + >(com, start, end); + } if (!target_eval_result) { Output::Warning("ControlVariables: Unsupported target evaluation mode {}", com.parameters[0]); return true; @@ -5325,6 +5356,13 @@ bool Game_Interpreter::CommandManiacCallCommand(lcf::rpg::EventCommand const& co return true; } +bool Game_Interpreter::CommandEasyRpgControlVariablesEx(lcf::rpg::EventCommand const& com) { // 2022 + if (!Player::HasEasyRpgExtensions()) { + return true; + } + return CommandControlVariables(com); +} + bool Game_Interpreter::CommandEasyRpgSetInterpreterFlag(lcf::rpg::EventCommand const& com) { if (!Player::HasEasyRpgExtensions()) { return true; diff --git a/src/game_interpreter.h b/src/game_interpreter.h index 04bf3afda3..2bb95a9214 100644 --- a/src/game_interpreter.h +++ b/src/game_interpreter.h @@ -205,6 +205,7 @@ class Game_Interpreter : public Game_BaseInterpreterContext bool CommandShowChoiceEnd(lcf::rpg::EventCommand const& com); bool CommandInputNumber(lcf::rpg::EventCommand const& com); bool CommandControlSwitches(lcf::rpg::EventCommand const& com); + template bool CommandControlVariables(lcf::rpg::EventCommand const& com); bool CommandTimerOperation(lcf::rpg::EventCommand const& com); bool CommandChangeGold(lcf::rpg::EventCommand const& com); @@ -297,6 +298,7 @@ class Game_Interpreter : public Game_BaseInterpreterContext bool CommandManiacSetGameOption(lcf::rpg::EventCommand const& com); bool CommandManiacControlStrings(lcf::rpg::EventCommand const& com); bool CommandManiacCallCommand(lcf::rpg::EventCommand const& com); + bool CommandEasyRpgControlVariablesEx(lcf::rpg::EventCommand const& com); bool CommandEasyRpgSetInterpreterFlag(lcf::rpg::EventCommand const& com); bool CommandEasyRpgProcessJson(lcf::rpg::EventCommand const& com); bool CommandEasyRpgCloneMapEvent(lcf::rpg::EventCommand const& com); diff --git a/src/game_interpreter_control_variables.cpp b/src/game_interpreter_control_variables.cpp index dc49678c02..d50646a230 100644 --- a/src/game_interpreter_control_variables.cpp +++ b/src/game_interpreter_control_variables.cpp @@ -487,3 +487,61 @@ int ControlVariables::Divmul(int arg1, int arg2, int arg3) { int ControlVariables::Between(int arg1, int arg2, int arg3) { return (arg1 >= arg2 && arg2 <= arg3) ? 0 : 1; } + +// +// New EasyRpgEx operations +// + +bool ControlVariables::EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& value) { + int operand = com.parameters[4]; + + switch (operand) { + case 210: // eVarOperand_EasyRpg_DateTime + // + // Possible method for a string-based lookup (inspired by Jetrotal's initial suggestion): + /* + ControlVariables::DateTimeOp op; + if (!com.string.empty() && kDateTimeOpTags.etag(com.string.c_str(), op)) { + value = DateTime(op); + } + */ + value = DateTime(static_cast(com.parameters[5])); + default: + Output::Warning("ControlVariables: Unsupported operand {}", com.parameters[5]); + return false; + } + + return true; +} + +int ControlVariables::DateTime(DateTimeOp op) { + std::time_t t = std::time(nullptr); + std::tm* tm = std::localtime(&t); + + switch (op) + { + case DateTimeOp::Year: + return tm->tm_year + 1900; + case DateTimeOp::Month: + return tm->tm_mon + 1; + case DateTimeOp::Day: + return tm->tm_mday; + case DateTimeOp::Hour: + return tm->tm_hour; + case DateTimeOp::Minute: + return tm->tm_min; + case DateTimeOp::Second: + return tm->tm_sec; + case DateTimeOp::WeekDay: + return tm->tm_wday + 1; + case DateTimeOp::DayOfYear: + return tm->tm_yday + 1; + case DateTimeOp::IsDayLightSavings: + return tm->tm_isdst; + case DateTimeOp::TimeStamp: + return t; + } + + Output::Warning("ControlVariables::GetTime: Unknown op {}", static_cast(op)); + return 0; +} diff --git a/src/game_interpreter_control_variables.h b/src/game_interpreter_control_variables.h index c1d7da11c4..37916d61b9 100644 --- a/src/game_interpreter_control_variables.h +++ b/src/game_interpreter_control_variables.h @@ -45,6 +45,37 @@ namespace ControlVariables { int Muldiv(int arg1, int arg2, int arg3); int Divmul(int arg1, int arg2, int arg3); int Between(int arg1, int arg2, int arg3); + + // + // New EasyRpgEx operations + // + bool EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& value); + + enum class DateTimeOp { + Year = 0, + Month, + Day, + Hour, + Minute, + Second, + WeekDay, + DayOfYear, + IsDayLightSavings, + TimeStamp + }; + static constexpr auto kDateTimeOpTags = lcf::makeEnumTags( + "getyear", + "getmonth", + "getday", + "gethour", + "getminute", + "getsecond", + "getweekday", + "getyearday", + "getdaylightsavings", + "gettimestamp" + ); + int DateTime(DateTimeOp op); } #endif From 40c51d36deda3db482d49e956d05f82bba7f2623 Mon Sep 17 00:00:00 2001 From: florianessl Date: Sat, 1 Feb 2025 18:25:20 +0100 Subject: [PATCH 2/5] ControlVariablesEx NewFeature: Get information about previously inaccessible info on current map ("ActiveMapInfo") or info on any map settings straight out of the map tree ("InspectMapTreeInfo" -> parent map, troop info, arena info) --- src/game_interpreter.cpp | 2 +- src/game_interpreter_control_variables.cpp | 119 ++++++++++++++++++++- src/game_interpreter_control_variables.h | 25 ++++- 3 files changed, 143 insertions(+), 3 deletions(-) diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index bec00ebe1c..31ac523307 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -1071,7 +1071,7 @@ bool Game_Interpreter::CommandControlVariables(lcf::rpg::EventCommand const& com int operand = com.parameters[4]; if constexpr (EasyRpgEx) { - if (EP_UNLIKELY(operand >= 200) && !ControlVariables::EasyRpgExCommand(com, value)) { + if (EP_UNLIKELY(operand >= 200) && !ControlVariables::EasyRpgExCommand(com, value, *this)) { return true; } } else { diff --git a/src/game_interpreter_control_variables.cpp b/src/game_interpreter_control_variables.cpp index d50646a230..a098a804f2 100644 --- a/src/game_interpreter_control_variables.cpp +++ b/src/game_interpreter_control_variables.cpp @@ -21,6 +21,7 @@ #include "game_enemyparty.h" #include "game_ineluki.h" #include "game_interpreter.h" +#include "game_map.h" #include "game_party.h" #include "game_player.h" #include "game_system.h" @@ -492,7 +493,9 @@ int ControlVariables::Between(int arg1, int arg2, int arg3) { // New EasyRpgEx operations // -bool ControlVariables::EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& value) { +bool ControlVariables::EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& value, const Game_BaseInterpreterContext& interpreter) { + using namespace Game_Interpreter_Shared; + int operand = com.parameters[4]; switch (operand) { @@ -506,6 +509,25 @@ bool ControlVariables::EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& } */ value = DateTime(static_cast(com.parameters[5])); + break; + case 211: // eVarOperand_EasyRpg_ActiveMapInfo + value = ActiveMapInfo(static_cast(com.parameters[5])); + break; + case 212: // eVarOperand_EasyRpg_InspectMapTreeInfo + { + int map_id = 0, arg1 = 0; + if (com.parameters.size() >= 9) { + map_id = ValueOrVariableBitfield(com.parameters[8], 0, com.parameters[6], interpreter); + arg1 = ValueOrVariableBitfield(com.parameters[8], 1, com.parameters[7], interpreter); + } else if (com.parameters.size() == 8) { + arg1 = com.parameters[7]; + } + if (map_id == 0) { + map_id = Game_Map::GetMapId(); + } + value = InspectMapTreeInfo(static_cast(com.parameters[5]), map_id, arg1); + break; + } default: Output::Warning("ControlVariables: Unsupported operand {}", com.parameters[5]); return false; @@ -545,3 +567,98 @@ int ControlVariables::DateTime(DateTimeOp op) { Output::Warning("ControlVariables::GetTime: Unknown op {}", static_cast(op)); return 0; } + +int ControlVariables::ActiveMapInfo(ActiveMapInfoOp op) { + switch (op) + { + case ActiveMapInfoOp::MapTileWidth: + return Game_Map::GetTilesX(); + case ActiveMapInfoOp::MapTileHeight: + return Game_Map::GetTilesY(); + case ActiveMapInfoOp::LoopHorizontal: + return Game_Map::LoopHorizontal(); + case ActiveMapInfoOp::LoopVertical: + return Game_Map::LoopVertical(); + } + + Output::Warning("ControlVariables::ActiveMapInfo: Unknown op {}", static_cast(op)); + return 0; +} + +int ControlVariables::InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, int arg1) { + auto& map_info = Game_Map::GetMapInfo(map_id); + if (map_info.ID == 0) { + return 0; + } + + switch (op) + { + case InspectMapTreeInfoOp::ParentMap: + return map_info.parent_map; + case InspectMapTreeInfoOp::OriginalEncounterSteps: + return map_info.encounter_steps; + case InspectMapTreeInfoOp::CountTroops: + return map_info.encounters.size();; + case InspectMapTreeInfoOp::CountArenas: + { + int cnt_arenas = 0; + for (unsigned int i = 0; i < lcf::Data::treemap.maps.size(); ++i) { + auto& map = lcf::Data::treemap.maps[i]; + if (map.parent_map == map_info.ID && map.type == lcf::rpg::TreeMap::MapType_area) { + cnt_arenas++; + } + } + return cnt_arenas; + } + case InspectMapTreeInfoOp::Troop_Id: + { + // TODO: provide a way to conveniently copy values into a range of variables ("ControlVarArrayEx"?) + if (arg1 >= 0 && arg1 < map_info.encounters.size()) { + return map_info.encounters[arg1].troop_id; + } + return 0; + } + case InspectMapTreeInfoOp::Arena_Top: + case InspectMapTreeInfoOp::Arena_Left: + case InspectMapTreeInfoOp::Arena_Bottom: + case InspectMapTreeInfoOp::Arena_Right: + case InspectMapTreeInfoOp::Arena_Width: + case InspectMapTreeInfoOp::Arena_Height: + { + // TODO: provide a way to conveniently copy values into a range of variables ("ControlVarArrayEx"?) + if (arg1 < 0) { + return 0; + } + + int cnt_arenas = 0; + for (unsigned int i = 0; i < lcf::Data::treemap.maps.size(); ++i) { + auto& map = lcf::Data::treemap.maps[i]; + if (map.parent_map == map_info.ID && map.type == lcf::rpg::TreeMap::MapType_area) { + if (arg1 < cnt_arenas) { + cnt_arenas++; + continue; + } + switch (op) + { + case InspectMapTreeInfoOp::Arena_Top: + return map.area_rect.t; + case InspectMapTreeInfoOp::Arena_Left: + return map.area_rect.l; + case InspectMapTreeInfoOp::Arena_Bottom: + return map.area_rect.b; + case InspectMapTreeInfoOp::Arena_Right: + return map.area_rect.r; + case InspectMapTreeInfoOp::Arena_Width: + return map.area_rect.r - map.area_rect.l; + case InspectMapTreeInfoOp::Arena_Height: + return map.area_rect.b - map.area_rect.t; + } + } + } + return 0; + } + } + + Output::Warning("ControlVariables::InspectMapTreeInfo: Unknown op {}", static_cast(op)); + return 0; +} diff --git a/src/game_interpreter_control_variables.h b/src/game_interpreter_control_variables.h index 37916d61b9..de927581c6 100644 --- a/src/game_interpreter_control_variables.h +++ b/src/game_interpreter_control_variables.h @@ -49,7 +49,7 @@ namespace ControlVariables { // // New EasyRpgEx operations // - bool EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& value); + bool EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& value, const Game_BaseInterpreterContext& interpreter); enum class DateTimeOp { Year = 0, @@ -76,6 +76,29 @@ namespace ControlVariables { "gettimestamp" ); int DateTime(DateTimeOp op); + + enum ActiveMapInfoOp { + MapTileWidth = 0, + MapTileHeight, + LoopHorizontal, + LoopVertical + }; + int ActiveMapInfo(ActiveMapInfoOp op); + + enum InspectMapTreeInfoOp { + ParentMap = 0, + OriginalEncounterSteps, + CountTroops, + CountArenas, + Troop_Id, + Arena_Top, + Arena_Left, + Arena_Bottom, + Arena_Right, + Arena_Width, + Arena_Height + }; + int InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, int arg1); } #endif From 9e69975d306e33949ff0e30b263701706e1bb0f3 Mon Sep 17 00:00:00 2001 From: florianessl Date: Sat, 1 Feb 2025 18:32:09 +0100 Subject: [PATCH 3/5] ControlVariablesEx NewFeature: Get information about configured window settings & active message windows --- src/game_interpreter_control_variables.cpp | 67 ++++++++++++++++++++++ src/game_interpreter_control_variables.h | 23 ++++++++ 2 files changed, 90 insertions(+) diff --git a/src/game_interpreter_control_variables.cpp b/src/game_interpreter_control_variables.cpp index a098a804f2..3452211bc4 100644 --- a/src/game_interpreter_control_variables.cpp +++ b/src/game_interpreter_control_variables.cpp @@ -22,10 +22,12 @@ #include "game_ineluki.h" #include "game_interpreter.h" #include "game_map.h" +#include "game_message.h" #include "game_party.h" #include "game_player.h" #include "game_system.h" #include "main_data.h" +#include "window_message.h" #include "output.h" #include "player.h" #include "rand.h" @@ -528,6 +530,12 @@ bool ControlVariables::EasyRpgExCommand(lcf::rpg::EventCommand const& com, int& value = InspectMapTreeInfo(static_cast(com.parameters[5]), map_id, arg1); break; } + case 213: //eVarOperand_EasyRpg_MessageSystemState + value = MessageSystemState(static_cast(com.parameters[5])); + break; + case 214: //eVarOperand_EasyRpg_MessageWindowState + value = MessageWindowState(static_cast(com.parameters[5])); + break; default: Output::Warning("ControlVariables: Unsupported operand {}", com.parameters[5]); return false; @@ -662,3 +670,62 @@ int ControlVariables::InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, in Output::Warning("ControlVariables::InspectMapTreeInfo: Unknown op {}", static_cast(op)); return 0; } + +int ControlVariables::MessageSystemState(MessageSystemStateOp op) { + switch (op) + { + case MessageSystemStateOp::IsMessageTransparent: + return Main_Data::game_system->IsMessageTransparent(); + case MessageSystemStateOp::IsMessagePositionFixed: + return Main_Data::game_system->IsMessagePositionFixed(); + case MessageSystemStateOp::IsContinueEvents: + return Main_Data::game_system->GetMessageContinueEvents(); + case MessageSystemStateOp::MessagePosition: + return Main_Data::game_system->GetMessagePosition(); + case MessageSystemStateOp::IsMessageFaceRightPosition: + return Main_Data::game_system->IsMessageFaceRightPosition(); + } + + Output::Warning("ControlVariables::MessageSystemState: Unknown op {}", static_cast(op)); + return 0; +} + +int ControlVariables::MessageWindowState(MessageWindowStateOp op) { + if (op == MessageWindowStateOp::IsMessageActive) { + return Game_Message::IsMessageActive(); + } + + auto* window = Game_Message::GetWindow(); + if (window) { + switch (op) + { + case MessageWindowStateOp::IsFaceActive: + return window->GetPendingMessage().IsFaceEnabled() && !Main_Data::game_system->GetMessageFaceName().empty(); + case MessageWindowStateOp::CanContinue: + return !window->GetPause(); + case MessageWindowStateOp::WindowTop: + return window->GetY(); + case MessageWindowStateOp::WindowLeft: + return window->GetX(); + case MessageWindowStateOp::WindowBottom: + return window->GetY() + window->GetHeight(); + case MessageWindowStateOp::WindowRight: + return window->GetX() + window->GetWidth(); + case MessageWindowStateOp::WindowWidth: + return window->GetWidth(); + case MessageWindowStateOp::WindowHeight: + return window->GetHeight(); + case MessageWindowStateOp::WindowType: + if (window->GetPendingMessage().HasChoices()) + return 1; + if (window->GetPendingMessage().HasNumberInput()) + return 2; + if (window->GetPendingMessage().ShowGoldWindow()) + return 3; + return 0; + } + } + + Output::Warning("ControlVariables::MessageWindowState: Unknown op {}", static_cast(op)); + return 0; +} diff --git a/src/game_interpreter_control_variables.h b/src/game_interpreter_control_variables.h index de927581c6..8c64d4f6f4 100644 --- a/src/game_interpreter_control_variables.h +++ b/src/game_interpreter_control_variables.h @@ -99,6 +99,29 @@ namespace ControlVariables { Arena_Height }; int InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, int arg1); + + enum MessageSystemStateOp { + IsMessageTransparent = 0, + IsMessagePositionFixed, + IsContinueEvents, + MessagePosition, + IsMessageFaceRightPosition + }; + int MessageSystemState(MessageSystemStateOp op); + + enum MessageWindowStateOp { + IsMessageActive = 0, + IsFaceActive, + CanContinue, + WindowTop, + WindowLeft, + WindowBottom, + WindowRight, + WindowWidth, + WindowHeight, + WindowType + }; + int MessageWindowState(MessageWindowStateOp op); } #endif From 6f9fedb3579312cccc725732fe197dbd020e36e5 Mon Sep 17 00:00:00 2001 From: florianessl Date: Sat, 1 Feb 2025 18:43:40 +0100 Subject: [PATCH 4/5] Fix GCC compiler's warnings. --- src/game_interpreter_control_variables.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/game_interpreter_control_variables.cpp b/src/game_interpreter_control_variables.cpp index 3452211bc4..369222ad90 100644 --- a/src/game_interpreter_control_variables.cpp +++ b/src/game_interpreter_control_variables.cpp @@ -621,7 +621,7 @@ int ControlVariables::InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, in case InspectMapTreeInfoOp::Troop_Id: { // TODO: provide a way to conveniently copy values into a range of variables ("ControlVarArrayEx"?) - if (arg1 >= 0 && arg1 < map_info.encounters.size()) { + if (arg1 >= 0 && arg1 < static_cast(map_info.encounters.size())) { return map_info.encounters[arg1].troop_id; } return 0; @@ -660,6 +660,8 @@ int ControlVariables::InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, in return map.area_rect.r - map.area_rect.l; case InspectMapTreeInfoOp::Arena_Height: return map.area_rect.b - map.area_rect.t; + default: + break; } } } @@ -723,6 +725,8 @@ int ControlVariables::MessageWindowState(MessageWindowStateOp op) { if (window->GetPendingMessage().ShowGoldWindow()) return 3; return 0; + case MessageWindowStateOp::IsMessageActive: + break; } } From b92572d479ac010d9998624c49b27dc96582527a Mon Sep 17 00:00:00 2001 From: florianessl Date: Sat, 1 Feb 2025 20:45:36 +0100 Subject: [PATCH 5/5] InspectMapTreeInfo fix: LMU data indexes need to start at 1 --- src/game_interpreter_control_variables.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game_interpreter_control_variables.cpp b/src/game_interpreter_control_variables.cpp index 369222ad90..e8e5c7f860 100644 --- a/src/game_interpreter_control_variables.cpp +++ b/src/game_interpreter_control_variables.cpp @@ -621,8 +621,8 @@ int ControlVariables::InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, in case InspectMapTreeInfoOp::Troop_Id: { // TODO: provide a way to conveniently copy values into a range of variables ("ControlVarArrayEx"?) - if (arg1 >= 0 && arg1 < static_cast(map_info.encounters.size())) { - return map_info.encounters[arg1].troop_id; + if (arg1 >= 1 && arg1 <= static_cast(map_info.encounters.size())) { + return map_info.encounters[arg1 - 1].troop_id; } return 0; } @@ -634,7 +634,7 @@ int ControlVariables::InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, in case InspectMapTreeInfoOp::Arena_Height: { // TODO: provide a way to conveniently copy values into a range of variables ("ControlVarArrayEx"?) - if (arg1 < 0) { + if (arg1 <= 0) { return 0; } @@ -642,7 +642,7 @@ int ControlVariables::InspectMapTreeInfo(InspectMapTreeInfoOp op, int map_id, in for (unsigned int i = 0; i < lcf::Data::treemap.maps.size(); ++i) { auto& map = lcf::Data::treemap.maps[i]; if (map.parent_map == map_info.ID && map.type == lcf::rpg::TreeMap::MapType_area) { - if (arg1 < cnt_arenas) { + if (arg1 <= cnt_arenas) { cnt_arenas++; continue; }