Adds functionality for held items
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2022-02-19 12:19:03 +01:00
parent c40f063683
commit c078d91b0d
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
8 changed files with 108 additions and 44 deletions

View File

@ -4,7 +4,10 @@ using namespace CreatureLib::Library;
export Item* CreatureLib_Item_Construct(const char* name, ItemCategory category, BattleItemCategory battleCategory, export Item* CreatureLib_Item_Construct(const char* name, ItemCategory category, BattleItemCategory battleCategory,
int32_t price, const char* effectName, EffectParameter* effectParameters[], int32_t price, const char* effectName, EffectParameter* effectParameters[],
size_t effectParameterCount, const char* flags[], size_t flagsCount) { size_t effectParameterCount, const char* battleTriggerEffectName,
EffectParameter* battleTriggerEffectParameters[],
size_t battleTriggerEffectParameterCount, const char* flags[],
size_t flagsCount) {
std::unordered_set<uint32_t> conversedFlags(flagsCount); std::unordered_set<uint32_t> conversedFlags(flagsCount);
for (size_t i = 0; i < flagsCount; i++) { for (size_t i = 0; i < flagsCount; i++) {
conversedFlags.insert(ArbUt::StringView::CalculateHash(flags[i])); conversedFlags.insert(ArbUt::StringView::CalculateHash(flags[i]));
@ -14,6 +17,10 @@ export Item* CreatureLib_Item_Construct(const char* name, ItemCategory category,
ArbUt::StringView(name), category, battleCategory, price, ArbUt::StringView(name), category, battleCategory, price,
new SecondaryEffect(100, effectName, new SecondaryEffect(100, effectName,
ArbUt::List<EffectParameter*>(effectParameters, effectParameters + effectParameterCount)), ArbUt::List<EffectParameter*>(effectParameters, effectParameters + effectParameterCount)),
new SecondaryEffect(
100, battleTriggerEffectName,
ArbUt::List<EffectParameter*>(battleTriggerEffectParameters,
battleTriggerEffectParameters + battleTriggerEffectParameterCount)),
conversedFlags); conversedFlags);
}; };

View File

@ -17,15 +17,20 @@ namespace CreatureLib::Battling {
const Library::TalentIndex& talent, const std::vector<LearnedAttack*>& attacks, const Library::TalentIndex& talent, const std::vector<LearnedAttack*>& attacks,
bool allowedExperienceGain) bool allowedExperienceGain)
: _library(library), _species(species), _variant(variant), _level(level), _experience(experience), : _library(library), _species(species), _variant(variant), _level(level), _experience(experience),
_uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _heldItem(heldItem), _uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _weight(variant->GetWeight()),
_weight(variant->GetWeight()), _height(variant->GetHeight()), _nickname(std::move(nickname)), _height(variant->GetHeight()), _nickname(std::move(nickname)), _talentIndex(talent),
_talentIndex(talent), _hasOverridenTalent(false), _attacks(attacks), _hasOverridenTalent(false), _attacks(attacks), _allowedExperienceGain(allowedExperienceGain),
_allowedExperienceGain(allowedExperienceGain) { _heldItem(heldItem) {
_activeTalent = std::unique_ptr<BattleScript>( _activeTalent = std::unique_ptr<BattleScript>(
_library->LoadScript(this, ScriptCategory::Talent, GetActiveTalent()->GetEffect())); _library->LoadScript(this, ScriptCategory::Talent, GetActiveTalent()->GetEffect()));
if (_activeTalent != nullptr) { if (_activeTalent != nullptr) {
_activeTalent->OnInitialize(_library.GetRaw(), GetActiveTalent()->GetParameters()); _activeTalent->OnInitialize(_library.GetRaw(), GetActiveTalent()->GetParameters());
} }
if (_heldItem.HasValue() && _heldItem.GetValue()->GetBattleTriggerEffect().HasValue()) {
_heldItemTriggerScript = std::unique_ptr<BattleScript>(
_library->LoadScript(this, ScriptCategory::ItemBattleTrigger,
_heldItem.GetValue()->GetBattleTriggerEffect().GetValue()->GetEffectName()));
}
for (auto t : _variant->GetTypes()) { for (auto t : _variant->GetTypes()) {
_types.push_back(t); _types.push_back(t);
} }
@ -283,6 +288,7 @@ namespace CreatureLib::Battling {
} }
} }
void Creature::GetOwnScripts(ArbUt::List<ScriptWrapper>& scripts) { void Creature::GetOwnScripts(ArbUt::List<ScriptWrapper>& scripts) {
scripts.Append(ScriptWrapper::FromScript(&_heldItemTriggerScript));
scripts.Append(ScriptWrapper::FromScript(&_activeTalent)); scripts.Append(ScriptWrapper::FromScript(&_activeTalent));
scripts.Append(ScriptWrapper::FromScript(&_status)); scripts.Append(ScriptWrapper::FromScript(&_status));
scripts.Append(ScriptWrapper::FromSet(&_volatile)); scripts.Append(ScriptWrapper::FromSet(&_volatile));
@ -318,19 +324,54 @@ namespace CreatureLib::Battling {
return variant; return variant;
} }
void Creature::SetHeldItem(const ArbUt::BasicStringView& itemName) { void Creature::SetHeldItem(const ArbUt::BasicStringView& itemName) {
if (itemName == ""_cnc) {
_heldItem = {};
_heldItemTriggerScript = {};
} else {
auto v = _library->GetItemLibrary()->TryGet(itemName.GetHash()); auto v = _library->GetItemLibrary()->TryGet(itemName.GetHash());
if (!v.has_value()) { if (!v.has_value()) {
THROW("Item not found '", itemName.c_str(), "'."); THROW("Item not found '", itemName.c_str(), "'.");
} }
_heldItem = v.value(); _heldItem = v.value();
} }
}
void Creature::SetHeldItem(uint32_t itemNameHash) { void Creature::SetHeldItem(uint32_t itemNameHash) {
if (itemNameHash == ArbUt::StringView::CalculateHash("")) {
_heldItem = {};
_heldItemTriggerScript = {};
} else {
auto v = _library->GetItemLibrary()->TryGet(itemNameHash); auto v = _library->GetItemLibrary()->TryGet(itemNameHash);
if (!v.has_value()) { if (!v.has_value()) {
THROW("Item not found."); THROW("Item not found.");
} }
_heldItem = v.value(); _heldItem = v.value();
} }
}
bool Creature::ConsumeHeldItem() {
if (!_heldItem.HasValue()) {
return false;
}
auto* script = _library->GetScriptResolver()->LoadItemScript(_heldItem.GetValue());
auto isCreatureUseItem = script->IsCreatureUseItem();
if (isCreatureUseItem) {
if (!script->IsUseValidForCreature(this)) {
return false;
}
script->OnCreatureUse(this, true);
} else {
script->OnUse(_battleData.Battle.GetValue());
}
auto item = _heldItem;
SetHeldItem(""_cnc);
if (_battleData.Battle.HasValue()) {
HOOK(OnAfterHeldItemConsume, this, this, item.GetValue());
}
return true;
}
BattleScript* Creature::AddVolatileScript(const ArbUt::StringView& name) { BattleScript* Creature::AddVolatileScript(const ArbUt::StringView& name) {
auto script = _volatile.Get(name); auto script = _volatile.Get(name);
@ -421,19 +462,16 @@ namespace CreatureLib::Battling {
return c; return c;
} }
} void Creature::SetStatus(const ArbUt::StringView& name) {
void CreatureLib::Battling::Creature::SetStatus(const ArbUt::StringView& name) {
if (_status != nullptr) { if (_status != nullptr) {
_status->OnRemove(); _status->OnRemove();
} }
_status = _status = std::unique_ptr<BattleScript>(_library->LoadScript(this, ScriptCategory::Status, name));
std::unique_ptr<CreatureLib::Battling::BattleScript>(_library->LoadScript(this, ScriptCategory::Status, name));
if (_battleData.Battle.HasValue()) { if (_battleData.Battle.HasValue()) {
_battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, name); _battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, name);
} }
} }
void CreatureLib::Battling::Creature::ClearStatus() { void Creature::ClearStatus() {
if (_status == nullptr) { if (_status == nullptr) {
return; return;
} }
@ -444,8 +482,10 @@ void CreatureLib::Battling::Creature::ClearStatus() {
} }
} }
Battling::Creature::~Creature() { Creature::~Creature() {
if (_battleData.OnBattleField && _battleData.Side.HasValue()) { if (_battleData.OnBattleField && _battleData.Side.HasValue()) {
_battleData.Side.GetValue()->ForceClearCreature(_battleData.Index.GetCreatureIndex()); _battleData.Side.GetValue()->ForceClearCreature(_battleData.Index.GetCreatureIndex());
} }
} }
}

View File

@ -33,7 +33,7 @@ namespace CreatureLib::Battling {
uint32_t _uniqueIdentifier; uint32_t _uniqueIdentifier;
Library::Gender _gender; Library::Gender _gender;
uint8_t _coloring; uint8_t _coloring;
ArbUt::OptionalBorrowedPtr<const Library::Item> _heldItem;
uint32_t _currentHealth = -1; uint32_t _currentHealth = -1;
f32 _weight; f32 _weight;
@ -66,6 +66,9 @@ namespace CreatureLib::Battling {
std::vector<u8> _types = {}; std::vector<u8> _types = {};
ArbUt::OptionalBorrowedPtr<const Library::Item> _heldItem;
std::unique_ptr<BattleScript> _heldItemTriggerScript = nullptr;
private: private:
void OnFaint(DamageSource damageSource); void OnFaint(DamageSource damageSource);
@ -109,6 +112,7 @@ namespace CreatureLib::Battling {
void SetHeldItem(const ArbUt::BasicStringView& itemName); void SetHeldItem(const ArbUt::BasicStringView& itemName);
void SetHeldItem(uint32_t itemNameHash); void SetHeldItem(uint32_t itemNameHash);
inline void SetHeldItem(const ArbUt::BorrowedPtr<const Library::Item>& item) noexcept { _heldItem = item; }; inline void SetHeldItem(const ArbUt::BorrowedPtr<const Library::Item>& item) noexcept { _heldItem = item; };
bool ConsumeHeldItem();
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; } inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }

View File

@ -5,6 +5,7 @@
#include <Arbutils/Memory/Memory.hpp> #include <Arbutils/Memory/Memory.hpp>
#include <Arbutils/Misc.hpp> #include <Arbutils/Misc.hpp>
#include "../../Library/EffectParameter.hpp" #include "../../Library/EffectParameter.hpp"
#include "../../Library/Items/Item.hpp"
#include "../../Library/Statistic.hpp" #include "../../Library/Statistic.hpp"
#include "../Models/DamageSource.hpp" #include "../Models/DamageSource.hpp"
@ -117,6 +118,8 @@ namespace CreatureLib::Battling {
virtual void OnDamage(Creature*, DamageSource, _par_ u32 oldHealth, _par_ u32 newHealth){}; virtual void OnDamage(Creature*, DamageSource, _par_ u32 oldHealth, _par_ u32 newHealth){};
virtual void OnFaint(Creature*, DamageSource){}; virtual void OnFaint(Creature*, DamageSource){};
virtual void OnSwitchIn(Creature*){}; virtual void OnSwitchIn(Creature*){};
virtual void OnAfterHeldItemConsume(Creature*, const Library::Item*){};
}; };
} }

View File

@ -2,6 +2,6 @@
#define CREATURELIB_SCRIPTCATEGORY_HPP #define CREATURELIB_SCRIPTCATEGORY_HPP
#include <Arbutils/Enum.hpp> #include <Arbutils/Enum.hpp>
ENUM(ScriptCategory, uint8_t, Attack, Talent, Status, Creature, Battle, Side) ENUM(ScriptCategory, uint8_t, Attack, Talent, Status, Creature, Battle, Side, ItemBattleTrigger)
#endif // CREATURELIB_SCRIPTCATEGORY_HPP #endif // CREATURELIB_SCRIPTCATEGORY_HPP

View File

@ -1 +0,0 @@
#include "ScriptResolver.hpp"

View File

@ -8,26 +8,32 @@ namespace CreatureLib::Library {
int32_t _price; int32_t _price;
ArbUt::OptionalUniquePtr<const SecondaryEffect> _effect = nullptr; ArbUt::OptionalUniquePtr<const SecondaryEffect> _effect = nullptr;
ArbUt::OptionalUniquePtr<const SecondaryEffect> _battleTriggerEffect = nullptr;
std::unordered_set<uint32_t> _flags; std::unordered_set<uint32_t> _flags;
public: public:
inline impl(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, inline impl(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory,
int32_t price, const SecondaryEffect* effect, const std::unordered_set<uint32_t>& flags) noexcept int32_t price, const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect,
const std::unordered_set<uint32_t>& flags) noexcept
: _name(name), _category(category), _battleCategory(battleCategory), _price(price), _effect(effect), : _name(name), _category(category), _battleCategory(battleCategory), _price(price), _effect(effect),
_flags(flags) {} _battleTriggerEffect(battleTriggerEffect), _flags(flags) {}
inline const ArbUt::StringView& GetName() const noexcept { return _name; } inline const ArbUt::StringView& GetName() const noexcept { return _name; }
inline ItemCategory GetCategory() const noexcept { return _category; } inline ItemCategory GetCategory() const noexcept { return _category; }
inline BattleItemCategory GetBattleCategory() const noexcept { return _battleCategory; } inline BattleItemCategory GetBattleCategory() const noexcept { return _battleCategory; }
inline int32_t GetPrice() const noexcept { return _price; } inline int32_t GetPrice() const noexcept { return _price; }
inline const ArbUt::OptionalUniquePtr<const SecondaryEffect>& GetEffect() const noexcept { return _effect; } inline const ArbUt::OptionalUniquePtr<const SecondaryEffect>& GetEffect() const noexcept { return _effect; }
inline const ArbUt::OptionalUniquePtr<const SecondaryEffect>& GetBattleTriggerEffect() const noexcept {
return _battleTriggerEffect;
}
inline bool HasFlag(const ArbUt::BasicStringView& flag) const noexcept { return this->_flags.contains(flag); } inline bool HasFlag(const ArbUt::BasicStringView& flag) const noexcept { return this->_flags.contains(flag); }
inline bool HasFlag(uint32_t flag) const noexcept { return this->_flags.contains(flag); } inline bool HasFlag(uint32_t flag) const noexcept { return this->_flags.contains(flag); }
}; };
Item::Item(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, int32_t price, Item::Item(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, int32_t price,
const SecondaryEffect* effect, const std::unordered_set<uint32_t>& flags) noexcept const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect,
: _impl(new impl(name, category, battleCategory, price, effect, flags)) {} const std::unordered_set<uint32_t>& flags) noexcept
: _impl(new impl(name, category, battleCategory, price, effect, battleTriggerEffect, flags)) {}
Item::~Item() = default; Item::~Item() = default;
const ArbUt::StringView& Item::GetName() const noexcept { return _impl->GetName(); } const ArbUt::StringView& Item::GetName() const noexcept { return _impl->GetName(); }
@ -37,6 +43,9 @@ namespace CreatureLib::Library {
const ArbUt::OptionalUniquePtr<const SecondaryEffect>& Item::GetEffect() const noexcept { const ArbUt::OptionalUniquePtr<const SecondaryEffect>& Item::GetEffect() const noexcept {
return _impl->GetEffect(); return _impl->GetEffect();
} }
const ArbUt::OptionalUniquePtr<const SecondaryEffect>& Item::GetBattleTriggerEffect() const noexcept {
return _impl->GetBattleTriggerEffect();
}
bool Item::HasFlag(const ArbUt::BasicStringView& flag) const noexcept { return _impl->HasFlag(flag); } bool Item::HasFlag(const ArbUt::BasicStringView& flag) const noexcept { return _impl->HasFlag(flag); }
bool Item::HasFlag(uint32_t flag) const noexcept { return _impl->HasFlag(flag); } bool Item::HasFlag(uint32_t flag) const noexcept { return _impl->HasFlag(flag); }

View File

@ -16,7 +16,8 @@ namespace CreatureLib::Library {
public: public:
Item(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, int32_t price, Item(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, int32_t price,
const SecondaryEffect* effect, const std::unordered_set<uint32_t>& flags) noexcept; const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect,
const std::unordered_set<uint32_t>& flags) noexcept;
NO_COPY_OR_MOVE(Item) NO_COPY_OR_MOVE(Item)
virtual ~Item(); virtual ~Item();
@ -27,6 +28,7 @@ namespace CreatureLib::Library {
int32_t GetPrice() const noexcept; int32_t GetPrice() const noexcept;
const ArbUt::OptionalUniquePtr<const SecondaryEffect>& GetEffect() const noexcept; const ArbUt::OptionalUniquePtr<const SecondaryEffect>& GetEffect() const noexcept;
const ArbUt::OptionalUniquePtr<const SecondaryEffect>& GetBattleTriggerEffect() const noexcept;
bool HasFlag(const ArbUt::BasicStringView& flag) const noexcept; bool HasFlag(const ArbUt::BasicStringView& flag) const noexcept;
bool HasFlag(uint32_t flag) const noexcept; bool HasFlag(uint32_t flag) const noexcept;
}; };