Browse Source

Merge pull request #2123 from Warzyw647/rmg-split-enum-monster-strength

Refactor enums and add zone monster strength "none" in rmg
DjWarmonger 2 years ago
parent
commit
e98a50b45a

+ 3 - 3
lib/rmg/CMapGenOptions.cpp

@@ -191,7 +191,7 @@ void CMapGenOptions::setStartingTownForPlayer(const PlayerColor & color, si32 to
 	it->second.setStartingTown(town);
 }
 
-void CMapGenOptions::setPlayerTypeForStandardPlayer(const PlayerColor & color, EPlayerType::EPlayerType playerType)
+void CMapGenOptions::setPlayerTypeForStandardPlayer(const PlayerColor & color, EPlayerType playerType)
 {
 	assert(playerType != EPlayerType::COMP_ONLY);
 	auto it = players.find(color);
@@ -526,12 +526,12 @@ void CMapGenOptions::CPlayerSettings::setStartingTown(si32 value)
 	startingTown = value;
 }
 
-EPlayerType::EPlayerType CMapGenOptions::CPlayerSettings::getPlayerType() const
+EPlayerType CMapGenOptions::CPlayerSettings::getPlayerType() const
 {
 	return playerType;
 }
 
-void CMapGenOptions::CPlayerSettings::setPlayerType(EPlayerType::EPlayerType value)
+void CMapGenOptions::CPlayerSettings::setPlayerType(EPlayerType value)
 {
 	playerType = value;
 }

+ 9 - 12
lib/rmg/CMapGenOptions.h

@@ -17,15 +17,12 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 class CRandomGenerator;
 
-namespace EPlayerType
+enum class EPlayerType
 {
-	enum EPlayerType
-	{
-		HUMAN,
-		AI,
-		COMP_ONLY
-	};
-}
+	HUMAN,
+	AI,
+	COMP_ONLY
+};
 
 /// The map gen options class holds values about general map generation settings
 /// e.g. the size of the map, the count of players,...
@@ -49,8 +46,8 @@ public:
 		void setStartingTown(si32 value);
 
 		/// The default value is EPlayerType::AI.
-		EPlayerType::EPlayerType getPlayerType() const;
-		void setPlayerType(EPlayerType::EPlayerType value);
+		EPlayerType getPlayerType() const;
+		void setPlayerType(EPlayerType value);
 		
 		/// Team id for this player. TeamID::NO_TEAM by default - team will be randomly assigned
 		TeamID getTeam() const;
@@ -62,7 +59,7 @@ public:
 	private:
 		PlayerColor color;
 		si32 startingTown;
-		EPlayerType::EPlayerType playerType;
+		EPlayerType playerType;
 		TeamID team;
 
 	public:
@@ -122,7 +119,7 @@ public:
 	void setStartingTownForPlayer(const PlayerColor & color, si32 town);
 	/// Sets a player type for a standard player. A standard player is the opposite of a computer only player. The
 	/// values which can be chosen for the player type are EPlayerType::AI or EPlayerType::HUMAN.
-	void setPlayerTypeForStandardPlayer(const PlayerColor & color, EPlayerType::EPlayerType playerType);
+	void setPlayerTypeForStandardPlayer(const PlayerColor & color, EPlayerType playerType);
 
 	void setPlayerTeam(const PlayerColor & color, const TeamID & team = TeamID::NO_TEAM);
 

+ 1 - 1
lib/rmg/CMapGenerator.cpp

@@ -192,7 +192,7 @@ void CMapGenerator::addPlayerInfo()
 {
 	// Calculate which team numbers exist
 
-	enum ETeams {CPHUMAN = 0, CPUONLY = 1, AFTER_LAST = 2};
+	enum ETeams {CPHUMAN = 0, CPUONLY = 1, AFTER_LAST = 2}; // Used as a kind of a local named array index, so left as enum, not enum class
 	std::array<std::list<int>, 2> teamNumbers;
 	std::set<int> teamsTotal;
 

+ 27 - 20
lib/rmg/CRmgTemplate.cpp

@@ -139,7 +139,7 @@ ZoneOptions::ZoneOptions():
 	owner(std::nullopt),
 	matchTerrainToTown(true),
 	townsAreSameType(false),
-	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
+	monsterStrength(EMonsterStrength::ZONE_NORMAL),
 	minesLikeZone(NO_ZONE),
 	terrainTypeLikeZone(NO_ZONE),
 	treasureLikeZone(NO_ZONE)
@@ -161,12 +161,12 @@ void ZoneOptions::setId(TRmgTemplateZoneId value)
 	id = value;
 }
 
-ETemplateZoneType::ETemplateZoneType ZoneOptions::getType() const
+ETemplateZoneType ZoneOptions::getType() const
 {
 	return type;
 }
 	
-void ZoneOptions::setType(ETemplateZoneType::ETemplateZoneType value)
+void ZoneOptions::setType(ETemplateZoneType value)
 {
 	type = value;
 }
@@ -377,24 +377,31 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler)
 
 	{
 		//TODO: add support for std::map to serializeEnum
-		static const std::vector<std::string> STRENGTH =
+		static const std::vector<std::string> zoneMonsterStrengths =
 		{
+			"none",
 			"weak",
 			"normal",
 			"strong"
 		};
 
-		si32 rawStrength = 0;
-		if(handler.saving)
-		{
-			rawStrength = static_cast<decltype(rawStrength)>(zoneMonsterStrength);
-			rawStrength++;
-		}
-		handler.serializeEnum("monsters", rawStrength, EMonsterStrength::ZONE_NORMAL + 1, STRENGTH);
-		if(!handler.saving)
+		int temporaryZoneMonsterStrengthIndex = monsterStrength == EMonsterStrength::ZONE_NONE ? 0 : monsterStrength - EMonsterStrength::ZONE_WEAK + 1 ; // temporary until serializeEnum starts supporting std::map
+		// temporaryZoneMonsterStrengthIndex = 0, 1, 2 and 3 for monsterStrength = ZONE_NONE, ZONE_WEAK, ZONE_NORMAL and ZONE_STRONG respectively
+		handler.serializeEnum("monsters", temporaryZoneMonsterStrengthIndex, 2, zoneMonsterStrengths); // default is normal monsters
+		switch (temporaryZoneMonsterStrengthIndex)
 		{
-			rawStrength--;
-			zoneMonsterStrength = static_cast<decltype(zoneMonsterStrength)>(rawStrength);
+			case 0:
+				monsterStrength = EMonsterStrength::ZONE_NONE;
+				break;
+			case 1:
+				monsterStrength = EMonsterStrength::ZONE_WEAK;
+				break;
+			case 2:
+				monsterStrength = EMonsterStrength::ZONE_NORMAL;
+				break;
+			case 3:
+				monsterStrength = EMonsterStrength::ZONE_STRONG;
+				break;
 		}
 	}
 
@@ -476,7 +483,7 @@ bool CRmgTemplate::matchesSize(const int3 & value) const
 
 bool CRmgTemplate::isWaterContentAllowed(EWaterContent::EWaterContent waterContent) const
 {
-	return waterContent == EWaterContent::EWaterContent::RANDOM || allowedWaterContent.count(waterContent);
+	return waterContent == EWaterContent::RANDOM || allowedWaterContent.count(waterContent);
 }
 
 const std::set<EWaterContent::EWaterContent> & CRmgTemplate::getWaterContentAllowed() const
@@ -764,13 +771,13 @@ void CRmgTemplate::afterLoad()
 		zone2->addConnection(id1);
 	}
 	
-	if(allowedWaterContent.empty() || allowedWaterContent.count(EWaterContent::EWaterContent::RANDOM))
+	if(allowedWaterContent.empty() || allowedWaterContent.count(EWaterContent::RANDOM))
 	{
-		allowedWaterContent.insert(EWaterContent::EWaterContent::NONE);
-		allowedWaterContent.insert(EWaterContent::EWaterContent::NORMAL);
-		allowedWaterContent.insert(EWaterContent::EWaterContent::ISLANDS);
+		allowedWaterContent.insert(EWaterContent::NONE);
+		allowedWaterContent.insert(EWaterContent::NORMAL);
+		allowedWaterContent.insert(EWaterContent::ISLANDS);
 	}
-	allowedWaterContent.erase(EWaterContent::EWaterContent::RANDOM);
+	allowedWaterContent.erase(EWaterContent::RANDOM);
 }
 
 void CRmgTemplate::serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName)

+ 16 - 18
lib/rmg/CRmgTemplate.h

@@ -18,21 +18,18 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 class JsonSerializeFormat;
 
-namespace ETemplateZoneType
+enum class ETemplateZoneType
 {
-	enum ETemplateZoneType
-	{
-		PLAYER_START,
-		CPU_START,
-		TREASURE,
-		JUNCTION,
-		WATER
-	};
-}
+	PLAYER_START,
+	CPU_START,
+	TREASURE,
+	JUNCTION,
+	WATER
+};
 
-namespace EWaterContent
-{
-	enum EWaterContent
+namespace EWaterContent // Not enum class, because it's used in method RandomMapTab::setMapGenOptions
+{ // defined in client\lobby\RandomMapTab.cpp and probably in other similar places
+	enum EWaterContent // as an argument of CToggleGroup::setSelected(int id) from \client\widgets\Buttons.cpp 
 	{
 		RANDOM = -1,
 		NONE,
@@ -41,10 +38,11 @@ namespace EWaterContent
 	};
 }
 
-namespace EMonsterStrength
+namespace EMonsterStrength // used as int in monster generation procedure and in map description for the generated random map
 {
 	enum EMonsterStrength
 	{
+		ZONE_NONE = -3,
 		RANDOM = -2,
 		ZONE_WEAK = -1,
 		ZONE_NORMAL = 0,
@@ -119,8 +117,8 @@ public:
 	TRmgTemplateZoneId getId() const;
 	void setId(TRmgTemplateZoneId value);
 
-	ETemplateZoneType::ETemplateZoneType getType() const;
-	void setType(ETemplateZoneType::ETemplateZoneType value);
+	ETemplateZoneType getType() const;
+	void setType(ETemplateZoneType value);
 	
 	int getSize() const;
 	void setSize(int value);
@@ -156,14 +154,14 @@ public:
 
 	void serializeJson(JsonSerializeFormat & handler);
 	
-	EMonsterStrength::EMonsterStrength zoneMonsterStrength;
+	EMonsterStrength::EMonsterStrength monsterStrength;
 	
 	bool areTownsSameType() const;
 	bool isMatchTerrainToTown() const;
 
 protected:
 	TRmgTemplateZoneId id;
-	ETemplateZoneType::ETemplateZoneType type;
+	ETemplateZoneType type;
 	int size;
 	ui32 maxTreasureValue;
 	std::optional<int> owner;

+ 3 - 0
lib/rmg/RmgMap.cpp

@@ -111,6 +111,9 @@ void RmgMap::initTiles(CMapGenerator & generator, CRandomGenerator & rand)
 			options.setType(ETemplateZoneType::WATER);
 			auto zone = std::make_shared<Zone>(*this, generator, rand);
 			zone->setOptions(options);
+			//std::set<FactionID> allowedMonsterFactions({FactionID::CASTLE, FactionID::INFERNO}); // example of filling allowed monster factions
+			//zone->setMonsterTypes(allowedMonsterFactions); // can be set here, probably from template json, along with the treasure ranges and densities
+			zone->monsterStrength = EMonsterStrength::ZONE_NONE; // can be set to other value, probably from a new field in the template json
 			zones[zone->getId()] = zone;
 			break;
 	}

+ 4 - 1
lib/rmg/modificators/ObjectManager.cpp

@@ -449,8 +449,11 @@ CGCreature * ObjectManager::chooseGuard(si32 strength, bool zoneGuard)
 	//precalculate actual (randomized) monster strength based on this post
 	//http://forum.vcmi.eu/viewtopic.php?p=12426#12426
 	
+	if(!zoneGuard && zone.monsterStrength == EMonsterStrength::ZONE_NONE)
+		return nullptr; //no guards inside this zone except for zone guards
+	
 	int mapMonsterStrength = map.getMapGenOptions().getMonsterStrength();
-	int monsterStrength = (zoneGuard ? 0 : zone.zoneMonsterStrength) + mapMonsterStrength - 1; //array index from 0 to 4
+	int monsterStrength = (zoneGuard ? 0 : zone.monsterStrength - EMonsterStrength::ZONE_NORMAL) + mapMonsterStrength - 1; //array index from 0 to 4
 	static const std::array<int, 5> value1{2500, 1500, 1000, 500, 0};
 	static const std::array<int, 5> value2{7500, 7500, 7500, 5000, 5000};
 	static const std::array<float, 5> multiplier1{0.5, 0.75, 1.0, 1.5, 1.5};

+ 3 - 4
lib/rmg/modificators/TreasurePlacer.cpp

@@ -546,8 +546,8 @@ size_t TreasurePlacer::getMaxPrisons() const
 }
 
 bool TreasurePlacer::isGuardNeededForTreasure(int value)
-{
-	return zone.getType() != ETemplateZoneType::WATER && value > minGuardedValue;
+{// no guard in a zone with "monsters: none" and for small treasures; water zones cen get monster strength ZONE_NONE elsewhere if needed
+	return zone.monsterStrength != EMonsterStrength::ZONE_NONE && value > minGuardedValue;
 }
 
 std::vector<ObjectInfo*> TreasurePlacer::prepareTreasurePile(const CTreasureInfo& treasureInfo)
@@ -706,8 +706,7 @@ void TreasurePlacer::createTreasures(ObjectManager & manager)
 	const int maxAttempts = 2;
 	
 	int mapMonsterStrength = map.getMapGenOptions().getMonsterStrength();
-	int monsterStrength = zone.zoneMonsterStrength + mapMonsterStrength - 1; //array index from 0 to 4
-	
+	int monsterStrength = (zone.monsterStrength == EMonsterStrength::ZONE_NONE ? 0 : zone.monsterStrength  + mapMonsterStrength - 1); //array index from 0 to 4; pick any correct value for ZONE_NONE, minGuardedValue won't be used in this case anyway
 	static int minGuardedValues[] = { 6500, 4167, 3000, 1833, 1333 };
 	minGuardedValue = minGuardedValues[monsterStrength];