diff --git a/src/exe_reader.cpp b/src/exe_reader.cpp index 988ffc3683..4a0a05144c 100644 --- a/src/exe_reader.cpp +++ b/src/exe_reader.cpp @@ -121,6 +121,7 @@ EXEReader::EXEReader(Filesystem_Stream::InputStream core) : corefile(std::move(c uint32_t sectionsOfs = optional_header + GetU16(ofs + 0x14); // skip opt header uint32_t data_directory_ofs = (format_pe32 ? 0x60 : 0x70); resource_rva = GetU32(optional_header + data_directory_ofs + 16); + if (!resource_rva) { // Is some kind of encrypted EXE -> Give up return; @@ -137,6 +138,7 @@ EXEReader::EXEReader(Filesystem_Stream::InputStream core) : corefile(std::move(c if (secName == 0x45444F43) { // CODE file_info.code_size = sectVs; + file_info.code_ofs = GetU32(sectionsOfs + 0x14); } else if (secName == 0x52454843) { // CHER(RY) file_info.cherry_size = sectVs; } else if (secName == 0x50454547) { // GEEP @@ -536,4 +538,52 @@ int EXEReader::FileInfo::GetEngineType(bool& is_maniac_patch) const { return Player::EngineNone; } +std::map EXEReader::GetOverriddenGameConstants() { + std::map game_constants; + + auto apply_known_config = [&](Player::Constants::KnownPatchConfigurations conf) { + Output::Debug("Assuming known patch config '{}'", Player::Constants::kKnownPatchConfigurations.tag(static_cast(conf))); + auto it_conf = Player::Constants::known_patch_configurations.find(conf); + assert(it_conf != Player::Constants::known_patch_configurations.end()); + + for (auto it = it_conf->second.begin(); it != it_conf->second.end(); ++it) { + game_constants[it->first] = it->second; + } + }; + + auto check_for_string = [&](uint32_t offset, const char* p) { + while (*p) { + if (GetU8(offset++) != *p++) + return false; + } + return true; + }; + + switch (file_info.code_size) { + case 0x9CC00: // RM2K 1.62 + if (check_for_string(file_info.code_ofs + 0x07DAA6, "XXX" /* 3x "POP EAX" */)) { + apply_known_config(Player::Constants::KnownPatchConfigurations::StatDelimiter); + } + break; + case 0xC8E00: // RM2K3 1.0.8.0 + // For all known Italian translations, the "WhiteDragon" patch seems to be the only one + // to translate this string in RPG_RT. So this segment can be used to reliably detect + // the patch without having to read all individual constant values from the EXE + if (check_for_string(file_info.code_ofs + 0x08EBE0, "NoTitolo")) { + apply_known_config(Player::Constants::KnownPatchConfigurations::Rm2k3_Italian_WD_108); + } + if (check_for_string(file_info.code_ofs + 0x09D279, "XXX" /* 3x "POP EAX" */)) { + apply_known_config(Player::Constants::KnownPatchConfigurations::StatDelimiter); + } + break; + case 0xC9000: // RM2K3 1.0.9.1 + if (check_for_string(file_info.code_ofs + 0x09C5AD, "XXX" /* 3x "POP EAX" */)) { + apply_known_config(Player::Constants::KnownPatchConfigurations::StatDelimiter); + } + break; + } + + return game_constants; +} + #endif diff --git a/src/exe_reader.h b/src/exe_reader.h index 15abb5ded8..12d1f2c2e6 100644 --- a/src/exe_reader.h +++ b/src/exe_reader.h @@ -64,6 +64,7 @@ class EXEReader { uint32_t geep_size = 0; MachineType machine_type = MachineType::Unknown; bool is_easyrpg_player = false; + uint32_t code_ofs = 0; int GetEngineType(bool& is_maniac_patch) const; void Print() const; @@ -71,6 +72,8 @@ class EXEReader { const FileInfo& GetFileInfo(); + std::map GetOverriddenGameConstants(); + private: // Bounds-checked unaligned reader primitives. // In case of out-of-bounds, returns 0 - this will usually result in a harmless error at some other level, diff --git a/src/game_actor.cpp b/src/game_actor.cpp index 8a41a3925b..c4634de971 100644 --- a/src/game_actor.cpp +++ b/src/game_actor.cpp @@ -35,47 +35,24 @@ #include "rand.h" #include "algo.h" -constexpr int max_level_2k = 50; -constexpr int max_level_2k3 = 99; - int Game_Actor::MaxHpValue() const { - auto& val = lcf::Data::system.easyrpg_max_actor_hp; - if (val == -1) { - return Player::IsRPG2k() ? 999 : 9999; - } - return val; + return Player::Constants::MaxActorHpValue(); } int Game_Actor::MaxSpValue() const { - auto& val = lcf::Data::system.easyrpg_max_actor_sp; - if (val == -1) { - return 999; - } - return val; + return Player::Constants::MaxActorSpValue(); } int Game_Actor::MaxStatBattleValue() const { - auto& val = lcf::Data::system.easyrpg_max_stat_battle_value; - if (val == -1) { - return 9999; - } - return val; + return Player::Constants::MaxStatBattleValue(); } int Game_Actor::MaxStatBaseValue() const { - auto& val = lcf::Data::system.easyrpg_max_stat_base_value; - if (val == -1) { - return 999; - } - return val; + return Player::Constants::MaxStatBaseValue(); } int Game_Actor::MaxExpValue() const { - auto& val = lcf::Data::system.easyrpg_max_exp; - if (val == -1) { - return Player::IsRPG2k() ? 999999 : 9999999; - } - return val; + return Player::Constants::MaxExpValue(); } Game_Actor::Game_Actor(int actor_id) { @@ -744,11 +721,7 @@ int Game_Actor::GetAccessoryId() const { } int Game_Actor::GetMaxLevel() const { - int max_level = Player::IsRPG2k() ? max_level_2k : max_level_2k3; - if (lcf::Data::system.easyrpg_max_level > -1) { - max_level = lcf::Data::system.easyrpg_max_level; - } - return Utils::Clamp(max_level, 1, dbActor->final_level); + return Utils::Clamp(Player::Constants::MaxLevel(), 1, dbActor->final_level); } void Game_Actor::SetExp(int _exp) { diff --git a/src/game_actor.h b/src/game_actor.h index bad19e1cda..ac18619d1c 100644 --- a/src/game_actor.h +++ b/src/game_actor.h @@ -425,7 +425,7 @@ class Game_Actor final : public Game_Battler { /** * Sets exp of actor. - * The value is adjusted to the boundary 0 up 999999. + * The value is adjusted to the boundary 0 up to a maximum (dependent on engine type & patch). * Other actor attributes are not altered. Use ChangeExp to do a proper * experience change. * diff --git a/src/game_battlealgorithm.cpp b/src/game_battlealgorithm.cpp index 6204d32f2c..ce9cc5a22d 100644 --- a/src/game_battlealgorithm.cpp +++ b/src/game_battlealgorithm.cpp @@ -52,7 +52,7 @@ #include "feature.h" static inline int MaxDamageValue() { - return lcf::Data::system.easyrpg_max_damage == -1 ? (Player::IsRPG2k() ? 999 : 9999) : lcf::Data::system.easyrpg_max_damage; + return Player::Constants::MaxDamageValue(); } Game_BattleAlgorithm::AlgorithmBase::AlgorithmBase(Type ty, Game_Battler* source, Game_Battler* target) : diff --git a/src/game_config_game.cpp b/src/game_config_game.cpp index 4a719b5556..519782bf08 100644 --- a/src/game_config_game.cpp +++ b/src/game_config_game.cpp @@ -78,6 +78,16 @@ void Game_ConfigGame::LoadFromArgs(CmdlineParser& cp) { } continue; } + if (cp.ParseNext(arg, 1, "--engine-path")) { + if (arg.NumValues() > 0) { + std::string path = arg.Value(0); + path = FileFinder::MakeCanonical(path, 0); + if (!path.empty()) { + engine_path.Set(path); + } + } + continue; + } if (cp.ParseNext(arg, 0, "--no-patch")) { patch_support.Set(false); patch_dynrpg.Lock(false); @@ -192,6 +202,7 @@ void Game_ConfigGame::LoadFromStream(Filesystem_Stream::InputStream& is) { new_game.FromIni(ini); engine_str.FromIni(ini); + engine_path.FromIni(ini); fake_resolution.FromIni(ini); if (patch_easyrpg.FromIni(ini)) { diff --git a/src/game_config_game.h b/src/game_config_game.h index fe9e3ec0c0..dff3ac33d2 100644 --- a/src/game_config_game.h +++ b/src/game_config_game.h @@ -37,6 +37,7 @@ struct Game_ConfigGame { BoolConfigParam new_game{ "Start new game", "Skips the title screen and starts a new game directly", "Game", "NewGame", false }; StringConfigParam engine_str{ "Engine", "", "Game", "Engine", std::string() }; + StringConfigParam engine_path{ "Engine Path", "Sets the executable to be used by the engine auto-detection", "Game", "EnginePath", std::string() }; BoolConfigParam fake_resolution{ "Fake Metrics", "Makes games run on higher resolutions (with some success)", "Game", "FakeResolution", false }; BoolConfigParam patch_easyrpg{ "EasyRPG", "EasyRPG Engine Extensions", "Patch", "EasyRPG", false }; BoolConfigParam patch_destiny{ "Destiny Patch", "", "Patch", "Destiny", false }; diff --git a/src/game_enemy.cpp b/src/game_enemy.cpp index 3da6b4a7fd..99531c405a 100644 --- a/src/game_enemy.cpp +++ b/src/game_enemy.cpp @@ -48,35 +48,19 @@ Game_Enemy::Game_Enemy(const lcf::rpg::TroopMember* member) } int Game_Enemy::MaxHpValue() const { - auto& val = lcf::Data::system.easyrpg_max_enemy_hp; - if (val == -1) { - return Player::IsRPG2k() ? 9999 : 99999; - } - return val; + return Player::Constants::MaxEnemyHpValue(); } int Game_Enemy::MaxSpValue() const { - auto& val = lcf::Data::system.easyrpg_max_enemy_sp; - if (val == -1) { - return 9999; - } - return val; + return Player::Constants::MaxEnemySpValue(); } int Game_Enemy::MaxStatBattleValue() const { - auto& val = lcf::Data::system.easyrpg_max_stat_battle_value; - if (val == -1) { - return 9999; - } - return val; + return Player::Constants::MaxStatBattleValue(); } int Game_Enemy::MaxStatBaseValue() const { - auto& val = lcf::Data::system.easyrpg_max_stat_base_value; - if (val == -1) { - return 999; - } - return val; + return Player::Constants::MaxStatBaseValue(); } int Game_Enemy::GetStateProbability(int state_id) const { diff --git a/src/game_party.cpp b/src/game_party.cpp index 745a3916ac..cd09e866a4 100644 --- a/src/game_party.cpp +++ b/src/game_party.cpp @@ -161,7 +161,7 @@ int Game_Party::GetItemTotalCount(int item_id) const { int Game_Party::GetMaxItemCount(int item_id) const { const lcf::rpg::Item* item = lcf::ReaderUtil::GetElement(lcf::Data::items, item_id); if (!item || item->easyrpg_max_count == -1) { - return (lcf::Data::system.easyrpg_max_item_count == -1 ? 99 : lcf::Data::system.easyrpg_max_item_count); + return Player::Constants::MaxItemCount(); } else { return item->easyrpg_max_count; } @@ -169,12 +169,12 @@ int Game_Party::GetMaxItemCount(int item_id) const { void Game_Party::GainGold(int n) { data.gold = data.gold + n; - data.gold = std::min(std::max(data.gold, 0), 999999); + data.gold = std::min(std::max(data.gold, 0), Player::Constants::MaxGoldValue()); } void Game_Party::LoseGold(int n) { data.gold = data.gold - n; - data.gold = std::min(std::max(data.gold, 0), 999999); + data.gold = std::min(std::max(data.gold, 0), Player::Constants::MaxGoldValue()); } void Game_Party::AddItem(int item_id, int amount) { diff --git a/src/game_variables.h b/src/game_variables.h index 1da0393a9d..bd4d5d5211 100644 --- a/src/game_variables.h +++ b/src/game_variables.h @@ -34,10 +34,10 @@ class Game_Variables { using Variables_t = std::vector; static constexpr int max_warnings = 10; - static constexpr Var_t min_2k = -999999; - static constexpr Var_t max_2k = 999999; - static constexpr Var_t min_2k3 = -9999999; - static constexpr Var_t max_2k3 = 9999999; + static constexpr Var_t min_2k = -999'999; + static constexpr Var_t max_2k = 999'999; + static constexpr Var_t min_2k3 = -9'999'999; + static constexpr Var_t max_2k3 = 9'999'999; Game_Variables(Var_t minval, Var_t maxval); diff --git a/src/player.cpp b/src/player.cpp index 47825e8411..ffe02f8a90 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -754,11 +754,16 @@ void Player::CreateGameObjects() { } int& engine = game_config.engine; + std::map game_constant_overrides; #ifndef EMSCRIPTEN // Attempt reading ExFont and version information from RPG_RT.exe (not supported on Emscripten) std::unique_ptr exe_reader; - auto exeis = FileFinder::Game().OpenFile(EXE_NAME); + const auto exe_file = game_config.engine_path.Get().empty() ? EXE_NAME : game_config.engine_path.Get(); + if (!game_config.engine_path.Get().empty()) { + Output::Debug("Using specified .EXE '{}' for engine detection", exe_file); + } + auto exeis = FileFinder::Game().OpenFile(exe_file); if (exeis) { exe_reader.reset(new EXEReader(std::move(exeis))); @@ -774,6 +779,8 @@ void Player::CreateGameObjects() { } } + game_constant_overrides = exe_reader->GetOverriddenGameConstants(); + if (engine == EngineNone) { Output::Debug("Unable to detect version from exe"); } @@ -831,6 +838,14 @@ void Player::CreateGameObjects() { game_config.PrintActivePatches(); + Constants::ResetOverrides(); + if (game_constant_overrides.size() > 0) { + for (auto it = game_constant_overrides.begin(); it != game_constant_overrides.end();++it) { + Constants::OverrideGameConstant(it->first, it->second); + } + Constants::PrintActiveOverrides(); + } + ResetGameObjects(); LoadFonts(); @@ -906,22 +921,9 @@ void Player::ResetGameObjects() { Main_Data::game_switches = std::make_unique(); Main_Data::game_switches->SetLowerLimit(lcf::Data::switches.size()); - auto min_var = lcf::Data::system.easyrpg_variable_min_value; - if (min_var == 0) { - if ((Player::game_config.patch_maniac.Get() & 1) == 1) { - min_var = std::numeric_limits::min(); - } else { - min_var = Player::IsRPG2k3() ? Game_Variables::min_2k3 : Game_Variables::min_2k; - } - } - auto max_var = lcf::Data::system.easyrpg_variable_max_value; - if (max_var == 0) { - if ((Player::game_config.patch_maniac.Get() & 1) == 1) { - max_var = std::numeric_limits::max(); - } else { - max_var = Player::IsRPG2k3() ? Game_Variables::max_2k3 : Game_Variables::max_2k; - } - } + int32_t min_var, max_var; + Player::Constants::GetVariableLimits(min_var, max_var); + Main_Data::game_variables = std::make_unique(min_var, max_var); Main_Data::game_variables->SetLowerLimit(lcf::Data::variables.size()); @@ -1430,6 +1432,8 @@ Engine options: rpg2k3 - RPG Maker 2003 (v1.00 - v1.04) rpg2k3v105 - RPG Maker 2003 (v1.05 - v1.09a) rpg2k3e - RPG Maker 2003 (English release, v1.12) + --engine-path EXE Set a custom path for the executable which is to be used + by the automatic engine detection. --font1 FILE Font to use for the first font. The system graphic of the game determines whether font 1 or 2 is used. --font1-size PX Size of font 1 in pixel. The default is 12. @@ -1613,3 +1617,174 @@ std::string Player::GetEngineVersion() { if (EngineVersion() > 0) return std::to_string(EngineVersion()); return std::string(); } + +namespace Player::Constants { + std::map constant_overrides; +} + +void Player::Constants::GetVariableLimits(Var_t& min_var, Var_t& max_var) { + min_var = lcf::Data::system.easyrpg_variable_min_value; + TryGetOverriddenConstant(GameConstantType::MinVarLimit, min_var); + if (min_var == 0) { + if (Player::IsPatchManiac()) { + min_var = std::numeric_limits::min(); + } else { + min_var = Player::IsRPG2k3() ? Game_Variables::min_2k3 : Game_Variables::min_2k; + } + } + max_var = lcf::Data::system.easyrpg_variable_max_value; + TryGetOverriddenConstant(GameConstantType::MaxVarLimit, max_var); + if (max_var == 0) { + if (Player::IsPatchManiac()) { + max_var = std::numeric_limits::max(); + } else { + max_var = Player::IsRPG2k3() ? Game_Variables::max_2k3 : Game_Variables::max_2k; + } + } +} + +int32_t Player::Constants::MaxActorHpValue() { + auto val = lcf::Data::system.easyrpg_max_actor_hp; + TryGetOverriddenConstant(GameConstantType::MaxActorHP, val); + if (val == -1) { + return Player::IsRPG2k() ? 999 : 9'999; + } + return val; +} + +int32_t Player::Constants::MaxActorSpValue() { + auto val = lcf::Data::system.easyrpg_max_actor_sp; + TryGetOverriddenConstant(GameConstantType::MaxActorSP, val); + if (val == -1) { + return 999; + } + return val; +} + +int32_t Player::Constants::MaxEnemyHpValue() { + auto val = lcf::Data::system.easyrpg_max_enemy_hp; + if (val == -1) { + return std::numeric_limits::max(); + } + return val; +} + +int32_t Player::Constants::MaxEnemySpValue() { + auto val = lcf::Data::system.easyrpg_max_enemy_sp; + if (val == -1) { + return std::numeric_limits::max(); + } + return val; +} + +int32_t Player::Constants::MaxStatBaseValue() { + auto val = lcf::Data::system.easyrpg_max_stat_base_value; + TryGetOverriddenConstant(GameConstantType::MaxStatBaseValue, val); + if (val == -1) { + return 999; + } + return val; +} + +int32_t Player::Constants::MaxStatBattleValue() { + auto val = lcf::Data::system.easyrpg_max_stat_battle_value; + TryGetOverriddenConstant(GameConstantType::MaxStatBattleValue, val); + if (val == -1) { + return 9'999; + } + return val; +} + +int32_t Player::Constants::MaxDamageValue() { + auto val = lcf::Data::system.easyrpg_max_damage; + TryGetOverriddenConstant(GameConstantType::MaxDamageValue, val); + if (val == -1) { + return (Player::IsRPG2k() ? 999 : 9'999); + } + return val; +} + +int32_t Player::Constants::MaxExpValue() { + auto val = lcf::Data::system.easyrpg_max_exp; + TryGetOverriddenConstant(GameConstantType::MaxExpValue, val); + if (val == -1) { + return Player::IsRPG2k() ? 999'999 : 9'999'999; + } + return val; +} + +int32_t Player::Constants::MaxLevel() { + auto max_level = Player::IsRPG2k() ? max_level_2k : max_level_2k3; + if (TryGetOverriddenConstant(GameConstantType::MaxLevel, max_level)) { + return max_level; + } + if (lcf::Data::system.easyrpg_max_level > -1) { + max_level = lcf::Data::system.easyrpg_max_level; + } + return max_level; +} + +int32_t Player::Constants::MaxGoldValue() { + int32_t max_gold = 999'999; + if (TryGetOverriddenConstant(GameConstantType::MaxGoldValue, max_gold)) { + return max_gold; + } + return max_gold; +} + +int32_t Player::Constants::MaxItemCount() { + int32_t max_item_count = (lcf::Data::system.easyrpg_max_item_count == -1 ? 99 : lcf::Data::system.easyrpg_max_item_count);; + TryGetOverriddenConstant(GameConstantType::MaxItemCount, max_item_count); + return max_item_count; +} + +int32_t Player::Constants::MaxSaveFiles() { + int32_t max_savefiles = Utils::Clamp(lcf::Data::system.easyrpg_max_savefiles, 3, 99); + TryGetOverriddenConstant(GameConstantType::MaxSaveFiles, max_savefiles); + return max_savefiles; +} + +bool Player::Constants::TryGetOverriddenConstant(GameConstantType const_type, int32_t& out_value) { + auto it = constant_overrides.find(const_type); + if (it != constant_overrides.end()) { + out_value = (*it).second; + } + return it != constant_overrides.end(); +} + +void Player::Constants::OverrideGameConstant(GameConstantType const_type, int32_t value) { + constant_overrides[const_type] = value; +} + +void Player::Constants::ResetOverrides() { + constant_overrides.clear(); +} + +void Player::Constants::PrintActiveOverrides() { + std::vector> overridden_constants; + + auto it = Player::kGameConstantType.begin(); + int32_t value; + while (it != Player::kGameConstantType.end()) { + auto const_type = static_cast((*it).value); + if (!TryGetOverriddenConstant(const_type, value)) { + ++it; + continue; + } + overridden_constants.push_back(std::make_tuple((*it).name, value)); + ++it; + } + + if (!overridden_constants.empty()) { + std::string out = "Overridden Game Constants: "; + bool first = true; + for (const auto& p : overridden_constants) { + if (!first) { + out += ", "; + } + out += fmt::format("{}: {}", std::get(p), std::get(p)); + first = false; + } + Output::DebugStr(out); + } +} diff --git a/src/player.h b/src/player.h index 13575c7738..18f3cb3020 100644 --- a/src/player.h +++ b/src/player.h @@ -25,6 +25,7 @@ #include "game_clock.h" #include "game_config.h" #include "game_config_game.h" +#include "game_variables.h" #include #include #include @@ -58,6 +59,36 @@ namespace Player { PatchOverride = 1 << 16 }; + enum class GameConstantType { + MinVarLimit, + MaxVarLimit, + MaxActorHP, + MaxActorSP, + MaxStatBaseValue, + MaxStatBattleValue, + MaxDamageValue, + MaxExpValue, + MaxLevel, + MaxGoldValue, + MaxItemCount, + MaxSaveFiles + }; + + static constexpr auto kGameConstantType = lcf::makeEnumTags( + "MinVarLimit", + "MaxVarLimit", + "MaxActorHP", + "MaxActorSP", + "MaxStatBaseValue", + "MaxStatBattleValue", + "MaxDamageValue", + "MaxExpValue", + "MaxLevel", + "MaxGoldValue", + "MaxItemCount", + "MaxSaveFiles" + ); + /** * Initializes EasyRPG Player. * @@ -435,6 +466,72 @@ namespace Player { /** Name of game emscripten uses */ extern std::string emscripten_game_name; #endif + + namespace Constants { + using Var_t = int32_t; + + static constexpr int32_t max_level_2k = 50; + static constexpr int32_t max_level_2k3 = 99; + + void GetVariableLimits(Var_t& min_var, Var_t& max_var); + + int32_t MaxActorHpValue(); + int32_t MaxActorSpValue(); + + int32_t MaxEnemyHpValue(); + int32_t MaxEnemySpValue(); + + int32_t MaxStatBaseValue(); + int32_t MaxStatBattleValue(); + int32_t MaxDamageValue(); + + int32_t MaxExpValue(); + int32_t MaxLevel(); + + int32_t MaxGoldValue(); + int32_t MaxItemCount(); + int32_t MaxSaveFiles(); + + extern std::map constant_overrides; + + bool TryGetOverriddenConstant(GameConstantType const_type, int32_t& out_value); + void OverrideGameConstant(GameConstantType const_type, int32_t value); + void ResetOverrides(); + void PrintActiveOverrides(); + + enum class KnownPatchConfigurations { + Rm2k3_Italian_WD_108, // Italian "WhiteDragon" patch + StatDelimiter, + LAST + }; + static constexpr auto kKnownPatchConfigurations = lcf::makeEnumTags( + "Rm2k3 Italian 1.08", + "StatDelimiter" + ); + + static_assert(kKnownPatchConfigurations.size() == static_cast(KnownPatchConfigurations::LAST)); + + using T = Player::GameConstantType; + using patch_config = std::map; + inline const std::map known_patch_configurations = { + { + KnownPatchConfigurations::Rm2k3_Italian_WD_108, { + { T::MinVarLimit, -999999999 }, + { T::MaxVarLimit, 999999999 }, + { T::MaxActorHP, 99999 }, + { T::MaxActorSP, 9999 }, + { T::MaxStatBaseValue, 9999 }, + { T::MaxDamageValue, 99999 }, + { T::MaxGoldValue, 9999999 } + }},{ + KnownPatchConfigurations::StatDelimiter, { + { T::MaxActorHP, 9999999 }, + { T::MaxActorSP, 9999999 }, + { T::MaxStatBaseValue, 999999 }, + { T::MaxStatBattleValue, 999999 } + }} + }; + } } inline bool Player::IsRPG2k() { @@ -508,5 +605,4 @@ inline bool Player::IsPatchDestiny() { inline bool Player::HasEasyRpgExtensions() { return game_config.patch_easyrpg.Get(); } - #endif diff --git a/src/scene_file.cpp b/src/scene_file.cpp index 4e23f64c9c..cd9fa341b9 100644 --- a/src/scene_file.cpp +++ b/src/scene_file.cpp @@ -123,7 +123,7 @@ void Scene_File::Start() { // Refresh File Finder Save Folder fs = FileFinder::Save(); - for (int i = 0; i < Utils::Clamp(lcf::Data::system.easyrpg_max_savefiles, 3, 99); i++) { + for (int i = 0; i < Player::Constants::MaxSaveFiles(); i++) { std::shared_ptr w(new Window_SaveFile(Player::menu_offset_x, 40 + i * 64, MENU_WIDTH, 64)); w->SetIndex(i); @@ -168,7 +168,7 @@ void Scene_File::RefreshWindows() { } void Scene_File::Refresh() { - for (int i = 0; i < Utils::Clamp(lcf::Data::system.easyrpg_max_savefiles, 3, 99); i++) { + for (int i = 0; i < Player::Constants::MaxSaveFiles(); i++) { Window_SaveFile *w = file_windows[i].get(); PopulateSaveWindow(*w, i); w->Refresh(); diff --git a/src/scene_save.cpp b/src/scene_save.cpp index c802b103ad..a01a54766a 100644 --- a/src/scene_save.cpp +++ b/src/scene_save.cpp @@ -53,7 +53,7 @@ Scene_Save::Scene_Save() : void Scene_Save::Start() { Scene_File::Start(); - for (int i = 0; i < Utils::Clamp(lcf::Data::system.easyrpg_max_savefiles, 3, 99); i++) { + for (int i = 0; i < Player::Constants::MaxSaveFiles(); i++) { file_windows[i]->SetHasSave(true); file_windows[i]->Refresh(); } diff --git a/tests/game_enemy.cpp b/tests/game_enemy.cpp index 0044dfe57e..5921fce176 100644 --- a/tests/game_enemy.cpp +++ b/tests/game_enemy.cpp @@ -52,10 +52,9 @@ TEST_CASE("Default") { REQUIRE(e.IsInParty()); } -static void testLimits(int hp, int base, int battle) { +static void testLimits(int base, int battle) { auto& enemy = MakeEnemy(1, 100, 10, 11, 12, 13, 14); - REQUIRE_EQ(enemy.MaxHpValue(), hp); REQUIRE_EQ(enemy.MaxStatBaseValue(), base); REQUIRE_EQ(enemy.MaxStatBattleValue(), battle); @@ -86,12 +85,12 @@ TEST_CASE("Limits") { SUBCASE("2k") { const MockActor m(Player::EngineRpg2k); - testLimits(9999, 999, 9999); + testLimits(999, 9999); } SUBCASE("2k3") { const MockActor m(Player::EngineRpg2k3); - testLimits(99999, 999, 9999); + testLimits(999, 9999); } }