From 58bef9292091aaf1c2f92705cd60d8d2e4c1cb32 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Thu, 1 Nov 2018 21:03:47 -0400 Subject: [PATCH 1/2] Refactor Switches and Variables * No more count fields * Variables are signed * Reads don't resize the array * Writes to id <= 0 silently do nothing. * Writes to any value N > 0, even > 5000 actually work. It writes a value which is saved to LSD and can be read back. This works in RPG_RT to enable any number of variables. * Matches RPG_RT behavior and written to LSD in same way * Always clamp in Game_Variable::set() --- src/game_battle.cpp | 6 +-- src/game_battlealgorithm.cpp | 6 +-- src/game_battler.cpp | 2 +- src/game_character.cpp | 4 +- src/game_commonevent.cpp | 4 +- src/game_enemy.cpp | 2 +- src/game_event.cpp | 18 +++---- src/game_interpreter.cpp | 96 ++++++++++++++------------------- src/game_interpreter_battle.cpp | 10 ++-- src/game_interpreter_map.cpp | 6 +-- src/game_map.cpp | 2 +- src/game_player.cpp | 2 +- src/game_switches.cpp | 42 +++++++-------- src/game_switches.h | 11 ++-- src/game_variables.cpp | 46 ++++++++-------- src/game_variables.h | 7 ++- src/scene_debug.cpp | 6 +-- src/scene_item.cpp | 4 +- src/window_message.cpp | 8 ++- src/window_varlist.cpp | 4 +- 20 files changed, 134 insertions(+), 152 deletions(-) diff --git a/src/game_battle.cpp b/src/game_battle.cpp index 83bab82c57..36b8e381d1 100644 --- a/src/game_battle.cpp +++ b/src/game_battle.cpp @@ -276,13 +276,13 @@ bool Game_Battle::AreConditionsMet(const RPG::TroopPageCondition& condition) { return false; } - if (condition.flags.switch_a && !Game_Switches[condition.switch_a_id]) + if (condition.flags.switch_a && !Game_Switches.Get(condition.switch_a_id)) return false; - if (condition.flags.switch_b && !Game_Switches[condition.switch_b_id]) + if (condition.flags.switch_b && !Game_Switches.Get(condition.switch_b_id)) return false; - if (condition.flags.variable && !(Game_Variables[condition.variable_id] >= condition.variable_value)) + if (condition.flags.variable && !(Game_Variables.Get(condition.variable_id) >= condition.variable_value)) return false; if (condition.flags.turn && !CheckTurns(GetTurn(), condition.turn_b, condition.turn_a)) diff --git a/src/game_battlealgorithm.cpp b/src/game_battlealgorithm.cpp index 1f9e982606..e2684c1b94 100644 --- a/src/game_battlealgorithm.cpp +++ b/src/game_battlealgorithm.cpp @@ -578,7 +578,7 @@ void Game_BattleAlgorithm::AlgorithmBase::Apply() { } if (GetAffectedSwitch() != -1) { - Game_Switches[GetAffectedSwitch()] = true; + Game_Switches.Set(GetAffectedSwitch(), true); } std::vector::const_iterator it = conditions.begin(); @@ -607,11 +607,11 @@ void Game_BattleAlgorithm::AlgorithmBase::Apply() { void Game_BattleAlgorithm::AlgorithmBase::ApplyActionSwitches() { for (int s : switch_on) { - Game_Switches[s] = true; + Game_Switches.Set(s, true); } for (int s : switch_off) { - Game_Switches[s] = false; + Game_Switches.Set(s, false); } } diff --git a/src/game_battler.cpp b/src/game_battler.cpp index 9d8bfbd4de..8c8eb79aa5 100644 --- a/src/game_battler.cpp +++ b/src/game_battler.cpp @@ -316,7 +316,7 @@ bool Game_Battler::UseSkill(int skill_id) { was_used = true; } else if (skill->type == RPG::Skill::Type_switch) { Game_System::SePlay(skill->sound_effect); - Game_Switches[skill->switch_id] = true; + Game_Switches.Set(skill->switch_id, true); was_used = true; } diff --git a/src/game_character.cpp b/src/game_character.cpp index bda42e1b80..afc51be6ba 100644 --- a/src/game_character.cpp +++ b/src/game_character.cpp @@ -371,12 +371,12 @@ void Game_Character::MoveTypeCustom() { SetMoveFrequency(max(GetMoveFrequency() - 1, 1)); break; case RPG::MoveCommand::Code::switch_on: // Parameter A: Switch to turn on - Game_Switches[move_command.parameter_a] = true; + Game_Switches.Set(move_command.parameter_a, true); Game_Map::SetNeedRefresh(Game_Map::Refresh_All); Game_Map::Refresh(); break; case RPG::MoveCommand::Code::switch_off: // Parameter A: Switch to turn off - Game_Switches[move_command.parameter_a] = false; + Game_Switches.Set(move_command.parameter_a, false); Game_Map::SetNeedRefresh(Game_Map::Refresh_All); Game_Map::Refresh(); break; diff --git a/src/game_commonevent.cpp b/src/game_commonevent.cpp index 56f9d4da86..64d9cbb587 100644 --- a/src/game_commonevent.cpp +++ b/src/game_commonevent.cpp @@ -38,7 +38,7 @@ void Game_CommonEvent::SetSaveData(const RPG::SaveEventData& data) { void Game_CommonEvent::Refresh() { if (GetTrigger() == RPG::EventPage::Trigger_parallel) { - if (GetSwitchFlag() ? Game_Switches[GetSwitchId()] : true) { + if (GetSwitchFlag() ? Game_Switches.Get(GetSwitchId()) : true) { if (!interpreter) { interpreter.reset(new Game_Interpreter_Map()); } @@ -54,7 +54,7 @@ void Game_CommonEvent::Update() { return; for (int i = 0; i < 500; ++i) { - if (GetSwitchFlag() ? Game_Switches[GetSwitchId()] : true) { + if (GetSwitchFlag() ? Game_Switches.Get(GetSwitchId()) : true) { if (!Game_Map::GetInterpreter().IsRunning()) { Game_Map::GetInterpreter().Setup(this, 0); Game_Map::GetInterpreter().Update(); diff --git a/src/game_enemy.cpp b/src/game_enemy.cpp index 7c4058a300..3d4ad7f2d6 100644 --- a/src/game_enemy.cpp +++ b/src/game_enemy.cpp @@ -261,7 +261,7 @@ bool Game_Enemy::IsActionValid(const RPG::EnemyAction& action) { case RPG::EnemyAction::ConditionType_always: return true; case RPG::EnemyAction::ConditionType_switch: - return Game_Switches[action.switch_id]; + return Game_Switches.Get(action.switch_id); case RPG::EnemyAction::ConditionType_turn: { int turns = Game_Battle::GetTurn(); diff --git a/src/game_event.cpp b/src/game_event.cpp index df350ee0b2..7c2135afef 100644 --- a/src/game_event.cpp +++ b/src/game_event.cpp @@ -372,45 +372,45 @@ void Game_Event::Refresh() { bool Game_Event::AreConditionsMet(const RPG::EventPage& page) { // First switch (A) - if (page.condition.flags.switch_a && !Game_Switches[page.condition.switch_a_id]) { + if (page.condition.flags.switch_a && !Game_Switches.Get(page.condition.switch_a_id)) { return false; } // Second switch (B) - if (page.condition.flags.switch_b && !Game_Switches[page.condition.switch_b_id]) { + if (page.condition.flags.switch_b && !Game_Switches.Get(page.condition.switch_b_id)) { return false; } // Variable if (Player::IsRPG2k()) { - if (page.condition.flags.variable && !(Game_Variables[page.condition.variable_id] >= page.condition.variable_value)) { + if (page.condition.flags.variable && !(Game_Variables.Get(page.condition.variable_id) >= page.condition.variable_value)) { return false; } } else { if (page.condition.flags.variable) { switch (page.condition.compare_operator) { case 0: // == - if (!(Game_Variables[page.condition.variable_id] == page.condition.variable_value)) + if (!(Game_Variables.Get(page.condition.variable_id) == page.condition.variable_value)) return false; break; case 1: // >= - if (!(Game_Variables[page.condition.variable_id] >= page.condition.variable_value)) + if (!(Game_Variables.Get(page.condition.variable_id) >= page.condition.variable_value)) return false; break; case 2: // <= - if (!(Game_Variables[page.condition.variable_id] <= page.condition.variable_value)) + if (!(Game_Variables.Get(page.condition.variable_id) <= page.condition.variable_value)) return false; break; case 3: // > - if (!(Game_Variables[page.condition.variable_id] > page.condition.variable_value)) + if (!(Game_Variables.Get(page.condition.variable_id) > page.condition.variable_value)) return false; break; case 4: // < - if (!(Game_Variables[page.condition.variable_id] < page.condition.variable_value)) + if (!(Game_Variables.Get(page.condition.variable_id) < page.condition.variable_value)) return false; break; case 5: // != - if (!(Game_Variables[page.condition.variable_id] != page.condition.variable_value)) + if (!(Game_Variables.Get(page.condition.variable_id) != page.condition.variable_value)) return false; break; } diff --git a/src/game_interpreter.cpp b/src/game_interpreter.cpp index 49c9f39f64..31082bed4c 100644 --- a/src/game_interpreter.cpp +++ b/src/game_interpreter.cpp @@ -52,11 +52,6 @@ #include "transition.h" namespace { - constexpr int max_var_size_2k3 = 9999999; - constexpr int min_var_size_2k3 = -max_var_size_2k3; - constexpr int max_var_size_2k = 999999; - constexpr int min_var_size_2k = -max_var_size_2k; - // Used to ensure that the interpreter that runs after a Erase/ShowScreen // is the invoker of the transition static Game_Interpreter* transition_owner = nullptr; @@ -727,14 +722,14 @@ bool Game_Interpreter::CommandControlSwitches(RPG::EventCommand const& com) { // // Param0: 0: Single, 1: Range, 2: Indirect // For Range set end to param 2, otherwise to start, this way the loop runs exactly once - int start = com.parameters[0] == 2 ? Game_Variables[com.parameters[1]] : com.parameters[1]; + int start = com.parameters[0] == 2 ? Game_Variables.Get(com.parameters[1]) : com.parameters[1]; int end = com.parameters[0] == 1 ? com.parameters[2] : start; for (int i = start; i <= end; ++i) { if (com.parameters[3] != 2) { - Game_Switches[i] = com.parameters[3] == 0; + Game_Switches.Set(i, com.parameters[3] == 0); } else { - Game_Switches[i] = !Game_Switches[i]; + Game_Switches.Flip(i); } } @@ -757,11 +752,11 @@ bool Game_Interpreter::CommandControlVariables(RPG::EventCommand const& com) { / break; case 1: // Var A ops B - value = Game_Variables[com.parameters[5]]; + value = Game_Variables.Get(com.parameters[5]); break; case 2: // Number of var A ops B - value = Game_Variables[Game_Variables[com.parameters[5]]]; + value = Game_Variables.Get(Game_Variables.Get(com.parameters[5])); break; case 3: // Random between range @@ -981,50 +976,41 @@ bool Game_Interpreter::CommandControlVariables(RPG::EventCommand const& com) { / // Param0: 0: Single, 1: Range, 2: Indirect // For Range set end to param 2, otherwise to start, this way the loop runs exactly once - int start = com.parameters[0] == 2 ? Game_Variables[com.parameters[1]] : com.parameters[1]; + int start = com.parameters[0] == 2 ? Game_Variables.Get(com.parameters[1]) : com.parameters[1]; int end = com.parameters[0] == 1 ? com.parameters[2] : start; for (i = start; i <= end; ++i) { switch (com.parameters[3]) { case 0: // Assignement - Game_Variables[i] = value; + Game_Variables.Set(i, value); break; case 1: // Addition - Game_Variables[i] += value; + Game_Variables.Set(i, Game_Variables.Get(i) + value); break; case 2: // Subtraction - Game_Variables[i] -= value; + Game_Variables.Set(i, Game_Variables.Get(i) - value); break; case 3: // Multiplication - Game_Variables[i] *= value; + Game_Variables.Set(i, Game_Variables.Get(i) * value); break; case 4: // Division if (value != 0) { - Game_Variables[i] /= value; + Game_Variables.Set(i, Game_Variables.Get(i) / value); } break; case 5: // Module if (value != 0) { - Game_Variables[i] %= value; + Game_Variables.Set(i, Game_Variables.Get(i) % value); } else { - Game_Variables[i] = 0; + Game_Variables.Set(i, 0); } } - - // Clamp to variable range - if (Player::IsRPG2k3()) { - Game_Variables[i] = std::max( - std::min(Game_Variables[i], max_var_size_2k3), min_var_size_2k3); - } else { - Game_Variables[i] = std::max( - std::min(Game_Variables[i], max_var_size_2k), min_var_size_2k); - } } Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); @@ -1039,7 +1025,7 @@ int Game_Interpreter::OperateValue(int operation, int operand_type, int operand) if (operand_type == 0) { value = operand; } else { - value = Game_Variables[operand]; + value = Game_Variables.Get(operand); } // Reverse sign of value if operation is substract @@ -1072,9 +1058,9 @@ std::vector Game_Interpreter::GetActors(int mode, int id) { break; case 2: // Var hero - actor = Game_Actors::GetActor(Game_Variables[id]); + actor = Game_Actors::GetActor(Game_Variables.Get(id)); if (!actor) { - Output::Warning("Invalid actor ID %d", Game_Variables[id]); + Output::Warning("Invalid actor ID %d", Game_Variables.Get(id)); return actors; } @@ -1169,7 +1155,7 @@ bool Game_Interpreter::CommandChangeItems(RPG::EventCommand const& com) { // Cod } else { // Item by variable Main_Data::game_party->AddItem( - Game_Variables[com.parameters[2]], + Game_Variables.Get(com.parameters[2]), value ); } @@ -1185,7 +1171,7 @@ bool Game_Interpreter::CommandChangePartyMember(RPG::EventCommand const& com) { if (com.parameters[1] == 0) { id = com.parameters[2]; } else { - id = Game_Variables[com.parameters[2]]; + id = Game_Variables.Get(com.parameters[2]); } actor = Game_Actors::GetActor(id); @@ -1245,7 +1231,7 @@ int Game_Interpreter::ValueOrVariable(int mode, int val) { case 0: return val; case 1: - return Game_Variables[val]; + return Game_Variables.Get(val); default: return -1; } @@ -1471,7 +1457,7 @@ bool Game_Interpreter::CommandSimulatedAttack(RPG::EventCommand const& com) { // CheckGameOver(); if (com.parameters[6] != 0) { - Game_Variables[com.parameters[7]] = result; + Game_Variables.Set(com.parameters[7], result); Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); } } @@ -1661,9 +1647,9 @@ bool Game_Interpreter::CommandMemorizeLocation(RPG::EventCommand const& com) { / int var_map_id = com.parameters[0]; int var_x = com.parameters[1]; int var_y = com.parameters[2]; - Game_Variables[var_map_id] = Game_Map::GetMapId(); - Game_Variables[var_x] = player->GetX(); - Game_Variables[var_y] = player->GetY(); + Game_Variables.Set(var_map_id, Game_Map::GetMapId()); + Game_Variables.Set(var_x, player->GetX()); + Game_Variables.Set(var_y, player->GetY()); Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); return true; } @@ -1775,7 +1761,7 @@ bool Game_Interpreter::CommandStoreTerrainID(RPG::EventCommand const& com) { // int x = ValueOrVariable(com.parameters[0], com.parameters[1]); int y = ValueOrVariable(com.parameters[0], com.parameters[2]); int var_id = com.parameters[3]; - Game_Variables[var_id] = Game_Map::GetTerrainTag(x, y); + Game_Variables.Set(var_id, Game_Map::GetTerrainTag(x, y)); Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); return true; } @@ -1786,7 +1772,7 @@ bool Game_Interpreter::CommandStoreEventID(RPG::EventCommand const& com) { // co int var_id = com.parameters[3]; std::vector events; Game_Map::GetEventsXY(events, x, y); - Game_Variables[var_id] = events.size() > 0 ? events.back()->GetId() : 0; + Game_Variables.Set(var_id, events.size() > 0 ? events.back()->GetId() : 0); Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); return true; } @@ -2057,9 +2043,9 @@ namespace PicPointerPatch { if (pic_id > 10000) { int new_id; if (pic_id > 50000) { - new_id = Game_Variables[pic_id - 50000]; + new_id = Game_Variables.Get(pic_id - 50000); } else { - new_id = Game_Variables[pic_id - 10000]; + new_id = Game_Variables.Get(pic_id - 10000); } if (new_id > 0) { @@ -2071,19 +2057,19 @@ namespace PicPointerPatch { static void AdjustParams(Game_Picture::Params& params) { if (params.magnify > 10000) { - int new_magnify = Game_Variables[params.magnify - 10000]; + int new_magnify = Game_Variables.Get(params.magnify - 10000); Output::Debug("PicPointer: Zoom %d replaced with %d", params.magnify, new_magnify); params.magnify = new_magnify; } if (params.top_trans > 10000) { - int new_top_trans = Game_Variables[params.top_trans - 10000]; + int new_top_trans = Game_Variables.Get(params.top_trans - 10000); Output::Debug("PicPointer: Top transparency %d replaced with %d", params.top_trans, new_top_trans); params.top_trans = new_top_trans; } if (params.bottom_trans > 10000) { - int new_bottom_trans = Game_Variables[params.bottom_trans - 10000]; + int new_bottom_trans = Game_Variables.Get(params.bottom_trans - 10000); Output::Debug("PicPointer: Bottom transparency %d replaced with %d", params.bottom_trans, new_bottom_trans); params.bottom_trans = new_bottom_trans; } @@ -2119,7 +2105,7 @@ namespace PicPointerPatch { // Adjust name if (pic_id >= 50000) { // Name substitution is pic_id + 1 - int pic_num = Game_Variables[pic_id - 50000 + 1]; + int pic_num = Game_Variables.Get(pic_id - 50000 + 1); if (pic_num >= 0) { params.name = ReplaceName(params.name, pic_num, 4); @@ -2135,7 +2121,7 @@ namespace PicPointerPatch { AdjustParams(params); if (params.duration > 10000) { - int new_duration = Game_Variables[params.duration - 10000]; + int new_duration = Game_Variables.Get(params.duration - 10000); Output::Debug("PicPointer: Move duration %d replaced with %d", params.duration, new_duration); params.duration = new_duration; } @@ -2175,7 +2161,7 @@ bool Game_Interpreter::CommandShowPicture(RPG::EventCommand const& com) { // cod if (com.parameters[19] != 0) { int var = 0; if (Game_Variables.IsValid(com.parameters[19])) { - var = Game_Variables[com.parameters[19]]; + var = Game_Variables.Get(com.parameters[19]); } params.name = PicPointerPatch::ReplaceName(params.name, var, com.parameters[18]); } @@ -2364,7 +2350,7 @@ bool Game_Interpreter::CommandKeyInputProc(RPG::EventCommand const& com) { // co if (wait) { // While waiting the variable is reset to 0 every frame - Game_Variables[var_id] = 0; + Game_Variables.Set(var_id, 0); Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); } @@ -2459,7 +2445,7 @@ bool Game_Interpreter::CommandKeyInputProc(RPG::EventCommand const& com) { // co } if (var_id > 0) { - Game_Variables[var_id] = result; + Game_Variables.Set(var_id, result); Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); } @@ -2473,7 +2459,7 @@ bool Game_Interpreter::CommandKeyInputProc(RPG::EventCommand const& com) { // co if (time) { // 10 per second - Game_Variables[time_id] = (int)((float)button_timer / Graphics::GetDefaultFps() * 10); + Game_Variables.Set(time_id, (int)((float)button_timer / Graphics::GetDefaultFps() * 10)); } button_timer = 0; @@ -2597,15 +2583,15 @@ bool Game_Interpreter::CommandConditionalBranch(RPG::EventCommand const& com) { switch (com.parameters[0]) { case 0: // Switch - result = Game_Switches[com.parameters[1]] == (com.parameters[2] == 0); + result = Game_Switches.Get(com.parameters[1]) == (com.parameters[2] == 0); break; case 1: // Variable - value1 = Game_Variables[com.parameters[1]]; + value1 = Game_Variables.Get(com.parameters[1]); if (com.parameters[2] == 0) { value2 = com.parameters[3]; } else { - value2 = Game_Variables[com.parameters[3]]; + value2 = Game_Variables.Get(com.parameters[3]); } switch (com.parameters[4]) { case 0: @@ -2884,8 +2870,8 @@ bool Game_Interpreter::CommandCallEvent(RPG::EventCommand const& com) { // code event_page = com.parameters[2]; break; case 2: // Indirect - evt_id = Game_Variables[com.parameters[1]]; - event_page = Game_Variables[com.parameters[2]]; + evt_id = Game_Variables.Get(com.parameters[1]); + event_page = Game_Variables.Get(com.parameters[2]); break; default: return false; diff --git a/src/game_interpreter_battle.cpp b/src/game_interpreter_battle.cpp index f403dbcd9a..02e14da2cd 100644 --- a/src/game_interpreter_battle.cpp +++ b/src/game_interpreter_battle.cpp @@ -171,7 +171,7 @@ bool Game_Interpreter_Battle::CommandChangeMonsterHP(RPG::EventCommand const& co change = com.parameters[3]; break; case 1: - change = Game_Variables[com.parameters[3]]; + change = Game_Variables.Get(com.parameters[3]); break; case 2: change = com.parameters[3] * hp / 100; @@ -203,7 +203,7 @@ bool Game_Interpreter_Battle::CommandChangeMonsterMP(RPG::EventCommand const& co change = com.parameters[3]; break; case 1: - change = Game_Variables[com.parameters[3]]; + change = Game_Variables.Get(com.parameters[3]); break; } @@ -311,15 +311,15 @@ bool Game_Interpreter_Battle::CommandConditionalBranchBattle(RPG::EventCommand c switch (com.parameters[0]) { case 0: // Switch - result = Game_Switches[com.parameters[1]] == (com.parameters[2] == 0); + result = Game_Switches.Get(com.parameters[1]) == (com.parameters[2] == 0); break; case 1: // Variable - value1 = Game_Variables[com.parameters[1]]; + value1 = Game_Variables.Get(com.parameters[1]); if (com.parameters[2] == 0) { value2 = com.parameters[3]; } else { - value2 = Game_Variables[com.parameters[3]]; + value2 = Game_Variables.Get(com.parameters[3]); } switch (com.parameters[4]) { case 0: diff --git a/src/game_interpreter_map.cpp b/src/game_interpreter_map.cpp index e03e0f1321..b9d7b34839 100644 --- a/src/game_interpreter_map.cpp +++ b/src/game_interpreter_map.cpp @@ -198,9 +198,9 @@ bool Game_Interpreter_Map::CommandRecallToLocation(RPG::EventCommand const& com) int var_map_id = com.parameters[0]; int var_x = com.parameters[1]; int var_y = com.parameters[2]; - int map_id = Game_Variables[var_map_id]; - int x = Game_Variables[var_x]; - int y = Game_Variables[var_y]; + int map_id = Game_Variables.Get(var_map_id); + int x = Game_Variables.Get(var_x); + int y = Game_Variables.Get(var_y); if (map_id == Game_Map::GetMapId()) { player->MoveTo(x, y); diff --git a/src/game_map.cpp b/src/game_map.cpp index db3997e9d0..7407911897 100644 --- a/src/game_map.cpp +++ b/src/game_map.cpp @@ -1218,7 +1218,7 @@ bool Game_Map::IsAnyEventStarting() { for (Game_CommonEvent& ev : common_events) if ((ev.GetTrigger() == RPG::EventPage::Trigger_auto_start) && - (ev.GetSwitchFlag() ? Game_Switches[ev.GetSwitchId()] : true) && + (ev.GetSwitchFlag() ? Game_Switches.Get(ev.GetSwitchId()) : true) && (!ev.GetList().empty())) return true; diff --git a/src/game_player.cpp b/src/game_player.cpp index 00db8baed8..bed45ec211 100644 --- a/src/game_player.cpp +++ b/src/game_player.cpp @@ -236,7 +236,7 @@ void Game_Player::ReserveTeleport(const RPG::SaveTarget& target) { ReserveTeleport(map_id, target.map_x, target.map_y, Down); if (target.switch_on) { - Game_Switches[target.switch_id] = true; + Game_Switches.Set(target.switch_id, true); Game_Map::SetNeedRefresh(Game_Map::Refresh_All); } } diff --git a/src/game_switches.cpp b/src/game_switches.cpp index 75b26b8acf..a68bb29918 100644 --- a/src/game_switches.cpp +++ b/src/game_switches.cpp @@ -21,34 +21,33 @@ #include "output.h" #include "reader_util.h" -#define PLAYER_VAR_LIMIT 1000000 - Game_Switches_Class::Game_Switches_Class() {} static std::vector& switches() { return Main_Data::game_data.system.switches; } -static int resize_report_limit = 10; +bool Game_Switches_Class::Get(int switch_id) const { + auto& sv = switches(); + if (switch_id <= 0 || switch_id > sv.size()) { + return false; + } + return sv[switch_id - 1]; +} -std::vector::reference Game_Switches_Class::operator[](int switch_id) { - if (!IsValid(switch_id)) { - if (switch_id > 0 && switch_id <= PLAYER_VAR_LIMIT) { - if (resize_report_limit > 0) { - Output::Debug("Resizing switch array to %d elements.", switch_id); - --resize_report_limit; - } - switches().reserve(switch_id + 1000); - switches().resize(switch_id); - Main_Data::game_data.system.switches_size = switches().size(); - } else { - Output::Debug("Switch index %d is invalid.", switch_id); - dummy.resize(1); - return dummy[0]; - } +void Game_Switches_Class::Set(int switch_id, bool value) { + auto& sv = switches(); + if (switch_id <= 0) { + return; } + if (switch_id > sv.size()) { + sv.resize(switch_id); + } + sv[switch_id - 1] = value; +} - return switches()[switch_id - 1]; +void Game_Switches_Class::Flip(int switch_id) { + Set(switch_id, !Get(switch_id)); } std::string Game_Switches_Class::GetName(int _id) const { @@ -63,7 +62,7 @@ std::string Game_Switches_Class::GetName(int _id) const { } bool Game_Switches_Class::IsValid(int switch_id) const { - return (switch_id > 0 && switch_id <= (int)switches().size()); + return switch_id > 0 && switch_id <= (int)Data::switches.size(); } int Game_Switches_Class::GetSize() const { @@ -71,6 +70,5 @@ int Game_Switches_Class::GetSize() const { } void Game_Switches_Class::Reset() { - resize_report_limit = 10; - switches().assign(Data::switches.size(), false); + switches().clear(); } diff --git a/src/game_switches.h b/src/game_switches.h index 1ccb5dcaf6..327a532884 100644 --- a/src/game_switches.h +++ b/src/game_switches.h @@ -29,9 +29,13 @@ class Game_Switches_Class { public: Game_Switches_Class(); - std::vector::reference operator[](int switch_id); - - std::string GetName(int _id) const; + bool Get(int switch_id) const; + + void Set(int switch_id, bool value); + + void Flip(int switch_id); + + std::string GetName(int switch_id) const; bool IsValid(int switch_id) const; @@ -43,6 +47,7 @@ class Game_Switches_Class { std::vector dummy; }; + // Global variable extern Game_Switches_Class Game_Switches; diff --git a/src/game_variables.cpp b/src/game_variables.cpp index 3765e9d9ad..b87f51b6a0 100644 --- a/src/game_variables.cpp +++ b/src/game_variables.cpp @@ -19,37 +19,34 @@ #include "game_variables.h" #include "main_data.h" #include "output.h" +#include "player.h" #include "reader_util.h" -#define PLAYER_VAR_LIMIT 1000000 - Game_Variables_Class::Game_Variables_Class() {} -static std::vector& variables() { +static std::vector& variables() { return Main_Data::game_data.system.variables; } -static int resize_report_limit = 10; - -int& Game_Variables_Class::operator[] (int variable_id) { - if (!IsValid(variable_id)) { - if (variable_id > 0 && variable_id <= PLAYER_VAR_LIMIT) { - if (resize_report_limit > 0) { - Output::Debug("Resizing variable array to %d elements.", variable_id); - --resize_report_limit; - } - variables().reserve(variable_id + 1000); - variables().resize(variable_id); - Main_Data::game_data.system.variables_size = variables().size(); - } else { - Output::Debug("Variable index %d is invalid.", - variable_id); - dummy = 0; - return dummy; - } +int Game_Variables_Class::Get(int variable_id) const { + auto& vv = variables(); + if (variable_id <= 0 || variable_id > vv.size()) { + return 0; } + return vv[variable_id - 1]; +} - return (int&)variables()[variable_id - 1]; +void Game_Variables_Class::Set(int variable_id, int value) { + auto& vv = variables(); + if (variable_id <= 0) { + return; + } + if (variable_id > vv.size()) { + vv.resize(variable_id); + } + const int maxval = Player::IsRPG2k3() ? 9999999 : 999999; + const int minval = Player::IsRPG2k3() ? -9999999 : -999999; + vv[variable_id - 1] = std::max(std::min(value, maxval), minval); } std::string Game_Variables_Class::GetName(int _id) const { @@ -64,7 +61,7 @@ std::string Game_Variables_Class::GetName(int _id) const { } bool Game_Variables_Class::IsValid(int variable_id) const { - return (variable_id > 0 && variable_id <= (int)variables().size()); + return variable_id > 0 && variable_id <= (int)Data::variables.size(); } int Game_Variables_Class::GetSize() const { @@ -72,6 +69,5 @@ int Game_Variables_Class::GetSize() const { } void Game_Variables_Class::Reset() { - resize_report_limit = 10; - variables().assign(Data::variables.size(), 0); + variables().clear(); } diff --git a/src/game_variables.h b/src/game_variables.h index 5ec14c3957..85526ea880 100644 --- a/src/game_variables.h +++ b/src/game_variables.h @@ -29,7 +29,9 @@ class Game_Variables_Class { public: Game_Variables_Class(); - int& operator[] (int variable_id); + int Get(int variable_id) const; + + void Set(int variable_id, int value); std::string GetName(int _id) const; @@ -38,9 +40,6 @@ class Game_Variables_Class { int GetSize() const; void Reset(); - -private: - int dummy = 0; }; // Global variable diff --git a/src/scene_debug.cpp b/src/scene_debug.cpp index dc59a40e2e..ae99eb4158 100644 --- a/src/scene_debug.cpp +++ b/src/scene_debug.cpp @@ -208,13 +208,13 @@ void Scene_Debug::Update() { switch (mode) { case eSwitch: if (Game_Switches.IsValid(GetIndex())) { - Game_Switches[GetIndex()] = !Game_Switches[GetIndex()]; + Game_Switches.Flip(GetIndex()); } break; case eVariable: if (Game_Variables.IsValid(GetIndex())) { var_window->SetActive(false); - numberinput_window->SetNumber(Game_Variables[GetIndex()]); + numberinput_window->SetNumber(Game_Variables.Get(GetIndex())); numberinput_window->SetShowOperator(true); numberinput_window->SetVisible(true); numberinput_window->SetActive(true); @@ -259,7 +259,7 @@ void Scene_Debug::Update() { var_window->Refresh(); } else if (numberinput_window->GetActive()) { if (mode == eVariable) { - Game_Variables[GetIndex()] = numberinput_window->GetNumber(); + Game_Variables.Set(GetIndex(), numberinput_window->GetNumber()); } else if (mode == eGold) { auto delta = numberinput_window->GetNumber() - Main_Data::game_party->GetGold(); Main_Data::game_party->GainGold(delta); diff --git a/src/scene_item.cpp b/src/scene_item.cpp index 5d7e232b02..361457dd88 100644 --- a/src/scene_item.cpp +++ b/src/scene_item.cpp @@ -66,7 +66,7 @@ void Scene_Item::Update() { if (item.type == RPG::Item::Type_switch) { Main_Data::game_party->ConsumeItemUse(item_id); - Game_Switches[item.switch_id] = true; + Game_Switches.Set(item.switch_id, true); Scene::PopUntil(Scene::Map); Game_Map::SetNeedRefresh(Game_Map::Refresh_All); } else if (item.type == RPG::Item::Type_special && item.skill_id > 0) { @@ -87,7 +87,7 @@ void Scene_Item::Update() { Scene::PopUntil(Scene::Map); } else if (skill->type == RPG::Skill::Type_switch) { Main_Data::game_party->ConsumeItemUse(item_id); - Game_Switches[skill->switch_id] = true; + Game_Switches.Set(skill->switch_id, true); Scene::PopUntil(Scene::Map); Game_Map::SetNeedRefresh(Game_Map::Refresh_All); } else { diff --git a/src/window_message.cpp b/src/window_message.cpp index 707983fb28..9677252390 100644 --- a/src/window_message.cpp +++ b/src/window_message.cpp @@ -613,10 +613,8 @@ std::string Window_Message::ParseCommandCode(bool& success, int& parameter) { case 'v': // Show Variable value parameter = ParseParameter(is_valid); - if (is_valid && Game_Variables.IsValid(parameter)) { - std::stringstream ss; - ss << Game_Variables[parameter]; - return ss.str(); + if (is_valid) { + return std::to_string(Game_Variables.Get(parameter)); } else { // Invalid Var is always 0 return "0"; @@ -685,7 +683,7 @@ void Window_Message::InputChoice() { void Window_Message::InputNumber() { if (Input::IsTriggered(Input::DECISION)) { Game_System::SePlay(Game_System::GetSystemSE(Game_System::SFX_Decision)); - Game_Variables[Game_Message::num_input_variable_id] = number_input_window->GetNumber(); + Game_Variables.Set(Game_Message::num_input_variable_id, number_input_window->GetNumber()); Game_Map::SetNeedRefresh(Game_Map::Refresh_Map); TerminateMessage(); number_input_window->SetNumber(0); diff --git a/src/window_varlist.cpp b/src/window_varlist.cpp index 061cf84848..c11037b860 100644 --- a/src/window_varlist.cpp +++ b/src/window_varlist.cpp @@ -52,7 +52,7 @@ void Window_VarList::DrawItemValue(int index){ switch (mode) { case eSwitch: { - auto value = Game_Switches[first_var + index]; + auto value = Game_Switches.Get(first_var + index); auto font = (!value) ? Font::ColorCritical : Font::ColorDefault; DrawItem(index, Font::ColorDefault); contents->TextDraw(GetWidth() - 16, 16 * index + 2, font, value ? "[ON]" : "[OFF]", Text::AlignRight); @@ -60,7 +60,7 @@ void Window_VarList::DrawItemValue(int index){ break; case eVariable: { - auto value = Game_Variables[first_var + index]; + auto value = Game_Variables.Get(first_var + index); auto font = (value < 0) ? Font::ColorCritical : Font::ColorDefault; DrawItem(index, Font::ColorDefault); contents->TextDraw(GetWidth() - 16, 16 * index + 2, font, std::to_string(value), Text::AlignRight); From 5ec72a498e7e9664adf4f6eda95501467820daa4 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Sun, 4 Nov 2018 07:51:25 -0500 Subject: [PATCH 2/2] Add debug logging when reading/writing to invalid switches and vars --- src/game_switches.cpp | 11 +++++++++++ src/game_switches.h | 2 +- src/game_variables.cpp | 11 +++++++++++ src/game_variables.h | 2 ++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/game_switches.cpp b/src/game_switches.cpp index a68bb29918..ecb2b52779 100644 --- a/src/game_switches.cpp +++ b/src/game_switches.cpp @@ -21,6 +21,8 @@ #include "output.h" #include "reader_util.h" +constexpr int kMaxWarnings = 10; + Game_Switches_Class::Game_Switches_Class() {} static std::vector& switches() { @@ -28,6 +30,10 @@ static std::vector& switches() { } bool Game_Switches_Class::Get(int switch_id) const { + if ((switch_id <= 0 || switch_id > Data::switches.size()) && _warnings < kMaxWarnings) { + Output::Debug("Invalid read sw[%d]!", switch_id); + ++_warnings; + } auto& sv = switches(); if (switch_id <= 0 || switch_id > sv.size()) { return false; @@ -36,6 +42,10 @@ bool Game_Switches_Class::Get(int switch_id) const { } void Game_Switches_Class::Set(int switch_id, bool value) { + if ((switch_id <= 0 || switch_id > Data::switches.size()) && _warnings < kMaxWarnings) { + Output::Debug("Invalid write sw[%d] = %d!", switch_id, value); + ++_warnings; + } auto& sv = switches(); if (switch_id <= 0) { return; @@ -71,4 +81,5 @@ int Game_Switches_Class::GetSize() const { void Game_Switches_Class::Reset() { switches().clear(); + _warnings = 0; } diff --git a/src/game_switches.h b/src/game_switches.h index 327a532884..32cbc6d659 100644 --- a/src/game_switches.h +++ b/src/game_switches.h @@ -44,7 +44,7 @@ class Game_Switches_Class { void Reset(); private: - std::vector dummy; + mutable int _warnings = 0; }; diff --git a/src/game_variables.cpp b/src/game_variables.cpp index b87f51b6a0..10bf648f35 100644 --- a/src/game_variables.cpp +++ b/src/game_variables.cpp @@ -22,6 +22,8 @@ #include "player.h" #include "reader_util.h" +constexpr int kMaxWarnings = 10; + Game_Variables_Class::Game_Variables_Class() {} static std::vector& variables() { @@ -29,6 +31,10 @@ static std::vector& variables() { } int Game_Variables_Class::Get(int variable_id) const { + if ((variable_id <= 0 || variable_id > Data::variables.size()) && _warnings < kMaxWarnings) { + Output::Debug("Invalid read var[%d]!", variable_id); + ++_warnings; + } auto& vv = variables(); if (variable_id <= 0 || variable_id > vv.size()) { return 0; @@ -37,6 +43,10 @@ int Game_Variables_Class::Get(int variable_id) const { } void Game_Variables_Class::Set(int variable_id, int value) { + if ((variable_id <= 0 || variable_id > Data::variables.size()) && _warnings < kMaxWarnings) { + Output::Debug("Invalid write var[%d] = %d!", variable_id, value); + ++_warnings; + } auto& vv = variables(); if (variable_id <= 0) { return; @@ -70,4 +80,5 @@ int Game_Variables_Class::GetSize() const { void Game_Variables_Class::Reset() { variables().clear(); + _warnings = 0; } diff --git a/src/game_variables.h b/src/game_variables.h index 85526ea880..296644089f 100644 --- a/src/game_variables.h +++ b/src/game_variables.h @@ -40,6 +40,8 @@ class Game_Variables_Class { int GetSize() const; void Reset(); +private: + mutable int _warnings = 0; }; // Global variable