mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
* implemented 206 and 207 from mantis
This commit is contained in:
parent
882ae5a53a
commit
db4ee5844f
@ -124,6 +124,17 @@ int CCallback::getSpellCost(const CSpell * sp, const CGHeroInstance * caster) co
|
|||||||
return sp->costs[caster->getSpellSchoolLevel(sp)];
|
return sp->costs[caster->getSpellSchoolLevel(sp)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CCallback::estimateSpellDamage(const CSpell * sp) const
|
||||||
|
{
|
||||||
|
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||||
|
|
||||||
|
if(!gs->curB)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
|
||||||
|
return gs->curB->calculateSpellDmg(sp, ourHero, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
int CCallback::howManyTowns() const
|
int CCallback::howManyTowns() const
|
||||||
{
|
{
|
||||||
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
|
||||||
@ -640,6 +651,14 @@ ui8 CCallback::battleGetSiegeLevel()
|
|||||||
return gs->curB->siege;
|
return gs->curB->siege;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CGHeroInstance * CCallback::battleGetFightingHero(ui8 side) const
|
||||||
|
{
|
||||||
|
if(!gs->curB)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return gs->curB->heroes[side];
|
||||||
|
}
|
||||||
|
|
||||||
void CCallback::swapGarrisonHero( const CGTownInstance *town )
|
void CCallback::swapGarrisonHero( const CGTownInstance *town )
|
||||||
{
|
{
|
||||||
if(town->tempOwner != player) return;
|
if(town->tempOwner != player) return;
|
||||||
|
@ -131,6 +131,7 @@ public:
|
|||||||
virtual const StartInfo * getStartInfo()const =0;
|
virtual const StartInfo * getStartInfo()const =0;
|
||||||
virtual const CMapHeader * getMapHeader()const =0;
|
virtual const CMapHeader * getMapHeader()const =0;
|
||||||
virtual int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const =0; //when called during battle, takes into account creatures' spell cost reduction
|
virtual int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const =0; //when called during battle, takes into account creatures' spell cost reduction
|
||||||
|
virtual int estimateSpellDamage(const CSpell * sp) const =0; //estimates damage of given spell; returns 0 if spell causes no dmg
|
||||||
|
|
||||||
//hero
|
//hero
|
||||||
virtual int howManyHeroes(bool includeGarrisoned = true)const =0;
|
virtual int howManyHeroes(bool includeGarrisoned = true)const =0;
|
||||||
@ -188,6 +189,7 @@ public:
|
|||||||
virtual int battleGetWallUnderHex(int hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
virtual int battleGetWallUnderHex(int hex)=0; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||||
virtual std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID)=0; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
virtual std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID)=0; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||||
virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
virtual ui8 battleGetSiegeLevel()=0; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||||
|
virtual const CGHeroInstance * battleGetFightingHero(ui8 side) const =0; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HeroMoveDetails
|
struct HeroMoveDetails
|
||||||
@ -260,6 +262,7 @@ public:
|
|||||||
const StartInfo * getStartInfo() const;
|
const StartInfo * getStartInfo() const;
|
||||||
const CMapHeader * getMapHeader()const ;
|
const CMapHeader * getMapHeader()const ;
|
||||||
int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
|
int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
|
||||||
|
int estimateSpellDamage(const CSpell * sp) const; //estimates damage of given spell; returns 0 if spell causes no dmg
|
||||||
|
|
||||||
std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos) const;
|
std::vector < const CGObjectInstance * > getBlockingObjs(int3 pos) const;
|
||||||
std::vector < const CGObjectInstance * > getVisitableObjs(int3 pos) const;
|
std::vector < const CGObjectInstance * > getVisitableObjs(int3 pos) const;
|
||||||
@ -299,6 +302,7 @@ public:
|
|||||||
int battleGetWallUnderHex(int hex); //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
int battleGetWallUnderHex(int hex); //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||||
std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID); //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
std::pair<ui32, ui32> battleEstimateDamage(int attackerID, int defenderID); //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||||
ui8 battleGetSiegeLevel(); //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
ui8 battleGetSiegeLevel(); //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
|
||||||
|
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //returns hero corresponding ot given side (0 - attacker, 1 - defender)
|
||||||
|
|
||||||
//XXX hmmm _tmain on _GNUC_ wtf?
|
//XXX hmmm _tmain on _GNUC_ wtf?
|
||||||
//friends
|
//friends
|
||||||
|
@ -2579,6 +2579,29 @@ void CBattleInterface::spellCast(SpellCast * sc)
|
|||||||
int tile = LOCPLINT->cb->battleGetStackByID(sc->resisted[j])->position;
|
int tile = LOCPLINT->cb->battleGetStackByID(sc->resisted[j])->position;
|
||||||
displayEffect(78, tile);
|
displayEffect(78, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//displaying message in console
|
||||||
|
if(sc->affectedCres.size() == 1)
|
||||||
|
{
|
||||||
|
std::string text = CGI->generaltexth->allTexts[195];
|
||||||
|
boost::algorithm::replace_first(text, "%s", LOCPLINT->cb->battleGetFightingHero(sc->side)->name);
|
||||||
|
boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id].name);
|
||||||
|
boost::algorithm::replace_first(text, "%s", LOCPLINT->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->creature->namePl );
|
||||||
|
console->addText(text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string text = CGI->generaltexth->allTexts[196];
|
||||||
|
boost::algorithm::replace_first(text, "%s", LOCPLINT->cb->battleGetFightingHero(sc->side)->name);
|
||||||
|
boost::algorithm::replace_first(text, "%s", CGI->spellh->spells[sc->id].name);
|
||||||
|
console->addText(text);
|
||||||
|
}
|
||||||
|
if(sc->dmgToDisplay != 0)
|
||||||
|
{
|
||||||
|
std::string dmgInfo = CGI->generaltexth->allTexts[343].substr(1, CGI->generaltexth->allTexts[343].size() - 1);
|
||||||
|
boost::algorithm::replace_first(dmgInfo, "%d", boost::lexical_cast<std::string>(sc->dmgToDisplay));
|
||||||
|
console->addText(dmgInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
|
void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
|
||||||
|
@ -677,9 +677,19 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
|
|||||||
{
|
{
|
||||||
if(down && mySpell != -1)
|
if(down && mySpell != -1)
|
||||||
{
|
{
|
||||||
|
std::string dmgInfo;
|
||||||
|
int causedDmg = LOCPLINT->cb->estimateSpellDamage( &CGI->spellh->spells[mySpell] );
|
||||||
|
if(causedDmg == 0)
|
||||||
|
dmgInfo = "";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dmgInfo = CGI->generaltexth->allTexts[343];
|
||||||
|
boost::algorithm::replace_first(dmgInfo, "%d", boost::lexical_cast<std::string>(causedDmg));
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Surface *spellBox = CMessage::drawBoxTextBitmapSub(
|
SDL_Surface *spellBox = CMessage::drawBoxTextBitmapSub(
|
||||||
LOCPLINT->playerID,
|
LOCPLINT->playerID,
|
||||||
CGI->spellh->spells[mySpell].descriptions[0], this->owner->spells->ourImages[mySpell].bitmap,
|
CGI->spellh->spells[mySpell].descriptions[0] + dmgInfo, this->owner->spells->ourImages[mySpell].bitmap,
|
||||||
CGI->spellh->spells[mySpell].name,30,30);
|
CGI->spellh->spells[mySpell].name,30,30);
|
||||||
CInfoPopup *vinya = new CInfoPopup(spellBox, true);
|
CInfoPopup *vinya = new CInfoPopup(spellBox, true);
|
||||||
GH.pushInt(vinya);
|
GH.pushInt(vinya);
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/thread/shared_mutex.hpp>
|
#include <boost/thread/shared_mutex.hpp>
|
||||||
|
#include <boost/assign/list_of.hpp>
|
||||||
#include "RegisterTypes.cpp"
|
#include "RegisterTypes.cpp"
|
||||||
|
|
||||||
boost::rand48 ran;
|
boost::rand48 ran;
|
||||||
@ -2739,6 +2740,94 @@ std::pair<const CStack *, int> BattleInfo::getNearestStack(const CStack * closes
|
|||||||
return std::make_pair<const CStack * , int>(NULL, -1);
|
return std::make_pair<const CStack * , int>(NULL, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui32 BattleInfo::calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const
|
||||||
|
{
|
||||||
|
ui32 ret = 0; //value to return
|
||||||
|
|
||||||
|
//15 - magic arrows, 16 - ice bolt, 17 - lightning bolt, 18 - implosion, 20 - frost ring, 21 - fireball, 22 - inferno, 23 - meteor shower,
|
||||||
|
//24 - death ripple, 25 - destroy undead, 26 - armageddon
|
||||||
|
static std::map <int, int> dmgMultipliers = boost::assign::map_list_of(15, 10)(16, 20)(17, 25)(18, 75)(20, 10)(21, 10)(22, 10)(23, 10)(24, 5)(25, 10)(26, 50);
|
||||||
|
|
||||||
|
//check if spell really does damage - if not, return 0
|
||||||
|
if(dmgMultipliers.find(sp->id) == dmgMultipliers.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = caster->getPrimSkillLevel(2) * dmgMultipliers[sp->id] + sp->powers[caster->getSpellSchoolLevel(sp)];
|
||||||
|
|
||||||
|
//applying sorcerery secondary skill
|
||||||
|
switch(caster->getSecSkillLevel(25))
|
||||||
|
{
|
||||||
|
case 1: //basic
|
||||||
|
ret *= 1.05f;
|
||||||
|
break;
|
||||||
|
case 2: //advanced
|
||||||
|
ret *= 1.1f;
|
||||||
|
break;
|
||||||
|
case 3: //expert
|
||||||
|
ret *= 1.15f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//applying hero bonuses
|
||||||
|
if(sp->air && caster->valOfBonuses(HeroBonus::AIR_SPELL_DMG_PREMY) != 0)
|
||||||
|
{
|
||||||
|
ret *= (100.0f + caster->valOfBonuses(HeroBonus::AIR_SPELL_DMG_PREMY) / 100.0f);
|
||||||
|
}
|
||||||
|
else if(sp->fire && caster->valOfBonuses(HeroBonus::FIRE_SPELL_DMG_PREMY) != 0)
|
||||||
|
{
|
||||||
|
ret *= (100.0f + caster->valOfBonuses(HeroBonus::FIRE_SPELL_DMG_PREMY) / 100.0f);
|
||||||
|
}
|
||||||
|
else if(sp->water && caster->valOfBonuses(HeroBonus::WATER_SPELL_DMG_PREMY) != 0)
|
||||||
|
{
|
||||||
|
ret *= (100.0f + caster->valOfBonuses(HeroBonus::WATER_SPELL_DMG_PREMY) / 100.0f);
|
||||||
|
}
|
||||||
|
else if(sp->earth && caster->valOfBonuses(HeroBonus::EARTH_SPELL_DMG_PREMY) != 0)
|
||||||
|
{
|
||||||
|
ret *= (100.0f + caster->valOfBonuses(HeroBonus::EARTH_SPELL_DMG_PREMY) / 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//affected creature-specific part
|
||||||
|
if(affectedCreature)
|
||||||
|
{
|
||||||
|
//applying protections - when spell has more then one elements, only one protection should be applied (I think)
|
||||||
|
if(sp->air && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 0)) //air spell & protection from air
|
||||||
|
{
|
||||||
|
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 0);
|
||||||
|
ret /= 100;
|
||||||
|
}
|
||||||
|
else if(sp->fire && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 1)) //fire spell & protection from fire
|
||||||
|
{
|
||||||
|
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 1);
|
||||||
|
ret /= 100;
|
||||||
|
}
|
||||||
|
else if(sp->water && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 2)) //water spell & protection from water
|
||||||
|
{
|
||||||
|
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 2);
|
||||||
|
ret /= 100;
|
||||||
|
}
|
||||||
|
else if (sp->earth && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 3)) //earth spell & protection from earth
|
||||||
|
{
|
||||||
|
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 3);
|
||||||
|
ret /= 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
//general spell dmg reduction
|
||||||
|
if(sp->air && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, -1)) //air spell & protection from air
|
||||||
|
{
|
||||||
|
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, -1);
|
||||||
|
ret /= 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
//dmg increasing
|
||||||
|
if( affectedCreature->hasFeatureOfType(StackFeature::MORE_DAMAGE_FROM_SPELL, sp->id) )
|
||||||
|
{
|
||||||
|
ret *= 100 + affectedCreature->valOfFeatures(StackFeature::MORE_DAMAGE_FROM_SPELL, sp->id);
|
||||||
|
ret /= 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool CGameState::battleCanShoot(int ID, int dest)
|
bool CGameState::battleCanShoot(int ID, int dest)
|
||||||
{
|
{
|
||||||
if(!curB)
|
if(!curB)
|
||||||
|
@ -164,6 +164,7 @@ struct DLL_EXPORT BattleInfo
|
|||||||
ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
|
ui32 getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
|
||||||
int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
int hexToWallPart(int hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||||
std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
|
std::pair<const CStack *, int> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
|
||||||
|
ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) const; //calculates damage inflicted by spell
|
||||||
};
|
};
|
||||||
|
|
||||||
class DLL_EXPORT CStack
|
class DLL_EXPORT CStack
|
||||||
|
@ -933,6 +933,7 @@ struct SpellCast : public CPackForClient//3009
|
|||||||
DLL_EXPORT void applyGs(CGameState *gs);
|
DLL_EXPORT void applyGs(CGameState *gs);
|
||||||
void applyCl(CClient *cl);
|
void applyCl(CClient *cl);
|
||||||
|
|
||||||
|
si32 dmgToDisplay; //this amount will be displayed as amount of damage dealt by spell
|
||||||
ui8 side; //which hero did cast spell: 0 - attacker, 1 - defender
|
ui8 side; //which hero did cast spell: 0 - attacker, 1 - defender
|
||||||
ui32 id; //id of spell
|
ui32 id; //id of spell
|
||||||
ui8 skill; //caster's skill level
|
ui8 skill; //caster's skill level
|
||||||
@ -941,7 +942,7 @@ struct SpellCast : public CPackForClient//3009
|
|||||||
std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
|
std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & side & id & skill & tile & resisted & affectedCres;
|
h & dmgToDisplay & side & id & skill & tile & resisted & affectedCres;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2840,87 +2840,6 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature)
|
|
||||||
{
|
|
||||||
ui32 ret = 0; //value to return
|
|
||||||
|
|
||||||
//15 - magic arrows, 16 - ice bolt, 17 - lightning bolt, 18 - implosion, 20 - frost ring, 21 - fireball, 22 - inferno, 23 - meteor shower,
|
|
||||||
//24 - death ripple, 25 - destroy undead, 26 - armageddon
|
|
||||||
static std::map <int, int> dmgMultipliers = boost::assign::map_list_of(15, 10)(16, 20)(17, 25)(18, 75)(20, 10)(21, 10)(22, 10)(23, 10)(24, 5)(25, 10)(26, 50);
|
|
||||||
|
|
||||||
ret = caster->getPrimSkillLevel(2) * dmgMultipliers[sp->id] + sp->powers[caster->getSpellSchoolLevel(sp)];
|
|
||||||
|
|
||||||
//applying sorcerery secondary skill
|
|
||||||
switch(caster->getSecSkillLevel(25))
|
|
||||||
{
|
|
||||||
case 1: //basic
|
|
||||||
ret *= 1.05f;
|
|
||||||
break;
|
|
||||||
case 2: //advanced
|
|
||||||
ret *= 1.1f;
|
|
||||||
break;
|
|
||||||
case 3: //expert
|
|
||||||
ret *= 1.15f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//applying hero bonuses
|
|
||||||
if(sp->air && caster->valOfBonuses(HeroBonus::AIR_SPELL_DMG_PREMY) != 0)
|
|
||||||
{
|
|
||||||
ret *= (100.0f + caster->valOfBonuses(HeroBonus::AIR_SPELL_DMG_PREMY) / 100.0f);
|
|
||||||
}
|
|
||||||
else if(sp->fire && caster->valOfBonuses(HeroBonus::FIRE_SPELL_DMG_PREMY) != 0)
|
|
||||||
{
|
|
||||||
ret *= (100.0f + caster->valOfBonuses(HeroBonus::FIRE_SPELL_DMG_PREMY) / 100.0f);
|
|
||||||
}
|
|
||||||
else if(sp->water && caster->valOfBonuses(HeroBonus::WATER_SPELL_DMG_PREMY) != 0)
|
|
||||||
{
|
|
||||||
ret *= (100.0f + caster->valOfBonuses(HeroBonus::WATER_SPELL_DMG_PREMY) / 100.0f);
|
|
||||||
}
|
|
||||||
else if(sp->earth && caster->valOfBonuses(HeroBonus::EARTH_SPELL_DMG_PREMY) != 0)
|
|
||||||
{
|
|
||||||
ret *= (100.0f + caster->valOfBonuses(HeroBonus::EARTH_SPELL_DMG_PREMY) / 100.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
//applying protections - when spell has more then one elements, only one protection should be applied (I think)
|
|
||||||
if(sp->air && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 0)) //air spell & protection from air
|
|
||||||
{
|
|
||||||
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 0);
|
|
||||||
ret /= 100;
|
|
||||||
}
|
|
||||||
else if(sp->fire && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 1)) //fire spell & protection from fire
|
|
||||||
{
|
|
||||||
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 1);
|
|
||||||
ret /= 100;
|
|
||||||
}
|
|
||||||
else if(sp->water && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 2)) //water spell & protection from water
|
|
||||||
{
|
|
||||||
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 2);
|
|
||||||
ret /= 100;
|
|
||||||
}
|
|
||||||
else if (sp->earth && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, 3)) //earth spell & protection from earth
|
|
||||||
{
|
|
||||||
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, 3);
|
|
||||||
ret /= 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
//general spell dmg reduction
|
|
||||||
if(sp->air && affectedCreature->hasFeatureOfType(StackFeature::SPELL_DAMAGE_REDUCTION, -1)) //air spell & protection from air
|
|
||||||
{
|
|
||||||
ret *= affectedCreature->valOfFeatures(StackFeature::SPELL_DAMAGE_REDUCTION, -1);
|
|
||||||
ret /= 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
//dmg increasing
|
|
||||||
if( affectedCreature->hasFeatureOfType(StackFeature::MORE_DAMAGE_FROM_SPELL, sp->id) )
|
|
||||||
{
|
|
||||||
ret *= 100 + affectedCreature->valOfFeatures(StackFeature::MORE_DAMAGE_FROM_SPELL, sp->id);
|
|
||||||
ret /= 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack)
|
static ui32 calculateHealedHP(const CGHeroInstance * caster, const CSpell * spell, const CStack * stack)
|
||||||
{
|
{
|
||||||
switch(spell->id)
|
switch(spell->id)
|
||||||
@ -3057,6 +2976,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
sc.id = ba.additionalInfo;
|
sc.id = ba.additionalInfo;
|
||||||
sc.skill = skill;
|
sc.skill = skill;
|
||||||
sc.tile = ba.destinationTile;
|
sc.tile = ba.destinationTile;
|
||||||
|
sc.dmgToDisplay = 0;
|
||||||
|
|
||||||
//calculating affected creatures for all spells
|
//calculating affected creatures for all spells
|
||||||
std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(s, h, ba.destinationTile);
|
std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(s, h, ba.destinationTile);
|
||||||
@ -3068,6 +2988,14 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
//checking if creatures resist
|
//checking if creatures resist
|
||||||
sc.resisted = calculateResistedStacks(s, h, secondHero, attackedCres);
|
sc.resisted = calculateResistedStacks(s, h, secondHero, attackedCres);
|
||||||
|
|
||||||
|
//calculating dmg to display
|
||||||
|
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
|
||||||
|
{
|
||||||
|
if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
|
||||||
|
continue;
|
||||||
|
sc.dmgToDisplay += gs->curB->calculateSpellDmg(s, h, *it);
|
||||||
|
}
|
||||||
|
|
||||||
sendAndApply(&sc);
|
sendAndApply(&sc);
|
||||||
|
|
||||||
//applying effects
|
//applying effects
|
||||||
@ -3094,7 +3022,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
|
|||||||
BattleStackAttacked bsa;
|
BattleStackAttacked bsa;
|
||||||
bsa.flags |= 2;
|
bsa.flags |= 2;
|
||||||
bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim;
|
bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim;
|
||||||
bsa.damageAmount = calculateSpellDmg(s, h, *it);
|
bsa.damageAmount = gs->curB->calculateSpellDmg(s, h, *it);
|
||||||
bsa.stackAttacked = (*it)->ID;
|
bsa.stackAttacked = (*it)->ID;
|
||||||
bsa.attackerID = -1;
|
bsa.attackerID = -1;
|
||||||
prepareAttacked(bsa,*it);
|
prepareAttacked(bsa,*it);
|
||||||
|
Loading…
Reference in New Issue
Block a user