From 899e4322710171d5c2f52a1ea3723bc6b37b86ca Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 22 Mar 2020 13:42:26 +0100 Subject: [PATCH] Added lots of security using asserts. --- .clang-format | 2 ++ src/Battling/EventHooks/EventHook.cpp | 1 - src/Battling/EventHooks/EventHook.hpp | 1 + src/Battling/Flow/ChoiceQueue.cpp | 2 ++ src/Battling/Flow/TurnHandler.cpp | 7 ++-- src/Battling/Flow/TurnHandler.hpp | 2 +- src/Battling/Library/BattleLibrary.cpp | 1 - src/Battling/Library/BattleStatCalculator.cpp | 3 ++ src/Battling/Library/DamageLibrary.cpp | 11 +++++++ src/Battling/Library/ExperienceLibrary.cpp | 2 ++ src/Battling/Library/MiscLibrary.cpp | 3 ++ src/Battling/Models/Battle.cpp | 11 ++++--- src/Battling/Models/Battle.hpp | 6 ++++ src/Battling/Models/BattleParty.hpp | 6 ++-- src/Battling/Models/BattleSide.cpp | 5 +++ src/Battling/Models/BattleSide.hpp | 7 ++-- src/Battling/Models/Creature.cpp | 9 ++++-- src/Battling/Models/Creature.hpp | 32 +++++++++---------- src/Battling/Models/ExecutingAttack.hpp | 3 ++ src/Battling/Models/LearnedAttack.cpp | 6 ++-- src/Battling/ScriptHandling/ScriptWrapper.cpp | 1 - src/Battling/TurnChoices/AttackTurnChoice.hpp | 1 + src/Battling/TurnChoices/BaseTurnChoice.hpp | 1 + src/Battling/TurnChoices/SwitchTurnChoice.hpp | 4 ++- src/Library/BaseLibrary.hpp | 15 ++++----- src/Library/CreatureData/CreatureSpecies.cpp | 5 ++- src/Library/CreatureData/LearnableAttacks.hpp | 8 ++++- src/Library/CreatureData/SpeciesVariant.cpp | 2 +- src/Library/CreatureData/SpeciesVariant.hpp | 4 +-- src/Library/DataLibrary.cpp | 9 +++++- src/Library/GrowthRates/ExternGrowthRate.hpp | 6 +++- src/Library/GrowthRates/LookupGrowthRate.hpp | 5 ++- src/Library/StatisticSet.hpp | 3 ++ src/Library/TypeLibrary.cpp | 6 +++- tests/BattleTests/TurnOrderTests.cpp | 4 ++- 35 files changed, 138 insertions(+), 56 deletions(-) delete mode 100644 src/Battling/EventHooks/EventHook.cpp delete mode 100644 src/Battling/ScriptHandling/ScriptWrapper.cpp diff --git a/.clang-format b/.clang-format index 2c6fbf1..965124f 100644 --- a/.clang-format +++ b/.clang-format @@ -116,6 +116,8 @@ Standard: Cpp11 StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION + - Assert + - AssertNotNull TabWidth: 8 UseTab: Never ... diff --git a/src/Battling/EventHooks/EventHook.cpp b/src/Battling/EventHooks/EventHook.cpp deleted file mode 100644 index a2fe121..0000000 --- a/src/Battling/EventHooks/EventHook.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "EventHook.hpp" diff --git a/src/Battling/EventHooks/EventHook.hpp b/src/Battling/EventHooks/EventHook.hpp index 6e0d940..e8a1b0b 100644 --- a/src/Battling/EventHooks/EventHook.hpp +++ b/src/Battling/EventHooks/EventHook.hpp @@ -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); } diff --git a/src/Battling/Flow/ChoiceQueue.cpp b/src/Battling/Flow/ChoiceQueue.cpp index 2024d48..6813f04 100644 --- a/src/Battling/Flow/ChoiceQueue.cpp +++ b/src/Battling/Flow/ChoiceQueue.cpp @@ -1,6 +1,8 @@ #include "ChoiceQueue.hpp" +#include 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++) { diff --git a/src/Battling/Flow/TurnHandler.cpp b/src/Battling/Flow/TurnHandler.cpp index 9667656..e4af64c 100644 --- a/src/Battling/Flow/TurnHandler.cpp +++ b/src/Battling/Flow/TurnHandler.cpp @@ -1,11 +1,12 @@ #include "TurnHandler.hpp" +#include #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()) { diff --git a/src/Battling/Flow/TurnHandler.hpp b/src/Battling/Flow/TurnHandler.hpp index 868ad8e..dc97454 100644 --- a/src/Battling/Flow/TurnHandler.hpp +++ b/src/Battling/Flow/TurnHandler.hpp @@ -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); }; } diff --git a/src/Battling/Library/BattleLibrary.cpp b/src/Battling/Library/BattleLibrary.cpp index c819e7d..0cb0104 100644 --- a/src/Battling/Library/BattleLibrary.cpp +++ b/src/Battling/Library/BattleLibrary.cpp @@ -1,5 +1,4 @@ #include "BattleLibrary.hpp" -#include using namespace CreatureLib::Battling; diff --git a/src/Battling/Library/BattleStatCalculator.cpp b/src/Battling/Library/BattleStatCalculator.cpp index d9334b3..175384c 100644 --- a/src/Battling/Library/BattleStatCalculator.cpp +++ b/src/Battling/Library/BattleStatCalculator.cpp @@ -1,4 +1,5 @@ #include "BattleStatCalculator.hpp" +#include #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; diff --git a/src/Battling/Library/DamageLibrary.cpp b/src/Battling/Library/DamageLibrary.cpp index fc5cb4f..7a01c5b 100644 --- a/src/Battling/Library/DamageLibrary.cpp +++ b/src/Battling/Library/DamageLibrary.cpp @@ -1,8 +1,11 @@ #include "DamageLibrary.hpp" +#include #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(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; diff --git a/src/Battling/Library/ExperienceLibrary.cpp b/src/Battling/Library/ExperienceLibrary.cpp index 03d1b3e..4dec0ea 100644 --- a/src/Battling/Library/ExperienceLibrary.cpp +++ b/src/Battling/Library/ExperienceLibrary.cpp @@ -4,6 +4,8 @@ void CreatureLib::Battling::ExperienceLibrary::HandleExperienceGain( CreatureLib::Battling::Creature* faintedMon, const std::unordered_set& opponents) const { for (auto opponent : opponents) { + if (opponent == nullptr) + continue; auto levelDiff = faintedMon->GetLevel() - opponent->GetLevel() + 10; if (levelDiff <= 0) continue; diff --git a/src/Battling/Library/MiscLibrary.cpp b/src/Battling/Library/MiscLibrary.cpp index 39f0605..3bfff5c 100644 --- a/src/Battling/Library/MiscLibrary.cpp +++ b/src/Battling/Library/MiscLibrary.cpp @@ -1,9 +1,11 @@ #include "MiscLibrary.hpp" +#include #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; diff --git a/src/Battling/Models/Battle.cpp b/src/Battling/Models/Battle.cpp index df507a9..ed006d1 100644 --- a/src/Battling/Models/Battle.cpp +++ b/src/Battling/Models/Battle.cpp @@ -1,4 +1,5 @@ #include "Battle.hpp" +#include #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(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((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& 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); } diff --git a/src/Battling/Models/Battle.hpp b/src/Battling/Models/Battle.hpp index 296179b..20092c6 100644 --- a/src/Battling/Models/Battle.hpp +++ b/src/Battling/Models/Battle.hpp @@ -1,6 +1,7 @@ #ifndef CREATURELIB_BATTLE_HPP #define CREATURELIB_BATTLE_HPP +#include #include #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(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); } diff --git a/src/Battling/Models/BattleParty.hpp b/src/Battling/Models/BattleParty.hpp index 143e12e..f072360 100644 --- a/src/Battling/Models/BattleParty.hpp +++ b/src/Battling/Models/BattleParty.hpp @@ -1,9 +1,9 @@ #ifndef CREATURELIB_BATTLEPARTY_HPP #define CREATURELIB_BATTLEPARTY_HPP +#include #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 responsibleIndices) - : _party(party), _responsibleIndices(responsibleIndices) {} + : _party(party), _responsibleIndices(responsibleIndices) { + AssertNotNull(_party) + } inline CreatureParty* GetParty() const { return _party; } inline const std::vector& GetResponsibleIndices() const { return _responsibleIndices; } diff --git a/src/Battling/Models/BattleSide.cpp b/src/Battling/Models/BattleSide.cpp index f7c415e..d2d2f86 100644 --- a/src/Battling/Models/BattleSide.cpp +++ b/src/Battling/Models/BattleSide.cpp @@ -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& 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& scripts) { } uint8_t BattleSide::GetRandomCreatureIndex() { // TODO: Consider adding parameter to only get index for available creatures. + AssertNotNull(_battle) return _battle->GetRandom()->Get(_creaturesPerSide); } diff --git a/src/Battling/Models/BattleSide.hpp b/src/Battling/Models/BattleSide.hpp index 2dada24..428b604 100644 --- a/src/Battling/Models/BattleSide.hpp +++ b/src/Battling/Models/BattleSide.hpp @@ -1,6 +1,7 @@ #ifndef CREATURELIB_BATTLESIDE_HPP #define CREATURELIB_BATTLESIDE_HPP +#include #include #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(creaturesPerSide); - _choices = std::vector(creaturesPerSide); - _fillableSlots = std::vector(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; diff --git a/src/Battling/Models/Creature.cpp b/src/Battling/Models/Creature.cpp index edd5599..80af431 100644 --- a/src/Battling/Models/Creature.cpp +++ b/src/Battling/Models/Creature.cpp @@ -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& Battling::Creature::GetTypes() const { +const std::vector& 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(); } diff --git a/src/Battling/Models/Creature.hpp b/src/Battling/Models/Creature.hpp index beaf3c8..db53bbb 100644 --- a/src/Battling/Models/Creature.hpp +++ b/src/Battling/Models/Creature.hpp @@ -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& GetTypes() const; - [[nodiscard]] bool HasType(uint8_t type) const; + [[nodiscard]] bool IsFainted() const noexcept; + [[nodiscard]] const std::vector& 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); diff --git a/src/Battling/Models/ExecutingAttack.hpp b/src/Battling/Models/ExecutingAttack.hpp index e83f0eb..70eef51 100644 --- a/src/Battling/Models/ExecutingAttack.hpp +++ b/src/Battling/Models/ExecutingAttack.hpp @@ -1,6 +1,7 @@ #ifndef CREATURELIB_EXECUTINGATTACK_HPP #define CREATURELIB_EXECUTINGATTACK_HPP +#include #include #include #include @@ -61,6 +62,8 @@ namespace CreatureLib::Battling { ExecutingAttack(const std::vector& 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)}); diff --git a/src/Battling/Models/LearnedAttack.cpp b/src/Battling/Models/LearnedAttack.cpp index ab97e49..1a3cdac 100644 --- a/src/Battling/Models/LearnedAttack.cpp +++ b/src/Battling/Models/LearnedAttack.cpp @@ -1,8 +1,10 @@ #include "LearnedAttack.hpp" - +#include 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) diff --git a/src/Battling/ScriptHandling/ScriptWrapper.cpp b/src/Battling/ScriptHandling/ScriptWrapper.cpp deleted file mode 100644 index 73f8d65..0000000 --- a/src/Battling/ScriptHandling/ScriptWrapper.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "ScriptWrapper.hpp" diff --git a/src/Battling/TurnChoices/AttackTurnChoice.hpp b/src/Battling/TurnChoices/AttackTurnChoice.hpp index 127d521..964f4da 100644 --- a/src/Battling/TurnChoices/AttackTurnChoice.hpp +++ b/src/Battling/TurnChoices/AttackTurnChoice.hpp @@ -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) diff --git a/src/Battling/TurnChoices/BaseTurnChoice.hpp b/src/Battling/TurnChoices/BaseTurnChoice.hpp index d29f968..347ced5 100644 --- a/src/Battling/TurnChoices/BaseTurnChoice.hpp +++ b/src/Battling/TurnChoices/BaseTurnChoice.hpp @@ -1,6 +1,7 @@ #ifndef CREATURELIB_BASETURNCHOICE_HPP #define CREATURELIB_BASETURNCHOICE_HPP +#include #include "../ScriptHandling/ScriptSource.hpp" #include "TurnChoiceKind.hpp" diff --git a/src/Battling/TurnChoices/SwitchTurnChoice.hpp b/src/Battling/TurnChoices/SwitchTurnChoice.hpp index c154558..90b931a 100644 --- a/src/Battling/TurnChoices/SwitchTurnChoice.hpp +++ b/src/Battling/TurnChoices/SwitchTurnChoice.hpp @@ -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; } diff --git a/src/Library/BaseLibrary.hpp b/src/Library/BaseLibrary.hpp index e5a36fd..951ab73 100644 --- a/src/Library/BaseLibrary.hpp +++ b/src/Library/BaseLibrary.hpp @@ -1,6 +1,7 @@ #ifndef CREATURELIB_BASELIBRARY_HPP #define CREATURELIB_BASELIBRARY_HPP +#include #include #include #include @@ -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); diff --git a/src/Library/CreatureData/CreatureSpecies.cpp b/src/Library/CreatureData/CreatureSpecies.cpp index c517b17..e2d3ec5 100644 --- a/src/Library/CreatureData/CreatureSpecies.cpp +++ b/src/Library/CreatureData/CreatureSpecies.cpp @@ -1,11 +1,14 @@ #include "CreatureSpecies.hpp" +#include 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(); } diff --git a/src/Library/CreatureData/LearnableAttacks.hpp b/src/Library/CreatureData/LearnableAttacks.hpp index b7364a4..b242b22 100644 --- a/src/Library/CreatureData/LearnableAttacks.hpp +++ b/src/Library/CreatureData/LearnableAttacks.hpp @@ -1,6 +1,7 @@ #ifndef CREATURELIB_LEARNABLEATTACKS_HPP #define CREATURELIB_LEARNABLEATTACKS_HPP +#include #include #include #include "../Attacks/AttackData.hpp" @@ -11,7 +12,12 @@ namespace CreatureLib::Library { public: LearnableAttacks(size_t levelAttackCapacity) - : _learnedByLevel(std::unordered_map>(levelAttackCapacity)) {} + : _learnedByLevel(std::unordered_map>(levelAttackCapacity)) { + for (auto kv : _learnedByLevel) { + for (auto attack : kv.second) + AssertNotNull(attack) + } + } void AddLevelMove(uint8_t level, const AttackData* attack); diff --git a/src/Library/CreatureData/SpeciesVariant.cpp b/src/Library/CreatureData/SpeciesVariant.cpp index 9abe62a..24bd6d9 100644 --- a/src/Library/CreatureData/SpeciesVariant.cpp +++ b/src/Library/CreatureData/SpeciesVariant.cpp @@ -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 types, - CreatureLib::Library::StatisticSet baseStats, + const CreatureLib::Library::StatisticSet& baseStats, std::vector talents, std::vector secretTalents, const LearnableAttacks* attacks) diff --git a/src/Library/CreatureData/SpeciesVariant.hpp b/src/Library/CreatureData/SpeciesVariant.hpp index 0e99672..71c421b 100644 --- a/src/Library/CreatureData/SpeciesVariant.hpp +++ b/src/Library/CreatureData/SpeciesVariant.hpp @@ -23,14 +23,14 @@ namespace CreatureLib::Library { private: std::vector _types; - const Library::StatisticSet _baseStatistics; + const Library::StatisticSet& _baseStatistics; std::vector _talents; std::vector _secretTalents; const LearnableAttacks* _attacks; public: SpeciesVariant(ConstString name, float height, float weight, uint32_t baseExperience, - std::vector types, Library::StatisticSet baseStats, + std::vector types, const Library::StatisticSet& baseStats, std::vector talents, std::vector secretTalents, const LearnableAttacks* attacks); diff --git a/src/Library/DataLibrary.cpp b/src/Library/DataLibrary.cpp index 96af82c..1958060 100644 --- a/src/Library/DataLibrary.cpp +++ b/src/Library/DataLibrary.cpp @@ -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; diff --git a/src/Library/GrowthRates/ExternGrowthRate.hpp b/src/Library/GrowthRates/ExternGrowthRate.hpp index fd534ae..2c8c076 100644 --- a/src/Library/GrowthRates/ExternGrowthRate.hpp +++ b/src/Library/GrowthRates/ExternGrowthRate.hpp @@ -1,6 +1,7 @@ #ifndef CREATURELIB_EXTERNGROWTHRATE_HPP #define CREATURELIB_EXTERNGROWTHRATE_HPP +#include #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); } diff --git a/src/Library/GrowthRates/LookupGrowthRate.hpp b/src/Library/GrowthRates/LookupGrowthRate.hpp index 53b626c..caf38d2 100644 --- a/src/Library/GrowthRates/LookupGrowthRate.hpp +++ b/src/Library/GrowthRates/LookupGrowthRate.hpp @@ -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]; + } }; } diff --git a/src/Library/StatisticSet.hpp b/src/Library/StatisticSet.hpp index 74e048f..b160cfd 100644 --- a/src/Library/StatisticSet.hpp +++ b/src/Library/StatisticSet.hpp @@ -15,6 +15,9 @@ namespace CreatureLib::Library { T _magicalDefense; T _speed; + private: + StatisticSet(const StatisticSet& v) = delete; + public: StatisticSet(T health, T physicalAttack, T physicalDefense, T magicalAttack, T magicalDefense, T speed) : _health(health), _physicalAttack(physicalAttack), _physicalDefense(physicalDefense), diff --git a/src/Library/TypeLibrary.cpp b/src/Library/TypeLibrary.cpp index e2f17d2..07d08bb 100644 --- a/src/Library/TypeLibrary.cpp +++ b/src/Library/TypeLibrary.cpp @@ -1,5 +1,5 @@ #include "TypeLibrary.hpp" -#include +#include using namespace CreatureLib::Library; @@ -12,6 +12,8 @@ float TypeLibrary::GetEffectiveness(uint8_t attacking, const std::vectorGetAttackLibrary()->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{choice1, choice2}; auto rand = Arbutils::Random(); TurnOrdering::OrderChoices(vec, rand);