#ifndef CREATURELIB_BATTLECREATURE_HPP #define CREATURELIB_BATTLECREATURE_HPP #include #include #include #include "../../Library/ClampedStatisticSet.hpp" #include "../../Library/CreatureData/CreatureSpecies.hpp" #include "../../Library/Items/Item.hpp" #include "../ScriptHandling/ScriptAggregator.hpp" #include "../ScriptHandling/ScriptSet.hpp" #include "../ScriptHandling/ScriptSource.hpp" #include "DamageSource.hpp" #include "LearnedAttack.hpp" namespace CreatureLib::Battling { // Forward declare battle class class Battle; class BattleSide; class BattleLibrary; class Creature : public ScriptSource { protected: const BattleLibrary* _library; ArbUt::BorrowedPtr _species; ArbUt::BorrowedPtr _variant; ArbUt::BorrowedPtr _displaySpecies = nullptr; ArbUt::BorrowedPtr _displayVariant = nullptr; uint8_t _level; uint32_t _experience; uint32_t _uniqueIdentifier; Library::Gender _gender; uint8_t _coloring; ArbUt::BorrowedPtr _heldItem; uint32_t _currentHealth; Library::ClampedStatisticSet _statBoost; Library::StatisticSet _flatStats; Library::StatisticSet _boostedStats; ArbUt::BorrowedPtr _battle = nullptr; BattleSide* _side = nullptr; bool _onBattleField = false; std::string _nickname = ""; CreatureLib::Library::TalentIndex _talentIndex; Script* _activeTalent = nullptr; bool _hasOverridenTalent; ArbUt::CaseInsensitiveConstString _overridenTalentName = ""_cnc; std::unordered_set _seenOpponents = {}; ArbUt::UniquePtrList _attacks; bool _allowedExperienceGain; Script* _status = nullptr; ScriptSet _volatile = {}; private: void OnFaint(); public: Creature(const BattleLibrary* library, const ArbUt::BorrowedPtr& species, const ArbUt::BorrowedPtr& variant, uint8_t level, uint32_t experience, uint32_t uid, Library::Gender gender, uint8_t coloring, const ArbUt::BorrowedPtr heldItem, std::string nickname, const Library::TalentIndex& talent, const std::vector& attacks, bool allowedExperienceGain = true); virtual ~Creature() { delete _activeTalent; delete _status; }; virtual void Initialize() { RecalculateFlatStats(); _currentHealth = GetBoostedStat(Library::Statistic::Health); } inline const ArbUt::BorrowedPtr& GetSpecies() const noexcept { return _species; } inline const ArbUt::BorrowedPtr& 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 ArbUt::CaseInsensitiveConstString& name) const noexcept { return _heldItem != nullptr && _heldItem->GetName() == name; } inline bool HasHeldItem(uint32_t nameHash) const noexcept { return _heldItem != nullptr && _heldItem->GetName() == nameHash; } inline const ArbUt::BorrowedPtr& GetHeldItem() const noexcept { return _heldItem; } void SetHeldItem(const ArbUt::CaseInsensitiveConstString& itemName); void SetHeldItem(uint32_t itemNameHash); inline void SetHeldItem(const ArbUt::BorrowedPtr& item) noexcept { _heldItem = item; }; inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; } void SetBattleData(ArbUt::BorrowedPtr battle, BattleSide* side); const ArbUt::BorrowedPtr& GetBattle() const; BattleSide* GetBattleSide() const; void SetOnBattleField(bool value) { _onBattleField = value; } bool IsOnBattleField() const { return _onBattleField; } const std::string& GetNickname() const noexcept { return _nickname; } const ArbUt::CaseInsensitiveConstString& GetActiveTalent() const; [[nodiscard]] bool IsFainted() const noexcept; [[nodiscard]] const ArbUt::List& GetTypes() const noexcept; [[nodiscard]] bool HasType(uint8_t type) const noexcept; 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); void OverrideActiveTalent(const ArbUt::CaseInsensitiveConstString& talent); void AddExperience(uint32_t amount); void MarkOpponentAsSeen(Creature* creature) { _seenOpponents.insert(creature); } const std::unordered_set& GetSeenOpponents() const { return _seenOpponents; } size_t ScriptCount() const override; void GetActiveScripts(ArbUt::List& scripts) override; void ClearVolatileScripts(); void AddVolatileScript(const ArbUt::CaseInsensitiveConstString& name); void AddVolatileScript(Script* script); void RemoveVolatileScript(const ArbUt::CaseInsensitiveConstString& name); void RemoveVolatileScript(Script* script); bool HasVolatileScript(const ArbUt::CaseInsensitiveConstString& name) const; const ArbUt::UniquePtrList& GetAttacks() noexcept { return _attacks; } ArbUt::BorrowedPtr GetDisplaySpecies() const noexcept; ArbUt::BorrowedPtr GetDisplayVariant() const noexcept; void SetDisplaySpecies(const ArbUt::BorrowedPtr& species) noexcept { _displaySpecies = species; } void SetDisplayVariant(const Library::SpeciesVariant* variant) noexcept { _displayVariant = variant; }; inline bool AllowedExperienceGain() const noexcept { return _allowedExperienceGain; } inline void SetAllowedExperienceGain(bool allowed) noexcept { _allowedExperienceGain = allowed; } // region Stat APIs bool ChangeStatBoost(Library::Statistic stat, int8_t diffAmount); [[nodiscard]] inline uint32_t GetFlatStat(Library::Statistic stat) const { return _flatStats.GetStat(stat); } [[nodiscard]] inline uint32_t GetBoostedStat(Library::Statistic stat) const { return _boostedStats.GetStat(stat); } [[nodiscard]] inline uint32_t GetBaseStat(Library::Statistic stat) const { return _variant->GetStatistic(stat); } [[nodiscard]] inline int8_t GetStatBoost(Library::Statistic stat) const { return _statBoost.GetStat(stat); } void RecalculateFlatStats(); void RecalculateBoostedStats(); void RecalculateFlatStat(Library::Statistic); void RecalculateBoostedStat(Library::Statistic); // endregion }; } #endif // CREATURELIB_CREATURE_HPP