1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-17 00:07:41 +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 TerrainTile t = *getTile(hmpos);
const int3 guardPos = gs->guardingCreaturePosition(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 const bool disembarking = h->boat
&& t.terType->isLand() && t.terType->isLand()
&& (dst == h->pos && (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 int cost = pathfinderHelper->getMovementCost(h->visitablePos(), hmpos, nullptr, nullptr, h->movementPointsRemaining());
const bool standAtObstacle = t.blocked && !t.visitable; 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) const auto complainRet = [&](const std::string & message)
{ {
@ -1120,6 +1130,18 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
return false; 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 //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) //OR hero is on land and dest is water and (there is not present only one object - boat)
if (!t.terType->isPassable() || (standAtObstacle && !canFly)) 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)) else if (lookForGuards == CHECK_FOR_GUARDS && isInTheMap(guardPos))
{ {
const TerrainTile &guardTile = *gs->getTile(guardPos); objectVisited(guardian, h);
objectVisited(guardTile.visitableObjects.back(), h);
moveQuery->visitDestAfterVictory = visitDest==VISIT_DEST; 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 // visit town for town portal \ castle gates
// do not use generic visitObjectOnTile to avoid double-teleporting // do not use generic visitObjectOnTile to avoid double-teleporting
// if this moveHero call was triggered by teleporter // 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); town->onHeroVisit(h);
} }

View File

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

View File

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