Cleans up HistoryHolder to be a lot less complicated (although possibly a bit slower), adds DamageHistory.

Signed-off-by: Deukhoofd <Deukhoofd@gmail.com>
This commit is contained in:
Deukhoofd 2021-10-23 16:57:58 +02:00
parent 1ed57e51af
commit 20b53833c4
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
8 changed files with 54 additions and 69 deletions

View File

@ -4,19 +4,15 @@
using namespace CreatureLib::Battling; using namespace CreatureLib::Battling;
export const HistoryElement* CreatureLib_HistoryHandler_GetTopElement(const HistoryHolder* p) { export const HistoryElement* CreatureLib_HistoryHandler_GetTopElement(const HistoryHolder* p) {
return p->GetTopElement().GetRaw(); return p->GetTopElement().GetValue();
} }
export const HistoryElement* CreatureLib_HistoryHandler_GetLastUsedAttack(const HistoryHolder* p) { export const HistoryElement* CreatureLib_HistoryHandler_GetLastUsedAttack(const HistoryHolder* p) {
auto res = p->GetLastUsedAttack(); return p->GetLastUsedAttack().GetValue();
if (res.has_value()) {
return res.value();
}
return nullptr;
} }
export HistoryElementKind CreatureLib_HistoryElement_GetKind(const HistoryElement* p) { return p->GetKind(); } export HistoryElementKind CreatureLib_HistoryElement_GetKind(const HistoryElement* p) { return p->GetKind(); }
export const HistoryElement* CreatureLib_HistoryElement_GetPrevious(const HistoryElement* p) { export const HistoryElement* CreatureLib_HistoryElement_GetPrevious(const HistoryElement* p) {
return p->GetPrevious().GetRaw(); return p->GetPrevious().GetValue();
} }
export const ExecutingAttack* CreatureLib_AttackUseHistory_GetAttack(const AttackUseHistory* p) { export const ExecutingAttack* CreatureLib_AttackUseHistory_GetAttack(const AttackUseHistory* p) {

View File

@ -1,5 +1,5 @@
#ifndef CREATURELIB_HISTORYELEMENTKIND_HPP #ifndef CREATURELIB_HISTORYELEMENTKIND_HPP
#define CREATURELIB_HISTORYELEMENTKIND_HPP #define CREATURELIB_HISTORYELEMENTKIND_HPP
ENUM(HistoryElementKind, uint8_t, AttackUse) ENUM(HistoryElementKind, uint8_t, AttackUse, Damage)
#endif // CREATURELIB_HISTORYELEMENTKIND_HPP #endif // CREATURELIB_HISTORYELEMENTKIND_HPP

View File

@ -7,17 +7,14 @@ namespace CreatureLib::Battling {
class AttackUseHistory final : public HistoryElement { class AttackUseHistory final : public HistoryElement {
std::unique_ptr<const ExecutingAttack> _attack; std::unique_ptr<const ExecutingAttack> _attack;
protected: public:
void Clear() override { AttackUseHistory(u32 turn, const ExecutingAttack* attack) : HistoryElement(turn), _attack(attack) {}
~AttackUseHistory() {
if (_attack != nullptr) { if (_attack != nullptr) {
_attack.reset(); _attack.reset();
} }
HistoryElement::Clear();
} }
public:
AttackUseHistory(const ExecutingAttack* attack) : _attack(attack) {}
HistoryElementKind GetKind() const noexcept override { return HistoryElementKind::AttackUse; } HistoryElementKind GetKind() const noexcept override { return HistoryElementKind::AttackUse; }
ArbUt::BorrowedPtr<const ExecutingAttack> GetAttack() const noexcept { return _attack; } ArbUt::BorrowedPtr<const ExecutingAttack> GetAttack() const noexcept { return _attack; }
}; };

View File

@ -0,0 +1,24 @@
#ifndef CREATURELIB_DAMAGEHISTORY_HPP
#define CREATURELIB_DAMAGEHISTORY_HPP
#include "HistoryElement.hpp"
namespace CreatureLib::Battling {
class DamageHistory final : public HistoryElement {
ArbUt::BorrowedPtr<CreatureLib::Battling::Creature> _target;
u32 _amount;
DamageSource _source;
public:
DamageHistory(u32 turn, ArbUt::BorrowedPtr<CreatureLib::Battling::Creature> target, u32 amount,
DamageSource source)
: HistoryElement(turn), _target(target), _amount(amount), _source(source) {}
HistoryElementKind GetKind() const noexcept override { return HistoryElementKind::Damage; }
inline ArbUt::BorrowedPtr<CreatureLib::Battling::Creature> GetTarget() const noexcept { return _target; }
inline u32 GetAmount() const noexcept { return _amount; }
inline DamageSource GetDamageSource() const noexcept { return _source; }
};
}
#endif // CREATURELIB_DAMAGEHISTORY_HPP

View File

@ -5,25 +5,23 @@
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class HistoryElement { class HistoryElement {
friend class HistoryHolder; ArbUt::OptionalUniquePtr<HistoryElement> _previous;
u8* _previousOffset = nullptr; u32 _turnNumber;
protected:
virtual void Clear() {
if (_previousOffset != nullptr) {
GetPrevious()->Clear();
}
}
public: public:
virtual HistoryElementKind GetKind() const noexcept = 0; HistoryElement(u32 turn) : _turnNumber(turn) {}
ArbUt::BorrowedPtr<const HistoryElement> GetPrevious() const noexcept { virtual ~HistoryElement() {}
return reinterpret_cast<HistoryElement*>((u8*)this - _previousOffset);
[[nodiscard]] virtual HistoryElementKind GetKind() const noexcept = 0;
[[nodiscard]] ArbUt::OptionalBorrowedPtr<const HistoryElement> GetPrevious() const noexcept {
return _previous.GetValue();
} }
ArbUt::BorrowedPtr<HistoryElement> GetPrevious() noexcept { ArbUt::OptionalBorrowedPtr<HistoryElement> GetPrevious() noexcept { return _previous.GetValue(); }
return reinterpret_cast<HistoryElement*>((u8*)this - _previousOffset);
} void SetPrevious(HistoryElement* el) noexcept { _previous = el; }
inline u32 GetTurnNumber() const noexcept { return _turnNumber; }
}; };
} }

View File

@ -9,56 +9,24 @@ concept HistoryElementType = std::is_base_of<CreatureLib::Battling::HistoryEleme
namespace CreatureLib::Battling { namespace CreatureLib::Battling {
class HistoryHolder { class HistoryHolder {
size_t _offset;
size_t _capacity;
u8* _memory = nullptr;
HistoryElement* _top = nullptr; HistoryElement* _top = nullptr;
static constexpr size_t initialSize = 2048;
static constexpr size_t stepSize = 1024;
public: public:
HistoryHolder() : _offset(0), _capacity(2048) { HistoryHolder() {}
auto ptr = malloc(_capacity);
if (ptr == nullptr) {
THROW("Out of memory.");
}
_memory = static_cast<u8*>(ptr);
}
HistoryHolder(const HistoryHolder&) = delete; HistoryHolder(const HistoryHolder&) = delete;
HistoryHolder& operator=(const HistoryHolder&) = delete; HistoryHolder& operator=(const HistoryHolder&) = delete;
~HistoryHolder() { virtual ~HistoryHolder() { delete _top; }
if (_top != nullptr)
_top->Clear();
free(_memory);
}
void Resize() {
_capacity += stepSize;
auto newPtr = realloc(_memory, _capacity);
if (newPtr == nullptr) {
THROW("Out of memory.");
}
_memory = static_cast<u8*>(newPtr);
}
template <HistoryElementType T, class... parameters> void Register(parameters... args) { template <HistoryElementType T, class... parameters> void Register(parameters... args) {
if (_offset + sizeof(T) >= _capacity) { auto* prev = _top;
Resize(); _top = new T(args...);
} _top->SetPrevious(prev);
u8* ptr = _memory + _offset;
T* element = new (ptr) T(args...);
_offset += sizeof(T);
if (_top != nullptr) {
element->_previousOffset = (u8*)sizeof(T);
}
_top = element;
} }
ArbUt::BorrowedPtr<const HistoryElement> GetTopElement() const noexcept { return _top; } [[nodiscard]] ArbUt::OptionalBorrowedPtr<const HistoryElement> GetTopElement() const noexcept { return _top; }
std::optional<ArbUt::BorrowedPtr<const HistoryElement>> GetLastUsedAttack() const noexcept { ArbUt::OptionalBorrowedPtr<const HistoryElement> GetLastUsedAttack() const noexcept {
const auto* c = _top; const auto* c = _top;
while (c != nullptr) { while (c != nullptr) {
if (c->GetKind() == HistoryElementKind::AttackUse) if (c->GetKind() == HistoryElementKind::AttackUse)

View File

@ -112,7 +112,7 @@ namespace CreatureLib::Battling {
const EventHook& GetEventHook() const noexcept { return _eventHook; } const EventHook& GetEventHook() const noexcept { return _eventHook; }
template <HistoryElementType T, class... parameters> void RegisterHistoryElement(parameters... args) { template <HistoryElementType T, class... parameters> void RegisterHistoryElement(parameters... args) {
try_creature(this->_historyHolder.Register<T>(args...); try_creature(this->_historyHolder.Register<T>(this->GetCurrentTurn(), args...);
, "Exception occurred during history element registration."); , "Exception occurred during history element registration.");
} }
const HistoryHolder& GetHistory() const noexcept { return _historyHolder; } const HistoryHolder& GetHistory() const noexcept { return _historyHolder; }

View File

@ -1,6 +1,7 @@
#include "Creature.hpp" #include "Creature.hpp"
#include <utility> #include <utility>
#include "../EventHooks/EventDataClasses.hpp" #include "../EventHooks/EventDataClasses.hpp"
#include "../History/HistoryElements/DamageHistory.hpp"
#include "../Models/Battle.hpp" #include "../Models/Battle.hpp"
#include "../ScriptHandling/ScriptMacros.hpp" #include "../ScriptHandling/ScriptMacros.hpp"
@ -176,6 +177,7 @@ namespace CreatureLib::Battling {
auto battle = this->GetBattle(); auto battle = this->GetBattle();
if (battle.HasValue()) { if (battle.HasValue()) {
battle.GetValue()->TriggerEventListener<DamageEvent>(this, source, _currentHealth, newHealth); battle.GetValue()->TriggerEventListener<DamageEvent>(this, source, _currentHealth, newHealth);
battle.GetValue()->RegisterHistoryElement<DamageHistory>(this, damage, source);
} }
_currentHealth = newHealth; _currentHealth = newHealth;