1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

added one-line option for standard creature specialty; also fixes bug for creatures where upgrades have different attack/defense

This commit is contained in:
Henning Koehler 2018-02-06 13:44:43 +13:00
parent 7a69bd1559
commit 6442842731
3 changed files with 70 additions and 60 deletions

View File

@ -75,36 +75,7 @@
{ "skill" : "armorer", "level": "basic" } { "skill" : "armorer", "level": "basic" }
], ],
"specialty" : { "specialty" : {
"base" : { "creature" : "griffin"
"limiters" : [
{
"parameters" : [ "griffin", true ],
"type" : "CREATURE_TYPE_LIMITER"
}
]
},
"bonuses" : {
"attack" : {
"subtype" : "primSkill.attack",
"type" : "PRIMARY_SKILL",
"updater" : {
"parameters" : [ 8, 3 ],
"type" : "GROWS_WITH_LEVEL"
}
},
"defence" : {
"subtype" : "primSkill.defence",
"type" : "PRIMARY_SKILL",
"updater" : {
"parameters" : [ 8, 3 ],
"type" : "GROWS_WITH_LEVEL"
}
},
"speed" : {
"type" : "STACKS_SPEED",
"val" : 1
}
}
} }
}, },
"sylvia": "sylvia":

View File

@ -140,7 +140,6 @@
"type" : "object", "type" : "object",
"description": "Description of hero specialty using bonus system", "description": "Description of hero specialty using bonus system",
"additionalProperties" : false, "additionalProperties" : false,
"required" : [ "bonuses" ],
"properties" : { "properties" : {
"base" : { "base" : {
"type" : "object", "type" : "object",
@ -150,6 +149,10 @@
"type" : "object", "type" : "object",
"description" : "Set of bonuses", "description" : "Set of bonuses",
"additionalProperties" : { "$ref" : "vcmi:bonus" } "additionalProperties" : { "$ref" : "vcmi:bonus" }
},
"creature" : {
"type" : "string",
"description" : "Name of base creature to grant standard specialty to."
} }
} }
} }

View File

@ -379,6 +379,43 @@ void CHeroHandler::loadHeroSkills(CHero * hero, const JsonNode & node)
} }
} }
// add standard creature specialty to result
void AddSpecialtyForCreature(int creatureID, std::shared_ptr<Bonus> bonus, std::vector<std::shared_ptr<Bonus>> &result)
{
const CCreature &specBaseCreature = *VLC->creh->creatures[creatureID]; //base creature in which we have specialty
bonus->limiter.reset(new CCreatureTypeLimiter(specBaseCreature, true));
bonus->type = Bonus::STACKS_SPEED;
bonus->valType = Bonus::ADDITIVE_VALUE;
bonus->val = 1;
result.push_back(bonus);
// attack and defense may differ for upgraded creatures => separate bonuses
std::vector<int> specTargets;
specTargets.push_back(creatureID);
specTargets.insert(specTargets.end(), specBaseCreature.upgrades.begin(), specBaseCreature.upgrades.end());
for(int cid : specTargets)
{
const CCreature &specCreature = *VLC->creh->creatures[cid];
bonus = std::make_shared<Bonus>(*bonus);
bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, false));
bonus->type = Bonus::PRIMARY_SKILL;
bonus->val = 0;
int stepSize = specCreature.level ? specCreature.level : 5;
bonus->subtype = PrimarySkill::ATTACK;
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getAttack(false), stepSize));
result.push_back(bonus);
bonus = std::make_shared<Bonus>(*bonus);
bonus->subtype = PrimarySkill::DEFENSE;
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefence(false), stepSize));
result.push_back(bonus);
}
}
// convert deprecated format // convert deprecated format
std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo & spec, int sid) std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo & spec, int sid)
{ {
@ -393,29 +430,7 @@ std::vector<std::shared_ptr<Bonus>> SpecialtyInfoToBonuses(const SSpecialtyInfo
switch (spec.type) switch (spec.type)
{ {
case 1: //creature specialty case 1: //creature specialty
{ AddSpecialtyForCreature(spec.additionalinfo, bonus, result);
const CCreature &specCreature = *VLC->creh->creatures[spec.additionalinfo]; //creature in which we have specialty
bonus->limiter.reset(new CCreatureTypeLimiter(specCreature, true));
bonus->type = Bonus::STACKS_SPEED;
bonus->valType = Bonus::ADDITIVE_VALUE;
bonus->val = 1;
result.push_back(bonus);
bonus = std::make_shared<Bonus>(*bonus);
bonus->type = Bonus::PRIMARY_SKILL;
bonus->val = 0;
int stepSize = specCreature.level ? specCreature.level : 5;
bonus->subtype = PrimarySkill::ATTACK;
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getAttack(false), stepSize));
result.push_back(bonus);
bonus = std::make_shared<Bonus>(*bonus);
bonus->subtype = PrimarySkill::DEFENSE;
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefence(false), stepSize));
result.push_back(bonus);
}
break; break;
case 2: //secondary skill case 2: //secondary skill
bonus->type = Bonus::SECONDARY_SKILL_PREMY; bonus->type = Bonus::SECONDARY_SKILL_PREMY;
@ -584,12 +599,19 @@ void CHeroHandler::beforeValidate(JsonNode & object)
{ {
const JsonNode & base = specialtyNode["base"]; const JsonNode & base = specialtyNode["base"];
if(!base.isNull()) if(!base.isNull())
{
if(specialtyNode["bonuses"].isNull())
{
logMod->warn("specialty has base without bonuses");
}
else
{ {
JsonMap & bonuses = specialtyNode["bonuses"].Struct(); JsonMap & bonuses = specialtyNode["bonuses"].Struct();
for(std::pair<std::string, JsonNode> keyValue : bonuses) for(std::pair<std::string, JsonNode> keyValue : bonuses)
JsonUtils::inherit(bonuses[keyValue.first], base); JsonUtils::inherit(bonuses[keyValue.first], base);
} }
} }
}
} }
void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node) void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
@ -634,11 +656,25 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
} }
} }
else if(specialtyNode.getType() == JsonNode::JsonType::DATA_STRUCT) else if(specialtyNode.getType() == JsonNode::JsonType::DATA_STRUCT)
{
//creature specialty - alias for simplicity
if(!specialtyNode["creature"].isNull())
{
VLC->modh->identifiers.requestIdentifier("creature", specialtyNode["creature"], [hero](si32 creature) {
// use legacy format for delayed conversion (must have all creature data loaded, also for upgrades)
SSpecialtyInfo spec;
spec.type = 1;
spec.additionalinfo = creature;
hero->specDeprecated.push_back(spec);
});
}
if(!specialtyNode["bonuses"].isNull())
{ {
//proper new format //proper new format
for(auto keyValue : specialtyNode["bonuses"].Struct()) for(auto keyValue : specialtyNode["bonuses"].Struct())
hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(keyValue.second))); hero->specialty.push_back(prepSpec(JsonUtils::parseBonus(keyValue.second)));
} }
}
} }
void CHeroHandler::loadExperience() void CHeroHandler::loadExperience()