mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Pathfinder: implement new feature - node action
No action going to simplify isMovementAfterDestPossible and should be as well useful for cost calculations. It's can be also used by client interface to show appropriate cursors and path.
This commit is contained in:
parent
bd8eec7fb8
commit
82048cbf2d
@ -106,7 +106,6 @@ void CPathfinder::calculatePaths()
|
||||
dt = &gs->map->getTile(neighbour);
|
||||
for(EPathfindingLayer i = EPathfindingLayer::LAND; i <= EPathfindingLayer::AIR; i.advance(1))
|
||||
{
|
||||
useEmbarkCost = 0; //0 - usual movement; 1 - embark; 2 - disembark
|
||||
dp = out.getNode(neighbour, i);
|
||||
if(dp->accessible == CGPathNode::NOT_SET)
|
||||
continue;
|
||||
@ -117,14 +116,15 @@ void CPathfinder::calculatePaths()
|
||||
if(cp->layer != i && !isLayerTransitionPossible())
|
||||
continue;
|
||||
|
||||
destAction = CGPathNode::UNKNOWN;
|
||||
if(!isMovementToDestPossible())
|
||||
continue;
|
||||
|
||||
int cost = gs->getMovementCost(hero, cp->coord, dp->coord, movement);
|
||||
int remains = movement - cost;
|
||||
if(useEmbarkCost)
|
||||
if(destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK)
|
||||
{
|
||||
remains = hero->movementPointsAfterEmbark(movement, cost, useEmbarkCost - 1);
|
||||
remains = hero->movementPointsAfterEmbark(movement, cost, destAction - 1);
|
||||
cost = movement - remains;
|
||||
}
|
||||
|
||||
@ -144,6 +144,7 @@ void CPathfinder::calculatePaths()
|
||||
dp->moveRemains = remains;
|
||||
dp->turns = turnAtNextTile;
|
||||
dp->theNodeBefore = cp;
|
||||
dp->action = destAction;
|
||||
|
||||
if(isMovementAfterDestPossible())
|
||||
pq.push(dp);
|
||||
@ -166,6 +167,7 @@ void CPathfinder::calculatePaths()
|
||||
dp->moveRemains = movement;
|
||||
dp->turns = turn;
|
||||
dp->theNodeBefore = cp;
|
||||
dp->action = CGPathNode::NORMAL;
|
||||
pq.push(dp);
|
||||
}
|
||||
}
|
||||
@ -258,24 +260,18 @@ bool CPathfinder::isLayerTransitionPossible()
|
||||
if((dp->accessible != CGPathNode::ACCESSIBLE && (dp->accessible != CGPathNode::BLOCKVIS || dt->blocked))
|
||||
|| dt->visitable) //TODO: passableness problem -> town says it's passable (thus accessible) but we obviously can't disembark onto town gate
|
||||
return false;
|
||||
|
||||
useEmbarkCost = 2;
|
||||
}
|
||||
else if(cp->layer == EPathfindingLayer::LAND && dp->layer == EPathfindingLayer::SAIL)
|
||||
{
|
||||
Obj destTopVisObjID = dt->topVisitableId();
|
||||
if(dp->accessible == CGPathNode::ACCESSIBLE || destTopVisObjID < 0) //cannot enter empty water tile from land -> it has to be visitable
|
||||
if(dp->accessible == CGPathNode::ACCESSIBLE) //cannot enter empty water tile from land -> it has to be visitable
|
||||
return false;
|
||||
if(destTopVisObjID != Obj::HERO && destTopVisObjID != Obj::BOAT) //only boat or hero can be accessed from land
|
||||
return false;
|
||||
if(destTopVisObjID == Obj::BOAT)
|
||||
useEmbarkCost = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPathfinder::isMovementToDestPossible()
|
||||
{
|
||||
auto obj = dt->topVisitableObj();
|
||||
switch(dp->layer)
|
||||
{
|
||||
case EPathfindingLayer::LAND:
|
||||
@ -284,6 +280,9 @@ bool CPathfinder::isMovementToDestPossible()
|
||||
if(isSourceGuarded() && !isDestinationGuardian()) // Can step into tile of guard
|
||||
return false;
|
||||
|
||||
if(cp->layer == EPathfindingLayer::SAIL)
|
||||
destAction = CGPathNode::DISEMBARK;
|
||||
|
||||
break;
|
||||
case EPathfindingLayer::SAIL:
|
||||
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED)
|
||||
@ -291,6 +290,16 @@ bool CPathfinder::isMovementToDestPossible()
|
||||
if(isSourceGuarded() && !isDestinationGuardian()) // Can step into tile of guard
|
||||
return false;
|
||||
|
||||
if(cp->layer == EPathfindingLayer::LAND)
|
||||
{
|
||||
if(!obj)
|
||||
return false;
|
||||
|
||||
if(obj->ID == Obj::BOAT)
|
||||
destAction = CGPathNode::EMBARK;
|
||||
else if(obj->ID != Obj::HERO)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case EPathfindingLayer::AIR:
|
||||
@ -308,6 +317,29 @@ bool CPathfinder::isMovementToDestPossible()
|
||||
break;
|
||||
}
|
||||
|
||||
if(destAction == CGPathNode::UNKNOWN)
|
||||
{
|
||||
destAction = CGPathNode::NORMAL;
|
||||
if(dp->layer == EPathfindingLayer::LAND || dp->layer == EPathfindingLayer::SAIL)
|
||||
{
|
||||
if(obj)
|
||||
{
|
||||
if(obj->ID == Obj::HERO || obj->ID == Obj::TOWN)
|
||||
{
|
||||
if(getPlayerRelations(obj->tempOwner, hero->tempOwner) == PlayerRelations::ENEMIES)
|
||||
destAction = CGPathNode::BATTLE;
|
||||
else
|
||||
destAction = CGPathNode::BLOCKING_VISIT; // TODO: Probably you should be able to go into air from town too
|
||||
}
|
||||
else if(obj->blockVisit)
|
||||
destAction = CGPathNode::BLOCKING_VISIT;
|
||||
else
|
||||
destAction = CGPathNode::VISIT;
|
||||
}
|
||||
else if(isDestinationGuarded())
|
||||
destAction = CGPathNode::BATTLE;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -330,7 +362,7 @@ bool CPathfinder::isMovementAfterDestPossible()
|
||||
if(!whirlpool || options.useTeleportWhirlpool)
|
||||
return true;
|
||||
}
|
||||
if(useEmbarkCost && options.useEmbarkAndDisembark)
|
||||
if((destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK) && options.useEmbarkAndDisembark)
|
||||
return true;
|
||||
break;
|
||||
|
||||
@ -527,6 +559,7 @@ void CGPathNode::reset()
|
||||
moveRemains = 0;
|
||||
turns = 255;
|
||||
theNodeBefore = nullptr;
|
||||
action = UNKNOWN;
|
||||
}
|
||||
|
||||
bool CGPathNode::reachable() const
|
||||
|
@ -23,6 +23,17 @@ struct TerrainTile;
|
||||
|
||||
struct DLL_LINKAGE CGPathNode
|
||||
{
|
||||
enum ENodeAction
|
||||
{
|
||||
UNKNOWN = -1,
|
||||
NORMAL = 0,
|
||||
EMBARK = 1,
|
||||
DISEMBARK, //2
|
||||
BATTLE,//3
|
||||
VISIT,//4
|
||||
BLOCKING_VISIT//5
|
||||
};
|
||||
|
||||
enum EAccessibility
|
||||
{
|
||||
NOT_SET = 0,
|
||||
@ -40,6 +51,7 @@ struct DLL_LINKAGE CGPathNode
|
||||
CGPathNode * theNodeBefore;
|
||||
int3 coord; //coordinates
|
||||
EPathfindingLayer layer;
|
||||
ENodeAction action;
|
||||
|
||||
CGPathNode(int3 Coord, EPathfindingLayer Layer);
|
||||
void reset();
|
||||
@ -120,7 +132,7 @@ private:
|
||||
CGPathNode *dp; //destination node -> it's a neighbour of cp that we consider
|
||||
const TerrainTile *ct, *dt; //tile info for both nodes
|
||||
const CGObjectInstance *sTileObj;
|
||||
ui8 useEmbarkCost; //0 - usual movement; 1 - embark; 2 - disembark
|
||||
CGPathNode::ENodeAction destAction;
|
||||
|
||||
void addNeighbours(const int3 &coord);
|
||||
void addTeleportExits(bool noTeleportExcludes = false);
|
||||
|
Loading…
x
Reference in New Issue
Block a user