mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-21 21:17:49 +02:00
Pathfinding: re-introduce EAccessibility::FLYABLE
That let us get rid of really hacky code in initializeGraph and also fix flying over tiles that aren't visible.
This commit is contained in:
parent
c2ba3e3faf
commit
fe12b8f664
@ -321,10 +321,13 @@ bool CPathfinder::isLayerTransitionPossible() const
|
||||
|
||||
bool CPathfinder::isMovementToDestPossible() const
|
||||
{
|
||||
if(dp->accessible == CGPathNode::BLOCKED)
|
||||
return false;
|
||||
|
||||
switch(dp->layer)
|
||||
{
|
||||
case ELayer::LAND:
|
||||
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED)
|
||||
if(!canMoveBetween(cp->coord, dp->coord))
|
||||
return false;
|
||||
if(isSourceGuarded())
|
||||
{
|
||||
@ -338,7 +341,7 @@ bool CPathfinder::isMovementToDestPossible() const
|
||||
break;
|
||||
|
||||
case ELayer::SAIL:
|
||||
if(!canMoveBetween(cp->coord, dp->coord) || dp->accessible == CGPathNode::BLOCKED)
|
||||
if(!canMoveBetween(cp->coord, dp->coord))
|
||||
return false;
|
||||
if(isSourceGuarded())
|
||||
{
|
||||
@ -531,17 +534,10 @@ bool CPathfinder::isDestinationGuardian() const
|
||||
|
||||
void CPathfinder::initializeGraph()
|
||||
{
|
||||
auto updateNode = [&](int3 pos, ELayer layer, const TerrainTile * tinfo, bool blockNotAccessible)
|
||||
auto updateNode = [&](int3 pos, ELayer layer, const TerrainTile * tinfo)
|
||||
{
|
||||
auto node = out.getNode(pos, layer);
|
||||
|
||||
auto accessibility = evaluateAccessibility(pos, tinfo);
|
||||
/// TODO: Probably this shouldn't be handled by initializeGraph
|
||||
if(blockNotAccessible
|
||||
&& (accessibility != CGPathNode::ACCESSIBLE || tinfo->terType == ETerrainType::WATER))
|
||||
{
|
||||
accessibility = CGPathNode::BLOCKED;
|
||||
}
|
||||
auto accessibility = evaluateAccessibility(pos, tinfo, layer);
|
||||
node->update(pos, layer, accessibility);
|
||||
};
|
||||
|
||||
@ -555,65 +551,86 @@ void CPathfinder::initializeGraph()
|
||||
const TerrainTile * tinfo = getTile(pos);
|
||||
switch(tinfo->terType)
|
||||
{
|
||||
case ETerrainType::ROCK:
|
||||
break;
|
||||
case ETerrainType::WATER:
|
||||
updateNode(pos, ELayer::SAIL, tinfo, false);
|
||||
if(options.useFlying)
|
||||
updateNode(pos, ELayer::AIR, tinfo, true);
|
||||
if(options.useWaterWalking)
|
||||
updateNode(pos, ELayer::WATER, tinfo, false);
|
||||
break;
|
||||
default:
|
||||
updateNode(pos, ELayer::LAND, tinfo, false);
|
||||
if(options.useFlying)
|
||||
updateNode(pos, ELayer::AIR, tinfo, true);
|
||||
break;
|
||||
case ETerrainType::ROCK:
|
||||
break;
|
||||
|
||||
case ETerrainType::WATER:
|
||||
updateNode(pos, ELayer::SAIL, tinfo);
|
||||
if(options.useFlying)
|
||||
updateNode(pos, ELayer::AIR, tinfo);
|
||||
if(options.useWaterWalking)
|
||||
updateNode(pos, ELayer::WATER, tinfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
updateNode(pos, ELayer::LAND, tinfo);
|
||||
if(options.useFlying)
|
||||
updateNode(pos, ELayer::AIR, tinfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo) const
|
||||
CGPathNode::EAccessibility CPathfinder::evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, const ELayer layer) const
|
||||
{
|
||||
CGPathNode::EAccessibility ret = (tinfo->blocked ? CGPathNode::BLOCKED : CGPathNode::ACCESSIBLE);
|
||||
|
||||
if(tinfo->terType == ETerrainType::ROCK || !isVisible(pos, hero->tempOwner))
|
||||
return CGPathNode::BLOCKED;
|
||||
|
||||
if(tinfo->visitable)
|
||||
switch(layer)
|
||||
{
|
||||
if(tinfo->visitableObjects.front()->ID == Obj::SANCTUARY && tinfo->visitableObjects.back()->ID == Obj::HERO && tinfo->visitableObjects.back()->tempOwner != hero->tempOwner) //non-owned hero stands on Sanctuary
|
||||
case ELayer::LAND:
|
||||
case ELayer::SAIL:
|
||||
if(tinfo->visitable)
|
||||
{
|
||||
return CGPathNode::BLOCKED;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const CGObjectInstance * obj : tinfo->visitableObjects)
|
||||
if(tinfo->visitableObjects.front()->ID == Obj::SANCTUARY && tinfo->visitableObjects.back()->ID == Obj::HERO && tinfo->visitableObjects.back()->tempOwner != hero->tempOwner) //non-owned hero stands on Sanctuary
|
||||
{
|
||||
if(obj->passableFor(hero->tempOwner))
|
||||
return CGPathNode::BLOCKED;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const CGObjectInstance * obj : tinfo->visitableObjects)
|
||||
{
|
||||
ret = CGPathNode::ACCESSIBLE;
|
||||
}
|
||||
else if(obj->blockVisit)
|
||||
{
|
||||
return CGPathNode::BLOCKVIS;
|
||||
}
|
||||
else if(obj->ID != Obj::EVENT) //pathfinder should ignore placed events
|
||||
{
|
||||
ret = CGPathNode::VISITABLE;
|
||||
if(obj->passableFor(hero->tempOwner))
|
||||
{
|
||||
return CGPathNode::ACCESSIBLE;
|
||||
}
|
||||
else if(obj->blockVisit)
|
||||
{
|
||||
return CGPathNode::BLOCKVIS;
|
||||
}
|
||||
else if(obj->ID != Obj::EVENT) //pathfinder should ignore placed events
|
||||
{
|
||||
return CGPathNode::VISITABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(guardingCreaturePosition(pos).valid() && !tinfo->blocked)
|
||||
{
|
||||
// Monster close by; blocked visit for battle.
|
||||
return CGPathNode::BLOCKVIS;
|
||||
else if(guardingCreaturePosition(pos).valid() && !tinfo->blocked)
|
||||
{
|
||||
// Monster close by; blocked visit for battle
|
||||
return CGPathNode::BLOCKVIS;
|
||||
}
|
||||
else if(tinfo->blocked)
|
||||
return CGPathNode::BLOCKED;
|
||||
|
||||
break;
|
||||
|
||||
case ELayer::WATER:
|
||||
if(tinfo->blocked || tinfo->terType != ETerrainType::WATER)
|
||||
return CGPathNode::BLOCKED;
|
||||
|
||||
break;
|
||||
|
||||
case ELayer::AIR:
|
||||
if(tinfo->blocked || tinfo->terType == ETerrainType::WATER)
|
||||
return CGPathNode::FLYABLE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return CGPathNode::ACCESSIBLE;
|
||||
}
|
||||
|
||||
bool CPathfinder::canMoveBetween(const int3 & a, const int3 & b) const
|
||||
|
@ -43,6 +43,7 @@ struct DLL_LINKAGE CGPathNode
|
||||
ACCESSIBLE = 1, //tile can be entered and passed
|
||||
VISITABLE, //tile can be entered as the last tile in path
|
||||
BLOCKVIS, //visitable from neighbouring tile but not passable
|
||||
FLYABLE, //can only be accessed in air layer
|
||||
BLOCKED //tile can't be entered nor visited
|
||||
};
|
||||
|
||||
@ -181,7 +182,7 @@ private:
|
||||
|
||||
void initializeGraph();
|
||||
|
||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo) const;
|
||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, const ELayer layer) const;
|
||||
bool canMoveBetween(const int3 & a, const int3 & b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
|
||||
|
||||
bool isAllowedTeleportEntrance(const CGTeleport * obj) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user