#include "ExperienceLibrary.hpp" #include #include "../PkmnScriptHook.hpp" #include "../Pokemon/Pokemon.hpp" static inline uint32_t CalculateDynamicExperience(level_int_t level, float v1, ArbUt::BorrowedPtr op, ArbUt::BorrowedPtr faintedMon) { float a = 2 * level + 10; float b = level + op->GetLevel() + 10; float v2 = (a * a * sqrt(a)) / (b * b * sqrt(b)); uint32_t experienceGain = v1 * v2 + 1; // TODO: Check owner and international PKMN_HOOK(ModifyExperienceGain, op, faintedMon.GetRaw(), op.GetRaw(), &experienceGain); return experienceGain; } void PkmnLib::Battling::ExperienceLibrary::HandleExperienceGain( CreatureLib::Battling::Creature* faintedMon, const std::unordered_set>& opponents) const { auto fainted = dynamic_cast(faintedMon); EnsureNotNull(fainted); auto& forme = fainted->GetForme(); auto expGain = forme->GetBaseExperience(); auto level = fainted->GetLevel(); float v1 = (expGain * level) / 5; for (const auto& op : opponents) { if (!op->AllowedExperienceGain()) continue; auto experienceGain = CalculateDynamicExperience(level, v1, op, fainted); op->AddExperience(experienceGain); } auto battle = fainted->GetBattle(); if (!battle.HasValue()) { return; } std::unordered_set shareExperience; for (const auto& party : battle.GetValue()->GetParties()) { for (const auto& mon : party->GetParty()->GetParty()) { if (mon == nullptr) continue; // If the mon is not allowed to gain experience, or is fainted, don't check for experience sharing. if (!mon->AllowedExperienceGain() || mon->IsFainted()) continue; // If the mon is already in the opponents set, don't check for experience sharing. if (opponents.find(mon) != opponents.end()) continue; bool sharedExp = false; PKMN_HOOK(DoesShareExperience, mon, faintedMon, mon, &sharedExp); if (sharedExp) { shareExperience.insert(mon); } } } if (shareExperience.size() == 0) return; v1 /= 2; for (auto op : shareExperience) { auto experienceGain = CalculateDynamicExperience(level, v1, op, faintedMon); op->AddExperience(experienceGain); } }