#include "CreatureSpecies.hpp" using namespace CreatureLib::Library; struct CreatureSpecies::impl { const ArbUt::StringView _name; uint16_t _id; float _genderRate; const ArbUt::StringView _growthRate; uint8_t _captureRate; ArbUt::Dictionary> _variantsLookup; ArbUt::List> _variantsList; std::unordered_set _flags; impl(uint16_t id, const ArbUt::StringView& name, const SpeciesVariant* defaultVariant, float genderRatio, const ArbUt::StringView& growthRate, uint8_t captureRate, std::unordered_set flags) : _name(name), _id(id), _genderRate(genderRatio), _growthRate(growthRate), _captureRate(captureRate), _variantsLookup(1), _variantsList(1), _flags(std::move(flags)) { EnsureNotNull(defaultVariant) SetVariant("default"_cnc, defaultVariant); } ~impl() { _variantsLookup.Clear(); } inline uint16_t GetId() const noexcept { return _id; } inline float GetGenderRate() const noexcept { return _genderRate; } inline const ArbUt::StringView& GetGrowthRate() const noexcept { return _growthRate; } inline uint8_t GetCaptureRate() const noexcept { return _captureRate; } [[nodiscard]] inline bool HasVariant(const ArbUt::BasicStringView& key) const noexcept { return _variantsLookup.Has(key); } [[nodiscard]] inline bool HasVariant(uint32_t hash) const noexcept { return _variantsLookup.Has(hash); } [[nodiscard]] inline std::optional> TryGetVariant(const ArbUt::BasicStringView& name) const noexcept { return TryGetVariant(name.GetHash()); } [[nodiscard]] std::optional> TryGetVariant(uint32_t hash) const noexcept { auto find = _variantsLookup.GetStdMap().find(hash); if (find == _variantsLookup.end()) return {}; return std::get<1>(*find).GetRaw(); } [[nodiscard]] inline ArbUt::BorrowedPtr GetVariant(const ArbUt::BasicStringView& key) const { return _variantsLookup.Get(key).GetRaw(); } [[nodiscard]] inline ArbUt::BorrowedPtr GetVariant(uint32_t key) const { return _variantsLookup.Get(key).GetRaw(); } [[nodiscard]] Gender GetRandomGender(ArbUt::Random& rand) const noexcept { if (this->_genderRate == -1) { return Gender::Genderless; } auto val = rand.GetDouble(); if (val >= this->_genderRate) return Gender ::Female; return Gender ::Male; } [[nodiscard]] inline const ArbUt::StringView& GetName() const noexcept { return _name; } void SetVariant(const ArbUt::StringView& name, const SpeciesVariant* variant) { Ensure(!name.IsEmpty()) _variantsList.CreateBack(variant); _variantsLookup.GetStdMap().emplace(name, variant); } inline const ArbUt::List>& GetVariantsIterator() const { return _variantsList; } 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(); } }; CreatureSpecies::CreatureSpecies(uint16_t id, const ArbUt::StringView& name, const SpeciesVariant* defaultVariant, float genderRatio, const ArbUt::StringView& growthRate, uint8_t captureRate, std::unordered_set flags) : _impl(new impl(id, name, defaultVariant, genderRatio, growthRate, captureRate, flags)) {} #define ImplGetter(type, func) \ type CreatureSpecies::func() const noexcept { return _impl->func(); } CreatureSpecies::~CreatureSpecies() = default; ImplGetter(uint16_t, GetId); ImplGetter(float, GetGenderRate); ImplGetter(const ArbUt::StringView&, GetGrowthRate); ImplGetter(uint8_t, GetCaptureRate); ImplGetter(const ArbUt::StringView&, GetName); bool CreatureSpecies::HasVariant(const ArbUt::BasicStringView& key) const noexcept { return _impl->HasVariant(key); } bool CreatureSpecies::HasVariant(uint32_t hash) const noexcept { return _impl->HasVariant(hash); } std::optional> CreatureSpecies::TryGetVariant(const ArbUt::BasicStringView& name) const noexcept { return _impl->TryGetVariant(name); } std::optional> CreatureSpecies::TryGetVariant(uint32_t hash) const noexcept { return _impl->TryGetVariant(hash); } ArbUt::BorrowedPtr CreatureSpecies::GetVariant(const ArbUt::BasicStringView& key) const { return _impl->GetVariant(key); } ArbUt::BorrowedPtr CreatureSpecies::GetVariant(uint32_t key) const { return _impl->GetVariant(key); } Gender CreatureSpecies::GetRandomGender(ArbUt::Random& rand) const noexcept { return _impl->GetRandomGender(rand); } void CreatureSpecies::SetVariant(const ArbUt::StringView& name, const SpeciesVariant* variant) { _impl->SetVariant(name, variant); } const ArbUt::List>& CreatureSpecies::GetVariantsIterator() const { return _impl->GetVariantsIterator(); } bool CreatureSpecies::HasFlag(const ArbUt::StringView& key) const noexcept { return _impl->HasFlag(key); } bool CreatureSpecies::HasFlag(uint32_t keyHash) const noexcept { return _impl->HasFlag(keyHash); }