Support for experience sharing.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2020-05-24 13:36:45 +02:00
parent d6792635f9
commit 0d111739f4
6 changed files with 76 additions and 7 deletions

View File

@@ -1,7 +1,19 @@
#include "ExperienceLibrary.hpp"
#include <CreatureLib/Battling/Models/Battle.hpp>
#include "../PkmnScriptHook.hpp"
#include "../Pokemon/Pokemon.hpp"
static inline uint32_t CalculateDynamicExperience(uint8_t level, float v1, CreatureLib::Battling::Creature* op,
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, op, &experienceGain);
return experienceGain;
}
void PkmnLib::Battling::ExperienceLibrary::HandleExperienceGain(
CreatureLib::Battling::Creature* faintedMon,
const std::unordered_set<CreatureLib::Battling::Creature*>& opponents) const {
@@ -9,17 +21,45 @@ void PkmnLib::Battling::ExperienceLibrary::HandleExperienceGain(
auto fainted = dynamic_cast<Pokemon*>(faintedMon);
auto expGain = fainted->GetForme()->GetBaseExperience();
auto level = fainted->GetLevel();
// TODO exp share
auto v1 = (expGain * level) / 5;
float v1 = (expGain * level) / 5;
for (auto op : opponents) {
if (!op->AllowedExperienceGain())
continue;
auto v2 = pow(2 * level + 10, 2.5) / pow(level + op->GetLevel() + 10, 2.5);
uint32_t experienceGain = v1 * v2 + 1;
// TODO: Check owner and international
PKMN_HOOK(ModifyExperienceGain, op, faintedMon, op, experienceGain);
auto experienceGain = CalculateDynamicExperience(level, v1, op, fainted);
op->AddExperience(experienceGain);
}
auto battle = fainted->GetBattle();
if (battle == nullptr) {
return;
}
std::unordered_set<CreatureLib::Battling::Creature*> shareExperience;
for (const auto& party : battle->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);
}
}

View File

@@ -8,7 +8,9 @@ namespace PkmnLib::Battling {
virtual void ModifyCriticalStage(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, uint8_t hit, uint8_t* critStage){};
virtual void ModifyExperienceGain(CreatureLib::Battling::Creature* faintedMon,
CreatureLib::Battling::Creature* winningMon, uint32_t experienceGain){};
CreatureLib::Battling::Creature* winningMon, uint32_t* experienceGain){};
virtual void DoesShareExperience(CreatureLib::Battling::Creature* faintedMon,
CreatureLib::Battling::Creature* winningMon, bool* shareExperience){};
};
}