mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-21 21:17:49 +02:00
CPathfinder: patrol support using getTilesInRange
For now we use getTilesInRange which isn't really correct for patrol, but good enough for first version.
This commit is contained in:
parent
56c6785bd0
commit
6bb205b15b
@ -37,7 +37,7 @@ CPathfinder::PathfinderOptions::PathfinderOptions()
|
||||
}
|
||||
|
||||
CPathfinder::CPathfinder(CPathsInfo & _out, CGameState * _gs, const CGHeroInstance * _hero)
|
||||
: CGameInfoCallback(_gs, boost::optional<PlayerColor>()), out(_out), hero(_hero), FoW(getPlayerTeam(hero->tempOwner)->fogOfWarMap)
|
||||
: CGameInfoCallback(_gs, boost::optional<PlayerColor>()), out(_out), hero(_hero), FoW(getPlayerTeam(hero->tempOwner)->fogOfWarMap), patrolTiles({})
|
||||
{
|
||||
assert(hero);
|
||||
assert(hero == getHero(hero->id));
|
||||
@ -52,6 +52,7 @@ CPathfinder::CPathfinder(CPathsInfo & _out, CGameState * _gs, const CGHeroInstan
|
||||
|
||||
hlp = make_unique<CPathfinderHelper>(hero, options);
|
||||
|
||||
initializePatrol();
|
||||
initializeGraph();
|
||||
neighbourTiles.reserve(8);
|
||||
neighbours.reserve(16);
|
||||
@ -95,8 +96,10 @@ void CPathfinder::calculatePaths()
|
||||
CGPathNode * initialNode = out.getNode(out.hpos, hero->boat ? ELayer::SAIL : ELayer::LAND);
|
||||
initialNode->turns = 0;
|
||||
initialNode->moveRemains = hero->movement;
|
||||
pq.push(initialNode);
|
||||
if(isHeroPatrolLocked())
|
||||
return;
|
||||
|
||||
pq.push(initialNode);
|
||||
while(!pq.empty())
|
||||
{
|
||||
cp = pq.top();
|
||||
@ -119,6 +122,9 @@ void CPathfinder::calculatePaths()
|
||||
addNeighbours();
|
||||
for(auto & neighbour : neighbours)
|
||||
{
|
||||
if(!isPatrolMovementAllowed(neighbour))
|
||||
continue;
|
||||
|
||||
dt = &gs->map->getTile(neighbour);
|
||||
dtObj = dt->topVisitableObj();
|
||||
for(ELayer i = ELayer::LAND; i <= ELayer::AIR; i.advance(1))
|
||||
@ -215,7 +221,9 @@ void CPathfinder::addNeighbours()
|
||||
void CPathfinder::addTeleportExits()
|
||||
{
|
||||
neighbours.clear();
|
||||
if(!isSourceVisitableObj())
|
||||
/// For now we disable teleports usage for patrol movement
|
||||
/// VCAI not aware about patrol and may stuck while attempt to use teleport
|
||||
if(!isSourceVisitableObj() || patrolState == PATROL_RADIUS)
|
||||
return;
|
||||
|
||||
const CGTeleport * objTeleport = dynamic_cast<const CGTeleport *>(ctObj);
|
||||
@ -256,6 +264,22 @@ void CPathfinder::addTeleportExits()
|
||||
}
|
||||
}
|
||||
|
||||
bool CPathfinder::isHeroPatrolLocked() const
|
||||
{
|
||||
return patrolState == PATROL_LOCKED;
|
||||
}
|
||||
|
||||
bool CPathfinder::isPatrolMovementAllowed(const int3 & dst) const
|
||||
{
|
||||
if(patrolState == PATROL_RADIUS)
|
||||
{
|
||||
if(!vstd::contains(patrolTiles, dst))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPathfinder::isLayerTransitionPossible(const ELayer destLayer) const
|
||||
{
|
||||
/// No layer transition allowed when previous node action is BATTLE
|
||||
@ -564,6 +588,23 @@ bool CPathfinder::isDestinationGuardian() const
|
||||
return gs->guardingCreaturePosition(cp->coord) == dp->coord;
|
||||
}
|
||||
|
||||
void CPathfinder::initializePatrol()
|
||||
{
|
||||
auto state = PATROL_NONE;
|
||||
if(hero->patrol.patrolling && !getPlayer(hero->tempOwner)->human)
|
||||
{
|
||||
if(hero->patrol.patrolRadious)
|
||||
{
|
||||
state = PATROL_RADIUS;
|
||||
gs->getTilesInRange(patrolTiles, hero->patrol.initialPos, hero->patrol.patrolRadious);
|
||||
}
|
||||
else
|
||||
state = PATROL_LOCKED;
|
||||
}
|
||||
|
||||
patrolState = state;
|
||||
}
|
||||
|
||||
void CPathfinder::initializeGraph()
|
||||
{
|
||||
auto updateNode = [&](int3 pos, ELayer layer, const TerrainTile * tinfo)
|
||||
|
@ -159,6 +159,13 @@ private:
|
||||
const std::vector<std::vector<std::vector<ui8> > > &FoW;
|
||||
unique_ptr<CPathfinderHelper> hlp;
|
||||
|
||||
enum EPatrolState {
|
||||
PATROL_NONE = 0,
|
||||
PATROL_LOCKED = 1,
|
||||
PATROL_RADIUS
|
||||
} patrolState;
|
||||
std::unordered_set<int3, ShashInt3> patrolTiles;
|
||||
|
||||
struct NodeComparer
|
||||
{
|
||||
bool operator()(const CGPathNode * lhs, const CGPathNode * rhs) const
|
||||
@ -185,6 +192,9 @@ private:
|
||||
void addNeighbours();
|
||||
void addTeleportExits();
|
||||
|
||||
bool isHeroPatrolLocked() const;
|
||||
bool isPatrolMovementAllowed(const int3 & dst) const;
|
||||
|
||||
bool isLayerTransitionPossible(const ELayer dstLayer) const;
|
||||
bool isLayerTransitionPossible() const;
|
||||
bool isMovementToDestPossible() const;
|
||||
@ -198,6 +208,7 @@ private:
|
||||
bool isDestinationGuarded(const bool ignoreAccessibility = true) const;
|
||||
bool isDestinationGuardian() const;
|
||||
|
||||
void initializePatrol();
|
||||
void initializeGraph();
|
||||
|
||||
CGPathNode::EAccessibility evaluateAccessibility(const int3 & pos, const TerrainTile * tinfo, const ELayer layer) const;
|
||||
|
@ -1658,7 +1658,7 @@ CGObjectInstance * CMapLoaderH3M::readHero(ObjectInstanceID idToBeGiven, const i
|
||||
else
|
||||
{
|
||||
nhi->patrol.patrolling = true;
|
||||
nhi->patrol.initialPos = initialPos;
|
||||
nhi->patrol.initialPos = CGHeroInstance::convertPosition(initialPos, false);
|
||||
}
|
||||
|
||||
if(map->version > EMapFormat::ROE)
|
||||
|
Loading…
x
Reference in New Issue
Block a user