/* * CRmgTemplate.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once #include "../int3.h" #include "../GameConstants.h" #include "../ResourceSet.h" #include "ObjectInfo.h" #include "ObjectConfig.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" VCMI_LIB_NAMESPACE_BEGIN class JsonSerializeFormat; struct CompoundMapObjectID; enum class ETemplateZoneType { PLAYER_START, CPU_START, TREASURE, JUNCTION, WATER, SEALED }; 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, NORMAL, ISLANDS }; } 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, ZONE_STRONG = 1, GLOBAL_WEAK = 2, GLOBAL_NORMAL = 3, GLOBAL_STRONG = 4 }; } class DLL_LINKAGE CTreasureInfo { public: ui32 min; ui32 max; ui16 density; CTreasureInfo(); CTreasureInfo(ui32 min, ui32 max, ui16 density); bool operator ==(const CTreasureInfo & other) const; void serializeJson(JsonSerializeFormat & handler); }; namespace rmg { enum class EConnectionType { GUARDED = 0, //default FICTIVE, REPULSIVE, WIDE, FORCE_PORTAL }; enum class ERoadOption { ROAD_TRUE, ROAD_FALSE, ROAD_RANDOM }; class DLL_LINKAGE ZoneConnection { public: ZoneConnection(); int getId() const; void setId(int id); TRmgTemplateZoneId getZoneA() const; TRmgTemplateZoneId getZoneB() const; TRmgTemplateZoneId getOtherZoneId(TRmgTemplateZoneId id) const; int getGuardStrength() const; rmg::EConnectionType getConnectionType() const; rmg::ERoadOption getRoadOption() const; void serializeJson(JsonSerializeFormat & handler); friend bool operator==(const ZoneConnection &, const ZoneConnection &); private: int id; TRmgTemplateZoneId zoneA; TRmgTemplateZoneId zoneB; int guardStrength; rmg::EConnectionType connectionType; rmg::ERoadOption hasRoad; }; class DLL_LINKAGE ZoneOptions { public: static const TRmgTemplateZoneId NO_ZONE; class DLL_LINKAGE CTownInfo { public: CTownInfo(); int getTownCount() const; int getCastleCount() const; int getTownDensity() const; int getCastleDensity() const; void serializeJson(JsonSerializeFormat & handler); private: int townCount; int castleCount; int townDensity; int castleDensity; // TODO: Copy from another zone once its randomized TRmgTemplateZoneId sourceZone = NO_ZONE; }; ZoneOptions(); TRmgTemplateZoneId getId() const; void setId(TRmgTemplateZoneId value); ETemplateZoneType getType() const; void setType(ETemplateZoneType value); int getSize() const; void setSize(int value); std::optional getOwner() const; std::set getTerrainTypes() const; void setTerrainTypes(const std::set & value); std::set getDefaultTerrainTypes() const; const CTownInfo & getPlayerTowns() const; const CTownInfo & getNeutralTowns() const; std::set getDefaultTownTypes() const; std::set getTownTypes() const; std::set getMonsterTypes() const; void setTownTypes(const std::set & value); void setMonsterTypes(const std::set & value); void setMinesInfo(const std::map & value); std::map getMinesInfo() const; void setTreasureInfo(const std::vector & value); void addTreasureInfo(const CTreasureInfo & value); std::vector getTreasureInfo() const; ui32 getMaxTreasureValue() const; void recalculateMaxTreasureValue(); TRmgTemplateZoneId getMinesLikeZone() const; TRmgTemplateZoneId getTerrainTypeLikeZone() const; TRmgTemplateZoneId getTreasureLikeZone() const; void addConnection(const ZoneConnection & connection); std::vector getConnections() const; std::vector getConnectedZoneIds() const; void serializeJson(JsonSerializeFormat & handler); EMonsterStrength::EMonsterStrength monsterStrength; bool areTownsSameType() const; bool isMatchTerrainToTown() const; // Get a group of configured objects const std::vector & getBannedObjects() const; const std::vector & getBannedObjectCategories() const; const std::vector & getConfiguredObjects() const; // Copy whole custom object config from another zone ObjectConfig getCustomObjects() const; void setCustomObjects(const ObjectConfig & value); TRmgTemplateZoneId getCustomObjectsLikeZone() const; protected: TRmgTemplateZoneId id; ETemplateZoneType type; int size; ui32 maxTreasureValue; std::optional owner; ObjectConfig objectConfig; CTownInfo playerTowns; CTownInfo neutralTowns; bool matchTerrainToTown; std::set terrainTypes; std::set bannedTerrains; bool townsAreSameType; std::set townTypes; std::set bannedTownTypes; std::set monsterTypes; std::set bannedMonsters; std::map mines; //obligatory mines to spawn in this zone std::vector treasureInfo; std::vector connectedZoneIds; //list of adjacent zone ids std::vector connectionDetails; //list of connections linked to that zone TRmgTemplateZoneId minesLikeZone; TRmgTemplateZoneId terrainTypeLikeZone; TRmgTemplateZoneId treasureLikeZone; TRmgTemplateZoneId customObjectsLikeZone; }; } /// The CRmgTemplate describes a random map template. class DLL_LINKAGE CRmgTemplate : boost::noncopyable { public: using Zones = std::map>; class DLL_LINKAGE CPlayerCountRange { public: void addRange(int lower, int upper); void addNumber(int value); bool isInRange(int count) const; std::set getNumbers() const; std::string toString() const; void fromString(const std::string & value); int maxValue() const; int minValue() const; private: std::vector > range; }; CRmgTemplate(); ~CRmgTemplate(); bool matchesSize(const int3 & value) const; bool isWaterContentAllowed(EWaterContent::EWaterContent waterContent) const; const std::set & getWaterContentAllowed() const; void setId(const std::string & value); void setName(const std::string & value); const std::string & getId() const; const std::string & getName() const; const std::string & getDescription() const; const CPlayerCountRange & getPlayers() const; const CPlayerCountRange & getHumanPlayers() const; std::pair getMapSizes() const; const Zones & getZones() const; const JsonNode & getMapSettings() const; const std::vector & getConnectedZoneIds() const; void validate() const; /// Tests template on validity and throws exception on failure void serializeJson(JsonSerializeFormat & handler); void afterLoad(); private: std::string id; std::string name; std::string description; int3 minSize; int3 maxSize; CPlayerCountRange players; CPlayerCountRange humanPlayers; Zones zones; std::vector connections; std::set allowedWaterContent; std::unique_ptr mapSettings; std::set inheritTerrainType(std::shared_ptr zone, uint32_t iteration = 0); std::map inheritMineTypes(std::shared_ptr zone, uint32_t iteration = 0); std::vector inheritTreasureInfo(std::shared_ptr zone, uint32_t iteration = 0); // TODO: Copy custom object settings // TODO: Copy town type after source town is actually randomized void serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName); void serializePlayers(JsonSerializeFormat & handler, CPlayerCountRange & value, const std::string & fieldName); template T inheritZoneProperty(std::shared_ptr zone, T (rmg::ZoneOptions::*getter)() const, void (rmg::ZoneOptions::*setter)(const T&), TRmgTemplateZoneId (rmg::ZoneOptions::*inheritFrom)() const, const std::string& propertyString, uint32_t iteration = 0); }; VCMI_LIB_NAMESPACE_END