#ifndef CREATURELIB_EXECUTINGATTACK_HPP #define CREATURELIB_EXECUTINGATTACK_HPP #include "Creature.hpp" namespace CreatureLib::Battling { class ExecutingAttack : public ScriptSource { public: class HitData { bool _critical = false; uint8_t _basePower = 0; float _effectiveness = 1; uint32_t _damage = 0; uint8_t _type = 0; bool _hasFailed = false; public: HitData() noexcept {} [[nodiscard]] inline bool IsCritical() const noexcept { return _critical; } [[nodiscard]] inline uint8_t GetBasePower() const noexcept { return _basePower; } [[nodiscard]] inline float GetEffectiveness() const noexcept { return _effectiveness; } [[nodiscard]] inline uint32_t GetDamage() const noexcept { return _damage; } [[nodiscard]] inline uint8_t GetType() const noexcept { return _type; } [[nodiscard]] inline bool HasFailed() const noexcept { return _hasFailed; } inline void SetCritical(bool value) noexcept { _critical = value; } inline void SetBasePower(uint8_t value) noexcept { _basePower = value; } inline void SetEffectiveness(float value) noexcept { _effectiveness = value; } inline void SetDamage(uint32_t value) noexcept { _damage = value; } inline void SetType(uint8_t value) noexcept { _type = value; } inline void Fail() noexcept { _hasFailed = true; } }; private: uint8_t _numberHits; std::unique_ptr _hits; ArbUt::BorrowedPtr _user; ArbUt::BorrowedPtr _attack; std::unique_ptr _script = nullptr; ArbUt::List> _targets; public: ExecutingAttack(const ArbUt::List>& targets, uint8_t numberHits, ArbUt::BorrowedPtr user, const ArbUt::BorrowedPtr& attack, const std::unique_ptr& script) : _numberHits(numberHits), _hits(std::make_unique(targets.Count() * numberHits)), _user(user), _attack(attack), _targets(targets) { // Take ownership of the script of the attack choice, and give attack choice our initial nullptr. _script.swap(const_cast&>(script)); } ExecutingAttack(const ExecutingAttack&) = delete; ExecutingAttack& operator=(const ExecutingAttack&) = delete; virtual ~ExecutingAttack() noexcept = default; HitData& GetHitData(ArbUt::BorrowedPtr creature, uint8_t hit) { for (uint8_t i = 0; i < _targets.Count(); i++) { if (!_targets[i].HasValue()) { continue; } if (_targets[i].GetValue() == creature) { return _hits[i * _numberHits + hit]; } } THROW("Invalid target requested."); } HitData* GetTargetIteratorBegin(ArbUt::BorrowedPtr creature) { for (uint8_t i = 0; i < _targets.Count(); i++) { if (!_targets[i].HasValue()) { continue; } if (_targets[i].GetValue() == creature) { return &_hits[i * _numberHits]; } } THROW("Invalid target requested."); } bool IsCreatureTarget(ArbUt::BorrowedPtr creature) noexcept { for (uint8_t i = 0; i < _targets.Count(); i++) { if (!_targets[i].HasValue()) { continue; } if (_targets[i].GetValue() == creature) { return true; } } return false; } inline uint8_t GetTargetCount() const noexcept { return _targets.Count(); } inline const ArbUt::List>& GetTargets() const noexcept { return _targets; } inline uint8_t GetNumberOfHits() const noexcept { return _numberHits; } inline const ArbUt::BorrowedPtr& GetUser() noexcept { return _user; } inline const ArbUt::BorrowedPtr& GetAttack() noexcept { return _attack; } size_t ScriptCount() const override { return _user->ScriptCount() + 1; } inline ArbUt::BorrowedPtr GetScript() const noexcept { return _script; } protected: void GetActiveScripts(ArbUt::List& scripts) override { scripts.Append(ScriptWrapper::FromScript(&_script)); _user->GetActiveScripts(scripts); } }; } #endif // CREATURELIB_EXECUTINGATTACK_HPP