Implemented and fixed all code required to run at least a single turn.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2019-12-05 12:56:41 +01:00
parent 5d6ac316eb
commit 6f32d1245b
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
17 changed files with 171 additions and 58 deletions

View File

@ -10,7 +10,7 @@ void TurnHandler::RunTurn(Battle* battle, ChoiceQueue* queue) {
HOOK(OnBeforeTurn, choice, choice); HOOK(OnBeforeTurn, choice, choice);
} }
while (queue->HasNext()) { while (queue->HasNext()) {
if (!battle->HasRecalledSlots()) { if (battle->HasRecalledSlots()) {
return; return;
} }
auto item = queue->Dequeue(); auto item = queue->Dequeue();

View File

@ -37,7 +37,6 @@ const DamageLibrary* BattleLibrary::GetDamageLibrary() const { return _damageLib
const CriticalLibrary* BattleLibrary::GetCriticalLibrary() const { return _criticalLibrary; } const CriticalLibrary* BattleLibrary::GetCriticalLibrary() const { return _criticalLibrary; }
Script* BattleLibrary::LoadScript(ScriptResolver::ScriptCategory category, const std::string& scriptName) { Script* BattleLibrary::LoadScript(ScriptResolver::ScriptCategory category, const std::string& scriptName) const {
assert(this->_scriptResolver != nullptr);
return _scriptResolver->LoadScript(category, scriptName); return _scriptResolver->LoadScript(category, scriptName);
} }

View File

@ -9,11 +9,11 @@
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class BattleLibrary { class BattleLibrary {
const Library::DataLibrary* _staticLib; const Library::DataLibrary* _staticLib = nullptr;
BattleStatCalculator* _statCalculator; BattleStatCalculator* _statCalculator = nullptr;
DamageLibrary* _damageLibrary; DamageLibrary* _damageLibrary = nullptr;
CriticalLibrary* _criticalLibrary; CriticalLibrary* _criticalLibrary = nullptr;
ScriptResolver* _scriptResolver; ScriptResolver* _scriptResolver = nullptr;
public: public:
BattleLibrary(Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator, BattleLibrary(Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator,
@ -30,7 +30,7 @@ namespace CreatureLib::Battling {
[[nodiscard]] const DamageLibrary* GetDamageLibrary() const; [[nodiscard]] const DamageLibrary* GetDamageLibrary() const;
[[nodiscard]] const CriticalLibrary* GetCriticalLibrary() const; [[nodiscard]] const CriticalLibrary* GetCriticalLibrary() const;
[[nodiscard]] Script* LoadScript(ScriptResolver::ScriptCategory category, const std::string& scriptName); [[nodiscard]] Script* LoadScript(ScriptResolver::ScriptCategory category, const std::string& scriptName) const;
}; };
} }

View File

@ -50,11 +50,12 @@ void Battle::CheckChoicesSetAndRun() {
side->ResetChoices(); side->ResetChoices();
} }
TurnOrdering::OrderChoices(choices, _random); TurnOrdering::OrderChoices(choices, _random);
auto choiceQueue = new ChoiceQueue(choices); this->_currentTurnQueue = new ChoiceQueue(choices);
this->_currentTurnQueue = choiceQueue; TurnHandler::RunTurn(this, this->_currentTurnQueue);
TurnHandler::RunTurn(this, choiceQueue); if (this->_currentTurnQueue->HasCompletedQueue) {
if (choiceQueue->HasCompletedQueue) delete this->_currentTurnQueue;
_currentTurnQueue = nullptr; this->_currentTurnQueue = nullptr;
}
} }
ChoiceQueue* Battle::GetCurrentTurnQueue() const { return _currentTurnQueue; } ChoiceQueue* Battle::GetCurrentTurnQueue() const { return _currentTurnQueue; }
@ -85,3 +86,7 @@ void Battle::FillRecall(uint8_t side, uint8_t, Creature* c) {
} }
void Battle::GetActiveScripts(std::vector<ScriptWrapper>& scripts) { scripts.emplace_back(&_volatile); } void Battle::GetActiveScripts(std::vector<ScriptWrapper>& scripts) { scripts.emplace_back(&_volatile); }
void Battle::SwitchCreature(uint8_t sideIndex, uint8_t index, Creature* c) {
auto side = this->_sides[sideIndex];
side->SetCreature(c, index);
}

View File

@ -5,12 +5,14 @@
#include "../Flow/ChoiceQueue.hpp" #include "../Flow/ChoiceQueue.hpp"
#include "../Library/BattleLibrary.hpp" #include "../Library/BattleLibrary.hpp"
#include "../TurnChoices/BaseTurnChoice.hpp" #include "../TurnChoices/BaseTurnChoice.hpp"
#include "BattleParty.hpp"
#include "BattleSide.hpp" #include "BattleSide.hpp"
#include "CreatureIndex.hpp" #include "CreatureIndex.hpp"
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class Battle : public ScriptSource { class Battle : public ScriptSource {
const BattleLibrary* _library; const BattleLibrary* _library;
std::vector<BattleParty> _parties;
uint8_t _numberOfSides; uint8_t _numberOfSides;
uint8_t _creaturesPerSide; uint8_t _creaturesPerSide;
std::vector<BattleSide*> _sides; std::vector<BattleSide*> _sides;
@ -21,6 +23,21 @@ namespace CreatureLib::Battling {
ScriptSet _volatile; ScriptSet _volatile;
public: public:
Battle(const BattleLibrary* library, std::vector<BattleParty> parties, uint8_t numberOfSides = 2,
uint8_t creaturesPerSide = 1)
: _library(library), _parties(parties), _numberOfSides(numberOfSides), _creaturesPerSide(creaturesPerSide) {
_sides = std::vector<BattleSide*>(numberOfSides);
for (size_t i = 0; i < numberOfSides; i++) {
_sides[i] = new BattleSide(this, creaturesPerSide);
}
}
~Battle() {
for (auto s : _sides) {
delete s;
}
}
[[nodiscard]] const BattleLibrary* GetLibrary() const; [[nodiscard]] const BattleLibrary* GetLibrary() const;
virtual bool CanUse(const BaseTurnChoice* choice); virtual bool CanUse(const BaseTurnChoice* choice);
@ -40,8 +57,8 @@ namespace CreatureLib::Battling {
[[nodiscard]] bool HasRecalledSlots() const; [[nodiscard]] bool HasRecalledSlots() const;
void ForceRecall(uint8_t side, uint8_t index); void ForceRecall(uint8_t side, uint8_t index);
void FillRecall(uint8_t side, uint8_t, Creature* c); void FillRecall(uint8_t side, uint8_t, Creature* c);
void SwitchCreature(uint8_t side, uint8_t index, Creature* c);
void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override; void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override;
}; };

View File

@ -0,0 +1,21 @@
#ifndef CREATURELIB_BATTLEPARTY_HPP
#define CREATURELIB_BATTLEPARTY_HPP
#include "CreatureIndex.hpp"
#include "CreatureParty.hpp"
namespace CreatureLib::Battling {
class BattleParty {
CreatureParty* _party;
std::vector<CreatureIndex> _responsibleIndices;
public:
BattleParty(CreatureParty* party, std::vector<CreatureIndex> responsibleIndices)
: _party(party), _responsibleIndices(responsibleIndices) {}
CreatureParty* GetParty() { return _party; }
std::vector<CreatureIndex>& GetResponsibleIndices() { return _responsibleIndices; }
};
}
#endif // CREATURELIB_BATTLEPARTY_HPP

View File

@ -25,7 +25,10 @@ void BattleSide::SetChoice(BaseTurnChoice* choice) {
_choicesSet++; _choicesSet++;
} }
void BattleSide::SetCreature(Creature* creature, uint8_t index) { _creatures[index] = creature; } void BattleSide::SetCreature(Creature* creature, uint8_t index) {
_creatures[index] = creature;
creature->SetBattleData(_battle, this);
}
bool BattleSide::CreatureOnSide(const Creature* creature) const { bool BattleSide::CreatureOnSide(const Creature* creature) const {
return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end(); return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end();

View File

@ -16,11 +16,18 @@ namespace CreatureLib::Battling {
public: public:
explicit BattleSide(Battle* battle, uint8_t creaturesPerSide) explicit BattleSide(Battle* battle, uint8_t creaturesPerSide)
: _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide), _choices(creaturesPerSide), : _creaturesPerSide(creaturesPerSide), _battle(battle) {
_battle(battle) { _creatures = std::vector<Creature*>(creaturesPerSide);
_choices = std::vector<BaseTurnChoice*>(creaturesPerSide);
for (size_t i = 0; i < creaturesPerSide; i++) {
_creatures[i] = nullptr;
_choices[i] = nullptr;
}
ResetChoices(); ResetChoices();
} }
virtual ~BattleSide() = default;
[[nodiscard]] bool AllChoicesSet() const; [[nodiscard]] bool AllChoicesSet() const;
[[nodiscard]] const std::vector<BaseTurnChoice*>& GetChoices() const; [[nodiscard]] const std::vector<BaseTurnChoice*>& GetChoices() const;
@ -32,7 +39,7 @@ namespace CreatureLib::Battling {
Creature* GetCreature(uint8_t index) const; Creature* GetCreature(uint8_t index) const;
bool CreatureOnSide(const Creature* creature) const; bool CreatureOnSide(const Creature* creature) const;
void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override; void GetActiveScripts(std::vector<ScriptWrapper>& scripts) final;
}; };
} }

View File

@ -107,10 +107,10 @@ Creature* CreateCreature::Create() {
_magAttackPotential, _magDefensePotential, _speedPotential); _magAttackPotential, _magDefensePotential, _speedPotential);
auto attacks = std::vector<LearnedAttack*>(_attacks.size()); auto attacks = std::vector<LearnedAttack*>(_attacks.size());
for (auto kv : _attacks) { for (size_t i = 0; i < attacks.size(); i++) {
attacks.push_back(new LearnedAttack(std::get<0>(kv), std::get<1>(kv))); auto kv = _attacks[i];
attacks[i] = new LearnedAttack(std::get<0>(kv), std::get<1>(kv));
} }
return new Creature(_library, species, variant, _level, experience, statExperience, statPotential, identifier,
return new Creature(species, variant, _level, experience, statExperience, statPotential, identifier, gender, gender, _coloring, heldItem, _nickname, talent, attacks);
_coloring, heldItem, _nickname, talent, attacks);
} }

View File

@ -5,16 +5,18 @@
using namespace CreatureLib; using namespace CreatureLib;
Battling::Creature::Creature(const Library::CreatureSpecies* species, const Library::SpeciesVariant* variant, Battling::Creature::Creature(const BattleLibrary* library, const Library::CreatureSpecies* species,
uint8_t level, uint32_t experience, Core::StatisticSet<uint8_t> statExp, const Library::SpeciesVariant* variant, uint8_t level, uint32_t experience,
Core::StatisticSet<uint8_t> statPotential, uint32_t uid, Library::Gender gender, Core::StatisticSet<uint8_t> statExp, Core::StatisticSet<uint8_t> statPotential,
uint8_t coloring, const Library::Item* heldItem, std::string nickname, int8_t talent, uint32_t uid, Library::Gender gender, uint8_t coloring, const Library::Item* heldItem,
std::vector<LearnedAttack*> attacks) std::string nickname, int8_t talent, std::vector<LearnedAttack*> attacks)
: __Species(species), __Variant(variant), __Level(level), __Experience(experience), __StatExperience(statExp), : _library(library), __Species(species), __Variant(variant), __Level(level), __Experience(experience),
__StatPotential(statPotential), __UniqueIdentifier(uid), __Gender(gender), __Coloring(coloring), __StatExperience(statExp), __StatPotential(statPotential), __UniqueIdentifier(uid), __Gender(gender),
__HeldItem(heldItem), _nickname(std::move(nickname)), _talentIndex(talent), _hasOverridenTalent(false), __Coloring(coloring), __HeldItem(heldItem), _nickname(std::move(nickname)), _talentIndex(talent),
_attacks(std::move(attacks)) { _hasOverridenTalent(false), _attacks(std::move(attacks)) {
RecalculateFlatStats();
__CurrentHealth = GetBoostedStat(Core::Statistic::Health); __CurrentHealth = GetBoostedStat(Core::Statistic::Health);
_activeTalent = _library->LoadScript(ScriptResolver::ScriptCategory::Talent, GetActiveTalent());
} }
void Battling::Creature::ChangeLevel(int8_t amount) { void Battling::Creature::ChangeLevel(int8_t amount) {
@ -22,13 +24,6 @@ void Battling::Creature::ChangeLevel(int8_t amount) {
RecalculateFlatStats(); RecalculateFlatStats();
} }
void Battling::Creature::SetBattle(Battling::Battle* battle) { this->_battle = battle; }
void Battling::Creature::SetBattleLibrary(Battling::BattleLibrary* library) {
this->_library = library;
_activeTalent = _library->LoadScript(ScriptResolver::ScriptCategory::Talent, GetActiveTalent());
}
const std::string& Battling::Creature::GetNickname() const { const std::string& Battling::Creature::GetNickname() const {
if (_nickname.empty()) if (_nickname.empty())
return __Species->GetName(); return __Species->GetName();
@ -70,7 +65,8 @@ uint32_t Battling::Creature::GetStatExperience(Core::Statistic stat) const { ret
int8_t Battling::Creature::GetStatBoost(Core::Statistic stat) const { return _statBoost.GetStat(stat); } int8_t Battling::Creature::GetStatBoost(Core::Statistic stat) const { return _statBoost.GetStat(stat); }
void Battling::Creature::RecalculateFlatStats() { void Battling::Creature::RecalculateFlatStats() {
this->_flatStats = this->_library->GetStatCalculator()->CalculateFlatStats(this); auto statCalc = this->_library->GetStatCalculator();
this->_flatStats = statCalc->CalculateFlatStats(this);
RecalculateBoostedStats(); RecalculateBoostedStats();
} }
void Battling::Creature::RecalculateBoostedStats() { void Battling::Creature::RecalculateBoostedStats() {

View File

@ -17,6 +17,8 @@ namespace CreatureLib::Battling {
class BattleLibrary; class BattleLibrary;
class Creature : public ScriptSource { class Creature : public ScriptSource {
const BattleLibrary* _library;
GetProperty(const Library::CreatureSpecies*, Species); GetProperty(const Library::CreatureSpecies*, Species);
GetProperty(const Library::SpeciesVariant*, Variant); GetProperty(const Library::SpeciesVariant*, Variant);
@ -37,7 +39,6 @@ namespace CreatureLib::Battling {
Battle* _battle; Battle* _battle;
BattleSide* _side; BattleSide* _side;
BattleLibrary* _library;
std::string _nickname = ""; std::string _nickname = "";
int8_t _talentIndex; int8_t _talentIndex;
@ -52,12 +53,17 @@ namespace CreatureLib::Battling {
ScriptSet _volatile = {}; ScriptSet _volatile = {};
public: public:
Creature(const Library::CreatureSpecies* species, const Library::SpeciesVariant* variant, uint8_t level, Creature(const BattleLibrary* library, const Library::CreatureSpecies* species,
uint32_t experience, Core::StatisticSet<uint8_t> statExp, Core::StatisticSet<uint8_t> statPotential, const Library::SpeciesVariant* variant, uint8_t level, uint32_t experience,
uint32_t uid, Library::Gender gender, uint8_t coloring, const Library::Item* heldItem, Core::StatisticSet<uint8_t> statExp, Core::StatisticSet<uint8_t> statPotential, uint32_t uid,
std::string nickname, int8_t talent, std::vector<LearnedAttack*> attacks); Library::Gender gender, uint8_t coloring, const Library::Item* heldItem, std::string nickname,
int8_t talent, std::vector<LearnedAttack*> attacks);
virtual ~Creature() = default; virtual ~Creature() {
for (auto attack : _attacks) {
delete attack;
}
};
void SetBattleData(Battle* battle, BattleSide* side); void SetBattleData(Battle* battle, BattleSide* side);
Battle* GetBattle() const; Battle* GetBattle() const;
@ -76,10 +82,9 @@ namespace CreatureLib::Battling {
void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override; void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override;
// region Stat APIs std::vector<LearnedAttack*>& GetAttacks() { return _attacks; }
void SetBattle(Battle* battle); // region Stat APIs
void SetBattleLibrary(BattleLibrary* library);
void ChangeStatBoost(Core::Statistic stat, int8_t diffAmount); void ChangeStatBoost(Core::Statistic stat, int8_t diffAmount);
[[nodiscard]] uint32_t GetFlatStat(Core::Statistic stat) const; [[nodiscard]] uint32_t GetFlatStat(Core::Statistic stat) const;

View File

@ -1 +0,0 @@
#include "CreatureParty.hpp"

View File

@ -5,11 +5,18 @@
#include "Creature.hpp" #include "Creature.hpp"
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
template <int max> class CreatureParty { class CreatureParty {
std::array<Creature*, max> _party; std::vector<Creature*> _party;
public: public:
CreatureParty(std::array<Creature*, max> party) : _party(party) {} CreatureParty(std::vector<Creature*> party) : _party(party) {}
CreatureParty(std::initializer_list<Creature*> party) : _party(party) {}
~CreatureParty() {
for (auto c : _party) {
delete c;
}
}
Creature* GetAtIndex(int index) const { return _party[index]; } Creature* GetAtIndex(int index) const { return _party[index]; }
@ -29,6 +36,8 @@ namespace CreatureLib::Battling {
} }
return false; return false;
} }
std::vector<Creature*>& GetParty() { return _party; }
}; };
} }

View File

@ -1 +0,0 @@
#include "ExecutingAttack.hpp"

View File

@ -9,7 +9,7 @@ namespace CreatureLib::Battling {
class AttackTurnChoice : public BaseTurnChoice { class AttackTurnChoice : public BaseTurnChoice {
LearnedAttack* _attack; LearnedAttack* _attack;
CreatureIndex _target; CreatureIndex _target;
Script* _attackScript; Script* _attackScript = nullptr;
public: public:
AttackTurnChoice(Creature* user, LearnedAttack* attack, const CreatureIndex& target) AttackTurnChoice(Creature* user, LearnedAttack* attack, const CreatureIndex& target)

View File

@ -0,0 +1,53 @@
#ifdef TESTS_BUILD
#include "../../extern/catch.hpp"
#include "../../src/Battling/Models/Battle.hpp"
#include "../../src/Battling/Models/BattleParty.hpp"
#include "../../src/Battling/Models/CreateCreature.hpp"
#include "../../src/Battling/TurnChoices/AttackTurnChoice.hpp"
#include "../../src/Battling/TurnChoices/PassTurnChoice.hpp"
#include "../TestLibrary/TestLibrary.cpp"
using namespace CreatureLib;
using namespace Battling;
TEST_CASE("Create Party", "[Integrations]") {
auto library = GetLibrary();
auto c1 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
CreatureParty party1{c1};
auto battleParty = BattleParty(&party1, {CreatureIndex(0, 0)});
REQUIRE(battleParty.GetParty()->GetAtIndex(0) == c1);
}
TEST_CASE("Create Battle", "[Integrations]") {
auto library = GetLibrary();
auto c1 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
CreatureParty party1{c1};
auto battleParty1 = BattleParty(&party1, {CreatureIndex(0, 0)});
auto c2 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
CreatureParty party2{c2};
auto battleParty2 = BattleParty(&party2, {CreatureIndex(1, 0)});
auto battle = Battle(library, {battleParty1, battleParty2});
}
TEST_CASE("Use damaging move", "[Integrations]") {
auto library = GetLibrary();
auto c1 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
CreatureParty party1{c1};
auto battleParty1 = BattleParty(&party1, {CreatureIndex(0, 0)});
auto c2 = CreateCreature(library, "testSpecies1", 50).WithAttack("standard", AttackLearnMethod::Unknown)->Create();
CreatureParty party2{c2};
auto battleParty2 = BattleParty(&party2, {CreatureIndex(1, 0)});
auto battle = Battle(library, {battleParty1, battleParty2});
battle.SwitchCreature(0, 0, c1);
battle.SwitchCreature(1, 0, c2);
battle.TrySetChoice(new AttackTurnChoice(c1, c1->GetAttacks()[0], CreatureIndex(1, 0)));
battle.TrySetChoice(new PassTurnChoice(c2));
REQUIRE(c2->GetCurrentHealth() < c2->GetBoostedStat(Statistic::Health));
}
#endif

View File

@ -52,8 +52,8 @@ static TypeLibrary* BuildTypeLibrary() {
static BattleLibrary* BuildLibrary() { static BattleLibrary* BuildLibrary() {
auto l = new DataLibrary(LibrarySettings(100, 4), BuildSpeciesLibrary(), BuildAttackLibrary(), BuildItemLibrary(), auto l = new DataLibrary(LibrarySettings(100, 4), BuildSpeciesLibrary(), BuildAttackLibrary(), BuildItemLibrary(),
BuildGrowthRateLibrary(), BuildTypeLibrary()); BuildGrowthRateLibrary(), BuildTypeLibrary());
auto battleLib = new BattleLibrary(l, new BattleStatCalculator(), new DamageLibrary(), new CriticalLibrary(), auto statCalc = new BattleStatCalculator();
new ScriptResolver()); auto battleLib = new BattleLibrary(l, statCalc, new DamageLibrary(), new CriticalLibrary(), new ScriptResolver());
return battleLib; return battleLib;
} }