1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge pull request #3902 from vcmi/underground_biomes

Option to define surface or underground level for obstacle set
This commit is contained in:
Ivan Savenko 2024-05-07 16:42:33 +03:00 committed by GitHub
commit 4769c86c82
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 77 additions and 7 deletions

View File

@ -10,6 +10,7 @@ If not enough biomes are defined for [terrain type](Terrain_Format.md), map gene
"obstacleSetId" : { "obstacleSetId" : {
"biome" : { "biome" : {
"terrain" : "grass", // Id or vector of Ids this obstacle set can spawn at "terrain" : "grass", // Id or vector of Ids this obstacle set can spawn at
"level" : "underground", // or "surface", by default both
"faction" : ["castle", "rampart"], //Id or vector of faction Ids. Set will only be used if zone belongs to this faction "faction" : ["castle", "rampart"], //Id or vector of faction Ids. Set will only be used if zone belongs to this faction
"alignment" : ["good", "evil", "neutral"], //Alignment of the zone. Set will only be used if zone has this alignment "alignment" : ["good", "evil", "neutral"], //Alignment of the zone. Set will only be used if zone has this alignment
"objectType": "mountain" "objectType": "mountain"

View File

@ -19,13 +19,15 @@ VCMI_LIB_NAMESPACE_BEGIN
ObstacleSet::ObstacleSet(): ObstacleSet::ObstacleSet():
type(INVALID), type(INVALID),
allowedTerrains({TerrainId::NONE}) allowedTerrains({TerrainId::NONE}),
level(EMapLevel::ANY)
{ {
} }
ObstacleSet::ObstacleSet(EObstacleType type, TerrainId terrain): ObstacleSet::ObstacleSet(EObstacleType type, TerrainId terrain):
type(type), type(type),
allowedTerrains({terrain}) allowedTerrains({terrain}),
level(EMapLevel::ANY)
{ {
} }
@ -47,17 +49,27 @@ void ObstacleSet::removeEmptyTemplates()
}); });
} }
ObstacleSetFilter::ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain = TerrainId::ANY_TERRAIN, FactionID faction = FactionID::ANY, EAlignment alignment = EAlignment::ANY): ObstacleSetFilter::ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes,
TerrainId terrain = TerrainId::ANY_TERRAIN,
ObstacleSet::EMapLevel level = ObstacleSet::EMapLevel::ANY,
FactionID faction = FactionID::ANY,
EAlignment alignment = EAlignment::ANY):
allowedTypes(allowedTypes), allowedTypes(allowedTypes),
terrain(terrain), terrain(terrain),
level(level),
faction(faction), faction(faction),
alignment(alignment) alignment(alignment)
{ {
} }
ObstacleSetFilter::ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain = TerrainId::ANY_TERRAIN, FactionID faction = FactionID::ANY, EAlignment alignment = EAlignment::ANY): ObstacleSetFilter::ObstacleSetFilter(ObstacleSet::EObstacleType allowedType,
TerrainId terrain = TerrainId::ANY_TERRAIN,
ObstacleSet::EMapLevel level = ObstacleSet::EMapLevel::ANY,
FactionID faction = FactionID::ANY,
EAlignment alignment = EAlignment::ANY):
allowedTypes({allowedType}), allowedTypes({allowedType}),
terrain(terrain), terrain(terrain),
level(level),
faction(faction), faction(faction),
alignment(alignment) alignment(alignment)
{ {
@ -70,6 +82,14 @@ bool ObstacleSetFilter::filter(const ObstacleSet &set) const
return false; return false;
} }
if (level != ObstacleSet::EMapLevel::ANY && set.getLevel() != ObstacleSet::EMapLevel::ANY)
{
if (level != set.getLevel())
{
return false;
}
}
if (faction != FactionID::ANY) if (faction != FactionID::ANY)
{ {
auto factions = set.getFactions(); auto factions = set.getFactions();
@ -117,6 +137,16 @@ void ObstacleSet::addTerrain(TerrainId terrain)
this->allowedTerrains.insert(terrain); this->allowedTerrains.insert(terrain);
} }
ObstacleSet::EMapLevel ObstacleSet::getLevel() const
{
return level;
}
void ObstacleSet::setLevel(ObstacleSet::EMapLevel newLevel)
{
level = newLevel;
}
std::set<FactionID> ObstacleSet::getFactions() const std::set<FactionID> ObstacleSet::getFactions() const
{ {
return allowedFactions; return allowedFactions;
@ -248,6 +278,22 @@ std::string ObstacleSet::toString() const
return OBSTACLE_TYPE_STRINGS.at(type); return OBSTACLE_TYPE_STRINGS.at(type);
} }
ObstacleSet::EMapLevel ObstacleSet::levelFromString(const std::string &str)
{
static const std::map<std::string, EMapLevel> LEVEL_NAMES =
{
{"surface", SURFACE},
{"underground", UNDERGROUND}
};
if (LEVEL_NAMES.find(str) != LEVEL_NAMES.end())
{
return LEVEL_NAMES.at(str);
}
throw std::runtime_error("Invalid map level: " + str);
}
std::vector<ObstacleSet::EObstacleType> ObstacleSetFilter::getAllowedTypes() const std::vector<ObstacleSet::EObstacleType> ObstacleSetFilter::getAllowedTypes() const
{ {
return allowedTypes; return allowedTypes;
@ -325,6 +371,12 @@ std::shared_ptr<ObstacleSet> ObstacleSetHandler::loadFromJson(const std::string
logMod->error("No terrain specified for obstacle set %s", name); logMod->error("No terrain specified for obstacle set %s", name);
} }
if (biome["level"].isString())
{
auto level = biome["level"].String();
os->setLevel(ObstacleSet::levelFromString(level));
}
auto handleFaction = [os, scope](const std::string & str) auto handleFaction = [os, scope](const std::string & str)
{ {
VLC->identifiers()->requestIdentifier(scope, "faction", str, [os](si32 id) VLC->identifiers()->requestIdentifier(scope, "faction", str, [os](si32 id)

View File

@ -37,6 +37,14 @@ public:
ANIMALS, // Living, or bones ANIMALS, // Living, or bones
OTHER // Crystals, shipwrecks, barrels, etc. OTHER // Crystals, shipwrecks, barrels, etc.
}; };
enum EMapLevel // TODO: Move somewhere to map definitions
{
ANY = -1,
SURFACE = 0,
UNDERGROUND = 1
};
ObstacleSet(); ObstacleSet();
explicit ObstacleSet(EObstacleType type, TerrainId terrain); explicit ObstacleSet(EObstacleType type, TerrainId terrain);
@ -51,6 +59,8 @@ public:
void setTerrain(TerrainId terrain); void setTerrain(TerrainId terrain);
void setTerrains(const std::set<TerrainId> & terrains); void setTerrains(const std::set<TerrainId> & terrains);
void addTerrain(TerrainId terrain); void addTerrain(TerrainId terrain);
EMapLevel getLevel() const;
void setLevel(EMapLevel level);
std::set<EAlignment> getAlignments() const; std::set<EAlignment> getAlignments() const;
void addAlignment(EAlignment alignment); void addAlignment(EAlignment alignment);
std::set<FactionID> getFactions() const; std::set<FactionID> getFactions() const;
@ -58,12 +68,14 @@ public:
static EObstacleType typeFromString(const std::string &str); static EObstacleType typeFromString(const std::string &str);
std::string toString() const; std::string toString() const;
static EMapLevel levelFromString(const std::string &str);
si32 id; si32 id;
private: private:
EObstacleType type; EObstacleType type;
EMapLevel level;
std::set<TerrainId> allowedTerrains; // Empty means all terrains std::set<TerrainId> allowedTerrains; // Empty means all terrains
std::set<FactionID> allowedFactions; // Empty means all factions std::set<FactionID> allowedFactions; // Empty means all factions
std::set<EAlignment> allowedAlignments; // Empty means all alignments std::set<EAlignment> allowedAlignments; // Empty means all alignments
@ -75,8 +87,8 @@ typedef std::vector<std::shared_ptr<ObstacleSet>> TObstacleTypes;
class DLL_LINKAGE ObstacleSetFilter class DLL_LINKAGE ObstacleSetFilter
{ {
public: public:
ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain, FactionID faction, EAlignment alignment); ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain, ObstacleSet::EMapLevel level, FactionID faction, EAlignment alignment);
ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain, FactionID faction, EAlignment alignment); ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, TerrainId terrain, ObstacleSet::EMapLevel level, FactionID faction, EAlignment alignment);
bool filter(const ObstacleSet &set) const; bool filter(const ObstacleSet &set) const;
@ -93,6 +105,7 @@ private:
EAlignment alignment; EAlignment alignment;
// TODO: Filter by faction, surface/underground, etc. // TODO: Filter by faction, surface/underground, etc.
const TerrainId terrain; const TerrainId terrain;
ObstacleSet::EMapLevel level;
}; };
// TODO: Instantiate ObstacleSetHandler // TODO: Instantiate ObstacleSetHandler

View File

@ -38,7 +38,11 @@ void ObstaclePlacer::process()
auto faction = zone.getTownType().toFaction(); auto faction = zone.getTownType().toFaction();
ObstacleSetFilter filter(ObstacleSet::EObstacleType::INVALID, zone.getTerrainType(), faction->getId(), faction->alignment); ObstacleSetFilter filter(ObstacleSet::EObstacleType::INVALID,
zone.getTerrainType(),
static_cast<ObstacleSet::EMapLevel>(zone.isUnderground()),
faction->getId(),
faction->alignment);
if (!prepareBiome(filter, zone.getRand())) if (!prepareBiome(filter, zone.getRand()))
{ {