Просмотр исходного кода

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

Michał W. Urbańczyk 13 лет назад
Родитель
Сommit
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);