1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Merge branch 'dispellFixes' into develop

This commit is contained in:
AlexVinS
2015-04-11 11:02:56 +03:00
6 changed files with 100 additions and 13 deletions

View File

@@ -2177,6 +2177,10 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
legalAction = true;
}
break;
case ANY_CREATURE:
if (shere && shere->alive() && isCastingPossibleHere (sactive, shere, myNumber))
legalAction = true;
break;
case HOSTILE_CREATURE_SPELL:
if (shere && shere->alive() && !ourStack && isCastingPossibleHere (sactive, shere, myNumber))
legalAction = true;
@@ -2372,6 +2376,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
break;
case HOSTILE_CREATURE_SPELL:
case FRIENDLY_CREATURE_SPELL:
case ANY_CREATURE:
sp = CGI->spellh->objects[creatureCasting ? creatureSpellToCast : spellToCast->additionalInfo]; //necessary if creature has random Genie spell at same time
consoleMsg = boost::str(boost::format(CGI->generaltexth->allTexts[27]) % sp->name % shere->getName()); //Cast %s on %s
switch (sp->id)
@@ -2442,6 +2447,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
{
switch (illegalAction)
{
case ANY_CREATURE:
case HOSTILE_CREATURE_SPELL:
case FRIENDLY_CREATURE_SPELL:
case RANDOM_GENIE_SPELL:

View File

@@ -106,15 +106,20 @@
"cast": "DISPELL"
},
"levels" : {
"base":{
"range" : "0"
"base":{
"targetModifier":{"smart":true},
"range" : "0"
},
"advanced":{
"targetModifier":{"smart":false}
},
"expert":{
"range" : "X"
}
"expert":{
"targetModifier":{"smart":false},
"range" : "X"
}
},
"flags" : {
"indifferent": true
"positive": true
}
},
"cure" : {

View File

@@ -14,6 +14,31 @@
#include "../NetPacks.h"
#include "../BattleState.h"
///AntimagicMechanics
void AntimagicMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const
{
DefaultSpellMechanics::applyBattle(battle, packet);
for(auto stackID : packet->affectedCres)
{
if(vstd::contains(packet->resisted, stackID))
{
logGlobal->errorStream() << "Resistance to positive spell " << owner->name;
continue;
}
CStack * s = battle->getStack(stackID);
s->popBonuses([&](const Bonus *b) -> bool
{
if(b->source == Bonus::SPELL_EFFECT)
{
return b->sid != owner->id; //effect from this spell
}
return false; //not a spell effect
});
}
}
///ChainLightningMechanics
std::set<const CStack *> ChainLightningMechanics::getAffectedStacks(SpellTargetingContext & ctx) const
{
@@ -142,7 +167,10 @@ void DispellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast *
for(auto stackID : packet->affectedCres)
{
if(vstd::contains(packet->resisted, stackID))
{
logGlobal->errorStream() << "Resistance to DISPELL";
continue;
}
CStack *s = battle->getStack(stackID);
s->popBonuses([&](const Bonus *b) -> bool
@@ -152,6 +180,42 @@ void DispellMechanics::applyBattle(BattleInfo * battle, const BattleSpellCast *
}
}
ESpellCastProblem::ESpellCastProblem DispellMechanics::isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const
{
//DISPELL ignores all immunities, so do not call default
std::stringstream cachingStr;
cachingStr << "source_" << Bonus::SPELL_EFFECT;
if(obj->hasBonus(Selector::sourceType(Bonus::SPELL_EFFECT), cachingStr.str()))
{
return ESpellCastProblem::OK;
}
return ESpellCastProblem::WRONG_SPELL_TARGET;
}
void DispellMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
{
DefaultSpellMechanics::applyBattleEffects(env, parameters, ctx);
if(parameters.spellLvl > 2)
{
//expert DISPELL also removes spell-created obstacles
ObstaclesRemoved packet;
for(const auto obstacle : parameters.cb->obstacles)
{
if(obstacle->obstacleType == CObstacleInstance::FIRE_WALL
|| obstacle->obstacleType == CObstacleInstance::FORCE_FIELD
|| obstacle->obstacleType == CObstacleInstance::LAND_MINE)
packet.obstacles.insert(obstacle->uniqueID);
}
if(!packet.obstacles.empty())
env->sendAndApply(&packet);
}
}
///EarthquakeMechanics
void EarthquakeMechanics::applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const
{
@@ -421,7 +485,7 @@ void RemoveObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * en
ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const
{
// for sacrifice we have to check for 2 targets (one dead to resurrect and one living to destroy)
bool targetExists = false;
bool targetToSacrificeExists = false;
@@ -442,9 +506,9 @@ ESpellCastProblem::ESpellCastProblem SacrificeMechanics::canBeCasted(const CBatt
if(targetExists && targetToSacrificeExists)
break;
}
}
if(targetExists && targetToSacrificeExists)
return ESpellCastProblem::OK;
else

View File

@@ -12,6 +12,14 @@
#include "CDefaultSpellMechanics.h"
class DLL_LINKAGE AntimagicMechanics : public DefaultSpellMechanics
{
public:
AntimagicMechanics(CSpell * s): DefaultSpellMechanics(s){};
void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final;
};
class DLL_LINKAGE ChainLightningMechanics : public DefaultSpellMechanics
{
public:
@@ -40,17 +48,20 @@ class DLL_LINKAGE DispellMechanics : public DefaultSpellMechanics
{
public:
DispellMechanics(CSpell * s): DefaultSpellMechanics(s){};
ESpellCastProblem::ESpellCastProblem isImmuneByStack(const CGHeroInstance * caster, const CStack * obj) const override;
void applyBattle(BattleInfo * battle, const BattleSpellCast * packet) const override final;
protected:
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
};
class DLL_LINKAGE EarthquakeMechanics : public DefaultSpellMechanics
{
public:
EarthquakeMechanics(CSpell * s): DefaultSpellMechanics(s){};
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
protected:
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
};
class DLL_LINKAGE HypnotizeMechanics : public DefaultSpellMechanics
@@ -115,7 +126,7 @@ class DLL_LINKAGE SummonMechanics : public DefaultSpellMechanics
public:
SummonMechanics(CSpell * s): DefaultSpellMechanics(s){};
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
ESpellCastProblem::ESpellCastProblem canBeCasted(const CBattleInfoCallback * cb, PlayerColor player) const override;
protected:
void applyBattleEffects(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters, SpellCastContext & ctx) const override;
};

View File

@@ -216,7 +216,6 @@ bool DefaultSpellMechanics::applyAdventureEffects(const SpellCastEnvironment * e
}
}
void DefaultSpellMechanics::battleCast(const SpellCastEnvironment * env, BattleSpellCastParameters & parameters) const
{
BattleSpellCast sc;

View File

@@ -28,6 +28,8 @@ ISpellMechanics * ISpellMechanics::createMechanics(CSpell * s)
{
switch (s->id)
{
case SpellID::ANTI_MAGIC:
return new AntimagicMechanics(s);
case SpellID::ACID_BREATH_DAMAGE:
return new AcidBreathDamageMechanics(s);
case SpellID::CHAIN_LIGHTNING: