Browse Source

Change cartographer tile reveal logic to match H3

M 2 years ago
parent
commit
23de4a188b
5 changed files with 70 additions and 11 deletions
  1. 26 7
      lib/IGameCallback.cpp
  2. 15 3
      lib/IGameCallback.h
  3. 10 0
      lib/Terrain.cpp
  4. 2 0
      lib/Terrain.h
  5. 17 1
      lib/mapObjects/MiscObjects.cpp

+ 26 - 7
lib/IGameCallback.cpp

@@ -67,7 +67,7 @@ void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3, ShashInt3
 		return;
 	}
 	if(radious == CBuilding::HEIGHT_SKYSHIP) //reveal entire map
-		getAllTiles (tiles, player, -1, 0);
+		getAllTiles (tiles, player, -1, MapTerrainFilterMode::NONE);
 	else
 	{
 		const TeamState * team = !player ? nullptr : gs->getPlayerTeam(*player);
@@ -91,15 +91,15 @@ void CPrivilegedInfoCallback::getTilesInRange(std::unordered_set<int3, ShashInt3
 	}
 }
 
-void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3, ShashInt3> & tiles, boost::optional<PlayerColor> Player, int level, int surface) const
+void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3, ShashInt3> & tiles, boost::optional<PlayerColor> Player, int level, MapTerrainFilterMode tileFilterMode) const
 {
 	if(!!Player && *Player >= PlayerColor::PLAYER_LIMIT)
 	{
 		logGlobal->error("Illegal call to getAllTiles !");
 		return;
 	}
-	bool water = surface == 0 || surface == 2,
-		land = surface == 0 || surface == 1;
+//	bool water = surface == 0 || surface == 2,
+//		land = surface == 0 || surface == 1;
 
 	std::vector<int> floors;
 	if(level == -1)
@@ -114,13 +114,32 @@ void CPrivilegedInfoCallback::getAllTiles(std::unordered_set<int3, ShashInt3> &
 
 	for (auto zd : floors)
 	{
-
 		for (int xd = 0; xd < gs->map->width; xd++)
 		{
 			for (int yd = 0; yd < gs->map->height; yd++)
 			{
-				if ((getTile (int3 (xd,yd,zd))->terType->isWater() && water)
-					|| (getTile (int3 (xd,yd,zd))->terType->isLand() && land))
+                bool isTileEligible = false;
+
+                switch(tileFilterMode)
+                {
+                    case MapTerrainFilterMode::NONE:
+                        isTileEligible = true;
+                        break;
+                    case MapTerrainFilterMode::WATER:
+                        isTileEligible = getTile (int3 (xd,yd,zd))->terType->isWater();
+                        break;
+                    case MapTerrainFilterMode::LAND:
+                        isTileEligible = getTile (int3 (xd,yd,zd))->terType->isLand();
+                        break;
+                    case MapTerrainFilterMode::LAND_CARTOGRAPHER:
+                        isTileEligible = getTile(int3 (xd,yd,zd))->terType->isSurfaceCartographerCompatible();
+                        break;
+                    case MapTerrainFilterMode::UNDERGROUND_CARTOGRAPHER:
+                        isTileEligible = getTile(int3 (xd,yd,zd))->terType->isUndergroundCartographerCompatible();
+                        break;
+                }
+
+				if (isTileEligible)
 					tiles.insert(int3(xd,yd,zd));
 			}
 		}

+ 15 - 3
lib/IGameCallback.h

@@ -40,10 +40,22 @@ namespace scripting
 class DLL_LINKAGE CPrivilegedInfoCallback : public CGameInfoCallback
 {
 public:
+    enum class MapTerrainFilterMode
+    {
+        NONE = 0,
+        LAND = 1,
+        WATER = 2,
+        LAND_CARTOGRAPHER = 3,
+        UNDERGROUND_CARTOGRAPHER = 4
+    };
+
 	CGameState * gameState();
-	void getFreeTiles (std::vector<int3> &tiles) const; //used for random spawns
-	void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode = 0, int3::EDistanceFormula formula = int3::DIST_2D) const; //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only revealed
-	void getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int level=-1, int surface=0) const; //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
+    //used for random spawns
+	void getFreeTiles (std::vector<int3> &tiles) const;
+    //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 -  only revealed
+	void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode = 0, int3::EDistanceFormula formula = int3::DIST_2D) const;
+    //returns all tiles on given level (-1 - both levels, otherwise number of level)
+	void getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int level=-1, MapTerrainFilterMode tileFilterMode = MapTerrainFilterMode::NONE) const;
 	void pickAllowedArtsSet(std::vector<const CArtifact*> &out, CRandomGenerator & rand); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
 	void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
 

+ 10 - 0
lib/Terrain.cpp

@@ -440,6 +440,16 @@ bool TerrainType::isUnderground() const
 	return passabilityType & PassabilityType::SUBTERRANEAN;
 }
 
+bool TerrainType::isSurfaceCartographerCompatible() const
+{
+	return isLand() && id != Terrain::SUBTERRANEAN && id != Terrain::ROCK;
+}
+
+bool TerrainType::isUndergroundCartographerCompatible() const
+{
+	return isLand() && id == Terrain::SUBTERRANEAN;
+}
+
 bool TerrainType::isTransitionRequired() const
 {
 	return transitionRequired;

+ 2 - 0
lib/Terrain.h

@@ -60,6 +60,8 @@ public:
 	bool isSurface() const;
 	bool isUnderground() const;
 	bool isTransitionRequired() const;
+    bool isSurfaceCartographerCompatible() const;
+    bool isUndergroundCartographerCompatible() const;
 		
 	operator std::string() const;
 	

+ 17 - 1
lib/mapObjects/MiscObjects.cpp

@@ -2077,7 +2077,23 @@ void CCartographer::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answ
 
 		//subIDs of different types of cartographers:
 		//water = 0; land = 1; underground = 2;
-		cb->getAllTiles (fw.tiles, hero->tempOwner, subID - 1, !subID + 1); //reveal appropriate tiles
+
+        IGameCallback::MapTerrainFilterMode tileFilterMode = IGameCallback::MapTerrainFilterMode::NONE;
+
+        switch(subID)
+        {
+            case 0:
+                tileFilterMode = CPrivilegedInfoCallback::MapTerrainFilterMode::WATER;
+                break;
+            case 1:
+                tileFilterMode = CPrivilegedInfoCallback::MapTerrainFilterMode::LAND_CARTOGRAPHER;
+                break;
+            case 2:
+                tileFilterMode = CPrivilegedInfoCallback::MapTerrainFilterMode::UNDERGROUND_CARTOGRAPHER;
+                break;
+        }
+
+		cb->getAllTiles (fw.tiles, hero->tempOwner, -1, tileFilterMode); //reveal appropriate tiles
 		cb->sendAndApply (&fw);
 		cb->setObjProperty (id, CCartographer::OBJPROP_VISITED, hero->tempOwner.getNum());
 	}