Browse Source

* new spells
- protection from air
- protection from fire
- protection from water
- protection from earth
* a bit of refactoring in spell handling code

mateuszb 16 years ago
parent
commit
d14083272d
6 changed files with 178 additions and 142 deletions
  1. 5 24
      CBattleInterface.cpp
  2. 0 1
      CBattleInterface.h
  3. 71 71
      config/spell_info.txt
  4. 6 2
      hch/CSpellHandler.cpp
  5. 2 2
      hch/CSpellHandler.h
  6. 94 42
      server/CGameHandler.cpp

+ 5 - 24
CBattleInterface.cpp

@@ -261,28 +261,6 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C
 			SDL_SetColorKey(idToObstacle[obst[t].ID]->ourImages[n].bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(idToObstacle[obst[t].ID]->ourImages[n].bitmap->format,0,255,255));
 		}
 	}
-
-	//initializing spellToEffect
-	spellToEffect[17] = 1; //lightning bolt
-	spellToEffect[18] = 10; //implosion
-	spellToEffect[27] = 27; //shield
-	spellToEffect[28] = 2; //air shield
-	spellToEffect[35] = 41; //dispel
-	spellToEffect[41] = 36; //bless
-	spellToEffect[42] = 40; //curse
-	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
-	spellToEffect[51] = 18; //fortune
-	spellToEffect[52] = 48; //misfortune
-	spellToEffect[53] = 31; //haste
-	spellToEffect[54] = 19; //slow
-	spellToEffect[56] = 17; //frenzy
-	spellToEffect[61] = 42; //forgetfulness
 }
 
 CBattleInterface::~CBattleInterface()
@@ -1863,8 +1841,11 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
 			SDL_SetClipRect(screen, &buf); //restoring previous clip rect
 			break; //for 15 and 16 cases
 		}
+	case 17: //lightning bolt
+		displayEffect(1, sc->tile);
+		displayEffect(CGI->spellh->spells[sc->id].mainEffectAnim, sc->tile);
 	case 35: //dispel
-		displayEffect(spellToEffect[sc->id], sc->tile);
+		displayEffect(CGI->spellh->spells[sc->id].mainEffectAnim, sc->tile);
 	} //switch(sc->id)
 }
 
@@ -1872,7 +1853,7 @@ void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
 {
 	for(std::set<ui32>::const_iterator ci = sse.stacks.begin(); ci!=sse.stacks.end(); ++ci)
 	{
-		displayEffect(spellToEffect[sse.effect.id], LOCPLINT->cb->battleGetStackByID(*ci)->position);
+		displayEffect(CGI->spellh->spells[sse.effect.id].mainEffectAnim, LOCPLINT->cb->battleGetStackByID(*ci)->position);
 	}
 	redrawBackgroundWithHexes(activeStack);
 }

+ 0 - 1
CBattleInterface.h

@@ -165,7 +165,6 @@ private:
 	std::map< int, CDefHandler * > idToProjectile; //projectiles of creaures (creatureID, defhandler)
 	std::map< int, CDefHandler * > idToObstacle; //obstacles located on the battlefield
 	std::map< int, bool > creDir; // <creatureID, if false reverse creature's animation>
-	std::map< int, int > spellToEffect; //which effect should be played when different spells are casted (spellID, effectID)
 	unsigned char animCount;
 	int activeStack; //number of active stack; -1 - no one
 	int mouseHoveredStack; //stack hovered by mouse; if -1 -> none

+ 71 - 71
config/spell_info.txt

@@ -1,73 +1,73 @@
 //additional spell info, not included in original heroes III files
-//[spellID - -1 is the end of data in file] [-1 -> spell is negative for influenced creatures; 0 - spell is indifferent for them; 1 - spell is poitive for them] [spell range description in SRSL, none magic] [basic] [advanced] [expert]
-0 0 X X X X
-1 0 X X X X
-2 0 X X X X
-3 0 X X X X
-4 0 X X X X
-5 0 X X X X
-6 0 X X X X
-7 0 X X X X
-8 0 X X X X
-9 0 X X X X
-10 0 X X X X
-11 0 X X X X
-12 0 0 0 0 0
-13 0 0 0 0 0
-14 0 X X X X
-15 -1 0 0 0 0
-16 -1 0 0 0 0
-17 -1 0 0 0 0
-18 -1 0 0 0 0
-19 -1 0 0 0 0
-20 -1 1 1 1 1
-21 -1 0,1 0,1 0,1 0,1
-22 -1 0-2 0-2 0-2 0-2
-23 -1 0,1 0,1 0,1 0,1
-24 -1 X X X X
-25 -1 X X X X
-26 -1 X X X X
-27 1 0 0 0 X
-28 1 0 0 0 X
-29 1 0 0 0 X
-30 1 0 0 0 X
-31 1 0 0 0 X
-32 1 0 0 0 X
-33 1 0 0 0 X
-34 1 0 0 0 X
-35 0 0 0 0 X
-36 1 0 0 0 0
-37 1 0 0 0 0
-38 1 0 0 0 0
-39 1 0 0 0 0
-40 1 0 0 0 0
-41 1 0 0 0 X
-42 -1 0 0 0 X
-43 1 0 0 0 X
-44 1 0 0 0 X
-45 -1 0 0 0 X
-46 1 0 0 0 X
-47 -1 0 0 0 X
-48 1 0 0 0 X
-49 1 0 0 0 X
-50 -1 0 0 0 X
-51 1 0 0 0 X
-52 -1 0 0 0 X
-53 1 0 0 0 X
-54 -1 0 0 0 X
-55 1 0 0 0 0
-56 1 0 0 0 0
-57 -1 0 0 0 0
-58 1 0 0 0 X
-59 -1 0 0 0-1 0-2
-60 -1 0 0 0 0
-61 -1 0 0 0 X
-62 -1 0 0 0 0
-63 1 0 0 0 0
-64 0 X X X X
-65 1 0 0 0 0
-66 0 X X X X
-67 0 X X X X
-68 0 X X X X
-69 0 X X X X
+//[spellID - -1 is the end of data in file] [-1 -> spell is negative for influenced creatures; 0 - spell is indifferent for them; 1 - spell is poitive for them] [main effect animation (AC format), -1 - none] [spell range description in SRSL, none magic] [basic] [advanced] [expert]
+0 0 -1 X X X X
+1 0 -1 X X X X
+2 0 -1 X X X X
+3 0 -1 X X X X
+4 0 -1 X X X X
+5 0 -1 X X X X
+6 0 -1 X X X X
+7 0 -1 X X X X
+8 0 -1 X X X X
+9 0 -1 X X X X
+10 0 -1 X X X X
+11 0 -1 X X X X
+12 0 -1 0 0 0 0
+13 0 -1 0 0 0 0
+14 0 -1 X X X X
+15 -1 64 0 0 0 0
+16 -1 46 0 0 0 0
+17 -1 38 0 0 0 0
+18 -1 10 0 0 0 0
+19 -1 -1 0 0 0 0
+20 -1 45 1 1 1 1
+21 -1 53 0,1 0,1 0,1 0,1
+22 -1 9 0-2 0-2 0-2 0-2
+23 -1 16 0,1 0,1 0,1 0,1
+24 -1 8 X X X X
+25 -1 29 X X X X
+26 -1 12 X X X X
+27 1 27 0 0 0 X
+28 1 2 0 0 0 X
+29 1 -1 0 0 0 X
+30 1 22 0 0 0 X
+31 1 24 0 0 0 X
+32 1 23 0 0 0 X
+33 1 26 0 0 0 X
+34 1 -1 0 0 0 X
+35 0 41 0 0 0 X
+36 1 -1 0 0 0 0
+37 1 -1 0 0 0 0
+38 1 -1 0 0 0 0
+39 1 -1 0 0 0 0
+40 1 -1 0 0 0 0
+41 1 36 0 0 0 X
+42 -1 40 0 0 0 X
+43 1 4 0 0 0 X
+44 1 -1 0 0 0 X
+45 -1 56 0 0 0 X
+46 1 54 0 0 0 X
+47 -1 14 0 0 0 X
+48 1 0 0 0 0 X
+49 1 20 0 0 0 X
+50 -1 30 0 0 0 X
+51 1 18 0 0 0 X
+52 -1 48 0 0 0 X
+53 1 31 0 0 0 X
+54 -1 19 0 0 0 X
+55 1 -1 0 0 0 0
+56 1 17 0 0 0 0
+57 -1 -1 0 0 0 0
+58 1 -1 0 0 0 X
+59 -1 -1 0 0 0-1 0-2
+60 -1 -1 0 0 0 0
+61 -1 42 0 0 0 X
+62 -1 -1 0 0 0 0
+63 1 -1 0 0 0 0
+64 0 -1 X X X X
+65 1 -1 0 0 0 0
+66 0 -1 X X X X
+67 0 -1 X X X X
+68 0 -1 X X X X
+69 0 -1 X X X X
 -1

+ 6 - 2
hch/CSpellHandler.cpp

@@ -255,6 +255,7 @@ void CSpellHandler::loadSpells()
 		nsp.id = spells.size();
 		nsp.combatSpell = combSpells;
 		nsp.creatureAbility = creatureAbility;
+		nsp.mainEffectAnim = -1;
 		spells.push_back(nsp);
 	}
 	//loading of additional spell traits
@@ -268,15 +269,18 @@ void CSpellHandler::loadSpells()
 	{
 		//reading header
 		std::string dump;
-		for(int i=0; i<52; ++i) ast>>dump;
+		for(int i=0; i<60; ++i) ast>>dump;
 		//reading exact info
 		int spellID;
 		ast>>spellID;
 		while(spellID != -1)
 		{
 			int buf;
-			ast>>buf;
+			ast >> buf;
 			spells[spellID].positiveness = buf;
+			ast >> buf;
+			spells[spellID].mainEffectAnim = buf;
+
 			spells[spellID].range.resize(4);
 			for(int g=0; g<4; ++g)
 				ast>>spells[spellID].range[g];

+ 2 - 2
hch/CSpellHandler.h

@@ -38,12 +38,12 @@ public:
 	si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
 	std::vector<std::string> range; //description of spell's range in SRSL by magic school level
 	std::set<ui16> rangeInHexes(unsigned int centralHex, ui8 schoolLvl ) const; //convert range to specific hexes
-
+	si16 mainEffectAnim; //main spell effect animation, in AC format (or -1 when none)
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & id & name & abbName & descriptions & level & earth & water & fire & air & power & costs 
-			& powers & probabilities & AIVals & attributes & combatSpell & creatureAbility & positiveness & range;
+			& powers & probabilities & AIVals & attributes & combatSpell & creatureAbility & positiveness & range & mainEffectAnim;
 	}
 };
 

+ 94 - 42
server/CGameHandler.cpp

@@ -2246,6 +2246,81 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
 	}
 }
 
+ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature)
+{
+	ui32 ret = 0; //value to return
+	switch(sp->id)
+	{
+		case 15: //magic arrow
+			{
+				ret = caster->getPrimSkillLevel(2) * 10  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 16: //ice bolt
+			{
+				ret = caster->getPrimSkillLevel(2) * 20  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 17: //lightning bolt
+			{
+				ret = caster->getPrimSkillLevel(2) * 25  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 18: //implosion
+			{
+				ret = caster->getPrimSkillLevel(2) * 75  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 20: //frost ring
+			{
+				ret = caster->getPrimSkillLevel(2) * 10  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 21: //fireball
+			{
+				ret = caster->getPrimSkillLevel(2) * 10  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 22: //inferno
+			{
+				ret = caster->getPrimSkillLevel(2) * 10  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 23: //meteor shower
+			{
+				ret = caster->getPrimSkillLevel(2) * 10  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 24: //death ripple
+			{
+				ret = caster->getPrimSkillLevel(2) * 5  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 25: //destroy undead
+			{
+				ret = caster->getPrimSkillLevel(2) * 10  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+		case 26: //armageddon
+			{
+				ret = caster->getPrimSkillLevel(2) * 50  +  sp->powers[caster->getSpellSchoolLevel(sp)];
+			}
+	}
+	//applying protections - when spell has more then one elements, only one protection should be applied (I think)
+	if(sp->air && affectedCreature->getEffect(30)) //air spell & protection from air
+	{
+		ret *= VLC->spellh->spells[30].powers[affectedCreature->getEffect(30)->level];
+		ret /= 100;
+	}
+	else if(sp->fire && affectedCreature->getEffect(31)) //fire spell & protection from fire
+	{
+		ret *= VLC->spellh->spells[31].powers[affectedCreature->getEffect(31)->level];
+		ret /= 100;
+	}
+	else if(sp->water && affectedCreature->getEffect(32)) //water spell & protection from water
+	{
+		ret *= VLC->spellh->spells[32].powers[affectedCreature->getEffect(32)->level];
+		ret /= 100;
+	}
+	else if (sp->earth && affectedCreature->getEffect(33)) //earth spell & protection from earth
+	{
+		ret *= VLC->spellh->spells[33].powers[affectedCreature->getEffect(33)->level];
+		ret /= 100;
+	}
+
+	return ret;
+}
+
 bool CGameHandler::makeCustomAction( BattleAction &ba )
 {
 	switch(ba.actionType)
@@ -2281,14 +2356,14 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 
 			//TODO: check resistances
 
-#define SPELL_CAST_TEMPLATE_2(EFFECT_ID, DAMAGE) \
+#define SPELL_CAST_TEMPLATE_2 \
 					StacksInjured si; \
 					for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) \
 					{ \
 						BattleStackAttacked bsa; \
 						bsa.flags |= 2; \
-						bsa.effect = EFFECT_ID; \
-						bsa.damageAmount = DAMAGE;  \
+						bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim; \
+						bsa.damageAmount = calculateSpellDmg(&VLC->spellh->spells[ba.additionalInfo], h, *it);  \
 						bsa.stackAttacked = (*it)->ID; \
 						prepareAttacked(bsa,*it); \
 						si.stacks.insert(bsa); \
@@ -2306,13 +2381,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 			//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(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 */
 				{
@@ -2334,11 +2403,18 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 					}
 				} //if(h->getSpellSchoolLevel(s) < 3)
 			}
+			else 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 //custom range from attackedHexes
 			{
 				for(std::set<ui16>::iterator it = attackedHexes.begin(); it != attackedHexes.end(); ++it)
 				{
 					CStack * st = gs->curB->getStackT(*it);
+					if(st)
 						attackedCres.insert(st);
 				}
 			}
@@ -2347,43 +2423,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 			switch(ba.additionalInfo) //spell id
 			{
 			case 15: //magic arrow
-				{
-					SPELL_CAST_TEMPLATE_2(64, h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]);
-					break;
-				}
 			case 16: //ice bolt
-				{
-					SPELL_CAST_TEMPLATE_2(46, h->getPrimSkillLevel(2) * 20  +  s->powers[h->getSpellSchoolLevel(s)]);
-					break;
-				}
 			case 17: //lightning bolt
-				{
-					SPELL_CAST_TEMPLATE_2(38, h->getPrimSkillLevel(2) * 25  +  s->powers[h->getSpellSchoolLevel(s)]);
-					break;
-				}
 			case 18: //implosion
-				{
-					SPELL_CAST_TEMPLATE_2(10, h->getPrimSkillLevel(2) * 75  +  s->powers[h->getSpellSchoolLevel(s)]);
-					break;
-				}
 			case 20: //frost ring
-				{
-					SPELL_CAST_TEMPLATE_2(45, h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]);
-					break;
-				}
 			case 21: //fireball
-				{
-					SPELL_CAST_TEMPLATE_2(53, h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]);
-					break;
-				}
 			case 22: //inferno
-				{
-					SPELL_CAST_TEMPLATE_2(9, h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]);
-					break;
-				}
 			case 23: //meteor shower
 				{
-					SPELL_CAST_TEMPLATE_2(16, h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]);
+					SPELL_CAST_TEMPLATE_2;
 					break;
 				}
 			case 24: //death ripple
@@ -2396,7 +2444,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 							attackedCres.insert(gs->curB->stacks[it]);
 					}
 					if(attackedCres.size() == 0) break;
-					SPELL_CAST_TEMPLATE_2(8, h->getPrimSkillLevel(2) * 5  +  s->powers[h->getSpellSchoolLevel(s)]);
+					SPELL_CAST_TEMPLATE_2;
 					break;
 				}
 			case 25: //destroy undead
@@ -2409,7 +2457,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 							attackedCres.insert(gs->curB->stacks[it]);
 					}
 					if(attackedCres.size() == 0) break;
-					SPELL_CAST_TEMPLATE_2(29, h->getPrimSkillLevel(2) * 10  +  s->powers[h->getSpellSchoolLevel(s)]);
+					SPELL_CAST_TEMPLATE_2;
 					break;
 				}
 			case 26: //armageddon
@@ -2421,11 +2469,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 						attackedCres.insert(gs->curB->stacks[it]);
 					}
 					if(attackedCres.size() == 0) break;
-					SPELL_CAST_TEMPLATE_2(12, h->getPrimSkillLevel(2) * 50  +  s->powers[h->getSpellSchoolLevel(s)]);
+					SPELL_CAST_TEMPLATE_2;
 					break;
 				}
 			case 27: //shield 
 			case 28: //air shield
+			case 30: //protection from air
+			case 31: //protection from fire
+			case 32: //protection from water
+			case 33: //protection from earth
 			case 41: //bless
 			case 42: //curse
 			case 43: //bloodlust