#include "DamageLibrary.hpp" #include "../ScriptHandling/ScriptMacros.hpp" using namespace CreatureLib::Battling; u32 DamageLibrary::GetDamage(ExecutingAttack* non_null attack, Creature* non_null target, u8 hitIndex, const ExecutingAttack::HitData& hitData) const { EnsureNotNull(attack) EnsureNotNull(target) auto levelMod = static_cast(2 * attack->GetUser()->GetLevel()) / 5 + 2; auto bp = hitData.GetBasePower(); auto statMod = GetStatModifier(attack, target, hitIndex, hitData); HOOK(ModifyStatModifier, attack, attack, target, hitIndex, &statMod); u32 damage = static_cast((((levelMod * static_cast(bp) * statMod) / 50) + 2) * GetDamageModifier(attack, target, hitIndex, hitData)); HOOK(OverrideDamage, attack, attack, target, hitIndex, &damage); HOOK(OverrideIncomingDamage, target, attack, target, hitIndex, &damage); return damage; } u8 DamageLibrary::GetBasePower(ExecutingAttack* non_null attack, Creature* non_null target, u8 hitIndex, [[maybe_unused]] const ExecutingAttack::HitData& hitData) const { EnsureNotNull(attack) EnsureNotNull(target) auto bp = attack->GetUseAttack()->GetBasePower(); HOOK(OverrideBasePower, attack, attack, target, hitIndex, &bp); return bp; } float DamageLibrary::GetStatModifier(ExecutingAttack* non_null attack, Creature* non_null target, u8 hitIndex, const ExecutingAttack::HitData& hitData) const { EnsureNotNull(attack) EnsureNotNull(target) auto user = attack->GetUser().GetRaw(); EnsureNotNull(user) HOOK(ChangeDamageStatsUser, attack, attack, target, hitIndex, &user); Library::Statistic offensiveStat; Library::Statistic defensiveStat; if (attack->GetUseAttack()->GetCategory() == Library::AttackCategory::Physical) { offensiveStat = Library::Statistic::PhysicalAttack; defensiveStat = Library::Statistic::PhysicalDefense; } else { offensiveStat = Library::Statistic::MagicalAttack; defensiveStat = Library::Statistic::MagicalDefense; } auto bypassDefensive = hitData.IsCritical() && target->GetStatBoost(defensiveStat) > 0; HOOK(BypassDefensiveStat, attack, attack, target, hitIndex, &bypassDefensive); auto bypassOffensive = hitData.IsCritical() && user->GetStatBoost(offensiveStat) < 0; HOOK(BypassOffensiveStat, attack, attack, target, hitIndex, &bypassOffensive); 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* non_null attack, Creature* non_null target, u8 hitIndex, const ExecutingAttack::HitData& hitData) const { EnsureNotNull(attack) EnsureNotNull(target) float mod = 1; mod *= hitData.GetEffectiveness(); HOOK(ModifyDamageModifier, attack, attack, target, hitIndex, &mod); return mod; }