Fixes invalid pointers to a battle dangling when a battle is removed.
continuous-integration/drone/push Build is passing Details

Signed-off-by: Deukhoofd <Deukhoofd@gmail.com>
This commit is contained in:
Deukhoofd 2020-12-28 13:40:39 +01:00
parent 69476b6f9d
commit a284641b5a
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
7 changed files with 26 additions and 11 deletions

View File

@ -84,4 +84,6 @@ export uint8_t CreatureLib_Battle_RegisterEventListener(Battle* p, void (*func)(
} }
export const HistoryHolder* CreatureLib_Battle_GetHistory(Battle* p) { return &p->GetHistory(); } export const HistoryHolder* CreatureLib_Battle_GetHistory(Battle* p) { return &p->GetHistory(); }
export uint8_t CreatureLib_Battle_EndBattle(Battle* p) { Try(p->EndBattle()) }
SIMPLE_GET_FUNC(Battle, GetLastTurnTimeMicroseconds, long); SIMPLE_GET_FUNC(Battle, GetLastTurnTimeMicroseconds, long);

View File

@ -6,11 +6,11 @@
using namespace CreatureLib::Battling; using namespace CreatureLib::Battling;
void TurnHandler::RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue) { void TurnHandler::RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue, ArbUt::BorrowedPtr<Battle> battle) {
for (auto choice : queue->GetInnerQueue()) { for (auto choice : queue->GetInnerQueue()) {
HOOK(OnBeforeTurn, choice, choice.get()); HOOK(OnBeforeTurn, choice, choice.get());
} }
while (queue->HasNext()) { while (queue->HasNext() && !battle->HasEnded()) {
auto item = queue->Dequeue(); auto item = queue->Dequeue();
EnsureNotNull(item) EnsureNotNull(item)
Ensure(item->GetUser()->GetBattle().HasValue()) Ensure(item->GetUser()->GetBattle().HasValue())

View File

@ -20,7 +20,7 @@ namespace CreatureLib::Battling {
static void ExecuteFleeChoice(ArbUt::BorrowedPtr<FleeTurnChoice> choice); static void ExecuteFleeChoice(ArbUt::BorrowedPtr<FleeTurnChoice> choice);
public: public:
static void RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue); static void RunTurn(ArbUt::BorrowedPtr<ChoiceQueue> queue, ArbUt::BorrowedPtr<Battle> battle);
}; };
} }

View File

@ -79,7 +79,7 @@ void Battle::CheckChoicesSetAndRun() {
this->_currentTurnQueue = std::make_unique<ChoiceQueue>(choices); this->_currentTurnQueue = std::make_unique<ChoiceQueue>(choices);
TriggerEventListener<TurnStartEvent>(); TriggerEventListener<TurnStartEvent>();
try { try {
TurnHandler::RunTurn(this->_currentTurnQueue); TurnHandler::RunTurn(this->_currentTurnQueue, this);
} catch (const ArbUt::Exception& e) { } catch (const ArbUt::Exception& e) {
throw e; throw e;
} catch (const std::exception& e) { } catch (const std::exception& e) {
@ -133,7 +133,7 @@ void Battle::ValidateBattleState() {
auto side = _sides[i]; auto side = _sides[i];
if (side->HasFled()) { if (side->HasFled()) {
this->_battleResult = BattleResult::Inconclusive(); this->_battleResult = BattleResult::Inconclusive();
this->_hasEnded = true; EndBattle();
return; return;
} }
if (!side->IsDefeated()) { if (!side->IsDefeated()) {
@ -146,11 +146,11 @@ void Battle::ValidateBattleState() {
} }
if (!survivingSideExists) { if (!survivingSideExists) {
this->_battleResult = BattleResult::Inconclusive(); this->_battleResult = BattleResult::Inconclusive();
this->_hasEnded = true; EndBattle();
return; return;
} }
this->_battleResult = BattleResult::Conclusive(winningSide); this->_battleResult = BattleResult::Conclusive(winningSide);
this->_hasEnded = true; EndBattle();
} }
void Battle::AddVolatileScript(const ArbUt::StringView& key) { void Battle::AddVolatileScript(const ArbUt::StringView& key) {
auto script = _volatile.Get(key); auto script = _volatile.Get(key);

View File

@ -116,6 +116,18 @@ namespace CreatureLib::Battling {
const HistoryHolder& GetHistory() const noexcept { return _historyHolder; } const HistoryHolder& GetHistory() const noexcept { return _historyHolder; }
long GetLastTurnTimeMicroseconds() const noexcept { return _lastTurnTime; } long GetLastTurnTimeMicroseconds() const noexcept { return _lastTurnTime; }
void EndBattle() {
this->_hasEnded = true;
for (size_t i = 0; i < _numberOfSides; i++) {
auto side = _sides[i];
for (auto c : side->GetCreatures()) {
if (c.HasValue()) {
c.GetValue()->ClearBattleData();
}
}
}
}
}; };
} }

View File

@ -100,8 +100,10 @@ namespace CreatureLib::Battling {
_side = side.GetRaw(); _side = side.GetRaw();
this->ResetActiveScripts(); this->ResetActiveScripts();
} }
void Creature::ClearBattleData() noexcept {
// region Stat APIs _battle = nullptr;
_side = nullptr;
}
bool Creature::ChangeStatBoost(Library::Statistic stat, int8_t diffAmount) { bool Creature::ChangeStatBoost(Library::Statistic stat, int8_t diffAmount) {
bool changed = false; bool changed = false;
@ -133,8 +135,6 @@ namespace CreatureLib::Battling {
this->_boostedStats.SetStat(stat, s); this->_boostedStats.SetStat(stat, s);
} }
// endregion
const ArbUt::OptionalBorrowedPtr<Battle>& Creature::GetBattle() const { return _battle; } const ArbUt::OptionalBorrowedPtr<Battle>& Creature::GetBattle() const { return _battle; }
const ArbUt::OptionalBorrowedPtr<BattleSide>& Creature::GetBattleSide() const { return _side; } const ArbUt::OptionalBorrowedPtr<BattleSide>& Creature::GetBattleSide() const { return _side; }

View File

@ -105,6 +105,7 @@ namespace CreatureLib::Battling {
inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; } inline uint32_t GetCurrentHealth() const noexcept { return _currentHealth; }
void SetBattleData(const ArbUt::BorrowedPtr<Battle>& battle, const ArbUt::BorrowedPtr<BattleSide>& side); void SetBattleData(const ArbUt::BorrowedPtr<Battle>& battle, const ArbUt::BorrowedPtr<BattleSide>& side);
void ClearBattleData() noexcept;
const ArbUt::OptionalBorrowedPtr<Battle>& GetBattle() const; const ArbUt::OptionalBorrowedPtr<Battle>& GetBattle() const;
const ArbUt::OptionalBorrowedPtr<BattleSide>& GetBattleSide() const; const ArbUt::OptionalBorrowedPtr<BattleSide>& GetBattleSide() const;
inline void SetOnBattleField(bool value) { _onBattleField = value; } inline void SetOnBattleField(bool value) { _onBattleField = value; }