فهرست منبع

Fixed #1055 - hang when creature performed automatic (not controleld by player) action.
Fixed possible crash on arrow turret turn.

Michał W. Urbańczyk 13 سال پیش
والد
کامیت
a14f381d48
5فایلهای تغییر یافته به همراه41 افزوده شده و 23 حذف شده
  1. 3 0
      client/NetPacksClient.cpp
  2. 3 0
      lib/CBattleCallback.cpp
  3. 8 2
      lib/NetPacks.h
  4. 25 20
      server/CGameHandler.cpp
  5. 2 1
      server/CGameHandler.h

+ 3 - 0
client/NetPacksClient.cpp

@@ -589,6 +589,9 @@ void BattleNextRound::applyCl( CClient *cl )
 
 void BattleSetActiveStack::applyCl( CClient *cl )
 {
+	if(!askPlayerInterface)
+		return;
+
 	const CStack * activated = GS(cl)->curB->battleGetStackByID(stack);
 	int playerToCall = -1; //player that will move activated stack
 	if( activated->hasBonusOfType(Bonus::HYPNOTIZED) )

+ 3 - 0
lib/CBattleCallback.cpp

@@ -1088,6 +1088,9 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo &accessibi
 	ret.predecessors.fill(BattleHex::INVALID);
 	ret.distances.fill(ReachabilityInfo::INFINITE_DIST);
 
+	if(!params.startPosition.isValid()) //if got call for arrow turrets
+		return ret;
+
 	const std::set<BattleHex> quicksands = getStoppers(params.perspective);
 	//const bool twoHexCreature = params.doubleWide;
 

+ 8 - 2
lib/NetPacks.h

@@ -1288,15 +1288,21 @@ struct BattleNextRound : public CPackForClient//3001
 };
 struct BattleSetActiveStack : public CPackForClient//3002
 {
-	BattleSetActiveStack(){type = 3002;};
+	BattleSetActiveStack()
+	{
+		type = 3002;
+		askPlayerInterface = true;
+	}
+
 	void applyCl(CClient *cl);
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	ui32 stack;
+	ui8 askPlayerInterface;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & stack;
+		h & stack & askPlayerInterface;
 	}
 };
 struct BattleResult : public CPackForClient//3003

+ 25 - 20
server/CGameHandler.cpp

@@ -1550,8 +1550,10 @@ void CGameHandler::setupBattle( int3 tile, const CArmedInstance *armies[2], cons
 	sendAndApply(&bs);
 }
 
-void CGameHandler::checkForBattleEnd( std::vector<CStack*> &stacks )
+void CGameHandler::checkForBattleEnd()
 {
+	auto &stacks = gs->curB->stacks;
+
 	//checking winning condition
 	bool hasStack[2]; //hasStack[0] - true if attacker has a living stack; defender similarly
 	hasStack[0] = hasStack[1] = false;
@@ -3248,6 +3250,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
 	switch(ba.actionType)
 	{
 	case BattleAction::END_TACTIC_PHASE: //wait
+	case BattleAction::BAD_MORALE:
 		{
 			StartAction start_action(ba);
 			sendAndApply(&start_action);
@@ -4424,7 +4427,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 				{
 					battleMadeAction.setn(true);
 				}
-				checkForBattleEnd(gs->curB->stacks);
+				checkForBattleEnd();
 				if(battleResult.get())
 				{
 					battleMadeAction.setn(true);
@@ -5588,15 +5591,13 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
 void CGameHandler::makeStackDoNothing(const CStack * next)
 {
 	BattleAction doNothing;
-	doNothing.actionType = 0;
+	doNothing.actionType = BattleAction::NO_ACTION;
 	doNothing.additionalInfo = 0;
 	doNothing.destinationTile = -1;
 	doNothing.side = !next->attackerOwned;
 	doNothing.stackNumber = next->ID;
 
-	StartAction start_action(doNothing);
-	sendAndApply(&start_action);
-	sendAndApply(&end_action);
+	makeAutomaticAction(next, doNothing);
 }
 
 bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count)
@@ -5809,10 +5810,7 @@ void CGameHandler::runBattle()
 					ba.side = !next->attackerOwned;
 					ba.stackNumber = next->ID;
 
-					StartAction start_action(ba);
-					sendAndApply(&start_action);
-					sendAndApply(&end_action);
-					checkForBattleEnd(stacks); //check if this "action" ended the battle (not likely but who knows...)
+					makeAutomaticAction(next, ba);
 					continue;
 				}
 			}
@@ -5826,13 +5824,10 @@ void CGameHandler::runBattle()
 					attack.actionType = BattleAction::WALK_AND_ATTACK;
 					attack.side = !next->attackerOwned;
 					attack.stackNumber = next->ID;
-
 					attack.additionalInfo = attackInfo.first->position;
 					attack.destinationTile = attackInfo.second;
 
-					makeBattleAction(attack);
-
-					checkForBattleEnd(stacks);
+					makeAutomaticAction(next, attack);
 				}
 				else
 				{
@@ -5860,9 +5855,7 @@ void CGameHandler::runBattle()
 					}
 				}
 
-				makeBattleAction(attack);
-
-				checkForBattleEnd(stacks);
+				makeAutomaticAction(next, attack);
 				continue;
 			}
 
@@ -5877,7 +5870,7 @@ void CGameHandler::runBattle()
 				attack.side = !next->attackerOwned;
 				attack.stackNumber = next->ID;
 
-				makeBattleAction(attack);
+				makeAutomaticAction(next, attack);
 				continue;
 			}
 
@@ -5908,8 +5901,8 @@ void CGameHandler::runBattle()
 					heal.destinationTile = toBeHealed->position;
 					heal.side = !next->attackerOwned;
 					heal.stackNumber = next->ID;
-					makeBattleAction(heal);
 
+					makeAutomaticAction(next, heal);
 					continue;
 				}
 			}
@@ -5947,7 +5940,7 @@ void CGameHandler::runBattle()
 				}
 
 				//we're after action, all results applied
-				checkForBattleEnd(stacks); //check if this action ended the battle
+				checkForBattleEnd(); //check if this action ended the battle
 
 				//check for good morale
 				nextStackMorale = next->MoraleVal();
@@ -5988,6 +5981,18 @@ void CGameHandler::runBattle()
 	endBattle(gs->curB->tile, gs->curB->heroes[0], gs->curB->heroes[1]);
 }
 
+bool CGameHandler::makeAutomaticAction(const CStack *stack, BattleAction &ba)
+{
+	BattleSetActiveStack bsa;
+	bsa.stack = stack->ID;
+	bsa.askPlayerInterface = false;
+	sendAndApply(&bsa);
+
+	bool ret = makeBattleAction(ba);
+	checkForBattleEnd();
+	return ret;
+}
+
 void CGameHandler::giveHeroArtifact(const CGHeroInstance *h, const CArtifactInstance *a, int pos)
 {
 	assert(a->artType);

+ 2 - 1
server/CGameHandler.h

@@ -119,7 +119,7 @@ public:
 	void endBattle(int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2); //ends battle
 	void prepareAttack(BattleAttack &bat, const CStack *att, const CStack *def, int distance, int targetHex); //distance - number of hexes travelled before attacking
 	void applyBattleEffects(BattleAttack &bat, const CStack *att, const CStack *def, int distance, bool secondary); //damage, drain life & fire shield
-	void checkForBattleEnd( std::vector<CStack*> &stacks );
+	void checkForBattleEnd();
 	void setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance *heroes[2], bool creatureBank, const CGTownInstance *town);
 	void setBattleResult(int resultType, int victoriusSide);
 
@@ -197,6 +197,7 @@ public:
 
 	void playerMessage( ui8 player, const std::string &message);
 	bool makeBattleAction(BattleAction &ba);
+	bool makeAutomaticAction(const CStack *stack, BattleAction &ba); //used when action is taken by stack without volition of player (eg. unguided catapult attack)
 	void handleSpellCasting(int spellID, int spellLvl, BattleHex destination, ui8 casterSide, ui8 casterColor, const CGHeroInstance * caster, const CGHeroInstance * secHero,
 		int usedSpellPower, ECastingMode::ECastingMode mode, const CStack * stack, si32 selectedStack = -1);
 	bool makeCustomAction(BattleAction &ba);