mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Move all OH3 objects and obstacle sets to a mod
This commit is contained in:
parent
86cffb3a77
commit
3e3959d360
@ -37,6 +37,7 @@ void CGameInfo::setFromLib()
|
||||
terrainTypeHandler = VLC->terrainTypeHandler;
|
||||
battleFieldHandler = VLC->battlefieldsHandler;
|
||||
obstacleHandler = VLC->obstacleHandler;
|
||||
//TODO: biomeHandler?
|
||||
}
|
||||
|
||||
const ArtifactService * CGameInfo::artifacts() const
|
||||
|
1320
config/biomes.json
Normal file
1320
config/biomes.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -67,6 +67,11 @@
|
||||
"config/objects/witchHut.json"
|
||||
],
|
||||
|
||||
"biomes" :
|
||||
[
|
||||
"config/biomes.json"
|
||||
],
|
||||
|
||||
"artifacts" :
|
||||
[
|
||||
"config/artifacts.json"
|
||||
|
31
config/schemas/biome.json
Normal file
31
config/schemas/biome.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"type" : "object",
|
||||
"$schema" : "http://json-schema.org/draft-04/schema",
|
||||
"title" : "VCMI map obstacle set format",
|
||||
"description" : "Description of map object set, used only as sub-schema of object",
|
||||
"required" : ["biome", "templates"],
|
||||
"additionalProperties" : true, // may have type-dependant properties
|
||||
"properties" : {
|
||||
"biome" : {
|
||||
"type" : "object",
|
||||
"properties": {
|
||||
"objectType" : {
|
||||
"type" : "string",
|
||||
"enmum": ["mountain", "tree", "lake", "crater", "rock", "plant", "structure", "animal", "other"],
|
||||
"description" : "Type of the obstacle set"
|
||||
},
|
||||
"terrain" : {
|
||||
// TODO: Allow multiple terrains
|
||||
"type" : "string",
|
||||
"description" : "Terrain of the obstacle set"
|
||||
}
|
||||
}
|
||||
},
|
||||
"templates" : {
|
||||
"type" : "array",
|
||||
"items" : { "type" : "string" },
|
||||
"description" : "Object templates of the obstacle set"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -482,6 +482,7 @@ public:
|
||||
OUTCROPPING = 136,
|
||||
PINE_TREES = 137,
|
||||
PLANT = 138,
|
||||
RIVER_DELTA = 143,
|
||||
ROCK = 147,
|
||||
SAND_DUNE = 148,
|
||||
SAND_PIT = 149,
|
||||
|
@ -108,7 +108,9 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData()
|
||||
auto totalNumber = static_cast<size_t>(parser.readNumber()); // first line contains number of objects to read and nothing else
|
||||
parser.endLine();
|
||||
|
||||
std::map<TerrainId, std::map<MapObjectID, std::map<MapObjectSubID, ObstacleSet>>> obstacleSets;
|
||||
//std::map<TerrainId, std::map<MapObjectID, std::map<MapObjectSubID, ObstacleSet>>> obstacleSets;
|
||||
|
||||
// TODO: Create map defName -> tmpl
|
||||
|
||||
for (size_t i = 0; i < totalNumber; i++)
|
||||
{
|
||||
@ -120,44 +122,15 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData()
|
||||
std::pair key(tmpl->id, tmpl->subid);
|
||||
legacyTemplates.insert(std::make_pair(key, tmpl));
|
||||
|
||||
// Populate ObstacleSetHandler on our way
|
||||
if (!tmpl->isVisitable())
|
||||
{
|
||||
// Create obstacle sets. Group by terrain for now
|
||||
|
||||
for (auto terrain : tmpl->getAllowedTerrains())
|
||||
if (tmpl->id != Obj::RIVER_DELTA)
|
||||
{
|
||||
auto &obstacleMap = obstacleSets[terrain][tmpl->id];
|
||||
auto it = obstacleMap.find(tmpl->subid);
|
||||
if (it == obstacleMap.end())
|
||||
{
|
||||
// FIXME: This means this set will be available only on one terrain
|
||||
auto type = VLC->biomeHandler->convertObstacleClass(tmpl->id);
|
||||
auto newIt = obstacleMap.insert(std::make_pair(tmpl->subid, ObstacleSet(type, terrain)));
|
||||
newIt.first->second.addObstacle(tmpl);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second.addObstacle(tmpl);
|
||||
}
|
||||
VLC->biomeHandler->addTemplate("core", tmpl->stringID, tmpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
for (auto terrain : obstacleSets)
|
||||
{
|
||||
for (auto obstacleType : terrain.second)
|
||||
{
|
||||
for (auto obstacleSet : obstacleType.second)
|
||||
{
|
||||
VLC->biomeHandler->addObstacleSet(obstacleSet.second);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
logGlobal->info("Obstacle sets loaded: %d", count);
|
||||
|
||||
objects.resize(256);
|
||||
|
||||
std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
|
||||
|
@ -64,10 +64,10 @@ void CObstacleConstructor::afterLoadFinalization()
|
||||
// For now assume that all templates are from the same biome
|
||||
for (auto terrain : terrains)
|
||||
{
|
||||
ObstacleSet os(obstacleType, terrain);
|
||||
std::shared_ptr<ObstacleSet> os = std::make_shared<ObstacleSet>(obstacleType, terrain);
|
||||
for (auto tmpl : templates)
|
||||
{
|
||||
os.addObstacle(tmpl);
|
||||
os->addObstacle(tmpl);
|
||||
}
|
||||
VLC->biomeHandler->addObstacleSet(os);
|
||||
logGlobal->info("Loaded obstacle set from mod %s, terrain: %s", getJsonKey(), terrain.encode(terrain.getNum()));
|
||||
|
@ -11,8 +11,16 @@
|
||||
#include "StdInc.h"
|
||||
#include "ObstacleSetHandler.h"
|
||||
|
||||
#include "../modding/IdentifierStorage.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
ObstacleSet::ObstacleSet():
|
||||
type(INVALID),
|
||||
terrain(TerrainId::NONE)
|
||||
{
|
||||
}
|
||||
|
||||
ObstacleSet::ObstacleSet(EObstacleType type, TerrainId terrain):
|
||||
type(type),
|
||||
terrain(terrain)
|
||||
@ -51,11 +59,21 @@ TerrainId ObstacleSet::getTerrain() const
|
||||
return terrain;
|
||||
}
|
||||
|
||||
void ObstacleSet::setTerrain(TerrainId terrain)
|
||||
{
|
||||
this->terrain = terrain;
|
||||
}
|
||||
|
||||
ObstacleSet::EObstacleType ObstacleSet::getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void ObstacleSet::setType(EObstacleType type)
|
||||
{
|
||||
this->type = type;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<const ObjectTemplate>> ObstacleSet::getObstacles() const
|
||||
{
|
||||
return obstacles;
|
||||
@ -139,14 +157,128 @@ ObstacleSet::EObstacleType ObstacleSet::typeFromString(const std::string &str)
|
||||
throw std::runtime_error("Invalid obstacle type: " + str);
|
||||
}
|
||||
|
||||
std::string ObstacleSet::toString() const
|
||||
{
|
||||
static const std::map<EObstacleType, std::string> OBSTACLE_TYPE_STRINGS =
|
||||
{
|
||||
{MOUNTAINS, "mountain"},
|
||||
{TREES, "tree"},
|
||||
{LAKES, "lake"},
|
||||
{CRATERS, "crater"},
|
||||
{ROCKS, "rock"},
|
||||
{PLANTS, "plant"},
|
||||
{STRUCTURES, "structure"},
|
||||
{ANIMALS, "animal"},
|
||||
{OTHER, "other"}
|
||||
};
|
||||
|
||||
return OBSTACLE_TYPE_STRINGS.at(type);
|
||||
}
|
||||
|
||||
std::vector<ObstacleSet::EObstacleType> ObstacleSetFilter::getAllowedTypes() const
|
||||
{
|
||||
return allowedTypes;
|
||||
}
|
||||
|
||||
void ObstacleSetHandler::addObstacleSet(const ObstacleSet &os)
|
||||
std::vector<JsonNode> ObstacleSetHandler::loadLegacyData()
|
||||
{
|
||||
obstacleSets[os.getType()].push_back(os);
|
||||
// TODO: Where to load objects.json?
|
||||
return {};
|
||||
}
|
||||
|
||||
void ObstacleSetHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
|
||||
{
|
||||
auto os = loadFromJson(scope, data, name, biomes.size());
|
||||
if(os)
|
||||
{
|
||||
addObstacleSet(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
logMod->error("Failed to load obstacle set: %s", name);
|
||||
}
|
||||
// TODO: Define some const array of object types ("biome" etc.)
|
||||
VLC->identifiersHandler->registerObject(scope, "biome", name, biomes.back()->id);
|
||||
}
|
||||
|
||||
void ObstacleSetHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
|
||||
{
|
||||
assert(objects.at(index) == nullptr); // ensure that this id was not loaded before
|
||||
|
||||
auto os = loadFromJson(scope, data, name, index);
|
||||
if(os)
|
||||
{
|
||||
addObstacleSet(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
logMod->error("Failed to load obstacle set: %s", name);
|
||||
}
|
||||
// TODO:
|
||||
VLC->identifiersHandler->registerObject(scope, "biome", name, biomes.at(index)->id);
|
||||
}
|
||||
|
||||
std::shared_ptr<ObstacleSet> ObstacleSetHandler::loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index)
|
||||
{
|
||||
auto os = std::make_shared<ObstacleSet>();
|
||||
|
||||
// TODO: Register ObstacleSet by its name
|
||||
|
||||
auto biome = json["biome"].Struct();
|
||||
os->setType(ObstacleSet::typeFromString(biome["objectType"].String()));
|
||||
|
||||
auto terrainName = biome["terrain"].String();
|
||||
|
||||
VLC->identifiers()->requestIdentifier(scope, "terrain", terrainName, [this, os](si32 id)
|
||||
{
|
||||
os->setTerrain(TerrainId(id));
|
||||
});
|
||||
|
||||
auto templates = json["templates"].Vector();
|
||||
for (const auto & node : templates)
|
||||
{
|
||||
// TODO: We need to store all the templates by their name
|
||||
// TODO: We need to store all the templates by their id
|
||||
|
||||
logGlobal->info("Registering obstacle template: %s", node.String());
|
||||
/*
|
||||
FIXME:
|
||||
Warning: identifier AVXplns0 is not in camelCase!
|
||||
registered biome.templateSet1 as core:1701602145
|
||||
*/
|
||||
|
||||
VLC->identifiers()->requestIdentifier(scope, "obstacleTemplate", node.String(), [this, os](si32 id)
|
||||
{
|
||||
logGlobal->info("Resolved obstacle id: %d", id);
|
||||
os->addObstacle(obstacleTemplates[id]);
|
||||
});
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
void ObstacleSetHandler::addTemplate(const std::string & scope, const std::string &name, std::shared_ptr<const ObjectTemplate> tmpl)
|
||||
{
|
||||
auto id = obstacleTemplates.size();
|
||||
|
||||
auto strippedName = name;
|
||||
auto pos = strippedName.find(".def");
|
||||
if(pos != std::string::npos)
|
||||
strippedName.erase(pos, 4);
|
||||
|
||||
// TODO: Consider converting to lowercase?
|
||||
// Save by name
|
||||
VLC->identifiersHandler->registerObject(scope, "obstacleTemplate", strippedName, id);
|
||||
|
||||
// Index by id
|
||||
obstacleTemplates[id] = tmpl;
|
||||
}
|
||||
|
||||
void ObstacleSetHandler::addObstacleSet(std::shared_ptr<ObstacleSet> os)
|
||||
{
|
||||
// TODO: Allow to refer to existing obstacle set by its id (name)
|
||||
obstacleSets[os->getType()].push_back(os);
|
||||
biomes.push_back(os);
|
||||
}
|
||||
|
||||
TObstacleTypes ObstacleSetHandler::getObstacles( const ObstacleSetFilter &filter) const
|
||||
@ -160,7 +292,7 @@ TObstacleTypes ObstacleSetHandler::getObstacles( const ObstacleSetFilter &filter
|
||||
{
|
||||
for (const auto &os : it->second)
|
||||
{
|
||||
if (filter.filter(os))
|
||||
if (filter.filter(*os))
|
||||
{
|
||||
result.push_back(os);
|
||||
}
|
||||
|
@ -37,15 +37,22 @@ public:
|
||||
ANIMALS, // Living, or bones
|
||||
OTHER // Crystals, shipwrecks, barrels, etc.
|
||||
};
|
||||
ObstacleSet();
|
||||
explicit ObstacleSet(EObstacleType type, TerrainId terrain);
|
||||
|
||||
void addObstacle(std::shared_ptr<const ObjectTemplate> obstacle);
|
||||
std::vector<std::shared_ptr<const ObjectTemplate>> getObstacles() const;
|
||||
|
||||
EObstacleType getType() const;
|
||||
void setType(EObstacleType type);
|
||||
|
||||
TerrainId getTerrain() const;
|
||||
void setTerrain(TerrainId terrain);
|
||||
|
||||
static EObstacleType typeFromString(const std::string &str);
|
||||
std::string toString() const;
|
||||
|
||||
si32 id;
|
||||
|
||||
private:
|
||||
EObstacleType type;
|
||||
@ -53,7 +60,7 @@ private:
|
||||
std::vector<std::shared_ptr<const ObjectTemplate>> obstacles;
|
||||
};
|
||||
|
||||
typedef std::vector<ObstacleSet> TObstacleTypes;
|
||||
typedef std::vector<std::shared_ptr<ObstacleSet>> TObstacleTypes;
|
||||
|
||||
class DLL_LINKAGE ObstacleSetFilter
|
||||
{
|
||||
@ -80,22 +87,29 @@ public:
|
||||
ObstacleSetHandler() = default;
|
||||
~ObstacleSetHandler() = default;
|
||||
|
||||
// FIXME: Not needed at all
|
||||
std::vector<JsonNode> loadLegacyData() override {return {};};
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override {};
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override {};
|
||||
std::vector<JsonNode> loadLegacyData() override;
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||
std::shared_ptr<ObstacleSet> loadFromJson(const std::string & scope, const JsonNode & json, const std::string & name, size_t index);
|
||||
|
||||
ObstacleSet::EObstacleType convertObstacleClass(MapObjectID id);
|
||||
|
||||
// TODO: Populate obstacleSets with all the obstacle sets from the game data
|
||||
void addTemplate(const std::string & scope, const std::string &name, std::shared_ptr<const ObjectTemplate> tmpl);
|
||||
|
||||
void addObstacleSet(const ObstacleSet &set);
|
||||
void addObstacleSet(std::shared_ptr<ObstacleSet> set);
|
||||
|
||||
TObstacleTypes getObstacles(const ObstacleSetFilter &filter) const;
|
||||
|
||||
private:
|
||||
|
||||
std::map<ObstacleSet::EObstacleType, std::vector<ObstacleSet>> obstacleSets;
|
||||
std::vector< std::shared_ptr<ObstacleSet> > biomes;
|
||||
|
||||
// TODO: Serialize?
|
||||
std::map<si32, std::shared_ptr<const ObjectTemplate>> obstacleTemplates;
|
||||
|
||||
// FIXME: Store pointers?
|
||||
std::map<ObstacleSet::EObstacleType, std::vector<std::shared_ptr<ObstacleSet>>> obstacleSets;
|
||||
};
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
@ -58,7 +58,9 @@ bool ObstacleProxy::prepareBiome(TerrainId terrain, CRandomGenerator & rand)
|
||||
|
||||
possibleObstacles.clear();
|
||||
|
||||
std::vector<ObstacleSet> obstacleSets;
|
||||
// TODO: Move this logic to ObstacleSetHandler
|
||||
|
||||
std::vector<std::shared_ptr<ObstacleSet>> obstacleSets;
|
||||
|
||||
size_t selectedSets = 0;
|
||||
const size_t MINIMUM_SETS = 6;
|
||||
@ -103,7 +105,7 @@ bool ObstacleProxy::prepareBiome(TerrainId terrain, CRandomGenerator & rand)
|
||||
selectedSets++;
|
||||
|
||||
// TODO: Convert to string
|
||||
logGlobal->info("Added large set of type %s", obstacleSets.back().getType());
|
||||
logGlobal->info("Added large set of type %s", obstacleSets.back()->getType());
|
||||
}
|
||||
|
||||
TObstacleTypes rockSets = VLC->biomeHandler->getObstacles(ObstacleSetFilter(ObstacleSet::EObstacleType::ROCKS, terrain));
|
||||
@ -152,7 +154,7 @@ bool ObstacleProxy::prepareBiome(TerrainId terrain, CRandomGenerator & rand)
|
||||
smallObstacleSets.pop_back();
|
||||
selectedSets++;
|
||||
smallSets--;
|
||||
logGlobal->info("Added small set of type %s", obstacleSets.back().getType());
|
||||
logGlobal->info("Added small set of type %s", obstacleSets.back()->getType());
|
||||
}
|
||||
else if(otherSets.empty())
|
||||
{
|
||||
@ -183,7 +185,7 @@ bool ObstacleProxy::prepareBiome(TerrainId terrain, CRandomGenerator & rand)
|
||||
obstaclesBySize.clear();
|
||||
for (const auto & os : obstacleSets)
|
||||
{
|
||||
for (const auto & temp : os.getObstacles())
|
||||
for (const auto & temp : os->getObstacles())
|
||||
{
|
||||
if(temp->getBlockMapOffset().valid())
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "../IHandlerBase.h"
|
||||
#include "../Languages.h"
|
||||
#include "../ObstacleHandler.h"
|
||||
#include "../mapObjects/ObstacleSetHandler.h"
|
||||
#include "../RiverHandler.h"
|
||||
#include "../RoadHandler.h"
|
||||
#include "../ScriptHandler.h"
|
||||
@ -207,7 +208,7 @@ void CContentHandler::init()
|
||||
handlers.insert(std::make_pair("rivers", ContentTypeHandler(VLC->riverTypeHandler.get(), "river")));
|
||||
handlers.insert(std::make_pair("roads", ContentTypeHandler(VLC->roadTypeHandler.get(), "road")));
|
||||
handlers.insert(std::make_pair("obstacles", ContentTypeHandler(VLC->obstacleHandler.get(), "obstacle")));
|
||||
//TODO: any other types of moddables?
|
||||
handlers.insert(std::make_pair("biomes", ContentTypeHandler(VLC->biomeHandler.get(), "biome")));
|
||||
}
|
||||
|
||||
bool CContentHandler::preloadModData(const std::string & modName, JsonNode modConfig, bool validate)
|
||||
|
Loading…
Reference in New Issue
Block a user