1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-29 23:07:48 +02:00

* support for spell resistance, including secondary skill (resistance) and new artifacts (Garniture of Interference, Surcoat of Counterpoise, Boots of Polarity) and unit's resistance (such as dwarfs' resistance)

This commit is contained in:
mateuszb
2009-07-26 12:15:38 +00:00
parent 0d408bc6c2
commit 27dda485a4
5 changed files with 67 additions and 8 deletions

View File

@@ -1870,6 +1870,13 @@ void CBattleInterface::spellCast(SpellCast * sc)
case 35: //dispel case 35: //dispel
displayEffect(spell.mainEffectAnim, sc->tile); displayEffect(spell.mainEffectAnim, sc->tile);
} //switch(sc->id) } //switch(sc->id)
//support for resistance
for(int j=0; j<sc->resisted.size(); ++j)
{
int tile = LOCPLINT->cb->battleGetStackByID(sc->resisted[j])->position;
displayEffect(78, tile);
}
} }
void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse) void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)

View File

@@ -519,6 +519,9 @@ CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S)
ui32 CStack::Speed() const ui32 CStack::Speed() const
{ {
if(hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //war machnes cannot move
return 0;
int speed = creature->speed; int speed = creature->speed;
speed += valOfFeatures(StackFeature::SPEED_BONUS); speed += valOfFeatures(StackFeature::SPEED_BONUS);

View File

@@ -886,9 +886,10 @@ struct SpellCast : public CPackForClient//3009
ui32 id; ui32 id;
ui8 skill; ui8 skill;
ui16 tile; //destination tile (may not be set in some global/mass spells ui16 tile; //destination tile (may not be set in some global/mass spells
std::vector<ui32> resisted; //ids of creatures that resisted this spell
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & side & id & skill & tile; h & side & id & skill & tile & resisted;
} }
}; };

View File

@@ -692,10 +692,11 @@ DLL_EXPORT void SpellCast::applyGs( CGameState *gs )
{ {
gs->curB->castSpells[side]++; gs->curB->castSpells[side]++;
} }
if(gs->curB && id == 35) //dispel if(gs->curB && id == 35) //dispel
{ {
CStack *s = gs->curB->getStackT(tile); CStack *s = gs->curB->getStackT(tile);
if(s) if(s && !vstd::contains(resisted, s->ID)) //if stack exists and it didn't resist
{ {
s->effects.clear(); //removing all effects s->effects.clear(); //removing all effects
//removing all features from spells //removing all features from spells

View File

@@ -2604,6 +2604,41 @@ static ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster,
return ret; return ret;
} }
static std::vector<ui32> calculateResistedStacks(const CSpell * sp, const CGHeroInstance * caster, const std::set<CStack*> affectedCreatures)
{
std::vector<ui32> ret;
for(std::set<CStack*>::const_iterator it = affectedCreatures.begin(); it != affectedCreatures.end(); ++it)
{
//non-negative spells on friendly stacks should always succeed
if(sp->positiveness >= 0 && (*it)->owner == caster->tempOwner)
continue;
int prob = (*it)->valOfFeatures(StackFeature::MAGIC_RESISTANCE); //probability of resistance in %
//caster's resistance support (secondary skils and artifacts)
prob += caster->valOfBonuses(HeroBonus::MAGIC_RESISTANCE);
switch(caster->getSecSkillLevel(26)) //resistance
{
case 1: //basic
prob += 5;
break;
case 2: //advanced
prob += 10;
break;
case 3: //expert
prob += 20;
break;
}
if(prob > 100) prob = 100;
if(rand()%100 < prob)
ret.push_back((*it)->ID);
}
return ret;
}
bool CGameHandler::makeCustomAction( BattleAction &ba ) bool CGameHandler::makeCustomAction( BattleAction &ba )
{ {
switch(ba.actionType) switch(ba.actionType)
@@ -2640,18 +2675,20 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
sendAndApply(&StartAction(ba)); //start spell casting sendAndApply(&StartAction(ba)); //start spell casting
//TODO: check resistances
SpellCast sc; SpellCast sc;
sc.side = ba.side; sc.side = ba.side;
sc.id = ba.additionalInfo; sc.id = ba.additionalInfo;
sc.skill = skill; sc.skill = skill;
sc.tile = ba.destinationTile; sc.tile = ba.destinationTile;
sendAndApply(&sc);
//calculating affected creatures for all spells //calculating affected creatures for all spells
std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(s, h, ba.destinationTile); std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(s, h, ba.destinationTile);
//checking if creatures resist
sc.resisted = calculateResistedStacks(s, h, attackedCres);
sendAndApply(&sc);
//applying effects //applying effects
switch(ba.additionalInfo) //spell id switch(ba.additionalInfo) //spell id
{ {
@@ -2670,6 +2707,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
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(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
continue;
BattleStackAttacked bsa; BattleStackAttacked bsa;
bsa.flags |= 2; bsa.flags |= 2;
bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim; bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim;
@@ -2678,7 +2718,8 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
prepareAttacked(bsa,*it); prepareAttacked(bsa,*it);
si.stacks.insert(bsa); si.stacks.insert(bsa);
} }
sendAndApply(&si); if(!si.stacks.empty())
sendAndApply(&si);
break; break;
} }
case 27: //shield case 27: //shield
@@ -2707,12 +2748,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
SetStackEffect sse; SetStackEffect sse;
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(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
continue;
sse.stacks.insert((*it)->ID); sse.stacks.insert((*it)->ID);
} }
sse.effect.id = ba.additionalInfo; sse.effect.id = ba.additionalInfo;
sse.effect.level = h->getSpellSchoolLevel(s); sse.effect.level = h->getSpellSchoolLevel(s);
sse.effect.turnsRemain = h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION); sse.effect.turnsRemain = h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION);
sendAndApply(&sse); if(!sse.stacks.empty())
sendAndApply(&sse);
break; break;
} }
case 56: //frenzy case 56: //frenzy
@@ -2720,12 +2764,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
SetStackEffect sse; SetStackEffect sse;
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(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
continue;
sse.stacks.insert((*it)->ID); sse.stacks.insert((*it)->ID);
} }
sse.effect.id = ba.additionalInfo; sse.effect.id = ba.additionalInfo;
sse.effect.level = h->getSpellSchoolLevel(s); sse.effect.level = h->getSpellSchoolLevel(s);
sse.effect.turnsRemain = 1; sse.effect.turnsRemain = 1;
sendAndApply(&sse); if(!sse.stacks.empty())
sendAndApply(&sse);
break; break;
} }
} }