From ade84699b0f9aa36888a769050010b91aa0c905d Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Sat, 30 Jan 2021 14:13:45 +0200 Subject: [PATCH] found a bug in code where AI can change client gamestate directly causing sorting crash --- AI/BattleAI/BattleAI.cpp | 1 + AI/BattleAI/StackWithBonuses.cpp | 9 +++++++-- client/CPlayerInterface.cpp | 2 +- lib/battle/BattleInfo.cpp | 28 ++++++++-------------------- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/AI/BattleAI/BattleAI.cpp b/AI/BattleAI/BattleAI.cpp index 2eaf2f8eb..331bc68d5 100644 --- a/AI/BattleAI/BattleAI.cpp +++ b/AI/BattleAI/BattleAI.cpp @@ -578,6 +578,7 @@ void CBattleAI::attemptCastingSpell() size_t minTurnSpan = ourUnits/3; //todo: tweak this std::vector newTurnOrder; + state.battleGetTurnOrder(newTurnOrder, amount, 2); const bool turnSpanOK = evaluateQueue(newValueOfStack, newTurnOrder, &state, minTurnSpan, nullptr); diff --git a/AI/BattleAI/StackWithBonuses.cpp b/AI/BattleAI/StackWithBonuses.cpp index 6d98e2ce0..2c1a0cd79 100644 --- a/AI/BattleAI/StackWithBonuses.cpp +++ b/AI/BattleAI/StackWithBonuses.cpp @@ -14,11 +14,16 @@ void actualizeEffect(TBonusListPtr target, const Bonus & ef) { - for(auto bonus : *target) //TODO: optimize + for(auto & bonus : *target) //TODO: optimize { if(bonus->source == Bonus::SPELL_EFFECT && bonus->type == ef.type && bonus->subtype == ef.subtype) { - bonus->turnsRemain = std::max(bonus->turnsRemain, ef.turnsRemain); + if(bonus->turnsRemain < ef.turnsRemain) + { + bonus.reset(new Bonus(*bonus)); + + bonus->turnsRemain = ef.turnsRemain; + } } } } diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 3e22682b1..f66f9221b 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -137,7 +137,7 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player) CPlayerInterface::~CPlayerInterface() { - CCS->soundh->ambientStopAllChannels(); + if(CCS->soundh) CCS->soundh->ambientStopAllChannels(); logGlobal->trace("\tHuman player interface for player %s being destructed", playerID.getStr()); delete showingDialog; delete cingconsole; diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index 65278f443..6590ce55c 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -1066,33 +1066,21 @@ bool CMP_stack::operator()(const battle::Unit * a, const battle::Unit * b) { case 0: //catapult moves after turrets return a->creatureIndex() > b->creatureIndex(); //catapult is 145 and turrets are 149 - case 1: //fastest first, upper slot first - { - int as = a->getInitiative(turn), bs = b->getInitiative(turn); - if(as != bs) - return as > bs; - - if (a->unitSide() == b->unitSide()) - return a->unitSlot() < b->unitSlot(); - else if (a->unitSide() == side || b->unitSide() == side) - return a->unitSide() != side; - //FIXME: what about summoned stacks - - return std::addressof(a) > std::addressof(b); - } - case 2: //fastest last, upper slot first - case 3: //fastest last, upper slot first + case 1: + case 2: + case 3: { int as = a->getInitiative(turn), bs = b->getInitiative(turn); + if(as != bs) return as > bs; if(a->unitSide() == b->unitSide()) return a->unitSlot() < b->unitSlot(); - else if (a->unitSide() == side || b->unitSide() == side) - return a->unitSide() != side; - - return std::addressof(a) > std::addressof(b); + + return (a->unitSide() == side || b->unitSide() == side) + ? a->unitSide() != side + : a->unitSide() < b->unitSide(); } default: assert(false);