Overhaul memory model to new Arbutils memory.
Some checks failed
continuous-integration/drone/push Build is failing

Signed-off-by: Deukhoofd <Deukhoofd@gmail.com>
This commit is contained in:
2020-12-12 12:22:48 +01:00
parent 1dc3aafd33
commit 5c39694f19
33 changed files with 279 additions and 211 deletions

View File

@@ -46,7 +46,7 @@ namespace CreatureLib::Battling {
if (_offset + sizeof(T) >= _capacity) {
_capacity += stepSize;
auto newPtr = realloc(_memory, _capacity);
auto* newPtr = realloc(_memory, _capacity);
if (newPtr == nullptr) {
THROW("Out of memory.");
}
@@ -55,7 +55,7 @@ namespace CreatureLib::Battling {
uint8_t* ptr = _memory + _offset;
T* event = new (ptr) T(args...);
_offset += sizeof(T);
for (auto listener : _listeners) {
for (const auto& listener : _listeners) {
try_creature(listener(event), "Exception in event listener");
}
}

View File

@@ -15,9 +15,9 @@ namespace CreatureLib::Battling {
return 1;
}
static ArbUt::List<ArbUt::BorrowedPtr<Creature>> ResolveTargets(const CreatureIndex& index,
CreatureLib::Library::AttackTarget target,
const ArbUt::BorrowedPtr<Battle>& battle) {
static ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>
ResolveTargets(const CreatureIndex& index, CreatureLib::Library::AttackTarget target,
const ArbUt::BorrowedPtr<Battle>& battle) {
switch (target) {
case CreatureLib::Library::AttackTarget::Adjacent: {
return {battle->GetCreature(index)};
@@ -32,14 +32,15 @@ namespace CreatureLib::Battling {
return {battle->GetCreature(index)};
};
case CreatureLib::Library::AttackTarget::All: {
ArbUt::BorrowedPtr<Creature> arr[battle->GetCreaturesPerSide() * battle->GetSides().Count()];
ArbUt::OptionalBorrowedPtr<Creature>
arr[battle->GetCreaturesPerSide() * battle->GetSides().Count()];
size_t i = 0;
for (auto side : battle->GetSides()) {
for (auto mon : side->GetCreatures()) {
arr[i++] = mon;
}
}
return ArbUt::List<ArbUt::BorrowedPtr<Creature>>(arr, arr + i);
return ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(arr, arr + i);
}
case CreatureLib::Library::AttackTarget::AllAdjacent: {
auto left = index.GetCreatureIndex() - 1;
@@ -77,20 +78,20 @@ namespace CreatureLib::Battling {
}
}
case CreatureLib::Library::AttackTarget::AllAlly: {
ArbUt::BorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
ArbUt::OptionalBorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
size_t i = 0;
for (auto mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
arr[i++] = mon;
}
return ArbUt::List<ArbUt::BorrowedPtr<Creature>>(arr, arr + i);
return ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(arr, arr + i);
};
case CreatureLib::Library::AttackTarget::AllOpponent: {
ArbUt::BorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
ArbUt::OptionalBorrowedPtr<Creature> arr[battle->GetCreaturesPerSide()];
size_t i = 0;
for (auto mon : battle->GetSides()[index.GetSideIndex()]->GetCreatures()) {
arr[i++] = mon;
}
return ArbUt::List<ArbUt::BorrowedPtr<Creature>>(arr, arr + i);
return ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>(arr, arr + i);
};
case CreatureLib::Library::AttackTarget::Any: {
return {battle->GetCreature(index)};

View File

@@ -15,14 +15,14 @@ void TurnHandler::RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue) {
auto item = queue->Dequeue();
AssertNotNull(item)
AssertNotNull(item->GetUser())
AssertNotNull(item->GetUser()->GetBattle())
AssertNotNull(item->GetUser()->GetBattleSide())
auto index = (uint32_t)item->GetUser()->GetBattleSide()->GetCreatureIndex(item->GetUser());
Assert(item->GetUser()->GetBattle().HasValue())
Assert(item->GetUser()->GetBattleSide().HasValue())
auto index = (uint32_t)item->GetUser()->GetBattleSide().GetValue()->GetCreatureIndex(item->GetUser());
try_creature(ExecuteChoice(item.get()),
"Executing choice failed for choice by mon on side "
<< ((uint32_t)item->GetUser()->GetBattleSide()->GetSideIndex()) << " and index " << index
<< ". Choice had choice kind "
<< ((uint32_t)item->GetUser()->GetBattleSide().GetValue()->GetSideIndex()) << " and index "
<< index << ". Choice had choice kind "
<< CreatureLib::Battling::TurnChoiceKindHelper::ToString(item->GetKind()) << " "
<< " with message");
}
@@ -37,14 +37,15 @@ void TurnHandler::ExecuteChoice(ArbUt::BorrowedPtr<BaseTurnChoice> choice) {
}
auto user = choice->GetUser();
AssertNotNull(user)
if (user->GetBattle()->HasEnded())
if (!user->GetBattle().HasValue())
return;
auto battle = user->GetBattle().GetValue();
if (battle->HasEnded())
return;
// If the user is fainted, we don't want to execute its choice.
if (user->IsFainted()) {
return;
}
auto battle = user->GetBattle();
AssertNotNull(battle)
// If the user is not in the field, we don't want to execute its choice.
if (!user->IsOnBattleField()) {
return;
@@ -76,8 +77,9 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
}
auto targetType = choice->GetAttack()->GetAttack()->GetTarget();
ArbUt::List<ArbUt::BorrowedPtr<Creature>> targets;
try_creature(targets = TargetResolver::ResolveTargets(choice->GetTarget(), targetType, battle);
ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>> targets;
Assert(battle.HasValue());
try_creature(targets = TargetResolver::ResolveTargets(choice->GetTarget(), targetType, battle.GetValue());
, "Exception during target determination");
auto attack = new ExecutingAttack(targets, 1, choice->GetUser(), choice->GetAttack(), choice->GetAttackScript());
@@ -94,8 +96,8 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
return;
}
battle->TriggerEventListener<AttackUseEvent>(attack);
battle->RegisterHistoryElement<AttackUseHistory>(attack);
battle.GetValue()->TriggerEventListener<AttackUseEvent>(attack);
battle.GetValue()->RegisterHistoryElement<AttackUseHistory>(attack);
// HOOK: check if attack fails
bool fail = false;
@@ -114,7 +116,10 @@ void TurnHandler::ExecuteAttackChoice(const ArbUt::BorrowedPtr<AttackTurnChoice>
for (uint8_t i = 0; i < attack->GetTargetCount(); i++) {
auto target = attack->GetTargets()[i];
try_creature(HandleAttackForTarget(attack, target), "Exception occurred during handling attack for target");
if (target.HasValue()) {
try_creature(HandleAttackForTarget(attack, target.GetValue()), "Exception occurred during handling attack "
"for target");
}
}
}
@@ -124,8 +129,8 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
AssertNotNull(user)
AssertNotNull(target)
auto& battle = user->GetBattle();
AssertNotNull(battle)
if (battle->HasEnded())
Assert(battle.HasValue())
if (battle.GetValue()->HasEnded())
return;
bool fail = false;
@@ -145,7 +150,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
auto numberOfHits = attack->GetNumberOfHits();
if (numberOfHits == 0) {
HOOK(OnAttackMiss, target, attack, target.GetRaw());
battle->TriggerEventListener<MissEvent>(user);
battle.GetValue()->TriggerEventListener<MissEvent>(user);
return;
}
@@ -154,7 +159,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
auto& attackData = learnedAttack->GetAttack();
AssertNotNull(attackData);
auto& library = battle->GetLibrary();
auto& library = battle.GetValue()->GetLibrary();
AssertNotNull(library)
auto& dmgLibrary = library->GetDamageLibrary();
auto& typeLibrary = library->GetTypeLibrary();
@@ -165,7 +170,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
auto hitIterator = attack->GetTargetIteratorBegin(target);
for (uint8_t hitIndex = 0; hitIndex < numberOfHits; hitIndex++) {
if (battle->HasEnded())
if (battle.GetValue()->HasEnded())
return;
if (user->IsFainted()) {
break;
@@ -193,7 +198,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
hasSecondaryEffect = true;
} else {
hasSecondaryEffect =
battle->GetRandom()->EffectChance(effect->GetChance(), attack, target.GetRaw());
battle.GetValue()->GetRandom()->EffectChance(effect->GetChance(), attack, target.GetRaw());
}
if (hasSecondaryEffect) {
HOOK(OnSecondaryEffect, user, attack, target.GetRaw(), hitIndex);
@@ -223,7 +228,7 @@ void TurnHandler::HandleAttackForTarget(ExecutingAttack* attack, const ArbUt::Bo
if (effect->GetChance() == -1) {
hasSecondaryEffect = true;
} else {
auto random = battle->GetRandom();
auto random = battle.GetValue()->GetRandom();
AssertNotNull(random);
hasSecondaryEffect = random->EffectChance(effect->GetChance(), attack, target.GetRaw());
}
@@ -257,20 +262,24 @@ void TurnHandler::ExecuteSwitchChoice(ArbUt::BorrowedPtr<SwitchTurnChoice> choic
auto user = choice->GetUser();
user->ClearVolatileScripts();
auto userSide = user->GetBattleSide();
auto userIndex = userSide->GetCreatureIndex(user);
userSide->SetCreature(choice->GetNewCreature(), userIndex);
if (userSide.HasValue()) {
auto userIndex = userSide.GetValue()->GetCreatureIndex(user);
userSide.GetValue()->SetCreature(choice->GetNewCreature(), userIndex);
}
}
void TurnHandler::ExecuteFleeChoice(ArbUt::BorrowedPtr<FleeTurnChoice> choice) {
auto user = choice->GetUser();
auto battle = user->GetBattle();
if (!battle->CanFlee()) {
if (!battle.HasValue() || !battle.GetValue()->CanFlee()) {
return;
}
// TODO: If any of the creatures on the users side has a script that prevents it from running, block.
// TODO: If any of the creatures on any other side has a script that prevents this side from running, block.
if (battle->GetLibrary()->GetMiscLibrary()->CanFlee(choice.GetRaw())) {
user->GetBattleSide()->MarkAsFled();
battle->ValidateBattleState();
if (battle.GetValue()->GetLibrary()->GetMiscLibrary()->CanFlee(choice.GetRaw())) {
if (user->GetBattleSide().HasValue()) {
user->GetBattleSide().GetValue()->MarkAsFled();
}
battle.GetValue()->ValidateBattleState();
}
}

View File

@@ -51,14 +51,14 @@ namespace CreatureLib::Battling {
ArbUt::BorrowedPtr<const HistoryElement> GetTopElement() const noexcept { return _top; }
ArbUt::BorrowedPtr<const HistoryElement> GetLastUsedAttack() const noexcept {
std::optional<ArbUt::BorrowedPtr<const HistoryElement>> GetLastUsedAttack() const noexcept {
const auto* c = _top;
while (c != nullptr) {
if (c->GetKind() == HistoryElementKind::AttackUse)
return c;
c = c->_previous;
}
return nullptr;
return {};
}
};
}

View File

@@ -6,7 +6,8 @@ bool CreatureLib::Battling::MiscLibrary::IsCritical([[maybe_unused]] CreatureLib
CreatureLib::Battling::Creature* target,
[[maybe_unused]] uint8_t hit) const {
AssertNotNull(target)
auto rand = target->GetBattle()->GetRandom();
Assert(target->GetBattle().HasValue())
auto rand = target->GetBattle().GetValue()->GetRandom();
return rand->Get(10) <= 0;
}
@@ -35,10 +36,11 @@ bool CreatureLib::Battling::MiscLibrary::CanFlee([[maybe_unused]] FleeTurnChoice
CreatureLib::Battling::BaseTurnChoice*
CreatureLib::Battling::MiscLibrary::ReplacementAttack(Creature* user, [[maybe_unused]] CreatureIndex target) const {
AssertNotNull(user)
Assert(user->GetBattleSide().HasValue())
auto sideTarget = 0;
if (user->GetBattleSide()->GetSideIndex() == 0)
if (user->GetBattleSide().GetValue()->GetSideIndex() == 0)
sideTarget = 1;
auto side = user->GetBattle()->GetSides()[sideTarget];
auto side = user->GetBattle().GetValue()->GetSides()[sideTarget];
auto random_mon = side->GetRandomCreatureIndex();
return new AttackTurnChoice(user, GetReplacementAttack(), CreatureIndex(side->GetSideIndex(), random_mon));
}

View File

@@ -21,7 +21,8 @@ bool Battle::TrySetChoice(BaseTurnChoice* choice) {
AssertNotNull(choice)
if (!CanUse(choice))
return false;
choice->GetUser()->GetBattleSide()->SetChoice(choice);
Assert(choice->GetUser()->GetBattleSide().HasValue())
choice->GetUser()->GetBattleSide().GetValue()->SetChoice(choice);
CheckChoicesSetAndRun();
return true;
}
@@ -155,15 +156,15 @@ void Battle::ValidateBattleState() {
}
void Battle::AddVolatileScript(const ArbUt::StringView& key) {
auto script = _volatile.Get(key);
if (script != nullptr) {
script->Stack();
if (script.has_value()) {
script.value()->Stack();
return;
}
script = _library->LoadScript(ScriptCategory::Battle, key);
if (script == nullptr) {
if (!script.has_value()) {
THROW("Invalid volatile script requested for battle: '" << key.c_str() << "'.");
}
return _volatile.Add(script.GetRaw());
return _volatile.Add(script.value().GetRaw());
}
void Battle::AddVolatileScript(Script* script) { return _volatile.Add(script); }
void Battle::RemoveVolatileScript(Script* script) { _volatile.Remove(script->GetName()); }

View File

@@ -41,7 +41,6 @@ namespace CreatureLib::Battling {
.count())
: _library(library), _parties(parties.GetStdList()), _canFlee(canFlee), _numberOfSides(numberOfSides),
_creaturesPerSide(creaturesPerSide), _sides(numberOfSides), _random(randomSeed) {
AssertNotNull(_library);
AssertAllNotNull(parties);
for (size_t i = 0; i < numberOfSides; i++) {
@@ -67,10 +66,10 @@ namespace CreatureLib::Battling {
bool CreatureInField(ArbUt::BorrowedPtr<Creature> creature) const;
const ArbUt::BorrowedPtr<Creature>& GetCreature(const CreatureIndex& target) const {
const ArbUt::OptionalBorrowedPtr<Creature>& GetCreature(const CreatureIndex& target) const {
return _sides[target.GetSideIndex()]->GetCreature(target.GetCreatureIndex());
}
const ArbUt::BorrowedPtr<Creature>& GetCreature(uint8_t side, uint8_t target) const {
const ArbUt::OptionalBorrowedPtr<Creature>& GetCreature(uint8_t side, uint8_t target) const {
return _sides[side]->GetCreature(target);
}
@@ -87,8 +86,12 @@ namespace CreatureLib::Battling {
const ArbUt::UniquePtrList<BattleParty>& GetParties() const noexcept { return _parties; }
const ArbUt::UniquePtrList<BattleSide>& GetSides() const noexcept { return _sides; }
ArbUt::BorrowedPtr<Script> GetVolatileScript(const ArbUt::StringView& key) const { return _volatile.Get(key); }
ArbUt::BorrowedPtr<Script> GetVolatileScript(uint32_t keyHash) const noexcept { return _volatile.Get(keyHash); }
std::optional<ArbUt::BorrowedPtr<Script>> GetVolatileScript(const ArbUt::StringView& key) const {
return _volatile.Get(key);
}
std::optional<ArbUt::BorrowedPtr<Script>> GetVolatileScript(uint32_t keyHash) const noexcept {
return _volatile.Get(keyHash);
}
void AddVolatileScript(const ArbUt::StringView& key);
void AddVolatileScript(Script* script);
void RemoveVolatileScript(const ArbUt::BasicStringView& name) { _volatile.Remove(name); }

View File

@@ -11,7 +11,7 @@ bool BattleSide::AllPossibleSlotsFilled() const {
try {
for (size_t i = 0; i < _creatures.Count(); i++) {
auto c = _creatures[i];
if (c == nullptr || c->IsFainted()) {
if (!c.HasValue() || c.GetValue()->IsFainted()) {
if (_battle->CanSlotBeFilled(_index, i))
return false;
}
@@ -34,7 +34,10 @@ void BattleSide::SetChoice(BaseTurnChoice* choice) {
try {
for (size_t i = 0; i < _creatures.Count(); i++) {
auto& c = _creatures[i];
if (c == choice->GetUser()) {
if (!c.HasValue()) {
continue;
}
if (c.GetValue() == choice->GetUser()) {
_choices[i] = std::shared_ptr<BaseTurnChoice>(choice);
_choicesSet++;
return;
@@ -46,37 +49,39 @@ void BattleSide::SetChoice(BaseTurnChoice* choice) {
THROW("User not found");
}
void BattleSide::SetCreature(ArbUt::BorrowedPtr<Creature> creature, uint8_t index) {
void BattleSide::SetCreature(ArbUt::OptionalBorrowedPtr<Creature> creature, uint8_t index) {
auto old = _creatures[index];
if (old != nullptr) {
old->SetOnBattleField(false);
if (old.HasValue()) {
old.GetValue()->SetOnBattleField(false);
}
_creatures[index] = creature;
if (creature != nullptr) {
creature->SetBattleData(_battle, this);
creature->SetOnBattleField(true);
}
if (_battle == nullptr)
_creatures[index] = creature.GetValue();
if (!creature.HasValue()) {
return;
for (auto side : _battle->GetSides()) {
if (side == this)
}
creature.GetValue()->SetBattleData(_battle, this);
creature.GetValue()->SetOnBattleField(true);
if (_battle == nullptr) {
return;
}
for (auto* side : _battle->GetSides()) {
if (side == this) {
continue;
}
for (const auto& c : side->GetCreatures()) {
if (c != nullptr) {
c->MarkOpponentAsSeen(creature);
creature->MarkOpponentAsSeen(c.GetRaw());
if (c.HasValue()) {
c.GetValue()->MarkOpponentAsSeen(creature.GetValue());
creature.GetValue()->MarkOpponentAsSeen(c.GetValue());
}
}
}
_battle->TriggerEventListener<SwitchEvent>(CreatureIndex(this->_index, index), creature);
_battle->TriggerEventListener<SwitchEvent>(CreatureIndex(this->_index, index), creature.GetValue());
}
bool BattleSide::CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const {
AssertNotNull(creature)
return std::find(_creatures.begin(), _creatures.end(), creature) != _creatures.end();
return std::find(_creatures.begin(), _creatures.end(), creature.GetRaw()) != _creatures.end();
}
const ArbUt::BorrowedPtr<Creature>& BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; }
const ArbUt::OptionalBorrowedPtr<Creature>& BattleSide::GetCreature(uint8_t index) const { return _creatures[index]; }
void BattleSide::GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) {
scripts.Append(ScriptWrapper::FromSet(&_volatile));

View File

@@ -8,7 +8,7 @@ namespace CreatureLib::Battling {
class BattleSide : public ScriptSource {
uint8_t _index;
uint8_t _creaturesPerSide;
ArbUt::List<ArbUt::BorrowedPtr<Creature>> _creatures;
ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>> _creatures;
ArbUt::List<std::shared_ptr<BaseTurnChoice>> _choices;
ArbUt::List<bool> _fillableSlots;
uint8_t _choicesSet = 0;
@@ -40,20 +40,22 @@ namespace CreatureLib::Battling {
void SetChoice(BaseTurnChoice* choice);
void ResetChoices() noexcept;
void SetCreature(ArbUt::BorrowedPtr<Creature> creature, uint8_t index);
void SetCreature(ArbUt::OptionalBorrowedPtr<Creature> creature, uint8_t index);
const ArbUt::BorrowedPtr<Creature>& GetCreature(uint8_t index) const;
const ArbUt::OptionalBorrowedPtr<Creature>& GetCreature(uint8_t index) const;
bool CreatureOnSide(const ArbUt::BorrowedPtr<Creature>& creature) const;
size_t ScriptCount() const override;
void GetActiveScripts(ArbUt::List<ScriptWrapper>& scripts) override;
const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& GetCreatures() { return _creatures; }
const ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>& GetCreatures() { return _creatures; }
uint8_t GetSideIndex() noexcept { return _index; }
uint8_t GetCreatureIndex(const ArbUt::BorrowedPtr<Creature>& c) {
for (size_t i = 0; i < _creatures.Count(); i++) {
if (_creatures[i] == c)
if (!_creatures[i].HasValue())
continue;
if (_creatures[i].GetValue() == c.GetRaw())
return i;
}
THROW("Unable to find creature on field.");
@@ -61,7 +63,9 @@ namespace CreatureLib::Battling {
void MarkSlotAsUnfillable(const ArbUt::BorrowedPtr<Creature>& creature) noexcept {
for (uint8_t i = 0; i < _creaturesPerSide; i++) {
if (_creatures[i] == creature) {
if (!_creatures[i].HasValue())
continue;
if (_creatures[i].GetValue() == creature) {
_fillableSlots.At(i) = false;
return;
}

View File

@@ -17,10 +17,6 @@ namespace CreatureLib::Battling {
_uniqueIdentifier(uid), _gender(gender), _coloring(coloring), _heldItem(heldItem),
_nickname(std::move(nickname)), _talentIndex(talent), _hasOverridenTalent(false), _attacks(attacks),
_allowedExperienceGain(allowedExperienceGain) {
AssertNotNull(library)
AssertNotNull(species)
AssertNotNull(variant)
_activeTalent = std::unique_ptr<Script>(_library->LoadScript(ScriptCategory::Talent, GetActiveTalent()));
for (auto t : _variant->GetTypes()) {
_types.push_back(t);
@@ -36,8 +32,8 @@ namespace CreatureLib::Battling {
// If the creature is genderless, but it's new species is not, we want to set its gender
if (_gender != CreatureLib::Library::Gender::Genderless && _species->GetGenderRate() != -1) {
// If we are currently in battle, use the battle random so we can get predictable events.
if (!_battle.IsNull()) {
_gender = _species->GetRandomGender(_battle->GetRandom()->GetRNG());
if (_battle.HasValue()) {
_gender = _species->GetRandomGender(_battle.GetValue()->GetRandom()->GetRNG());
}
// Else create a new random.
else {
@@ -48,8 +44,8 @@ namespace CreatureLib::Battling {
else if (_species->GetGenderRate() == -1 && _gender != CreatureLib::Library::Gender::Genderless) {
_gender = CreatureLib::Library::Gender::Genderless;
}
if (_battle != nullptr) {
_battle->TriggerEventListener<ChangeSpeciesEvent>(this, _species);
if (_battle.HasValue()) {
_battle.GetValue()->TriggerEventListener<ChangeSpeciesEvent>(this, _species);
}
ChangeVariant(variant);
}
@@ -79,8 +75,8 @@ namespace CreatureLib::Battling {
// TODO: consider variant specific attacks?
if (_battle != nullptr) {
_battle->TriggerEventListener<ChangeVariantEvent>(this, _variant);
if (_battle.HasValue()) {
_battle.GetValue()->TriggerEventListener<ChangeVariantEvent>(this, _variant);
}
}
@@ -102,9 +98,9 @@ namespace CreatureLib::Battling {
return _variant->GetTalent(_talentIndex);
}
void Creature::SetBattleData(ArbUt::BorrowedPtr<Battle> battle, ArbUt::BorrowedPtr<BattleSide> side) {
_battle = battle;
_side = side;
void Creature::SetBattleData(const ArbUt::BorrowedPtr<Battle>& battle, const ArbUt::BorrowedPtr<BattleSide>& side) {
_battle = battle.GetRaw();
_side = side.GetRaw();
this->ResetActiveScripts();
}
@@ -142,9 +138,9 @@ namespace CreatureLib::Battling {
// endregion
const ArbUt::BorrowedPtr<Battle>& Creature::GetBattle() const { return _battle; }
const ArbUt::OptionalBorrowedPtr<Battle>& Creature::GetBattle() const { return _battle; }
const ArbUt::BorrowedPtr<BattleSide>& Creature::GetBattleSide() const { return _side; }
const ArbUt::OptionalBorrowedPtr<BattleSide>& Creature::GetBattleSide() const { return _side; }
bool Creature::IsFainted() const noexcept { return this->_currentHealth == 0; }
@@ -152,15 +148,17 @@ namespace CreatureLib::Battling {
AssertNotNull(_battle)
AssertNotNull(_side)
// HOOK: On Faint
if (_battle != nullptr) {
_battle->TriggerEventListener<FaintEvent>(this);
if (_battle.HasValue()) {
_battle.GetValue()->TriggerEventListener<FaintEvent>(this);
}
_library->GetExperienceLibrary()->HandleExperienceGain(this, _seenOpponents);
auto sideIndex = _side->GetCreatureIndex(this);
if (!_battle->CanSlotBeFilled(_side->GetSideIndex(), sideIndex)) {
_side->MarkSlotAsUnfillable(this);
if (_battle.HasValue() && _side.HasValue()) {
auto sideIndex = _side.GetValue()->GetCreatureIndex(this);
if (!_battle.GetValue()->CanSlotBeFilled(_side.GetValue()->GetSideIndex(), sideIndex)) {
_side.GetValue()->MarkSlotAsUnfillable(this);
}
_battle.GetValue()->ValidateBattleState();
}
_battle->ValidateBattleState();
}
void Creature::Damage(uint32_t damage, DamageSource source) {
@@ -172,8 +170,8 @@ namespace CreatureLib::Battling {
// HOOK: On Damage
auto newHealth = _currentHealth - damage;
auto battle = this->GetBattle();
if (battle != nullptr) {
battle->TriggerEventListener<DamageEvent>(this, source, _currentHealth, newHealth);
if (battle.HasValue()) {
battle.GetValue()->TriggerEventListener<DamageEvent>(this, source, _currentHealth, newHealth);
}
_currentHealth = newHealth;
@@ -192,8 +190,8 @@ namespace CreatureLib::Battling {
// HOOK: On Heal
auto newHealth = _currentHealth + amount;
auto battle = this->GetBattle();
if (battle != nullptr) {
battle->TriggerEventListener<HealEvent>(this, _currentHealth, newHealth);
if (battle.HasValue()) {
battle.GetValue()->TriggerEventListener<HealEvent>(this, _currentHealth, newHealth);
}
_currentHealth = newHealth;
}
@@ -223,8 +221,8 @@ namespace CreatureLib::Battling {
size_t Creature::ScriptCount() const {
auto c = 3;
if (_side != nullptr) {
c += _side->ScriptCount();
if (_side.HasValue()) {
c += _side.GetValue()->ScriptCount();
}
return c;
}
@@ -233,8 +231,8 @@ namespace CreatureLib::Battling {
scripts.Append(ScriptWrapper::FromScript(&_activeTalent));
scripts.Append(ScriptWrapper::FromScript(&_status));
scripts.Append(ScriptWrapper::FromSet(&_volatile));
if (_side != nullptr) {
_side->GetActiveScripts(scripts);
if (_side.HasValue()) {
_side.GetValue()->GetActiveScripts(scripts);
}
}
void Creature::ClearVolatileScripts() { _volatile.Clear(); }
@@ -248,22 +246,22 @@ namespace CreatureLib::Battling {
if (level >= maxLevel) {
exp = _library->GetGrowthRateLibrary()->CalculateExperience(this->GetSpecies()->GetGrowthRate(), maxLevel);
}
if (_battle != nullptr) {
_battle->TriggerEventListener<ExperienceGainEvent>(this, _experience, exp);
if (_battle.HasValue()) {
_battle.GetValue()->TriggerEventListener<ExperienceGainEvent>(this, _experience, exp);
}
_experience = exp;
_level = level;
}
ArbUt::BorrowedPtr<const Library::CreatureSpecies> Creature::GetDisplaySpecies() const noexcept {
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> Creature::GetDisplaySpecies() const noexcept {
auto species = _displaySpecies;
if (species == nullptr)
species = _species;
if (!species.HasValue())
species = _species.GetRaw();
return species;
}
ArbUt::BorrowedPtr<const Library::SpeciesVariant> Creature::GetDisplayVariant() const noexcept {
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> Creature::GetDisplayVariant() const noexcept {
auto variant = _displayVariant;
if (variant == nullptr)
variant = _variant;
if (!variant.HasValue())
variant = _variant.GetRaw();
return variant;
}
void Creature::SetHeldItem(const ArbUt::BasicStringView& itemName) {
@@ -283,15 +281,15 @@ namespace CreatureLib::Battling {
void Creature::AddVolatileScript(const ArbUt::StringView& name) {
auto script = _volatile.Get(name);
if (script != nullptr) {
script->Stack();
if (script.has_value()) {
script.value()->Stack();
return;
}
script = this->_library->LoadScript(ScriptCategory::Creature, name);
if (script == nullptr) {
if (!script.has_value()) {
THROW("Invalid volatile script requested for creature: '" << name.c_str() << "'.");
}
_volatile.Add(script.GetRaw());
_volatile.Add(script.value().GetRaw());
}
void Creature::AddVolatileScript(Script* script) { _volatile.Add(script); }

View File

@@ -24,8 +24,8 @@ namespace CreatureLib::Battling {
ArbUt::BorrowedPtr<const Library::CreatureSpecies> _species;
ArbUt::BorrowedPtr<const Library::SpeciesVariant> _variant;
ArbUt::BorrowedPtr<const Library::CreatureSpecies> _displaySpecies = nullptr;
ArbUt::BorrowedPtr<const Library::SpeciesVariant> _displayVariant = nullptr;
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> _displaySpecies = nullptr;
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> _displayVariant = nullptr;
level_int_t _level;
uint32_t _experience;
@@ -39,8 +39,8 @@ namespace CreatureLib::Battling {
Library::StatisticSet<uint32_t> _flatStats;
Library::StatisticSet<uint32_t> _boostedStats;
ArbUt::BorrowedPtr<Battle> _battle = nullptr;
ArbUt::BorrowedPtr<BattleSide> _side = nullptr;
ArbUt::OptionalBorrowedPtr<Battle> _battle = nullptr;
ArbUt::OptionalBorrowedPtr<BattleSide> _side = nullptr;
bool _onBattleField = false;
std::string _nickname = "";
@@ -104,9 +104,9 @@ namespace CreatureLib::Battling {
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }
void SetBattleData(ArbUt::BorrowedPtr<Battle> battle, ArbUt::BorrowedPtr<BattleSide> side);
const ArbUt::BorrowedPtr<Battle>& GetBattle() const;
const ArbUt::BorrowedPtr<BattleSide>& GetBattleSide() const;
void SetBattleData(const ArbUt::BorrowedPtr<Battle>& battle, const ArbUt::BorrowedPtr<BattleSide>& side);
const ArbUt::OptionalBorrowedPtr<Battle>& GetBattle() const;
const ArbUt::OptionalBorrowedPtr<BattleSide>& GetBattleSide() const;
inline void SetOnBattleField(bool value) { _onBattleField = value; }
inline bool IsOnBattleField() const { return _onBattleField; }
@@ -149,14 +149,14 @@ namespace CreatureLib::Battling {
return false;
}
ArbUt::BorrowedPtr<const Library::CreatureSpecies> GetDisplaySpecies() const noexcept;
ArbUt::BorrowedPtr<const Library::SpeciesVariant> GetDisplayVariant() const noexcept;
ArbUt::OptionalBorrowedPtr<const Library::CreatureSpecies> GetDisplaySpecies() const noexcept;
ArbUt::OptionalBorrowedPtr<const Library::SpeciesVariant> GetDisplayVariant() const noexcept;
void SetDisplaySpecies(const ArbUt::BorrowedPtr<const Library::CreatureSpecies>& species) noexcept {
_displaySpecies = species;
_displaySpecies = species.GetRaw();
}
void SetDisplayVariant(ArbUt::BorrowedPtr<const Library::SpeciesVariant> variant) noexcept {
_displayVariant = variant;
_displayVariant = variant.GetRaw();
};
inline bool AllowedExperienceGain() const noexcept { return _allowedExperienceGain; }

View File

@@ -5,7 +5,7 @@
namespace CreatureLib::Battling {
class CreatureParty {
ArbUt::UniquePtrList<Creature> _party;
ArbUt::OptionalUniquePtrList<Creature> _party;
public:
CreatureParty(size_t size) noexcept : _party(size) {
@@ -18,7 +18,7 @@ namespace CreatureLib::Battling {
virtual ~CreatureParty() = default;
ArbUt::BorrowedPtr<Creature> GetAtIndex(size_t index) const noexcept { return _party[index]; }
ArbUt::OptionalBorrowedPtr<Creature> GetAtIndex(size_t index) const noexcept { return _party[index]; }
void Switch(size_t a, size_t b) noexcept { _party.Swap(a, b); }
@@ -42,8 +42,8 @@ namespace CreatureLib::Battling {
return false;
}
ArbUt::UniquePtrList<Creature>& GetParty() noexcept { return _party; }
const ArbUt::UniquePtrList<Creature>& GetParty() const noexcept { return _party; }
ArbUt::OptionalUniquePtrList<Creature>& GetParty() noexcept { return _party; }
const ArbUt::OptionalUniquePtrList<Creature>& GetParty() const noexcept { return _party; }
size_t GetLength() const noexcept { return _party.Count(); }

View File

@@ -35,10 +35,10 @@ namespace CreatureLib::Battling {
ArbUt::BorrowedPtr<Creature> _user;
ArbUt::BorrowedPtr<LearnedAttack> _attack;
std::unique_ptr<Script> _script = nullptr;
ArbUt::List<ArbUt::BorrowedPtr<Creature>> _targets;
ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>> _targets;
public:
ExecutingAttack(const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& targets, uint8_t numberHits,
ExecutingAttack(const ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>& targets, uint8_t numberHits,
ArbUt::BorrowedPtr<Creature> user, const ArbUt::BorrowedPtr<LearnedAttack>& attack,
const std::unique_ptr<Script>& script)
: _numberHits(numberHits), _hits(std::make_unique<HitData[]>(targets.Count() * numberHits)), _user(user),
@@ -55,7 +55,10 @@ namespace CreatureLib::Battling {
HitData& GetHitData(ArbUt::BorrowedPtr<Creature> creature, uint8_t hit) {
for (uint8_t i = 0; i < _targets.Count(); i++) {
if (_targets[i] == creature) {
if (!_targets[i].HasValue()) {
continue;
}
if (_targets[i].GetValue() == creature) {
return _hits[i * _numberHits + hit];
}
}
@@ -64,7 +67,10 @@ namespace CreatureLib::Battling {
HitData* GetTargetIteratorBegin(ArbUt::BorrowedPtr<Creature> creature) {
for (uint8_t i = 0; i < _targets.Count(); i++) {
if (_targets[i] == creature) {
if (!_targets[i].HasValue()) {
continue;
}
if (_targets[i].GetValue() == creature) {
return &_hits[i * _numberHits];
}
}
@@ -73,7 +79,10 @@ namespace CreatureLib::Battling {
bool IsCreatureTarget(ArbUt::BorrowedPtr<Creature> creature) noexcept {
for (uint8_t i = 0; i < _targets.Count(); i++) {
if (_targets[i] == creature) {
if (!_targets[i].HasValue()) {
continue;
}
if (_targets[i].GetValue() == creature) {
return true;
}
}
@@ -82,7 +91,7 @@ namespace CreatureLib::Battling {
inline uint8_t GetTargetCount() const noexcept { return _targets.Count(); }
inline const ArbUt::List<ArbUt::BorrowedPtr<Creature>>& GetTargets() const noexcept { return _targets; }
inline const ArbUt::List<ArbUt::OptionalBorrowedPtr<Creature>>& GetTargets() const noexcept { return _targets; }
inline uint8_t GetNumberOfHits() const noexcept { return _numberHits; }
inline const ArbUt::BorrowedPtr<Creature>& GetUser() noexcept { return _user; }

View File

@@ -45,14 +45,14 @@ namespace CreatureLib::Battling {
}
inline bool HasNext() { return _index < _size; }
ArbUt::BorrowedPtr<Script> GetNextNotNull() {
std::optional<ArbUt::BorrowedPtr<Script>> GetNextNotNull() {
while (HasNext()) {
auto s = GetNext();
if (s != nullptr) {
return s;
}
}
return nullptr;
return {};
}
ArbUt::BorrowedPtr<Script> GetNext() {

View File

@@ -27,14 +27,16 @@ namespace CreatureLib::Battling {
_lookup.Insert(script->GetName(), _scripts.Count() - 1);
}
ArbUt::BorrowedPtr<Script> Get(const ArbUt::BasicStringView& key) const { return Get(key.GetHash()); }
std::optional<ArbUt::BorrowedPtr<Script>> Get(const ArbUt::BasicStringView& key) const {
return Get(key.GetHash());
}
ArbUt::BorrowedPtr<Script> Get(uint32_t keyHash) const noexcept {
std::optional<ArbUt::BorrowedPtr<Script>> Get(uint32_t keyHash) const noexcept {
size_t v;
if (_lookup.TryGet(keyHash, v)) {
return _scripts[v];
}
return nullptr;
return {};
}
void Remove(const ArbUt::BasicStringView& key) { Remove(key.GetHash()); }

View File

@@ -22,9 +22,9 @@ namespace CreatureLib::Battling {
if (user == nullptr)
return;
auto battle = user->GetBattle();
if (battle != nullptr) {
if (battle.HasValue()) {
if (_attack->GetAttack()->HasSecondaryEffect()) {
auto library = battle->GetLibrary();
auto library = battle.GetValue()->GetLibrary();
auto& effect = _attack->GetAttack()->GetSecondaryEffect();
_attackScript =
std::unique_ptr<Script>(library->LoadScript(ScriptCategory::Attack, effect->GetEffectName()));

View File

@@ -4,15 +4,15 @@
#include "BaseTurnChoice.hpp"
namespace CreatureLib::Battling {
class SwitchTurnChoice : public BaseTurnChoice {
ArbUt::BorrowedPtr<Creature> _newCreature;
ArbUt::OptionalBorrowedPtr<Creature> _newCreature;
public:
SwitchTurnChoice(ArbUt::BorrowedPtr<Creature> user, ArbUt::BorrowedPtr<Creature> newCreature) noexcept
SwitchTurnChoice(ArbUt::BorrowedPtr<Creature> user, ArbUt::OptionalBorrowedPtr<Creature> newCreature) noexcept
: BaseTurnChoice(user), _newCreature(newCreature) {}
TurnChoiceKind GetKind() const noexcept final { return TurnChoiceKind::Switch; }
inline const ArbUt::BorrowedPtr<Creature>& GetNewCreature() const noexcept { return _newCreature; }
inline const ArbUt::OptionalBorrowedPtr<Creature>& GetNewCreature() const noexcept { return _newCreature; }
size_t ScriptCount() const override { return GetUser()->ScriptCount(); }
protected:

View File

@@ -36,9 +36,9 @@ namespace CreatureLib::Library {
return _distinctLevelAttacks;
}
ArbUt::BorrowedPtr<const AttackData> GetRandomAttack(ArbUt::Random& rand) const {
std::optional<ArbUt::BorrowedPtr<const AttackData>> GetRandomAttack(ArbUt::Random& rand) const {
if (_distinctLevelAttacks.Count() == 0) {
return nullptr;
return {};
}
auto val = rand.Get(_distinctLevelAttacks.Count());
auto it = _distinctLevelAttacks.begin();
@@ -64,7 +64,7 @@ namespace CreatureLib::Library {
LearnableAttacks::GetDistinctLevelAttacks() const noexcept {
return _impl->GetDistinctLevelAttacks();
}
ArbUt::BorrowedPtr<const AttackData> LearnableAttacks::GetRandomAttack(ArbUt::Random& rand) const {
std::optional<ArbUt::BorrowedPtr<const AttackData>> LearnableAttacks::GetRandomAttack(ArbUt::Random& rand) const {
return _impl->GetRandomAttack(rand);
}

View File

@@ -36,7 +36,7 @@ namespace CreatureLib::Library {
/// @brief Returns a random attack that can be learned.
/// @param rand A random number generator.
/// @return A random attack that can be learned.
virtual ArbUt::BorrowedPtr<const AttackData> GetRandomAttack(ArbUt::Random& rand) const;
virtual std::optional<ArbUt::BorrowedPtr<const AttackData>> GetRandomAttack(ArbUt::Random& rand) const;
};
}

View File

@@ -27,8 +27,7 @@
#include <Arbutils/Collections/List.hpp>
#include <Arbutils/Enum.hpp>
#include <Arbutils/Exception.hpp>
#include <Arbutils/Memory/BorrowedPtr.hpp>
#include <Arbutils/Memory/UniquePtrList.hpp>
#include <Arbutils/Memory/Memory.hpp>
#include <Arbutils/Precompiled.hxx>
#include <Arbutils/StringView.hpp>