Skip to content

Patch compatibility Power Mode 2003 #3384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
255d082
Implemented KotatsuAkira's "Encounter Randomness Alert MEPR" (cherry …
florianessl Feb 28, 2024
09ad303
Implemented support for RPG_RT patch 'MonSca' (Scaling of enemy param…
florianessl Feb 26, 2025
a6ecaab
Reworked incomplete patch implementation for 'Encounter Randomness Al…
florianessl Feb 26, 2025
bf263cc
Implemented support for RPG_RT patches 'EXPlus' & 'EXPlus[+]'
florianessl Feb 27, 2025
1883855
Refactored handling of command args & INI reading for runtime patches
florianessl Feb 28, 2025
ba1ddd8
Implemented support for RPG_RT patch 'GuardRevamp'
florianessl Feb 28, 2025
bf8b7ba
Fixes:
florianessl Feb 28, 2025
5c3bda6
Fix: Build was broken when compiler flag "NO_RUNTIME_PATCHES" was set.
florianessl Feb 28, 2025
f064e5b
MonSca: Implemented support for patch variant 'MonScaPlus'
florianessl Mar 1, 2025
fe9dcd1
Minor: fixing some comments
florianessl Mar 22, 2025
8d24a74
Fix build errors for 3DS platform, the 2nd
florianessl Mar 22, 2025
ff2d493
Refactor: Moved Maniacs code for mapping virtual keys to game_runtime…
florianessl Mar 23, 2025
dd9cc06
PowerMode2003: Patch detection
florianessl Mar 24, 2025
d2648c8
PowerMode2003: Implemented functionality of variable "registers" V[00…
florianessl Mar 24, 2025
77a47ed
Fix: include cmath for floating point operations
florianessl Mar 25, 2025
51fa251
PowerMode2003: Implemented custom picture rotation (V[0008] "Special")
florianessl Mar 25, 2025
c609260
PowerMode2003: Implemented counter-clock-wise rotation
florianessl Mar 25, 2025
e936c88
PowerMode2003: Some minor refactoring & added documentation
florianessl Mar 25, 2025
c9ec067
MP3 detection: Detect AAC files by some known magic bytes, otherwise …
florianessl Mar 25, 2025
e1e4ae3
PowerMode: added cmd line & ini parsing
florianessl Mar 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ add_library(${PROJECT_NAME} OBJECT
src/game_pictures.h
src/game_player.cpp
src/game_player.h
src/game_runtime_patches.cpp
src/game_runtime_patches.h
src/game_quit.cpp
src/game_quit.h
src/game_screen.cpp
Expand Down
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ libeasyrpg_player_a_SOURCES = \
src/game_pictures.h \
src/game_player.cpp \
src/game_player.h \
src/game_runtime_patches.cpp \
src/game_runtime_patches.h \
src/game_screen.cpp \
src/game_screen.h \
src/game_strings.cpp \
Expand Down
3 changes: 3 additions & 0 deletions src/algo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ int VarianceAdjustEffect(int base, int var) {
}

int AdjustDamageForDefend(int dmg, const Game_Battler& target) {
if (RuntimePatches::GuardRevamp::OverrideDamageAdjustment(dmg, target)) {
return dmg;
}
if (target.IsDefending()) {
dmg /= 2;
if (target.HasStrongDefense()) {
Expand Down
13 changes: 13 additions & 0 deletions src/audio_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ class WMAUnsupportedFormatDecoder : public AudioDecoder {
int FillBuffer(uint8_t*, int) override { return -1; };
};
const char wma_magic[] = { (char)0x30, (char)0x26, (char)0xB2, (char)0x75 };
const std::array<char[2], 4> aac_magics = { {
{ (char)0xFF, (char)0xF1 },
{ (char)0xFF, (char)0xF0 },
{ (char)0xFF, (char)0xF8 },
{ (char)0xFF, (char)0xF9 }
}};

std::unique_ptr<AudioDecoderBase> AudioDecoder::Create(Filesystem_Stream::InputStream& stream, bool resample) {
char magic[4] = { 0 };
Expand Down Expand Up @@ -141,6 +147,13 @@ std::unique_ptr<AudioDecoderBase> AudioDecoder::Create(Filesystem_Stream::InputS
return mp3dec;
}

bool is_aac = std::any_of(aac_magics.begin(), aac_magics.end(), [&](auto& mpeg4_magic) {
return memcmp(magic, mpeg4_magic, 2);
});
if (is_aac) {
return nullptr;
}

// Parsing MP3s seems to be the only reliable way to detect them
if (Mpg123Decoder::IsMp3(stream)) {
stream.clear();
Expand Down
29 changes: 25 additions & 4 deletions src/game_config_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

#include "game_config_game.h"
#include "game_runtime_patches.h"
#include "cmdline_parser.h"
#include "directory_tree.h"
#include "filefinder.h"
Expand All @@ -24,8 +25,8 @@
#include "player.h"
#include <cstring>

Game_ConfigGame Game_ConfigGame::Create(CmdlineParser& cp) {
Game_ConfigGame cfg;
void Game_ConfigGame::Initialize(CmdlineParser& cp) {
Game_ConfigGame& cfg = *this;

auto cli_config = FileFinder::Game().OpenFile(EASYRPG_INI_NAME);
if (cli_config) {
Expand Down Expand Up @@ -56,8 +57,6 @@ Game_ConfigGame Game_ConfigGame::Create(CmdlineParser& cp) {
cfg.engine = Player::EngineRpg2k3 | Player::EngineMajorUpdated | Player::EngineEnglish;
}
}

return cfg;
}

void Game_ConfigGame::LoadFromArgs(CmdlineParser& cp) {
Expand Down Expand Up @@ -88,6 +87,9 @@ void Game_ConfigGame::LoadFromArgs(CmdlineParser& cp) {
patch_rpg2k3_commands.Lock(false);
patch_anti_lag_switch.Lock(0);
patch_direct_menu.Lock(0);
patch_powermode.Lock(0);

RuntimePatches::LockPatchesAsDiabled();
patch_override = true;
continue;
}
Expand Down Expand Up @@ -155,6 +157,15 @@ void Game_ConfigGame::LoadFromArgs(CmdlineParser& cp) {
}
continue;
}
if (cp.ParseNext(arg, 0, { "--patch-powermode", "--no-patch-powermode" })) {
patch_powermode.Set(arg.ArgIsOn());
patch_override = true;
continue;
}
if (RuntimePatches::ParseFromCommandLine(cp)) {
patch_override = true;
continue;
}
if (cp.ParseNext(arg, 6, "--patch")) {
// For backwards compatibility only
for (int i = 0; i < arg.NumValues(); ++i) {
Expand Down Expand Up @@ -229,6 +240,14 @@ void Game_ConfigGame::LoadFromStream(Filesystem_Stream::InputStream& is) {
if (patch_direct_menu.FromIni(ini)) {
patch_override = true;
}

if (patch_powermode.FromIni(ini)) {
patch_override = true;
}

if (RuntimePatches::ParseFromIni(ini)) {
patch_override = true;
}
}

void Game_ConfigGame::PrintActivePatches() {
Expand Down Expand Up @@ -258,6 +277,8 @@ void Game_ConfigGame::PrintActivePatches() {
add_int(patch_anti_lag_switch);
add_int(patch_direct_menu);

RuntimePatches::DetermineActivePatches(patches);

if (patches.empty()) {
Output::Debug("Patch configuration: None");
} else {
Expand Down
28 changes: 26 additions & 2 deletions src/game_config_game.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,30 @@ struct Game_ConfigGame {
ConfigParam<int> patch_anti_lag_switch{ "Anti-Lag Switch", "Disable event page refreshes when switch is set", "Patch", "AntiLagSwitch", 0 };
ConfigParam<int> patch_direct_menu{ "Direct Menu", " Allows direct access to subscreens of the default menu", "Patch", "DirectMenu", 0 };

ConfigParam<int> patch_encounter_random_alert_sw{ "Encounter Randomness Alert", "Set troop id to a variable, activate a switch and skip random battle", "Patch", "EncounterAlert.Switch", 0 };
ConfigParam<int> patch_encounter_random_alert_var{ "Encounter Randomness Alert", "Set troop id to a variable, activate a switch and skip random battle", "Patch", "EncounterAlert.Var", 0 };

ConfigParam<int> patch_monsca_maxhp{ "MonSca", "Scales enemy battle stats by variable value. (MaxHP)", "Patch", "MonSca.MaxHP", 0 };
ConfigParam<int> patch_monsca_maxsp{ "MonSca", "Scales enemy battle stats by variable value. (MaxSP)", "Patch", "MonSca.MaxSP", 0 };
ConfigParam<int> patch_monsca_atk{ "MonSca", "Scales enemy battle stats by variable value. (Attack)", "Patch", "MonSca.Attack", 0 };
ConfigParam<int> patch_monsca_def{ "MonSca", "Scales enemy battle stats by variable value. (Defense)", "Patch", "MonSca.Defense", 0 };
ConfigParam<int> patch_monsca_spi{ "MonSca", "Scales enemy battle stats by variable value. (Spirit)", "Patch", "MonSca.Spirit", 0 };
ConfigParam<int> patch_monsca_agi{ "MonSca", "Scales enemy battle stats by variable value. (Agility)", "Patch", "MonSca.Agility", 0 };
ConfigParam<int> patch_monsca_exp{ "MonSca", "Scales enemy battle stats by variable value. (Gained EXP)", "Patch", "MonSca.Experience", 0 };
ConfigParam<int> patch_monsca_gold{ "MonSca", "Scales enemy battle stats by variable value. (Gained Money)", "Patch", "MonSca.Money", 0 };
ConfigParam<int> patch_monsca_item{ "MonSca", "Scales enemy battle stats by variable value. (Gained Item)", "Patch", "MonSca.ItemId", 0 };
ConfigParam<int> patch_monsca_droprate{ "MonSca", "Scales enemy battle stats by variable value. (Item Drop Rate)", "Patch", "MonSca.ItemDropRate", 0 };
ConfigParam<int> patch_monsca_levelscaling{ "MonSca", "Scales enemy battle stats by variable value. (Alternate formula)", "Patch", "MonSca.LevelScaling", 0 };
ConfigParam<int> patch_monsca_plus{ "MonSca", "Scale enemies individually based on troop index", "Patch", "MonSca.Plus", 0 };

ConfigParam<int> patch_explus_var{ "EXPlus", "Boosts party EXP by set percentages", "Patch", "EXPlus.VarExpBoost", 0 };
ConfigParam<int> patch_explusplus_var{ "EXPlus", "Allows for setting party index of given actors to a variable", "Patch", "EXPlus.VarActorInParty", 0 };

ConfigParam<int> patch_guardrevamp_normal{ "GuardRevamp", "Changes damage calculation for defense situations (Normal)", "Patch", "GuardRevamp.NormalDefense", 0 };
ConfigParam<int> patch_guardrevamp_strong{ "GuardRevamp", "Changes damage calculation for defense situations (Strong)", "Patch", "GuardRevamp.StrongDefense", 0 };

ConfigParam<int> patch_powermode{ "Power Mode 2003", "", "Patch", "PowerMode2003", 0 };

// Command line only
BoolConfigParam patch_support{ "Support patches", "When OFF all patch support is disabled", "", "", true };

Expand All @@ -58,9 +82,9 @@ struct Game_ConfigGame {
int engine = 0;

/**
* Create a game config from the config file in the game directory, then loads command line arguments.
* Initializes a game config from the config file in the game directory, then loads command line arguments.
*/
static Game_ConfigGame Create(CmdlineParser& cp);
void Initialize(CmdlineParser& cp);

/**
* Load configuration values from a stream;
Expand Down
25 changes: 19 additions & 6 deletions src/game_enemy.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

// Headers
#include "game_battler.h"
#include "game_runtime_patches.h"
#include "sprite_enemy.h"
#include "player.h"
#include <lcf/rpg/enemy.h>
Expand Down Expand Up @@ -327,27 +328,39 @@ inline int Game_Enemy::GetTroopMemberId() const {
}

inline int Game_Enemy::GetBaseMaxHp() const {
return enemy->max_hp;
auto max_hp = enemy->max_hp;
RuntimePatches::MonSca::ModifyMaxHp(*this, max_hp);
return max_hp;
}

inline int Game_Enemy::GetBaseMaxSp() const {
return enemy->max_sp;
auto max_sp = enemy->max_sp;
RuntimePatches::MonSca::ModifyMaxSp(*this, max_sp);
return max_sp;
}

inline int Game_Enemy::GetBaseAtk(Weapon) const {
return enemy->attack;
auto attack = enemy->attack;
RuntimePatches::MonSca::ModifyAtk(*this, attack);
return attack;
}

inline int Game_Enemy::GetBaseDef(Weapon) const {
return enemy->defense;
auto defense = enemy->defense;
RuntimePatches::MonSca::ModifyDef(*this, defense);
return defense;
}

inline int Game_Enemy::GetBaseSpi(Weapon) const {
return enemy->spirit;
auto spirit = enemy->spirit;
RuntimePatches::MonSca::ModifySpi(*this, spirit);
return spirit;
}

inline int Game_Enemy::GetBaseAgi(Weapon) const {
return enemy->agility;
auto agility = enemy->agility;
RuntimePatches::MonSca::ModifyAgi(*this, agility);
return agility;
}

inline int Game_Enemy::GetHp() const {
Expand Down
23 changes: 18 additions & 5 deletions src/game_enemyparty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <algorithm>
#include "game_interpreter.h"
#include "game_enemyparty.h"
#include "game_runtime_patches.h"
#include "main_data.h"
#include <lcf/reader_util.h>
#include "utils.h"
Expand Down Expand Up @@ -102,7 +103,10 @@ int Game_EnemyParty::GetExp() const {
int sum = 0;
for (auto& enemy: enemies) {
if (enemy.IsDead()) {
sum += enemy.GetExp();
auto exp = enemy.GetExp();
RuntimePatches::MonSca::ModifyExpGained(enemy, exp);

sum += exp;
}
}
return sum;
Expand All @@ -112,7 +116,10 @@ int Game_EnemyParty::GetMoney() const {
int sum = 0;
for (auto& enemy: enemies) {
if (enemy.IsDead()) {
sum += enemy.GetMoney();
auto money = enemy.GetMoney();
RuntimePatches::MonSca::ModifyMoneyGained(enemy, money);

sum += money;
}
}
return sum;
Expand All @@ -121,10 +128,16 @@ int Game_EnemyParty::GetMoney() const {
void Game_EnemyParty::GenerateDrops(std::vector<int>& out) const {
for (auto& enemy: enemies) {
if (enemy.IsDead()) {
auto drop_id = enemy.GetDropId();
RuntimePatches::MonSca::ModifyItemGained(enemy, drop_id);

// Only roll if the enemy has something to drop
if (enemy.GetDropId() != 0) {
if (Rand::ChanceOf(enemy.GetDropProbability(), 100)) {
out.push_back(enemy.GetDropId());
if (drop_id > 0) {
auto drop_rate = enemy.GetDropProbability();
RuntimePatches::MonSca::ModifyItemDropRate(enemy, drop_rate);

if (Rand::ChanceOf(drop_rate, 100)) {
out.push_back(drop_id);
}
}
}
Expand Down
Loading
Loading