Added lots of security using asserts.
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2020-03-22 13:42:26 +01:00
parent 970ca8ddd5
commit 899e432271
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
35 changed files with 138 additions and 56 deletions

View File

@ -116,6 +116,8 @@ Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
- Assert
- AssertNotNull
TabWidth: 8
UseTab: Never
...

View File

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

View File

@ -16,6 +16,7 @@ namespace CreatureLib::Battling {
void RegisterListener(EVENT_HOOK_FUNC(func)) { _listeners.push_back(func); }
void TriggerEvent(EventData* eventData) const {
AssertNotNull(eventData)
for (auto listener : _listeners) {
listener(eventData);
}

View File

@ -1,6 +1,8 @@
#include "ChoiceQueue.hpp"
#include <Arbutils/Assert.hpp>
bool CreatureLib::Battling::ChoiceQueue::MoveCreatureChoiceNext(CreatureLib::Battling::Creature* creature) {
AssertNotNull(creature)
// Find which index the creature choice is at.
size_t choiceIndex = SIZE_MAX;
for (size_t index = _current; index < _queue.size(); index++) {

View File

@ -1,11 +1,12 @@
#include "TurnHandler.hpp"
#include <Arbutils/Assert.hpp>
#include "../../Library/Exceptions/NotImplementedException.hpp"
#include "../Models/Battle.hpp"
#include "../ScriptHandling/ScriptMacros.hpp"
using namespace CreatureLib::Battling;
void TurnHandler::RunTurn(Battle* battle, ChoiceQueue* queue) {
void TurnHandler::RunTurn(ChoiceQueue* queue) {
AssertNotNull(queue)
for (auto choice : queue->GetInnerQueue()) {
HOOK(OnBeforeTurn, choice, choice);
}
@ -31,6 +32,7 @@ void TurnHandler::ExecuteChoice(BaseTurnChoice* choice) {
return;
}
auto battle = user->GetBattle();
AssertNotNull(battle)
// If the user is not in the field, we don't want to execute its choice.
if (!battle->CreatureInField(user)) {
return;
@ -51,6 +53,7 @@ void TurnHandler::ExecuteChoice(BaseTurnChoice* choice) {
}
void TurnHandler::ExecuteAttackChoice(AttackTurnChoice* choice) {
AssertNotNull(choice)
auto attackName = choice->GetAttack()->GetAttack()->GetName();
HOOK(ChangeAttack, choice, choice, &attackName);
if (attackName != choice->GetAttack()->GetAttack()->GetName()) {

View File

@ -21,7 +21,7 @@ namespace CreatureLib::Battling {
static void ExecuteFleeChoice(FleeTurnChoice* choice);
public:
static void RunTurn(Battle* battle, ChoiceQueue* queue);
static void RunTurn(ChoiceQueue* queue);
};
}

View File

@ -1,5 +1,4 @@
#include "BattleLibrary.hpp"
#include <cassert>
using namespace CreatureLib::Battling;

View File

@ -1,4 +1,5 @@
#include "BattleStatCalculator.hpp"
#include <Arbutils/Assert.hpp>
#include "../../Library/Exceptions/NotImplementedException.hpp"
#include "../Models/Creature.hpp"
@ -24,12 +25,14 @@ Battling::BattleStatCalculator::CalculateBoostedStats(Battling::Creature* creatu
}
uint32_t CalculateHealthStat(Battling::Creature* creature) {
AssertNotNull(creature)
auto level = creature->GetLevel();
auto a = (creature->GetBaseStat(Library::Statistic::Health)) * 2 * level;
return floor(a / 100) + level + 10;
}
uint32_t CalculateOtherStat(Battling::Creature* creature, Library::Statistic stat) {
AssertNotNull(creature)
auto level = creature->GetLevel();
auto a = (creature->GetBaseStat(stat)) * 2 * level;
return floor(a / 100) + 10;

View File

@ -1,8 +1,11 @@
#include "DamageLibrary.hpp"
#include <Arbutils/Assert.hpp>
#include "../ScriptHandling/ScriptMacros.hpp"
using namespace CreatureLib::Battling;
uint32_t DamageLibrary::GetDamage(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const {
AssertNotNull(attack)
AssertNotNull(target)
auto levelMod = static_cast<float>(2 * attack->GetUser()->GetLevel());
auto hit = attack->GetAttackDataForTarget(target)->GetHit(hitIndex);
auto bp = hit->GetBasePower();
@ -15,13 +18,18 @@ uint32_t DamageLibrary::GetDamage(ExecutingAttack* attack, Creature* target, uin
}
uint8_t DamageLibrary::GetBasePower(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const {
AssertNotNull(attack)
AssertNotNull(target)
auto bp = attack->GetAttack()->GetAttack()->GetBasePower();
HOOK(OverrideBasePower, attack, attack, target, hitIndex, &bp);
return bp;
}
float DamageLibrary::GetStatModifier(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const {
AssertNotNull(attack)
AssertNotNull(target)
auto user = attack->GetUser();
AssertNotNull(user)
HOOK(ChangeDamageStatsUser, attack, attack, target, hitIndex, &user);
auto hit = attack->GetAttackDataForTarget(target)->GetHit(hitIndex);
Library::Statistic offensiveStat;
@ -57,8 +65,11 @@ float DamageLibrary::GetStatModifier(ExecutingAttack* attack, Creature* target,
}
float DamageLibrary::GetDamageModifier(ExecutingAttack* attack, Creature* target, uint8_t hitIndex) const {
AssertNotNull(attack)
AssertNotNull(target)
float mod = 1;
auto hit = attack->GetAttackDataForTarget(target)->GetHit(hitIndex);
AssertNotNull(hit)
mod *= hit->GetEffectiveness();
HOOK(ModifyDamageModifier, attack, attack, target, hitIndex, &mod);
return mod;

View File

@ -4,6 +4,8 @@
void CreatureLib::Battling::ExperienceLibrary::HandleExperienceGain(
CreatureLib::Battling::Creature* faintedMon, const std::unordered_set<Creature*>& opponents) const {
for (auto opponent : opponents) {
if (opponent == nullptr)
continue;
auto levelDiff = faintedMon->GetLevel() - opponent->GetLevel() + 10;
if (levelDiff <= 0)
continue;

View File

@ -1,9 +1,11 @@
#include "MiscLibrary.hpp"
#include <Arbutils/Assert.hpp>
#include "../Models/Battle.hpp"
#include "../TurnChoices/AttackTurnChoice.hpp"
bool CreatureLib::Battling::MiscLibrary::IsCritical(CreatureLib::Battling::ExecutingAttack* attack,
CreatureLib::Battling::Creature* target, uint8_t hit) const {
AssertNotNull(target)
auto rand = target->GetBattle()->GetRandom();
return rand->Get(10) <= 0;
}
@ -31,6 +33,7 @@ static CreatureLib::Battling::LearnedAttack* GetReplacementAttack() {
bool CreatureLib::Battling::MiscLibrary::CanFlee(FleeTurnChoice* switchChoice) const { return true; }
CreatureLib::Battling::BaseTurnChoice*
CreatureLib::Battling::MiscLibrary::ReplacementAttack(Creature* user, CreatureIndex target) const {
AssertNotNull(user)
auto sideTarget = 0;
if (user->GetBattleSide()->GetSideIndex() == 0)
sideTarget = 1;

View File

@ -1,4 +1,5 @@
#include "Battle.hpp"
#include <Arbutils/Assert.hpp>
#include "../../Library/Exceptions/NotImplementedException.hpp"
#include "../Flow/TurnHandler.hpp"
#include "../Flow/TurnOrdering.hpp"
@ -9,6 +10,7 @@ using namespace CreatureLib::Battling;
const BattleLibrary* Battle::GetLibrary() const { return _library; }
bool Battle::CanUse(const BaseTurnChoice* choice) {
AssertNotNull(choice)
if (choice->GetKind() == TurnChoiceKind::Attack) {
// HOOK: change number of uses needed.
return dynamic_cast<const AttackTurnChoice*>(choice)->GetAttack()->GetRemainingUses() > 1;
@ -17,6 +19,7 @@ bool Battle::CanUse(const BaseTurnChoice* choice) {
}
bool Battle::TrySetChoice(BaseTurnChoice* choice) {
AssertNotNull(choice)
if (!CanUse(choice))
return false;
choice->GetUser()->GetBattleSide()->SetChoice(choice);
@ -40,9 +43,7 @@ void Battle::CheckChoicesSetAndRun() {
auto i = 0;
for (auto side : _sides) {
for (BaseTurnChoice* choice : side->GetChoices()) {
if (choice == nullptr) {
throw CreatureException("Choice was null");
}
AssertNotNull(choice)
if (choice->GetKind() == TurnChoiceKind::Attack) {
auto attack = (dynamic_cast<AttackTurnChoice*>((choice)))->GetAttack();
uint8_t uses = 1;
@ -60,7 +61,7 @@ void Battle::CheckChoicesSetAndRun() {
}
TurnOrdering::OrderChoices(choices, _random.GetRNG());
this->_currentTurnQueue = new ChoiceQueue(choices);
TurnHandler::RunTurn(this, this->_currentTurnQueue);
TurnHandler::RunTurn(this->_currentTurnQueue);
if (this->_currentTurnQueue->HasCompletedQueue) {
delete this->_currentTurnQueue;
this->_currentTurnQueue = nullptr;
@ -72,6 +73,7 @@ ChoiceQueue* Battle::GetCurrentTurnQueue() const { return _currentTurnQueue; }
BattleRandom* Battle::GetRandom() { return &_random; }
bool Battle::CreatureInField(const Creature* creature) const {
AssertNotNull(creature)
for (auto s : _sides) {
if (s->CreatureOnSide(creature))
return true;
@ -84,6 +86,7 @@ void Battle::ForceRecall(uint8_t side, uint8_t index) { _sides[side]->SetCreatur
void Battle::GetActiveScripts(std::vector<ScriptWrapper>& scripts) { scripts.emplace_back(&_volatile); }
void Battle::SwitchCreature(uint8_t sideIndex, uint8_t index, Creature* c) {
AssertNotNull(c)
auto side = this->_sides[sideIndex];
side->SetCreature(c, index);
}

View File

@ -1,6 +1,7 @@
#ifndef CREATURELIB_BATTLE_HPP
#define CREATURELIB_BATTLE_HPP
#include <Arbutils/Assert.hpp>
#include <vector>
#include "../EventHooks/EventHook.hpp"
#include "../Flow/ChoiceQueue.hpp"
@ -33,6 +34,10 @@ namespace CreatureLib::Battling {
uint8_t numberOfSides = 2, uint8_t creaturesPerSide = 1)
: _library(library), _parties(std::move(parties)), _canFlee(canFlee), _numberOfSides(numberOfSides),
_creaturesPerSide(creaturesPerSide) {
AssertNotNull(_library)
for (auto p : parties)
AssertNotNull(p)
_sides = std::vector<BattleSide*>(numberOfSides);
for (size_t i = 0; i < numberOfSides; i++) {
_sides[i] = new BattleSide(i, this, creaturesPerSide);
@ -64,6 +69,7 @@ namespace CreatureLib::Battling {
bool CreatureInField(const Creature* creature) const;
Creature* GetCreature(const CreatureIndex& target) const {
Assert(target.GetSideIndex() < _sides.size())
return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex());
}
Creature* GetCreature(uint8_t side, uint8_t target) const { return _sides[side]->GetCreature(target); }

View File

@ -1,9 +1,9 @@
#ifndef CREATURELIB_BATTLEPARTY_HPP
#define CREATURELIB_BATTLEPARTY_HPP
#include <Arbutils/Assert.hpp>
#include "CreatureIndex.hpp"
#include "CreatureParty.hpp"
namespace CreatureLib::Battling {
class BattleParty {
CreatureParty* _party;
@ -11,7 +11,9 @@ namespace CreatureLib::Battling {
public:
BattleParty(CreatureParty* party, std::vector<CreatureIndex> responsibleIndices)
: _party(party), _responsibleIndices(responsibleIndices) {}
: _party(party), _responsibleIndices(responsibleIndices) {
AssertNotNull(_party)
}
inline CreatureParty* GetParty() const { return _party; }
inline const std::vector<CreatureIndex>& GetResponsibleIndices() const { return _responsibleIndices; }

View File

@ -8,6 +8,7 @@ using namespace CreatureLib::Battling;
bool BattleSide::AllChoicesSet() const { return _choicesSet == _creaturesPerSide; }
bool BattleSide::AllPossibleSlotsFilled() const {
AssertNotNull(_battle)
for (size_t i = 0; i < _creatures.size(); i++) {
auto c = _creatures[i];
if (c == nullptr || c->IsFainted()) {
@ -28,6 +29,7 @@ void BattleSide::ResetChoices() {
const std::vector<BaseTurnChoice*>& BattleSide::GetChoices() const { return _choices; }
void BattleSide::SetChoice(BaseTurnChoice* choice) {
AssertNotNull(choice)
auto find = std::find(_creatures.begin(), _creatures.end(), choice->GetUser());
if (find == _creatures.end())
throw CreatureException("User not found");
@ -37,6 +39,7 @@ void BattleSide::SetChoice(BaseTurnChoice* choice) {
}
void BattleSide::SetCreature(Creature* creature, uint8_t index) {
AssertNotNull(creature)
auto old = _creatures[index];
if (old != nullptr) {
old->SetOnBattleField(false);
@ -59,6 +62,7 @@ void BattleSide::SetCreature(Creature* creature, uint8_t index) {
}
bool BattleSide::CreatureOnSide(const Creature* creature) const {
AssertNotNull(creature)
return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end();
}
@ -70,5 +74,6 @@ void BattleSide::GetActiveScripts(std::vector<ScriptWrapper>& scripts) {
}
uint8_t BattleSide::GetRandomCreatureIndex() {
// TODO: Consider adding parameter to only get index for available creatures.
AssertNotNull(_battle)
return _battle->GetRandom()->Get(_creaturesPerSide);
}

View File

@ -1,6 +1,7 @@
#ifndef CREATURELIB_BATTLESIDE_HPP
#define CREATURELIB_BATTLESIDE_HPP
#include <Arbutils/Assert.hpp>
#include <vector>
#include "../TurnChoices/BaseTurnChoice.hpp"
#include "Creature.hpp"
@ -19,10 +20,8 @@ namespace CreatureLib::Battling {
public:
explicit BattleSide(uint8_t index, Battle* battle, uint8_t creaturesPerSide)
: _index(index), _creaturesPerSide(creaturesPerSide), _battle(battle) {
_creatures = std::vector<Creature*>(creaturesPerSide);
_choices = std::vector<BaseTurnChoice*>(creaturesPerSide);
_fillableSlots = std::vector<bool>(creaturesPerSide);
: _index(index), _creaturesPerSide(creaturesPerSide), _creatures(creaturesPerSide),
_choices(creaturesPerSide), _fillableSlots(creaturesPerSide), _battle(battle) {
for (size_t i = 0; i < creaturesPerSide; i++) {
_creatures[i] = nullptr;
_choices[i] = nullptr;

View File

@ -14,6 +14,9 @@ Battling::Creature::Creature(const BattleLibrary* library, const Library::Creatu
: _library(library), _species(species), _variant(variant), _level(level), _experience(experience),
_uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _heldItem(heldItem), _nickname(std::move(nickname)),
_talentIndex(talent), _hasOverridenTalent(false), _attacks(std::move(attacks)) {
AssertNotNull(library)
AssertNotNull(species)
AssertNotNull(variant)
_activeTalent = _library->LoadScript(ScriptCategory::Talent, GetActiveTalent());
if (_nickname.empty()) {
@ -84,7 +87,7 @@ Battling::Battle* Battling::Creature::GetBattle() const { return _battle; }
Battling::BattleSide* Battling::Creature::GetBattleSide() const { return _side; }
bool Battling::Creature::IsFainted() const { return this->_currentHealth <= 0; }
bool Battling::Creature::IsFainted() const noexcept { return this->_currentHealth <= 0; }
void Battling::Creature::OnFaint() {
// HOOK: On Faint
@ -140,12 +143,12 @@ void Battling::Creature::OverrideActiveTalent(const ConstString& talent) {
_activeTalent = this->_library->LoadScript(ScriptCategory::Talent, talent);
}
const std::vector<uint8_t>& Battling::Creature::GetTypes() const {
const std::vector<uint8_t>& Battling::Creature::GetTypes() const noexcept {
// HOOK: override types.
return this->_variant->GetTypes();
}
bool Battling::Creature::HasType(uint8_t type) const {
bool Battling::Creature::HasType(uint8_t type) const noexcept {
auto t = GetTypes();
return std::find(t.begin(), t.end(), type) != t.end();
}

View File

@ -76,24 +76,24 @@ namespace CreatureLib::Battling {
_currentHealth = GetBoostedStat(Library::Statistic::Health);
}
inline const Library::CreatureSpecies* GetSpecies() const { return _species; }
inline const Library::SpeciesVariant* GetVariant() const { return _variant; }
inline uint8_t GetLevel() const { return _level; }
inline uint32_t GetExperience() const { return _experience; }
inline Library::Gender GetGender() const { return _gender; }
inline uint8_t GetColoring() const { return _coloring; }
inline bool HasHeldItem(const ConstString& name) const {
inline const Library::CreatureSpecies* GetSpecies() const noexcept { return _species; }
inline const Library::SpeciesVariant* GetVariant() const noexcept { return _variant; }
inline uint8_t GetLevel() const noexcept { return _level; }
inline uint32_t GetExperience() const noexcept { return _experience; }
inline Library::Gender GetGender() const noexcept { return _gender; }
inline uint8_t GetColoring() const noexcept { return _coloring; }
inline bool HasHeldItem(const ConstString& name) const noexcept {
return _heldItem != nullptr && _heldItem->GetName() == name;
}
inline bool HasHeldItem(uint32_t nameHash) const {
inline bool HasHeldItem(uint32_t nameHash) const noexcept {
return _heldItem != nullptr && _heldItem->GetName() == nameHash;
}
inline const Library::Item* GetHeldItem() const { return _heldItem; }
inline const Library::Item* GetHeldItem() const noexcept { return _heldItem; }
void SetHeldItem(const ConstString& itemName);
void SetHeldItem(uint32_t itemNameHash);
inline void SetHeldItem(const Library::Item* item) { _heldItem = item; };
inline void SetHeldItem(const Library::Item* item) noexcept { _heldItem = item; };
inline uint32_t GetCurrentHealth() const { return _currentHealth; }
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }
void SetBattleData(Battle* battle, BattleSide* side);
Battle* GetBattle() const;
@ -101,14 +101,14 @@ namespace CreatureLib::Battling {
void SetOnBattleField(bool value) { _onBattleField = value; }
bool IsOnBattleField() const { return _onBattleField; }
const std::string& GetNickname() const { return _nickname; }
const std::string& GetNickname() const noexcept { return _nickname; }
const ConstString& GetActiveTalent() const;
[[nodiscard]] bool IsFainted() const;
[[nodiscard]] const std::vector<uint8_t>& GetTypes() const;
[[nodiscard]] bool HasType(uint8_t type) const;
[[nodiscard]] bool IsFainted() const noexcept;
[[nodiscard]] const std::vector<uint8_t>& GetTypes() const noexcept;
[[nodiscard]] bool HasType(uint8_t type) const noexcept;
uint32_t GetMaxHealth() const { return _boostedStats.GetHealth(); }
uint32_t GetMaxHealth() const noexcept { return _boostedStats.GetHealth(); }
void ChangeLevelBy(int8_t amount);
void Damage(uint32_t damage, DamageSource source);
void Heal(uint32_t amount, bool canRevive = false);

View File

@ -1,6 +1,7 @@
#ifndef CREATURELIB_EXECUTINGATTACK_HPP
#define CREATURELIB_EXECUTINGATTACK_HPP
#include <Arbutils/Assert.hpp>
#include <cstdint>
#include <unordered_map>
#include <vector>
@ -61,6 +62,8 @@ namespace CreatureLib::Battling {
ExecutingAttack(const std::vector<Creature*>& targets, uint8_t numberHits, Creature* user,
LearnedAttack* attack, Script* script)
: _user(user), _attack(attack), _script(script) {
AssertNotNull(user)
AssertNotNull(attack)
_targets.reserve(targets.size());
for (auto target : targets) {
_targets.insert({target, TargetData(numberHits)});

View File

@ -1,8 +1,10 @@
#include "LearnedAttack.hpp"
#include <Arbutils/Assert.hpp>
CreatureLib::Battling::LearnedAttack::LearnedAttack(CreatureLib::Library::AttackData* attack, uint8_t maxUses,
AttackLearnMethod learnMethod)
: _attack(attack), _maxUses(maxUses), _remainingUses(maxUses), _learnMethod(learnMethod) {}
: _attack(attack), _maxUses(maxUses), _remainingUses(maxUses), _learnMethod(learnMethod) {
AssertNotNull(_attack)
}
CreatureLib::Battling::LearnedAttack::LearnedAttack(const CreatureLib::Library::AttackData* attack,
AttackLearnMethod learnMethod)

View File

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

View File

@ -29,6 +29,7 @@ namespace CreatureLib::Battling {
public:
AttackTurnChoice(Creature* user, LearnedAttack* attack, const CreatureIndex& target)
: BaseTurnChoice(user), _attack(attack), _target(target) {
AssertNotNull(attack)
ResolveScript();
}
AttackTurnChoice(Creature* user, LearnedAttack* attack, const CreatureIndex& target, Script* script)

View File

@ -1,6 +1,7 @@
#ifndef CREATURELIB_BASETURNCHOICE_HPP
#define CREATURELIB_BASETURNCHOICE_HPP
#include <Arbutils/Assert.hpp>
#include "../ScriptHandling/ScriptSource.hpp"
#include "TurnChoiceKind.hpp"

View File

@ -7,7 +7,9 @@ namespace CreatureLib::Battling {
Creature* _newCreature;
public:
SwitchTurnChoice(Creature* user, Creature* newCreature) : BaseTurnChoice(user), _newCreature(newCreature) {}
SwitchTurnChoice(Creature* user, Creature* newCreature) : BaseTurnChoice(user), _newCreature(newCreature) {
AssertNotNull(_newCreature)
}
TurnChoiceKind GetKind() const final { return TurnChoiceKind::Switch; }

View File

@ -1,6 +1,7 @@
#ifndef CREATURELIB_BASELIBRARY_HPP
#define CREATURELIB_BASELIBRARY_HPP
#include <Arbutils/Assert.hpp>
#include <Arbutils/ConstString.hpp>
#include <algorithm>
#include <string>
@ -21,21 +22,19 @@ namespace CreatureLib::Library {
}
inline void Insert(const Arbutils::CaseInsensitiveConstString& key, const T* value) {
AssertNotNull(value)
_values.insert({key.GetHash(), value});
}
inline void Insert(uint32_t hashedKey, const T* value) { _values.insert({hashedKey, value}); }
inline void Insert(uint32_t hashedKey, const T* value) {
AssertNotNull(value)
_values.insert({hashedKey, value});
}
inline void Delete(const Arbutils::CaseInsensitiveConstString& key) { _values.erase(key.GetHash()); }
inline void Delete(uint32_t hashedKey) { _values.erase({hashedKey}); }
bool TryGet(const Arbutils::CaseInsensitiveConstString& name, const T*& out) const {
auto find = this->_values.find(name.GetHash());
if (find == this->_values.end()) {
out = nullptr;
return false;
}
out = find->second;
return true;
return TryGet(name.GetHash(), out);
}
bool TryGet(uint32_t hashedKey, const T*& out) const {
auto find = this->_values.find(hashedKey);

View File

@ -1,11 +1,14 @@
#include "CreatureSpecies.hpp"
#include <Arbutils/Assert.hpp>
using namespace CreatureLib::Library;
CreatureSpecies::CreatureSpecies(uint16_t id, const ConstString& name, const SpeciesVariant* defaultVariant,
float genderRatio, const ConstString& growthRate, uint8_t captureRate)
: _name(name), _id(id), _genderRate(genderRatio), _growthRate(growthRate), _captureRate(captureRate),
_variants({{"default"_cnc, defaultVariant}}) {}
_variants({{"default"_cnc, defaultVariant}}) {
AssertNotNull(defaultVariant)
}
bool CreatureSpecies::HasVariant(const ConstString& name) const { return _variants.find(name) != _variants.end(); }

View File

@ -1,6 +1,7 @@
#ifndef CREATURELIB_LEARNABLEATTACKS_HPP
#define CREATURELIB_LEARNABLEATTACKS_HPP
#include <Arbutils/Assert.hpp>
#include <unordered_map>
#include <vector>
#include "../Attacks/AttackData.hpp"
@ -11,7 +12,12 @@ namespace CreatureLib::Library {
public:
LearnableAttacks(size_t levelAttackCapacity)
: _learnedByLevel(std::unordered_map<uint8_t, std::vector<const AttackData*>>(levelAttackCapacity)) {}
: _learnedByLevel(std::unordered_map<uint8_t, std::vector<const AttackData*>>(levelAttackCapacity)) {
for (auto kv : _learnedByLevel) {
for (auto attack : kv.second)
AssertNotNull(attack)
}
}
void AddLevelMove(uint8_t level, const AttackData* attack);

View File

@ -37,7 +37,7 @@ const CreatureLib::Library::LearnableAttacks* CreatureLib::Library::SpeciesVaria
CreatureLib::Library::SpeciesVariant::SpeciesVariant(ConstString name, float height, float weight,
uint32_t baseExperience, std::vector<uint8_t> types,
CreatureLib::Library::StatisticSet<uint16_t> baseStats,
const CreatureLib::Library::StatisticSet<uint16_t>& baseStats,
std::vector<ConstString> talents,
std::vector<ConstString> secretTalents,
const LearnableAttacks* attacks)

View File

@ -23,14 +23,14 @@ namespace CreatureLib::Library {
private:
std::vector<uint8_t> _types;
const Library::StatisticSet<uint16_t> _baseStatistics;
const Library::StatisticSet<uint16_t>& _baseStatistics;
std::vector<ConstString> _talents;
std::vector<ConstString> _secretTalents;
const LearnableAttacks* _attacks;
public:
SpeciesVariant(ConstString name, float height, float weight, uint32_t baseExperience,
std::vector<uint8_t> types, Library::StatisticSet<uint16_t> baseStats,
std::vector<uint8_t> types, const Library::StatisticSet<uint16_t>& baseStats,
std::vector<ConstString> talents, std::vector<ConstString> secretTalents,
const LearnableAttacks* attacks);

View File

@ -6,7 +6,14 @@ CreatureLib::Library::DataLibrary::DataLibrary(LibrarySettings* settings, Creatu
CreatureLib::Library::GrowthRateLibrary* growthRates,
TypeLibrary* typeLibrary)
: _settings(settings), _species(species), _attacks(attacks), _items(items), _growthRates(growthRates),
_typeLibrary(typeLibrary) {}
_typeLibrary(typeLibrary) {
AssertNotNull(_settings)
AssertNotNull(_species)
AssertNotNull(_attacks)
AssertNotNull(_items)
AssertNotNull(_growthRates)
AssertNotNull(_typeLibrary)
}
const CreatureLib::Library::LibrarySettings* CreatureLib::Library::DataLibrary::GetSettings() const {
return _settings;

View File

@ -1,6 +1,7 @@
#ifndef CREATURELIB_EXTERNGROWTHRATE_HPP
#define CREATURELIB_EXTERNGROWTHRATE_HPP
#include <Arbutils/Assert.hpp>
#include "GrowthRate.hpp"
namespace CreatureLib::Library {
class ExternGrowthRate : public GrowthRate {
@ -9,7 +10,10 @@ namespace CreatureLib::Library {
public:
ExternGrowthRate(uint8_t (*calcLevel)(uint32_t), uint32_t (*calcExperience)(uint8_t level))
: _calcLevel(calcLevel), _calcExperience(calcExperience) {}
: _calcLevel(calcLevel), _calcExperience(calcExperience) {
AssertNotNull(calcLevel)
AssertNotNull(calcExperience)
}
uint8_t CalculateLevel(uint32_t experience) const override { return _calcLevel(experience); }
uint32_t CalculateExperience(uint8_t level) const override { return _calcExperience(level); }

View File

@ -20,7 +20,10 @@ namespace CreatureLib::Library {
return _experience[_experience.size() - 1];
}
uint32_t CalculateExperience(uint8_t level) const override { return _experience[level - 1]; }
uint32_t CalculateExperience(uint8_t level) const override {
Assert(level <= _experience.size())
return _experience[level - 1];
}
};
}

View File

@ -15,6 +15,9 @@ namespace CreatureLib::Library {
T _magicalDefense;
T _speed;
private:
StatisticSet<T>(const StatisticSet<T>& v) = delete;
public:
StatisticSet(T health, T physicalAttack, T physicalDefense, T magicalAttack, T magicalDefense, T speed)
: _health(health), _physicalAttack(physicalAttack), _physicalDefense(physicalDefense),

View File

@ -1,5 +1,5 @@
#include "TypeLibrary.hpp"
#include <algorithm>
#include <Arbutils/Assert.hpp>
using namespace CreatureLib::Library;
@ -12,6 +12,8 @@ float TypeLibrary::GetEffectiveness(uint8_t attacking, const std::vector<uint8_t
}
float TypeLibrary::GetSingleEffectiveness(uint8_t attacking, uint8_t defensive) const {
Assert(attacking < _effectiveness.size())
Assert(defensive < _effectiveness.size())
return _effectiveness[attacking][defensive];
}
@ -36,5 +38,7 @@ uint8_t TypeLibrary::RegisterType(uint32_t key) {
}
void TypeLibrary::SetEffectiveness(uint8_t attacking, uint8_t defensive, float effectiveness) {
Assert(attacking < _effectiveness.size())
Assert(defensive < _effectiveness.size())
_effectiveness[attacking][defensive] = effectiveness;
}

View File

@ -10,8 +10,10 @@ using namespace CreatureLib;
using namespace CreatureLib::Battling;
TEST_CASE("Turn ordering: Attack before pass", "[Battling]") {
auto lib = TestLibrary::Get();
auto learnedAttack = LearnedAttack(lib->GetAttackLibrary()->Get("standard"_cnc), AttackLearnMethod::Unknown);
auto choice1 = new PassTurnChoice(nullptr);
auto choice2 = new AttackTurnChoice(nullptr, nullptr, CreatureIndex(0, 0));
auto choice2 = new AttackTurnChoice(nullptr, &learnedAttack, CreatureIndex(0, 0));
auto vec = std::vector<BaseTurnChoice*>{choice1, choice2};
auto rand = Arbutils::Random();
TurnOrdering::OrderChoices(vec, rand);