mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-27 00:41:08 +02:00
Implement shortcut for hero skill specialties
Should make changes to secondary skill bonuses less mod-breaking, and reduce chances of incorrectly defined specialties in mods
This commit is contained in:
@ -10,16 +10,7 @@
|
||||
{ "skill" : "archery", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"archery" : {
|
||||
"type" : "PERCENTAGE_DAMAGE_BOOST",
|
||||
"subtype" : "damageTypeRanged",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "archery"
|
||||
}
|
||||
},
|
||||
"valeska":
|
||||
@ -61,16 +52,7 @@
|
||||
{ "skill" : "navigation", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"navigation" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"subtype" : "heroMovementSea",
|
||||
"type" : "MOVEMENT",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "navigation"
|
||||
}
|
||||
},
|
||||
"lordHaart":
|
||||
@ -84,16 +66,7 @@
|
||||
{ "skill" : "estates", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"estates" : {
|
||||
"subtype" : "resource.gold",
|
||||
"type" : "GENERATE_RESOURCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "estates"
|
||||
}
|
||||
},
|
||||
"sorsha":
|
||||
@ -150,16 +123,7 @@
|
||||
{ "skill" : "firstAid", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"firstAid" : {
|
||||
"subtype" : "spell.firstAid",
|
||||
"type" : "SPECIFIC_SPELL_POWER",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "firstAid"
|
||||
}
|
||||
},
|
||||
"adela":
|
||||
@ -265,15 +229,7 @@
|
||||
{ "skill" : "eagleEye", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"eagleEye" : {
|
||||
"type" : "LEARN_BATTLE_SPELL_CHANCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "eagleEye"
|
||||
}
|
||||
},
|
||||
"loynis":
|
||||
|
@ -85,16 +85,7 @@
|
||||
{ "skill" : "tactics", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"logistics" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"subtype" : "heroMovementLand",
|
||||
"type" : "MOVEMENT",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "logistics"
|
||||
}
|
||||
},
|
||||
"synca":
|
||||
@ -159,15 +150,7 @@
|
||||
{ "skill" : "mysticism", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"mysticism" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "MANA_REGENERATION",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "mysticism"
|
||||
}
|
||||
},
|
||||
"malekith":
|
||||
@ -182,16 +165,7 @@
|
||||
{ "skill" : "sorcery", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"sorcery" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "SPELL_DAMAGE",
|
||||
"subtype" : "spellSchool.any",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "sorcery"
|
||||
}
|
||||
},
|
||||
"jeddite":
|
||||
@ -227,15 +201,7 @@
|
||||
{ "skill" : "eagleEye", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"eagleEye" : {
|
||||
"type" : "LEARN_BATTLE_SPELL_CHANCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "eagleEye"
|
||||
}
|
||||
},
|
||||
"deemer":
|
||||
|
@ -66,16 +66,7 @@
|
||||
{ "skill" : "armorer", "level": "advanced" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"armorer" : {
|
||||
"type" : "GENERAL_DAMAGE_REDUCTION",
|
||||
"subtype" : "damageTypeAll",
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "armorer"
|
||||
}
|
||||
},
|
||||
"alkin":
|
||||
@ -166,15 +157,7 @@
|
||||
{ "skill" : "mysticism", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"mysticism" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "MANA_REGENERATION",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "mysticism"
|
||||
}
|
||||
},
|
||||
"voy":
|
||||
@ -189,16 +172,7 @@
|
||||
{ "skill" : "navigation", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"navigation" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"subtype" : "heroMovementSea",
|
||||
"type" : "MOVEMENT",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "navigation"
|
||||
}
|
||||
},
|
||||
"verdish":
|
||||
@ -213,16 +187,7 @@
|
||||
{ "skill" : "firstAid", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"firstAid" : {
|
||||
"subtype" : "spell.firstAid",
|
||||
"type" : "SPECIFIC_SPELL_POWER",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "firstAid"
|
||||
}
|
||||
},
|
||||
"merist":
|
||||
@ -258,16 +223,7 @@
|
||||
{ "skill" : "sorcery", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"sorcery" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "SPELL_DAMAGE",
|
||||
"subtype" : "spellSchool.any",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "sorcery"
|
||||
}
|
||||
},
|
||||
"andra":
|
||||
@ -282,15 +238,7 @@
|
||||
{ "skill" : "intelligence", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"intelligence" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "MANA_PER_KNOWLEDGE_PERCENTAGE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "intelligence"
|
||||
}
|
||||
},
|
||||
"tiva":
|
||||
@ -305,15 +253,7 @@
|
||||
{ "skill" : "eagleEye", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"eagleEye" : {
|
||||
"type" : "LEARN_BATTLE_SPELL_CHANCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "eagleEye"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,15 +126,7 @@
|
||||
{ "skill" : "intelligence", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"intelligence" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "MANA_PER_KNOWLEDGE_PERCENTAGE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "intelligence"
|
||||
}
|
||||
},
|
||||
"xyron":
|
||||
@ -171,15 +163,7 @@
|
||||
{ "skill" : "mysticism", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"mysticism" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "MANA_REGENERATION",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "mysticism"
|
||||
}
|
||||
},
|
||||
"olema":
|
||||
@ -257,16 +241,7 @@
|
||||
{ "skill" : "sorcery", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"sorcery" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "SPELL_DAMAGE",
|
||||
"subtype" : "spellSchool.any",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "sorcery"
|
||||
}
|
||||
},
|
||||
"xarfax":
|
||||
|
@ -85,15 +85,7 @@
|
||||
{ "skill" : "necromancy", "level": "advanced" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"necromancy" : {
|
||||
"type" : "UNDEAD_RAISE_PERCENTAGE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "necromancy"
|
||||
}
|
||||
},
|
||||
"clavius":
|
||||
@ -188,16 +180,7 @@
|
||||
{ "skill" : "sorcery", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"sorcery" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "SPELL_DAMAGE",
|
||||
"subtype" : "spellSchool.any",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "sorcery"
|
||||
}
|
||||
},
|
||||
"nimbus":
|
||||
@ -212,15 +195,7 @@
|
||||
{ "skill" : "eagleEye", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"eagleEye" : {
|
||||
"type" : "LEARN_BATTLE_SPELL_CHANCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "eagleEye"
|
||||
}
|
||||
},
|
||||
"thant":
|
||||
@ -277,15 +252,7 @@
|
||||
{ "skill" : "necromancy", "level": "advanced" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"necromancy" : {
|
||||
"type" : "UNDEAD_RAISE_PERCENTAGE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "necromancy"
|
||||
}
|
||||
},
|
||||
"nagash":
|
||||
|
@ -10,16 +10,7 @@
|
||||
{ "skill" : "armorer", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"armorer" : {
|
||||
"type" : "GENERAL_DAMAGE_REDUCTION",
|
||||
"subtype" : "damageTypeAll",
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "armorer"
|
||||
}
|
||||
},
|
||||
"ufretin":
|
||||
@ -79,15 +70,7 @@
|
||||
{ "skill" : "resistance", "level": "advanced" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"resistance" : {
|
||||
"type" : "MAGIC_RESISTANCE",
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "resistance"
|
||||
}
|
||||
},
|
||||
"ivor":
|
||||
@ -129,16 +112,7 @@
|
||||
{ "skill" : "logistics", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"logistics" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"subtype" : "heroMovementLand",
|
||||
"type" : "MOVEMENT",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "logistics"
|
||||
}
|
||||
},
|
||||
"coronius":
|
||||
@ -196,15 +170,7 @@
|
||||
{ "skill" : "intelligence", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"intelligence" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "MANA_PER_KNOWLEDGE_PERCENTAGE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "intelligence"
|
||||
}
|
||||
},
|
||||
"gem":
|
||||
@ -219,16 +185,7 @@
|
||||
{ "skill" : "firstAid", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"firstAid" : {
|
||||
"subtype" : "spell.firstAid",
|
||||
"type" : "SPECIFIC_SPELL_POWER",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "firstAid"
|
||||
}
|
||||
},
|
||||
"malcom":
|
||||
@ -243,15 +200,7 @@
|
||||
{ "skill" : "eagleEye", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"eagleEye" : {
|
||||
"type" : "LEARN_BATTLE_SPELL_CHANCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "eagleEye"
|
||||
}
|
||||
},
|
||||
"melodia":
|
||||
|
@ -93,16 +93,7 @@
|
||||
{ "skill" : "offence", "level": "advanced" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"offence" : {
|
||||
"subtype" : "damageTypeMelee",
|
||||
"type" : "PERCENTAGE_DAMAGE_BOOST",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "offence"
|
||||
}
|
||||
},
|
||||
"tyraxor":
|
||||
@ -131,16 +122,7 @@
|
||||
{ "skill" : "sorcery", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"sorcery" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "SPELL_DAMAGE",
|
||||
"subtype" : "spellSchool.any",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "sorcery"
|
||||
}
|
||||
},
|
||||
"vey":
|
||||
@ -170,16 +152,7 @@
|
||||
{ "skill" : "logistics", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"logistics" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"subtype" : "heroMovementLand",
|
||||
"type" : "MOVEMENT",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "logistics"
|
||||
}
|
||||
},
|
||||
"terek":
|
||||
@ -236,16 +209,7 @@
|
||||
{ "skill" : "offence", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"offence" : {
|
||||
"subtype" : "damageTypeMelee",
|
||||
"type" : "PERCENTAGE_DAMAGE_BOOST",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "offence"
|
||||
}
|
||||
},
|
||||
"oris":
|
||||
@ -260,15 +224,7 @@
|
||||
{ "skill" : "eagleEye", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"eagleEye" : {
|
||||
"type" : "LEARN_BATTLE_SPELL_CHANCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "eagleEye"
|
||||
}
|
||||
},
|
||||
"saurug":
|
||||
|
@ -55,16 +55,7 @@
|
||||
{ "skill" : "armorer", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"armorer" : {
|
||||
"type" : "GENERAL_DAMAGE_REDUCTION",
|
||||
"subtype" : "damageTypeAll",
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "armorer"
|
||||
}
|
||||
},
|
||||
"torosar":
|
||||
@ -167,15 +158,7 @@
|
||||
{ "skill" : "mysticism", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"mysticism" : {
|
||||
"targetSourceType" : "SECONDARY_SKILL",
|
||||
"type" : "MANA_REGENERATION",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE"
|
||||
}
|
||||
}
|
||||
"secondary" : "mysticism"
|
||||
}
|
||||
},
|
||||
"serena":
|
||||
@ -190,15 +173,7 @@
|
||||
{ "skill" : "eagleEye", "level": "basic" }
|
||||
],
|
||||
"specialty" : {
|
||||
"bonuses" : {
|
||||
"eagleEye" : {
|
||||
"type" : "LEARN_BATTLE_SPELL_CHANCE",
|
||||
"updater" : "TIMES_HERO_LEVEL",
|
||||
"val" : 5,
|
||||
"valueType" : "PERCENT_TO_TARGET_TYPE",
|
||||
"targetSourceType" : "SECONDARY_SKILL"
|
||||
}
|
||||
}
|
||||
"secondary" : "eagleEye"
|
||||
}
|
||||
},
|
||||
"daremyth":
|
||||
|
@ -132,6 +132,10 @@
|
||||
"creature" : {
|
||||
"type" : "string",
|
||||
"description" : "Shortcut for defining creature specialty, using standard H3 rules."
|
||||
},
|
||||
"secondary" : {
|
||||
"type" : "string",
|
||||
"description" : "Shortcut for defining secondary skill specialty, using standard H3 rules."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -43,7 +43,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"required" : ["name", "basic", "advanced", "expert"],
|
||||
"required" : ["name", "basic", "advanced", "expert", "specialty", "gainChance" ],
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type" : "string",
|
||||
@ -61,6 +61,11 @@
|
||||
"type" : "boolean",
|
||||
"description" : "This skill is minor obligatory (like H3 Magic school)"
|
||||
},
|
||||
"specialty" : {
|
||||
"type" : "array",
|
||||
"description" : "List of bonuses that are affected by hero specialty",
|
||||
"items" : { "type" : "string" }
|
||||
},
|
||||
"gainChance" : {
|
||||
"description" : "Chance for the skill to be offered on level-up (heroClass may override)",
|
||||
"type" : "object",
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"pathfinding" : {
|
||||
"index" : 0,
|
||||
"specialty" : [], // no generic specialty
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -27,6 +28,9 @@
|
||||
},
|
||||
"archery" : {
|
||||
"index" : 1,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -54,6 +58,9 @@
|
||||
},
|
||||
"logistics" : {
|
||||
"index" : 2,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -81,6 +88,9 @@
|
||||
},
|
||||
"scouting" : {
|
||||
"index" : 3,
|
||||
"specialty" : [ // NOTE: no such specialists in H3, hota uses different logic
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -107,6 +117,9 @@
|
||||
},
|
||||
"diplomacy" : {
|
||||
"index" : 4,
|
||||
"specialty" : [ // NOTE: no such specialists in H3
|
||||
"surr"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -141,6 +154,9 @@
|
||||
},
|
||||
"navigation" : {
|
||||
"index" : 5,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -169,6 +185,7 @@
|
||||
},
|
||||
"leadership" : {
|
||||
"index" : 6,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -195,6 +212,7 @@
|
||||
},
|
||||
"wisdom" : {
|
||||
"index" : 7,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"obligatoryMajor" : true,
|
||||
"base" : {
|
||||
"effects" : {
|
||||
@ -222,6 +240,9 @@
|
||||
},
|
||||
"mysticism" : {
|
||||
"index" : 8,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -248,6 +269,7 @@
|
||||
},
|
||||
"luck" : {
|
||||
"index" : 9,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -274,6 +296,7 @@
|
||||
},
|
||||
"ballistics" : {
|
||||
"index" : 10,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -307,6 +330,9 @@
|
||||
},
|
||||
"eagleEye" : {
|
||||
"index" : 11,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -340,6 +366,9 @@
|
||||
},
|
||||
"necromancy" : {
|
||||
"index" : 12,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -374,6 +403,9 @@
|
||||
},
|
||||
"estates" : {
|
||||
"index" : 13,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -401,6 +433,7 @@
|
||||
},
|
||||
"fireMagic" : {
|
||||
"index" : 14,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"obligatoryMinor" : true,
|
||||
"base" : {
|
||||
"effects" : {
|
||||
@ -429,6 +462,7 @@
|
||||
},
|
||||
"airMagic" : {
|
||||
"index" : 15,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"obligatoryMinor" : true,
|
||||
"base" : {
|
||||
"effects" : {
|
||||
@ -457,6 +491,7 @@
|
||||
},
|
||||
"waterMagic" : {
|
||||
"index" : 16,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"obligatoryMinor" : true,
|
||||
"base" : {
|
||||
"effects" : {
|
||||
@ -485,6 +520,7 @@
|
||||
},
|
||||
"earthMagic" : {
|
||||
"index" : 17,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"obligatoryMinor" : true,
|
||||
"base" : {
|
||||
"effects" : {
|
||||
@ -513,6 +549,7 @@
|
||||
},
|
||||
"scholar" : {
|
||||
"index" : 18,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -539,6 +576,7 @@
|
||||
},
|
||||
"tactics" : {
|
||||
"index" : 19,
|
||||
"specialty" : [], // generic specialty not applicable
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -572,6 +610,7 @@
|
||||
},
|
||||
"artillery" : {
|
||||
"index" : 20,
|
||||
"specialty" : [], // generic specialty not applicable, H3 heroes specialize in ballista creature instead
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -625,6 +664,9 @@
|
||||
},
|
||||
"learning" : {
|
||||
"index" : 21,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -651,6 +693,9 @@
|
||||
},
|
||||
"offence" : {
|
||||
"index" : 22,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -678,6 +723,9 @@
|
||||
},
|
||||
"armorer" : {
|
||||
"index" : 23,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -705,6 +753,9 @@
|
||||
},
|
||||
"intelligence" : {
|
||||
"index" : 24,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -731,6 +782,9 @@
|
||||
},
|
||||
"sorcery" : {
|
||||
"index" : 25,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -758,6 +812,9 @@
|
||||
},
|
||||
"resistance" : {
|
||||
"index" : 26,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
@ -784,6 +841,9 @@
|
||||
},
|
||||
"firstAid" : {
|
||||
"index" : 27,
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
"base" : {
|
||||
"effects" : {
|
||||
"main" : {
|
||||
|
@ -129,8 +129,11 @@ In order to make functional hero you also need:
|
||||
"someBonus" : {Bonus Format},
|
||||
"anotherOne" : {Bonus Format}
|
||||
},
|
||||
// Optional. Shortcut for defining creature specialty, using standard H3 rules
|
||||
"creature" : "griffin"
|
||||
// Shortcut for defining creature specialty, using standard H3 rules
|
||||
"creature" : "griffin",
|
||||
|
||||
// Shortcut for defining specialty in secondary skill, using standard H3 rules
|
||||
"secondary" : "offence"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -26,6 +26,11 @@
|
||||
"advanced": {Skill level format},
|
||||
"expert": {Skill level format},
|
||||
|
||||
// Names of bonuses of the skill that are affected by default secondary skill specialty of a hero
|
||||
"specialty" : [
|
||||
"main"
|
||||
],
|
||||
|
||||
// Chance for the skill to be offered on level-up (heroClass may override)
|
||||
"gainChance" : {
|
||||
// Chance for hero classes with might affinity
|
||||
|
@ -14,16 +14,14 @@
|
||||
|
||||
#include "CSkillHandler.h"
|
||||
|
||||
#include "bonuses/Updaters.h"
|
||||
#include "constants/StringConstants.h"
|
||||
#include "filesystem/Filesystem.h"
|
||||
#include "json/JsonBonus.h"
|
||||
#include "json/JsonUtils.h"
|
||||
#include "modding/IdentifierStorage.h"
|
||||
#include "modding/ModUtility.h"
|
||||
#include "modding/ModScope.h"
|
||||
#include "texts/CGeneralTextHandler.h"
|
||||
#include "texts/CLegacyConfigParser.h"
|
||||
#include "texts/TextOperations.h"
|
||||
#include "GameLibrary.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
@ -253,6 +251,23 @@ std::shared_ptr<CSkill> CSkillHandler::loadFromJson(const std::string & scope, c
|
||||
skillAtLevel.iconMedium = levelNode["images"]["medium"].String();
|
||||
skillAtLevel.iconLarge = levelNode["images"]["large"].String();
|
||||
}
|
||||
|
||||
for(const auto & b : json["specialty"].Vector())
|
||||
{
|
||||
const auto & bonusNode = json["basic"]["effects"][b.String()];
|
||||
|
||||
if (bonusNode.isStruct())
|
||||
{
|
||||
auto bonus = JsonUtils::parseBonus(bonusNode);
|
||||
bonus->val = 5; // default H3 value, hardcoded for now
|
||||
bonus->updater = std::make_shared<TimesHeroLevelUpdater>();
|
||||
bonus->valType = BonusValueType::PERCENT_TO_TARGET_TYPE;
|
||||
bonus->targetSourceType = BonusSource::SECONDARY_SKILL;
|
||||
skill->specialtyTargetBonuses.push_back(bonus);
|
||||
}
|
||||
else
|
||||
logMod->warn("Failed to load speciality bonus '%s' for skill '%s'", b.String(), identifier);
|
||||
}
|
||||
logMod->debug("loaded secondary skill %s(%d)", identifier, skill->id.getNum());
|
||||
|
||||
return skill;
|
||||
|
@ -71,6 +71,9 @@ public:
|
||||
|
||||
std::array<si32, 2> gainChance; // gainChance[0/1] = default gain chance on level-up for might/magic heroes
|
||||
|
||||
/// Bonuses that should be given to hero that specializes in this skill
|
||||
std::vector<std::shared_ptr<const Bonus>> specialtyTargetBonuses;
|
||||
|
||||
void updateFrom(const JsonNode & data);
|
||||
void serializeJson(JsonSerializeFormat & handler);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "../../json/JsonBonus.h"
|
||||
#include "../../json/JsonUtils.h"
|
||||
#include "../../modding/IdentifierStorage.h"
|
||||
#include "../../CSkillHandler.h"
|
||||
#include "../../texts/CGeneralTextHandler.h"
|
||||
#include "../../texts/CLegacyConfigParser.h"
|
||||
|
||||
@ -140,7 +141,7 @@ void CHeroHandler::loadHeroSkills(CHero * hero, const JsonNode & node) const
|
||||
}
|
||||
|
||||
/// creates standard H3 hero specialty for creatures
|
||||
static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID cid)
|
||||
std::vector<std::shared_ptr<Bonus>> CHeroHandler::createCreatureSpecialty(CreatureID cid) const
|
||||
{
|
||||
std::vector<std::shared_ptr<Bonus>> result;
|
||||
|
||||
@ -174,6 +175,19 @@ static std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID ci
|
||||
bonus->updater.reset(new GrowsWithLevelUpdater(specCreature.getDefense(false), stepSize));
|
||||
result.push_back(bonus);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Bonus>> CHeroHandler::createSecondarySkillSpecialty(SecondarySkill skillID) const
|
||||
{
|
||||
std::vector<std::shared_ptr<Bonus>> result;
|
||||
const auto & skillPtr = LIBRARY->skillh->objects[skillID.getNum()];
|
||||
|
||||
if (skillPtr->specialtyTargetBonuses.empty())
|
||||
logMod->warn("Skill '%s' does not supports generic specialties!", skillPtr->getJsonKey());
|
||||
|
||||
for (const auto & bonus : skillPtr->specialtyTargetBonuses)
|
||||
result.push_back(std::make_shared<Bonus>(*bonus));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -201,15 +215,7 @@ void CHeroHandler::beforeValidate(JsonNode & object)
|
||||
}
|
||||
}
|
||||
|
||||
void CHeroHandler::afterLoadFinalization()
|
||||
{
|
||||
for(const auto & functor : callAfterLoadFinalization)
|
||||
functor();
|
||||
|
||||
callAfterLoadFinalization.clear();
|
||||
}
|
||||
|
||||
void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
|
||||
void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node) const
|
||||
{
|
||||
auto prepSpec = [=](std::shared_ptr<Bonus> bonus)
|
||||
{
|
||||
@ -230,18 +236,21 @@ void CHeroHandler::loadHeroSpecialty(CHero * hero, const JsonNode & node)
|
||||
//creature specialty - alias for simplicity
|
||||
if(!specialtyNode["creature"].isNull())
|
||||
{
|
||||
JsonNode creatureNode = specialtyNode["creature"];
|
||||
|
||||
std::function<void()> specialtyLoader = [creatureNode, hero, prepSpec]
|
||||
LIBRARY->identifiers()->requestIdentifier("creature", specialtyNode["creature"], [this, hero, prepSpec](si32 creature)
|
||||
{
|
||||
LIBRARY->identifiers()->requestIdentifier("creature", creatureNode, [hero, prepSpec](si32 creature)
|
||||
{
|
||||
for (const auto & bonus : createCreatureSpecialty(CreatureID(creature)))
|
||||
hero->specialty.push_back(prepSpec(bonus));
|
||||
});
|
||||
};
|
||||
for (const auto & bonus : createCreatureSpecialty(CreatureID(creature)))
|
||||
hero->specialty.push_back(prepSpec(bonus));
|
||||
});
|
||||
}
|
||||
|
||||
callAfterLoadFinalization.push_back(specialtyLoader);
|
||||
//secondary skill specialty - alias for simplicity
|
||||
if(!specialtyNode["secondary"].isNull())
|
||||
{
|
||||
LIBRARY->identifiers()->requestIdentifier("secondarySkill", specialtyNode["secondary"], [this, hero, prepSpec](si32 creature)
|
||||
{
|
||||
for (const auto & bonus : createSecondarySkillSpecialty(SecondarySkill(creature)))
|
||||
hero->specialty.push_back(prepSpec(bonus));
|
||||
});
|
||||
}
|
||||
|
||||
for(const auto & keyValue : specialtyNode["bonuses"].Struct())
|
||||
|
@ -28,11 +28,12 @@ class DLL_LINKAGE CHeroHandler : public CHandlerBase<HeroTypeID, HeroType, CHero
|
||||
/// helpers for loading to avoid huge load functions
|
||||
void loadHeroArmy(CHero * hero, const JsonNode & node) const;
|
||||
void loadHeroSkills(CHero * hero, const JsonNode & node) const;
|
||||
void loadHeroSpecialty(CHero * hero, const JsonNode & node);
|
||||
void loadHeroSpecialty(CHero * hero, const JsonNode & node) const;
|
||||
|
||||
void loadExperience();
|
||||
|
||||
std::vector<std::function<void()>> callAfterLoadFinalization;
|
||||
std::vector<std::shared_ptr<Bonus>> createCreatureSpecialty(CreatureID cid) const;
|
||||
std::vector<std::shared_ptr<Bonus>> createSecondarySkillSpecialty(SecondarySkill skillID) const;
|
||||
|
||||
public:
|
||||
ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount
|
||||
@ -44,7 +45,6 @@ public:
|
||||
void beforeValidate(JsonNode & object) override;
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data) override;
|
||||
void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
|
||||
void afterLoadFinalization() override;
|
||||
|
||||
CHeroHandler();
|
||||
~CHeroHandler();
|
||||
|
Reference in New Issue
Block a user