Browse Source

Support for Chain Lightning.

Fixed getClosestTile function.
DjWarmonger 13 years ago
parent
commit
d34cf90bf7

+ 1 - 1
client/BattleInterface/CBattleInterface.cpp

@@ -1607,6 +1607,7 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 	case Spells::LIGHTNING_BOLT:
 	case Spells::TITANS_LIGHTNING_BOLT:
 	case Spells::THUNDERBOLT:
+	case Spells::CHAIN_LIGHTNING: //TODO: zigzag effect
 		for (auto it = sc->affectedCres.begin(); it != sc->affectedCres.end(); ++it) //in case we have multiple targets
 		{
 			displayEffect(1, curInt->cb->battleGetStackByID(*it, false)->position);
@@ -1630,7 +1631,6 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 	case Spells::SUMMON_AIR_ELEMENTAL:
 	case Spells::CLONE:
 	case Spells::REMOVE_OBSTACLE:
-	case Spells::CHAIN_LIGHTNING:
 		addNewAnim(new CDummyAnimation(this, 2)); //interface won't return until animation is played. TODO: make it smarter?
 		break;
 	} //switch(sc->id)

+ 1 - 1
config/spell_info.json

@@ -27,7 +27,7 @@
 		{ "id": 16, "effect": -1, "anim": 46, "ranges": [ "0", "0", "0", "0" ] },
 		{ "id": 17, "effect": -1, "anim": 38, "ranges": [ "0", "0", "0", "0" ] },
 		{ "id": 18, "effect": -1, "anim": 10, "ranges": [ "0", "0", "0", "0" ] },
-		{ "id": 19, "effect": -1, "anim": -1, "ranges": [ "0", "0", "0", "0" ] },
+		{ "id": 19, "effect": -1, "anim": 38, "ranges": [ "0", "0", "0", "0" ] },
 		{ "id": 20, "effect": -1, "anim": 45, "ranges": [ "1", "1", "1", "1" ] },
 		{ "id": 21, "effect": -1, "anim": 53, "ranges": [ "0,1", "0,1", "0,1", "0,1" ] },
 		{ "id": 22, "effect": -1, "anim": 9, "ranges": [ "0-2", "0-2", "0-2", "0-2" ] },

+ 32 - 5
lib/BattleState.cpp

@@ -385,7 +385,7 @@ BattleHex BattleInfo::getClosestTile (bool attackerOwned, int initialPos, std::s
 	std::vector<BattleHex> sortedTiles (possibilities.begin(), possibilities.end()); //set can't be sorted properly :(
 
 	BattleHex initialHex = BattleHex(initialPos);
-	auto compareDistance = [initialPos, initialHex](const BattleHex left, const BattleHex right) -> bool
+	auto compareDistance = [initialHex](const BattleHex left, const BattleHex right) -> bool
 	{
 		return initialHex.getDistance (initialHex, left) < initialHex.getDistance (initialHex, right);
 	};
@@ -396,10 +396,12 @@ BattleHex BattleInfo::getClosestTile (bool attackerOwned, int initialPos, std::s
 
 	auto notClosest = [closestDistance, initialPos](const BattleHex here) -> bool
 	{
-		return closestDistance < here.getDistance (initialPos, here);
+		int debug = here.getDistance (initialPos, here);
+		bool debug2 = closestDistance < debug;
+		return debug2;
 	};
 
-	boost::remove_if (sortedTiles, notClosest); //only closest tiles are interesting
+	sortedTiles.erase (boost::remove_if (sortedTiles, notClosest), sortedTiles.end()); //only closest tiles are interesting
 
 	auto compareHorizontal = [attackerOwned](const BattleHex left, const BattleHex right) -> bool
 	{
@@ -764,8 +766,8 @@ std::set<CStack*> BattleInfo::getAttackedCreatures(const CSpell * s, int skillLe
 
 	const ui8 attackerSide = sides[1] == attackerOwner;
 	const auto attackedHexes = s->rangeInHexes(destinationTile, skillLevel, attackerSide);
-	const bool onlyAlive = s->id != 38 && s->id != 39; //when casting resurrection or animate dead we should be allow to select dead stack
-
+	const bool onlyAlive = s->id != Spells::RESURRECTION && s->id != Spells::ANIMATE_DEAD; //when casting resurrection or animate dead we should be allow to select dead stack
+	//fixme: what about other rising spells (Sacrifice) ?
 	if(s->id == Spells::DEATH_RIPPLE || s->id == Spells::DESTROY_UNDEAD || s->id == Spells::ARMAGEDDON)
 	{
 		for(int it=0; it<stacks.size(); ++it)
@@ -780,6 +782,31 @@ std::set<CStack*> BattleInfo::getAttackedCreatures(const CSpell * s, int skillLe
 			}
 		}
 	}
+	else if (s->id == Spells::CHAIN_LIGHTNING)
+	{
+		std::set<BattleHex> possibleHexes;
+		BOOST_FOREACH (auto stack, stacks)
+		{
+			if (stack->isValidTarget())
+			BOOST_FOREACH (auto hex, stack->getHexes())
+			{
+				possibleHexes.insert (hex);
+			}
+		}
+		BattleHex lightningHex =  destinationTile;
+		for (int i = 0; i < 5; ++i) //TODO: depends on spell school level
+		{
+			auto stack = getStackT (lightningHex, true);
+			if (!stack)
+				break;
+			attackedCres.insert (stack);
+			BOOST_FOREACH (auto hex, stack->getHexes())
+			{
+				possibleHexes.erase (hex); //can't hit same place twice
+			}
+			lightningHex = getClosestTile (attackerOwner, destinationTile, possibleHexes);
+		}
+	}
 	else if (s->range[skillLevel].size() > 1) //custom many-hex range
 	{
 		BOOST_FOREACH(BattleHex hex, attackedHexes)

+ 7 - 2
server/CGameHandler.cpp

@@ -3953,6 +3953,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 	case Spells::ICE_BOLT:
 	case Spells::LIGHTNING_BOLT:
 	case Spells::IMPLOSION:
+	case Spells::CHAIN_LIGHTNING:
 	case Spells::FROST_RING:
 	case Spells::FIREBALL:
 	case Spells::INFERNO:
@@ -3975,6 +3976,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 					sc.dmgToDisplay = 0;
 				}
 			}
+			int chainLightningModifier = 0;
 			for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
 			{
 				if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
@@ -3988,10 +3990,10 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 					bsa.effect = spell->mainEffectAnim;
 				}
 				if (spellDamage)
-					bsa.damageAmount = spellDamage;
+					bsa.damageAmount = spellDamage >> chainLightningModifier;
 				else
 				{
-					bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower);
+					bsa.damageAmount = gs->curB->calculateSpellDmg(spell, caster, *it, spellLvl, usedSpellPower) >> chainLightningModifier;
 					sc.dmgToDisplay += bsa.damageAmount;
 				}
 				bsa.stackAttacked = (*it)->ID;
@@ -4001,6 +4003,9 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
 					bsa.attackerID = -1;
 				(*it)->prepareAttacked(bsa);
 				si.stacks.push_back(bsa);
+
+				if (spellID == Spells::CHAIN_LIGHTNING)
+					++chainLightningModifier;
 			}
 			break;
 		}