1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-29 23:07:48 +02:00

Extended building dependencies:

- buiding/structure lists must use object format. This may break some
outdated mods.
- generic support for logical expressions that consist from and/or/not
operators.
- string ID's for buidings are now actually used.
This commit is contained in:
Ivan Savenko
2013-12-02 11:58:02 +00:00
parent 1e619c95bc
commit ee1b0459e6
16 changed files with 717 additions and 289 deletions

View File

@@ -260,7 +260,31 @@ std::vector<JsonNode> CTownHandler::loadLegacyData(size_t dataSize)
return dest;
}
void CTownHandler::loadBuilding(CTown &town, const JsonNode & source)
void CTownHandler::loadBuildingRequirements(CTown &town, CBuilding & building, const JsonNode & source)
{
if (source.isNull())
return;
if (source.Vector()[0].getType() == JsonNode::DATA_FLOAT)
{
// MODS COMPATIBILITY
CBuilding::TRequired::OperatorAll required;
for(const JsonNode &building : source.Vector())
required.expressions.push_back(BuildingID(building.Float()));
building.requirements = CBuilding::TRequired(required);
}
else
{
BuildingRequirementsHelper hlp;
hlp.building = &building;
hlp.faction = town.faction;
hlp.json = source;
requirementsToLoad.push_back(hlp);
}
}
void CTownHandler::loadBuilding(CTown &town, const std::string & stringID, const JsonNode & source)
{
auto ret = new CBuilding;
@@ -268,65 +292,71 @@ void CTownHandler::loadBuilding(CTown &town, const JsonNode & source)
ret->mode = static_cast<CBuilding::EBuildMode>(boost::find(modes, source["mode"].String()) - modes);
ret->identifier = stringID;
ret->town = &town;
ret->bid = BuildingID(source["id"].Float());
ret->name = source["name"].String();
ret->description = source["description"].String();
ret->resources = TResources(source["cost"]);
for(const JsonNode &building : source["requires"].Vector())
ret->requirements.insert(BuildingID(building.Float()));
loadBuildingRequirements(town, *ret, source["requires"]);
if (!source["upgrades"].isNull())
{
ret->requirements.insert(BuildingID(source["upgrades"].Float()));
ret->upgrade = BuildingID(source["upgrades"].Float());
}
else
ret->upgrade = BuildingID::NONE;
town.buildings[ret->bid] = ret;
VLC->modh->identifiers.registerObject(source.meta, "building." + town.faction->identifier, ret->identifier, ret->bid);
}
void CTownHandler::loadBuildings(CTown &town, const JsonNode & source)
{
if (source.getType() == JsonNode::DATA_VECTOR)
for(auto &node : source.Struct())
{
for(auto &node : source.Vector())
if (!node.second.isNull())
{
if (!node.isNull())
loadBuilding(town, node);
}
}
else
{
for(auto &node : source.Struct())
{
if (!node.second.isNull())
loadBuilding(town, node.second);
loadBuilding(town, node.first, node.second);
}
}
}
void CTownHandler::loadStructure(CTown &town, const JsonNode & source)
void CTownHandler::loadStructure(CTown &town, const std::string & stringID, const JsonNode & source)
{
auto ret = new CStructure;
auto ret = new CStructure;
if (source["id"].isNull())
//Note: MODS COMPATIBILITY CODE
ret->building = nullptr;
ret->buildable = nullptr;
VLC->modh->identifiers.tryRequestIdentifier( source.meta, "building." + town.faction->identifier, stringID, [=, &town](si32 identifier) mutable
{
ret->building = nullptr;
ret->buildable = nullptr;
ret->building = town.buildings[BuildingID(identifier)];
});
if (source["builds"].isNull())
{
VLC->modh->identifiers.tryRequestIdentifier( source.meta, "building." + town.faction->identifier, stringID, [=, &town](si32 identifier) mutable
{
ret->building = town.buildings[BuildingID(identifier)];
});
}
else
{
ret->building = town.buildings[BuildingID(source["id"].Float())];
if (source["builds"].isNull())
ret->buildable = ret->building;
else
if (source["builds"].getType() == JsonNode::DATA_FLOAT)
{
ret->buildable = town.buildings[BuildingID(source["builds"].Float())];
}
else
{
VLC->modh->identifiers.tryRequestIdentifier("building." + town.faction->identifier, source["builds"], [=, &town](si32 identifier) mutable
{
ret->buildable = town.buildings[BuildingID(identifier)];
});
}
}
ret->identifier = stringID;
ret->pos.x = source["x"].Float();
ret->pos.y = source["y"].Float();
ret->pos.z = source["z"].Float();
@@ -341,21 +371,10 @@ void CTownHandler::loadStructure(CTown &town, const JsonNode & source)
void CTownHandler::loadStructures(CTown &town, const JsonNode & source)
{
if (source.getType() == JsonNode::DATA_VECTOR)
for(auto &node : source.Struct())
{
for(auto &node : source.Vector())
{
if (!node.isNull())
loadStructure(town, node);
}
}
else
{
for(auto &node : source.Struct())
{
if (!node.second.isNull())
loadStructure(town, node.second);
}
if (!node.second.isNull())
loadStructure(town, node.first, node.second);
}
}
@@ -564,11 +583,12 @@ void CTownHandler::loadPuzzle(CFaction &faction, const JsonNode &source)
assert(faction.puzzleMap.size() == GameConstants::PUZZLE_MAP_PIECES);
}
CFaction * CTownHandler::loadFromJson(const JsonNode &source)
CFaction * CTownHandler::loadFromJson(const JsonNode &source, std::string identifier)
{
auto faction = new CFaction();
faction->name = source["name"].String();
faction->identifier = identifier;
VLC->modh->identifiers.requestIdentifier ("creature", source["commander"],
[=](si32 commanderID)
@@ -604,7 +624,7 @@ CFaction * CTownHandler::loadFromJson(const JsonNode &source)
void CTownHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
{
auto object = loadFromJson(data);
auto object = loadFromJson(data, name);
object->index = factions.size();
if (object->town)
{
@@ -622,7 +642,7 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
void CTownHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
{
auto object = loadFromJson(data);
auto object = loadFromJson(data, name);
object->index = index;
if (object->town)
{
@@ -639,6 +659,24 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
VLC->modh->identifiers.registerObject(scope, "faction", name, object->index);
}
void CTownHandler::afterLoadFinalization()
{
initializeRequirements();
}
void CTownHandler::initializeRequirements()
{
// must be done separately after all ID's are known
for (auto & requirement : requirementsToLoad)
{
requirement.building->requirements = CBuilding::TRequired(requirement.json, [&](const JsonNode & node)
{
return BuildingID(VLC->modh->identifiers.getIdentifier("building." + requirement.faction->identifier, node.Vector()[0]).get());
});
}
requirementsToLoad.clear();
}
std::vector<bool> CTownHandler::getDefaultAllowed() const
{
std::vector<bool> allowedFactions;