From e0556f366e581d330ce077c83193703eaaf86f24 Mon Sep 17 00:00:00 2001 From: Dino Suvalic <82914521+MakoInfused@users.noreply.github.com> Date: Sun, 10 Nov 2024 12:38:40 -0500 Subject: [PATCH 1/5] Implement Maniacs Command 3009: ControlBattle --- src/game_battle.cpp | 17 +++++ src/game_battle.h | 10 +++ src/game_battlealgorithm.cpp | 111 ++++++++++++++++++++++++++++++++ src/game_battlealgorithm.h | 52 +++++++++++++++ src/game_battler.cpp | 11 ++++ src/game_battler.h | 7 ++ src/game_interpreter_battle.cpp | 111 +++++++++++++++++++++++++++++++- src/game_interpreter_battle.h | 22 +++++++ src/game_party_base.cpp | 15 +++++ src/game_party_base.h | 7 ++ src/scene_battle_rpg2k3.cpp | 60 +++++++++++++++-- src/scene_battle_rpg2k3.h | 7 +- 12 files changed, 421 insertions(+), 9 deletions(-) diff --git a/src/game_battle.cpp b/src/game_battle.cpp index 8703c704ef..a9cbb8670a 100644 --- a/src/game_battle.cpp +++ b/src/game_battle.cpp @@ -219,11 +219,28 @@ void Game_Battle::UpdateAtbGauges() { const auto multiplier = std::max(1.0, static_cast(275000 - cur_atb) / 55000.0); increment = Utils::RoundTo(multiplier * increment); } + + ManiacBattleHook( + Game_Interpreter_Battle::AtbIncrement, + bat->GetType() == Game_Battler::Type_Enemy, + bat->GetPartyIndex(), + bat->GetAtbGauge(), + increment + ); + bat->IncrementAtbGauge(increment); } } } +bool Game_Battle::ManiacBattleHook(Game_Interpreter_Battle::ManiacBattleHookType hook_type, int var1, int var2, int var3, int var4, int var5, int var6) { + return interpreter->ManiacBattleHook(hook_type, var1, var2, var3, var4, var5, var6); +} + +bool Game_Battle::ManiacProcessSubEvents() { + return interpreter->ProcessManiacSubEvents(); +} + void Game_Battle::ChangeBackground(const std::string& name) { background_name = name; } diff --git a/src/game_battle.h b/src/game_battle.h index 6c828df4ef..7eeece4b71 100644 --- a/src/game_battle.h +++ b/src/game_battle.h @@ -23,6 +23,7 @@ #include #include #include "teleport_target.h" +#include "game_interpreter_battle.h" #include "utils.h" #include "point.h" @@ -109,6 +110,15 @@ namespace Game_Battle { */ void UpdateAtbGauges(); + /** + * Convenience function to call a maniacs battle hook, which processes sub-events at any time. + */ + bool ManiacBattleHook(Game_Interpreter_Battle::ManiacBattleHookType hook_type, int var1, int var2, int var3, int var4 = 0, int var5 = 0, int var6 = 0); + /** + * Convenience function to process all maniacs sub-events, and return whether they're currently running + */ + bool ManiacProcessSubEvents(); + void ChangeBackground(const std::string& name); const std::string& GetBackground(); diff --git a/src/game_battlealgorithm.cpp b/src/game_battlealgorithm.cpp index 3c939b64e4..f952aa210b 100644 --- a/src/game_battlealgorithm.cpp +++ b/src/game_battlealgorithm.cpp @@ -88,6 +88,14 @@ Game_BattleAlgorithm::AlgorithmBase::AlgorithmBase(Type ty, Game_Battler* source party_target = target; } +int Game_BattleAlgorithm::AlgorithmBase::GetActionType() { + return 0; +} + +int Game_BattleAlgorithm::AlgorithmBase::GetActionId() { + return 0; +} + void Game_BattleAlgorithm::AlgorithmBase::Reset() { hp = 0; sp = 0; @@ -185,7 +193,18 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplySpEffect() { // Only absorb the sp that were left source->ChangeSp(-sp); } + + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 3, + sp + ); } + return sp; } @@ -198,6 +217,16 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyAtkEffect() { if (IsAbsorbAtk()) { source->ChangeAtkModifier(-atk); } + + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 4, + atk + ); } return atk; } @@ -211,6 +240,16 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyDefEffect() { if (IsAbsorbDef()) { source->ChangeDefModifier(-def); } + + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 5, + def + ); } return def; } @@ -224,6 +263,16 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplySpiEffect() { if (IsAbsorbSpi()) { source->ChangeSpiModifier(-spi); } + + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 6, + spi + ); } return spi; } @@ -237,6 +286,16 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyAgiEffect() { if (IsAbsorbAgi()) { source->ChangeAgiModifier(-agi); } + + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 7, + agi + ); } return agi; } @@ -532,6 +591,10 @@ AlgorithmBase(Type::None, source, source) { // no-op } +int Game_BattleAlgorithm::None::GetActionId() { + return 7; +} + Game_BattleAlgorithm::Normal::Normal(Game_Battler* source, Game_Battler* target, int hits_multiplier, Style style) : AlgorithmBase(Type::Normal, source, target), hits_multiplier(hits_multiplier) { @@ -849,6 +912,14 @@ Game_BattleAlgorithm::Skill::Skill(Game_Battler* source, const lcf::rpg::Skill& { } +int Game_BattleAlgorithm::Skill::GetActionType() { + return 1; +} + +int Game_BattleAlgorithm::Skill::GetActionId() { + return skill.ID; +} + void Game_BattleAlgorithm::Skill::Init() { } @@ -1236,6 +1307,14 @@ Game_BattleAlgorithm::Item::Item(Game_Battler* source, Game_Party_Base* target, // no-op } +int Game_BattleAlgorithm::Item::GetActionType() { + return 3; +} + +int Game_BattleAlgorithm::Item::GetActionId() { + return item.ID; +} + bool Game_BattleAlgorithm::Item::vStart() { Main_Data::game_party->ConsumeItemUse(item.ID); return true; @@ -1340,6 +1419,10 @@ Game_BattleAlgorithm::Defend::Defend(Game_Battler* source) : source->SetIsDefending(true); } +int Game_BattleAlgorithm::Defend::GetActionId() { + return 2; +} + std::string Game_BattleAlgorithm::Defend::GetStartMessage(int line) const { if (line == 0) { if (Feature::HasRpg2kBattleSystem()) { @@ -1360,6 +1443,10 @@ AlgorithmBase(Type::Observe, source, source) { // no-op } +int Game_BattleAlgorithm::Observe::GetActionId() { + return 3; +} + std::string Game_BattleAlgorithm::Observe::GetStartMessage(int line) const { if (line == 0) { if (Feature::HasRpg2kBattleSystem()) { @@ -1376,6 +1463,10 @@ AlgorithmBase(Type::Charge, source, source) { // no-op } +int Game_BattleAlgorithm::Charge::GetActionId() { + return 4; +} + std::string Game_BattleAlgorithm::Charge::GetStartMessage(int line) const { if (line == 0) { if (Feature::HasRpg2kBattleSystem()) { @@ -1396,6 +1487,10 @@ AlgorithmBase(Type::SelfDestruct, source, target) { // no-op } +int Game_BattleAlgorithm::SelfDestruct::GetActionId() { + return 5; +} + std::string Game_BattleAlgorithm::SelfDestruct::GetStartMessage(int line) const { if (line == 0) { if (Feature::HasRpg2kBattleSystem()) { @@ -1450,6 +1545,10 @@ Game_BattleAlgorithm::Escape::Escape(Game_Battler* source) : // no-op } +int Game_BattleAlgorithm::Escape::GetActionId() { + return 6; +} + std::string Game_BattleAlgorithm::Escape::GetStartMessage(int line) const { if (line == 0) { if (Feature::HasRpg2kBattleSystem()) { @@ -1487,6 +1586,14 @@ AlgorithmBase(Type::Transform, source, source), new_monster_id(new_monster_id) { // no-op } +int Game_BattleAlgorithm::Transform::GetActionType() { + return 2; +} + +int Game_BattleAlgorithm::Transform::GetActionId() { + return new_monster_id; +} + std::string Game_BattleAlgorithm::Transform::GetStartMessage(int line) const { if (line == 0 && Feature::HasRpg2kBattleSystem()) { auto* enemy = lcf::ReaderUtil::GetElement(lcf::Data::enemies, new_monster_id); @@ -1509,3 +1616,7 @@ AlgorithmBase(Type::DoNothing, source, source) { // no-op } +int Game_BattleAlgorithm::DoNothing::GetActionId() { + return 7; +} + diff --git a/src/game_battlealgorithm.h b/src/game_battlealgorithm.h index 542e29a905..dacc61b14c 100644 --- a/src/game_battlealgorithm.h +++ b/src/game_battlealgorithm.h @@ -83,6 +83,19 @@ class AlgorithmBase { public: virtual ~AlgorithmBase() {} + enum ActionType { + Basic, + Skill, + Transformation, + Item + }; + + /** @return the category associated with this action */ + virtual int GetActionType(); + + /** @return the unique identifier associated with this specific action */ + virtual int GetActionId(); + /** @return the source of the battle action. */ Game_Battler* GetSource() const; @@ -616,6 +629,9 @@ class AlgorithmBase { class None : public AlgorithmBase { public: None(Game_Battler* source); + + /** @return the id associated with this action */ + int GetActionId() override; }; @@ -667,6 +683,12 @@ class Skill : public AlgorithmBase { Skill(Game_Battler* source, Game_Party_Base* target, const lcf::rpg::Skill& skill, const lcf::rpg::Item* item = NULL); Skill(Game_Battler* source, const lcf::rpg::Skill& skill, const lcf::rpg::Item* item = NULL); + /** @return the type associated with this action */ + int GetActionType() override; + + /** @return the id associated with this action */ + int GetActionId() override; + bool IsTargetValid(const Game_Battler&) const override; bool vExecute() override; bool vStart() override; @@ -704,6 +726,12 @@ class Item : public AlgorithmBase { Item(Game_Battler* source, Game_Party_Base* target, const lcf::rpg::Item& item); Item(Game_Battler* source, const lcf::rpg::Item& item); + /** @return the type associated with this action */ + int GetActionType() override; + + /** @return the id associated with this action */ + int GetActionId() override; + bool IsTargetValid(const Game_Battler&) const override; bool vExecute() override; bool vStart() override; @@ -724,6 +752,9 @@ class Defend : public AlgorithmBase { public: Defend(Game_Battler* source); + /** @return the id associated with this action */ + int GetActionId() override; + std::string GetStartMessage(int line) const override; int GetSourcePose() const override; }; @@ -732,6 +763,9 @@ class Observe : public AlgorithmBase { public: Observe(Game_Battler* source); + /** @return the id associated with this action */ + int GetActionId() override; + std::string GetStartMessage(int line) const override; }; @@ -739,6 +773,9 @@ class Charge : public AlgorithmBase { public: Charge(Game_Battler* source); + /** @return the id associated with this action */ + int GetActionId() override; + std::string GetStartMessage(int line) const override; void ApplyCustomEffect() override; }; @@ -747,6 +784,9 @@ class SelfDestruct : public AlgorithmBase { public: SelfDestruct(Game_Battler* source, Game_Party_Base* target); + /** @return the id associated with this action */ + int GetActionId() override; + std::string GetStartMessage(int line) const override; const lcf::rpg::Sound* GetStartSe() const override; bool vExecute() override; @@ -759,6 +799,9 @@ class Escape : public AlgorithmBase { public: Escape(Game_Battler* source); + /** @return the id associated with this action */ + int GetActionId() override; + std::string GetStartMessage(int line) const override; int GetSourcePose() const override; const lcf::rpg::Sound* GetStartSe() const override; @@ -769,6 +812,12 @@ class Transform : public AlgorithmBase { public: Transform(Game_Battler* source, int new_monster_id); + /** @return the type associated with this action */ + int GetActionType() override; + + /** @return the id associated with this action */ + int GetActionId() override; + std::string GetStartMessage(int line) const override; void ApplyCustomEffect() override; @@ -780,6 +829,9 @@ class Transform : public AlgorithmBase { class DoNothing : public AlgorithmBase { public: DoNothing(Game_Battler* source); + + /** @return the id associated with this action */ + int GetActionId() override; }; inline Type AlgorithmBase::GetType() const { diff --git a/src/game_battler.cpp b/src/game_battler.cpp index 03eafdb57a..671b611d7f 100644 --- a/src/game_battler.cpp +++ b/src/game_battler.cpp @@ -367,6 +367,13 @@ bool Game_Battler::AddState(int state_id, bool allow_battle_states) { } } + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::SetState, + GetType() == Game_Battler::Type_Enemy, + GetPartyIndex(), + state_id + ); + return was_added; } @@ -586,6 +593,10 @@ Game_Party_Base& Game_Battler::GetParty() const { } } +int Game_Battler::GetPartyIndex() { + return GetParty().GetMemberIndex(this); +} + void Game_Battler::UpdateBattle() { Shake::Update(shake.position, shake.time_left, shake.strength, shake.speed, false); Flash::Update(flash.current_level, flash.time_left); diff --git a/src/game_battler.h b/src/game_battler.h index 48ce45d179..79b4acad7c 100644 --- a/src/game_battler.h +++ b/src/game_battler.h @@ -769,6 +769,13 @@ class Game_Battler { */ Game_Party_Base& GetParty() const; + /** + * Convenience function to access the battlers party member index. + * + * @return Index of this member in their party. + */ + int GetPartyIndex(); + /** * Gets the maximal atb gauge value. * When GetAtbGauge() >= this, the battler can act. diff --git a/src/game_interpreter_battle.cpp b/src/game_interpreter_battle.cpp index 8fc9a65495..3d1ac489ae 100644 --- a/src/game_interpreter_battle.cpp +++ b/src/game_interpreter_battle.cpp @@ -43,14 +43,35 @@ enum TargetType { Enemy, }; +// Implemented as a static map, since maniac hooks can only have one common event callback at a time. +// Subsequent calls will simply override the previous common event callback. +std::map> Game_Interpreter_Battle::maniac_hooks = { + {AtbIncrement, std::make_tuple(0, 0)}, + {DamagePop, std::make_tuple(0, 0)}, + {Targetting, std::make_tuple(0, 0)}, + {SetState, std::make_tuple(0, 0)}, + {StatChange, std::make_tuple(0, 0)} +}; + static const char* target_text[] = { "actor", "party member", "enemy" }; static const void MissingTargetWarning(const char* command_name, TargetType target_type, int target_id) { Output::Warning("{}: Invalid {} ID: {}", command_name, target_text[target_type], target_id); } + +// Provides a facility for battle sub-events to be run immediately +// without blocking the standard interpreter from actually processing them. +std::unique_ptr maniac_interpreter; + Game_Interpreter_Battle::Game_Interpreter_Battle(Span pages) : Game_Interpreter(true), pages(pages), executed(pages.size(), false) +{ + maniac_interpreter.reset(new Game_Interpreter_Battle()); +} + +Game_Interpreter_Battle::Game_Interpreter_Battle() + : Game_Interpreter(true) { } @@ -600,12 +621,98 @@ bool Game_Interpreter_Battle::CommandEndBranchBattle(lcf::rpg::EventCommand cons return true; } -bool Game_Interpreter_Battle::CommandManiacControlBattle(lcf::rpg::EventCommand const&) { +bool Game_Interpreter_Battle::ManiacBattleHook(ManiacBattleHookType hook_type, int var1, int var2, int var3, int var4, int var5, int var6) { + if (!Player::IsPatchManiac()) { + return false; + } + + int common_event_id = std::get<0>(maniac_hooks[hook_type]); + int variable_start_id = std::get<1>(maniac_hooks[hook_type]); + + if (common_event_id <= 0) { + return false; + } + + Game_CommonEvent* common_event = lcf::ReaderUtil::GetElement(Game_Map::GetCommonEvents(), common_event_id); + if (!common_event) { + Output::Warning("CommandManiacControlBattle: Can't call invalid common event {}", common_event_id); + return false; + } + + // pushes the common event to be run into the queue of events. + maniac_interpreter->Push(common_event); + + // pushes the change variable events into the interpreters + // event queue, so we don't run into a race condition. + std::vector pre_commands; + for (size_t i = 0; i < 6; i++) + { + auto event_command = lcf::rpg::EventCommand(); + event_command.code = static_cast(lcf::rpg::EventCommand::Code::ControlVars); + event_command.parameters = lcf::DBArray(7); + event_command.parameters[1] = variable_start_id + i; + switch (i) + { + case 0: + event_command.parameters[5] = var1; + break; + case 1: + event_command.parameters[5] = var2; + break; + case 2: + event_command.parameters[5] = var3; + break; + case 3: + event_command.parameters[5] = var4; + break; + case 4: + event_command.parameters[5] = var5; + break; + case 5: + event_command.parameters[5] = var6; + break; + default: + break; + } + pre_commands.push_back(event_command); + } + + // Push is actually "push_back", so this gets added before other events. + maniac_interpreter->Push(pre_commands, 0); + + // Necessary to start the sub-event. + maniac_interpreter->Update(); + + return true; +} + +bool Game_Interpreter_Battle::ProcessManiacSubEvents() { + // If we have sub-events we're going to update them immediately + // until the queue is empty while making the rest of the game wait. + if (Player::IsPatchManiac() && maniac_interpreter->IsRunning()) { + maniac_interpreter->Update(); + return true; + } + return false; +} + +bool Game_Interpreter_Battle::CommandManiacControlBattle(lcf::rpg::EventCommand const& com) { if (!Player::IsPatchManiac()) { return true; } - Output::Warning("Maniac Patch: Command ControlBattle not supported"); + ManiacBattleHookType control_type_flags = static_cast(com.parameters[0]); + int common_event_flags = com.parameters[1]; + int common_event_identifier = com.parameters[2]; + int value_reference_identifier = com.parameters[3]; + + int common_event_id = ValueOrVariable(common_event_flags, common_event_identifier); + + // Sets the maniacs battle event hook to: + // the common event id and the variable id the developer would like to use. + std::get<0>(maniac_hooks[control_type_flags]) = common_event_identifier; + std::get<1>(maniac_hooks[control_type_flags]) = value_reference_identifier; + return true; } diff --git a/src/game_interpreter_battle.h b/src/game_interpreter_battle.h index 96ec7d191f..0fff228ef3 100644 --- a/src/game_interpreter_battle.h +++ b/src/game_interpreter_battle.h @@ -40,6 +40,7 @@ class Game_Interpreter_Battle : public Game_Interpreter { public: explicit Game_Interpreter_Battle(Span pages); + explicit Game_Interpreter_Battle(); int GetNumPages() const; @@ -60,6 +61,26 @@ class Game_Interpreter_Battle : public Game_Interpreter bool ExecuteCommand(lcf::rpg::EventCommand const& com) override; + /** + * All possible hook type events that maniacs offers. + */ + enum ManiacBattleHookType { + AtbIncrement, + DamagePop, + Targetting, + SetState, + StatChange + }; + + /** + * Calls a maniacs battle hook, which processes sub-events at any time. + */ + bool ManiacBattleHook(ManiacBattleHookType hook_type, int var1, int var2, int var3, int var4 = 0, int var5 = 0, int var6 = 0); + /** + * Processes all maniacs sub-events, and returns whether it's currently running + */ + bool ProcessManiacSubEvents(); + private: bool CommandCallCommonEvent(lcf::rpg::EventCommand const& com); bool CommandForceFlee(lcf::rpg::EventCommand const& com); @@ -87,6 +108,7 @@ class Game_Interpreter_Battle : public Game_Interpreter int current_actor_id = 0; bool targets_single_enemy = false; bool force_flee_enabled = false; + static std::map> maniac_hooks; }; inline int Game_Interpreter_Battle::GetNumPages() const { diff --git a/src/game_party_base.cpp b/src/game_party_base.cpp index 88c11db579..4709070bb1 100644 --- a/src/game_party_base.cpp +++ b/src/game_party_base.cpp @@ -119,3 +119,18 @@ int Game_Party_Base::GetAverageAgility() { return battlers.empty() ? 1 : agi /= battlers.size(); } +int Game_Party_Base::GetMemberIndex(Game_Battler* battler) { + std::vector battlers; + GetBattlers(battlers); + + auto iterator = std::find(battlers.begin(), battlers.end(), battler); + + if (iterator != battlers.end()) { + int index = std::distance(battlers.begin(), iterator); + return index; + } + else { + return -1; + } +} + diff --git a/src/game_party_base.h b/src/game_party_base.h index 1834e9a2e9..cdd1457066 100644 --- a/src/game_party_base.h +++ b/src/game_party_base.h @@ -108,6 +108,13 @@ class Game_Party_Base { */ int GetAverageAgility(); + /** + * Gets the index of the battler in the party + * + * @return the battlers party index, or -1 if not in the party + */ + int GetMemberIndex(Game_Battler* battler); + private: }; diff --git a/src/scene_battle_rpg2k3.cpp b/src/scene_battle_rpg2k3.cpp index aeb3ea65a4..b4ad096021 100644 --- a/src/scene_battle_rpg2k3.cpp +++ b/src/scene_battle_rpg2k3.cpp @@ -498,7 +498,24 @@ void Scene_Battle_Rpg2k3::UpdateAnimations() { } } -void Scene_Battle_Rpg2k3::DrawFloatText(int x, int y, int color, StringView text) { +void Scene_Battle_Rpg2k3::DrawFloatText(int x, int y, int color, StringView text, Game_Battler* battler, FloatTextType type) { + std::stringstream ss(text.to_string()); + int value = 0; + ss >> value; + bool should_override = Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::DamagePop, + battler->GetType() == Game_Battler::Type_Enemy, + battler->GetPartyIndex(), + x, + y, + static_cast(type), + value + ); + + if (should_override) { + return; + } + Rect rect = Text::GetSize(*Font::Default(), text); BitmapRef graphic = Bitmap::Create(rect.width, rect.height); @@ -953,6 +970,12 @@ void Scene_Battle_Rpg2k3::vUpdate() { break; } + // this is checked separately because we want normal events to be processed + // just not sub-events called by maniacs battle hooks. + if (state != State_Victory && state != State_Defeat && Game_Battle::ManiacProcessSubEvents()) { + break; + } + if (!CheckWait()) { break; } @@ -2209,7 +2232,9 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction b->GetBattlePosition().x, b->GetBattlePosition().y, damageTaken < 0 ? Font::ColorDefault : Font::ColorHeal, - std::to_string(std::abs(damageTaken))); + std::to_string(std::abs(damageTaken)), + b, + damageTaken < 0 ? Damage : Heal); } if (b->GetType() == Game_Battler::Type_Ally) { auto* sprite = static_cast(b)->GetActorBattleSprite(); @@ -2632,14 +2657,18 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction target->GetBattlePosition().x, target->GetBattlePosition().y, hp > 0 ? Font::ColorHeal : Font::ColorDefault, - std::to_string(std::abs(hp))); + std::to_string(std::abs(hp)), + target, + hp > 0 ? Heal : Damage); if (action->IsAbsorbHp()) { DrawFloatText( source->GetBattlePosition().x, source->GetBattlePosition().y, hp > 0 ? Font::ColorDefault : Font::ColorHeal, - std::to_string(std::abs(hp))); + std::to_string(std::abs(hp)), + source, + hp > 0 ? Damage : Heal); } } @@ -2660,7 +2689,9 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction target->GetBattlePosition().x, target->GetBattlePosition().y, 0, - lcf::Data::terms.miss); + lcf::Data::terms.miss, + target, + Miss); } status_window->Refresh(); @@ -2821,6 +2852,21 @@ void Scene_Battle_Rpg2k3::RowSelected() { } void Scene_Battle_Rpg2k3::ActionSelectedCallback(Game_Battler* for_battler) { + auto single_target = for_battler->GetBattleAlgorithm()->GetOriginalSingleTarget(); + auto group_targets = for_battler->GetBattleAlgorithm()->GetOriginalPartyTarget(); + // Target: 0 None, 1 Single Enemy, 2 All Enemies, 3 Single Ally, 4 All Allies + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::Targetting, + for_battler->GetType() == Game_Battler::Type_Enemy, + for_battler->GetPartyIndex(), + for_battler->GetBattleAlgorithm()->GetActionType(), + for_battler->GetBattleAlgorithm()->GetActionId(), + single_target + ? (single_target->GetType() != Game_Battler::Type_Enemy ? 1 : 3) + : (group_targets->GetRandomActiveBattler()->GetType() != Game_Battler::Type_Enemy ? 2 : 4), + single_target ? single_target->GetPartyIndex() : 0 + ); + for_battler->SetAtbGauge(0); if (for_battler == active_actor) { @@ -2905,7 +2951,9 @@ void Scene_Battle_Rpg2k3::OnEventHpChanged(Game_Battler* battler, int hp) { battler->GetBattlePosition().x, battler->GetBattlePosition().y, hp < 0 ? Font::ColorDefault : Font::ColorHeal, - std::to_string(std::abs(hp))); + std::to_string(std::abs(hp)), + battler, + hp < 0 ? Damage : Heal); } void Scene_Battle_Rpg2k3::RecreateSpWindow(Game_Battler* battler) { diff --git a/src/scene_battle_rpg2k3.h b/src/scene_battle_rpg2k3.h index d411cd309a..c88ab4d882 100644 --- a/src/scene_battle_rpg2k3.h +++ b/src/scene_battle_rpg2k3.h @@ -123,7 +123,12 @@ class Scene_Battle_Rpg2k3 : public Scene_Battle { void RefreshCommandWindow(const Game_Actor* actor); void SetActiveActor(int idx); - void DrawFloatText(int x, int y, int color, StringView text); + enum FloatTextType { + Damage = 0, + Heal = 1, + Miss = 2, + }; + void DrawFloatText(int x, int y, int color, StringView text, Game_Battler* battler, FloatTextType type); bool IsTransparent() const; From a723ec3ba027496767d930b37d86a04214c5c3a6 Mon Sep 17 00:00:00 2001 From: Dino Suvalic <82914521+MakoInfused@users.noreply.github.com> Date: Sun, 10 Nov 2024 14:11:55 -0500 Subject: [PATCH 2/5] fixed some unit tests that I broke --- src/game_battlealgorithm.cpp | 100 +++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/src/game_battlealgorithm.cpp b/src/game_battlealgorithm.cpp index f952aa210b..bf30cd1da6 100644 --- a/src/game_battlealgorithm.cpp +++ b/src/game_battlealgorithm.cpp @@ -194,15 +194,17 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplySpEffect() { source->ChangeSp(-sp); } - Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, - target->GetType() == Game_Battler::Type_Enemy, - target->GetPartyIndex(), - target->GetDisplayX(), - target->GetDisplayY(), - 3, - sp - ); + if (Player::IsPatchManiac()) { + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 3, + sp + ); + } } return sp; @@ -218,15 +220,17 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyAtkEffect() { source->ChangeAtkModifier(-atk); } - Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, - target->GetType() == Game_Battler::Type_Enemy, - target->GetPartyIndex(), - target->GetDisplayX(), - target->GetDisplayY(), - 4, - atk - ); + if (Player::IsPatchManiac()) { + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 4, + atk + ); + } } return atk; } @@ -241,15 +245,17 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyDefEffect() { source->ChangeDefModifier(-def); } - Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, - target->GetType() == Game_Battler::Type_Enemy, - target->GetPartyIndex(), - target->GetDisplayX(), - target->GetDisplayY(), - 5, - def - ); + if (Player::IsPatchManiac()) { + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 5, + def + ); + } } return def; } @@ -264,15 +270,17 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplySpiEffect() { source->ChangeSpiModifier(-spi); } - Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, - target->GetType() == Game_Battler::Type_Enemy, - target->GetPartyIndex(), - target->GetDisplayX(), - target->GetDisplayY(), - 6, - spi - ); + if (Player::IsPatchManiac()) { + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 6, + spi + ); + } } return spi; } @@ -287,15 +295,17 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyAgiEffect() { source->ChangeAgiModifier(-agi); } - Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, - target->GetType() == Game_Battler::Type_Enemy, - target->GetPartyIndex(), - target->GetDisplayX(), - target->GetDisplayY(), - 7, - agi - ); + if (Player::IsPatchManiac()) { + Game_Battle::ManiacBattleHook( + Game_Interpreter_Battle::StatChange, + target->GetType() == Game_Battler::Type_Enemy, + target->GetPartyIndex(), + target->GetDisplayX(), + target->GetDisplayY(), + 7, + agi + ); + } } return agi; } From a73d3876bac0148a16c5517cafe7d044b6856545 Mon Sep 17 00:00:00 2001 From: Dino Suvalic <82914521+MakoInfused@users.noreply.github.com> Date: Sat, 23 Nov 2024 11:12:21 -0500 Subject: [PATCH 3/5] fixed 2 bugs: maniac battle control hooks not being reset between battles & dual attack not being represented. Also made stylistic changes requested by Ghabry. --- src/game_battle.cpp | 2 +- src/game_battlealgorithm.cpp | 78 ++++++++++++++++++++++++++------- src/game_battlealgorithm.h | 28 ++++++++++++ src/game_battler.cpp | 2 +- src/game_interpreter_battle.cpp | 22 ++++++---- src/game_interpreter_battle.h | 4 +- src/scene_battle_rpg2k3.cpp | 17 ++++--- src/scene_battle_rpg2k3.h | 2 +- 8 files changed, 119 insertions(+), 36 deletions(-) diff --git a/src/game_battle.cpp b/src/game_battle.cpp index a9cbb8670a..5bcc6b9c9e 100644 --- a/src/game_battle.cpp +++ b/src/game_battle.cpp @@ -221,7 +221,7 @@ void Game_Battle::UpdateAtbGauges() { } ManiacBattleHook( - Game_Interpreter_Battle::AtbIncrement, + Game_Interpreter_Battle::ManiacBattleHookType::AtbIncrement, bat->GetType() == Game_Battler::Type_Enemy, bat->GetPartyIndex(), bat->GetAtbGauge(), diff --git a/src/game_battlealgorithm.cpp b/src/game_battlealgorithm.cpp index bf30cd1da6..f2eda7702d 100644 --- a/src/game_battlealgorithm.cpp +++ b/src/game_battlealgorithm.cpp @@ -89,11 +89,11 @@ Game_BattleAlgorithm::AlgorithmBase::AlgorithmBase(Type ty, Game_Battler* source } int Game_BattleAlgorithm::AlgorithmBase::GetActionType() { - return 0; + return -1; } int Game_BattleAlgorithm::AlgorithmBase::GetActionId() { - return 0; + return -1; } void Game_BattleAlgorithm::AlgorithmBase::Reset() { @@ -196,7 +196,7 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplySpEffect() { if (Player::IsPatchManiac()) { Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, + Game_Interpreter_Battle::ManiacBattleHookType::StatChange, target->GetType() == Game_Battler::Type_Enemy, target->GetPartyIndex(), target->GetDisplayX(), @@ -222,7 +222,7 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyAtkEffect() { if (Player::IsPatchManiac()) { Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, + Game_Interpreter_Battle::ManiacBattleHookType::StatChange, target->GetType() == Game_Battler::Type_Enemy, target->GetPartyIndex(), target->GetDisplayX(), @@ -247,7 +247,7 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyDefEffect() { if (Player::IsPatchManiac()) { Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, + Game_Interpreter_Battle::ManiacBattleHookType::StatChange, target->GetType() == Game_Battler::Type_Enemy, target->GetPartyIndex(), target->GetDisplayX(), @@ -272,7 +272,7 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplySpiEffect() { if (Player::IsPatchManiac()) { Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, + Game_Interpreter_Battle::ManiacBattleHookType::StatChange, target->GetType() == Game_Battler::Type_Enemy, target->GetPartyIndex(), target->GetDisplayX(), @@ -297,7 +297,7 @@ int Game_BattleAlgorithm::AlgorithmBase::ApplyAgiEffect() { if (Player::IsPatchManiac()) { Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::StatChange, + Game_Interpreter_Battle::ManiacBattleHookType::StatChange, target->GetType() == Game_Battler::Type_Enemy, target->GetPartyIndex(), target->GetDisplayX(), @@ -602,7 +602,23 @@ AlgorithmBase(Type::None, source, source) { } int Game_BattleAlgorithm::None::GetActionId() { - return 7; + return lcf::rpg::EnemyAction::Basic_nothing; +} + +int Game_BattleAlgorithm::None::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; +} + +int Game_BattleAlgorithm::Normal::GetActionId() { + if (IsDualAttack()) { + return lcf::rpg::EnemyAction::Basic_dual_attack; + } + + return lcf::rpg::EnemyAction::Basic_attack; +} + +int Game_BattleAlgorithm::Normal::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; } Game_BattleAlgorithm::Normal::Normal(Game_Battler* source, Game_Battler* target, int hits_multiplier, Style style) : @@ -813,12 +829,16 @@ bool Game_BattleAlgorithm::Normal::vExecute() { return SetIsSuccess(); } +bool Game_BattleAlgorithm::Normal::IsDualAttack() const { + return GetSource()->GetType() == Game_Battler::Type_Enemy && hits_multiplier == 2; +} + std::string Game_BattleAlgorithm::Normal::GetStartMessage(int line) const { if (line == 0) { if (Feature::HasRpg2kBattleSystem()) { return BattleMessage::GetNormalAttackStartMessage2k(*GetSource()); } - if (GetSource()->GetType() == Game_Battler::Type_Enemy && hits_multiplier == 2) { + if (IsDualAttack()) { return BattleMessage::GetDoubleAttackStartMessage2k3(*GetSource()); } } @@ -923,7 +943,7 @@ Game_BattleAlgorithm::Skill::Skill(Game_Battler* source, const lcf::rpg::Skill& } int Game_BattleAlgorithm::Skill::GetActionType() { - return 1; + return lcf::rpg::EnemyAction::Kind_skill; } int Game_BattleAlgorithm::Skill::GetActionId() { @@ -1429,8 +1449,12 @@ Game_BattleAlgorithm::Defend::Defend(Game_Battler* source) : source->SetIsDefending(true); } +int Game_BattleAlgorithm::Defend::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; +} + int Game_BattleAlgorithm::Defend::GetActionId() { - return 2; + return lcf::rpg::EnemyAction::Basic_defense; } std::string Game_BattleAlgorithm::Defend::GetStartMessage(int line) const { @@ -1453,8 +1477,12 @@ AlgorithmBase(Type::Observe, source, source) { // no-op } +int Game_BattleAlgorithm::Observe::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; +} + int Game_BattleAlgorithm::Observe::GetActionId() { - return 3; + return lcf::rpg::EnemyAction::Basic_observe; } std::string Game_BattleAlgorithm::Observe::GetStartMessage(int line) const { @@ -1473,8 +1501,12 @@ AlgorithmBase(Type::Charge, source, source) { // no-op } +int Game_BattleAlgorithm::Charge::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; +} + int Game_BattleAlgorithm::Charge::GetActionId() { - return 4; + return lcf::rpg::EnemyAction::Basic_charge; } std::string Game_BattleAlgorithm::Charge::GetStartMessage(int line) const { @@ -1497,8 +1529,12 @@ AlgorithmBase(Type::SelfDestruct, source, target) { // no-op } +int Game_BattleAlgorithm::SelfDestruct::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; +} + int Game_BattleAlgorithm::SelfDestruct::GetActionId() { - return 5; + return lcf::rpg::EnemyAction::Basic_autodestruction; } std::string Game_BattleAlgorithm::SelfDestruct::GetStartMessage(int line) const { @@ -1555,8 +1591,12 @@ Game_BattleAlgorithm::Escape::Escape(Game_Battler* source) : // no-op } +int Game_BattleAlgorithm::Escape::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; +} + int Game_BattleAlgorithm::Escape::GetActionId() { - return 6; + return lcf::rpg::EnemyAction::Basic_escape; } std::string Game_BattleAlgorithm::Escape::GetStartMessage(int line) const { @@ -1597,7 +1637,7 @@ AlgorithmBase(Type::Transform, source, source), new_monster_id(new_monster_id) { } int Game_BattleAlgorithm::Transform::GetActionType() { - return 2; + return lcf::rpg::EnemyAction::Kind_transformation; } int Game_BattleAlgorithm::Transform::GetActionId() { @@ -1626,7 +1666,11 @@ AlgorithmBase(Type::DoNothing, source, source) { // no-op } +int Game_BattleAlgorithm::DoNothing::GetActionType() { + return lcf::rpg::EnemyAction::Kind_basic; +} + int Game_BattleAlgorithm::DoNothing::GetActionId() { - return 7; + return lcf::rpg::EnemyAction::Basic_nothing; } diff --git a/src/game_battlealgorithm.h b/src/game_battlealgorithm.h index dacc61b14c..a3829855a3 100644 --- a/src/game_battlealgorithm.h +++ b/src/game_battlealgorithm.h @@ -630,6 +630,9 @@ class None : public AlgorithmBase { public: None(Game_Battler* source); + /** @return the type associated with this action */ + int GetActionType() override; + /** @return the id associated with this action */ int GetActionId() override; }; @@ -644,6 +647,12 @@ class Normal : public AlgorithmBase { Style_MultiHit, }; + /** @return the type associated with this action */ + int GetActionType() override; + + /** @return the id associated with this action */ + int GetActionId() override; + static Style GetDefaultStyle(); Normal(Game_Battler* source, Game_Battler* target, int hits_multiplier = 1, Style style = GetDefaultStyle()); @@ -651,6 +660,7 @@ class Normal : public AlgorithmBase { bool vExecute() override; bool vStart() override; + bool IsDualAttack() const; int GetAnimationId(int i) const override; std::string GetStartMessage(int line) const override; @@ -752,6 +762,9 @@ class Defend : public AlgorithmBase { public: Defend(Game_Battler* source); + /** @return the type associated with this action */ + int GetActionType() override; + /** @return the id associated with this action */ int GetActionId() override; @@ -763,6 +776,9 @@ class Observe : public AlgorithmBase { public: Observe(Game_Battler* source); + /** @return the type associated with this action */ + int GetActionType() override; + /** @return the id associated with this action */ int GetActionId() override; @@ -773,6 +789,9 @@ class Charge : public AlgorithmBase { public: Charge(Game_Battler* source); + /** @return the type associated with this action */ + int GetActionType() override; + /** @return the id associated with this action */ int GetActionId() override; @@ -784,6 +803,9 @@ class SelfDestruct : public AlgorithmBase { public: SelfDestruct(Game_Battler* source, Game_Party_Base* target); + /** @return the type associated with this action */ + int GetActionType() override; + /** @return the id associated with this action */ int GetActionId() override; @@ -799,6 +821,9 @@ class Escape : public AlgorithmBase { public: Escape(Game_Battler* source); + /** @return the type associated with this action */ + int GetActionType() override; + /** @return the id associated with this action */ int GetActionId() override; @@ -830,6 +855,9 @@ class DoNothing : public AlgorithmBase { public: DoNothing(Game_Battler* source); + /** @return the type associated with this action */ + int GetActionType() override; + /** @return the id associated with this action */ int GetActionId() override; }; diff --git a/src/game_battler.cpp b/src/game_battler.cpp index 671b611d7f..221975a69e 100644 --- a/src/game_battler.cpp +++ b/src/game_battler.cpp @@ -368,7 +368,7 @@ bool Game_Battler::AddState(int state_id, bool allow_battle_states) { } Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::SetState, + Game_Interpreter_Battle::ManiacBattleHookType::SetState, GetType() == Game_Battler::Type_Enemy, GetPartyIndex(), state_id diff --git a/src/game_interpreter_battle.cpp b/src/game_interpreter_battle.cpp index 3d1ac489ae..023752e57d 100644 --- a/src/game_interpreter_battle.cpp +++ b/src/game_interpreter_battle.cpp @@ -15,7 +15,7 @@ * along with EasyRPG Player. If not, see . */ -// Headers + // Headers #include "game_actors.h" #include "game_battle.h" #include "game_enemyparty.h" @@ -45,13 +45,19 @@ enum TargetType { // Implemented as a static map, since maniac hooks can only have one common event callback at a time. // Subsequent calls will simply override the previous common event callback. -std::map> Game_Interpreter_Battle::maniac_hooks = { - {AtbIncrement, std::make_tuple(0, 0)}, - {DamagePop, std::make_tuple(0, 0)}, - {Targetting, std::make_tuple(0, 0)}, - {SetState, std::make_tuple(0, 0)}, - {StatChange, std::make_tuple(0, 0)} -}; +std::map> Game_Interpreter_Battle::maniac_hooks; + +void Game_Interpreter_Battle::InitBattle() { + if (Player::IsPatchManiac()) { + Game_Interpreter_Battle::maniac_hooks = { + {Game_Interpreter_Battle::ManiacBattleHookType::AtbIncrement, std::make_tuple(0, 0)}, + {Game_Interpreter_Battle::ManiacBattleHookType::DamagePop, std::make_tuple(0, 0)}, + {Game_Interpreter_Battle::ManiacBattleHookType::Targetting, std::make_tuple(0, 0)}, + {Game_Interpreter_Battle::ManiacBattleHookType::SetState, std::make_tuple(0, 0)}, + {Game_Interpreter_Battle::ManiacBattleHookType::StatChange, std::make_tuple(0, 0)} + }; + } +} static const char* target_text[] = { "actor", "party member", "enemy" }; diff --git a/src/game_interpreter_battle.h b/src/game_interpreter_battle.h index 0fff228ef3..4b83790eca 100644 --- a/src/game_interpreter_battle.h +++ b/src/game_interpreter_battle.h @@ -61,10 +61,12 @@ class Game_Interpreter_Battle : public Game_Interpreter bool ExecuteCommand(lcf::rpg::EventCommand const& com) override; + static void InitBattle(); + /** * All possible hook type events that maniacs offers. */ - enum ManiacBattleHookType { + enum class ManiacBattleHookType { AtbIncrement, DamagePop, Targetting, diff --git a/src/scene_battle_rpg2k3.cpp b/src/scene_battle_rpg2k3.cpp index b4ad096021..68f163f0f9 100644 --- a/src/scene_battle_rpg2k3.cpp +++ b/src/scene_battle_rpg2k3.cpp @@ -60,10 +60,13 @@ Scene_Battle_Rpg2k3::Scene_Battle_Rpg2k3(const BattleArgs& args) : void Scene_Battle_Rpg2k3::Start() { Scene_Battle::Start(); + Game_Interpreter_Battle::InitBattle(); InitBattleCondition(Game_Battle::GetBattleCondition()); CreateEnemySprites(); CreateActorSprites(); + Game_Battle::GetInterpreterBattle(); + // We need to wait for actor and enemy graphics to load before we can finish initializing the battle. AsyncNext([this]() { Start2(); }); } @@ -503,7 +506,7 @@ void Scene_Battle_Rpg2k3::DrawFloatText(int x, int y, int color, StringView text int value = 0; ss >> value; bool should_override = Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::DamagePop, + Game_Interpreter_Battle::ManiacBattleHookType::DamagePop, battler->GetType() == Game_Battler::Type_Enemy, battler->GetPartyIndex(), x, @@ -2234,7 +2237,7 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction damageTaken < 0 ? Font::ColorDefault : Font::ColorHeal, std::to_string(std::abs(damageTaken)), b, - damageTaken < 0 ? Damage : Heal); + damageTaken < 0 ? Scene_Battle_Rpg2k3::FloatTextType::Damage : Scene_Battle_Rpg2k3::FloatTextType::Heal); } if (b->GetType() == Game_Battler::Type_Ally) { auto* sprite = static_cast(b)->GetActorBattleSprite(); @@ -2659,7 +2662,7 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction hp > 0 ? Font::ColorHeal : Font::ColorDefault, std::to_string(std::abs(hp)), target, - hp > 0 ? Heal : Damage); + hp > 0 ? Scene_Battle_Rpg2k3::FloatTextType::Heal : Scene_Battle_Rpg2k3::FloatTextType::Damage); if (action->IsAbsorbHp()) { DrawFloatText( @@ -2668,7 +2671,7 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction hp > 0 ? Font::ColorDefault : Font::ColorHeal, std::to_string(std::abs(hp)), source, - hp > 0 ? Damage : Heal); + hp > 0 ? Scene_Battle_Rpg2k3::FloatTextType::Damage : Scene_Battle_Rpg2k3::FloatTextType::Heal); } } @@ -2691,7 +2694,7 @@ Scene_Battle_Rpg2k3::BattleActionReturn Scene_Battle_Rpg2k3::ProcessBattleAction 0, lcf::Data::terms.miss, target, - Miss); + Scene_Battle_Rpg2k3::FloatTextType::Miss); } status_window->Refresh(); @@ -2856,7 +2859,7 @@ void Scene_Battle_Rpg2k3::ActionSelectedCallback(Game_Battler* for_battler) { auto group_targets = for_battler->GetBattleAlgorithm()->GetOriginalPartyTarget(); // Target: 0 None, 1 Single Enemy, 2 All Enemies, 3 Single Ally, 4 All Allies Game_Battle::ManiacBattleHook( - Game_Interpreter_Battle::Targetting, + Game_Interpreter_Battle::ManiacBattleHookType::Targetting, for_battler->GetType() == Game_Battler::Type_Enemy, for_battler->GetPartyIndex(), for_battler->GetBattleAlgorithm()->GetActionType(), @@ -2953,7 +2956,7 @@ void Scene_Battle_Rpg2k3::OnEventHpChanged(Game_Battler* battler, int hp) { hp < 0 ? Font::ColorDefault : Font::ColorHeal, std::to_string(std::abs(hp)), battler, - hp < 0 ? Damage : Heal); + hp < 0 ? Scene_Battle_Rpg2k3::FloatTextType::Damage : Scene_Battle_Rpg2k3::FloatTextType::Heal); } void Scene_Battle_Rpg2k3::RecreateSpWindow(Game_Battler* battler) { diff --git a/src/scene_battle_rpg2k3.h b/src/scene_battle_rpg2k3.h index c88ab4d882..045d3ce6ac 100644 --- a/src/scene_battle_rpg2k3.h +++ b/src/scene_battle_rpg2k3.h @@ -123,7 +123,7 @@ class Scene_Battle_Rpg2k3 : public Scene_Battle { void RefreshCommandWindow(const Game_Actor* actor); void SetActiveActor(int idx); - enum FloatTextType { + enum class FloatTextType { Damage = 0, Heal = 1, Miss = 2, From 26beabfbb31c35129ef37ff088d254131a666ea8 Mon Sep 17 00:00:00 2001 From: Dino Suvalic <82914521+MakoInfused@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:56:47 -0500 Subject: [PATCH 4/5] removd unused enum --- src/game_battlealgorithm.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/game_battlealgorithm.h b/src/game_battlealgorithm.h index a3829855a3..59f85adb90 100644 --- a/src/game_battlealgorithm.h +++ b/src/game_battlealgorithm.h @@ -83,13 +83,6 @@ class AlgorithmBase { public: virtual ~AlgorithmBase() {} - enum ActionType { - Basic, - Skill, - Transformation, - Item - }; - /** @return the category associated with this action */ virtual int GetActionType(); From 927aeed09d927572212131818cb56b39f33cd194 Mon Sep 17 00:00:00 2001 From: Dino Suvalic <82914521+MakoInfused@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:05:23 -0500 Subject: [PATCH 5/5] implemented maniacs battle common event triggers --- src/scene_battle_rpg2k3.cpp | 30 ++++++++++++++++++++++++++++++ src/scene_battle_rpg2k3.h | 5 +++++ 2 files changed, 35 insertions(+) diff --git a/src/scene_battle_rpg2k3.cpp b/src/scene_battle_rpg2k3.cpp index 68f163f0f9..fe6e94731e 100644 --- a/src/scene_battle_rpg2k3.cpp +++ b/src/scene_battle_rpg2k3.cpp @@ -34,11 +34,13 @@ #include "game_party.h" #include "game_enemy.h" #include "game_enemyparty.h" +#include "game_map.h" #include "game_message.h" #include "game_battle.h" #include "game_interpreter_battle.h" #include "game_battlealgorithm.h" #include "game_screen.h" +#include "game_switches.h" #include #include "scene_gameover.h" #include "utils.h" @@ -973,6 +975,16 @@ void Scene_Battle_Rpg2k3::vUpdate() { break; } + if (state != State_Victory && state != State_Defeat) { + parallel_interpreter.Update(); + if (!parallel_interpreter.IsRunning()) { + for (auto common_event : battle_parallel_events) + { + parallel_interpreter.Push(common_event); + } + } + } + // this is checked separately because we want normal events to be processed // just not sub-events called by maniacs battle hooks. if (state != State_Victory && state != State_Defeat && Game_Battle::ManiacProcessSubEvents()) { @@ -1115,6 +1127,23 @@ Scene_Battle_Rpg2k3::SceneActionReturn Scene_Battle_Rpg2k3::ProcessSceneAction() return SceneActionReturn::eWaitTillNextFrame; } +void Scene_Battle_Rpg2k3::CallBattleBeginCommonEvents() { + for (auto data_common_event : lcf::Data::commonevents) { + if ((!data_common_event.switch_flag || Main_Data::game_switches->Get(data_common_event.switch_id))) { + if (data_common_event.trigger == data_common_event.Trigger_battle_begin) { + Game_CommonEvent* common_event = lcf::ReaderUtil::GetElement(Game_Map::GetCommonEvents(), data_common_event.ID); + + Game_Battle::GetInterpreterBattle().Push(common_event); + } + else if (data_common_event.trigger == data_common_event.Trigger_battle_parallel) { + Game_CommonEvent* common_event = lcf::ReaderUtil::GetElement(Game_Map::GetCommonEvents(), data_common_event.ID); + + battle_parallel_events.push_back(common_event); + } + } + } +} + Scene_Battle_Rpg2k3::SceneActionReturn Scene_Battle_Rpg2k3::ProcessSceneActionStart() { enum SubState { eStartMessage, @@ -1154,6 +1183,7 @@ Scene_Battle_Rpg2k3::SceneActionReturn Scene_Battle_Rpg2k3::ProcessSceneActionSt EndNotification(); UpdateEnemiesDirection(); UpdateActorsDirection(); + CallBattleBeginCommonEvents(); SetSceneActionSubState(eUpdateEvents); return SceneActionReturn::eContinueThisFrame; } diff --git a/src/scene_battle_rpg2k3.h b/src/scene_battle_rpg2k3.h index 045d3ce6ac..81fd62ec51 100644 --- a/src/scene_battle_rpg2k3.h +++ b/src/scene_battle_rpg2k3.h @@ -164,6 +164,8 @@ class Scene_Battle_Rpg2k3 : public Scene_Battle { void SetSceneActionSubState(int substate); void ReturnToMainBattleState(); + void CallBattleBeginCommonEvents(); + // SceneAction State Machine Driver SceneActionReturn ProcessSceneAction(); @@ -260,6 +262,9 @@ class Scene_Battle_Rpg2k3 : public Scene_Battle { int GetNextReadyActor(); std::vector atb_order; + + std::vector battle_parallel_events; + Game_Interpreter_Battle parallel_interpreter; }; #endif