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,
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);
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<EffectParameter*>(effectParameters, effectParameters + effectParameterCount)),
new SecondaryEffect(
100, battleTriggerEffectName,
ArbUt::List<EffectParameter*>(battleTriggerEffectParameters,
battleTriggerEffectParameters + battleTriggerEffectParameterCount)),
conversedFlags);
};

View File

@ -17,15 +17,20 @@ namespace CreatureLib::Battling {
const Library::TalentIndex& talent, const std::vector<LearnedAttack*>& 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<BattleScript>(
_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<BattleScript>(
_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<ScriptWrapper>& 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<BattleScript>(_library->LoadScript(this, ScriptCategory::Status, name));
if (_battleData.Battle.HasValue()) {
_battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, name);
}
}
void Creature::ClearStatus() {
if (_status == nullptr) {
return;
}
_status->OnRemove();
_status = nullptr;
if (_battleData.Battle.HasValue()) {
_battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, ""_cnc);
}
}
_status =
std::unique_ptr<CreatureLib::Battling::BattleScript>(_library->LoadScript(this, ScriptCategory::Status, name));
if (_battleData.Battle.HasValue()) {
_battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(this, name);
}
}
void CreatureLib::Battling::Creature::ClearStatus() {
if (_status == nullptr) {
return;
}
_status->OnRemove();
_status = nullptr;
if (_battleData.Battle.HasValue()) {
_battleData.Battle.GetValue()->TriggerEventListener<StatusChangeEvent>(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());
}
}
}

View File

@ -33,7 +33,7 @@ namespace CreatureLib::Battling {
uint32_t _uniqueIdentifier;
Library::Gender _gender;
uint8_t _coloring;
ArbUt::OptionalBorrowedPtr<const Library::Item> _heldItem;
uint32_t _currentHealth = -1;
f32 _weight;
@ -66,6 +66,9 @@ namespace CreatureLib::Battling {
std::vector<u8> _types = {};
ArbUt::OptionalBorrowedPtr<const Library::Item> _heldItem;
std::unique_ptr<BattleScript> _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<const Library::Item>& item) noexcept { _heldItem = item; };
bool ConsumeHeldItem();
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }

View File

@ -5,6 +5,7 @@
#include <Arbutils/Memory/Memory.hpp>
#include <Arbutils/Misc.hpp>
#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*){};
};
}

View File

@ -2,6 +2,6 @@
#define CREATURELIB_SCRIPTCATEGORY_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

View File

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

View File

@ -8,26 +8,32 @@ namespace CreatureLib::Library {
int32_t _price;
ArbUt::OptionalUniquePtr<const SecondaryEffect> _effect = nullptr;
ArbUt::OptionalUniquePtr<const SecondaryEffect> _battleTriggerEffect = nullptr;
std::unordered_set<uint32_t> _flags;
public:
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),
_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<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(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<uint32_t>& flags) noexcept
: _impl(new impl(name, category, battleCategory, price, effect, flags)) {}
const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect,
const std::unordered_set<uint32_t>& 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<const SecondaryEffect>& Item::GetEffect() const noexcept {
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(uint32_t flag) const noexcept { return _impl->HasFlag(flag); }

View File

@ -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<uint32_t>& flags) noexcept;
const SecondaryEffect* effect, const SecondaryEffect* battleTriggerEffect,
const std::unordered_set<uint32_t>& flags) noexcept;
NO_COPY_OR_MOVE(Item)
virtual ~Item();
@ -27,6 +28,7 @@ namespace CreatureLib::Library {
int32_t GetPrice() 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(uint32_t flag) const noexcept;
};