Explorar o código

* new spell (disrupting ray)
* a few code cleanups

mateuszb %!s(int64=16) %!d(string=hai) anos
pai
achega
35f63bdc5f
Modificáronse 5 ficheiros con 106 adicións e 94 borrados
  1. 4 1
      CBattleInterface.cpp
  2. 24 8
      CGameState.cpp
  3. 1 0
      CGameState.h
  4. 9 8
      lib/NetPacksLib.cpp
  5. 68 77
      server/CGameHandler.cpp

+ 4 - 1
CBattleInterface.cpp

@@ -273,6 +273,7 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
 	spellToEffect[43] = 4; //bloodlust
 	spellToEffect[45] = 56; //weakness
 	spellToEffect[46] = 54; //stone skin
+	spellToEffect[47] = 14; //disrupting ray
 	spellToEffect[48] = 0; //prayer
 	spellToEffect[49] = 20; //mirth
 	spellToEffect[50] = 30; //sorrow
@@ -1862,7 +1863,9 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
 			SDL_SetClipRect(screen, &buf); //restoring previous clip rect
 			break; //for 15 and 16 cases
 		}
-	}
+	case 35: //dispel
+		displayEffect(spellToEffect[sc->id], sc->tile);
+	} //switch(sc->id)
 }
 
 void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)

+ 24 - 8
CGameState.cpp

@@ -486,6 +486,17 @@ const CStack::StackEffect * CStack::getEffect(ui16 id) const
 	return NULL;
 }
 
+ui8 CStack::howManyEffectsSet(ui16 id) const
+{
+	ui8 ret = 0;
+	for (int i=0; i< effects.size(); i++)
+		if(effects[i].id == id) //effect found
+		{
+			++ret;
+		}
+	return ret;
+}
+
 si8 CStack::Morale() const
 {
 	si8 ret = morale;
@@ -1697,7 +1708,7 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
 	//calculating total attack/defense skills modifier
 	if(attacker->getEffect(56)) //frenzy for attacker
 	{
-		attackerAttackBonus += (VLC->spellh->spells[attacker->getEffect(56)->id].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0));
+		attackerAttackBonus += (VLC->spellh->spells[56].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0));
 	}
 	if(defender->getEffect(56)) //frenzy for defender
 	{
@@ -1706,23 +1717,28 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
 	attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus;
 	if(defender->getEffect(48)) //defender's prayer handling
 	{
-		attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(48)->id].powers[defender->getEffect(48)->level];
+		attackDefenseBonus -= VLC->spellh->spells[48].powers[defender->getEffect(48)->level];
 	}
 	if(attacker->getEffect(48)) //attacker's prayer handling
 	{
-		attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(48)->id].powers[attacker->getEffect(48)->level];
+		attackDefenseBonus += VLC->spellh->spells[48].powers[attacker->getEffect(48)->level];
+	}
+	if(defender->getEffect(47)) //defender's disrupting ray handling
+	{
+		int howMany = defender->howManyEffectsSet(47);
+		attackDefenseBonus +=  VLC->spellh->spells[47].powers[attacker->getEffect(47)->level] * howMany;
 	}
 	if(defender->getEffect(46)) //stone skin handling
 	{
-		attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(46)->id].powers[defender->getEffect(46)->level];
+		attackDefenseBonus -= VLC->spellh->spells[46].powers[defender->getEffect(46)->level];
 	}
 	if(attacker->getEffect(45)) //weakness handling
 	{
-		attackDefenseBonus -= VLC->spellh->spells[attacker->getEffect(45)->id].powers[attacker->getEffect(45)->level];
+		attackDefenseBonus -= VLC->spellh->spells[45].powers[attacker->getEffect(45)->level];
 	}
 	if(!shooting && attacker->getEffect(43)) //bloodlust handling
 	{
-		attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(43)->id].powers[attacker->getEffect(43)->level];
+		attackDefenseBonus += VLC->spellh->spells[43].powers[attacker->getEffect(43)->level];
 	}
 
 	float dmgBonusMultiplier = 1.0f;
@@ -1828,12 +1844,12 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con
 
 	if(attacker->getEffect(42)) //curse handling (rest)
 	{
-		minDmg -= VLC->spellh->spells[attacker->getEffect(42)->id].powers[attacker->getEffect(42)->level];
+		minDmg -= VLC->spellh->spells[42].powers[attacker->getEffect(42)->level];
 		return minDmg;
 	}
 	else if(attacker->getEffect(41)) //bless handling
 	{
-		maxDmg += VLC->spellh->spells[attacker->getEffect(41)->id].powers[attacker->getEffect(41)->level];
+		maxDmg += VLC->spellh->spells[41].powers[attacker->getEffect(41)->level];
 		return maxDmg;
 	}
 	else

+ 1 - 0
CGameState.h

@@ -171,6 +171,7 @@ public:
 	CStack(CCreature * C, int A, int O, int I, bool AO, int S);
 	CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1), abilities(), state(), effects() {}
 	const StackEffect * getEffect(ui16 id) const; //effect id (SP)
+	ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
 	bool willMove(); //if stack has remaining move this turn
 	ui32 Speed() const;
 	si8 Morale() const;

+ 9 - 8
lib/NetPacksLib.cpp

@@ -558,6 +558,14 @@ DLL_EXPORT void SpellCasted::applyGs( CGameState *gs )
 	{
 		gs->curB->castedSpells[side]++;
 	}
+	if(gs->curB && id == 35) //dispel
+	{
+		CStack *s = gs->curB->getStackT(tile);
+		if(s)
+		{
+			s->effects.clear(); //removing all effects
+		}
+	}
 }
 
 DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
@@ -567,14 +575,7 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs )
 		CStack *s = gs->curB->getStack(id);
 		if(s)
 		{
-			if(effect.id == 35) //dispel - removing all effects
-			{
-				s->effects.clear();
-			}
-			else //adding effect
-			{
-				s->effects.push_back(effect);
-			}
+			s->effects.push_back(effect); //adding effect
 		}
 		else
 			tlog1 << "Cannot find stack " << id << std::endl;

+ 68 - 77
server/CGameHandler.cpp

@@ -2281,42 +2281,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 
 			//TODO: check resistances
 
-#define SPELL_CAST_TEMPLATE_1(NUMBER, DURATION) SetStackEffect sse; \
-			if(h->getSpellSchoolLevel(s) < 3)  /*not expert */ \
-			{ \
-				sse.stacks.insert(gs->curB->getStackT(ba.destinationTile)->ID); \
-				sse.effect.id = (NUMBER); \
-				sse.effect.level = h->getSpellSchoolLevel(s); \
-				sse.effect.turnsRemain = (DURATION); /*! - any duration */ \
-				sendAndApply(&sse); \
-			} \
-			else \
-			{ \
-				for(int it=0; it<gs->curB->stacks.size(); ++it) \
-				{ \
-					/*if it's non negative spell and our unit or non positive spell and hostile unit */ \
-					if((VLC->spellh->spells[ba.additionalInfo].positiveness >= 0 && gs->curB->stacks[it]->owner == h->tempOwner) \
-						||(VLC->spellh->spells[ba.additionalInfo].positiveness <= 0 && gs->curB->stacks[it]->owner != h->tempOwner ) \
-						) \
-					{ \
-						sse.stacks.insert(gs->curB->stacks[it]->ID); \
-					} \
-				} \
-				sse.effect.id = (NUMBER); \
-				sse.effect.level = h->getSpellSchoolLevel(s); \
-				sse.effect.turnsRemain = (DURATION); \
-				sendAndApply(&sse); \
-			}
-
-#define SPELL_CAST_TEMPLATE_2(EFFECT_ID, DAMAGE) std::set<ui16> attackedHexes = s->rangeInHexes(ba.destinationTile, h->getSpellSchoolLevel(s)); \
-					std::set<CStack*> attackedCres; /*std::set to exclude multiple occurences of two hex creatures*/ \
-					for(std::set<ui16>::iterator it = attackedHexes.begin(); it != attackedHexes.end(); ++it) \
-					{ \
-						CStack * st = gs->curB->getStackT(*it); \
-						if(st) \
-							attackedCres.insert(st); \
-					} \
-					if(attackedCres.size() == 0) break; \
+#define SPELL_CAST_TEMPLATE_2(EFFECT_ID, DAMAGE) \
 					StacksInjured si; \
 					for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) \
 					{ \
@@ -2336,6 +2301,49 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 			sc.skill = skill;
 			sc.tile = ba.destinationTile;
 			sendAndApply(&sc);
+
+			//calculating affected creatures - not for all spells, but for many of them
+			//it should spoil anything for other spells
+			std::set<ui16> attackedHexes = s->rangeInHexes(ba.destinationTile, h->getSpellSchoolLevel(s));
+			std::set<CStack*> attackedCres; /*std::set to exclude multiple occurences of two hex creatures*/
+			if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature
+			{
+				CStack * st = gs->curB->getStackT(ba.destinationTile);
+				if(st)
+					attackedCres.insert(st);
+			}
+			else if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
+			{
+				if(h->getSpellSchoolLevel(s) < 3)  /*not expert */
+				{
+					CStack * st = gs->curB->getStackT(ba.destinationTile);
+					if(st)
+						attackedCres.insert(st);
+				}
+				else
+				{
+					for(int it=0; it<gs->curB->stacks.size(); ++it)
+					{
+						/*if it's non negative spell and our unit or non positive spell and hostile unit */
+						if((VLC->spellh->spells[ba.additionalInfo].positiveness >= 0 && gs->curB->stacks[it]->owner == h->tempOwner)
+							||(VLC->spellh->spells[ba.additionalInfo].positiveness <= 0 && gs->curB->stacks[it]->owner != h->tempOwner )
+							)
+						{
+							attackedCres.insert(gs->curB->stacks[it]);
+						}
+					}
+				} //if(h->getSpellSchoolLevel(s) < 3)
+			}
+			else //custom range from attackedHexes
+			{
+				for(std::set<ui16>::iterator it = attackedHexes.begin(); it != attackedHexes.end(); ++it)
+				{
+					CStack * st = gs->curB->getStackT(*it);
+						attackedCres.insert(st);
+				}
+			}
+			//affected creatures calculated
+			//applying effects
 			switch(ba.additionalInfo) //spell id
 			{
 			case 15: //magic arrow
@@ -2388,18 +2396,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 							attackedCres.insert(gs->curB->stacks[it]);
 					}
 					if(attackedCres.size() == 0) break;
-					StacksInjured si;
-					for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
-					{
-						BattleStackAttacked bsa;
-						bsa.flags |= 2;
-						bsa.effect = 8;
-						bsa.damageAmount = h->getPrimSkillLevel(2) * 5  +  s->powers[h->getSpellSchoolLevel(s)]; 
-						bsa.stackAttacked = (*it)->ID;
-						prepareAttacked(bsa,*it);
-						si.stacks.insert(bsa);
-					}
-					sendAndApply(&si);
+					SPELL_CAST_TEMPLATE_2(8, h->getPrimSkillLevel(2) * 5  +  s->powers[h->getSpellSchoolLevel(s)]);
 					break;
 				}
 			case 25: //destroy undead
@@ -2412,18 +2409,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 							attackedCres.insert(gs->curB->stacks[it]);
 					}
 					if(attackedCres.size() == 0) break;
-					StacksInjured si;
-					for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
-					{
-						BattleStackAttacked bsa;
-						bsa.flags |= 2;
-						bsa.effect = 29;
-						bsa.damageAmount = h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]; 
-						bsa.stackAttacked = (*it)->ID;
-						prepareAttacked(bsa,*it);
-						si.stacks.insert(bsa);
-					}
-					sendAndApply(&si);
+					SPELL_CAST_TEMPLATE_2(29, h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]);
 					break;
 				}
 			case 26: //armageddon
@@ -2435,28 +2421,17 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 						attackedCres.insert(gs->curB->stacks[it]);
 					}
 					if(attackedCres.size() == 0) break;
-					StacksInjured si;
-					for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
-					{
-						BattleStackAttacked bsa;
-						bsa.flags |= 2;
-						bsa.effect = 12;
-						bsa.damageAmount = h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]; 
-						bsa.stackAttacked = (*it)->ID;
-						prepareAttacked(bsa,*it);
-						si.stacks.insert(bsa);
-					}
-					sendAndApply(&si);
+					SPELL_CAST_TEMPLATE_2(12, h->getPrimSkillLevel(2) * 50  +  s->powers[h->getSpellSchoolLevel(s)]);
 					break;
 				}
 			case 27: //shield 
 			case 28: //air shield
-			case 35: //dispel
 			case 41: //bless
 			case 42: //curse
 			case 43: //bloodlust
 			case 45: //weakness
 			case 46: //stone skin
+			case 47: //disrupting ray
 			case 48: //prayer
 			case 49: //mirth
 			case 50: //sorrow
@@ -2466,13 +2441,29 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 			case 54: //slow
 			case 61: //forgetfulness
 				{
-					SPELL_CAST_TEMPLATE_1(ba.additionalInfo, h->getPrimSkillLevel(2) + h->valOfBonuses(HeroBonus::SPELL_DURATION) )
-						break;
+					SetStackEffect sse;
+					for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
+					{
+						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);
+					break;
 				}
 			case 56: //frenzy
 				{
-					SPELL_CAST_TEMPLATE_1(ba.additionalInfo, 1)
-						break;
+					SetStackEffect sse;
+					for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
+					{
+						sse.stacks.insert((*it)->ID);
+					}
+					sse.effect.id = ba.additionalInfo;
+					sse.effect.level = h->getSpellSchoolLevel(s);
+					sse.effect.turnsRemain = 1;
+					sendAndApply(&sse);
+					break;
 				}
 			}
 			sendAndApply(&EndAction());