69 lines
2.6 KiB
C++
69 lines
2.6 KiB
C++
#include "ExperienceLibrary.hpp"
|
|
#include <CreatureLib/Battling/Models/Battle.hpp>
|
|
#include "../PkmnScriptHook.hpp"
|
|
#include "../Pokemon/Pokemon.hpp"
|
|
|
|
static inline uint32_t CalculateDynamicExperience(level_int_t level, float v1,
|
|
ArbUt::BorrowedPtr<CreatureLib::Battling::Creature> op,
|
|
ArbUt::BorrowedPtr<CreatureLib::Battling::Creature> 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<ArbUt::BorrowedPtr<CreatureLib::Battling::Creature>>& opponents) const {
|
|
|
|
auto fainted = dynamic_cast<Pokemon*>(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<CreatureLib::Battling::Creature*> 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);
|
|
}
|
|
}
|