فهرست منبع

VCAI: add channel probing support for teleporters with multiple exits

ArseniyShestakov 10 سال پیش
والد
کامیت
2f9ca778b2
2فایلهای تغییر یافته به همراه24 افزوده شده و 16 حذف شده
  1. 23 15
      AI/VCAI/VCAI.cpp
  2. 1 1
      server/CGameHandler.cpp

+ 23 - 15
AI/VCAI/VCAI.cpp

@@ -625,22 +625,29 @@ void VCAI::showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exit
 	int choosenExit = -1;
 	if(impassable)
 		knownTeleportChannels[channel]->passability = TeleportChannel::IMPASSABLE;
-	else
+	else if(destinationTeleport != ObjectInstanceID() && destinationTeleportPos.valid())
 	{
 		auto neededExit = std::make_pair(destinationTeleport, destinationTeleportPos);
 		if(destinationTeleport != ObjectInstanceID() && vstd::contains(exits, neededExit))
 			choosenExit = vstd::find_pos(exits, neededExit);
+	}
 
-		if(!status.channelProbing())
+	for(auto exit : exits)
+	{
+		if(status.channelProbing() && exit.first == destinationTeleport)
 		{
-			for(auto exit : exits)
+			choosenExit = vstd::find_pos(exits, exit);
+			break;
+		}
+		else
+		{
+			// FIXME: This code generate "Object is not visible." errors
+			// What is better way to check that certain teleport exit wasn't visited yet or not visible?
+			if(!vstd::contains(visitableObjs, cb->getObj(exit.first)) &&
+				!vstd::contains(teleportChannelProbingList, exit.first) &&
+				exit.first != destinationTeleport)
 			{
-				if(!vstd::contains(visitableObjs, cb->getObj(exit.first)) &&
-					!vstd::contains(teleportChannelProbingList, exit.first) &&
-					exit.first != destinationTeleport)
-				{
-					teleportChannelProbingList.push_back(exit.first);
-				}
+				teleportChannelProbingList.push_back(exit.first);
 			}
 		}
 	}
@@ -1867,11 +1874,11 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
 			cb->moveHero(*h, CGHeroInstance::convertPosition(dst, true), transit);
 		};
 
-		auto doTeleportMovement = [&](int3 dst, ObjectInstanceID exitId)
+		auto doTeleportMovement = [&](ObjectInstanceID exitId, int3 exitPos)
 		{
 			destinationTeleport = exitId;
-			destinationTeleportPos = CGHeroInstance::convertPosition(dst, true);
-			cb->moveHero(*h, destinationTeleportPos);
+			destinationTeleportPos = CGHeroInstance::convertPosition(exitPos, true);
+			cb->moveHero(*h, h->pos);
 			destinationTeleport = ObjectInstanceID();
 			destinationTeleportPos = int3();
 			afterMovementCheck();
@@ -1880,13 +1887,14 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
 		auto doChannelProbing = [&]() -> void
 		{
 			auto currentExit = getObj(CGHeroInstance::convertPosition(h->pos,false), false);
+			auto currentExitPos = CGHeroInstance::convertPosition(h->pos,false);
 			assert(currentExit);
 
 			status.setChannelProbing(true);
 			for(auto exit : teleportChannelProbingList)
-				doTeleportMovement(CGHeroInstance::convertPosition(h->pos,false), exit);
+				doTeleportMovement(exit, int3());
 			teleportChannelProbingList.clear();
-			doTeleportMovement(CGHeroInstance::convertPosition(h->pos,false), currentExit->id);
+			doTeleportMovement(currentExit->id, currentExitPos);
 			status.setChannelProbing(false);
 		};
 
@@ -1900,7 +1908,7 @@ bool VCAI::moveHeroToTile(int3 dst, HeroPtr h)
 			auto nextObject = getObj(nextCoord, false);
 			if(CGTeleport::isConnected(currentObject, nextObject))
 			{ //we use special login if hero standing on teleporter it's mean we need
-				doTeleportMovement(currentCoord, nextObject->id);
+				doTeleportMovement(nextObject->id, nextCoord);
 				if(teleportChannelProbingList.size())
 					doChannelProbing();
 

+ 1 - 1
server/CGameHandler.cpp

@@ -1755,7 +1755,7 @@ bool CGameHandler::moveHero( ObjectInstanceID hid, int3 dst, ui8 teleporting, bo
 	}
 
     logGlobal->traceStream() << "Player " << asker << " wants to move hero "<< hid.getNum() << " from "<< h->pos << " to " << dst;
-	const int3 hmpos = dst + int3(-1,0,0);
+	const int3 hmpos = CGHeroInstance::convertPosition(dst, false);
 
 	if(!gs->map->isInTheMap(hmpos))
 	{