1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-26 22:57:00 +02:00

- Restored Genie random spell

- Fixed crashes in many strange creature-spellcasting scenarios, including stack with multiple cast abilities and Enchanter with non-stadard spell
This commit is contained in:
DjWarmonger 2012-04-18 15:57:49 +00:00
parent 05311dd30c
commit cd1a9414ac
3 changed files with 45 additions and 26 deletions

View File

@ -1564,8 +1564,11 @@ 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:
displayEffect(1, sc->tile); for (auto it = sc->affectedCres.begin(); it != sc->affectedCres.end(); ++it) //in case we have multiple targets
displayEffect(spell.mainEffectAnim, sc->tile); {
displayEffect(1, curInt->cb->battleGetStackByID(*it, false)->position);
displayEffect(spell.mainEffectAnim, curInt->cb->battleGetStackByID(*it, false)->position);
}
break; break;
case Spells::DISPEL: case Spells::DISPEL:
case Spells::CURE: case Spells::CURE:
@ -2668,6 +2671,8 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
bool noStackIsHovered = true; //will cause removing a blue glow bool noStackIsHovered = true; //will cause removing a blue glow
localActions.clear(); localActions.clear();
illegalActions.clear();
BOOST_FOREACH (PossibleActions action, possibleActions) BOOST_FOREACH (PossibleActions action, possibleActions)
{ {
bool legalAction = false; //this action is legal and can't be performed bool legalAction = false; //this action is legal and can't be performed
@ -2709,11 +2714,11 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
legalAction = true; legalAction = true;
break; break;
case HOSTILE_CREATURE_SPELL: //TODO: check spell immunity case HOSTILE_CREATURE_SPELL: //TODO: check spell immunity
if (shere && !ourStack && isCastingPossibleHere (sactive, shere, myNumber)) if (shere && shere->alive() && !ourStack && isCastingPossibleHere (sactive, shere, myNumber))
legalAction = true; legalAction = true;
break; break;
case FRIENDLY_CREATURE_SPELL: case FRIENDLY_CREATURE_SPELL:
if (shere && ourStack && isCastingPossibleHere (sactive, shere, myNumber)) if (shere && shere->alive() && ourStack && isCastingPossibleHere (sactive, shere, myNumber))
legalAction = true; legalAction = true;
break; break;
case RISING_SPELL: case RISING_SPELL:
@ -2727,7 +2732,6 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
int spellID = curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE); int spellID = curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE);
if (spellID > -1) if (spellID > -1)
{ {
sp = CGI->spellh->spells[spellID];
legalAction = true; legalAction = true;
} }
} }
@ -2867,9 +2871,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
case HOSTILE_CREATURE_SPELL: case HOSTILE_CREATURE_SPELL:
case FRIENDLY_CREATURE_SPELL: case FRIENDLY_CREATURE_SPELL:
case RISING_SPELL: case RISING_SPELL:
case RANDOM_GENIE_SPELL: sp = CGI->spellh->spells[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo]; //necessary if creature has random Genie spell at same time
if (sp)
{
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s
switch (sp->id) switch (sp->id)
{ {
@ -2879,10 +2881,11 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
break; break;
} }
isCastingPossible = true; isCastingPossible = true;
} break;
else //spell is random case RANDOM_GENIE_SPELL: //we assume that teleport / sacrifice will never be avaliable as random spell
sp = NULL;
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[301]) % shere->getName()); //Cast a spell on % consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[301]) % shere->getName()); //Cast a spell on %
//we assume that teleport / sacrifice will never be avaliable as random spell isCastingPossible = true;
break; break;
case TELEPORT: case TELEPORT:
consoleMsg = CGI->generaltexth->allTexts[25]; //Teleport Here consoleMsg = CGI->generaltexth->allTexts[25]; //Teleport Here
@ -2974,9 +2977,16 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
else else
{ {
if(creatureCasting) if(creatureCasting)
{
if (sp)
{ {
giveCommand(BattleAction::MONSTER_SPELL, myNumber, sactive->ID, creatureSpellToCast); giveCommand(BattleAction::MONSTER_SPELL, myNumber, sactive->ID, creatureSpellToCast);
} }
else //unknown random spell
{
giveCommand(BattleAction::MONSTER_SPELL, myNumber, sactive->ID, curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE));
}
}
else else
{ {
spellToCast->destinationTile = myNumber; spellToCast->destinationTile = myNumber;
@ -2995,17 +3005,17 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CStack * shere, BattleHex myNumber) bool CBattleInterface::isCastingPossibleHere (const CStack * sactive, const CStack * shere, BattleHex myNumber)
{ {
creatureCasting = (stackCanCastSpell) && (shere != sactive); //is it really useful? creatureCasting = stackCanCastSpell; //is it really useful?
bool isCastingPossible = true; bool isCastingPossible = true;
int spellID = -1; int spellID = -1;
if (creatureCasting) if (creatureCasting)
{ {
if (creatureSpellToCast > -1) if (creatureSpellToCast > -1 && (shere != sactive)) //can't cast on itself
spellID = creatureSpellToCast; //TODO: merge with SpellTocast? spellID = creatureSpellToCast; //TODO: merge with SpellTocast?
} }
else if(spellDestSelectMode) //hero casting else //hero casting
spellID = spellToCast->additionalInfo; spellID = spellToCast->additionalInfo;
sp = NULL; sp = NULL;

View File

@ -835,7 +835,8 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
if (defender && !i->isSecondary()) if (defender && !i->isSecondary())
battleInt->displayEffect(i->effect, defender->position); battleInt->displayEffect(i->effect, defender->position);
} }
StackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, LOCPLINT->curAction->actionType==7, i->killed(), i->willRebirth(), i->cloneKilled()}; bool shooting = (LOCPLINT->curAction ? LOCPLINT->curAction->actionType == BattleAction::SHOOT : false); //FIXME: why action is deleted during enchanter cast?
StackAttackedInfo to_put = {defender, i->damageAmount, i->killedAmount, attacker, shooting, i->killed(), i->willRebirth(), i->cloneKilled()};
arg.push_back(to_put); arg.push_back(to_put);
} }

View File

@ -3561,10 +3561,12 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
|| (!spell->isPositive() && stack->owner != casterColor)) || (!spell->isPositive() && stack->owner != casterColor))
{ {
if(stack->isValidTarget()) //TODO: allow dead targets somewhere in the future if(stack->isValidTarget()) //TODO: allow dead targets somewhere in the future
{
attackedCres.insert(stack); attackedCres.insert(stack);
} }
} }
} }
}
//checking if creatures resist //checking if creatures resist
sc.resisted = gs->curB->calculateResistedStacks(spell, caster, secHero, attackedCres, casterColor, mode, usedSpellPower, spellLvl); sc.resisted = gs->curB->calculateResistedStacks(spell, caster, secHero, attackedCres, casterColor, mode, usedSpellPower, spellLvl);
@ -3619,7 +3621,8 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
continue; continue;
BattleStackAttacked bsa; BattleStackAttacked bsa;
if ((destination > -1 && (*it)->coversPos(destination)) || spell->range[spellLvl] == "X") //display effect only upon primary target of area spell if ((destination > -1 && (*it)->coversPos(destination)) || (spell->range[spellLvl] == "X" || mode == ECastingMode::ENCHANTER_CASTING))
//display effect only upon primary target of area spell
{ {
bsa.flags |= BattleStackAttacked::EFFECT; bsa.flags |= BattleStackAttacked::EFFECT;
bsa.effect = spell->mainEffectAnim; bsa.effect = spell->mainEffectAnim;
@ -3632,6 +3635,9 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, BattleHex dest
sc.dmgToDisplay += bsa.damageAmount; sc.dmgToDisplay += bsa.damageAmount;
} }
bsa.stackAttacked = (*it)->ID; bsa.stackAttacked = (*it)->ID;
if (mode == ECastingMode::ENCHANTER_CASTING) //multiple damage spells cast
bsa.attackerID = stack->ID;
else
bsa.attackerID = -1; bsa.attackerID = -1;
(*it)->prepareAttacked(bsa); (*it)->prepareAttacked(bsa);
si.stacks.push_back(bsa); si.stacks.push_back(bsa);
@ -4769,6 +4775,8 @@ void CGameHandler::handleAttackBeforeCasting (const BattleAttack & bat)
void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat ) void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
{ {
const CStack * attacker = gs->curB->getStack(bat.stackAttacking); const CStack * attacker = gs->curB->getStack(bat.stackAttacking);
if (!attacker) //could be already dead
return;
attackCasting(bat, Bonus::SPELL_AFTER_ATTACK, attacker); attackCasting(bat, Bonus::SPELL_AFTER_ATTACK, attacker);
if(bat.bsa[0].newAmount <= 0) if(bat.bsa[0].newAmount <= 0)