浏览代码

* 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)

mateuszb 16 年之前
父节点
当前提交
27dda485a4
共有 5 个文件被更改,包括 67 次插入8 次删除
  1. 7 0
      client/CBattleInterface.cpp
  2. 3 0
      lib/CGameState.cpp
  3. 2 1
      lib/NetPacks.h
  4. 2 1
      lib/NetPacksLib.cpp
  5. 53 6
      server/CGameHandler.cpp

+ 7 - 0
client/CBattleInterface.cpp

@@ -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)

+ 3 - 0
lib/CGameState.cpp

@@ -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);

+ 2 - 1
lib/NetPacks.h

@@ -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;
 	}
 	}
 };
 };
 
 

+ 2 - 1
lib/NetPacksLib.cpp

@@ -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

+ 53 - 6
server/CGameHandler.cpp

@@ -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;
 				}
 				}
 			}
 			}