From a86e12cd42debc5c0fa762cf36ce639a60833938 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Sun, 19 Feb 2023 23:55:18 +0300 Subject: [PATCH] vcmi: convert necromancy Now it is 3 bonuses to cover necromancy. 1. IMPROVED_NECROMANCY = possible creatures raized (affected by cloak) 2. UNDEAD_RAISE_CHANCE = raise chance (affected by artifacts) 3. UNDEAD_RAISE_POWER = helper to select creature from first --- config/artifacts.json | 14 ++++++++------ config/factions/necropolis.json | 4 ++-- config/heroes/necropolis.json | 12 ++++++------ config/skills.json | 17 ++++++++++++----- lib/HeroBonus.h | 3 ++- lib/mapObjects/CGHeroInstance.cpp | 19 ++++++++++++------- 6 files changed, 42 insertions(+), 27 deletions(-) diff --git a/config/artifacts.json b/config/artifacts.json index 02dc019f2..aed5918c5 100644 --- a/config/artifacts.json +++ b/config/artifacts.json @@ -834,8 +834,7 @@ { "bonuses" : [ { - "subtype" : 12, - "type" : "SECONDARY_SKILL_PREMY", + "type" : "UNDEAD_RAISE_PERCENTAGE", "val" : 5, "valueType" : "ADDITIVE_VALUE" } @@ -847,8 +846,7 @@ { "bonuses" : [ { - "subtype" : 12, - "type" : "SECONDARY_SKILL_PREMY", + "type" : "UNDEAD_RAISE_PERCENTAGE", "val" : 10, "valueType" : "ADDITIVE_VALUE" } @@ -860,8 +858,7 @@ { "bonuses" : [ { - "subtype" : 12, - "type" : "SECONDARY_SKILL_PREMY", + "type" : "UNDEAD_RAISE_PERCENTAGE", "val" : 15, "valueType" : "ADDITIVE_VALUE" } @@ -1931,6 +1928,11 @@ "cloakOfTheUndeadKing": { "bonuses" : [ + { + "type" : "IMPROVED_NECROMANCY", + "subtype" : "creature.skeleton", + "addInfo" : 0 + }, { "type" : "IMPROVED_NECROMANCY", "subtype" : "creature.walkingDead", diff --git a/config/factions/necropolis.json b/config/factions/necropolis.json index 8caa848a1..06b6ea00e 100644 --- a/config/factions/necropolis.json +++ b/config/factions/necropolis.json @@ -181,10 +181,10 @@ "horde1Upgr": { "id" : 19, "upgrades" : "dwellingUpLvl1", "requires" : [ "horde1" ], "mode" : "auto" }, "ship": { "id" : 20, "upgrades" : "shipyard" }, "special2": { "requires" : [ "mageGuild1" ], - "bonuses": [ { "type": "SECONDARY_SKILL_PREMY", "subtype": "skill.necromancy", "val": 10, "propagator": "PLAYER_PROPAGATOR" } ] }, + "bonuses": [ { "type": "UNDEAD_RAISE_PERCENTAGE", "val": 10, "propagator": "PLAYER_PROPAGATOR" } ] }, "special3": { "type" : "creatureTransformer", "requires" : [ "dwellingLvl1" ] }, "grail": { "id" : 26, "mode" : "grail", "produce": { "gold": 5000 }, - "bonuses": [ { "type": "SECONDARY_SKILL_PREMY", "subtype": "skill.necromancy", "val": 20, "propagator": "PLAYER_PROPAGATOR" } ] }, + "bonuses": [ { "type": "UNDEAD_RAISE_PERCENTAGE", "val": 20, "propagator": "PLAYER_PROPAGATOR" } ] }, "extraTownHall": { "id" : 27, "requires" : [ "townHall" ], "mode" : "auto" }, "extraCityHall": { "id" : 28, "requires" : [ "cityHall" ], "mode" : "auto" }, diff --git a/config/heroes/necropolis.json b/config/heroes/necropolis.json index 1a3e643e3..3cc272494 100644 --- a/config/heroes/necropolis.json +++ b/config/heroes/necropolis.json @@ -87,11 +87,11 @@ "specialty" : { "bonuses" : { "necromancy" : { - "subtype" : "skill.necromancy", - "type" : "SECONDARY_SKILL_PREMY", + "type" : "UNDEAD_RAISE_PERCENTAGE", "updater" : "TIMES_HERO_LEVEL", "val" : 5, - "valueType" : "PERCENT_TO_BASE" + "valueType" : "PERCENT_TO_TARGET_TYPE", + "targetSourceType" : "SECONDARY_SKILL" } } } @@ -279,11 +279,11 @@ "specialty" : { "bonuses" : { "necromancy" : { - "subtype" : "skill.necromancy", - "type" : "SECONDARY_SKILL_PREMY", + "type" : "UNDEAD_RAISE_PERCENTAGE", "updater" : "TIMES_HERO_LEVEL", "val" : 5, - "valueType" : "PERCENT_TO_BASE" + "valueType" : "PERCENT_TO_TARGET_TYPE", + "targetSourceType" : "SECONDARY_SKILL" } } } diff --git a/config/skills.json b/config/skills.json index 02369aa40..870fe06c3 100644 --- a/config/skills.json +++ b/config/skills.json @@ -345,25 +345,32 @@ "base" : { "effects" : { "main" : { - "subtype" : "skill.necromancy", - "type" : "SECONDARY_SKILL_PREMY", + "type" : "UNDEAD_RAISE_PERCENTAGE", "valueType" : "BASE_NUMBER" + }, + "power" : { + "type" : "IMPROVED_NECROMANCY", + "subtype" : "creature.skeleton", + "addInfo" : 0 } } }, "basic" : { "effects" : { - "main" : { "val" : 10 } + "main" : { "val" : 10 }, + "power" : { "val" : 1 } } }, "advanced" : { "effects" : { - "main" : { "val" : 20 } + "main" : { "val" : 20 }, + "power" : { "val" : 2 } } }, "expert" : { "effects" : { - "main" : { "val" : 30 } + "main" : { "val" : 30 }, + "power" : { "val" : 3 } } } }, diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index d6c5b0cf1..4c5e2d4a2 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -208,7 +208,7 @@ public: BONUS_NAME(MAGIC_SCHOOL_SKILL) /* //eg. for magic plains terrain, subtype: school of magic (0 - all, 1 - fire, 2 - air, 4 - water, 8 - earth), value - level*/ \ BONUS_NAME(FREE_SHOOTING) /*stacks can shoot even if otherwise blocked (sharpshooter's bow effect)*/ \ BONUS_NAME(OPENING_BATTLE_SPELL) /*casts a spell at expert level at beginning of battle, val - spell power, subtype - spell id*/ \ - BONUS_NAME(IMPROVED_NECROMANCY) /* raise more powerful creatures: subtype - creature type raised, addInfo - [required necromancy level, required stack level] */ \ + BONUS_NAME(IMPROVED_NECROMANCY) /* raise more powerful creatures: subtype - creature type raised, addInfo - [required necromancy level, required stack level], val - necromancy level for this purpose */ \ BONUS_NAME(CREATURE_GROWTH_PERCENT) /*increases growth of all units in all towns, val - percentage*/ \ BONUS_NAME(FREE_SHIP_BOARDING) /*movement points preserved with ship boarding and landing*/ \ BONUS_NAME(NO_TYPE) \ @@ -341,6 +341,7 @@ public: BONUS_NAME(BEFORE_BATTLE_REPOSITION) /*skill-agnostic tactics, bonus for allowing tactics*/\ BONUS_NAME(BEFORE_BATTLE_REPOSITION_BLOCK) /*skill-agnostic tactics, bonus for blocking opposite tactics. For now donble side tactics is TODO.*/\ BONUS_NAME(HERO_EXPERIENCE_GAIN_PERCENT) /*skill-agnostic learning, and we can use it as a global effect also*/\ + BONUS_NAME(UNDEAD_RAISE_PERCENTAGE) /*Percentage of killed enemy creatures to be raised after battle as undead*/\ /* end of list */ diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index f63a454f9..e7fc499fa 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -782,23 +782,27 @@ bool CGHeroInstance::canLearnSpell(const spells::Spell * spell) const */ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &battleResult) const { - const ui8 necromancyLevel = getSecSkillLevel(SecondarySkill::NECROMANCY); + bool hasImprovedNecromancy = hasBonusOfType(Bonus::IMPROVED_NECROMANCY); + // need skill or cloak of undead king - lesser artifacts don't work without skill - if (necromancyLevel > 0 || hasBonusOfType(Bonus::IMPROVED_NECROMANCY)) + if (hasImprovedNecromancy) { - double necromancySkill = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::NECROMANCY) / 100.0; + double necromancySkill = valOfBonuses(Bonus::UNDEAD_RAISE_PERCENTAGE) / 100.0; + const ui8 necromancyLevel = valOfBonuses(Bonus::IMPROVED_NECROMANCY); vstd::amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all... const std::map &casualties = battleResult.casualties[!battleResult.winner]; // figure out what to raise - pick strongest creature meeting requirements - CreatureID creatureTypeRaised = CreatureID::SKELETON; + auto creatureTypeRaised = CreatureID::NONE; //now we always have IMPROVED_NECROMANCY, no need for hardcode int requiredCasualtyLevel = 1; TConstBonusListPtr improvedNecromancy = getBonuses(Selector::type()(Bonus::IMPROVED_NECROMANCY)); if(!improvedNecromancy->empty()) { - auto getCreatureID = [necromancyLevel](const std::shared_ptr & bonus) -> CreatureID + auto getCreatureID = [](const std::shared_ptr & bonus) -> CreatureID { - const CreatureID legacyTypes[] = {CreatureID::SKELETON, CreatureID::WALKING_DEAD, CreatureID::WIGHTS, CreatureID::LICHES}; - return CreatureID(bonus->subtype >= 0 ? bonus->subtype : legacyTypes[necromancyLevel]); + assert(bonus->subtype >=0); + if(bonus->subtype >= 0) + return CreatureID(bonus->subtype); + return CreatureID::NONE; }; int maxCasualtyLevel = 1; for(const auto & casualty : casualties) @@ -831,6 +835,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b requiredCasualtyLevel = std::max(topPick->additionalInfo[1], 1); } } + assert(creatureTypeRaised != CreatureID::NONE); // raise upgraded creature (at 2/3 rate) if no space available otherwise if(getSlotFor(creatureTypeRaised) == SlotID()) {