mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +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:
parent
05311dd30c
commit
cd1a9414ac
@ -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,22 +2871,21 @@ 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
|
||||||
|
switch (sp->id)
|
||||||
{
|
{
|
||||||
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s
|
case Spells::TELEPORT:
|
||||||
switch (sp->id)
|
case Spells::SACRIFICE:
|
||||||
{
|
secondaryTarget = true;
|
||||||
case Spells::TELEPORT:
|
break;
|
||||||
case Spells::SACRIFICE:
|
|
||||||
secondaryTarget = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
isCastingPossible = true;
|
|
||||||
}
|
}
|
||||||
else //spell is random
|
isCastingPossible = true;
|
||||||
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[301]) % shere->getName()); //Cast a spell on %
|
break;
|
||||||
//we assume that teleport / sacrifice will never be avaliable as random spell
|
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 %
|
||||||
|
isCastingPossible = true;
|
||||||
break;
|
break;
|
||||||
case TELEPORT:
|
case TELEPORT:
|
||||||
consoleMsg = CGI->generaltexth->allTexts[25]; //Teleport Here
|
consoleMsg = CGI->generaltexth->allTexts[25]; //Teleport Here
|
||||||
@ -2975,7 +2978,14 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
|||||||
{
|
{
|
||||||
if(creatureCasting)
|
if(creatureCasting)
|
||||||
{
|
{
|
||||||
giveCommand(BattleAction::MONSTER_SPELL, myNumber, sactive->ID, creatureSpellToCast);
|
if (sp)
|
||||||
|
{
|
||||||
|
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
|
||||||
{
|
{
|
||||||
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3561,7 +3561,9 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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,7 +3635,10 @@ 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;
|
||||||
bsa.attackerID = -1;
|
if (mode == ECastingMode::ENCHANTER_CASTING) //multiple damage spells cast
|
||||||
|
bsa.attackerID = stack->ID;
|
||||||
|
else
|
||||||
|
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user