Implements experience gain on opponent faint.
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
3baed93597
commit
649de39571
|
@ -5,15 +5,16 @@ using namespace CreatureLib::Battling;
|
||||||
|
|
||||||
BattleLibrary::BattleLibrary(CreatureLib::Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator,
|
BattleLibrary::BattleLibrary(CreatureLib::Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator,
|
||||||
DamageLibrary* damageLibrary, CriticalLibrary* criticalLibrary,
|
DamageLibrary* damageLibrary, CriticalLibrary* criticalLibrary,
|
||||||
ScriptResolver* scriptResolver)
|
ExperienceLibrary* experienceLibrary, ScriptResolver* scriptResolver)
|
||||||
: _staticLib(staticLib), _statCalculator(statCalculator), _damageLibrary(damageLibrary),
|
: _staticLib(staticLib), _statCalculator(statCalculator), _damageLibrary(damageLibrary),
|
||||||
_criticalLibrary(criticalLibrary), _scriptResolver(scriptResolver) {}
|
_criticalLibrary(criticalLibrary), _experienceLibrary(experienceLibrary), _scriptResolver(scriptResolver) {}
|
||||||
|
|
||||||
BattleLibrary::~BattleLibrary() {
|
BattleLibrary::~BattleLibrary() {
|
||||||
delete _staticLib;
|
delete _staticLib;
|
||||||
delete _statCalculator;
|
delete _statCalculator;
|
||||||
delete _damageLibrary;
|
delete _damageLibrary;
|
||||||
delete _criticalLibrary;
|
delete _criticalLibrary;
|
||||||
|
delete _experienceLibrary;
|
||||||
delete _scriptResolver;
|
delete _scriptResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "BattleStatCalculator.hpp"
|
#include "BattleStatCalculator.hpp"
|
||||||
#include "CriticalLibrary.hpp"
|
#include "CriticalLibrary.hpp"
|
||||||
#include "DamageLibrary.hpp"
|
#include "DamageLibrary.hpp"
|
||||||
|
#include "ExperienceLibrary.hpp"
|
||||||
|
|
||||||
namespace CreatureLib::Battling {
|
namespace CreatureLib::Battling {
|
||||||
class BattleLibrary {
|
class BattleLibrary {
|
||||||
|
@ -13,11 +14,13 @@ namespace CreatureLib::Battling {
|
||||||
BattleStatCalculator* _statCalculator = nullptr;
|
BattleStatCalculator* _statCalculator = nullptr;
|
||||||
DamageLibrary* _damageLibrary = nullptr;
|
DamageLibrary* _damageLibrary = nullptr;
|
||||||
CriticalLibrary* _criticalLibrary = nullptr;
|
CriticalLibrary* _criticalLibrary = nullptr;
|
||||||
|
ExperienceLibrary* _experienceLibrary = nullptr;
|
||||||
ScriptResolver* _scriptResolver = nullptr;
|
ScriptResolver* _scriptResolver = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BattleLibrary(Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator,
|
BattleLibrary(Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator,
|
||||||
DamageLibrary* damageLibrary, CriticalLibrary* criticalLibrary, ScriptResolver* scriptResolver);
|
DamageLibrary* damageLibrary, CriticalLibrary* criticalLibrary,
|
||||||
|
ExperienceLibrary* experienceLibrary, ScriptResolver* scriptResolver);
|
||||||
~BattleLibrary();
|
~BattleLibrary();
|
||||||
|
|
||||||
[[nodiscard]] const Library::LibrarySettings& GetSettings() const;
|
[[nodiscard]] const Library::LibrarySettings& GetSettings() const;
|
||||||
|
@ -25,10 +28,14 @@ namespace CreatureLib::Battling {
|
||||||
[[nodiscard]] const Library::ItemLibrary* GetItemLibrary() const;
|
[[nodiscard]] const Library::ItemLibrary* GetItemLibrary() const;
|
||||||
[[nodiscard]] const Library::AttackLibrary* GetAttackLibrary() const;
|
[[nodiscard]] const Library::AttackLibrary* GetAttackLibrary() const;
|
||||||
[[nodiscard]] const Library::TypeLibrary* GetTypeLibrary() const;
|
[[nodiscard]] const Library::TypeLibrary* GetTypeLibrary() const;
|
||||||
|
[[nodiscard]] const Library::GrowthRateLibrary* GetGrowthRateLibrary() const {
|
||||||
|
return _staticLib->GetGrowthRates();
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] const BattleStatCalculator* GetStatCalculator() const;
|
[[nodiscard]] const BattleStatCalculator* GetStatCalculator() const;
|
||||||
[[nodiscard]] const DamageLibrary* GetDamageLibrary() const;
|
[[nodiscard]] const DamageLibrary* GetDamageLibrary() const;
|
||||||
[[nodiscard]] const CriticalLibrary* GetCriticalLibrary() const;
|
[[nodiscard]] const CriticalLibrary* GetCriticalLibrary() const;
|
||||||
|
[[nodiscard]] const ExperienceLibrary* GetExperienceLibrary() const { return _experienceLibrary; }
|
||||||
|
|
||||||
[[nodiscard]] Script* LoadScript(ScriptResolver::ScriptCategory category, const std::string& scriptName) const;
|
[[nodiscard]] Script* LoadScript(ScriptResolver::ScriptCategory category, const std::string& scriptName) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "ExperienceLibrary.hpp"
|
||||||
|
#include "../Models/Creature.hpp"
|
||||||
|
|
||||||
|
void CreatureLib::Battling::ExperienceLibrary::HandleExperienceGain(
|
||||||
|
CreatureLib::Battling::Creature* faintedMon, const std::unordered_set<Creature*>& opponents) const {
|
||||||
|
for (auto opponent : opponents) {
|
||||||
|
auto levelDiff = faintedMon->GetLevel() - opponent->GetLevel() + 10;
|
||||||
|
if (levelDiff <= 0)
|
||||||
|
continue;
|
||||||
|
auto experienceGain = levelDiff * 10;
|
||||||
|
opponent->AddExperience(static_cast<uint32_t>(experienceGain));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef CREATURELIB_EXPERIENCELIBRARY_HPP
|
||||||
|
#define CREATURELIB_EXPERIENCELIBRARY_HPP
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace CreatureLib::Battling {
|
||||||
|
class Creature;
|
||||||
|
|
||||||
|
class ExperienceLibrary {
|
||||||
|
public:
|
||||||
|
virtual ~ExperienceLibrary() = default;
|
||||||
|
|
||||||
|
virtual void HandleExperienceGain(Creature* faintedMon, const std::unordered_set<Creature*>& opponents) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CREATURELIB_EXPERIENCELIBRARY_HPP
|
|
@ -92,6 +92,16 @@ Battling::BattleSide* Battling::Creature::GetBattleSide() const { return _side;
|
||||||
|
|
||||||
bool Battling::Creature::IsFainted() const { return this->__CurrentHealth <= 0; }
|
bool Battling::Creature::IsFainted() const { return this->__CurrentHealth <= 0; }
|
||||||
|
|
||||||
|
void Battling::Creature::OnFaint() {
|
||||||
|
// HOOK: On Faint
|
||||||
|
_library->GetExperienceLibrary()->HandleExperienceGain(this, _seenOpponents);
|
||||||
|
|
||||||
|
if (!_battle->CanSlotBeFilled(_side->GetSideIndex(), _side->GetCreatureIndex(this))) {
|
||||||
|
_side->MarkSlotAsUnfillable(this);
|
||||||
|
}
|
||||||
|
_battle->ValidateBattleState();
|
||||||
|
}
|
||||||
|
|
||||||
void Battling::Creature::Damage(uint32_t damage, Battling::DamageSource source) {
|
void Battling::Creature::Damage(uint32_t damage, Battling::DamageSource source) {
|
||||||
if (damage > __CurrentHealth) {
|
if (damage > __CurrentHealth) {
|
||||||
damage = __CurrentHealth;
|
damage = __CurrentHealth;
|
||||||
|
@ -100,10 +110,7 @@ void Battling::Creature::Damage(uint32_t damage, Battling::DamageSource source)
|
||||||
__CurrentHealth -= damage;
|
__CurrentHealth -= damage;
|
||||||
|
|
||||||
if (IsFainted() && damage > 0) {
|
if (IsFainted() && damage > 0) {
|
||||||
if (!_battle->CanSlotBeFilled(_side->GetSideIndex(), _side->GetCreatureIndex(this))) {
|
OnFaint();
|
||||||
_side->MarkSlotAsUnfillable(this);
|
|
||||||
}
|
|
||||||
_battle->ValidateBattleState();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,3 +137,16 @@ void Battling::Creature::GetActiveScripts(std::vector<ScriptWrapper>& scripts) {
|
||||||
_side->GetActiveScripts(scripts);
|
_side->GetActiveScripts(scripts);
|
||||||
}
|
}
|
||||||
void Battling::Creature::ClearVolatileScripts() { _volatile.Clear(); }
|
void Battling::Creature::ClearVolatileScripts() { _volatile.Clear(); }
|
||||||
|
void Battling::Creature::AddExperience(uint32_t amount) {
|
||||||
|
auto maxLevel = _library->GetSettings().GetMaximalLevel();
|
||||||
|
if (__Level >= maxLevel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto exp = __Experience + amount;
|
||||||
|
auto level = _library->GetGrowthRateLibrary()->CalculateLevel(this->GetSpecies()->GetGrowthRate(), exp);
|
||||||
|
if (level >= maxLevel) {
|
||||||
|
exp = _library->GetGrowthRateLibrary()->CalculateExperience(this->GetSpecies()->GetGrowthRate(), maxLevel);
|
||||||
|
}
|
||||||
|
__Experience = exp;
|
||||||
|
__Level = level;
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,8 @@ namespace CreatureLib::Battling {
|
||||||
Script* _status = nullptr;
|
Script* _status = nullptr;
|
||||||
ScriptSet _volatile = {};
|
ScriptSet _volatile = {};
|
||||||
|
|
||||||
|
void OnFaint();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Creature(const BattleLibrary* library, const Library::CreatureSpecies* species,
|
Creature(const BattleLibrary* library, const Library::CreatureSpecies* species,
|
||||||
const Library::SpeciesVariant* variant, uint8_t level, uint32_t experience,
|
const Library::SpeciesVariant* variant, uint8_t level, uint32_t experience,
|
||||||
|
@ -83,6 +85,7 @@ namespace CreatureLib::Battling {
|
||||||
void ChangeLevel(int8_t amount);
|
void ChangeLevel(int8_t amount);
|
||||||
void Damage(uint32_t damage, DamageSource source);
|
void Damage(uint32_t damage, DamageSource source);
|
||||||
void OverrideActiveTalent(const std::string& talent);
|
void OverrideActiveTalent(const std::string& talent);
|
||||||
|
void AddExperience(uint32_t amount);
|
||||||
|
|
||||||
void MarkOpponentAsSeen(Creature* creature) { _seenOpponents.insert(creature); }
|
void MarkOpponentAsSeen(Creature* creature) { _seenOpponents.insert(creature); }
|
||||||
const std::unordered_set<Creature*>& GetSeenOpponents() const { return _seenOpponents; }
|
const std::unordered_set<Creature*>& GetSeenOpponents() const { return _seenOpponents; }
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace CreatureLib::Library {
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] uint8_t CalculateLevel(const std::string& growthRate, uint32_t experience) const;
|
[[nodiscard]] uint8_t CalculateLevel(const std::string& growthRate, uint32_t experience) const;
|
||||||
[[nodiscard]] uint32_t CalculateExperience(const std::string& growthRate, uint8_t level) const;
|
[[nodiscard]] uint32_t CalculateExperience(const std::string& growthRate, uint8_t level) const;
|
||||||
|
|
||||||
|
void AddGrowthRate(std::string name, GrowthRate* rate) { _growthRates.insert({name, rate}); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef CREATURELIB_LOOKUPGROWTHRATE_HPP
|
||||||
|
#define CREATURELIB_LOOKUPGROWTHRATE_HPP
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "GrowthRate.hpp"
|
||||||
|
namespace CreatureLib::Library {
|
||||||
|
class LookupGrowthRate : public GrowthRate {
|
||||||
|
protected:
|
||||||
|
std::vector<int32_t> _experience = {
|
||||||
|
0, 15, 52, 122, 237, 406, 637, 942, 1326, 1800, 2369, 3041, 3822,
|
||||||
|
4719, 5737, 6881, 8155, 9564, 11111, 12800, 14632, 16610, 18737, 21012, 23437, 26012,
|
||||||
|
28737, 31610, 34632, 37800, 41111, 44564, 48155, 51881, 55737, 59719, 63822, 68041, 72369,
|
||||||
|
76800, 81326, 85942, 90637, 95406, 100237, 105122, 110052, 115015, 120001, 125000, 131324, 137795,
|
||||||
|
144410, 151165, 158056, 165079, 172229, 179503, 186894, 194400, 202013, 209728, 217540, 225443, 233431,
|
||||||
|
241496, 249633, 257834, 267406, 276458, 286328, 296358, 305767, 316074, 326531, 336255, 346965, 357812,
|
||||||
|
367807, 378880, 390077, 400293, 411686, 423190, 433572, 445239, 457001, 467489, 479378, 491346, 501878,
|
||||||
|
513934, 526049, 536557, 548720, 560922, 571333, 583539, 591882, 600000};
|
||||||
|
|
||||||
|
public:
|
||||||
|
uint8_t CalculateLevel(uint32_t experience) const override {
|
||||||
|
for (uint8_t i = 0; i < _experience.size(); i++) {
|
||||||
|
if (_experience[i] > experience) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _experience[_experience.size() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CalculateExperience(uint8_t level) const override { return _experience[level - 1]; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CREATURELIB_LOOKUPGROWTHRATE_HPP
|
|
@ -1,35 +1,37 @@
|
||||||
#ifdef TESTS_BUILD
|
#ifdef TESTS_BUILD
|
||||||
|
|
||||||
#include "TestLibrary.hpp"
|
#include "TestLibrary.hpp"
|
||||||
|
#include "../../src/Library/GrowthRates/LookupGrowthRate.hpp"
|
||||||
|
|
||||||
using namespace CreatureLib::Core;
|
using namespace CreatureLib::Core;
|
||||||
using namespace CreatureLib::Library;
|
using namespace CreatureLib::Library;
|
||||||
using namespace CreatureLib::Battling;
|
using namespace CreatureLib::Battling;
|
||||||
BattleLibrary* TestLibrary::_library = nullptr;
|
BattleLibrary* TestLibrary::_library = nullptr;
|
||||||
|
|
||||||
BattleLibrary *TestLibrary::Get() {
|
BattleLibrary* TestLibrary::Get() {
|
||||||
if (TestLibrary::_library == nullptr){
|
if (TestLibrary::_library == nullptr) {
|
||||||
auto l = new DataLibrary(LibrarySettings(100, 4), BuildSpeciesLibrary(), BuildAttackLibrary(), BuildItemLibrary(),
|
auto l = new DataLibrary(LibrarySettings(100, 4), BuildSpeciesLibrary(), BuildAttackLibrary(),
|
||||||
BuildGrowthRateLibrary(), BuildTypeLibrary());
|
BuildItemLibrary(), BuildGrowthRateLibrary(), BuildTypeLibrary());
|
||||||
auto statCalc = new BattleStatCalculator();
|
auto statCalc = new BattleStatCalculator();
|
||||||
auto battleLib = new BattleLibrary(l, statCalc, new DamageLibrary(), new CriticalLibrary(), new ScriptResolver());
|
auto battleLib = new BattleLibrary(l, statCalc, new DamageLibrary(), new CriticalLibrary(),
|
||||||
|
new ExperienceLibrary(), new ScriptResolver());
|
||||||
TestLibrary::_library = battleLib;
|
TestLibrary::_library = battleLib;
|
||||||
}
|
}
|
||||||
return TestLibrary::_library;
|
return TestLibrary::_library;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeciesLibrary *TestLibrary::BuildSpeciesLibrary() {
|
SpeciesLibrary* TestLibrary::BuildSpeciesLibrary() {
|
||||||
auto l = new SpeciesLibrary();
|
auto l = new SpeciesLibrary();
|
||||||
l->LoadSpecies("testSpecies1",
|
l->LoadSpecies("testSpecies1",
|
||||||
new CreatureSpecies(
|
new CreatureSpecies(
|
||||||
0, "testSpecies1",
|
0, "testSpecies1",
|
||||||
new SpeciesVariant("default", 1, 1, 10, {0, 1}, StatisticSet<uint16_t>(10, 10, 10, 10, 10, 10),
|
new SpeciesVariant("default", 1, 1, 10, {0, 1}, StatisticSet<uint16_t>(10, 10, 10, 10, 10, 10),
|
||||||
{"testTalent"}, {"testSecretTalent"}, new LearnableAttacks(100)),
|
{"testTalent"}, {"testSecretTalent"}, new LearnableAttacks(100)),
|
||||||
0.5f, "testGrowthRate", 5, 100));
|
0.5f, "testGrowthRate", 5, 100));
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttackLibrary *TestLibrary::BuildAttackLibrary() {
|
AttackLibrary* TestLibrary::BuildAttackLibrary() {
|
||||||
auto l = new AttackLibrary();
|
auto l = new AttackLibrary();
|
||||||
l->LoadAttack("standard", new AttackData("standard", "normal", AttackCategory::Physical, 20, 100, 30,
|
l->LoadAttack("standard", new AttackData("standard", "normal", AttackCategory::Physical, 20, 100, 30,
|
||||||
AttackTarget::AdjacentOpponent, 0, {}));
|
AttackTarget::AdjacentOpponent, 0, {}));
|
||||||
|
@ -42,17 +44,18 @@ AttackLibrary *TestLibrary::BuildAttackLibrary() {
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemLibrary *TestLibrary::BuildItemLibrary() {
|
ItemLibrary* TestLibrary::BuildItemLibrary() {
|
||||||
auto l = new ItemLibrary();
|
auto l = new ItemLibrary();
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrowthRateLibrary *TestLibrary::BuildGrowthRateLibrary() {
|
GrowthRateLibrary* TestLibrary::BuildGrowthRateLibrary() {
|
||||||
auto l = new GrowthRateLibrary();
|
auto l = new GrowthRateLibrary();
|
||||||
|
l->AddGrowthRate("testGrowthRate", new LookupGrowthRate());
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeLibrary *TestLibrary::BuildTypeLibrary() {
|
TypeLibrary* TestLibrary::BuildTypeLibrary() {
|
||||||
auto l = new TypeLibrary();
|
auto l = new TypeLibrary();
|
||||||
l->RegisterType("testType1");
|
l->RegisterType("testType1");
|
||||||
l->RegisterType("testType2");
|
l->RegisterType("testType2");
|
||||||
|
|
Loading…
Reference in New Issue