diff --git a/src/Battling/Flow/TurnHandler.cpp b/src/Battling/Flow/TurnHandler.cpp index b1e7716..08b164f 100644 --- a/src/Battling/Flow/TurnHandler.cpp +++ b/src/Battling/Flow/TurnHandler.cpp @@ -89,6 +89,8 @@ void CreatureLib::Battling::TurnHandler::HandleAttackForTarget(CreatureLib::Batt return; auto user = attack.GetUser(); auto attackData = attack.GetAttack()->GetAttack(); + auto library = user->GetBattle()->GetLibrary(); + auto dmgLibrary = library->GetDamageLibrary(); for (uint8_t hitIndex = 0; hitIndex < numHits; hitIndex++){ if (user->IsFainted()){ break; @@ -98,9 +100,13 @@ void CreatureLib::Battling::TurnHandler::HandleAttackForTarget(CreatureLib::Batt break; } auto hit = targetData.GetHit(hitIndex); - //TODO: calculate data for hit - hit.SetEffectiveness(user->GetBattle()->GetLibrary()->GetTypeLibrary()->GetEffectiveness(hit.GetType(), target->GetTypes())); + //HOOK: Change move type + hit.SetEffectiveness(library->GetTypeLibrary()->GetEffectiveness(hit.GetType(), target->GetTypes())); + //TODO: Critical calculation + hit.SetCritical(false); + hit.SetBasePower(dmgLibrary->GetBasePower(&attack, target, hitIndex)); + hit.SetDamage(dmgLibrary->GetDamage(&attack, target, hitIndex)); if (attackData->GetCategory() == Library::AttackCategory::Status){ //HOOK: Status attack @@ -109,7 +115,7 @@ void CreatureLib::Battling::TurnHandler::HandleAttackForTarget(CreatureLib::Batt auto damage = hit.GetDamage(); if (damage > target->GetCurrentHealth()){ damage = target->GetCurrentHealth(); - hit.OverrideDamage(damage); + hit.SetDamage(damage); } if (damage > 0){ target->Damage(damage, DamageSource::AttackDamage); diff --git a/src/Battling/Library/BattleLibrary.cpp b/src/Battling/Library/BattleLibrary.cpp index c457af8..574ea14 100644 --- a/src/Battling/Library/BattleLibrary.cpp +++ b/src/Battling/Library/BattleLibrary.cpp @@ -29,3 +29,12 @@ const CreatureLib::Library::ItemLibrary* CreatureLib::Battling::BattleLibrary::G const CreatureLib::Library::AttackLibrary *CreatureLib::Battling::BattleLibrary::GetAttackLibrary() const { return _staticLib->GetAttackLibrary(); } + +const CreatureLib::Library::TypeLibrary *CreatureLib::Battling::BattleLibrary::GetTypeLibrary() const { + return _staticLib->GetTypeLibrary(); +} + +const CreatureLib::Battling::DamageLibrary *CreatureLib::Battling::BattleLibrary::GetDamageLibrary() const { + return _damageLibrary; +} + diff --git a/src/Battling/Library/BattleLibrary.hpp b/src/Battling/Library/BattleLibrary.hpp index f3cab37..aa3aefa 100644 --- a/src/Battling/Library/BattleLibrary.hpp +++ b/src/Battling/Library/BattleLibrary.hpp @@ -3,11 +3,13 @@ #include "BattleStatCalculator.hpp" #include "../../Library/DataLibrary.hpp" +#include "DamageLibrary.hpp" namespace CreatureLib::Battling { class BattleLibrary { const Library::DataLibrary* _staticLib; BattleStatCalculator* _statCalculator; + DamageLibrary* _damageLibrary; public: BattleLibrary(Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator); ~BattleLibrary(); @@ -19,6 +21,7 @@ namespace CreatureLib::Battling { const Library::TypeLibrary* GetTypeLibrary() const; const BattleStatCalculator* GetStatCalculator() const; + const DamageLibrary* GetDamageLibrary() const; }; } diff --git a/src/Battling/Library/DamageLibrary.cpp b/src/Battling/Library/DamageLibrary.cpp new file mode 100644 index 0000000..c685027 --- /dev/null +++ b/src/Battling/Library/DamageLibrary.cpp @@ -0,0 +1,66 @@ +#include "DamageLibrary.hpp" + +using namespace CreatureLib::Battling; +int DamageLibrary::GetDamage(ExecutingAttack *attack, Creature *target, uint8_t hitIndex) const{ + auto levelMod = static_cast(2 * attack->GetUser()->GetLevel()); + auto hit = attack->GetAttackDataForTarget(target).GetHit(hitIndex); + auto bp = hit.GetBasePower(); + auto statMod = GetStatModifier(attack, target, hitIndex); + //HOOK: Modify stat modifier + int damage = static_cast((((levelMod * static_cast(bp) * statMod) / 50) + 2) + * GetDamageModifier(attack, target, hitIndex)); + //HOOK: Override damage + return damage; +} + +int DamageLibrary::GetBasePower(ExecutingAttack *attack, Creature *target, uint8_t hitIndex) const{ + auto bp = attack->GetAttack()->GetAttack()->GetBasePower(); + //HOOK: modify base power. + return bp; +} + +float DamageLibrary::GetStatModifier(ExecutingAttack *attack, Creature *target, uint8_t hitIndex) const{ + auto user = attack->GetUser(); + //HOOK: allow overriding for which users stat we use. + auto hit = attack->GetAttackDataForTarget(target).GetHit(hitIndex); + Core::Statistic offensiveStat; + Core::Statistic defensiveStat; + if (attack->GetAttack()->GetAttack()->GetCategory() == Library::AttackCategory::Physical){ + offensiveStat = Core::Statistic::PhysicalAttack; + defensiveStat = Core::Statistic::PhysicalDefense; + } + else{ + offensiveStat = Core::Statistic::MagicalAttack; + defensiveStat = Core::Statistic::MagicalDefense; + } + + auto bypassDefensive = hit.IsCritical() && target->GetStatBoost(defensiveStat) > 0; + //HOOK: allow bypassing defensive stat modifiers. + auto bypassOffensive = hit.IsCritical() && user->GetStatBoost(offensiveStat) < 0; + //HOOK: Allow bypassing offensive stat modifiers. + + float offensiveValue; + float defensiveValue; + + if (bypassOffensive){ + offensiveValue = user->GetFlatStat(offensiveStat); + } else{ + offensiveValue = user->GetBoostedStat(offensiveStat); + } + if (bypassDefensive){ + defensiveValue = target->GetFlatStat(defensiveStat); + } else{ + defensiveValue = target->GetBoostedStat(defensiveStat); + } + + return offensiveValue / defensiveValue; +} + +float DamageLibrary::GetDamageModifier(ExecutingAttack *attack, Creature *target, uint8_t hitIndex) const{ + float mod = 1; + auto hit = attack->GetAttackDataForTarget(target).GetHit(hitIndex); + mod *= hit.GetEffectiveness(); + //HOOK: Modify damage modifier. + return mod; +} + diff --git a/src/Battling/Library/DamageLibrary.hpp b/src/Battling/Library/DamageLibrary.hpp new file mode 100644 index 0000000..10637ec --- /dev/null +++ b/src/Battling/Library/DamageLibrary.hpp @@ -0,0 +1,19 @@ +#ifndef CREATURELIB_DAMAGELIBRARY_HPP +#define CREATURELIB_DAMAGELIBRARY_HPP + +#include "../Models/Creature.hpp" +#include "../Models/ExecutingAttack.hpp" + +namespace CreatureLib::Battling{ + class DamageLibrary { + public: + virtual int GetDamage(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const; + + virtual int GetBasePower(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const; + virtual float GetStatModifier(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const; + virtual float GetDamageModifier(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const; + }; +} + + +#endif //CREATURELIB_DAMAGELIBRARY_HPP diff --git a/src/Battling/Models/Creature.cpp b/src/Battling/Models/Creature.cpp index 9ad84d8..861415f 100644 --- a/src/Battling/Models/Creature.cpp +++ b/src/Battling/Models/Creature.cpp @@ -1,3 +1,4 @@ +#include #include "Creature.hpp" #include "../Models/Battle.hpp" @@ -84,6 +85,10 @@ uint32_t Battling::Creature::GetStatExperience(Core::Statistic stat) const { return __StatExperience.GetStat(stat); } +int8_t Battling::Creature::GetStatBoost(Core::Statistic stat) const { + return _statBoost.GetStat(stat); +} + void Battling::Creature::RecalculateFlatStats() { this->_flatStats = this->_library->GetStatCalculator()->CalculateFlatStats(this); RecalculateBoostedStats(); @@ -129,3 +134,8 @@ const std::vector& Battling::Creature::GetTypes() const { //HOOK: override types. return this->__Variant->GetTypes(); } + +bool Battling::Creature::HasType(uint8_t type) const { + auto t = GetTypes(); + return std::find(t.begin(), t.end(), type) != t.end(); +} diff --git a/src/Battling/Models/Creature.hpp b/src/Battling/Models/Creature.hpp index 4f99cc8..9852034 100644 --- a/src/Battling/Models/Creature.hpp +++ b/src/Battling/Models/Creature.hpp @@ -53,8 +53,9 @@ namespace CreatureLib::Battling{ Battle* GetBattle() const; BattleSide* GetBattleSide() const; - bool IsFainted() const; - const std::vector& GetTypes() const; + [[nodiscard]] bool IsFainted() const; + [[nodiscard]] const std::vector& GetTypes() const; + [[nodiscard]] bool HasType(uint8_t type) const; //region Stat APIs @@ -67,6 +68,7 @@ namespace CreatureLib::Battling{ [[nodiscard]] uint32_t GetBaseStat(Core::Statistic stat) const; [[nodiscard]] uint32_t GetStatPotential(Core::Statistic stat) const; [[nodiscard]] uint32_t GetStatExperience(Core::Statistic stat) const; + [[nodiscard]] int8_t GetStatBoost(Core::Statistic stat) const; void RecalculateFlatStats(); void RecalculateBoostedStats(); void RecalculateFlatStat(Core::Statistic); diff --git a/src/Battling/Models/ExecutingAttack.hpp b/src/Battling/Models/ExecutingAttack.hpp index 81698f6..421d382 100644 --- a/src/Battling/Models/ExecutingAttack.hpp +++ b/src/Battling/Models/ExecutingAttack.hpp @@ -27,7 +27,7 @@ namespace CreatureLib::Battling { inline void SetCritical(bool value) {_critical = value;} inline void SetBasePower(uint8_t value) { _basePower = value; } inline void SetEffectiveness(float value) {_effectiveness = value;} - inline void OverrideDamage(uint32_t value) {_damage = value;} + inline void SetDamage(uint32_t value) { _damage = value;} inline void SetType(uint8_t value) {_type = value;} };