mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Support for Chain Lightning.
Fixed getClosestTile function.
This commit is contained in:
		| @@ -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) | ||||
|   | ||||
| @@ -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" ] }, | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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; | ||||
| 		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user