Browse Source

Merge branch 'issue/2033' into develop

AlexVinS 10 years ago
parent
commit
728dac3b47
1 changed files with 69 additions and 31 deletions
  1. 69 31
      server/CGameHandler.cpp

+ 69 - 31
server/CGameHandler.cpp

@@ -1020,50 +1020,76 @@ int CGameHandler::moveStack(int stack, BattleHex dest)
 	}
 	else //for non-flying creatures
 	{
-		// send one package with the creature path information
-
-		shared_ptr<const CObstacleInstance> obstacle; //obstacle that interrupted movement
+		shared_ptr<const CObstacleInstance> obstacle, obstacle2; //obstacle that interrupted movement
 		std::vector<BattleHex> tiles;
-		int tilesToMove = std::max((int)(path.first.size() - creSpeed), 0);
+		const int tilesToMove = std::max((int)(path.first.size() - creSpeed), 0);
 		int v = path.first.size()-1;
 
-startWalking:
-		for(; v >= tilesToMove; --v)
+		bool stackIsMoving = true;
+		
+		while(stackIsMoving)
 		{
-			BattleHex hex = path.first[v];
-			tiles.push_back(hex);
-
-			if((obstacle = battleGetObstacleOnPos(hex, false)))
+			if(v<tilesToMove)
 			{
-				//we walked onto something, so we finalize this portion of stack movement check into obstacle
+				logGlobal->error("Movement terminated abnormally");
 				break;
 			}
-		}
 
-		if (tiles.size() > 0)
-		{
-			//commit movement
-			BattleStackMoved sm;
-			sm.stack = curStack->ID;
-			sm.distance = path.second;
-			sm.teleporting = false;
-			sm.tilesToMove = tiles;
-			sendAndApply(&sm);
-		}
+			for(bool obstacleHit = false; (!obstacleHit) && (v >= tilesToMove); --v)
+			{
+				BattleHex hex = path.first[v];
+				tiles.push_back(hex);
 
-		//we don't handle obstacle at the destination tile -> it's handled separately in the if at the end
-		if(obstacle && curStack->position != dest)
-		{
-			handleDamageFromObstacle(*obstacle, curStack);
+				//if we walked onto something, finalize this portion of stack movement check into obstacle
+				if((obstacle = battleGetObstacleOnPos(hex, false)))
+					obstacleHit = true;
+
+				if(curStack->doubleWide())
+				{
+					BattleHex otherHex = curStack->occupiedHex(hex);
+
+					//two hex creature hit obstacle by backside
+					if(otherHex.isValid() && ((obstacle2 = battleGetObstacleOnPos(otherHex, false))))
+						obstacleHit = true;
+				}
+			}
 
-			//if stack didn't die in explosion, continue movement
-			if(!obstacle->stopsMovement() && curStack->alive())
+			if(tiles.size() > 0)
 			{
-				obstacle.reset();
+				//commit movement
+				BattleStackMoved sm;
+				sm.stack = curStack->ID;
+				sm.distance = path.second;
+				sm.teleporting = false;
+				sm.tilesToMove = tiles;
+				sendAndApply(&sm);
 				tiles.clear();
-				v--;
-				goto startWalking; //TODO it's so evil
 			}
+
+			//we don't handle obstacle at the destination tile -> it's handled separately in the if at the end
+			if(curStack->position != dest)
+			{
+				auto processObstacle = [&](shared_ptr<const CObstacleInstance> & obs)
+				{
+					if(obs)
+					{
+						handleDamageFromObstacle(*obs, curStack);
+
+						//if stack die in explosion or interrupted by obstacle, abort movement
+						if(obs->stopsMovement() || !curStack->alive())
+							stackIsMoving = false;
+
+						obs.reset();						
+					}
+				};
+				
+				processObstacle(obstacle);
+				if(curStack->alive())
+					processObstacle(obstacle2);
+			}
+			else
+				//movement finished normally: we reached destination
+				stackIsMoving = false;
 		}
 	}
 
@@ -1075,6 +1101,18 @@ startWalking:
 			handleDamageFromObstacle(*theLastObstacle, curStack);
 		}
 	}
+
+	if(curStack->alive() && curStack->doubleWide())
+	{
+		BattleHex otherHex = curStack->occupiedHex(curStack->position);
+		
+		if(otherHex.isValid())
+			if(auto theLastObstacle = battleGetObstacleOnPos(otherHex, false))
+			{
+				//two hex creature hit obstacle by backside
+				handleDamageFromObstacle(*theLastObstacle, curStack);
+			}
+	}	
 	return ret;
 }