Reworks attack scripts to handle effect chance and effect name through data files.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2020-04-06 12:02:29 +02:00
parent e2675d06fb
commit 340520e0e3
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
8 changed files with 68 additions and 21 deletions

View File

@ -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);)
}; };

View File

@ -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) {
if (attackData->HasSecondaryEffect()) {
HOOK(OnStatusMove, userSource, attack, target, hitIndex); 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,14 +166,26 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, Creature* targe
if (damage > 0) { if (damage > 0) {
target->Damage(damage, DamageSource::AttackDamage); target->Damage(damage, DamageSource::AttackDamage);
if (attackData->HasSecondaryEffect()) {
bool preventSecondary = false; bool preventSecondary = false;
HOOK(PreventSecondaryEffects, targetSource, attack, target, hitIndex, &preventSecondary); HOOK(PreventSecondaryEffects, targetSource, attack, target, hitIndex, &preventSecondary);
if (!preventSecondary) { 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); HOOK(OnSecondaryEffect, userSource, attack, target, hitIndex);
} }
} }
} }
} }
}
}
if (!user->IsFainted()) { if (!user->IsFainted()) {
HOOK(OnAfterHits, userSource, attack, target); HOOK(OnAfterHits, userSource, attack, target);

View File

@ -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;
} }

View File

@ -21,8 +21,11 @@ namespace CreatureLib::Battling {
return; return;
auto battle = user->GetBattle(); auto battle = user->GetBattle();
if (battle != nullptr) { if (battle != nullptr) {
if (_attack->GetAttack()->HasSecondaryEffect()) {
auto library = battle->GetLibrary(); auto library = battle->GetLibrary();
_attackScript = library->LoadScript(ScriptCategory::Attack, _attack->GetAttack()->GetName()); _attackScript = library->LoadScript(ScriptCategory::Attack,
_attack->GetAttack()->GetSecondaryEffect().GetEffectName());
}
} }
} }

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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;
} }