浏览代码

found a bug in code where AI can change client gamestate directly causing sorting crash

Andrii Danylchenko 4 年之前
父节点
当前提交
ade84699b0
共有 4 个文件被更改,包括 17 次插入23 次删除
  1. 1 0
      AI/BattleAI/BattleAI.cpp
  2. 7 2
      AI/BattleAI/StackWithBonuses.cpp
  3. 1 1
      client/CPlayerInterface.cpp
  4. 8 20
      lib/battle/BattleInfo.cpp

+ 1 - 0
AI/BattleAI/BattleAI.cpp

@@ -578,6 +578,7 @@ void CBattleAI::attemptCastingSpell()
 		size_t minTurnSpan = ourUnits/3; //todo: tweak this
 
 		std::vector<battle::Units> newTurnOrder;
+
 		state.battleGetTurnOrder(newTurnOrder, amount, 2);
 
 		const bool turnSpanOK = evaluateQueue(newValueOfStack, newTurnOrder, &state, minTurnSpan, nullptr);

+ 7 - 2
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;
+			}
 		}
 	}
 }

+ 1 - 1
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;

+ 8 - 20
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);