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);
}
while (queue->HasNext()) {
if (!battle->HasRecalledSlots()) {
if (battle->HasRecalledSlots()) {
return;
}
auto item = queue->Dequeue();

View File

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

View File

@ -9,11 +9,11 @@
namespace CreatureLib::Battling {
class BattleLibrary {
const Library::DataLibrary* _staticLib;
BattleStatCalculator* _statCalculator;
DamageLibrary* _damageLibrary;
CriticalLibrary* _criticalLibrary;
ScriptResolver* _scriptResolver;
const Library::DataLibrary* _staticLib = nullptr;
BattleStatCalculator* _statCalculator = nullptr;
DamageLibrary* _damageLibrary = nullptr;
CriticalLibrary* _criticalLibrary = nullptr;
ScriptResolver* _scriptResolver = nullptr;
public:
BattleLibrary(Library::DataLibrary* staticLib, BattleStatCalculator* statCalculator,
@ -30,7 +30,7 @@ namespace CreatureLib::Battling {
[[nodiscard]] const DamageLibrary* GetDamageLibrary() 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();
}
TurnOrdering::OrderChoices(choices, _random);
auto choiceQueue = new ChoiceQueue(choices);
this->_currentTurnQueue = choiceQueue;
TurnHandler::RunTurn(this, choiceQueue);
if (choiceQueue->HasCompletedQueue)
_currentTurnQueue = nullptr;
this->_currentTurnQueue = new ChoiceQueue(choices);
TurnHandler::RunTurn(this, this->_currentTurnQueue);
if (this->_currentTurnQueue->HasCompletedQueue) {
delete this->_currentTurnQueue;
this->_currentTurnQueue = nullptr;
}
}
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::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 "../Library/BattleLibrary.hpp"
#include "../TurnChoices/BaseTurnChoice.hpp"
#include "BattleParty.hpp"
#include "BattleSide.hpp"
#include "CreatureIndex.hpp"
namespace CreatureLib::Battling {
class Battle : public ScriptSource {
const BattleLibrary* _library;
std::vector<BattleParty> _parties;
uint8_t _numberOfSides;
uint8_t _creaturesPerSide;
std::vector<BattleSide*> _sides;
@ -21,6 +23,21 @@ namespace CreatureLib::Battling {
ScriptSet _volatile;
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;
virtual bool CanUse(const BaseTurnChoice* choice);
@ -40,8 +57,8 @@ namespace CreatureLib::Battling {
[[nodiscard]] bool HasRecalledSlots() const;
void ForceRecall(uint8_t side, uint8_t index);
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;
};

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++;
}
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 {
return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end();

View File

@ -16,11 +16,18 @@ namespace CreatureLib::Battling {
public:
explicit BattleSide(Battle* battle, uint8_t creaturesPerSide)
: _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide), _choices(creaturesPerSide),
_battle(battle) {
: _creaturesPerSide(creaturesPerSide), _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();
}
virtual ~BattleSide() = default;
[[nodiscard]] bool AllChoicesSet() const;
[[nodiscard]] const std::vector<BaseTurnChoice*>& GetChoices() const;
@ -32,7 +39,7 @@ namespace CreatureLib::Battling {
Creature* GetCreature(uint8_t index) 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);
auto attacks = std::vector<LearnedAttack*>(_attacks.size());
for (auto kv : _attacks) {
attacks.push_back(new LearnedAttack(std::get<0>(kv), std::get<1>(kv)));
for (size_t i = 0; i < attacks.size(); i++) {
auto kv = _attacks[i];
attacks[i] = new LearnedAttack(std::get<0>(kv), std::get<1>(kv));
}
return new Creature(species, variant, _level, experience, statExperience, statPotential, identifier, gender,
_coloring, heldItem, _nickname, talent, attacks);
return new Creature(_library, species, variant, _level, experience, statExperience, statPotential, identifier,
gender, _coloring, heldItem, _nickname, talent, attacks);
}

View File

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

View File

@ -17,6 +17,8 @@ namespace CreatureLib::Battling {
class BattleLibrary;
class Creature : public ScriptSource {
const BattleLibrary* _library;
GetProperty(const Library::CreatureSpecies*, Species);
GetProperty(const Library::SpeciesVariant*, Variant);
@ -37,7 +39,6 @@ namespace CreatureLib::Battling {
Battle* _battle;
BattleSide* _side;
BattleLibrary* _library;
std::string _nickname = "";
int8_t _talentIndex;
@ -52,12 +53,17 @@ namespace CreatureLib::Battling {
ScriptSet _volatile = {};
public:
Creature(const Library::CreatureSpecies* species, const Library::SpeciesVariant* variant, uint8_t level,
uint32_t experience, Core::StatisticSet<uint8_t> statExp, Core::StatisticSet<uint8_t> statPotential,
uint32_t uid, Library::Gender gender, uint8_t coloring, const Library::Item* heldItem,
std::string nickname, int8_t talent, std::vector<LearnedAttack*> attacks);
Creature(const BattleLibrary* library, const Library::CreatureSpecies* species,
const Library::SpeciesVariant* variant, uint8_t level, uint32_t experience,
Core::StatisticSet<uint8_t> statExp, Core::StatisticSet<uint8_t> statPotential, uint32_t uid,
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);
Battle* GetBattle() const;
@ -76,10 +82,9 @@ namespace CreatureLib::Battling {
void GetActiveScripts(std::vector<ScriptWrapper>& scripts) override;
// region Stat APIs
std::vector<LearnedAttack*>& GetAttacks() { return _attacks; }
void SetBattle(Battle* battle);
void SetBattleLibrary(BattleLibrary* library);
// region Stat APIs
void ChangeStatBoost(Core::Statistic stat, int8_t diffAmount);
[[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"
namespace CreatureLib::Battling {
template <int max> class CreatureParty {
std::array<Creature*, max> _party;
class CreatureParty {
std::vector<Creature*> _party;
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]; }
@ -29,6 +36,8 @@ namespace CreatureLib::Battling {
}
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 {
LearnedAttack* _attack;
CreatureIndex _target;
Script* _attackScript;
Script* _attackScript = nullptr;
public:
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() {
auto l = new DataLibrary(LibrarySettings(100, 4), BuildSpeciesLibrary(), BuildAttackLibrary(), BuildItemLibrary(),
BuildGrowthRateLibrary(), BuildTypeLibrary());
auto battleLib = new BattleLibrary(l, new BattleStatCalculator(), new DamageLibrary(), new CriticalLibrary(),
new ScriptResolver());
auto statCalc = new BattleStatCalculator();
auto battleLib = new BattleLibrary(l, statCalc, new DamageLibrary(), new CriticalLibrary(), new ScriptResolver());
return battleLib;
}