Use smart pointers for BattleSide.
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2020-06-02 13:06:24 +02:00
parent 49e8ff055d
commit f898698f49
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
20 changed files with 86 additions and 107 deletions

View File

@ -29,7 +29,7 @@ export uint8_t CreatureLib_Battle_CreatureInField(bool& out, const Battle* p, Cr
Try(out = p->CreatureInField(c);) Try(out = p->CreatureInField(c);)
} }
export uint8_t CreatureLib_Battle_GetCreature(Creature*& out, const Battle* p, uint8_t side, uint8_t target) { export uint8_t CreatureLib_Battle_GetCreature(Creature*& out, const Battle* p, uint8_t side, uint8_t target) {
Try(out = p->GetCreature(side, target);) Try(out = p->GetCreature(side, target).operator->();)
} }
export uint8_t CreatureLib_Battle_ForceRecall(Battle* p, uint8_t side, uint8_t target) { export uint8_t CreatureLib_Battle_ForceRecall(Battle* p, uint8_t side, uint8_t target) {

View File

@ -10,8 +10,6 @@ export void CreatureLib_BattleSide_Destruct(BattleSide* p) { delete p; }
export bool CreatureLib_BattleSide_AllChoicesSet(BattleSide* p) { return p->AllChoicesSet(); } export bool CreatureLib_BattleSide_AllChoicesSet(BattleSide* p) { return p->AllChoicesSet(); }
export BaseTurnChoice* const* CreatureLib_BattleSide_GetChoices(BattleSide* p) { return p->GetChoices().RawData(); }
export uint8_t CreatureLib_BattleSide_AllPossibleSlotsFilled(bool& out, BattleSide* p) { export uint8_t CreatureLib_BattleSide_AllPossibleSlotsFilled(bool& out, BattleSide* p) {
Try(out = p->AllPossibleSlotsFilled()); Try(out = p->AllPossibleSlotsFilled());
} }
@ -25,7 +23,7 @@ export uint8_t CreatureLib_BattleSide_SetCreature(BattleSide* p, Creature* creat
} }
export uint8_t CreatureLib_BattleSide_GetCreature(Creature*& out, BattleSide* p, uint8_t index) { export uint8_t CreatureLib_BattleSide_GetCreature(Creature*& out, BattleSide* p, uint8_t index) {
Try(out = p->GetCreature(index)); Try(out = p->GetCreature(index).GetRaw());
} }
export uint8_t CreatureLib_BattleSide_GetSideIndex(BattleSide* p) { return p->GetSideIndex(); } export uint8_t CreatureLib_BattleSide_GetSideIndex(BattleSide* p) { return p->GetSideIndex(); }

View File

@ -43,7 +43,7 @@ export void CreatureLib_Creature_SetHeldItemFromItem(Creature* p, const Creature
return p->SetHeldItem(ArbUt::BorrowedPtr<const CreatureLib::Library::Item>(item)); return p->SetHeldItem(ArbUt::BorrowedPtr<const CreatureLib::Library::Item>(item));
} }
SIMPLE_GET_FUNC(Creature, GetCurrentHealth, uint32_t); SIMPLE_GET_FUNC(Creature, GetCurrentHealth, uint32_t);
SIMPLE_GET_FUNC(Creature, GetBattle, Battle*); SIMPLE_GET_FUNC_SMART_PTR(Creature, GetBattle, Battle*);
SIMPLE_GET_FUNC(Creature, GetBattleSide, BattleSide*); SIMPLE_GET_FUNC(Creature, GetBattleSide, BattleSide*);
SIMPLE_GET_FUNC(Creature, IsOnBattleField, bool); SIMPLE_GET_FUNC(Creature, IsOnBattleField, bool);
export const char* CreatureLib_Creature_GetNickname(Creature* p) { return p->GetNickname().c_str(); } export const char* CreatureLib_Creature_GetNickname(Creature* p) { return p->GetNickname().c_str(); }

View File

@ -5,8 +5,9 @@ using namespace CreatureLib::Battling;
export uint8_t CreatureLib_ExecutingAttack_Construct(ExecutingAttack*& out, Creature* const* targets, export uint8_t CreatureLib_ExecutingAttack_Construct(ExecutingAttack*& out, Creature* const* targets,
size_t targetCount, uint8_t numberHits, Creature* user, size_t targetCount, uint8_t numberHits, Creature* user,
LearnedAttack* attack, Script* script) { LearnedAttack* attack, Script* script) {
Try(auto ls = ArbUt::List<Creature*>(targets, targets + targetCount); Try(auto ls = ArbUt::List<ArbUt::BorrowedPtr<Creature>>(targetCount); for (size_t i = 0; i < targetCount; i++) {
out = new ExecutingAttack(ls, numberHits, user, attack, script);) ls.Append(targets[i]);
} out = new ExecutingAttack(ls, numberHits, user, attack, script);)
} }
export void CreatureLib_ExecutingAttack_Destruct(ExecutingAttack* p) { delete p; } export void CreatureLib_ExecutingAttack_Destruct(ExecutingAttack* p) { delete p; }

View File

@ -5,8 +5,8 @@ bool CreatureLib::Battling::ChoiceQueue::MoveCreatureChoiceNext(CreatureLib::Bat
AssertNotNull(creature) AssertNotNull(creature)
// Find which index the creature choice is at. // Find which index the creature choice is at.
size_t choiceIndex = SIZE_MAX; size_t choiceIndex = SIZE_MAX;
for (size_t index = _current; index < _queue.Count(); index++) { for (size_t index = _current; index < _queue.size(); index++) {
if (_queue.At(index)->GetUser() == creature) { if (_queue[index]->GetUser() == creature) {
// If the creature choice is already next up, return. // If the creature choice is already next up, return.
if (index == _current) if (index == _current)
return false; return false;
@ -17,15 +17,14 @@ bool CreatureLib::Battling::ChoiceQueue::MoveCreatureChoiceNext(CreatureLib::Bat
if (choiceIndex == SIZE_MAX) if (choiceIndex == SIZE_MAX)
return false; return false;
auto& vec = _queue.GetStdList();
// Save the pointer to the creature choice. // Save the pointer to the creature choice.
auto creatureChoice = _queue[choiceIndex]; auto creatureChoice = _queue[choiceIndex];
// Starting at the position before the current creature choice, and iterating backwards up till the current choice. // Starting at the position before the current creature choice, and iterating backwards up till the current choice.
for (size_t i = choiceIndex - 1; i >= _current && i != SIZE_MAX; i--) { for (size_t i = choiceIndex - 1; i >= _current && i != SIZE_MAX; i--) {
// Place everything in one spot later. // Place everything in one spot later.
vec[i + 1] = vec[i]; _queue[i + 1] = _queue[i];
} }
// Set the creature choice up next. // Set the creature choice up next.
vec[_current] = creatureChoice.GetRaw(); _queue[_current] = creatureChoice;
return true; return true;
} }

View File

@ -8,25 +8,21 @@
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class ChoiceQueue { class ChoiceQueue {
ArbUt::UniquePtrList<BaseTurnChoice> _queue; std::vector<std::shared_ptr<BaseTurnChoice>> _queue;
size_t _current = 0; size_t _current = 0;
public: public:
bool HasCompletedQueue = false; bool HasCompletedQueue = false;
explicit ChoiceQueue(std::vector<BaseTurnChoice*> queue) : _queue(std::move(queue)) {} explicit ChoiceQueue(std::vector<std::shared_ptr<BaseTurnChoice>> queue) : _queue(std::move(queue)) {}
ArbUt::BorrowedPtr<BaseTurnChoice> Dequeue() { const std::shared_ptr<BaseTurnChoice>& Dequeue() { return _queue[_current++]; }
auto b = _queue[_current];
_current++;
return b;
}
ArbUt::BorrowedPtr<BaseTurnChoice> Peek() { return _queue[_current]; } const std::shared_ptr<BaseTurnChoice>& Peek() { return _queue[_current]; }
[[nodiscard]] bool HasNext() const { return _current < _queue.Count(); } [[nodiscard]] bool HasNext() const { return _current < _queue.size(); }
ArbUt::UniquePtrList<BaseTurnChoice>& GetInnerQueue() { return _queue; } const std::vector<std::shared_ptr<BaseTurnChoice>>& GetInnerQueue() { return _queue; }
bool MoveCreatureChoiceNext(Creature* creature); bool MoveCreatureChoiceNext(Creature* creature);
}; };

View File

@ -8,11 +8,11 @@ using namespace CreatureLib::Battling;
void TurnHandler::RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue) { void TurnHandler::RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue) {
AssertNotNull(queue) AssertNotNull(queue)
for (auto choice : queue->GetInnerQueue()) { for (auto choice : queue->GetInnerQueue()) {
HOOK(OnBeforeTurn, choice, choice); HOOK(OnBeforeTurn, choice, choice.get());
} }
while (queue->HasNext()) { while (queue->HasNext()) {
auto item = queue->Dequeue(); auto item = queue->Dequeue();
ExecuteChoice(item); ExecuteChoice(item.get());
} }
queue->HasCompletedQueue = true; queue->HasCompletedQueue = true;
} }
@ -59,7 +59,7 @@ void TurnHandler::ExecuteAttackChoice(ArbUt::BorrowedPtr<AttackTurnChoice> choic
// FIXME: Resolve all targets // FIXME: Resolve all targets
auto target = choice->GetUser()->GetBattle()->GetCreature(choice->GetTarget()); auto target = choice->GetUser()->GetBattle()->GetCreature(choice->GetTarget());
ArbUt::List<Creature*> targets = {target}; ArbUt::List<ArbUt::BorrowedPtr<Creature>> targets = {target};
auto attack = ExecutingAttack(targets, 1, choice->GetUser(), choice->GetAttack(), choice->GetAttackScript()); auto attack = ExecutingAttack(targets, 1, choice->GetUser(), choice->GetAttack(), choice->GetAttackScript());
choice->MarkScriptAsTaken(); choice->MarkScriptAsTaken();
@ -91,7 +91,7 @@ void TurnHandler::ExecuteAttackChoice(ArbUt::BorrowedPtr<AttackTurnChoice> choic
HOOK_LOCAL(OnBeforeAttack, attack, &attack); HOOK_LOCAL(OnBeforeAttack, attack, &attack);
for (auto& t : attack.GetTargets()) { for (auto& t : attack.GetTargets()) {
HandleAttackForTarget(&attack, t); HandleAttackForTarget(&attack, t.GetRaw());
} }
} }

View File

@ -9,14 +9,14 @@ using namespace Battling;
class ChoiceCompare { class ChoiceCompare {
public: public:
explicit ChoiceCompare() {} explicit ChoiceCompare() {}
bool operator()(const BaseTurnChoice* a, const BaseTurnChoice* b) { bool operator()(const std::shared_ptr<BaseTurnChoice>& a, const std::shared_ptr<BaseTurnChoice>& b) {
auto aKind = a->GetKind(); auto aKind = a->GetKind();
auto bKind = b->GetKind(); auto bKind = b->GetKind();
if (aKind != bKind) if (aKind != bKind)
return aKind > bKind; return aKind > bKind;
if (aKind == TurnChoiceKind::Attack) { if (aKind == TurnChoiceKind::Attack) {
auto aPriority = dynamic_cast<const AttackTurnChoice*>(a)->GetPriority(); auto aPriority = dynamic_cast<const AttackTurnChoice*>(a.get())->GetPriority();
auto bPriority = dynamic_cast<const AttackTurnChoice*>(b)->GetPriority(); auto bPriority = dynamic_cast<const AttackTurnChoice*>(b.get())->GetPriority();
if (aPriority != bPriority) if (aPriority != bPriority)
return aPriority > bPriority; return aPriority > bPriority;
} }
@ -29,6 +29,6 @@ public:
} }
}; };
void TurnOrdering::OrderChoices(std::vector<BaseTurnChoice*>& vec, ArbUt::Random& rand) { void TurnOrdering::OrderChoices(std::vector<std::shared_ptr<BaseTurnChoice>>& vec, ArbUt::Random& rand) {
std::sort(vec.begin(), vec.end(), ChoiceCompare()); std::sort(vec.begin(), vec.end(), ChoiceCompare());
} }

View File

@ -2,13 +2,14 @@
#define CREATURELIB_TURNORDERING_HPP #define CREATURELIB_TURNORDERING_HPP
#include <Arbutils/Random.hpp> #include <Arbutils/Random.hpp>
#include <memory>
#include <vector> #include <vector>
#include "../TurnChoices/BaseTurnChoice.hpp" #include "../TurnChoices/BaseTurnChoice.hpp"
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class TurnOrdering { class TurnOrdering {
public: public:
static void OrderChoices(std::vector<BaseTurnChoice*>& vec, ArbUt::Random& rand); static void OrderChoices(std::vector<std::shared_ptr<BaseTurnChoice>>& vec, ArbUt::Random& rand);
}; };
} }

View File

@ -39,13 +39,13 @@ void Battle::CheckChoicesSetAndRun() {
} }
} }
auto choices = std::vector<BaseTurnChoice*>(_numberOfSides * _creaturesPerSide); auto choices = std::vector<std::shared_ptr<BaseTurnChoice>>(_numberOfSides * _creaturesPerSide);
auto i = 0; auto i = 0;
for (auto side : _sides) { for (auto side : _sides) {
for (BaseTurnChoice* choice : side->GetChoices()) { for (const auto& choice : side->GetChoices()) {
AssertNotNull(choice) AssertNotNull(choice)
if (choice->GetKind() == TurnChoiceKind::Attack) { if (choice->GetKind() == TurnChoiceKind::Attack) {
auto attack = (dynamic_cast<AttackTurnChoice*>((choice)))->GetAttack(); auto attack = ((AttackTurnChoice*)choice.get())->GetAttack();
uint8_t uses = 1; uint8_t uses = 1;
// HOOK: change number of uses needed. // HOOK: change number of uses needed.
if (attack->GetRemainingUses() < uses) { if (attack->GetRemainingUses() < uses) {
@ -73,7 +73,7 @@ ArbUt::BorrowedPtr<ChoiceQueue> Battle::GetCurrentTurnQueue() const noexcept { r
BattleRandom* Battle::GetRandom() noexcept { return &_random; } BattleRandom* Battle::GetRandom() noexcept { return &_random; }
bool Battle::CreatureInField(const Creature* creature) const { bool Battle::CreatureInField(ArbUt::BorrowedPtr<Creature> creature) const {
AssertNotNull(creature) AssertNotNull(creature)
for (auto s : _sides) { for (auto s : _sides) {
if (s->CreatureOnSide(creature)) if (s->CreatureOnSide(creature))

View File

@ -60,12 +60,14 @@ namespace CreatureLib::Battling {
[[nodiscard]] ArbUt::BorrowedPtr<ChoiceQueue> GetCurrentTurnQueue() const noexcept; [[nodiscard]] ArbUt::BorrowedPtr<ChoiceQueue> GetCurrentTurnQueue() const noexcept;
BattleRandom* GetRandom() noexcept; BattleRandom* GetRandom() noexcept;
bool CreatureInField(const Creature* creature) const; bool CreatureInField(ArbUt::BorrowedPtr<Creature> creature) const;
Creature* GetCreature(const CreatureIndex& target) const { const ArbUt::BorrowedPtr<Creature>& GetCreature(const CreatureIndex& target) const {
return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex()); return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex());
} }
Creature* GetCreature(uint8_t side, uint8_t target) const { return _sides[side]->GetCreature(target); } const ArbUt::BorrowedPtr<Creature>& GetCreature(uint8_t side, uint8_t target) const {
return _sides[side]->GetCreature(target);
}
void ForceRecall(uint8_t side, uint8_t index); void ForceRecall(uint8_t side, uint8_t index);
void SwitchCreature(uint8_t side, uint8_t index, Creature* c); void SwitchCreature(uint8_t side, uint8_t index, Creature* c);

View File

@ -13,7 +13,7 @@ namespace CreatureLib::Battling {
public: public:
BattleRandom() noexcept : _random() {} BattleRandom() noexcept : _random() {}
BattleRandom(uint_fast32_t seed) noexcept : _random(seed) {} explicit BattleRandom(uint_fast32_t seed) noexcept : _random(seed) {}
bool EffectChance(float chance, ExecutingAttack* attack, Creature* target); bool EffectChance(float chance, ExecutingAttack* attack, Creature* target);
int32_t Get() noexcept { return _random.Get(); } int32_t Get() noexcept { return _random.Get(); }

View File

@ -26,15 +26,13 @@ void BattleSide::ResetChoices() noexcept {
} }
} }
const ArbUt::List<BaseTurnChoice*>& BattleSide::GetChoices() const noexcept { return _choices; }
void BattleSide::SetChoice(BaseTurnChoice* choice) { void BattleSide::SetChoice(BaseTurnChoice* choice) {
AssertNotNull(choice) AssertNotNull(choice)
auto find = std::find(_creatures.begin(), _creatures.end(), choice->GetUser()); auto find = std::find(_creatures.begin(), _creatures.end(), choice->GetUser());
if (find == _creatures.end()) if (find == _creatures.end())
throw CreatureException("User not found"); throw CreatureException("User not found");
uint8_t index = std::distance(_creatures.begin(), find); uint8_t index = std::distance(_creatures.begin(), find);
_choices[index] = choice; _choices[index] = std::shared_ptr<BaseTurnChoice>(choice);
_choicesSet++; _choicesSet++;
} }
@ -56,18 +54,18 @@ void BattleSide::SetCreature(Creature* creature, uint8_t index) {
for (auto c : side->GetCreatures()) { for (auto c : side->GetCreatures()) {
if (c != nullptr) { if (c != nullptr) {
c->MarkOpponentAsSeen(creature); c->MarkOpponentAsSeen(creature);
creature->MarkOpponentAsSeen(c); creature->MarkOpponentAsSeen(c.GetRaw());
} }
} }
} }
} }
bool BattleSide::CreatureOnSide(const Creature* creature) const { bool BattleSide::CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const {
AssertNotNull(creature) AssertNotNull(creature)
return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end(); return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end();
} }
Creature* BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; } const ArbUt::BorrowedPtr<Creature>& BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; }
void BattleSide::GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) { void BattleSide::GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) {
scripts.Append(ScriptWrapper::FromSet(&_volatile)); scripts.Append(ScriptWrapper::FromSet(&_volatile));

View File

@ -11,16 +11,16 @@ namespace CreatureLib::Battling {
class BattleSide : public ScriptSource { class BattleSide : public ScriptSource {
uint8_t _index; uint8_t _index;
uint8_t _creaturesPerSide; uint8_t _creaturesPerSide;
ArbUt::List<Creature*> _creatures; ArbUt::List<ArbUt::BorrowedPtr<Creature>> _creatures;
ArbUt::List<BaseTurnChoice*> _choices; ArbUt::List<std::shared_ptr<BaseTurnChoice>> _choices;
ArbUt::List<bool> _fillableSlots; ArbUt::List<bool> _fillableSlots;
uint8_t _choicesSet = 0; uint8_t _choicesSet = 0;
ScriptSet _volatile; ScriptSet _volatile;
Battle* _battle; ArbUt::BorrowedPtr<Battle> _battle;
bool _hasFled = false; bool _hasFled = false;
public: public:
BattleSide(uint8_t index, Battle* battle, uint8_t creaturesPerSide) noexcept BattleSide(uint8_t index, ArbUt::BorrowedPtr<Battle> battle, uint8_t creaturesPerSide) noexcept
: _index(index), _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide), : _index(index), _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide),
_choices(creaturesPerSide), _fillableSlots(creaturesPerSide), _battle(battle) { _choices(creaturesPerSide), _fillableSlots(creaturesPerSide), _battle(battle) {
for (size_t i = 0; i < creaturesPerSide; i++) { for (size_t i = 0; i < creaturesPerSide; i++) {
@ -34,7 +34,9 @@ namespace CreatureLib::Battling {
virtual ~BattleSide() = default; virtual ~BattleSide() = default;
[[nodiscard]] bool AllChoicesSet() const noexcept; [[nodiscard]] bool AllChoicesSet() const noexcept;
[[nodiscard]] const ArbUt::List<BaseTurnChoice*>& GetChoices() const noexcept; [[nodiscard]] const ArbUt::List<std::shared_ptr<BaseTurnChoice>>& GetChoices() const noexcept {
return _choices;
}
[[nodiscard]] bool AllPossibleSlotsFilled() const; [[nodiscard]] bool AllPossibleSlotsFilled() const;
@ -43,24 +45,24 @@ namespace CreatureLib::Battling {
void SetCreature(Creature* creature, uint8_t index); void SetCreature(Creature* creature, uint8_t index);
Creature* GetCreature(uint8_t index) const; const ArbUt::BorrowedPtr<Creature>& GetCreature(uint8_t index) const;
bool CreatureOnSide(const Creature* creature) const; bool CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const;
size_t ScriptCount() const override; size_t ScriptCount() const override;
void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override; void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override;
const ArbUt::List<Creature*>& GetCreatures() { return _creatures; } const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& GetCreatures() { return _creatures; }
uint8_t GetSideIndex() noexcept { return _index; } uint8_t GetSideIndex() noexcept { return _index; }
uint8_t GetCreatureIndex(Creature* c) { uint8_t GetCreatureIndex(const ArbUt::BorrowedPtr<Creature>& c) {
for (size_t i = 0; i < _creatures.Count(); i++) { for (size_t i = 0; i < _creatures.Count(); i++) {
if (c == _creatures[i]) if (_creatures[i] == c)
return i; return i;
} }
throw CreatureException("Unable to find creature on field."); throw CreatureException("Unable to find creature on field.");
} }
void MarkSlotAsUnfillable(Creature* creature) noexcept { void MarkSlotAsUnfillable(const ArbUt::BorrowedPtr<Creature>& creature) noexcept {
for (uint8_t i = 0; i < _creaturesPerSide; i++) { for (uint8_t i = 0; i < _creaturesPerSide; i++) {
if (_creatures[i] == creature) { if (_creatures[i] == creature) {
_fillableSlots.At(i) = false; _fillableSlots.At(i) = false;

View File

@ -45,7 +45,7 @@ const ConstString& Battling::Creature::GetActiveTalent() const {
return _variant->GetTalent(_talentIndex); return _variant->GetTalent(_talentIndex);
} }
void Battling::Creature::SetBattleData(Battling::Battle* battle, Battling::BattleSide* side) { void Battling::Creature::SetBattleData(ArbUt::BorrowedPtr<Battle> battle, BattleSide* side) {
_battle = battle; _battle = battle;
_side = side; _side = side;
this->ResetActiveScripts(); this->ResetActiveScripts();
@ -85,7 +85,7 @@ void Battling::Creature::RecalculateBoostedStat(Library::Statistic stat) {
// endregion // endregion
Battling::Battle* Battling::Creature::GetBattle() const { return _battle; } const ArbUt::BorrowedPtr<CreatureLib::Battling::Battle>& Battling::Creature::GetBattle() const { return _battle; }
Battling::BattleSide* Battling::Creature::GetBattleSide() const { return _side; } Battling::BattleSide* Battling::Creature::GetBattleSide() const { return _side; }

View File

@ -41,7 +41,7 @@ namespace CreatureLib::Battling {
Library::StatisticSet<uint32_t> _flatStats; Library::StatisticSet<uint32_t> _flatStats;
Library::StatisticSet<uint32_t> _boostedStats; Library::StatisticSet<uint32_t> _boostedStats;
Battle* _battle = nullptr; ArbUt::BorrowedPtr<Battle> _battle = nullptr;
BattleSide* _side = nullptr; BattleSide* _side = nullptr;
bool _onBattleField = false; bool _onBattleField = false;
@ -101,8 +101,8 @@ namespace CreatureLib::Battling {
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; } inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }
void SetBattleData(Battle* battle, BattleSide* side); void SetBattleData(ArbUt::BorrowedPtr<Battle> battle, BattleSide* side);
Battle* GetBattle() const; const ArbUt::BorrowedPtr<Battle>& GetBattle() const;
BattleSide* GetBattleSide() const; BattleSide* GetBattleSide() const;
void SetOnBattleField(bool value) { _onBattleField = value; } void SetOnBattleField(bool value) { _onBattleField = value; }
bool IsOnBattleField() const { return _onBattleField; } bool IsOnBattleField() const { return _onBattleField; }

View File

@ -36,7 +36,7 @@ namespace CreatureLib::Battling {
}; };
private: private:
ArbUt::List<Creature*> _targets; ArbUt::List<ArbUt::BorrowedPtr<Creature>> _targets;
uint8_t _numberHits; uint8_t _numberHits;
HitData* _hits; HitData* _hits;
Creature* _user; Creature* _user;
@ -44,7 +44,7 @@ namespace CreatureLib::Battling {
Script* _script; Script* _script;
public: public:
ExecutingAttack(const ArbUt::List<Creature*>& targets, uint8_t numberHits, Creature* user, ExecutingAttack(const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& targets, uint8_t numberHits, Creature* user,
const ArbUt::BorrowedPtr<LearnedAttack>& attack, Script* script) const ArbUt::BorrowedPtr<LearnedAttack>& attack, Script* script)
: _targets(targets.Count()), _numberHits(numberHits), _hits(new HitData[targets.Count() * numberHits]), : _targets(targets.Count()), _numberHits(numberHits), _hits(new HitData[targets.Count() * numberHits]),
_user(user), _attack(attack), _script(script) { _user(user), _attack(attack), _script(script) {
@ -82,7 +82,7 @@ namespace CreatureLib::Battling {
} }
bool IsCreatureTarget(Creature* creature) noexcept { return _targets.IndexOf(creature) != (size_t)-1; } bool IsCreatureTarget(Creature* creature) noexcept { return _targets.IndexOf(creature) != (size_t)-1; }
const ArbUt::List<Creature*>& GetTargets() noexcept { return _targets; } const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& GetTargets() noexcept { return _targets; }
uint8_t GetNumberOfHits() const noexcept { return _numberHits; } uint8_t GetNumberOfHits() const noexcept { return _numberHits; }
Creature* GetUser() noexcept { return _user; } Creature* GetUser() noexcept { return _user; }

View File

@ -16,11 +16,11 @@ TEST_CASE("Move creature choice up next.", "[Battling]") {
auto c3 = CreateCreature(lib, "testSpecies1"_cnc, 1).Create(); auto c3 = CreateCreature(lib, "testSpecies1"_cnc, 1).Create();
auto c4 = CreateCreature(lib, "testSpecies1"_cnc, 1).Create(); auto c4 = CreateCreature(lib, "testSpecies1"_cnc, 1).Create();
std::vector<BaseTurnChoice*> choices = { std::vector<std::shared_ptr<BaseTurnChoice>> choices = {
new PassTurnChoice(c1), std::make_shared<PassTurnChoice>(c1),
new PassTurnChoice(c2), std::make_shared<PassTurnChoice>(c2),
new PassTurnChoice(c3), std::make_shared<PassTurnChoice>(c3),
new PassTurnChoice(c4), std::make_shared<PassTurnChoice>(c4),
}; };
auto choiceQueue = ChoiceQueue(choices); auto choiceQueue = ChoiceQueue(choices);

View File

@ -14,7 +14,6 @@ TEST_CASE("Set Choice one-sized side", "[Battling]") {
side.SetCreature(c, 0); side.SetCreature(c, 0);
auto choice = new PassTurnChoice(c); auto choice = new PassTurnChoice(c);
side.SetChoice(choice); side.SetChoice(choice);
delete choice;
delete c; delete c;
} }
@ -26,7 +25,6 @@ TEST_CASE("Set Choice one-sized side, validate all choices set", "[Battling]") {
REQUIRE_FALSE(side.AllChoicesSet()); REQUIRE_FALSE(side.AllChoicesSet());
side.SetChoice(choice); side.SetChoice(choice);
REQUIRE(side.AllChoicesSet()); REQUIRE(side.AllChoicesSet());
delete choice;
delete c; delete c;
} }
@ -40,8 +38,6 @@ TEST_CASE("Set Choice two-sized side", "[Battling]") {
auto choice2 = new PassTurnChoice(c2); auto choice2 = new PassTurnChoice(c2);
side.SetChoice(choice1); side.SetChoice(choice1);
side.SetChoice(choice2); side.SetChoice(choice2);
delete choice1;
delete choice2;
delete c1; delete c1;
delete c2; delete c2;
} }
@ -59,8 +55,6 @@ TEST_CASE("Set Choice two-sized side, validate all choices set", "[Battling]") {
REQUIRE_FALSE(side.AllChoicesSet()); REQUIRE_FALSE(side.AllChoicesSet());
side.SetChoice(choice2); side.SetChoice(choice2);
REQUIRE(side.AllChoicesSet()); REQUIRE(side.AllChoicesSet());
delete choice1;
delete choice2;
delete c1; delete c1;
delete c2; delete c2;
} }

View File

@ -13,40 +13,35 @@ TEST_CASE("Turn ordering: Attack before pass", "[Battling]") {
auto lib = TestLibrary::Get(); auto lib = TestLibrary::Get();
auto learnedAttack = auto learnedAttack =
LearnedAttack(lib->GetAttackLibrary()->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown); LearnedAttack(lib->GetAttackLibrary()->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto choice1 = new PassTurnChoice(nullptr); auto choice1 = std::make_shared<PassTurnChoice>(nullptr);
auto choice2 = new AttackTurnChoice(nullptr, &learnedAttack, CreatureIndex(0, 0)); auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, &learnedAttack, CreatureIndex(0, 0));
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2}; auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
auto rand = ArbUt::Random(); auto rand = ArbUt::Random();
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
vec = std::vector<BaseTurnChoice*>{choice2, choice1}; vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice2, choice1};
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
delete choice1;
delete choice2;
} }
TEST_CASE("Turn ordering: High priority goes before no priority", "[Battling]") { TEST_CASE("Turn ordering: High priority goes before no priority", "[Battling]") {
const auto& l = TestLibrary::Get()->GetAttackLibrary(); const auto& l = TestLibrary::Get()->GetAttackLibrary();
auto a1 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a1 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto a2 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a2 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0)); auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0)); auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2}; auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
auto rand = ArbUt::Random(); auto rand = ArbUt::Random();
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
vec = std::vector<BaseTurnChoice*>{choice2, choice1}; vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice2, choice1};
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
delete choice1;
delete choice2;
delete a1; delete a1;
delete a2; delete a2;
} }
@ -55,20 +50,17 @@ TEST_CASE("Turn ordering: Higher priority goes before high priority", "[Battling
const auto& l = TestLibrary::Get()->GetAttackLibrary(); const auto& l = TestLibrary::Get()->GetAttackLibrary();
auto a1 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a1 = new LearnedAttack(l->Get("highPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0)); auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0)); auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2}; auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
auto rand = ArbUt::Random(); auto rand = ArbUt::Random();
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
vec = std::vector<BaseTurnChoice*>{choice2, choice1}; vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice2, choice1};
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
delete choice1;
delete choice2;
delete a1; delete a1;
delete a2; delete a2;
} }
@ -77,20 +69,18 @@ TEST_CASE("Turn ordering: High priority goes before low priority", "[Battling]")
const auto& l = TestLibrary::Get()->GetAttackLibrary(); const auto& l = TestLibrary::Get()->GetAttackLibrary();
auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a2 = new LearnedAttack(l->Get("higherPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0)); auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0)); auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2}; auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
auto rand = ArbUt::Random(); auto rand = ArbUt::Random();
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
vec = std::vector<BaseTurnChoice*>{choice2, choice1}; vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice2, choice1};
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
delete choice1;
delete choice2;
delete a1; delete a1;
delete a2; delete a2;
} }
@ -99,20 +89,18 @@ TEST_CASE("Turn ordering: No priority goes before low priority", "[Battling]") {
const auto& l = TestLibrary::Get()->GetAttackLibrary(); const auto& l = TestLibrary::Get()->GetAttackLibrary();
auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a1 = new LearnedAttack(l->Get("lowPriority"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto a2 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown); auto a2 = new LearnedAttack(l->Get("standard"_cnc.GetHash()), AttackLearnMethod::Unknown);
auto choice1 = new AttackTurnChoice(nullptr, a1, CreatureIndex(0, 0)); auto choice1 = std::make_shared<AttackTurnChoice>(nullptr, a1, CreatureIndex(0, 0));
auto choice2 = new AttackTurnChoice(nullptr, a2, CreatureIndex(0, 0)); auto choice2 = std::make_shared<AttackTurnChoice>(nullptr, a2, CreatureIndex(0, 0));
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2}; auto vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice1, choice2};
auto rand = ArbUt::Random(); auto rand = ArbUt::Random();
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
vec = std::vector<BaseTurnChoice*>{choice2, choice1}; vec = std::vector<std::shared_ptr<BaseTurnChoice>>{choice2, choice1};
TurnOrdering::OrderChoices(vec, rand); TurnOrdering::OrderChoices(vec, rand);
CHECK(vec[0] == choice2); CHECK(vec[0] == choice2);
CHECK(vec[1] == choice1); CHECK(vec[1] == choice1);
delete choice1;
delete choice2;
delete a1; delete a1;
delete a2; delete a2;
} }