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:
commit
4769c86c82
@ -10,6 +10,7 @@ If not enough biomes are defined for [terrain type](Terrain_Format.md), map gene
|
||||
"obstacleSetId" : {
|
||||
"biome" : {
|
||||
"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
|
||||
"alignment" : ["good", "evil", "neutral"], //Alignment of the zone. Set will only be used if zone has this alignment
|
||||
"objectType": "mountain"
|
||||
|
@ -19,13 +19,15 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
ObstacleSet::ObstacleSet():
|
||||
type(INVALID),
|
||||
allowedTerrains({TerrainId::NONE})
|
||||
allowedTerrains({TerrainId::NONE}),
|
||||
level(EMapLevel::ANY)
|
||||
{
|
||||
}
|
||||
|
||||
ObstacleSet::ObstacleSet(EObstacleType type, TerrainId terrain):
|
||||
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),
|
||||
terrain(terrain),
|
||||
level(level),
|
||||
faction(faction),
|
||||
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}),
|
||||
terrain(terrain),
|
||||
level(level),
|
||||
faction(faction),
|
||||
alignment(alignment)
|
||||
{
|
||||
@ -70,6 +82,14 @@ bool ObstacleSetFilter::filter(const ObstacleSet &set) const
|
||||
return false;
|
||||
}
|
||||
|
||||
if (level != ObstacleSet::EMapLevel::ANY && set.getLevel() != ObstacleSet::EMapLevel::ANY)
|
||||
{
|
||||
if (level != set.getLevel())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (faction != FactionID::ANY)
|
||||
{
|
||||
auto factions = set.getFactions();
|
||||
@ -117,6 +137,16 @@ void ObstacleSet::addTerrain(TerrainId 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
|
||||
{
|
||||
return allowedFactions;
|
||||
@ -248,6 +278,22 @@ std::string ObstacleSet::toString() const
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if (biome["level"].isString())
|
||||
{
|
||||
auto level = biome["level"].String();
|
||||
os->setLevel(ObstacleSet::levelFromString(level));
|
||||
}
|
||||
|
||||
auto handleFaction = [os, scope](const std::string & str)
|
||||
{
|
||||
VLC->identifiers()->requestIdentifier(scope, "faction", str, [os](si32 id)
|
||||
|
@ -37,6 +37,14 @@ public:
|
||||
ANIMALS, // Living, or bones
|
||||
OTHER // Crystals, shipwrecks, barrels, etc.
|
||||
};
|
||||
|
||||
enum EMapLevel // TODO: Move somewhere to map definitions
|
||||
{
|
||||
ANY = -1,
|
||||
SURFACE = 0,
|
||||
UNDERGROUND = 1
|
||||
};
|
||||
|
||||
ObstacleSet();
|
||||
explicit ObstacleSet(EObstacleType type, TerrainId terrain);
|
||||
|
||||
@ -51,6 +59,8 @@ public:
|
||||
void setTerrain(TerrainId terrain);
|
||||
void setTerrains(const std::set<TerrainId> & terrains);
|
||||
void addTerrain(TerrainId terrain);
|
||||
EMapLevel getLevel() const;
|
||||
void setLevel(EMapLevel level);
|
||||
std::set<EAlignment> getAlignments() const;
|
||||
void addAlignment(EAlignment alignment);
|
||||
std::set<FactionID> getFactions() const;
|
||||
@ -58,12 +68,14 @@ public:
|
||||
|
||||
static EObstacleType typeFromString(const std::string &str);
|
||||
std::string toString() const;
|
||||
static EMapLevel levelFromString(const std::string &str);
|
||||
|
||||
si32 id;
|
||||
|
||||
private:
|
||||
|
||||
EObstacleType type;
|
||||
EMapLevel level;
|
||||
std::set<TerrainId> allowedTerrains; // Empty means all terrains
|
||||
std::set<FactionID> allowedFactions; // Empty means all factions
|
||||
std::set<EAlignment> allowedAlignments; // Empty means all alignments
|
||||
@ -75,8 +87,8 @@ typedef std::vector<std::shared_ptr<ObstacleSet>> TObstacleTypes;
|
||||
class DLL_LINKAGE ObstacleSetFilter
|
||||
{
|
||||
public:
|
||||
ObstacleSetFilter(ObstacleSet::EObstacleType allowedType, TerrainId terrain, FactionID faction, EAlignment alignment);
|
||||
ObstacleSetFilter(std::vector<ObstacleSet::EObstacleType> allowedTypes, 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, ObstacleSet::EMapLevel level, FactionID faction, EAlignment alignment);
|
||||
|
||||
bool filter(const ObstacleSet &set) const;
|
||||
|
||||
@ -93,6 +105,7 @@ private:
|
||||
EAlignment alignment;
|
||||
// TODO: Filter by faction, surface/underground, etc.
|
||||
const TerrainId terrain;
|
||||
ObstacleSet::EMapLevel level;
|
||||
};
|
||||
|
||||
// TODO: Instantiate ObstacleSetHandler
|
||||
|
@ -38,7 +38,11 @@ void ObstaclePlacer::process()
|
||||
|
||||
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()))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user