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

Merge pull request #678 from MikeLodz/develop

Fixes mantis tickets 2899 and 2984 (bugged hero spell specialties)
This commit is contained in:
Alexander Shishkin 2021-02-14 11:22:23 +03:00 committed by GitHub
commit 11bb46780a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 23 deletions

View File

@ -325,6 +325,11 @@
"class" : "elementalist", "class" : "elementalist",
"female": true, "female": true,
"spellbook": [ "stoneSkin" ], "spellbook": [ "stoneSkin" ],
"texts" : {
"specialty" : {
"description" : "{Stone Skin}\r\n\r\nCasts Stone Skin with increased effect, based on the level of the target unit. (The bonus is greater when used on weaker units)"
}
},
"skills": "skills":
[ [
{ "skill" : "wisdom", "level": "basic" }, { "skill" : "wisdom", "level": "basic" },
@ -375,9 +380,9 @@
"specialty" : { "specialty" : {
"bonuses" : { "bonuses" : {
"disruptingRay" : { "disruptingRay" : {
"addInfo" : 0, "addInfo" : -2,
"subtype" : "spell.disruptingRay", "subtype" : "spell.disruptingRay",
"type" : "SPECIAL_PECULIAR_ENCHANT" "type" : "SPECIAL_ADD_VALUE_ENCHANT"
} }
} }
} }

View File

@ -265,8 +265,9 @@
"specialty" : { "specialty" : {
"bonuses" : { "bonuses" : {
"fortune" : { "fortune" : {
"addInfo" : 3,
"subtype" : "spell.fortune", "subtype" : "spell.fortune",
"type" : "MAXED_SPELL" "type" : "SPECIAL_FIXED_VALUE_ENCHANT"
} }
} }
} }

View File

@ -1468,6 +1468,8 @@ JsonNode subtypeToJson(Bonus::BonusType type, int subtype)
case Bonus::SPECIAL_BLESS_DAMAGE: case Bonus::SPECIAL_BLESS_DAMAGE:
case Bonus::MAXED_SPELL: case Bonus::MAXED_SPELL:
case Bonus::SPECIAL_PECULIAR_ENCHANT: case Bonus::SPECIAL_PECULIAR_ENCHANT:
case Bonus::SPECIAL_ADD_VALUE_ENCHANT:
case Bonus::SPECIAL_FIXED_VALUE_ENCHANT:
return JsonUtils::stringNode("spell." + (*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier); return JsonUtils::stringNode("spell." + (*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier);
case Bonus::IMPROVED_NECROMANCY: case Bonus::IMPROVED_NECROMANCY:
case Bonus::SPECIAL_UPGRADE: case Bonus::SPECIAL_UPGRADE:
@ -1556,6 +1558,8 @@ std::string Bonus::nameForBonus() const
case Bonus::SPECIAL_BLESS_DAMAGE: case Bonus::SPECIAL_BLESS_DAMAGE:
case Bonus::MAXED_SPELL: case Bonus::MAXED_SPELL:
case Bonus::SPECIAL_PECULIAR_ENCHANT: case Bonus::SPECIAL_PECULIAR_ENCHANT:
case Bonus::SPECIAL_ADD_VALUE_ENCHANT:
case Bonus::SPECIAL_FIXED_VALUE_ENCHANT:
return (*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier; return (*VLC->spellh)[SpellID::ESpellID(subtype)]->identifier;
case Bonus::SPECIAL_UPGRADE: case Bonus::SPECIAL_UPGRADE:
return CreatureID::encode(subtype) + "2" + CreatureID::encode(additionalInfo[0]); return CreatureID::encode(subtype) + "2" + CreatureID::encode(additionalInfo[0]);

View File

@ -321,6 +321,8 @@ public:
BONUS_NAME(SPECIAL_CRYSTAL_GENERATION) /*crystal dragon crystal generation*/ \ BONUS_NAME(SPECIAL_CRYSTAL_GENERATION) /*crystal dragon crystal generation*/ \
BONUS_NAME(NO_SPELLCAST_BY_DEFAULT) /*spellcast will not be default attack option for this creature*/ \ BONUS_NAME(NO_SPELLCAST_BY_DEFAULT) /*spellcast will not be default attack option for this creature*/ \
BONUS_NAME(GARGOYLE) /* gargoyle is special than NON_LIVING, cannot be rised or healed */ \ BONUS_NAME(GARGOYLE) /* gargoyle is special than NON_LIVING, cannot be rised or healed */ \
BONUS_NAME(SPECIAL_ADD_VALUE_ENCHANT) /*specialty spell like Aenin has, increased effect of spell, additionalInfo = value to add*/\
BONUS_NAME(SPECIAL_FIXED_VALUE_ENCHANT) /*specialty spell like Melody has, constant spell effect (i.e. 3 luck), additionalInfo = value to fix.*/\
/* end of list */ /* end of list */

View File

@ -791,7 +791,15 @@ TDmgRange CBattleInfoCallback::calculateDmgRange(const BattleAttackInfo & info)
} }
if(isAffected) if(isAffected)
{
attackDefenceDifference += SpellID(SpellID::SLAYER).toSpell()->getPower(spLevel); attackDefenceDifference += SpellID(SpellID::SLAYER).toSpell()->getPower(spLevel);
if(info.attacker->hasBonusOfType(Bonus::SPECIAL_PECULIAR_ENCHANT, SpellID::SLAYER))
{
ui8 attackerTier = info.attacker->unitType()->level;
ui8 specialtyBonus = std::max(5 - attackerTier, 0);
attackDefenceDifference += specialtyBonus;
}
}
} }
//bonus from attack/defense skills //bonus from attack/defense skills

View File

@ -151,10 +151,16 @@ void Timed::prepareEffects(SetStackEffect & sse, const Mechanics * m, const Effe
std::vector<Bonus> converted; std::vector<Bonus> converted;
convertBonus(m, duration, converted); convertBonus(m, duration, converted);
std::shared_ptr<const Bonus> bonus = nullptr; std::shared_ptr<const Bonus> peculiarBonus = nullptr;
std::shared_ptr<const Bonus> addedValueBonus = nullptr;
std::shared_ptr<const Bonus> fixedValueBonus = nullptr;
auto casterHero = dynamic_cast<const CGHeroInstance *>(m->caster); auto casterHero = dynamic_cast<const CGHeroInstance *>(m->caster);
if(casterHero) if(casterHero)
bonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_PECULIAR_ENCHANT, m->getSpellIndex())); {
peculiarBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_PECULIAR_ENCHANT, m->getSpellIndex()));
addedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_ADD_VALUE_ENCHANT, m->getSpellIndex()));
fixedValueBonus = casterHero->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPECIAL_FIXED_VALUE_ENCHANT, m->getSpellIndex()));
}
//TODO: does hero specialty should affects his stack casting spells? //TODO: does hero specialty should affects his stack casting spells?
for(auto & t : target) for(auto & t : target)
@ -175,16 +181,17 @@ void Timed::prepareEffects(SetStackEffect & sse, const Mechanics * m, const Effe
if(describe) if(describe)
describeEffect(sse.battleLog, m, converted, affected); describeEffect(sse.battleLog, m, converted, affected);
si32 power = 0; const auto tier = std::max(affected->creatureLevel(), 1); //don't divide by 0 for certain creatures (commanders, war machines)
//Apply hero specials - peculiar enchants //Apply hero specials - peculiar enchants
const auto tier = std::max(affected->creatureLevel(), 1); //don't divide by 0 for certain creatures (commanders, war machines) if(peculiarBonus)
if(bonus)
{ {
switch(bonus->additionalInfo[0])
si32 power = 0;
switch (peculiarBonus->additionalInfo[0])
{ {
case 0: //normal case 0: //normal
switch(tier) switch (tier)
{ {
case 1: case 1:
case 2: case 2:
@ -199,23 +206,36 @@ void Timed::prepareEffects(SetStackEffect & sse, const Mechanics * m, const Effe
power = 1; power = 1;
break; break;
} }
for(const Bonus & b : converted)
{
Bonus specialBonus(b);
specialBonus.val = power; //it doesn't necessarily make sense for some spells, use it wisely
specialBonus.turnsRemain = duration;
//additional premy to given effect
buffer.push_back(specialBonus);
}
break; break;
case 1: //only Coronius as yet case 1:
//Coronius style specialty bonus.
//Please note that actual Coronius isnt here, because Slayer is a spell that doesnt affect monster stats and is used only in calculateDmgRange
power = std::max(5 - tier, 0); power = std::max(5 - tier, 0);
Bonus specialBonus(Bonus::N_TURNS, Bonus::PRIMARY_SKILL, Bonus::SPELL_EFFECT, power, m->getSpellIndex(), PrimarySkill::ATTACK);
specialBonus.turnsRemain = duration;
buffer.push_back(specialBonus);
break; break;
} }
if(m->isNegativeSpell())
{
//negative spells like weakness are defined in json with negative numbers, so we need do same here
power = -1 * power;
}
for(Bonus& b : buffer)
{
b.val += power;
}
}
if(addedValueBonus)
{
for(Bonus& b : buffer)
{
b.val += addedValueBonus->additionalInfo[0];
}
}
if(fixedValueBonus)
{
for(Bonus& b : buffer)
{
b.val = fixedValueBonus->additionalInfo[0];
}
} }
if(casterHero && casterHero->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, m->getSpellIndex())) //TODO: better handling of bonus percentages if(casterHero && casterHero->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, m->getSpellIndex())) //TODO: better handling of bonus percentages
{ {