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

Merge pull request #2728 from Nordsoft91/turn-timer-fix

This commit is contained in:
Nordsoft91 2023-09-02 16:29:20 +04:00 committed by GitHub
commit 91565225c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 14 deletions

View File

@ -1106,11 +1106,14 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
const bool canWalkOnSea = pathfinderHelper->hasBonusOfType(BonusType::WATER_WALKING) || (h->boat && h->boat->layer == EPathfindingLayer::WATER);
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());
//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() || (t.blocked && !t.visitable && !canFly))
if (((!t.terType->isPassable() || (standAtObstacle && !canFly))
&& complain("Cannot move hero, destination tile is blocked!"))
|| ((!h->boat && !canWalkOnSea && !canFly && t.terType->isWater() && (t.visitableObjects.size() < 1 || !t.visitableObjects.back()->isCoastVisitable())) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
|| ((standAtWater && !canFly && !canWalkOnSea) //hero is not on boat/water walking and dst water tile doesn't contain boat/hero (objs visitable from land) -> we test back cause boat may be on top of another object (#276)
&& complain("Cannot move hero, destination tile is on water!"))
|| ((h->boat && h->boat->layer == EPathfindingLayer::SAIL && t.terType->isLand() && t.blocked)
&& complain("Cannot disembark hero, tile is blocked!"))
@ -1175,14 +1178,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
visitObjectOnTile(t, h);
}
for(auto topQuery = queries->topQuery(h->tempOwner); true; topQuery = queries->topQuery(h->tempOwner))
{
moveQuery = std::dynamic_pointer_cast<CHeroMovementQuery>(topQuery);
if(!moveQuery || (transit && result == TryMoveHero::SUCCESS))
break;
queries->popIfTop(moveQuery);
}
queries->popIfTop(moveQuery);
logGlobal->trace("Hero %s ends movement", h->getNameTranslated());
return result != TryMoveHero::FAILED;
};
@ -1266,6 +1262,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
if(h->boat && !h->boat->onboardAssaultAllowed)
lookForGuards = IGNORE_GUARDS;
turnTimerHandler.setEndTurnAllowed(h->getOwner(), !standAtWater && !standAtObstacle);
doMove(TryMoveHero::SUCCESS, lookForGuards, visitDest, LEAVING_TILE);
return true;
}

View File

@ -36,6 +36,7 @@ void TurnTimerHandler::onGameplayStart(PlayerColor player)
timers[player].isActive = true;
timers[player].isBattle = false;
lastUpdate[player] = std::numeric_limits<int>::max();
endTurnAllowed[player] = true;
}
}
@ -47,6 +48,13 @@ void TurnTimerHandler::setTimerEnabled(PlayerColor player, bool enabled)
sendTimerUpdate(player);
}
void TurnTimerHandler::setEndTurnAllowed(PlayerColor player, bool enabled)
{
std::lock_guard<std::recursive_mutex> guard(mx);
assert(player.isValidPlayer());
endTurnAllowed[player] = enabled;
}
void TurnTimerHandler::sendTimerUpdate(PlayerColor player)
{
TurnTimeUpdate ttu;
@ -63,6 +71,7 @@ void TurnTimerHandler::onPlayerGetTurn(PlayerColor player)
{
if(si->turnTimerInfo.isEnabled())
{
endTurnAllowed[player] = true;
auto & timer = timers[player];
if(si->turnTimerInfo.baseTimer > 0)
timer.baseTimer += timer.turnTimer;
@ -125,7 +134,7 @@ void TurnTimerHandler::onPlayerMakingTurn(PlayerColor player, int waitTime)
timer.baseTimer = 0;
onPlayerMakingTurn(player, 0);
}
else if(!gameHandler.queries->topQuery(state->color)) //wait for replies to avoid pending queries
else if(endTurnAllowed[state->color] && !gameHandler.queries->topQuery(state->color)) //wait for replies to avoid pending queries
gameHandler.turnOrder->onPlayerEndsTurn(state->color);
}
}
@ -151,7 +160,7 @@ void TurnTimerHandler::onBattleStart()
std::lock_guard<std::recursive_mutex> guard(mx);
const auto * gs = gameHandler.gameState();
const auto * si = gameHandler.getStartInfo();
if(!si || !gs || !gs->curB || !si->turnTimerInfo.isBattleEnabled())
if(!si || !gs || !gs->curB)
return;
auto attacker = gs->curB->getSidePlayer(BattleSide::ATTACKER);
@ -165,6 +174,7 @@ void TurnTimerHandler::onBattleStart()
{
auto & timer = timers[i];
timer.isBattle = true;
timer.isActive = si->turnTimerInfo.isBattleEnabled();
timer.battleTimer = (pvpBattle ? si->turnTimerInfo.battleTimer : 0);
timer.creatureTimer = (pvpBattle ? si->turnTimerInfo.creatureTimer : si->turnTimerInfo.battleTimer);
@ -178,7 +188,7 @@ void TurnTimerHandler::onBattleEnd()
std::lock_guard<std::recursive_mutex> guard(mx);
const auto * gs = gameHandler.gameState();
const auto * si = gameHandler.getStartInfo();
if(!si || !gs || !gs->curB || !si->turnTimerInfo.isBattleEnabled())
if(!si || !gs || !gs->curB)
return;
auto attacker = gs->curB->getSidePlayer(BattleSide::ATTACKER);
@ -192,7 +202,7 @@ void TurnTimerHandler::onBattleEnd()
{
auto & timer = timers[i];
timer.isBattle = false;
timer.isActive = true;
if(!pvpBattle)
{
if(si->turnTimerInfo.baseTimer && timer.baseTimer == 0)

View File

@ -29,6 +29,7 @@ class TurnTimerHandler
const int turnTimePropagateThreshold = 3000;
std::map<PlayerColor, TurnTimerInfo> timers;
std::map<PlayerColor, int> lastUpdate;
std::map<PlayerColor, bool> endTurnAllowed;
std::recursive_mutex mx;
void onPlayerMakingTurn(PlayerColor player, int waitTime);
@ -48,4 +49,5 @@ public:
void onBattleEnd();
void update(int waitTime);
void setTimerEnabled(PlayerColor player, bool enabled);
void setEndTurnAllowed(PlayerColor player, bool enabled);
};