1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-05 13:04:54 +02:00

Support for Chain Lightning.

Fixed getClosestTile function.
This commit is contained in:
DjWarmonger 2012-05-20 11:40:23 +00:00
parent 59255a4cad
commit d34cf90bf7
4 changed files with 41 additions and 9 deletions

View File

@ -1607,6 +1607,7 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
case Spells::LIGHTNING_BOLT: case Spells::LIGHTNING_BOLT:
case Spells::TITANS_LIGHTNING_BOLT: case Spells::TITANS_LIGHTNING_BOLT:
case Spells::THUNDERBOLT: 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 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); 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::SUMMON_AIR_ELEMENTAL:
case Spells::CLONE: case Spells::CLONE:
case Spells::REMOVE_OBSTACLE: 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? addNewAnim(new CDummyAnimation(this, 2)); //interface won't return until animation is played. TODO: make it smarter?
break; break;
} //switch(sc->id) } //switch(sc->id)

View File

@ -27,7 +27,7 @@
{ "id": 16, "effect": -1, "anim": 46, "ranges": [ "0", "0", "0", "0" ] }, { "id": 16, "effect": -1, "anim": 46, "ranges": [ "0", "0", "0", "0" ] },
{ "id": 17, "effect": -1, "anim": 38, "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": 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": 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": 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" ] }, { "id": 22, "effect": -1, "anim": 9, "ranges": [ "0-2", "0-2", "0-2", "0-2" ] },

View File

@ -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 :( std::vector<BattleHex> sortedTiles (possibilities.begin(), possibilities.end()); //set can't be sorted properly :(
BattleHex initialHex = BattleHex(initialPos); 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); 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 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 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 ui8 attackerSide = sides[1] == attackerOwner;
const auto attackedHexes = s->rangeInHexes(destinationTile, skillLevel, attackerSide); 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) if(s->id == Spells::DEATH_RIPPLE || s->id == Spells::DESTROY_UNDEAD || s->id == Spells::ARMAGEDDON)
{ {
for(int it=0; it<stacks.size(); ++it) 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 else if (s->range[skillLevel].size() > 1) //custom many-hex range
{ {
BOOST_FOREACH(BattleHex hex, attackedHexes) BOOST_FOREACH(BattleHex hex, attackedHexes)

View File

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