1
0
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:
Henning Koehler 2017-09-13 18:58:14 +12:00
parent d7942fd929
commit eb02ce0f31
6 changed files with 133 additions and 10 deletions

View File

@ -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" : [

View File

@ -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());
} }
} }
} }

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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