Support for experience sharing.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-05-24 13:36:45 +02:00
parent d6792635f9
commit 0d111739f4
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
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){};
};
}

View File

@ -258,3 +258,19 @@ void AngelScriptScript::ModifyCriticalStage(CreatureLib::Battling::ExecutingAtta
ctx->SetArgAddress(3, critStage);
})
}
void AngelScriptScript::ModifyExperienceGain(CreatureLib::Battling::Creature* faintedMon,
CreatureLib::Battling::Creature* winningMon, uint32_t* experienceGain) {
CALL_HOOK(ModifyExperienceGain, {
ctx->SetArgObject(0, (void*)faintedMon);
ctx->SetArgObject(1, (void*)winningMon);
ctx->SetArgAddress(2, experienceGain);
})
}
void AngelScriptScript::DoesShareExperience(CreatureLib::Battling::Creature* faintedMon,
CreatureLib::Battling::Creature* winningMon, bool* shareExperience) {
CALL_HOOK(DoesShareExperience, {
ctx->SetArgObject(0, (void*)faintedMon);
ctx->SetArgObject(1, (void*)winningMon);
ctx->SetArgAddress(2, shareExperience);
})
}

View File

@ -104,6 +104,11 @@ public:
void ModifyCriticalStage(CreatureLib::Battling::ExecutingAttack* attack, CreatureLib::Battling::Creature* target,
uint8_t hit, uint8_t* critStage) override;
void ModifyExperienceGain(CreatureLib::Battling::Creature* faintedMon, CreatureLib::Battling::Creature* winningMon,
uint32_t* experienceGain) override;
void DoesShareExperience(CreatureLib::Battling::Creature* faintedMon, CreatureLib::Battling::Creature* winningMon,
bool* shareExperience) override;
};
#undef CALL_HOOK

View File

@ -131,6 +131,10 @@ public:
SCRIPT_HOOK_FUNCTION(
ModifyCriticalStage,
"void ModifyCriticalStage(ExecutingMove@ attack, Pokemon@ target, uint8 hit, uint8& critStage)");
SCRIPT_HOOK_FUNCTION(ModifyExperienceGain,
"void ModifyExperienceGain(Pokemon@ faintedMon, Pokemon@ winningMon, uint32& critStage)");
SCRIPT_HOOK_FUNCTION(DoesShareExperience,
"void DoesShareExperience(Pokemon@ faintedMon, Pokemon@ winningMon, bool& shareExperience)");
};
#undef SCRIPT_HOOK_FUNCTION

View File

@ -39,6 +39,8 @@ shared abstract class PkmnScript {
// PkmnLib methods
void ModifyCriticalStage(ExecutingMove@ attack, Pokemon@ target, uint8 hit, uint8& critStage){};
void ModifyExperienceGain(Pokemon@ faintedMon, Pokemon@ winningMon, uint32& critStage){};
void DoesShareExperience(Pokemon@ faintedMon, Pokemon@ winningMon, bool& shareExperience){};
}
)");
assert(r >= 0);