소스 검색

* 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
 		displayEffect(spell.mainEffectAnim, sc->tile);
 	} //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)

+ 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
 {
+	if(hasFeatureOfType(StackFeature::SIEGE_WEAPON)) //war machnes cannot move
+		return 0;
+
 	int speed = creature->speed;
 
 	speed += valOfFeatures(StackFeature::SPEED_BONUS);

+ 2 - 1
lib/NetPacks.h

@@ -886,9 +886,10 @@ struct SpellCast : public CPackForClient//3009
 	ui32 id;
 	ui8 skill;
 	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)
 	{
-		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]++;
 	}
+
 	if(gs->curB && id == 35) //dispel
 	{
 		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
 			//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;
 }
 
+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 )
 {
 	switch(ba.actionType)
@@ -2640,18 +2675,20 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 
 			sendAndApply(&StartAction(ba)); //start spell casting
 
-			//TODO: check resistances
-
 			SpellCast sc;
 			sc.side = ba.side;
 			sc.id = ba.additionalInfo;
 			sc.skill = skill;
 			sc.tile = ba.destinationTile;
-			sendAndApply(&sc);
 
 			//calculating affected creatures for all spells
 			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
 			switch(ba.additionalInfo) //spell id
 			{
@@ -2670,6 +2707,9 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 					StacksInjured si;
 					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;
 						bsa.flags |= 2;
 						bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim;
@@ -2678,7 +2718,8 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 						prepareAttacked(bsa,*it);
 						si.stacks.insert(bsa);
 					}
-					sendAndApply(&si);
+					if(!si.stacks.empty())
+						sendAndApply(&si);
 					break;
 				}
 			case 27: //shield 
@@ -2707,12 +2748,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 					SetStackEffect sse;
 					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.effect.id = ba.additionalInfo;
 					sse.effect.level = h->getSpellSchoolLevel(s);
 					sse.effect.turnsRemain = h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION);
-					sendAndApply(&sse);
+					if(!sse.stacks.empty())
+						sendAndApply(&sse);
 					break;
 				}
 			case 56: //frenzy
@@ -2720,12 +2764,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 					SetStackEffect sse;
 					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.effect.id = ba.additionalInfo;
 					sse.effect.level = h->getSpellSchoolLevel(s);
 					sse.effect.turnsRemain = 1;
-					sendAndApply(&sse);
+					if(!sse.stacks.empty())
+						sendAndApply(&sse);
 					break;
 				}
 			}