diff --git a/CInterface/Library/Item.cpp b/CInterface/Library/Item.cpp index 3f32e93..0c0732e 100644 --- a/CInterface/Library/Item.cpp +++ b/CInterface/Library/Item.cpp @@ -4,7 +4,10 @@ using namespace CreatureLib::Library; export Item* CreatureLib_Item_Construct(const char* name, ItemCategory category, BattleItemCategory battleCategory, 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 conversedFlags(flagsCount); for (size_t i = 0; i < flagsCount; 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, new SecondaryEffect(100, effectName, ArbUt::List(effectParameters, effectParameters + effectParameterCount)), + new SecondaryEffect( + 100, battleTriggerEffectName, + ArbUt::List(battleTriggerEffectParameters, + battleTriggerEffectParameters + battleTriggerEffectParameterCount)), conversedFlags); }; diff --git a/src/Battling/Models/Creature.cpp b/src/Battling/Models/Creature.cpp index 828057b..8ca3944 100644 --- a/src/Battling/Models/Creature.cpp +++ b/src/Battling/Models/Creature.cpp @@ -17,15 +17,20 @@ namespace CreatureLib::Battling { const Library::TalentIndex& talent, const std::vector& attacks, bool allowedExperienceGain) : _library(library), _species(species), _variant(variant), _level(level), _experience(experience), - _uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _heldItem(heldItem), - _weight(variant->GetWeight()), _height(variant->GetHeight()), _nickname(std::move(nickname)), - _talentIndex(talent), _hasOverridenTalent(false), _attacks(attacks), - _allowedExperienceGain(allowedExperienceGain) { + _uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _weight(variant->GetWeight()), + _height(variant->GetHeight()), _nickname(std::move(nickname)), _talentIndex(talent), + _hasOverridenTalent(false), _attacks(attacks), _allowedExperienceGain(allowedExperienceGain), + _heldItem(heldItem) { _activeTalent = std::unique_ptr( _library->LoadScript(this, ScriptCategory::Talent, GetActiveTalent()->GetEffect())); if (_activeTalent != nullptr) { _activeTalent->OnInitialize(_library.GetRaw(), GetActiveTalent()->GetParameters()); } + if (_heldItem.HasValue() && _heldItem.GetValue()->GetBattleTriggerEffect().HasValue()) { + _heldItemTriggerScript = std::unique_ptr( + _library->LoadScript(this, ScriptCategory::ItemBattleTrigger, + _heldItem.GetValue()->GetBattleTriggerEffect().GetValue()->GetEffectName())); + } for (auto t : _variant->GetTypes()) { _types.push_back(t); } @@ -283,6 +288,7 @@ namespace CreatureLib::Battling { } } void Creature::GetOwnScripts(ArbUt::List& scripts) { + scripts.Append(ScriptWrapper::FromScript(&_heldItemTriggerScript)); scripts.Append(ScriptWrapper::FromScript(&_activeTalent)); scripts.Append(ScriptWrapper::FromScript(&_status)); scripts.Append(ScriptWrapper::FromSet(&_volatile)); @@ -318,18 +324,53 @@ namespace CreatureLib::Battling { return variant; } void Creature::SetHeldItem(const ArbUt::BasicStringView& itemName) { - auto v = _library->GetItemLibrary()->TryGet(itemName.GetHash()); - if (!v.has_value()) { - THROW("Item not found '", itemName.c_str(), "'."); + if (itemName == ""_cnc) { + _heldItem = {}; + _heldItemTriggerScript = {}; + } else { + auto v = _library->GetItemLibrary()->TryGet(itemName.GetHash()); + if (!v.has_value()) { + THROW("Item not found '", itemName.c_str(), "'."); + } + _heldItem = v.value(); } - _heldItem = v.value(); } void Creature::SetHeldItem(uint32_t itemNameHash) { - auto v = _library->GetItemLibrary()->TryGet(itemNameHash); - if (!v.has_value()) { - THROW("Item not found."); + if (itemNameHash == ArbUt::StringView::CalculateHash("")) { + _heldItem = {}; + _heldItemTriggerScript = {}; + } else { + auto v = _library->GetItemLibrary()->TryGet(itemNameHash); + if (!v.has_value()) { + 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) { @@ -421,31 +462,30 @@ namespace CreatureLib::Battling { return c; } -} - -void CreatureLib::Battling::Creature::SetStatus(const ArbUt::StringView& name) { - if (_status != nullptr) { + void Creature::SetStatus(const ArbUt::StringView& name) { + if (_status != nullptr) { + _status->OnRemove(); + } + _status = std::unique_ptr(_library->LoadScript(this, ScriptCategory::Status, name)); + if (_battleData.Battle.HasValue()) { + _battleData.Battle.GetValue()->TriggerEventListener(this, name); + } + } + void Creature::ClearStatus() { + if (_status == nullptr) { + return; + } _status->OnRemove(); + _status = nullptr; + if (_battleData.Battle.HasValue()) { + _battleData.Battle.GetValue()->TriggerEventListener(this, ""_cnc); + } } - _status = - std::unique_ptr(_library->LoadScript(this, ScriptCategory::Status, name)); - if (_battleData.Battle.HasValue()) { - _battleData.Battle.GetValue()->TriggerEventListener(this, name); - } -} -void CreatureLib::Battling::Creature::ClearStatus() { - if (_status == nullptr) { - return; - } - _status->OnRemove(); - _status = nullptr; - if (_battleData.Battle.HasValue()) { - _battleData.Battle.GetValue()->TriggerEventListener(this, ""_cnc); - } -} -Battling::Creature::~Creature() { - if (_battleData.OnBattleField && _battleData.Side.HasValue()) { - _battleData.Side.GetValue()->ForceClearCreature(_battleData.Index.GetCreatureIndex()); + Creature::~Creature() { + if (_battleData.OnBattleField && _battleData.Side.HasValue()) { + _battleData.Side.GetValue()->ForceClearCreature(_battleData.Index.GetCreatureIndex()); + } } + } diff --git a/src/Battling/Models/Creature.hpp b/src/Battling/Models/Creature.hpp index 77f7877..e0960c2 100644 --- a/src/Battling/Models/Creature.hpp +++ b/src/Battling/Models/Creature.hpp @@ -33,7 +33,7 @@ namespace CreatureLib::Battling { uint32_t _uniqueIdentifier; Library::Gender _gender; uint8_t _coloring; - ArbUt::OptionalBorrowedPtr _heldItem; + uint32_t _currentHealth = -1; f32 _weight; @@ -66,6 +66,9 @@ namespace CreatureLib::Battling { std::vector _types = {}; + ArbUt::OptionalBorrowedPtr _heldItem; + std::unique_ptr _heldItemTriggerScript = nullptr; + private: void OnFaint(DamageSource damageSource); @@ -109,6 +112,7 @@ namespace CreatureLib::Battling { void SetHeldItem(const ArbUt::BasicStringView& itemName); void SetHeldItem(uint32_t itemNameHash); inline void SetHeldItem(const ArbUt::BorrowedPtr& item) noexcept { _heldItem = item; }; + bool ConsumeHeldItem(); inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; } diff --git a/src/Battling/ScriptHandling/BattleScript.hpp b/src/Battling/ScriptHandling/BattleScript.hpp index 56f95ac..b940fa1 100644 --- a/src/Battling/ScriptHandling/BattleScript.hpp +++ b/src/Battling/ScriptHandling/BattleScript.hpp @@ -5,6 +5,7 @@ #include #include #include "../../Library/EffectParameter.hpp" +#include "../../Library/Items/Item.hpp" #include "../../Library/Statistic.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 OnFaint(Creature*, DamageSource){}; virtual void OnSwitchIn(Creature*){}; + + virtual void OnAfterHeldItemConsume(Creature*, const Library::Item*){}; }; } diff --git a/src/Battling/ScriptHandling/ScriptCategory.hpp b/src/Battling/ScriptHandling/ScriptCategory.hpp index 5360db3..6a8491d 100644 --- a/src/Battling/ScriptHandling/ScriptCategory.hpp +++ b/src/Battling/ScriptHandling/ScriptCategory.hpp @@ -2,6 +2,6 @@ #define CREATURELIB_SCRIPTCATEGORY_HPP #include -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 diff --git a/src/Battling/ScriptHandling/ScriptResolver.cpp b/src/Battling/ScriptHandling/ScriptResolver.cpp deleted file mode 100644 index af0d96b..0000000 --- a/src/Battling/ScriptHandling/ScriptResolver.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "ScriptResolver.hpp" diff --git a/src/Library/Items/Item.cpp b/src/Library/Items/Item.cpp index 5f36675..7fe7605 100644 --- a/src/Library/Items/Item.cpp +++ b/src/Library/Items/Item.cpp @@ -8,26 +8,32 @@ namespace CreatureLib::Library { int32_t _price; ArbUt::OptionalUniquePtr _effect = nullptr; + ArbUt::OptionalUniquePtr _battleTriggerEffect = nullptr; std::unordered_set _flags; public: inline impl(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, - int32_t price, const SecondaryEffect* effect, const std::unordered_set& flags) noexcept + int32_t price, const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect, + const std::unordered_set& flags) noexcept : _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 ItemCategory GetCategory() const noexcept { return _category; } inline BattleItemCategory GetBattleCategory() const noexcept { return _battleCategory; } inline int32_t GetPrice() const noexcept { return _price; } inline const ArbUt::OptionalUniquePtr& GetEffect() const noexcept { return _effect; } + inline const ArbUt::OptionalUniquePtr& GetBattleTriggerEffect() const noexcept { + return _battleTriggerEffect; + } 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); } }; Item::Item(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, int32_t price, - const SecondaryEffect* effect, const std::unordered_set& flags) noexcept - : _impl(new impl(name, category, battleCategory, price, effect, flags)) {} + const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect, + const std::unordered_set& flags) noexcept + : _impl(new impl(name, category, battleCategory, price, effect, battleTriggerEffect, flags)) {} Item::~Item() = default; const ArbUt::StringView& Item::GetName() const noexcept { return _impl->GetName(); } @@ -37,6 +43,9 @@ namespace CreatureLib::Library { const ArbUt::OptionalUniquePtr& Item::GetEffect() const noexcept { return _impl->GetEffect(); } + const ArbUt::OptionalUniquePtr& Item::GetBattleTriggerEffect() const noexcept { + return _impl->GetBattleTriggerEffect(); + } 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); } diff --git a/src/Library/Items/Item.hpp b/src/Library/Items/Item.hpp index aa5c029..a8ef5f6 100644 --- a/src/Library/Items/Item.hpp +++ b/src/Library/Items/Item.hpp @@ -16,7 +16,8 @@ namespace CreatureLib::Library { public: Item(const ArbUt::StringView& name, ItemCategory category, BattleItemCategory battleCategory, int32_t price, - const SecondaryEffect* effect, const std::unordered_set& flags) noexcept; + const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect, + const std::unordered_set& flags) noexcept; NO_COPY_OR_MOVE(Item) virtual ~Item(); @@ -27,6 +28,7 @@ namespace CreatureLib::Library { int32_t GetPrice() const noexcept; const ArbUt::OptionalUniquePtr& GetEffect() const noexcept; + const ArbUt::OptionalUniquePtr& GetBattleTriggerEffect() const noexcept; bool HasFlag(const ArbUt::BasicStringView& flag) const noexcept; bool HasFlag(uint32_t flag) const noexcept; };