Flexible Improved Necromancy

Currently the effects of the IMPROVED_NECROMANCY bonus are hard-coded to raise walking dead, wights or liches based on necromancy skill level. To improve flexibility I’d propose the following system:

  • Each IMPROVED_NECROMANCY bonus specifies target creature raised (val), and optionally minimum necromancy skill required (subtype) and minimum level of creature stack from which to raise (addInfo).
  • For each killed creature stack, the game will consider all applicable IMPROVED_NECROMANCY bonuses, i.e. where minimum skill and stack level conditions are met.
  • Among potential target creatures, the most powerful one (level & cost) is chosen.

So e.g. the Cloak of the Undead King could be specified as

"bonuses" : [
	{
		"type" : "IMPROVED_NECROMANCY",
		"subtype" : 1, // requires basic necromancy
		"val" : "creature.walkingDead"
	},
	{
		"type" : "IMPROVED_NECROMANCY",
		"subtype" : 2, // requires advanced necromancy
		"val" : "creature.wight"
	},
	{
		"type" : "IMPROVED_NECROMANCY",
		"subtype" : 3, // requires expert necromancy
		"val" : "creature.lich"
	}
]

but (for balance reasons) one could mod these bonuses to restrict these effects by creature stack as well, e.g.

"bonuses" : [
	{
		"type" : "IMPROVED_NECROMANCY",
		"subtype" : 1, // requires basic necromancy
		"addInfo" : 2, // requires stack of level 2+
		"val" : "creature.walkingDead"
	},
	{
		"type" : "IMPROVED_NECROMANCY",
		"subtype" : 2, // requires advanced necromancy
		"addInfo" : 3, // requires stack of level 3+
		"val" : "creature.wight"
	},
	{
		"type" : "IMPROVED_NECROMANCY",
		"subtype" : 3, // requires expert necromancy
		"addInfo" : 5, // requires stack of level 5+
		"val" : "creature.lich"
	}
]

Thoughts?

I`m against using “val” for identifiers, creature id should be subtype

Makes me uneasy as well, but we have 3 values to store and 3 fields. Happy to switch them around some other way, say subtype for target creature and val for required necromancy level.

You could go further on bonus improvements and make “addInfo” arbitrary JSON node

BTW. We already have few places where is not enough Bonus fields like that:

for(const std::shared_ptr<Bonus> sf : *spellsByType)
{
    vstd::amax(spellLevel, sf->additionalInfo % 1000); //pick highest level
    int meleeRanged = sf->additionalInfo / 1000;
    if (meleeRanged == 0 || (meleeRanged == 1 && ranged) || (meleeRanged == 2 && !ranged))
	castMe = true;
}

That may be a cleaner way to go. Though I think having a flat mapping of string->int instead of arbitrary nested type would be sufficient and much simpler.