I want to implement make secondary skills moddable, by introducing JSON config for them.
While looking at the code, I wondered something. In CGHeroInstance::updateSkill(), two different ways of getting a bonus object are used:
// used by luck, morale and diplomacy
Bonus *b = getBonusLocalFirst(Selector::type(Bonus::SURRENDER_DISCOUNT).And(Selector::sourceType(Bonus::SECONDARY_SKILL)))
// used by all others
Bonus * b = getExportedBonusList().getFirst(Selector::typeSubtype(Bonus::SECONDARY_SKILL_PREMY, which).And(Selector::sourceType(Bonus::SECONDARY_SKILL)))
Why is this the case, and does it have to be that way?
Also, I’m thinking about the JSON format for secondary skills. At the moment I have something like this in mind:
{
"name":"skill name",
"basicIcon":"icon name",
"advancedIcon":"icon name",
"expertIcon":"icon name",
"basicBonuses":<bonus format>,...],
"advancedBonuses":<bonus format>,...],
"expertBonuses":<bonus format>,...],
"whitelistFactions": "faction",..], // only necropolis heroes can have Necromancy
"blacklistFactions": "faction",..], // necropolis heroes can't have Leadership
"maxlevelsMight":0, // for wisdom and spell schools
"maxlevelsMagic":0
}
About bonuses. Code is inconsistent there because this way (with help of @AVS) I attempted to fix corruptions within bonus system. Issue was that some of that code modified “cache” of bonus lists instead of actual data. You can find related commits with “git blame”. Sadly looking on that code now I’m no longer sure there is no code with wrong behavior.
Unfortunately it’s impossible to improve bonus system further until noncopyableBonusSystemNode branch merged. And that won’t happen till we start breakage of save format.
PS: So if you decide to change something related to bonuses please make sure to work on top of that branch.
Second is right way to modify (only modify existing objects) local bonuses. (getExportedBonusList return actual container) Be careful with client-server synchronization.
I like different design
{
"base":{<attributes for all skill levels if any>},
"basic":{"icon":"", "bonuses":{} },
"advanced": ...
}
Also try to avoid json arrays - they are bad for modding.
// Chance to get specific secondary skill on level-up
// Skills not listed here will be considered as unavailable, including universities
I think it’s wrong idea, i suppose you change this to that way:
// Chance to get specific secondary skill on level-up
// Skills with chance to get =0 here will be considered as unavailable, including universities
// Skills non listed here will have default chance on level-up
It is true that secondary skills won’t know all factions. However, hero classes won’t know all secondary skills either. I think the best solution is doing it as you suggested; secondary skills need to be explicitly banned from the hero class. However, it would be troublesome if someone makes a mod with a secondary skill only meant for one faction (like necromancy), because the modder would then have to mod all existing hero classes (even other ones added by mods). A field in the secondary skill config, called “defaultChance” would solve that issue. That value will be used, if it is not expicitly specified in config.
Wisdom and spell schools have the property that heroes are guaranteed to get them as a choice every n:th level; that’s what I intended these fields for. What would the “affinity” field be useful for?
How do translations work? The same as other mods (by overriding JSON config) or somehow else? I couldn’t figure it out by looking through the code, and I need to know this to implement changes to secondary skills…
By overriding JSON. Also its recommended to have translatable strings in separate JSON files (but in same schema) - f.e. see “bonuses.json” “bonuses_texts.json” .
At the moment I have gotten stuck on handling heroes levelling up and proposing new skills. It is really difficult because there are a lot of special cases to handle, and even more so due to the fact that it should be configurable whether or not those special cases apply…
I will likely refactor the skill on level up selection away from CGHeroInstance, because I think it should be possible to override the default behaviour when scripting is supported.
Some of standard skills allow SECONDARY_SKILL_PREMY bonuses in %, and some are not. Maybe firstly make them all resposible to bonuses % and move level % to json configs.
Maybe standard secondary skills could be left as they are now, and only add new skills modding posibility?
I got stuck as mentioned above, then I didn’t have any time to work on it for a long time. I still want to do this at some point in the future, but I’ll likely have to take a different approach, such as refactoring CGHeroInstance first.