فهرست منبع

CPathfinder: patrol support using getTilesInRange

For now we use getTilesInRange which isn't really correct for patrol, but good enough for first version.
ArseniyShestakov 10 سال پیش
والد
کامیت
6bb205b15b
3فایلهای تغییر یافته به همراه56 افزوده شده و 4 حذف شده
  1. 44 3
      lib/CPathfinder.cpp
  2. 11 0
      lib/CPathfinder.h
  3. 1 1
      lib/mapping/MapFormatH3M.cpp

+ 44 - 3
lib/CPathfinder.cpp

@@ -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)

+ 11 - 0
lib/CPathfinder.h

@@ -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;

+ 1 - 1
lib/mapping/MapFormatH3M.cpp

@@ -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)