Browse Source

Merge pull request #6005 from thehonestcto/fix/monthly-random-monsters-hiding-nearby-danger

fix: monthly monsters aren't linked with other map objects at creatio…
Ivan Savenko 2 months ago
parent
commit
6bb5711ded

+ 1 - 1
AI/Nullkiller/Analyzers/ObjectClusterizer.cpp

@@ -425,7 +425,7 @@ void ObjectClusterizer::clusterizeObject(
 	for(auto & path : pathCache)
 	{
 #if NKAI_TRACE_LEVEL >= 2
-		logAi->trace("Checking path %s", path.toString());
+		logAi->trace("ObjectClusterizer Checking path %s", path.toString());
 #endif
 
 		if(ai->heroManager->getHeroRole(path.targetHero) == HeroRole::SCOUT)

+ 1 - 1
AI/Nullkiller/Behaviors/ClusterBehavior.cpp

@@ -62,7 +62,7 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(const Nullkiller * ai, std::sh
 	for(auto path = paths.begin(); path != paths.end();)
 	{
 #if NKAI_TRACE_LEVEL >= 2
-		logAi->trace("Checking path %s", path->toString());
+		logAi->trace("ClusterBehavior Checking path %s", path->toString());
 #endif
 
 		auto blocker = ai->objectClusterizer->getBlocker(*path);

+ 2 - 0
AI/Nullkiller/Engine/DeepDecomposer.cpp

@@ -72,6 +72,8 @@ void DeepDecomposer::decompose(TGoalVec & result, TSubgoal behavior, int depthLi
 				// 0 - goals directly from behavior
 				Goals::TSubgoal task = depth >= 1 ? aggregateGoals(0, subgoal) : subgoal;
 
+				// Issue with CGameHandler::spawnWanderingMonsters, see getFreeTiles(tiles, true);
+				// danger not linked GraphPaths::addChainInfo, so spawning only with nearby unblocked
 #if NKAI_TRACE_LEVEL >= 1
 				logAi->trace("Found task %s", task->toString());
 #endif

+ 15 - 1
lib/callback/CGameInfoCallback.cpp

@@ -791,7 +791,7 @@ bool CGameInfoCallback::isTeleportEntrancePassable(const CGTeleport * obj, Playe
 	return obj && obj->isEntrance() && !isTeleportChannelImpassable(obj->channel, player);
 }
 
-void CGameInfoCallback::getFreeTiles(std::vector<int3> & tiles) const
+void CGameInfoCallback::getFreeTiles(std::vector<int3> & tiles, bool skipIfNearbyGuarded) const
 {
 	std::vector<int> floors;
 	floors.reserve(gameState().getMap().levels());
@@ -808,7 +808,21 @@ void CGameInfoCallback::getFreeTiles(std::vector<int3> & tiles) const
 			{
 				tinfo = getTile(int3 (xd,yd,zd));
 				if (tinfo->isLand() && tinfo->getTerrain()->isPassable() && !tinfo->blocked()) //land and free
+				{
+					// Ensure that CGameHandler::spawnWanderingMonsters won't set a random monster next to another monster
+					// because Nullkiller AI is not able to go to one monster without falling into the attack range of the nearby one
+					// See GraphPaths::addChainInfo if(node.linkDanger > 0) (no link between random monsters and map monsters)
+					// Ivan: When new monster spawns, AI should receive AIGateway::newObject call for each object visible to AI. Probably you need to invalidate
+					// that data for AI & force recalculation on next turn. New queries to gamestate, like getGuardingCreaturePosition that are done either
+					// from AIGateway::newObject method or at any point later should correctly include newly spawned monsters
+					// TODO: Ensure this linking issue is properly fixed, not just with the workaround below
+					if (skipIfNearbyGuarded && guardingCreaturePosition(int3 (xd,yd,zd)).isValid())
+					{
+						continue;
+					}
+
 					tiles.emplace_back(xd, yd, zd);
+				}
 			}
 		}
 	}

+ 1 - 1
lib/callback/CGameInfoCallback.h

@@ -102,7 +102,7 @@ public:
 	bool isTeleportEntrancePassable(const CGTeleport * obj, PlayerColor player) const override;
 
 	//used for random spawns
-	void getFreeTiles(std::vector<int3> &tiles) const;
+	void getFreeTiles(std::vector<int3> &tiles, bool skipIfNearbyGuarded) const;
 	void getTilesInRange(FowTilesType & tiles, const int3 & pos, int radius, ETileVisibility mode, std::optional<PlayerColor> player = std::optional<PlayerColor>(), int3::EDistanceFormula formula = int3::DIST_2D) const override;
 	void getAllTiles(FowTilesType &tiles, std::optional<PlayerColor> player, int level, const std::function<bool(const TerrainTile *)> & filter) const override;
 

+ 1 - 1
server/CGameHandler.cpp

@@ -3995,7 +3995,7 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
 {
 	std::vector<int3>::iterator tile;
 	std::vector<int3> tiles;
-	gameState().getFreeTiles(tiles);
+	gameState().getFreeTiles(tiles, true);
 	ui32 amount = tiles.size() / 200; //Chance is 0.5% for each tile
 
 	RandomGeneratorUtil::randomShuffle(tiles, getRandomGenerator());