mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
changed specialty json format to struct with base (WIP)
This commit is contained in:
parent
d7942fd929
commit
eb02ce0f31
@ -51,7 +51,7 @@
|
|||||||
],
|
],
|
||||||
"type" : "CREATURE_TYPE_LIMITER"
|
"type" : "CREATURE_TYPE_LIMITER"
|
||||||
},
|
},
|
||||||
"subtype" : "attack",
|
"subtype" : "primSkill.attack",
|
||||||
"type" : "PRIMARY_SKILL",
|
"type" : "PRIMARY_SKILL",
|
||||||
"updater" : {
|
"updater" : {
|
||||||
"parameters" : [
|
"parameters" : [
|
||||||
@ -69,7 +69,7 @@
|
|||||||
],
|
],
|
||||||
"type" : "CREATURE_TYPE_LIMITER"
|
"type" : "CREATURE_TYPE_LIMITER"
|
||||||
},
|
},
|
||||||
"subtype" : "defence",
|
"subtype" : "primSkill.defence",
|
||||||
"type" : "PRIMARY_SKILL",
|
"type" : "PRIMARY_SKILL",
|
||||||
"updater" : {
|
"updater" : {
|
||||||
"parameters" : [
|
"parameters" : [
|
||||||
|
@ -737,17 +737,43 @@ void CHeroHandler::afterLoadFinalization()
|
|||||||
if(hero->specDeprecated.size() > 0)
|
if(hero->specDeprecated.size() > 0)
|
||||||
{
|
{
|
||||||
logMod->debug("Converting specialties format for hero %s(%s)", hero->identifier, VLC->townh->encodeFaction(hero->heroClass->faction));
|
logMod->debug("Converting specialties format for hero %s(%s)", hero->identifier, VLC->townh->encodeFaction(hero->heroClass->faction));
|
||||||
JsonNode specVec(JsonNode::JsonType::DATA_VECTOR);
|
std::vector<JsonNode> specVec;
|
||||||
|
std::vector<std::string> specNames;
|
||||||
for(const SSpecialtyInfo & spec : hero->specDeprecated)
|
for(const SSpecialtyInfo & spec : hero->specDeprecated)
|
||||||
{
|
{
|
||||||
for(std::shared_ptr<Bonus> bonus : SpecialtyInfoToBonuses(spec, hero->ID.getNum()))
|
for(std::shared_ptr<Bonus> bonus : SpecialtyInfoToBonuses(spec, hero->ID.getNum()))
|
||||||
{
|
{
|
||||||
hero->specialty.push_back(bonus);
|
hero->specialty.push_back(bonus);
|
||||||
specVec.Vector().push_back(bonus->toJsonNode());
|
specVec.push_back(bonus->toJsonNode());
|
||||||
|
// find fitting & unique bonus name
|
||||||
|
std::string bonusName = nameForBonus(*bonus);
|
||||||
|
if(vstd::contains(specNames, bonusName))
|
||||||
|
{
|
||||||
|
int i = 2;
|
||||||
|
while(vstd::contains(specNames, bonusName + std::to_string(i)))
|
||||||
|
i++;
|
||||||
|
bonusName += std::to_string(i);
|
||||||
|
}
|
||||||
|
specNames.push_back(bonusName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hero->specDeprecated.clear();
|
hero->specDeprecated.clear();
|
||||||
logMod->trace("\"specialty\" : %s", specVec.toJson());
|
// log new format for easy copy-and-paste
|
||||||
|
JsonNode specNode(JsonNode::JsonType::DATA_STRUCT);
|
||||||
|
if(specVec.size() > 1)
|
||||||
|
{
|
||||||
|
JsonNode base = JsonUtils::intersect(specVec);
|
||||||
|
if(!base.isEmpty())
|
||||||
|
{
|
||||||
|
specNode["base"] = base;
|
||||||
|
//TODO: subtract base from bonuses
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add json for bonuses
|
||||||
|
specNode["bonuses"].Struct();
|
||||||
|
for(int i = 0; i < specVec.size(); i++)
|
||||||
|
specNode["bonuses"][specNames[i]] = specVec[i];
|
||||||
|
logMod->trace("\"specialty\" : %s", specNode.toJson());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1169,17 +1169,17 @@ JsonNode subtypeToJson(Bonus::BonusType type, int subtype)
|
|||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case Bonus::PRIMARY_SKILL:
|
case Bonus::PRIMARY_SKILL:
|
||||||
return JsonUtils::stringNode(PrimarySkill::names[subtype]);
|
return JsonUtils::stringNode("primSkill." + PrimarySkill::names[subtype]);
|
||||||
case Bonus::SECONDARY_SKILL_PREMY:
|
case Bonus::SECONDARY_SKILL_PREMY:
|
||||||
return JsonUtils::stringNode(NSecondarySkill::names[subtype]);
|
return JsonUtils::stringNode("skill." + NSecondarySkill::names[subtype]);
|
||||||
case Bonus::SPECIAL_SPELL_LEV:
|
case Bonus::SPECIAL_SPELL_LEV:
|
||||||
case Bonus::SPECIFIC_SPELL_DAMAGE:
|
case Bonus::SPECIFIC_SPELL_DAMAGE:
|
||||||
case Bonus::SPECIAL_BLESS_DAMAGE:
|
case Bonus::SPECIAL_BLESS_DAMAGE:
|
||||||
case Bonus::MAXED_SPELL:
|
case Bonus::MAXED_SPELL:
|
||||||
case Bonus::SPECIAL_PECULIAR_ENCHANT:
|
case Bonus::SPECIAL_PECULIAR_ENCHANT:
|
||||||
return JsonUtils::stringNode((*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier);
|
return JsonUtils::stringNode("spell." + (*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier);
|
||||||
case Bonus::SPECIAL_UPGRADE:
|
case Bonus::SPECIAL_UPGRADE:
|
||||||
return JsonUtils::stringNode(CreatureID::encode(subtype));
|
return JsonUtils::stringNode("creature." + CreatureID::encode(subtype));
|
||||||
case Bonus::GENERATE_RESOURCE:
|
case Bonus::GENERATE_RESOURCE:
|
||||||
return JsonUtils::stringNode(GameConstants::RESOURCE_NAMES[subtype]);
|
return JsonUtils::stringNode(GameConstants::RESOURCE_NAMES[subtype]);
|
||||||
default:
|
default:
|
||||||
@ -1192,7 +1192,7 @@ JsonNode additionalInfoToJson(Bonus::BonusType type, int addInfo)
|
|||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case Bonus::SPECIAL_UPGRADE:
|
case Bonus::SPECIAL_UPGRADE:
|
||||||
return JsonUtils::stringNode(CreatureID::encode(addInfo));
|
return JsonUtils::stringNode("creature." + CreatureID::encode(addInfo));
|
||||||
default:
|
default:
|
||||||
return JsonUtils::intNode(addInfo);
|
return JsonUtils::intNode(addInfo);
|
||||||
}
|
}
|
||||||
@ -1717,3 +1717,26 @@ JsonNode ScalingUpdater::toJsonNode() const
|
|||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string nameForBonus(const Bonus & bonus)
|
||||||
|
{
|
||||||
|
switch(bonus.type)
|
||||||
|
{
|
||||||
|
case Bonus::PRIMARY_SKILL:
|
||||||
|
return PrimarySkill::names[bonus.subtype];
|
||||||
|
case Bonus::SECONDARY_SKILL_PREMY:
|
||||||
|
return NSecondarySkill::names[bonus.subtype];
|
||||||
|
case Bonus::SPECIAL_SPELL_LEV:
|
||||||
|
case Bonus::SPECIFIC_SPELL_DAMAGE:
|
||||||
|
case Bonus::SPECIAL_BLESS_DAMAGE:
|
||||||
|
case Bonus::MAXED_SPELL:
|
||||||
|
case Bonus::SPECIAL_PECULIAR_ENCHANT:
|
||||||
|
return (*VLC->spellh)[SpellID::ESpellID(bonus.subtype)]->identifier;
|
||||||
|
case Bonus::SPECIAL_UPGRADE:
|
||||||
|
return CreatureID::encode(bonus.subtype) + "2" + CreatureID::encode(bonus.additionalInfo);
|
||||||
|
case Bonus::GENERATE_RESOURCE:
|
||||||
|
return GameConstants::RESOURCE_NAMES[bonus.subtype];
|
||||||
|
default:
|
||||||
|
return vstd::findKey(bonusNameMap, bonus.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1057,3 +1057,6 @@ struct DLL_LINKAGE ScalingUpdater : public IUpdater
|
|||||||
virtual std::string toString() const override;
|
virtual std::string toString() const override;
|
||||||
virtual JsonNode toJsonNode() const override;
|
virtual JsonNode toJsonNode() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// generate suitable name for bonus - e.g. for storing in json struct
|
||||||
|
DLL_LINKAGE std::string nameForBonus(const Bonus & bonus);
|
||||||
|
@ -214,6 +214,24 @@ bool JsonNode::isNumber() const
|
|||||||
return type == JsonType::DATA_INTEGER || type == JsonType::DATA_FLOAT;
|
return type == JsonType::DATA_INTEGER || type == JsonType::DATA_FLOAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JsonNode::isEmpty() const
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case JsonType::DATA_NULL:
|
||||||
|
return true;
|
||||||
|
case JsonType::DATA_STRUCT:
|
||||||
|
for(auto elem : *data.Struct)
|
||||||
|
{
|
||||||
|
if(!elem.second.isEmpty())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JsonNode::clear()
|
void JsonNode::clear()
|
||||||
{
|
{
|
||||||
setType(JsonType::DATA_NULL);
|
setType(JsonType::DATA_NULL);
|
||||||
@ -839,6 +857,48 @@ void JsonUtils::inherit(JsonNode & descendant, const JsonNode & base)
|
|||||||
descendant.swap(inheritedNode);
|
descendant.swap(inheritedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonNode JsonUtils::intersect(const std::vector<JsonNode> & nodes, bool pruneEmpty)
|
||||||
|
{
|
||||||
|
if(nodes.size() == 0)
|
||||||
|
return nullNode;
|
||||||
|
|
||||||
|
JsonNode result = nodes[0];
|
||||||
|
for(int i = 1; i < nodes.size(); i++)
|
||||||
|
{
|
||||||
|
if(result.isNull())
|
||||||
|
break;
|
||||||
|
result = JsonUtils::intersect(result, nodes[i], pruneEmpty);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode JsonUtils::intersect(const JsonNode & a, const JsonNode & b, bool pruneEmpty)
|
||||||
|
{
|
||||||
|
if(a.getType() == JsonNode::JsonType::DATA_STRUCT && b.getType() == JsonNode::JsonType::DATA_STRUCT)
|
||||||
|
{
|
||||||
|
// intersect individual properties
|
||||||
|
JsonNode result(JsonNode::JsonType::DATA_STRUCT);
|
||||||
|
for(auto property : a.Struct())
|
||||||
|
{
|
||||||
|
if(vstd::contains(b.Struct(), property.first))
|
||||||
|
{
|
||||||
|
JsonNode propertyIntersect = JsonUtils::intersect(property.second, b.Struct().find(property.first)->second);
|
||||||
|
if(pruneEmpty && propertyIntersect.isEmpty())
|
||||||
|
continue;
|
||||||
|
result[property.first] = propertyIntersect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// not a struct - same or different, no middle ground
|
||||||
|
if(a == b)
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
return nullNode;
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode JsonUtils::assembleFromFiles(std::vector<std::string> files)
|
JsonNode JsonUtils::assembleFromFiles(std::vector<std::string> files)
|
||||||
{
|
{
|
||||||
bool isValid;
|
bool isValid;
|
||||||
|
@ -75,6 +75,7 @@ public:
|
|||||||
|
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
bool isNumber() const;
|
bool isNumber() const;
|
||||||
|
bool isEmpty() const;
|
||||||
/// removes all data from node and sets type to null
|
/// removes all data from node and sets type to null
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
@ -188,6 +189,16 @@ namespace JsonUtils
|
|||||||
*/
|
*/
|
||||||
DLL_LINKAGE void inherit(JsonNode & descendant, const JsonNode & base);
|
DLL_LINKAGE void inherit(JsonNode & descendant, const JsonNode & base);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief construct node representing the common structure of input nodes
|
||||||
|
* @param pruneEmpty - omit common properties whose intersection is empty
|
||||||
|
* different types: null
|
||||||
|
* struct: recursive intersect on common properties
|
||||||
|
* other: input if equal, null otherwise
|
||||||
|
*/
|
||||||
|
DLL_LINKAGE JsonNode intersect(const JsonNode & a, const JsonNode & b, bool pruneEmpty = true);
|
||||||
|
DLL_LINKAGE JsonNode intersect(const std::vector<JsonNode> & nodes, bool pruneEmpty = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief generate one Json structure from multiple files
|
* @brief generate one Json structure from multiple files
|
||||||
* @param files - list of filenames with parts of json structure
|
* @param files - list of filenames with parts of json structure
|
||||||
|
Loading…
Reference in New Issue
Block a user