mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Fixed pathfinding with free ship boarding (Admiral's Hat)
This commit is contained in:
@@ -63,7 +63,7 @@ struct DLL_LINKAGE CGPathNode
|
|||||||
CGPathNode * theNodeBefore;
|
CGPathNode * theNodeBefore;
|
||||||
int3 coord; //coordinates
|
int3 coord; //coordinates
|
||||||
ELayer layer;
|
ELayer layer;
|
||||||
ui32 moveRemains; //remaining movement points after hero reaches the tile
|
int moveRemains; //remaining movement points after hero reaches the tile
|
||||||
ui8 turns; //how many turns we have to wait before reaching the tile - 0 means current turn
|
ui8 turns; //how many turns we have to wait before reaching the tile - 0 means current turn
|
||||||
|
|
||||||
EPathAccessibility accessible;
|
EPathAccessibility accessible;
|
||||||
|
@@ -27,43 +27,65 @@ void MovementCostRule::process(
|
|||||||
const PathfinderConfig * pathfinderConfig,
|
const PathfinderConfig * pathfinderConfig,
|
||||||
CPathfinderHelper * pathfinderHelper) const
|
CPathfinderHelper * pathfinderHelper) const
|
||||||
{
|
{
|
||||||
float costAtNextTile = destination.cost;
|
const float currentCost = destination.cost;
|
||||||
int turnAtNextTile = destination.turn;
|
const int currentTurnsUsed = destination.turn;
|
||||||
int moveAtNextTile = destination.movementLeft;
|
const int currentMovePointsLeft = destination.movementLeft;
|
||||||
int cost = pathfinderHelper->getMovementCost(source, destination, moveAtNextTile);
|
const int sourceLayerMaxMovePoints = pathfinderHelper->getMaxMovePoints(source.node->layer);
|
||||||
int remains = moveAtNextTile - cost;
|
|
||||||
int sourceLayerMaxMovePoints = pathfinderHelper->getMaxMovePoints(source.node->layer);
|
|
||||||
|
|
||||||
if(remains < 0)
|
int moveCostPoints = pathfinderHelper->getMovementCost(source, destination, currentMovePointsLeft);
|
||||||
|
float destinationCost = currentCost;
|
||||||
|
int destTurnsUsed = currentTurnsUsed;
|
||||||
|
int destMovePointsLeft = currentMovePointsLeft;
|
||||||
|
|
||||||
|
if(currentMovePointsLeft < moveCostPoints)
|
||||||
{
|
{
|
||||||
//occurs rarely, when hero with low movepoints tries to leave the road
|
// occurs rarely, when hero with low movepoints tries to leave the road
|
||||||
costAtNextTile += static_cast<float>(moveAtNextTile) / sourceLayerMaxMovePoints;//we spent all points of current turn
|
// in this case, all remaining movement points from current turn are spent
|
||||||
pathfinderHelper->updateTurnInfo(++turnAtNextTile);
|
// and actual movement will happen on next turn, spending points from next turn pool
|
||||||
|
|
||||||
int destinationLayerMaxMovePoints = pathfinderHelper->getMaxMovePoints(destination.node->layer);
|
destinationCost += static_cast<float>(currentMovePointsLeft) / sourceLayerMaxMovePoints;
|
||||||
|
destTurnsUsed += 1;
|
||||||
|
destMovePointsLeft = sourceLayerMaxMovePoints;
|
||||||
|
|
||||||
moveAtNextTile = destinationLayerMaxMovePoints;
|
// update move cost - it might have changed since hero now makes next turn and replenished his pool
|
||||||
|
moveCostPoints = pathfinderHelper->getMovementCost(source, destination, destMovePointsLeft);
|
||||||
|
|
||||||
cost = pathfinderHelper->getMovementCost(source, destination, moveAtNextTile); //cost must be updated, movement points changed :(
|
pathfinderHelper->updateTurnInfo(destTurnsUsed);
|
||||||
remains = moveAtNextTile - cost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(destination.action == EPathNodeAction::EMBARK || destination.action == EPathNodeAction::DISEMBARK)
|
if(destination.action == EPathNodeAction::EMBARK || destination.action == EPathNodeAction::DISEMBARK)
|
||||||
{
|
{
|
||||||
/// FREE_SHIP_BOARDING bonus only remove additional penalty
|
// FREE_SHIP_BOARDING bonus only remove additional penalty
|
||||||
/// land <-> sail transition still cost movement points as normal movement
|
// land <-> sail transition still cost movement points as normal movement
|
||||||
remains = pathfinderHelper->movementPointsAfterEmbark(moveAtNextTile, cost, (destination.action == EPathNodeAction::DISEMBARK));
|
|
||||||
cost = moveAtNextTile - remains;
|
const int movementPointsAfterEmbark = pathfinderHelper->movementPointsAfterEmbark(destMovePointsLeft, moveCostPoints, (destination.action == EPathNodeAction::DISEMBARK));
|
||||||
|
|
||||||
|
const int destinationLayerMaxMovePoints = pathfinderHelper->getMaxMovePoints(destination.node->layer);
|
||||||
|
const float costBeforeConversion = static_cast<float>(destMovePointsLeft) / sourceLayerMaxMovePoints;
|
||||||
|
const float costAfterConversion = static_cast<float>(movementPointsAfterEmbark) / destinationLayerMaxMovePoints;
|
||||||
|
const float costDelta = costBeforeConversion - costAfterConversion;
|
||||||
|
|
||||||
|
assert(costDelta >= 0);
|
||||||
|
destMovePointsLeft = movementPointsAfterEmbark;
|
||||||
|
destinationCost += costDelta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Standard movement
|
||||||
|
assert(destMovePointsLeft >= moveCostPoints);
|
||||||
|
destMovePointsLeft -= moveCostPoints;
|
||||||
|
destinationCost += static_cast<float>(moveCostPoints) / sourceLayerMaxMovePoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
costAtNextTile += static_cast<float>(cost) / sourceLayerMaxMovePoints;
|
// pathfinder / priority queue does not supports negative costs
|
||||||
|
assert(destinationCost >= currentCost);
|
||||||
|
|
||||||
destination.cost = costAtNextTile;
|
destination.cost = destinationCost;
|
||||||
destination.turn = turnAtNextTile;
|
destination.turn = destTurnsUsed;
|
||||||
destination.movementLeft = remains;
|
destination.movementLeft = destMovePointsLeft;
|
||||||
|
|
||||||
if(destination.isBetterWay() &&
|
if(destination.isBetterWay() &&
|
||||||
((source.node->turns == turnAtNextTile && remains) || pathfinderHelper->passOneTurnLimitCheck(source)))
|
((source.node->turns == destTurnsUsed && destMovePointsLeft) || pathfinderHelper->passOneTurnLimitCheck(source)))
|
||||||
{
|
{
|
||||||
pathfinderConfig->nodeStorage->commit(destination, source);
|
pathfinderConfig->nodeStorage->commit(destination, source);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user