Reworks attack scripts to handle effect chance and effect name through data files.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
e2675d06fb
commit
340520e0e3
|
@ -5,11 +5,13 @@ using namespace CreatureLib::Library;
|
||||||
export uint8_t CreatureLib_AttackData_Construct(AttackData*& out, const char* name, uint8_t type,
|
export uint8_t CreatureLib_AttackData_Construct(AttackData*& out, const char* name, uint8_t type,
|
||||||
AttackCategory category, uint8_t power, uint8_t accuracy,
|
AttackCategory category, uint8_t power, uint8_t accuracy,
|
||||||
uint8_t baseUsage, AttackTarget target, int8_t priority,
|
uint8_t baseUsage, AttackTarget target, int8_t priority,
|
||||||
const char* flags[], size_t flagsCount) {
|
int8_t effectChance, const char* effectName, const char* flags[],
|
||||||
Try(std::unordered_set<uint32_t> conversedFlags(flagsCount);
|
size_t flagsCount) {
|
||||||
for (size_t i = 0; i < flagsCount; i++) { conversedFlags.insert(ConstString::GetHash(flags[i])); }
|
Try(std::unordered_set<uint32_t> conversedFlags(flagsCount); for (size_t i = 0; i < flagsCount; i++) {
|
||||||
|
conversedFlags.insert(ConstString::GetHash(flags[i]));
|
||||||
|
} auto effect = SecondaryEffect(effectChance, Arbutils::CaseInsensitiveConstString(effectName));
|
||||||
|
|
||||||
out = new AttackData(ConstString(name), type, category, power, accuracy, baseUsage, target, priority,
|
out = new AttackData(ConstString(name), type, category, power, accuracy, baseUsage, target, priority, effect,
|
||||||
conversedFlags);)
|
conversedFlags);)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -154,7 +154,9 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, Creature* targe
|
||||||
hit->SetDamage(dmgLibrary->GetDamage(attack, target, hitIndex));
|
hit->SetDamage(dmgLibrary->GetDamage(attack, target, hitIndex));
|
||||||
|
|
||||||
if (attackData->GetCategory() == Library::AttackCategory::Status) {
|
if (attackData->GetCategory() == Library::AttackCategory::Status) {
|
||||||
HOOK(OnStatusMove, userSource, attack, target, hitIndex);
|
if (attackData->HasSecondaryEffect()) {
|
||||||
|
HOOK(OnStatusMove, userSource, attack, target, hitIndex);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
auto damage = hit->GetDamage();
|
auto damage = hit->GetDamage();
|
||||||
if (damage > target->GetCurrentHealth()) {
|
if (damage > target->GetCurrentHealth()) {
|
||||||
|
@ -164,10 +166,22 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, Creature* targe
|
||||||
if (damage > 0) {
|
if (damage > 0) {
|
||||||
target->Damage(damage, DamageSource::AttackDamage);
|
target->Damage(damage, DamageSource::AttackDamage);
|
||||||
|
|
||||||
bool preventSecondary = false;
|
if (attackData->HasSecondaryEffect()) {
|
||||||
HOOK(PreventSecondaryEffects, targetSource, attack, target, hitIndex, &preventSecondary);
|
bool preventSecondary = false;
|
||||||
if (!preventSecondary) {
|
HOOK(PreventSecondaryEffects, targetSource, attack, target, hitIndex, &preventSecondary);
|
||||||
HOOK(OnSecondaryEffect, userSource, attack, target, hitIndex);
|
if (!preventSecondary) {
|
||||||
|
auto effect = attackData->GetSecondaryEffect();
|
||||||
|
bool hasSecondaryEffect;
|
||||||
|
if (effect.GetChance() == -1) {
|
||||||
|
hasSecondaryEffect = true;
|
||||||
|
} else {
|
||||||
|
hasSecondaryEffect =
|
||||||
|
user->GetBattle()->GetRandom()->EffectChance(effect.GetChance(), attack, target);
|
||||||
|
}
|
||||||
|
if (hasSecondaryEffect) {
|
||||||
|
HOOK(OnSecondaryEffect, userSource, attack, target, hitIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ static CreatureLib::Library::AttackData* _replacementAttackData = nullptr;
|
||||||
|
|
||||||
static CreatureLib::Library::AttackData* GetReplacementAttackData() {
|
static CreatureLib::Library::AttackData* GetReplacementAttackData() {
|
||||||
if (_replacementAttackData == nullptr) {
|
if (_replacementAttackData == nullptr) {
|
||||||
_replacementAttackData =
|
_replacementAttackData = new CreatureLib::Library::AttackData(
|
||||||
new CreatureLib::Library::AttackData("replacement"_cnc, 0, CreatureLib::Library::AttackCategory::Physical,
|
"replacement"_cnc, 0, CreatureLib::Library::AttackCategory::Physical, 30, 255, 255,
|
||||||
30, 255, 255, CreatureLib::Library::AttackTarget::Any, 0, {});
|
CreatureLib::Library::AttackTarget::Any, 0, CreatureLib::Library::SecondaryEffect(), {});
|
||||||
}
|
}
|
||||||
return _replacementAttackData;
|
return _replacementAttackData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,11 @@ namespace CreatureLib::Battling {
|
||||||
return;
|
return;
|
||||||
auto battle = user->GetBattle();
|
auto battle = user->GetBattle();
|
||||||
if (battle != nullptr) {
|
if (battle != nullptr) {
|
||||||
auto library = battle->GetLibrary();
|
if (_attack->GetAttack()->HasSecondaryEffect()) {
|
||||||
_attackScript = library->LoadScript(ScriptCategory::Attack, _attack->GetAttack()->GetName());
|
auto library = battle->GetLibrary();
|
||||||
|
_attackScript = library->LoadScript(ScriptCategory::Attack,
|
||||||
|
_attack->GetAttack()->GetSecondaryEffect().GetEffectName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ CreatureLib::Library::AttackData::AttackData(const ConstString& name, uint8_t ty
|
||||||
CreatureLib::Library::AttackCategory category, uint8_t power,
|
CreatureLib::Library::AttackCategory category, uint8_t power,
|
||||||
uint8_t accuracy, uint8_t baseUsage,
|
uint8_t accuracy, uint8_t baseUsage,
|
||||||
CreatureLib::Library::AttackTarget target, int8_t priority,
|
CreatureLib::Library::AttackTarget target, int8_t priority,
|
||||||
std::unordered_set<uint32_t> flags)
|
SecondaryEffect effect, std::unordered_set<uint32_t> flags)
|
||||||
: _name(std::move(name)), _type(type), _category(category), _basePower(power), _accuracy(accuracy),
|
: _name(std::move(name)), _type(type), _category(category), _basePower(power), _accuracy(accuracy),
|
||||||
_baseUsages(baseUsage), _target(target), _priority(priority), _flags(std::move(flags)) {}
|
_baseUsages(baseUsage), _target(target), _priority(priority), _effect(effect), _flags(std::move(flags)) {}
|
||||||
|
|
||||||
bool CreatureLib::Library::AttackData::HasFlag(const ConstString& key) const noexcept {
|
bool CreatureLib::Library::AttackData::HasFlag(const ConstString& key) const noexcept {
|
||||||
return this->_flags.find(key) != this->_flags.end();
|
return this->_flags.find(key) != this->_flags.end();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include "AttackCategory.hpp"
|
#include "AttackCategory.hpp"
|
||||||
#include "AttackTarget.hpp"
|
#include "AttackTarget.hpp"
|
||||||
|
#include "SecondaryEffect.hpp"
|
||||||
|
|
||||||
using ConstString = Arbutils::CaseInsensitiveConstString;
|
using ConstString = Arbutils::CaseInsensitiveConstString;
|
||||||
|
|
||||||
|
@ -20,11 +21,13 @@ namespace CreatureLib::Library {
|
||||||
uint8_t _baseUsages;
|
uint8_t _baseUsages;
|
||||||
AttackTarget _target;
|
AttackTarget _target;
|
||||||
int8_t _priority;
|
int8_t _priority;
|
||||||
|
SecondaryEffect _effect;
|
||||||
std::unordered_set<uint32_t> _flags;
|
std::unordered_set<uint32_t> _flags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AttackData(const ConstString& name, uint8_t type, AttackCategory category, uint8_t power, uint8_t accuracy,
|
AttackData(const ConstString& name, uint8_t type, AttackCategory category, uint8_t power, uint8_t accuracy,
|
||||||
uint8_t baseUsage, AttackTarget target, int8_t priority, std::unordered_set<uint32_t> flags);
|
uint8_t baseUsage, AttackTarget target, int8_t priority, SecondaryEffect effect,
|
||||||
|
std::unordered_set<uint32_t> flags);
|
||||||
virtual ~AttackData() = default;
|
virtual ~AttackData() = default;
|
||||||
|
|
||||||
inline const ConstString& GetName() const noexcept { return _name; }
|
inline const ConstString& GetName() const noexcept { return _name; }
|
||||||
|
@ -35,6 +38,10 @@ namespace CreatureLib::Library {
|
||||||
inline uint8_t GetBaseUsages() const noexcept { return _baseUsages; }
|
inline uint8_t GetBaseUsages() const noexcept { return _baseUsages; }
|
||||||
inline AttackTarget GetTarget() const noexcept { return _target; }
|
inline AttackTarget GetTarget() const noexcept { return _target; }
|
||||||
inline int8_t GetPriority() const noexcept { return _priority; }
|
inline int8_t GetPriority() const noexcept { return _priority; }
|
||||||
|
inline bool HasSecondaryEffect() const noexcept {
|
||||||
|
return _effect.GetChance() != 0 && _effect.GetEffectName() != ""_cnc;
|
||||||
|
}
|
||||||
|
inline const SecondaryEffect& GetSecondaryEffect() const noexcept { return _effect; }
|
||||||
|
|
||||||
bool HasFlag(const ConstString& key) const noexcept;
|
bool HasFlag(const ConstString& key) const noexcept;
|
||||||
bool HasFlag(uint32_t keyHash) const noexcept;
|
bool HasFlag(uint32_t keyHash) const noexcept;
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef CREATURELIB_SECONDARYEFFECT_HPP
|
||||||
|
#define CREATURELIB_SECONDARYEFFECT_HPP
|
||||||
|
|
||||||
|
#include <Arbutils/ConstString.hpp>
|
||||||
|
namespace CreatureLib::Library {
|
||||||
|
class SecondaryEffect {
|
||||||
|
private:
|
||||||
|
float _chance;
|
||||||
|
Arbutils::CaseInsensitiveConstString _effectName;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr SecondaryEffect() noexcept : _chance(0), _effectName(""_cnc) {}
|
||||||
|
constexpr SecondaryEffect(float chance, const Arbutils::CaseInsensitiveConstString& effectName) noexcept
|
||||||
|
: _chance(chance), _effectName(effectName) {}
|
||||||
|
|
||||||
|
constexpr float GetChance() const noexcept { return _chance; }
|
||||||
|
constexpr const Arbutils::CaseInsensitiveConstString& GetEffectName() const noexcept { return _effectName; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CREATURELIB_SECONDARYEFFECT_HPP
|
|
@ -33,13 +33,13 @@ SpeciesLibrary* TestLibrary::BuildSpeciesLibrary() {
|
||||||
AttackLibrary* TestLibrary::BuildAttackLibrary() {
|
AttackLibrary* TestLibrary::BuildAttackLibrary() {
|
||||||
auto l = new AttackLibrary();
|
auto l = new AttackLibrary();
|
||||||
l->Insert("standard"_cnc, new AttackData("standard"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
l->Insert("standard"_cnc, new AttackData("standard"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
||||||
AttackTarget::AdjacentOpponent, 0, {}));
|
AttackTarget::AdjacentOpponent, 0, SecondaryEffect(), {}));
|
||||||
l->Insert("highPriority"_cnc, new AttackData("highPriority"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
l->Insert("highPriority"_cnc, new AttackData("highPriority"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
||||||
AttackTarget::AdjacentOpponent, 1, {}));
|
AttackTarget::AdjacentOpponent, 1, SecondaryEffect(), {}));
|
||||||
l->Insert("higherPriority"_cnc, new AttackData("higherPriority"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
l->Insert("higherPriority"_cnc, new AttackData("higherPriority"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
||||||
AttackTarget::AdjacentOpponent, 2, {}));
|
AttackTarget::AdjacentOpponent, 2, SecondaryEffect(), {}));
|
||||||
l->Insert("lowPriority"_cnc, new AttackData("lowPriority"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
l->Insert("lowPriority"_cnc, new AttackData("lowPriority"_cnc, 0, AttackCategory::Physical, 20, 100, 30,
|
||||||
AttackTarget::AdjacentOpponent, -1, {}));
|
AttackTarget::AdjacentOpponent, -1, SecondaryEffect(), {}));
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue