1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

Do not allow visiting objects blocked by visit of another player

This commit is contained in:
Ivan Savenko 2023-09-20 00:05:11 +03:00
parent b807c3855b
commit 623fb2a63e
3 changed files with 34 additions and 6 deletions

View File

@ -1086,8 +1086,18 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
const TerrainTile t = *getTile(hmpos);
const int3 guardPos = gs->guardingCreaturePosition(hmpos);
CGObjectInstance * objectToVisit = nullptr;
CGObjectInstance * guardian = nullptr;
const bool embarking = !h->boat && !t.visitableObjects.empty() && t.visitableObjects.back()->ID == Obj::BOAT;
if (!t.visitableObjects.empty())
objectToVisit = t.visitableObjects.back();
if (isInTheMap(guardPos))
guardian = getTile(guardPos)->visitableObjects.back();
assert(guardian == nullptr || dynamic_cast<CGCreature*>(guardian) != nullptr);
const bool embarking = !h->boat && objectToVisit && objectToVisit->ID == Obj::BOAT;
const bool disembarking = h->boat
&& t.terType->isLand()
&& (dst == h->pos
@ -1110,7 +1120,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
const int cost = pathfinderHelper->getMovementCost(h->visitablePos(), hmpos, nullptr, nullptr, h->movementPointsRemaining());
const bool standAtObstacle = t.blocked && !t.visitable;
const bool standAtWater = !h->boat && t.terType->isWater() && (t.visitableObjects.empty() || !t.visitableObjects.back()->isCoastVisitable());
const bool standAtWater = !h->boat && t.terType->isWater() && (objectToVisit || !objectToVisit->isCoastVisitable());
const auto complainRet = [&](const std::string & message)
{
@ -1120,6 +1130,18 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
return false;
};
if (guardian && isVisitActiveForAny(guardian))
complainRet("Cannot move hero, destination monster is busy!");
if (objectToVisit && isVisitActiveForAny(objectToVisit))
complainRet("Cannot move hero, destination object is busy!");
if (objectToVisit &&
objectToVisit->getOwner().isValidPlayer() &&
getPlayerRelations(objectToVisit->getOwner(), h->getOwner()) == PlayerRelations::ENEMIES &&
!turnOrder->isContactAllowed(objectToVisit->getOwner(), h->getOwner()))
complainRet("Cannot move hero, destination player is busy!");
//it's a rock or blocked and not visitable tile
//OR hero is on land and dest is water and (there is not present only one object - boat)
if (!t.terType->isPassable() || (standAtObstacle && !canFly))
@ -1179,8 +1201,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
}
else if (lookForGuards == CHECK_FOR_GUARDS && isInTheMap(guardPos))
{
const TerrainTile &guardTile = *gs->getTile(guardPos);
objectVisited(guardTile.visitableObjects.back(), h);
objectVisited(guardian, h);
moveQuery->visitDestAfterVictory = visitDest==VISIT_DEST;
}
@ -1238,9 +1259,9 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
// visit town for town portal \ castle gates
// do not use generic visitObjectOnTile to avoid double-teleporting
// if this moveHero call was triggered by teleporter
if (!t.visitableObjects.empty())
if (objectToVisit)
{
if (CGTownInstance * town = dynamic_cast<CGTownInstance *>(t.visitableObjects.back()))
if (CGTownInstance * town = dynamic_cast<CGTownInstance *>(objectToVisit))
town->onHeroVisit(h);
}

View File

@ -90,6 +90,11 @@ bool TurnOrderProcessor::playersInContact(PlayerColor left, PlayerColor right) c
return false;
}
bool TurnOrderProcessor::isContactAllowed(PlayerColor active, PlayerColor waiting) const
{
return true;
}
bool TurnOrderProcessor::canActSimultaneously(PlayerColor active, PlayerColor waiting) const
{
const auto * activeInfo = gameHandler->getPlayerState(active, false);

View File

@ -53,6 +53,8 @@ class TurnOrderProcessor : boost::noncopyable
public:
TurnOrderProcessor(CGameHandler * owner);
bool isContactAllowed(PlayerColor left, PlayerColor right) const;
/// Add new player to handle (e.g. on game start)
void addPlayer(PlayerColor which);