mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Support for Poison, Age, Disease
Partial support for Stone Gaze, Paralyze, Mana drain Partial fix for #134 - animation triggers only for our own stacks, not enemy's Lots of tweaks & fixes.
This commit is contained in:
parent
362f413b4d
commit
a4d845688a
@ -2307,6 +2307,20 @@ void CBattleInterface::stackRemoved(const CStack * stack)
|
|||||||
|
|
||||||
void CBattleInterface::stackActivated(const CStack * stack)
|
void CBattleInterface::stackActivated(const CStack * stack)
|
||||||
{
|
{
|
||||||
|
//don't show animation when no HP is regenerated
|
||||||
|
if (stack->firstHPleft != stack->MaxHealth())
|
||||||
|
{
|
||||||
|
if( stack->hasBonusOfType(Bonus::HP_REGENERATION) || stack->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 1))
|
||||||
|
displayEffect(74, stack->position);
|
||||||
|
if( stack->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 0))
|
||||||
|
displayEffect(4, stack->position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stack->hasBonusOfType(Bonus::MANA_DRAIN))
|
||||||
|
displayEffect(77, stack->position);
|
||||||
|
if(stack->hasBonusOfType(Bonus::POISON))
|
||||||
|
displayEffect(67, stack->position);
|
||||||
|
|
||||||
//givenCommand = NULL;
|
//givenCommand = NULL;
|
||||||
stackToActivate = stack;
|
stackToActivate = stack;
|
||||||
if(pendingAnims.size() == 0)
|
if(pendingAnims.size() == 0)
|
||||||
@ -2347,20 +2361,6 @@ void CBattleInterface::newRoundFirst( int round )
|
|||||||
std::vector<const CStack*> stacks = curInt->cb->battleGetStacks(); //gets only alive stacks
|
std::vector<const CStack*> stacks = curInt->cb->battleGetStacks(); //gets only alive stacks
|
||||||
BOOST_FOREACH(const CStack *s, stacks)
|
BOOST_FOREACH(const CStack *s, stacks)
|
||||||
{
|
{
|
||||||
//don't show animation when no HP is regenerated
|
|
||||||
if (s->firstHPleft == s->MaxHealth())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( s->hasBonusOfType(Bonus::HP_REGENERATION))
|
|
||||||
displayEffect(74, s->position);
|
|
||||||
|
|
||||||
if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 0))
|
|
||||||
displayEffect(4, s->position);
|
|
||||||
|
|
||||||
if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION, 1))
|
|
||||||
displayEffect(74, s->position);
|
|
||||||
}
|
}
|
||||||
waitForAnims();
|
waitForAnims();
|
||||||
}
|
}
|
||||||
@ -2826,7 +2826,6 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
|
|||||||
case 37: //cure
|
case 37: //cure
|
||||||
case 38: //resurrection
|
case 38: //resurrection
|
||||||
case 39: //animate dead
|
case 39: //animate dead
|
||||||
case 78: //dispel helpful spells
|
|
||||||
for(std::set<ui32>::const_iterator it = sc->affectedCres.begin(); it != sc->affectedCres.end(); ++it)
|
for(std::set<ui32>::const_iterator it = sc->affectedCres.begin(); it != sc->affectedCres.end(); ++it)
|
||||||
{
|
{
|
||||||
displayEffect(spell.mainEffectAnim, curInt->cb->battleGetStackByID(*it, false)->position);
|
displayEffect(spell.mainEffectAnim, curInt->cb->battleGetStackByID(*it, false)->position);
|
||||||
@ -2856,24 +2855,32 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sc->id == 79) // Death Stare
|
switch(sc->id)
|
||||||
{
|
{
|
||||||
customSpell = true;
|
case 71: //Poison
|
||||||
if (sc->dmgToDisplay > 1)
|
customSpell = true;
|
||||||
{
|
break;
|
||||||
text = CGI->generaltexth->allTexts[119]; //%d %s die under the terrible gaze of the %s.
|
//case 75: // Aging
|
||||||
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(sc->dmgToDisplay));
|
// customSpell = true;
|
||||||
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getCreature()->namePl );
|
// break;
|
||||||
}
|
case 79: // Death Stare
|
||||||
else
|
customSpell = true;
|
||||||
{
|
if (sc->dmgToDisplay > 1)
|
||||||
text = CGI->generaltexth->allTexts[118]; //One %s dies under the terrible gaze of the %s.
|
{
|
||||||
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin())->type->nameSing);
|
text = CGI->generaltexth->allTexts[119]; //%d %s die under the terrible gaze of the %s.
|
||||||
}
|
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(sc->dmgToDisplay));
|
||||||
boost::algorithm::replace_first(text, "%s", "Creatures"); //casting stack
|
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getCreature()->namePl );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = CGI->generaltexth->allTexts[118]; //One %s dies under the terrible gaze of the %s.
|
||||||
|
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin())->type->nameSing);
|
||||||
|
}
|
||||||
|
boost::algorithm::replace_first(text, "%s", "Creatures"); //casting stack
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
|
||||||
}
|
}
|
||||||
else
|
|
||||||
boost::algorithm::replace_first(text, "%s", "Creature"); //TODO: better fix
|
|
||||||
}
|
}
|
||||||
if (!customSpell)
|
if (!customSpell)
|
||||||
boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id]->name);
|
boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id]->name);
|
||||||
@ -3503,10 +3510,12 @@ void CBattleInterface::startAction(const BattleAction* action)
|
|||||||
console->addText(txt);
|
console->addText(txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
//displaying heal animation
|
//displaying special abilities
|
||||||
if (action->actionType == BattleAction::STACK_HEAL)
|
switch (action->actionType)
|
||||||
{
|
{
|
||||||
displayEffect(50, action->destinationTile);
|
case BattleAction::STACK_HEAL:
|
||||||
|
displayEffect(50, action->destinationTile);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@
|
|||||||
64 1 C20SPX.DEF
|
64 1 C20SPX.DEF
|
||||||
65 0
|
65 0
|
||||||
66 0
|
66 0
|
||||||
67 0
|
67 1 SP11_.DEF
|
||||||
68 0
|
68 1 SP02_.DEF
|
||||||
69 1 C05SPE0.DEF
|
69 1 C05SPE0.DEF
|
||||||
70 2 SP02_.DEF SP10_.DEF
|
70 2 SP02_.DEF SP10_.DEF
|
||||||
71 1 SP01_.DEF
|
71 1 SP01_.DEF
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
+ 17 MAGIC_RESISTANCE 40 0 0 //battle dwarf's magic resistance 40%
|
+ 17 MAGIC_RESISTANCE 40 0 0 //battle dwarf's magic resistance 40%
|
||||||
+ 20 CHANGES_SPELL_COST_FOR_ENEMY 2 0 0 //pegasus makes spell cost higher for enemy mage
|
+ 20 CHANGES_SPELL_COST_FOR_ENEMY 2 0 0 //pegasus makes spell cost higher for enemy mage
|
||||||
+ 21 CHANGES_SPELL_COST_FOR_ENEMY 2 0 0 //silver pegasus makes spell cost higher for enemy mage
|
+ 21 CHANGES_SPELL_COST_FOR_ENEMY 2 0 0 //silver pegasus makes spell cost higher for enemy mage
|
||||||
+ 22 SPELL_AFTER_ATTACK 0 72 100 //dendroids cast bind
|
+ 22 SPELL_AFTER_ATTACK 72 0 100 //dendroids cast bind
|
||||||
+ 23 SPELL_AFTER_ATTACK 0 72 100 //dendroid guards cast bind
|
+ 23 SPELL_AFTER_ATTACK 72 0 100 //dendroid guards cast bind
|
||||||
+ 24 SPELL_AFTER_ATTACK 0 62 20 //unicorns cast blind with 20% probability
|
+ 24 SPELL_AFTER_ATTACK 62 0 20 //unicorns cast blind with 20% probability
|
||||||
+ 24 SPELL_RESISTANCE_AURA 0 55 0 //unicorn
|
+ 24 SPELL_RESISTANCE_AURA 0 55 0 //unicorn
|
||||||
+ 25 SPELL_AFTER_ATTACK 0 62 20 //war unicorns cast blind with 20% probability
|
+ 25 SPELL_AFTER_ATTACK 62 0 20 //war unicorns cast blind with 20% probability
|
||||||
+ 25 SPELL_RESISTANCE_AURA 20 55 0 //war unicorn
|
+ 25 SPELL_RESISTANCE_AURA 20 55 0 //war unicorn
|
||||||
+ 26 LEVEL_SPELL_IMMUNITY 3 0 0 //green dragon's spell immunity
|
+ 26 LEVEL_SPELL_IMMUNITY 3 0 0 //green dragon's spell immunity
|
||||||
+ 26 TWO_HEX_ATTACK_BREATH 0 0 0 //green dragon's breath
|
+ 26 TWO_HEX_ATTACK_BREATH 0 0 0 //green dragon's breath
|
||||||
@ -86,22 +86,22 @@
|
|||||||
+ 63 LIFE_DRAIN 0 0 0 //vampire lords
|
+ 63 LIFE_DRAIN 0 0 0 //vampire lords
|
||||||
+ 64 SPELL_LIKE_ATTACK 76 0 0 //liches
|
+ 64 SPELL_LIKE_ATTACK 76 0 0 //liches
|
||||||
+ 65 SPELL_LIKE_ATTACK 76 0 0 //power liches
|
+ 65 SPELL_LIKE_ATTACK 76 0 0 //power liches
|
||||||
+ 66 SPELL_AFTER_ATTACK 0 42 20 //black knights
|
+ 66 SPELL_AFTER_ATTACK 20 42 0 //black knights
|
||||||
+ 67 DOUBLE_DAMAGE_CHANCE 20 0 0 //vampire lords
|
+ 67 DOUBLE_DAMAGE_CHANCE 20 0 0 //vampire lords
|
||||||
+ 67 SPELL_AFTER_ATTACK 0 42 20 //dread knights
|
+ 67 SPELL_AFTER_ATTACK 20 42 0 //dread knights
|
||||||
+ 68 DRAGON_NATURE 0 0 0 //bone dragon is a dragon
|
+ 68 DRAGON_NATURE 0 0 0 //bone dragon is a dragon
|
||||||
+ 69 SPELL_AFTER_ATTACK 0 75 20 //ghost dragon
|
+ 69 SPELL_AFTER_ATTACK 20 75 0 //ghost dragon
|
||||||
+ 69 DRAGON_NATURE 0 0 0 //ghost dragon is a dragon
|
+ 69 DRAGON_NATURE 0 0 0 //ghost dragon is a dragon
|
||||||
+ 70 SPELL_IMMUNITY 0 62 0 //troglodytes are immune to blind
|
+ 70 SPELL_IMMUNITY 0 62 0 //troglodytes are immune to blind
|
||||||
+ 71 SPELL_IMMUNITY 0 62 0 //infernal troglodytes are immune to blind
|
+ 71 SPELL_IMMUNITY 0 62 0 //infernal troglodytes are immune to blind
|
||||||
+ 72 RETURN_AFTER_STRIKE 0 0 0 //Harpies return after attack
|
+ 72 RETURN_AFTER_STRIKE 0 0 0 //Harpies return after attack
|
||||||
+ 73 BLOCKS_RETALIATION 0 0 0 //Harpy Hags
|
+ 73 BLOCKS_RETALIATION 0 0 0 //Harpy Hags
|
||||||
+ 73 RETURN_AFTER_STRIKE 0 0 0 //Harpy Hags return after attack
|
+ 73 RETURN_AFTER_STRIKE 0 0 0 //Harpy Hags return after attack
|
||||||
+ 76 SPELL_AFTER_ATTACK 0 70 2020 //medusas
|
+ 76 SPELL_AFTER_ATTACK 20 70 2000 //medusas
|
||||||
+ 77 SPELL_AFTER_ATTACK 0 70 2020 //medusa queens
|
+ 77 SPELL_AFTER_ATTACK 20 70 2000 //medusa queens
|
||||||
+ 78 SELF_MORALE 0 0 0 //minotaurs
|
+ 78 SELF_MORALE 0 0 0 //minotaurs
|
||||||
+ 79 SELF_MORALE 0 0 0 //minotaur kings
|
+ 79 SELF_MORALE 0 0 0 //minotaur kings
|
||||||
+ 81 SPELL_AFTER_ATTACK 0 74 20 //scorpicore
|
+ 81 SPELL_AFTER_ATTACK 20 74 0 //scorpicore
|
||||||
+ 82 LEVEL_SPELL_IMMUNITY 3 0 0 //red dragon's spell immunity
|
+ 82 LEVEL_SPELL_IMMUNITY 3 0 0 //red dragon's spell immunity
|
||||||
+ 82 TWO_HEX_ATTACK_BREATH 0 0 0 //Red Dragon has breath attack
|
+ 82 TWO_HEX_ATTACK_BREATH 0 0 0 //Red Dragon has breath attack
|
||||||
+ 82 DRAGON_NATURE 0 0 0 //red dragon is a dragon
|
+ 82 DRAGON_NATURE 0 0 0 //red dragon is a dragon
|
||||||
@ -112,16 +112,16 @@
|
|||||||
+ 83 DRAGON_NATURE 0 0 0 //black dragon is a dragon
|
+ 83 DRAGON_NATURE 0 0 0 //black dragon is a dragon
|
||||||
+ 87 ADDITIONAL_ATTACK 1 0 0 //wolf raider
|
+ 87 ADDITIONAL_ATTACK 1 0 0 //wolf raider
|
||||||
+ 91 SPELLCASTER 2 43 6 //ogre magi cast bloodlust
|
+ 91 SPELLCASTER 2 43 6 //ogre magi cast bloodlust
|
||||||
+ 93 SPELL_AFTER_ATTACK 0 77 20 //thunderbirds
|
+ 93 SPELL_AFTER_ATTACK 20 77 0 //thunderbirds
|
||||||
+ 96 ENEMY_DEFENCE_REDUCTION 40 0 0 //behemots
|
+ 96 ENEMY_DEFENCE_REDUCTION 40 0 0 //behemots
|
||||||
+ 97 ENEMY_DEFENCE_REDUCTION 80 0 0 //ancient behemots
|
+ 97 ENEMY_DEFENCE_REDUCTION 80 0 0 //ancient behemots
|
||||||
+ 103 DEATH_STARE 10 0 0 //mighty gorgons
|
+ 103 DEATH_STARE 10 0 0 //mighty gorgons
|
||||||
+ 104 SPELL_AFTER_ATTACK 0 78 100 //serpent fly
|
+ 104 SPELL_AFTER_ATTACK 100 78 0 //serpent fly
|
||||||
+ 105 SPELL_AFTER_ATTACK 0 45 100 //mighty gorgons
|
+ 105 SPELL_AFTER_ATTACK 100 45 0 //mighty gorgons
|
||||||
+ 105 SPELL_AFTER_ATTACK 0 78 100 //dragon fly
|
+ 105 SPELL_AFTER_ATTACK 100 78 0 //dragon fly
|
||||||
+ 106 SPELL_AFTER_ATTACK 0 70 20 //basilisks
|
+ 106 SPELL_AFTER_ATTACK 20 70 0 //basilisks
|
||||||
+ 107 SPELL_AFTER_ATTACK 0 70 20 //greater basilisks
|
+ 107 SPELL_AFTER_ATTACK 20 70 0 //greater basilisks
|
||||||
+ 109 SPELL_AFTER_ATTACK 0 71 20 //Wyvern Monarch
|
+ 109 SPELL_AFTER_ATTACK 20 71 0 //Wyvern Monarch
|
||||||
+ 110 ATTACKS_ALL_ADJACENT 0 0 0 //hydras
|
+ 110 ATTACKS_ALL_ADJACENT 0 0 0 //hydras
|
||||||
+ 110 BLOCKS_RETALIATION 0 0 0 //hydras
|
+ 110 BLOCKS_RETALIATION 0 0 0 //hydras
|
||||||
+ 111 ATTACKS_ALL_ADJACENT 0 0 0 //chaos hydras
|
+ 111 ATTACKS_ALL_ADJACENT 0 0 0 //chaos hydras
|
||||||
|
@ -70,15 +70,15 @@
|
|||||||
67 0 -1 X X X X
|
67 0 -1 X X X X
|
||||||
68 0 -1 X X X X
|
68 0 -1 X X X X
|
||||||
69 0 -1 X X X X
|
69 0 -1 X X X X
|
||||||
70 -1 -1 0 0 0 0
|
70 0 70 0 0 0 0
|
||||||
71 -1 -1 0 0 0 0
|
71 -1 67 0 0 0 0
|
||||||
72 -1 -1 0 0 0 0
|
72 0 68 0 0 0 0
|
||||||
73 -1 -1 0 0 0 0
|
73 -1 69 0 0 0 0
|
||||||
74 -1 -1 0 0 0 0
|
74 -1 70 0 0 0 0
|
||||||
75 -1 -1 0 0 0 0
|
75 -1 71 0 0 0 0
|
||||||
76 -1 -1 0 0 0 0
|
76 0 72 0 0 0 0
|
||||||
77 -1 38 0 0 0 0
|
77 -1 38 0 0 0 0
|
||||||
78 -1 41 0 0 0 0
|
78 -1 41 0 0 0 0
|
||||||
79 0 80 0 0 0 0
|
79 0 80 0 0 0 0
|
||||||
80 -1 -1 0 0 0 0
|
80 0 81 0 0 0 0
|
||||||
-1
|
-1
|
12
config/spell_levels.txt
Normal file
12
config/spell_levels.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
70 3
|
||||||
|
71 2
|
||||||
|
72 255
|
||||||
|
73 2
|
||||||
|
74 4
|
||||||
|
75 5
|
||||||
|
76 255
|
||||||
|
77 2
|
||||||
|
78 1
|
||||||
|
79 255
|
||||||
|
80 255
|
||||||
|
-1
|
@ -1792,8 +1792,7 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id) ||
|
if(subject->hasBonusOfType(Bonus::SPELL_IMMUNITY, spell->id) ||
|
||||||
( immunities.size() > 0 && immunities.totalValue() >= spell->level)
|
( immunities.size() > 0 && immunities.totalValue() >= spell->level)) //many creature abilities have level equal to 0 by default, fixed in config\spell_levels
|
||||||
&& spell->level) //many creature abilities have level equal to 0, may cause bugs
|
|
||||||
{
|
{
|
||||||
return SpellCasting::STACK_IMMUNE_TO_SPELL;
|
return SpellCasting::STACK_IMMUNE_TO_SPELL;
|
||||||
}
|
}
|
||||||
@ -2140,6 +2139,34 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
|
|||||||
sf.push_back(makeFeatureVal(Bonus::GENERAL_ATTACK_REDUCTION, Bonus::UNTIL_ATTACK | Bonus::N_TURNS, 0, power, Bonus::SPELL_EFFECT, sse.turnsRemain));
|
sf.push_back(makeFeatureVal(Bonus::GENERAL_ATTACK_REDUCTION, Bonus::UNTIL_ATTACK | Bonus::N_TURNS, 0, power, Bonus::SPELL_EFFECT, sse.turnsRemain));
|
||||||
sf.back().sid = sse.sid;
|
sf.back().sid = sse.sid;
|
||||||
break;
|
break;
|
||||||
|
case 70: //Stone Gaze
|
||||||
|
case 74: //Paralyze
|
||||||
|
sf.push_back(makeFeatureVal(Bonus::NOT_ACTIVE, Bonus::UNITL_BEING_ATTACKED | Bonus::N_TURNS, 0, 0, Bonus::SPELL_EFFECT, sse.turnsRemain));
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
break;
|
||||||
|
case 71: //Poison
|
||||||
|
sf.push_back(featureGeneratorVT(Bonus::POISON, 0, 30, 3, Bonus::INDEPENDENT_MAX)); //max hp penalty from this source
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -10, 3, Bonus::PERCENT_TO_ALL));
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
break;
|
||||||
|
case 72: //Bind
|
||||||
|
sf.push_back(featureGeneratorVT(Bonus::STACKS_SPEED, 0, -100, 1, Bonus::PERCENT_TO_ALL)); //sets speed to zero
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
sf.push_back(featureGenerator(Bonus::BIND_EFFECT, 0, 0, 0)); //marker, TODO: handle it
|
||||||
|
sf.back().duration = Bonus::PERMANENT;
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
break;
|
||||||
|
case 73: //Disease
|
||||||
|
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, -2 ,3));
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -2 ,3));
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
break;
|
||||||
|
case 75: //Age
|
||||||
|
sf.push_back(featureGeneratorVT(Bonus::STACK_HEALTH, 0, -50, 3, Bonus::PERCENT_TO_ALL));
|
||||||
|
sf.back().sid = sse.sid;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,7 +956,7 @@ void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, std::string & src
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
//case 'c': //some special abilities are threated as spells, will cause bugs
|
case 'c': //some special abilities are threated as spells, work in progress
|
||||||
b.type = Bonus::SPELL_AFTER_ATTACK;
|
b.type = Bonus::SPELL_AFTER_ATTACK;
|
||||||
b.subtype = stringToNumber(mod);
|
b.subtype = stringToNumber(mod);
|
||||||
break;
|
break;
|
||||||
|
@ -583,9 +583,11 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const
|
|||||||
boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl);
|
boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl);
|
||||||
break;
|
break;
|
||||||
case Bonus::SPELL_AFTER_ATTACK:
|
case Bonus::SPELL_AFTER_ATTACK:
|
||||||
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bonus->additionalInfo % 1000));
|
{
|
||||||
|
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(valOfBonuses(Selector::typeSybtype(bonus->type, bonus->subtype))));
|
||||||
boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name);
|
boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{}//TODO: allow custom bonus types... someday, somehow
|
{}//TODO: allow custom bonus types... someday, somehow
|
||||||
}
|
}
|
||||||
|
@ -321,4 +321,24 @@ void CSpellHandler::loadSpells()
|
|||||||
ast>>spellID;
|
ast>>spellID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast.close();
|
||||||
|
ast.open(DATA_DIR "/config/spell_levels.txt", std::ios::binary);
|
||||||
|
if(!ast.is_open())
|
||||||
|
{
|
||||||
|
tlog1<<"lack of config/spell_levels.txt file!"<<std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//custom levels of spells. Level 0 seems to not be supported correctly, but we can replace it it something else
|
||||||
|
int spellID;
|
||||||
|
ast>>spellID;
|
||||||
|
int buf;
|
||||||
|
while(spellID != -1)
|
||||||
|
{
|
||||||
|
ast >> buf;
|
||||||
|
spells[spellID]->level = buf;
|
||||||
|
ast>>spellID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast.close();
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ namespace PrimarySkill
|
|||||||
BONUS_NAME(MAGIC_RESISTANCE) /*in % (value)*/ \
|
BONUS_NAME(MAGIC_RESISTANCE) /*in % (value)*/ \
|
||||||
BONUS_NAME(CHANGES_SPELL_COST_FOR_ALLY) /*in mana points (value) , eg. mage*/ \
|
BONUS_NAME(CHANGES_SPELL_COST_FOR_ALLY) /*in mana points (value) , eg. mage*/ \
|
||||||
BONUS_NAME(CHANGES_SPELL_COST_FOR_ENEMY) /*in mana points (value) , eg. pegasus */ \
|
BONUS_NAME(CHANGES_SPELL_COST_FOR_ENEMY) /*in mana points (value) , eg. pegasus */ \
|
||||||
BONUS_NAME(SPELL_AFTER_ATTACK) /* subtype - spell id, value - spell level, (additional info)%1000 - chance in %; eg. dendroids, (additional info)/1000 -> [0 - all attacks, 1 - shot only, 2 - melee only*/ \
|
BONUS_NAME(SPELL_AFTER_ATTACK) /* subtype - spell id, value - chance %, additional info % 1000 - level, (additional info)/1000 -> [0 - all attacks, 1 - shot only, 2 - melee only*/ \
|
||||||
BONUS_NAME(SPELL_RESISTANCE_AURA) /*eg. unicorns, value - resistance bonus in % for adjacent creatures*/ \
|
BONUS_NAME(SPELL_RESISTANCE_AURA) /*eg. unicorns, value - resistance bonus in % for adjacent creatures*/ \
|
||||||
BONUS_NAME(LEVEL_SPELL_IMMUNITY) /*creature is immune to all spell with level below or equal to value of this bonus*/ \
|
BONUS_NAME(LEVEL_SPELL_IMMUNITY) /*creature is immune to all spell with level below or equal to value of this bonus*/ \
|
||||||
BONUS_NAME(TWO_HEX_ATTACK_BREATH) /*eg. dragons*/ \
|
BONUS_NAME(TWO_HEX_ATTACK_BREATH) /*eg. dragons*/ \
|
||||||
@ -157,7 +157,9 @@ namespace PrimarySkill
|
|||||||
BONUS_NAME(CREATURE_DAMAGE)/*subtype 0 = both, 1 = min, 2 = max*/\
|
BONUS_NAME(CREATURE_DAMAGE)/*subtype 0 = both, 1 = min, 2 = max*/\
|
||||||
BONUS_NAME(EXP_MULTIPLIER)/* val - percent of additional exp gained by stack/commander (base value 100)*/\
|
BONUS_NAME(EXP_MULTIPLIER)/* val - percent of additional exp gained by stack/commander (base value 100)*/\
|
||||||
BONUS_NAME(SHOTS)\
|
BONUS_NAME(SHOTS)\
|
||||||
BONUS_NAME(DEATH_STARE) /*subtype 0 - gorgon, 1 - commander*/
|
BONUS_NAME(DEATH_STARE) /*subtype 0 - gorgon, 1 - commander*/\
|
||||||
|
BONUS_NAME(POISON) /*val - max health penalty from poison possible*/\
|
||||||
|
BONUS_NAME(BIND_EFFECT) /*doesn't do anything particular, works as a marker)*/
|
||||||
|
|
||||||
/// Struct for handling bonuses of several types. Can be transfered to any hero
|
/// Struct for handling bonuses of several types. Can be transfered to any hero
|
||||||
struct DLL_EXPORT Bonus
|
struct DLL_EXPORT Bonus
|
||||||
@ -185,7 +187,7 @@ struct DLL_EXPORT Bonus
|
|||||||
ARTIFACT,
|
ARTIFACT,
|
||||||
ARTIFACT_INSTANCE,
|
ARTIFACT_INSTANCE,
|
||||||
OBJECT,
|
OBJECT,
|
||||||
CREATURE_ABILITY,
|
CREATURE_ABILITY,
|
||||||
TERRAIN_NATIVE,
|
TERRAIN_NATIVE,
|
||||||
TERRAIN_OVERLAY,
|
TERRAIN_OVERLAY,
|
||||||
SPELL_EFFECT,
|
SPELL_EFFECT,
|
||||||
|
@ -874,13 +874,7 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs )
|
|||||||
s->state -= MOVED;
|
s->state -= MOVED;
|
||||||
s->state -= HAD_MORALE;
|
s->state -= HAD_MORALE;
|
||||||
s->counterAttacks = 1 + s->valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
s->counterAttacks = 1 + s->valOfBonuses(Bonus::ADDITIONAL_RETALIATION);
|
||||||
|
// new turn effects
|
||||||
//regeneration
|
|
||||||
if( s->hasBonusOfType(Bonus::HP_REGENERATION) && s->alive() )
|
|
||||||
s->firstHPleft = std::min<ui32>( s->MaxHealth(), s->valOfBonuses(Bonus::HP_REGENERATION) );
|
|
||||||
if( s->hasBonusOfType(Bonus::FULL_HP_REGENERATION) && s->alive() )
|
|
||||||
s->firstHPleft = s->MaxHealth();
|
|
||||||
|
|
||||||
s->battleTurnPassed();
|
s->battleTurnPassed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -890,6 +884,34 @@ DLL_EXPORT void BattleSetActiveStack::applyGs( CGameState *gs )
|
|||||||
gs->curB->activeStack = stack;
|
gs->curB->activeStack = stack;
|
||||||
CStack *st = gs->curB->getStack(stack);
|
CStack *st = gs->curB->getStack(stack);
|
||||||
|
|
||||||
|
if (st->alive())
|
||||||
|
{
|
||||||
|
//regeneration
|
||||||
|
if(st->hasBonusOfType(Bonus::HP_REGENERATION))
|
||||||
|
st->firstHPleft = std::min<ui32>( st->MaxHealth(), st->valOfBonuses(Bonus::HP_REGENERATION) );
|
||||||
|
if(st->hasBonusOfType(Bonus::FULL_HP_REGENERATION))
|
||||||
|
st->firstHPleft = st->MaxHealth();
|
||||||
|
if(st->hasBonusOfType(Bonus::POISON))
|
||||||
|
{
|
||||||
|
Bonus * b = st->getBonus(Selector::source(Bonus::SPELL_EFFECT, 71) && Selector::type(Bonus::STACK_HEALTH));
|
||||||
|
if (b) //TODO: what if not?...
|
||||||
|
{
|
||||||
|
b->val -= 10;
|
||||||
|
amax (b->val, -(st->valOfBonuses(Bonus::POISON)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(st->hasBonusOfType(Bonus::MANA_DRAIN))
|
||||||
|
{
|
||||||
|
const CGHeroInstance * enemy = gs->curB->getHero(gs->curB->theOtherPlayer(st->owner));
|
||||||
|
if (enemy)
|
||||||
|
{
|
||||||
|
ui32 manaDrained = st->valOfBonuses(Bonus::MANA_DRAIN);
|
||||||
|
amin (manaDrained, gs->curB->heroes[0]->mana);
|
||||||
|
gs->getHero(enemy->id)->mana -= manaDrained; //jeez, it's overcomplicate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//remove bonuses that last until when stack gets new turn
|
//remove bonuses that last until when stack gets new turn
|
||||||
st->bonuses.remove_if(Bonus::UntilGetsTurn);
|
st->bonuses.remove_if(Bonus::UntilGetsTurn);
|
||||||
|
|
||||||
@ -1135,14 +1157,14 @@ void actualizeEffect(CStack * s, const Bonus & ef)
|
|||||||
|
|
||||||
DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
|
DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
int id = effect.begin()->sid; //effects' source ID
|
int spellid = effect.begin()->sid; //effects' source ID
|
||||||
|
|
||||||
BOOST_FOREACH(ui32 id, stacks)
|
BOOST_FOREACH(ui32 id, stacks)
|
||||||
{
|
{
|
||||||
CStack *s = gs->curB->getStack(id);
|
CStack *s = gs->curB->getStack(id);
|
||||||
if(s)
|
if(s)
|
||||||
{
|
{
|
||||||
if(id == 47 || !s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, id)))//disrupting ray or not on the list - just add
|
if(spellid == 47 || spellid == 80 || !s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, spellid)))//disrupting ray or acid breath or not on the list - just add
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(Bonus &fromEffect, effect)
|
BOOST_FOREACH(Bonus &fromEffect, effect)
|
||||||
{
|
{
|
||||||
@ -1163,7 +1185,7 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
|
|||||||
CStack *s = gs->curB->getStack(para.first);
|
CStack *s = gs->curB->getStack(para.first);
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
if (!s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, id) && Selector::typeSybtype(para.second.type, para.second.subtype)))
|
if (!s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, spellid) && Selector::typeSybtype(para.second.type, para.second.subtype)))
|
||||||
s->addNewBonus(new Bonus(para.second));
|
s->addNewBonus(new Bonus(para.second));
|
||||||
else
|
else
|
||||||
actualizeEffect(s, effect);
|
actualizeEffect(s, effect);
|
||||||
|
@ -3077,6 +3077,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
bat.flags |= BattleAttack::SHOT;
|
bat.flags |= BattleAttack::SHOT;
|
||||||
prepareAttack(bat, curStack, destStack, 0);
|
prepareAttack(bat, curStack, destStack, 0);
|
||||||
sendAndApply(&bat);
|
sendAndApply(&bat);
|
||||||
|
handleAfterAttackCasting(bat);
|
||||||
|
|
||||||
//ballista & artillery handling
|
//ballista & artillery handling
|
||||||
if(destStack->alive() && curStack->getCreature()->idNumber == 146)
|
if(destStack->alive() && curStack->getCreature()->idNumber == 146)
|
||||||
@ -3203,7 +3204,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
|||||||
sendAndApply(&EndAction());
|
sendAndApply(&EndAction());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BattleAction::STACK_HEAL: //healing
|
case BattleAction::STACK_HEAL: //healing with First Aid Tent
|
||||||
{
|
{
|
||||||
sendAndApply(&StartAction(ba));
|
sendAndApply(&StartAction(ba));
|
||||||
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
const CGHeroInstance * attackingHero = gs->curB->heroes[ba.side];
|
||||||
@ -3404,14 +3405,12 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
continue;
|
continue;
|
||||||
sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
sc.dmgToDisplay += gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
|
||||||
}
|
}
|
||||||
if (spellID = 79) // Death stare
|
if (spellID == 79) // Death stare
|
||||||
{
|
{
|
||||||
sc.dmgToDisplay = usedSpellPower;
|
sc.dmgToDisplay = usedSpellPower;
|
||||||
amin(sc.dmgToDisplay, (*attackedCres.begin())->count); // hopefully stack is already reduced after attack
|
amin(sc.dmgToDisplay, (*attackedCres.begin())->count); //stack is already reduced after attack
|
||||||
}
|
}
|
||||||
|
|
||||||
sendAndApply(&sc);
|
|
||||||
|
|
||||||
//applying effects
|
//applying effects
|
||||||
switch(spellID)
|
switch(spellID)
|
||||||
{
|
{
|
||||||
@ -3477,6 +3476,12 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
case 60: //hypnotize
|
case 60: //hypnotize
|
||||||
case 61: //forgetfulness
|
case 61: //forgetfulness
|
||||||
case 62: //blind
|
case 62: //blind
|
||||||
|
case 70: //Stone Gaze
|
||||||
|
case 71: //Poison
|
||||||
|
case 72: //Bind
|
||||||
|
case 73: //Disease
|
||||||
|
case 74: //Paralyze
|
||||||
|
case 75: //Aging
|
||||||
{
|
{
|
||||||
SetStackEffect sse;
|
SetStackEffect sse;
|
||||||
Bonus pseudoBonus;
|
Bonus pseudoBonus;
|
||||||
@ -3484,8 +3489,10 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
pseudoBonus.val = spellLvl;
|
pseudoBonus.val = spellLvl;
|
||||||
pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower);
|
pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower);
|
||||||
CStack::stackEffectToFeature(sse.effect, pseudoBonus);
|
CStack::stackEffectToFeature(sse.effect, pseudoBonus);
|
||||||
|
const Bonus * bonus = NULL;
|
||||||
|
if (caster)
|
||||||
|
bonus = caster->getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, spellID));
|
||||||
|
|
||||||
const Bonus * bonus = caster->getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, spellID));
|
|
||||||
si32 power;
|
si32 power;
|
||||||
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
||||||
{
|
{
|
||||||
@ -3528,7 +3535,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages
|
if (caster && caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages
|
||||||
{
|
{
|
||||||
int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / tier;
|
int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / tier;
|
||||||
Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain);
|
Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain);
|
||||||
@ -3593,17 +3600,21 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case 79: //Death stare - handled in a bit different way
|
case 79: //Death stare - handled in a bit different way
|
||||||
{
|
{
|
||||||
StacksInjured si;
|
StacksInjured si;
|
||||||
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
||||||
{
|
{
|
||||||
if((*it)->hasBonusOfType (Bonus::UNDEAD) || (*it)->hasBonusOfType (Bonus::NON_LIVING)) //this creature is immune
|
if((*it)->hasBonusOfType(Bonus::UNDEAD) || (*it)->hasBonusOfType(Bonus::NON_LIVING)) //this creature is immune
|
||||||
|
{
|
||||||
|
sc.dmgToDisplay = 0; //TODO: handle Death Stare for multiple targets (?)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
BattleStackAttacked bsa;
|
BattleStackAttacked bsa;
|
||||||
bsa.flags |= BattleStackAttacked::EFFECT;
|
bsa.flags |= BattleStackAttacked::EFFECT;
|
||||||
bsa.effect = spell->mainEffectAnim; //TODO: find which it is
|
bsa.effect = spell->mainEffectAnim; //from config\spell-Info.txt
|
||||||
bsa.damageAmount = usedSpellPower * (*it)->valOfBonuses(Bonus::STACK_HEALTH);
|
bsa.damageAmount = usedSpellPower * (*it)->valOfBonuses(Bonus::STACK_HEALTH);
|
||||||
bsa.stackAttacked = (*it)->ID;
|
bsa.stackAttacked = (*it)->ID;
|
||||||
bsa.attackerID = -1;
|
bsa.attackerID = -1;
|
||||||
@ -3616,6 +3627,8 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendAndApply(&sc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CGameHandler::makeCustomAction( BattleAction &ba )
|
bool CGameHandler::makeCustomAction( BattleAction &ba )
|
||||||
@ -4203,40 +4216,50 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
|||||||
const CStack * attacker = gs->curB->getStack(bat.stackAttacking);
|
const CStack * attacker = gs->curB->getStack(bat.stackAttacking);
|
||||||
if( attacker->hasBonusOfType(Bonus::SPELL_AFTER_ATTACK) )
|
if( attacker->hasBonusOfType(Bonus::SPELL_AFTER_ATTACK) )
|
||||||
{
|
{
|
||||||
|
std::set<ui32> spellsToCast;
|
||||||
BOOST_FOREACH(const Bonus *sf, attacker->getBonuses(Selector::type(Bonus::SPELL_AFTER_ATTACK)))
|
BOOST_FOREACH(const Bonus *sf, attacker->getBonuses(Selector::type(Bonus::SPELL_AFTER_ATTACK)))
|
||||||
{
|
{
|
||||||
if (sf->type == Bonus::SPELL_AFTER_ATTACK)
|
spellsToCast.insert (sf->subtype);
|
||||||
|
}
|
||||||
|
BOOST_FOREACH(ui32 spellID, spellsToCast)
|
||||||
|
{
|
||||||
|
const CStack * oneOfAttacked = NULL;
|
||||||
|
for(int g=0; g<bat.bsa.size(); ++g)
|
||||||
{
|
{
|
||||||
const CStack * oneOfAttacked = NULL;
|
if (bat.bsa[g].newAmount > 0)
|
||||||
for(int g=0; g<bat.bsa.size(); ++g)
|
|
||||||
{
|
{
|
||||||
if (bat.bsa[g].newAmount > 0)
|
oneOfAttacked = gs->curB->getStack(bat.bsa[g].stackAttacked);
|
||||||
{
|
break;
|
||||||
oneOfAttacked = gs->curB->getStack(bat.bsa[g].stackAttacked);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(oneOfAttacked == NULL) //all attacked creatures have been killed
|
|
||||||
return;
|
|
||||||
|
|
||||||
int spellID = sf->subtype;
|
|
||||||
int spellLevel = sf->val;
|
|
||||||
int chance = sf->additionalInfo % 1000;
|
|
||||||
//int meleeRanged = sf->additionalInfo / 1000;
|
|
||||||
int destination = oneOfAttacked->position;
|
|
||||||
|
|
||||||
const CSpell * spell = VLC->spellh->spells[spellID];
|
|
||||||
if(gs->curB->battleCanCastThisSpellHere(attacker->owner, spell, SpellCasting::AFTER_ATTACK_CASTING, oneOfAttacked->position)
|
|
||||||
!= SpellCasting::OK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//check if spell should be casted (probability handling)
|
|
||||||
if( rand()%100 >= chance )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//casting
|
|
||||||
handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL, attacker->count, SpellCasting::AFTER_ATTACK_CASTING);
|
|
||||||
}
|
}
|
||||||
|
bool castMe = false;
|
||||||
|
int meleeRanged;
|
||||||
|
if(oneOfAttacked == NULL) //all attacked creatures have been killed
|
||||||
|
return;
|
||||||
|
int spellLevel = 0;
|
||||||
|
BOOST_FOREACH(const Bonus *sf, attacker->getBonuses(Selector::typeSybtype(Bonus::SPELL_AFTER_ATTACK, spellID)))
|
||||||
|
{
|
||||||
|
amax(spellLevel, sf->additionalInfo % 1000); //pick highest level
|
||||||
|
meleeRanged = sf->additionalInfo / 1000;
|
||||||
|
if (meleeRanged == 0 || (meleeRanged == 1 && bat.shot()) || (meleeRanged == 2 && !bat.shot()))
|
||||||
|
castMe = true;
|
||||||
|
}
|
||||||
|
int chance = attacker->valOfBonuses((Selector::typeSybtype(Bonus::SPELL_AFTER_ATTACK, spellID)));
|
||||||
|
amin (chance, 100);
|
||||||
|
int destination = oneOfAttacked->position;
|
||||||
|
|
||||||
|
const CSpell * spell = VLC->spellh->spells[spellID];
|
||||||
|
if(gs->curB->battleCanCastThisSpellHere(attacker->owner, spell, SpellCasting::AFTER_ATTACK_CASTING, oneOfAttacked->position)
|
||||||
|
!= SpellCasting::OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//check if spell should be casted (probability handling)
|
||||||
|
if(rand()%100 >= chance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//casting
|
||||||
|
if (castMe)
|
||||||
|
handleSpellCasting(spellID, spellLevel, destination, !attacker->attackerOwned, attacker->owner, NULL, NULL, attacker->count, SpellCasting::AFTER_ATTACK_CASTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (attacker->hasBonusOfType(Bonus::DEATH_STARE)) // spell id 79
|
if (attacker->hasBonusOfType(Bonus::DEATH_STARE)) // spell id 79
|
||||||
|
Loading…
Reference in New Issue
Block a user