Ver código fonte

- Fixed mantis #1576 (doesn't hang game)
- Implemented output stream operator<< for various classes(BattleAction, BattleHex,...) to improve debugging and logging

beegee1 12 anos atrás
pai
commit
e01ef8e36a

+ 1 - 0
client/Client.cpp

@@ -118,6 +118,7 @@ void CClient::waitForMoveAndSend(PlayerColor color)
 		setThreadName("CClient::waitForMoveAndSend");
 		assert(vstd::contains(battleints, color));
 		BattleAction ba = battleints[color]->activeStack(gs->curB->battleGetStackByID(gs->curB->activeStack, false));
+		logNetwork->traceStream() << "Send battle action to server: " << ba;
 		MakeAction temp_action(ba);
 		sendRequest(&temp_action, color);
 		return;

+ 19 - 4
client/battle/CBattleInterface.cpp

@@ -118,12 +118,14 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 	strongInterest = true;
 	givenCommand = new CondSh<BattleAction *>(nullptr);
 
-	if(attackerInt && attackerInt->cb->battleGetTacticDist()) //hot-seat -> check tactics for both players (defender may be local human)
+	//hot-seat -> check tactics for both players (defender may be local human)
+	if(attackerInt && attackerInt->cb->battleGetTacticDist())
 		tacticianInterface = attackerInt;
 	else if(defenderInt && defenderInt->cb->battleGetTacticDist())
 		tacticianInterface = defenderInt;
 
-	tacticsMode = static_cast<bool>(tacticianInterface);  //if we found interface of player with tactics, then enter tactics mode
+	//if we found interface of player with tactics, then enter tactics mode
+	tacticsMode = static_cast<bool>(tacticianInterface);
 
 	//create stack queue
 	bool embedQueue = screen->h < 700;
@@ -2848,11 +2850,24 @@ void CBattleInterface::requestAutofightingAIToTakeAction()
 
 	boost::thread aiThread([&] 
 	{
-		auto  ba = new BattleAction(curInt->autofightingAI->activeStack(activeStack));
+		auto ba = new BattleAction(curInt->autofightingAI->activeStack(activeStack));
 
 		if(curInt->isAutoFightOn)
 		{
-			givenCommand->setn(ba);
+			if(tacticsMode)
+			{
+				// Always end tactics mode. Player interface is blocked currently, so it's not possible that
+				// the AI can take any action except end tactics phase (AI actions won't be triggered)
+				//TODO implement the possibility that the AI will be triggered for further actions
+				//TODO any solution to merge tactics phase & normal phase in the way it is handled by the player and battle interface?
+				setActiveStack(nullptr);
+				blockUI(true);
+				tacticsMode = false;
+			}
+			else
+			{
+				givenCommand->setn(ba);
+			}
 		}
 		else
 		{

+ 9 - 0
lib/BattleAction.cpp

@@ -92,3 +92,12 @@ BattleAction BattleAction::makeEndOFTacticPhase(ui8 side)
 	ba.actionType = END_TACTIC_PHASE;
 	return ba;
 }
+
+std::ostream & operator<<(std::ostream & os, const BattleAction & ba)
+{
+	std::stringstream actionTypeStream;
+	actionTypeStream << ba.actionType;
+
+	return os << boost::str(boost::format("[BattleAction: side '%d', stackNumber '%d', actionType '%s', destinationTile '%s', additionalInfo '%d', selectedStack '%d']")
+			% static_cast<int>(ba.side) % ba.stackNumber % actionTypeStream.str() % ba.destinationTile % ba.additionalInfo % ba.selectedStack);
+}

+ 2 - 0
lib/BattleAction.h

@@ -40,3 +40,5 @@ struct DLL_LINKAGE BattleAction
 	static BattleAction makeMove(const CStack *stack, BattleHex dest);
 	static BattleAction makeEndOFTacticPhase(ui8 side);
 };
+
+std::ostream & operator<<(std::ostream & os, const BattleAction & ba);

+ 5 - 0
lib/BattleHex.cpp

@@ -158,3 +158,8 @@ BattleHex BattleHex::getClosestTile(bool attackerOwned, BattleHex initialPos, st
 
 	return sortedTiles.front();
 }
+
+std::ostream & operator<<(std::ostream & os, const BattleHex & hex)
+{
+	return os << boost::str(boost::format("[BattleHex: x '%d', y '%d', hex '%d']") % hex.getX() % hex.getY() % hex.hex);
+}

+ 3 - 1
lib/BattleHex.h

@@ -112,4 +112,6 @@ struct DLL_LINKAGE BattleHex
 
 	bool isAvailable() const; //valid position not in first or last column
 	static BattleHex getClosestTile(bool attackerOwned, BattleHex initialPos, std::set<BattleHex> & possibilities); //TODO: vector or set? copying one to another is bad
-};
+};
+
+std::ostream & operator<<(std::ostream & os, const BattleHex & hex);

+ 25 - 0
lib/GameConstants.cpp

@@ -103,3 +103,28 @@ bool PlayerColor::isValidPlayer() const
 {
 	return num < PLAYER_LIMIT_I;
 }
+
+std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType)
+{
+	static const std::map<Battle::ActionType, std::string> actionTypeToString = boost::assign::map_list_of
+			(Battle::END_TACTIC_PHASE, "End tactic phase")
+			(Battle::INVALID, "Invalid")
+			(Battle::NO_ACTION, "No action")
+			(Battle::HERO_SPELL, "Hero spell")
+			(Battle::WALK, "Walk")
+			(Battle::DEFEND, "Defend")
+			(Battle::RETREAT, "Retreat")
+			(Battle::SURRENDER, "Surrender")
+			(Battle::WALK_AND_ATTACK, "Walk and attack")
+			(Battle::SHOOT, "Shoot")
+			(Battle::WAIT, "Wait")
+			(Battle::CATAPULT, "Catapult")
+			(Battle::MONSTER_SPELL, "Monster spell")
+			(Battle::BAD_MORALE, "Bad morale")
+			(Battle::STACK_HEAL, "Stack heal")
+			(Battle::DAEMON_SUMMONING, "Daemon summoning");
+
+	auto it = actionTypeToString.find(actionType);
+	if (it == actionTypeToString.end()) return os << "<Unknown type>";
+	else return os << it->second;
+}

+ 2 - 0
lib/GameConstants.h

@@ -682,6 +682,8 @@ namespace Battle
 	};
 }
 
+std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType);
+
 class ETerrainType
 {
 public: