#include "SpeciesVariant.hpp" namespace CreatureLib::Library { struct SpeciesVariant::impl { private: ArbUt::StringView _name; float _height; float _weight; uint32_t _baseExperience; ArbUt::List _types; Library::StatisticSet _baseStatistics; ArbUt::List> _talents; ArbUt::List> _secretTalents; std::unique_ptr _attacks; std::unordered_set _flags; public: impl(const ArbUt::StringView& name, float height, float weight, uint32_t baseExperience, ArbUt::List types, Library::StatisticSet baseStats, ArbUt::List> talents, ArbUt::List> secretTalents, const LearnableAttacks* attacks, std::unordered_set flags) : _name(name), _height(height), _weight(weight), _baseExperience(baseExperience), _types(std::move((types))), _baseStatistics(baseStats), _talents(std::move(talents)), _secretTalents(std::move(secretTalents)), _attacks(attacks), _flags(std::move(flags)){}; inline const ArbUt::StringView& GetName() const { return _name; } inline float GetHeight() const { return _height; } inline float GetWeight() const { return _weight; } inline uint32_t GetBaseExperience() const { return _baseExperience; } [[nodiscard]] inline size_t GetTypeCount() const { return _types.Count(); } [[nodiscard]] inline uint8_t GetType(size_t index) const { return _types[index]; } [[nodiscard]] inline const ArbUt::List& GetTypes() const { return _types; } [[nodiscard]] inline uint16_t GetStatistic(Library::Statistic stat) const { return _baseStatistics.GetStat(stat); } [[nodiscard]] inline size_t GetTalentCount() const noexcept { return _talents.Count(); } [[nodiscard]] inline size_t GetSecretTalentCount() const noexcept { return _secretTalents.Count(); } [[nodiscard]] const ArbUt::BorrowedPtr& GetTalent(const TalentIndex& index) const { if (index.IsSecret() && _secretTalents.Count() > 0) { auto usedIndex = index.GetIndex(); if (usedIndex >= _secretTalents.Count()) { usedIndex = _secretTalents.Count() - 1; } return _secretTalents.At(usedIndex); } auto usedIndex = index.GetIndex(); if (usedIndex >= _talents.Count()) { usedIndex = _talents.Count() - 1; } return _talents.At(usedIndex); } [[nodiscard]] TalentIndex GetTalentIndex(const ArbUt::BorrowedPtr& talent) const { for (size_t i = 0; i < _talents.Count(); i++) { if (_talents.At(i) == talent) { return TalentIndex(false, i); } } for (size_t i = 0; i < _secretTalents.Count(); i++) { if (_secretTalents.At(i) == talent) { return TalentIndex(true, i); } } THROW("The given talent is not a valid talent for this creature."); } [[nodiscard]] TalentIndex GetTalentIndex(const ArbUt::StringView& talentName) const { for (size_t i = 0; i < _talents.Count(); i++) { if (_talents.At(i)->GetName() == talentName) { return TalentIndex(false, i); } } for (size_t i = 0; i < _secretTalents.Count(); i++) { if (_secretTalents.At(i)->GetName() == talentName) { return TalentIndex(true, i); } } THROW("The given talent name is not a valid talent for this creature."); } [[nodiscard]] inline ArbUt::BorrowedPtr GetLearnableAttacks() const { return _attacks; } [[nodiscard]] inline TalentIndex GetRandomTalent(ArbUt::Random& rand) const noexcept { return TalentIndex(false, rand.Get(_talents.Count())); } [[nodiscard]] inline const ArbUt::List>& GetTalents() const { return _talents; } [[nodiscard]] inline const ArbUt::List>& GetSecretTalents() const { return _secretTalents; } inline bool HasFlag(const ArbUt::StringView& key) const noexcept { return this->_flags.find(key) != this->_flags.end(); } inline bool HasFlag(uint32_t keyHash) const noexcept { return this->_flags.find(keyHash) != this->_flags.end(); } }; SpeciesVariant::SpeciesVariant(const ArbUt::StringView& name, float height, float weight, uint32_t baseExperience, const ArbUt::List& types, StatisticSet baseStats, const ArbUt::List>& talents, const ArbUt::List>& secretTalents, const LearnableAttacks* attacks, const std::unordered_set& flags) : _impl(new impl(name, height, weight, baseExperience, types, baseStats, talents, secretTalents, attacks, flags)) {} SpeciesVariant::~SpeciesVariant() = default; #define ImplGetter(type, func) \ type SpeciesVariant::func() const noexcept { return _impl->func(); } ImplGetter(const ArbUt::StringView&, GetName); ImplGetter(float, GetHeight); ImplGetter(float, GetWeight); ImplGetter(uint32_t, GetBaseExperience); ImplGetter(size_t, GetTypeCount); uint8_t SpeciesVariant::GetType(size_t index) const { return _impl->GetType(index); } ImplGetter(const ArbUt::List&, GetTypes); uint16_t SpeciesVariant::GetStatistic(Library::Statistic stat) const noexcept { return _impl->GetStatistic(stat); } ImplGetter(size_t, GetTalentCount); ImplGetter(size_t, GetSecretTalentCount); const ArbUt::BorrowedPtr& SpeciesVariant::GetTalent(const TalentIndex& index) const { return _impl->GetTalent(index); } TalentIndex SpeciesVariant::GetTalentIndex(const ArbUt::BorrowedPtr& talent) const { return _impl->GetTalentIndex(talent); } TalentIndex SpeciesVariant::GetTalentIndex(const ArbUt::StringView& talentName) const { return _impl->GetTalentIndex(talentName); } ImplGetter(ArbUt::BorrowedPtr, GetLearnableAttacks); TalentIndex SpeciesVariant::GetRandomTalent(ArbUt::Random& rand) const noexcept { return _impl->GetRandomTalent(rand); } ImplGetter(const ArbUt::List>&, GetTalents); ImplGetter(const ArbUt::List>&, GetSecretTalents); bool SpeciesVariant::HasFlag(const ArbUt::StringView& key) const noexcept { return _impl->HasFlag(key); } bool SpeciesVariant::HasFlag(uint32_t keyHash) const noexcept { return _impl->HasFlag(keyHash); } }