239 lines
11 KiB
C++
239 lines
11 KiB
C++
#ifndef CREATURELIB_BATTLECREATURE_HPP
|
|
#define CREATURELIB_BATTLECREATURE_HPP
|
|
|
|
#include "../../Defines.hpp"
|
|
#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 "CreatureIndex.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:
|
|
ArbUt::BorrowedPtr<const BattleLibrary> _library;
|
|
|
|
ArbUt::BorrowedPtr<const Library::CreatureSpecies> _species;
|
|
ArbUt::BorrowedPtr<const Library::SpeciesVariant> _variant;
|
|
|
|
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> _displaySpecies = nullptr;
|
|
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> _displayVariant = nullptr;
|
|
|
|
level_int_t _level;
|
|
u32 _experience;
|
|
u32 _uniqueIdentifier;
|
|
Library::Gender _gender;
|
|
u8 _coloring;
|
|
|
|
u32 _currentHealth = -1;
|
|
|
|
f32 _weight;
|
|
f32 _height;
|
|
|
|
Library::ClampedStatisticSet<i8, -6, 6> _statBoost;
|
|
Library::StatisticSet<u32> _flatStats;
|
|
Library::StatisticSet<u32> _boostedStats;
|
|
|
|
struct BattleData {
|
|
bool OnBattleField = false;
|
|
ArbUt::OptionalBorrowedPtr<Battle> Battle = nullptr;
|
|
ArbUt::OptionalBorrowedPtr<BattleSide> Side = nullptr;
|
|
CreatureIndex Index = {};
|
|
std::unordered_set<ArbUt::BorrowedPtr<Creature>> SeenOpponents;
|
|
} _battleData = {};
|
|
|
|
std::optional<std::string> _nickname = {};
|
|
CreatureLib::Library::TalentIndex _talentIndex = {};
|
|
std::unique_ptr<BattleScript> _activeTalent = {};
|
|
|
|
bool _hasOverridenTalent = false;
|
|
ArbUt::OptionalBorrowedPtr<const Library::Talent> _overridenTalent = {};
|
|
|
|
ArbUt::OptionalUniquePtrList<LearnedAttack> _attacks = {};
|
|
bool _allowedExperienceGain = {};
|
|
|
|
std::unique_ptr<BattleScript> _status = nullptr;
|
|
ScriptSet _volatile = {};
|
|
|
|
std::vector<u8> _types = {};
|
|
|
|
ArbUt::OptionalBorrowedPtr<const Library::Item> _heldItem;
|
|
std::unique_ptr<BattleScript> _heldItemTriggerScript = nullptr;
|
|
|
|
private:
|
|
void OnFaint(DamageSource damageSource);
|
|
|
|
public:
|
|
Creature(const ArbUt::BorrowedPtr<const BattleLibrary>& library,
|
|
const ArbUt::BorrowedPtr<const Library::CreatureSpecies>& species,
|
|
const ArbUt::BorrowedPtr<const Library::SpeciesVariant>& variant, level_int_t level, u32 experience,
|
|
u32 uid, Library::Gender gender, u8 coloring, ArbUt::OptionalBorrowedPtr<const Library::Item> heldItem,
|
|
std::optional<std::string> nickname, const Library::TalentIndex& talent,
|
|
const std::vector<LearnedAttack*>& attacks, bool allowedExperienceGain = true);
|
|
|
|
virtual ~Creature();
|
|
|
|
virtual void Initialize() {
|
|
RecalculateFlatStats();
|
|
_currentHealth = GetBoostedStat(Library::Statistic::Health);
|
|
}
|
|
|
|
inline const ArbUt::BorrowedPtr<const BattleLibrary>& GetLibrary() const noexcept { return _library; }
|
|
inline const ArbUt::BorrowedPtr<const Library::CreatureSpecies>& GetSpecies() const noexcept {
|
|
return _species;
|
|
}
|
|
inline const ArbUt::BorrowedPtr<const Library::SpeciesVariant>& GetVariant() const noexcept { return _variant; }
|
|
virtual void ChangeSpecies(const ArbUt::BorrowedPtr<const Library::CreatureSpecies>& species,
|
|
const ArbUt::BorrowedPtr<const Library::SpeciesVariant>& variant);
|
|
virtual void ChangeVariant(const ArbUt::StringView& variantName);
|
|
virtual void ChangeVariant(const ArbUt::BorrowedPtr<const Library::SpeciesVariant>& variant);
|
|
inline level_int_t GetLevel() const noexcept { return _level; }
|
|
inline u32 GetExperience() const noexcept { return _experience; }
|
|
inline u32 GetUniqueIdentifier() const noexcept { return _uniqueIdentifier; }
|
|
inline Library::Gender GetGender() const noexcept { return _gender; }
|
|
inline u8 GetColoring() const noexcept { return _coloring; }
|
|
inline bool HasHeldItem(const ArbUt::BasicStringView& name) const noexcept {
|
|
return _heldItem.HasValue() && _heldItem.GetValue()->GetName() == name;
|
|
}
|
|
inline bool HasHeldItem(u32 nameHash) const noexcept {
|
|
return _heldItem.HasValue() && _heldItem.GetValue()->GetName() == nameHash;
|
|
}
|
|
inline const ArbUt::OptionalBorrowedPtr<const Library::Item>& GetHeldItem() const noexcept { return _heldItem; }
|
|
void SetHeldItem(const ArbUt::BasicStringView& itemName);
|
|
void SetHeldItem(u32 itemNameHash);
|
|
inline void SetHeldItem(const ArbUt::BorrowedPtr<const Library::Item>& item) noexcept { _heldItem = item; };
|
|
bool ConsumeHeldItem();
|
|
|
|
inline u32 GetCurrentHealth() const noexcept { return _currentHealth; }
|
|
|
|
inline f32 GetWeight() const noexcept { return _weight; }
|
|
inline void SetWeight(f32 weight) noexcept {
|
|
if (weight < 0.1f) {
|
|
weight = 0.1f;
|
|
}
|
|
_weight = weight;
|
|
}
|
|
|
|
inline f32 GetHeight() const noexcept { return _height; }
|
|
inline void SetHeight(f32 height) noexcept {
|
|
if (height < 0.1f) {
|
|
height = 0.1f;
|
|
}
|
|
_height = height;
|
|
}
|
|
|
|
void SetBattleData(const ArbUt::BorrowedPtr<Battle>& battle, const ArbUt::BorrowedPtr<BattleSide>& side);
|
|
void ClearBattleData() noexcept;
|
|
inline const ArbUt::OptionalBorrowedPtr<Battle>& GetBattle() const { return _battleData.Battle; }
|
|
inline const ArbUt::OptionalBorrowedPtr<BattleSide>& GetBattleSide() const { return _battleData.Side; }
|
|
void SetOnBattleField(bool value);
|
|
inline void SetBattleIndex(const CreatureIndex& index) { _battleData.Index = index; }
|
|
inline const CreatureIndex& GetBattleIndex() const noexcept { return _battleData.Index; }
|
|
inline bool IsOnBattleField() const { return _battleData.OnBattleField; }
|
|
|
|
inline std::optional<std::string_view> GetNickname() const noexcept {
|
|
if (_nickname.has_value()) {
|
|
return _nickname.value();
|
|
}
|
|
return {};
|
|
}
|
|
inline void SetNickname(std::string nickname) noexcept { _nickname = nickname; }
|
|
const CreatureLib::Library::TalentIndex& GetRealTalent() const noexcept { return _talentIndex; }
|
|
ArbUt::BorrowedPtr<const Library::Talent> GetActiveTalent() const;
|
|
|
|
/// Are we allowed to use this creature in a battle?
|
|
[[nodiscard]] virtual bool IsUsable() const noexcept;
|
|
[[nodiscard]] bool IsFainted() const noexcept;
|
|
[[nodiscard]] const std::vector<u8>& GetTypes() const noexcept;
|
|
[[nodiscard]] bool HasType(u8 type) const noexcept;
|
|
void SetType(u8 index, u8 type) noexcept;
|
|
|
|
u32 GetMaxHealth() const noexcept { return _boostedStats.GetHealth(); }
|
|
void ChangeLevelBy(i8 amount);
|
|
void Damage(u32 damage, DamageSource source);
|
|
void Heal(u32 amount, bool canRevive = false);
|
|
void RestoreAllAttackUses() noexcept;
|
|
void OverrideActiveTalent(const ArbUt::StringView& talent);
|
|
void AddExperience(u32 amount);
|
|
|
|
void MarkOpponentAsSeen(ArbUt::BorrowedPtr<Creature> creature) { _battleData.SeenOpponents.insert(creature); }
|
|
const std::unordered_set<ArbUt::BorrowedPtr<Creature>>& GetSeenOpponents() const {
|
|
return _battleData.SeenOpponents;
|
|
}
|
|
|
|
size_t ScriptCount() const override;
|
|
void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override;
|
|
void GetOwnScripts(ArbUt::List<ScriptWrapper>& scripts) override;
|
|
void ClearVolatileScripts();
|
|
BattleScript* AddVolatileScript(const ArbUt::StringView& name);
|
|
BattleScript* AddVolatileScript(BattleScript* script);
|
|
void RemoveVolatileScript(const ArbUt::BasicStringView& name);
|
|
void RemoveVolatileScript(BattleScript* script);
|
|
bool HasVolatileScript(const ArbUt::BasicStringView& name) const;
|
|
|
|
const ArbUt::OptionalUniquePtrList<LearnedAttack>& GetAttacks() noexcept { return _attacks; }
|
|
bool HasAttack(const ArbUt::StringView& name) {
|
|
for (auto& a : _attacks) {
|
|
if (a == nullptr)
|
|
continue;
|
|
if (a->GetAttack()->GetName() == name)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> GetDisplaySpecies() const noexcept;
|
|
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> GetDisplayVariant() const noexcept;
|
|
|
|
void SetDisplaySpecies(const ArbUt::BorrowedPtr<const Library::CreatureSpecies>& species) noexcept {
|
|
_displaySpecies = species.GetRaw();
|
|
}
|
|
void SetDisplayVariant(ArbUt::BorrowedPtr<const Library::SpeciesVariant> variant) noexcept {
|
|
_displayVariant = variant.GetRaw();
|
|
};
|
|
|
|
inline bool AllowedExperienceGain() const noexcept { return _allowedExperienceGain; }
|
|
inline void SetAllowedExperienceGain(bool allowed) noexcept { _allowedExperienceGain = allowed; }
|
|
|
|
u8 GetAvailableAttackSlot() const noexcept;
|
|
void AddAttack(LearnedAttack* attack);
|
|
void ReplaceAttack(size_t index, LearnedAttack* attack);
|
|
void SwapAttacks(size_t a, size_t b) { _attacks.Swap(a, b); }
|
|
|
|
void SetStatus(const ArbUt::StringView& name);
|
|
void ClearStatus();
|
|
const ArbUt::StringView& GetStatusName() const noexcept {
|
|
if (_status == nullptr)
|
|
return ArbUt::StringView::EmptyString();
|
|
return _status->GetName();
|
|
}
|
|
|
|
// region Stat APIs
|
|
|
|
bool ChangeStatBoost(Library::Statistic stat, i8 diffAmount, bool selfInflicted = false);
|
|
[[nodiscard]] inline u32 GetFlatStat(Library::Statistic stat) const { return _flatStats.GetStat(stat); }
|
|
[[nodiscard]] inline u32 GetBoostedStat(Library::Statistic stat) const { return _boostedStats.GetStat(stat); }
|
|
[[nodiscard]] inline u32 GetBaseStat(Library::Statistic stat) const { return _variant->GetStatistic(stat); }
|
|
[[nodiscard]] inline i8 GetStatBoost(Library::Statistic stat) const { return _statBoost.GetStat(stat); }
|
|
void RecalculateFlatStats();
|
|
void RecalculateBoostedStats();
|
|
void RecalculateFlatStat(Library::Statistic);
|
|
void RecalculateBoostedStat(Library::Statistic);
|
|
|
|
// endregion
|
|
|
|
virtual Creature* Clone() const;
|
|
};
|
|
}
|
|
|
|
#endif // CREATURELIB_CREATURE_HPP
|