diff --git a/config/bonusnames.json b/config/bonusnames.json index 0125a3f40..b108de6a1 100644 --- a/config/bonusnames.json +++ b/config/bonusnames.json @@ -56,6 +56,7 @@ { "id": "REBIRTH", "name": "Rebirth (%d%)", "description": "Stack will rise after death" }, { "id": "SPELLCASTER", "name": "Spellcaster (%s)", "description": "Can cast spells" }, { "id": "ENCHANTER", "name": "Enchanter (%s)", "description": "Casts mass spell every turn" }, + { "id": "ENCHANTED", "name": "Enchanted (%s)", "description": "Affected by permanent spell" }, { "id": "RANDOM_SPELLCASTER", "name": "Random spellcaster", "description": "Can cast random spell" }, { "id": "DAEMON_SUMMONING", "name": "Summoner (%s)", "description": "Can rise creatures from corpses" } ] diff --git a/lib/CBattleCallback.cpp b/lib/CBattleCallback.cpp index 2c83d6323..e2e9b9b82 100644 --- a/lib/CBattleCallback.cpp +++ b/lib/CBattleCallback.cpp @@ -1517,6 +1517,7 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleIsImmune(const C } break; case Spells::FORGETFULNESS: + case Spells::PRECISION: if (!subject->hasBonusOfType(Bonus::SHOOTER)) return ESpellCastProblem::STACK_IMMUNE_TO_SPELL; break; diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index ced3de05b..996e01fce 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -799,7 +799,6 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars b.type = Bonus::STACKS_SPEED; break; case 'O': b.type = Bonus::SHOTS; break; - case 'b': b.type = Bonus::ENEMY_DEFENCE_REDUCTION; break; case 'C': @@ -826,7 +825,6 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars b.type = Bonus::MAGIC_RESISTANCE; b.subtype = 0; //otherwise creature window goes crazy break; - case 'f': //on-off skill enable = true; //sometimes format is: 2 -> 0, 1 -> 1 switch (mod[0]) @@ -866,7 +864,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars case 'U': b.type = Bonus::UNDEAD; break; default: - tlog5 << "Not parsed bonus " << buf << mod << "\n"; + tlog5 << "Not parsed bonus " << buf << mod << "\n"; return; break; } @@ -993,6 +991,11 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, CLegacyConfigPars b.subtype = stringToNumber(mod); b.additionalInfo = 3; //always expert? break; + case 's': + b.type = Bonus::ENCHANTED; + b.subtype = stringToNumber(mod); + b.valType = Bonus::INDEPENDENT_MAX; + break; default: tlog5 << "Not parsed bonus " << buf << mod << "\n"; return; diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 61d8ea0ef..b18eead73 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -666,6 +666,7 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const case Bonus::SPELL_IMMUNITY: case Bonus::SPELLCASTER: case Bonus::ENCHANTER: + case Bonus::ENCHANTED: boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name); break; case Bonus::MAGIC_RESISTANCE: @@ -690,7 +691,8 @@ std::string CStackInstance::bonusToGraphics(Bonus *bonus) const { //"E_ALIVE.bmp" //"E_ART.bmp" - //"E_BLESS.bmp" + case Bonus::ENCHANTED: + fileName = "E_BLESS.bmp"; break; //"E_BLOCK.bmp" //"E_BLOCK1.bmp" //"E_BLOCK2.bmp" diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 00515dc5c..36bf48fea 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -173,6 +173,7 @@ typedef boost::function CSelector; BONUS_NAME(SPECIFIC_SPELL_POWER) /* value used for Thunderbolt and Resurrection casted by units, subtype - spell id */\ BONUS_NAME(CREATURE_SPELL_POWER) /* value per unit, divided by 100 (so faerie Dragons have 800)*/ \ BONUS_NAME(CREATURE_ENCHANT_POWER) /* total duration of spells casted by creature */ \ + BONUS_NAME(ENCHANTED) /* permanently enchanted with spell subID of level = val, if val > 3 then spell is mass and has level of val-3*/ \ BONUS_NAME(REBIRTH) /* val - percent of life restored, subtype = 0 - regular, 1 - at least one unit (sacred Phoenix) */\ BONUS_NAME(ADDITIONAL_UNITS) /*val of units with id = subtype will be added to hero's army at the beginning of battle */\ BONUS_NAME(SPOILS_OF_WAR) /*val * 10^-6 * gained exp resources of subtype will be given to hero after battle*/\ diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index c0db23192..236e2675b 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -4605,6 +4605,36 @@ void CGameHandler::stackTurnTrigger(const CStack * st) sendAndApply(&ssp); } } + bl = *(st->getBonuses(Selector::type(Bonus::ENCHANTED))); + BOOST_FOREACH (auto b, bl) + { + SetStackEffect sse; + int val = bl.valOfBonuses (Selector::typeSubtype(b->type, b->subtype)); + if (val > 3) + { + BOOST_FOREACH (auto s, gs->curB->battleGetAllStacks()) + { + if (st->owner == s->owner && s->isValidTarget()) //all allied + sse.stacks.push_back (s->ID); + } + } + else + sse.stacks.push_back (st->ID); + //from handleSpellCasting + //SetStackEffect sse; + //Bonus pseudoBonus; + //pseudoBonus.sid = spellID; + //pseudoBonus.val = spellLvl; + //pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, stackSpellPower ? stackSpellPower : usedSpellPower); + //CStack::stackEffectToFeature(sse.effect, pseudoBonus); + + Bonus pseudoBonus; + pseudoBonus.sid = b->subtype; + pseudoBonus.val = ((val > 3) ? (val - 3) : val); + pseudoBonus.turnsRemain = 50; + st->stackEffectToFeature (sse.effect, pseudoBonus); + sendAndApply (&sse); + } } }