1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

* fixed crash on calculating dmg dealt by stack under Curse

* fixed crash on sea battles (obstacles data got corrupted during conversion)
* fixed crash when StupidAI had a catapult
* minor fixes and refactorings (typename for bonus list under shared ptr)
This commit is contained in:
Michał W. Urbańczyk 2011-09-06 13:59:26 +00:00
parent bb1bdcb0a7
commit 9621cbcaa7
12 changed files with 87 additions and 65 deletions

View File

@ -250,6 +250,12 @@ BattleAction CStupidAI::goTowards(const CStack * stack, THex hex)
dists = cb->battleGetDistances(stack, realDest, predecessors);
std::vector<THex> avHexes = cb->battleGetAvailableHexes(stack, false);
if(!avHexes.size())
{
print("goTowards: Stack cannot move! That's " + stack->nodeName());
return BattleAction::makeDefend(stack);
}
while(1)
{
assert(realDest.isValid());

View File

@ -3179,7 +3179,7 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
boost::algorithm::replace_first(text, "%s", curInt->cb->battleGetStackByID(*sc->affectedCres.begin())->type->nameSing);
}
//The %s shrivel with age, and lose %d hit points."
boost::shared_ptr<BonusList> bl = curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getBonuses(Selector::type(Bonus::STACK_HEALTH));
TBonusListPtr bl = curInt->cb->battleGetStackByID(*sc->affectedCres.begin(), false)->getBonuses(Selector::type(Bonus::STACK_HEALTH));
bl->remove_if(Selector::source(Bonus::SPELL_EFFECT, 75));
boost::algorithm::replace_first(text, "%d", boost::lexical_cast<std::string>(bl->totalValue()/2));
}
@ -3542,7 +3542,7 @@ void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
int yAdd = 260 + ((stack->attackerOwned || moveInside) ? 0 : -15);
//blitting amount background box
SDL_Surface *amountBG = NULL;
boost::shared_ptr<BonusList> spellEffects = stack->getSpellBonuses();
TBonusListPtr spellEffects = stack->getSpellBonuses();
if(!spellEffects->size())
{
amountBG = amountNormal;

View File

@ -44,11 +44,11 @@
extern SDL_Surface * screen;
using namespace boost::assign;
const boost::shared_ptr<BonusList> CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const std::string &cachingStr /*= ""*/) const
const TBonusListPtr CHeroWithMaybePickedArtifact::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const std::string &cachingStr /*= ""*/) const
{
boost::shared_ptr<BonusList> out(new BonusList);
boost::shared_ptr<BonusList> heroBonuses = hero->getAllBonuses(selector, limit, hero);
boost::shared_ptr<BonusList> bonusesFromPickedUpArtifact;
TBonusListPtr out(new BonusList);
TBonusListPtr heroBonuses = hero->getAllBonuses(selector, limit, hero);
TBonusListPtr bonusesFromPickedUpArtifact;
CArtifactsOfHero::SCommonPart *cp = cww->artSets.size() ? cww->artSets.front()->commonInfo : NULL;
if(cp && cp->src.art && cp->src.valid() && cp->src.AOH && cp->src.AOH->getHero() == hero)
@ -56,7 +56,7 @@ const boost::shared_ptr<BonusList> CHeroWithMaybePickedArtifact::getAllBonuses(c
bonusesFromPickedUpArtifact = cp->src.art->getAllBonuses(selector, limit, hero);
}
else
bonusesFromPickedUpArtifact = boost::shared_ptr<BonusList>(new BonusList);
bonusesFromPickedUpArtifact = TBonusListPtr(new BonusList);
BOOST_FOREACH(Bonus *b, *bonusesFromPickedUpArtifact)
*heroBonuses -= b;

View File

@ -46,7 +46,7 @@ public:
CWindowWithArtifacts *cww;
CHeroWithMaybePickedArtifact(CWindowWithArtifacts *Cww, const CGHeroInstance *Hero);
const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const OVERRIDE;
const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const OVERRIDE;
};
class CHeroWindow: public CWindowWithGarrison, public CWindowWithArtifacts

View File

@ -17,7 +17,7 @@
{ "id": 56, "defname": "OBBHS02.DEF", "blockmap": "XXLNX", "terrains": "1100000000000000000000100", "shift_x": -8, "shift_y": 0 },
{ "id": 57, "defname": "OBBHS03.DEF", "blockmap": "LXXX", "terrains": "1111100000000000000000100", "shift_x": -8, "shift_y": 0 },
{ "id": 91, "defname": "OBBHS04.DEF", "blockmap": "XXLNXX", "terrains": "1100000000000000000000000", "shift_x": -40, "shift_y": -20 },
{ "id": 58, "defname": "OBBHS11A.DEF", "blockmap": "XXXLNXXX", "terrains": "100000000000000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 58, "defname": "OBBHS11A.DEF", "blockmap": "XXXLNXXX", "terrains": "1100000000000000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 59, "defname": "OBBHS12B.DEF", "blockmap": "NXXLNXX", "terrains": "1100000000000000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 60, "defname": "OBBHS14B.DEF", "blockmap": "NXLNXX", "terrains": "1111100000000000000000100", "shift_x": 36, "shift_y": 0 },
{ "id": 92, "defname": "OBBHS16A.DEF", "blockmap": "XLNXX", "terrains": "1100000000000000000000000", "shift_x": -8, "shift_y": -28 },
@ -34,7 +34,7 @@
{ "id": 8, "defname": "OBDRK03.DEF", "blockmap": "X", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": -8 },
{ "id": 9, "defname": "OBDRK04.DEF", "blockmap": "LXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 },
{ "id": 10, "defname": "OBDSH01.DEF", "blockmap": "LXX", "terrains": "1111110000000000000000100", "shift_x": -8, "shift_y": 0 },
{ "id": 93, "defname": "OBDSM01.DEF", "blockmap": "NNXXXLNNXXXLNNXX", "terrains": "00000000000000000000000", "shift_x": 36, "shift_y": 0 },
{ "id": 93, "defname": "OBDSM01.DEF", "blockmap": "NNXXXLNNXXXLNNXX", "terrains": "1100000000000000000000000", "shift_x": 36, "shift_y": 0 },
{ "id": 17, "defname": "OBDSM02.DEF", "blockmap": "XXLNX", "terrains": "1111100000000000000000100", "shift_x": -9, "shift_y": -2 },
{ "id": 18, "defname": "OBDSS17.DEF", "blockmap": "XXLNXXX", "terrains": "1111100000000000000000100", "shift_x": -8, "shift_y": 0 },
{ "id": 11, "defname": "OBDTF03.DEF", "blockmap": "XX", "terrains": "1111100000000000000001100", "shift_x": 14, "shift_y": 0 },
@ -46,17 +46,17 @@
{ "id": 67, "defname": "OBEFS01.DEF", "blockmap": "XX", "terrains": "0000000000000000000100000", "shift_x": 14, "shift_y": 0 },
{ "id": 68, "defname": "OBEFS02.DEF", "blockmap": "NXLXXX", "terrains": "0000000000000000000100000", "shift_x": -8, "shift_y": 0 },
{ "id": 69, "defname": "OBEFS03.DEF", "blockmap": "LNXX", "terrains": "0000000000000000000100000", "shift_x": 0, "shift_y": 0 },
{ "id": 70, "defname": "OBEFS04.DEF", "blockmap": "NNXXXLNXXX", "terrains": "000000000000000000100000", "shift_x": -8, "shift_y": 0 },
{ "id": 70, "defname": "OBEFS04.DEF", "blockmap": "NNXXXLNXXX", "terrains": "0000000000000000000100000", "shift_x": -8, "shift_y": 0 },
{ "id": 79, "defname": "OBFFS00.DEF", "blockmap": "X", "terrains": "0000000000000100000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 80, "defname": "OBFFS01.DEF", "blockmap": "XX", "terrains": "0000000000000100000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 81, "defname": "OBFFS02.DEF", "blockmap": "NXLXXX", "terrains": "0000000000000100000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 82, "defname": "OBFFS03.DEF", "blockmap": "XXLNXXX", "terrains": "0000000000000100000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 83, "defname": "OBFFS04.DEF", "blockmap": "XXXLXXXX", "terrains": "000000000000100000000000", "shift_x": -8, "shift_y": -42 },
{ "id": 83, "defname": "OBFFS04.DEF", "blockmap": "XXXLXXXX", "terrains": "0000000000000100000000000", "shift_x": -8, "shift_y": -42 },
{ "id": 19, "defname": "OBGLG01.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 94, "defname": "OBGRK01.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": -42 },
{ "id": 23, "defname": "OBGRK02.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 20, "defname": "OBGRS02.DEF", "blockmap": "NXX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 22, "defname": "OBGRS01.DEF", "blockmap": "XXXXLNXXXX", "terrains": "000011010001000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 22, "defname": "OBGRS01.DEF", "blockmap": "XXXXLNXXXX", "terrains": "0000011010001000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 35, "defname": "OBGRS03.DEF", "blockmap": "XXXXXXX", "terrains": "1111111010000000000000100", "shift_x": 0, "shift_y": 0 },
{ "id": 21, "defname": "OBGST01.DEF", "blockmap": "X", "terrains": "1111111010000000000000100", "shift_x": 14, "shift_y": 0 },
{ "id": 61, "defname": "OBHGS00.DEF", "blockmap": "X", "terrains": "0000000000000000010000000", "shift_x": 14, "shift_y": 0 },
@ -67,23 +67,23 @@
{ "id": 75, "defname": "OBLPS00.DEF", "blockmap": "X", "terrains": "0000000000000000100000000", "shift_x": 14, "shift_y": 0 },
{ "id": 76, "defname": "OBLPS01.DEF", "blockmap": "XX", "terrains": "0000000000000000100000000", "shift_x": 14, "shift_y": 0 },
{ "id": 77, "defname": "OBLPS02.DEF", "blockmap": "NXXLNX", "terrains": "0000000000000000100000000", "shift_x": 36, "shift_y": 0 },
{ "id": 78, "defname": "OBLPS03.DEF", "blockmap": "XXXXLNXXXX", "terrains": "000000000000000100000000", "shift_x": -8, "shift_y": 0 },
{ "id": 78, "defname": "OBLPS03.DEF", "blockmap": "XXXXLNXXXX", "terrains": "0000000000000000100000000", "shift_x": -8, "shift_y": 0 },
{ "id": 48, "defname": "OBLVS01.DEF", "blockmap": "XXLNNX", "terrains": "0000000100000000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 49, "defname": "OBLVS02.DEF", "blockmap": "XXXLXXX", "terrains": "0000000100000000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 50, "defname": "OBLVS03.DEF", "blockmap": "XXXXLNXXX", "terrains": "000000100000000000000000", "shift_x": -30, "shift_y": 0 },
{ "id": 50, "defname": "OBLVS03.DEF", "blockmap": "XXXXLNXXX", "terrains": "0000000100000000000000000", "shift_x": -30, "shift_y": 0 },
{ "id": 51, "defname": "OBLVS04.DEF", "blockmap": "XXX", "terrains": "0000000100000000000000000", "shift_x": 14, "shift_y": -42 },
{ "id": 52, "defname": "OBLVS09.DEF", "blockmap": "XXLNXXLNNXX", "terrains": "000000100000000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 53, "defname": "OBLVS17.DEF", "blockmap": "NNXLXXXX", "terrains": "000000100000000000000000", "shift_x": -30, "shift_y": 0 },
{ "id": 54, "defname": "OBLVS22.DEF", "blockmap": "XXXLXXXX", "terrains": "000000100000000000000000", "shift_x": -30, "shift_y": 0 },
{ "id": 52, "defname": "OBLVS09.DEF", "blockmap": "XXLNXXLNNXX", "terrains": "0000000100000000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 53, "defname": "OBLVS17.DEF", "blockmap": "NNXLXXXX", "terrains": "0000000100000000000000000", "shift_x": -30, "shift_y": 0 },
{ "id": 54, "defname": "OBLVS22.DEF", "blockmap": "XXXLXXXX", "terrains": "0000000100000000000000000", "shift_x": -30, "shift_y": 0 },
{ "id": 88, "defname": "OBMCS00.DEF", "blockmap": "X", "terrains": "0000000000000001000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 89, "defname": "OBMCS01.DEF", "blockmap": "XLNX", "terrains": "0000000000000001000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 90, "defname": "OBMCS02.DEF", "blockmap": "NXXLXX", "terrains": "0000000000000001000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 41, "defname": "OBRGS01.DEF", "blockmap": "XLXX", "terrains": "1111100000000000000001100", "shift_x": -8, "shift_y": 0 },
{ "id": 40, "defname": "OBRGS02.DEF", "blockmap": "NXXLNXXX", "terrains": "111100000000000000001100", "shift_x": 14, "shift_y": 0 },
{ "id": 40, "defname": "OBRGS02.DEF", "blockmap": "NXXLNXXX", "terrains": "1111100000000000000001100", "shift_x": 14, "shift_y": 0 },
{ "id": 42, "defname": "OBRGS03.DEF", "blockmap": "XXLNX", "terrains": "1111100000000000000001100", "shift_x": -8, "shift_y": 0 },
{ "id": 43, "defname": "OBRGS04.DEF", "blockmap": "XXLX", "terrains": "1111100000000000000001100", "shift_x": -30, "shift_y": 0 },
{ "id": 44, "defname": "OBRGS05.DEF", "blockmap": "NXLXX", "terrains": "1111100000000000000001100", "shift_x": -30, "shift_y": 0 },
{ "id": 16, "defname": "OBRGS06.DEF", "blockmap": "NXXXXXXLNNNNNNNXLNNNNNNNNX", "terrains": "11100000000000000001100", "shift_x": -30, "shift_y": -30 },
{ "id": 16, "defname": "OBRGS06.DEF", "blockmap": "NXXXXXXLNNNNNNNXLNNNNNNNNX", "terrains": "1111100000000000000001100", "shift_x": -30, "shift_y": -30 },
{ "id": 84, "defname": "OBRLS00.DEF", "blockmap": "X", "terrains": "0000000000000010000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 85, "defname": "OBRLS01.DEF", "blockmap": "XX", "terrains": "0000000000000010000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 86, "defname": "OBRLS02.DEF", "blockmap": "XXX", "terrains": "0000000000000010000000000", "shift_x": 14, "shift_y": 0 },
@ -98,16 +98,16 @@
{ "id": 29, "defname": "OBSNS06.DEF", "blockmap": "LNXX", "terrains": "0000000001100000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 30, "defname": "OBSNS07.DEF", "blockmap": "XX", "terrains": "0000000001100000000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 31, "defname": "OBSNS08.DEF", "blockmap": "LNXXX", "terrains": "0000000001100000000000000", "shift_x": 36, "shift_y": 0 },
{ "id": 32, "defname": "OBSNS09.DEF", "blockmap": "XXXXLNNXXXX", "terrains": "000000001100000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 33, "defname": "OBSNS10.DEF", "blockmap": "XXLNXLNXXLNNXXX", "terrains": "000000001100000000000000", "shift_x": -30, "shift_y": -30 },
{ "id": 32, "defname": "OBSNS09.DEF", "blockmap": "XXXXLNNXXXX", "terrains": "0000000001100000000000000", "shift_x": -8, "shift_y": 0 },
{ "id": 33, "defname": "OBSNS10.DEF", "blockmap": "XXLNXLNXXLNNXXX", "terrains": "0000000001100000000000000", "shift_x": -30, "shift_y": -30 },
{ "id": 45, "defname": "OBSUS01.DEF", "blockmap": "XXLXXX", "terrains": "0000000000010000000000000", "shift_x": -8, "shift_y": -42 },
{ "id": 46, "defname": "OBSUS02.DEF", "blockmap": "XXX", "terrains": "0000000000010000000000000", "shift_x": 14, "shift_y": -42 },
{ "id": 47, "defname": "OBSUS11B.DEF", "blockmap": "XXXLXXXX", "terrains": "000000000010000000000000", "shift_x": -9, "shift_y": -43 },
{ "id": 47, "defname": "OBSUS11B.DEF", "blockmap": "XXXLXXXX", "terrains": "0000000000010000000000000", "shift_x": -9, "shift_y": -43 },
{ "id": 34, "defname": "OBSWS01.DEF", "blockmap": "LNX", "terrains": "0000000000001000000000000", "shift_x": 36, "shift_y": 0 },
{ "id": 95, "defname": "OBSWS02.DEF", "blockmap": "XXXXXXX", "terrains": "0000000000001000000000000", "shift_x": -8, "shift_y": -42 },
{ "id": 36, "defname": "OBSWS03.DEF", "blockmap": "XX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 37, "defname": "OBSWS04.DEF", "blockmap": "XXX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 },
{ "id": 38, "defname": "OBSWS11B.DEF", "blockmap": "XXXXLXXXX", "terrains": "000000000001000000000000", "shift_x": -30, "shift_y": -40 },
{ "id": 38, "defname": "OBSWS11B.DEF", "blockmap": "XXXXLXXXX", "terrains": "0000000000001000000000000", "shift_x": -30, "shift_y": -40 },
{ "id": 39, "defname": "OBSWS13A.DEF", "blockmap": "XXXXLXX", "terrains": "0000000000001000000000000", "shift_x": 14, "shift_y": 0 }
]
}

View File

@ -592,9 +592,15 @@ TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* d
{
multBonus *= float(defender->valOfBonuses(Bonus::GENERAL_DAMAGE_REDUCTION, 1)) / 100.0f;
}
if(attacker->getEffect(42)) //curse handling (partial, the rest is below)
TBonusListPtr curseEffects = attacker->getBonuses(Selector::type(Bonus::ALWAYS_MINIMUM_DAMAGE)); //attacker->getEffect(42);
TBonusListPtr blessEffects = attacker->getBonuses(Selector::type(Bonus::ALWAYS_MAXIMUM_DAMAGE)); //attacker->getEffect(43);
int curseBlessAdditiveModifier = blessEffects->totalValue() - curseEffects->totalValue();
double curseMultiplicativePenalty = curseEffects->size() ? (*std::max_element(curseEffects->begin(), curseEffects->end(), &Bonus::compareByAdditionalInfo))->additionalInfo : 0;
if(curseMultiplicativePenalty) //curse handling (partial, the rest is below)
{
multBonus *= 0.8f * float(VLC->spellh->spells[42]->powers[attacker->getEffect(42)->val]); //the second factor is 1 or 0
multBonus *= 1.0 - curseMultiplicativePenalty/100;
}
class HLP
@ -633,14 +639,14 @@ TDmgRange BattleInfo::calculateDmgRange( const CStack* attacker, const CStack* d
TDmgRange returnedVal;
if(attacker->getEffect(42)) //curse handling (rest)
if(curseEffects->size()) //curse handling (rest)
{
minDmg -= VLC->spellh->spells[42]->powers[attacker->getEffect(42)->val];
minDmg += curseBlessAdditiveModifier;
returnedVal = std::make_pair(int(minDmg), int(minDmg));
}
else if(attacker->getEffect(41)) //bless handling
else if(blessEffects->size()) //bless handling
{
maxDmg += VLC->spellh->spells[41]->powers[attacker->getEffect(41)->val];
maxDmg += curseBlessAdditiveModifier;
returnedVal = std::make_pair(int(maxDmg), int(maxDmg));
}
else
@ -1911,7 +1917,7 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
break;
case 78: //dispel helpful spells
{
boost::shared_ptr<BonusList> spellBon = subject->getSpellBonuses();
TBonusListPtr spellBon = subject->getSpellBonuses();
bool hasPositiveSpell = false;
BOOST_FOREACH(const Bonus * b, *spellBon)
{
@ -1955,7 +1961,7 @@ SpellCasting::ESpellCastProblem BattleInfo::battleIsImmune(const CGHeroInstance
return SpellCasting::STACK_IMMUNE_TO_SPELL;
}
boost::shared_ptr<BonusList> immunities = subject->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
TBonusListPtr immunities = subject->getBonuses(Selector::type(Bonus::LEVEL_SPELL_IMMUNITY));
if(subject->hasBonusOfType(Bonus::NEGATE_ALL_NATURAL_IMMUNITIES))
{
//std::remove_if(immunities->begin(), immunities->end(), NegateRemover);
@ -2199,11 +2205,13 @@ void CStack::stackEffectToFeature(std::vector<Bonus> & sf, const Bonus & sse)
sf.back().valType = Bonus::INDEPENDENT_MAX;
sf.back().sid = sse.sid;
case 41: //bless
sf.push_back(featureGenerator(Bonus::ALWAYS_MAXIMUM_DAMAGE, -1, power, sse.turnsRemain));
sf.push_back(featureGenerator(Bonus::ALWAYS_MAXIMUM_DAMAGE, -1, power, sse.turnsRemain));
sf.back().valType = Bonus::INDEPENDENT_MAX;
sf.back().sid = sse.sid;
break;
case 42: //curse
sf.push_back(featureGenerator(Bonus::ALWAYS_MINIMUM_DAMAGE, -1, -1 * power, sse.turnsRemain, sse.val >= 2 ? 20 : 0));
sf.push_back(featureGenerator(Bonus::ALWAYS_MINIMUM_DAMAGE, -1, power, sse.turnsRemain, sse.val >= 2 ? 20 : 0));
sf.back().valType = Bonus::INDEPENDENT_MAX;
sf.back().sid = sse.sid;
break;
case 43: //bloodlust
@ -2434,7 +2442,7 @@ std::vector<si32> CStack::activeSpells() const
{
std::vector<si32> ret;
boost::shared_ptr<BonusList> spellEffects = getSpellBonuses();
TBonusListPtr spellEffects = getSpellBonuses();
BOOST_FOREACH(const Bonus *it, *spellEffects)
{
if (!vstd::contains(ret, it->sid)) //do not duplicate spells with multiple effects

View File

@ -1678,7 +1678,7 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack)
t = static_cast<const CGTownInstance *>(stack.armyObj);
else if(h)
{ //hero speciality
boost::shared_ptr<BonusList> lista = h->speciality.getBonuses(Selector::typeSubtype(Bonus::SPECIAL_UPGRADE, base->idNumber));
TBonusListPtr lista = h->speciality.getBonuses(Selector::typeSubtype(Bonus::SPECIAL_UPGRADE, base->idNumber));
BOOST_FOREACH(const Bonus *it, *lista)
{
ui16 nid = it->additionalInfo;

View File

@ -153,6 +153,7 @@ void CHeroHandler::loadObstacles()
obi.defName = obs["defname"].String();
obi.blockmap = obs["blockmap"].String();
obi.allowedTerrains = obs["terrains"].String();
assert(obi.allowedTerrains.size() >= 25);
obi.posShift.first = obs["shift_x"].Float();
obi.posShift.second = obs["shift_y"].Float();

View File

@ -1877,12 +1877,12 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
ret.entries.push_back(GrowthInfo::Entry(VLC->generaltexth->allTexts[591], dwellingBonus));// \nExternal dwellings %+d
//other *-of-legion-like bonuses (%d to growth cumulative with grail)
boost::shared_ptr<BonusList> bonuses = getBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level));
TBonusListPtr bonuses = getBonuses(Selector::type(Bonus::CREATURE_GROWTH) && Selector::subtype(level));
BOOST_FOREACH(const Bonus *b, *bonuses)
ret.entries.push_back(GrowthInfo::Entry(b->Description() + " %+d", b->val));
//statue-of-legion-like bonus: % to base+castle
boost::shared_ptr<BonusList> bonuses2 = getBonuses(Selector::type(Bonus::CREATURE_GROWTH_PERCENT));
TBonusListPtr bonuses2 = getBonuses(Selector::type(Bonus::CREATURE_GROWTH_PERCENT));
BOOST_FOREACH(const Bonus *b, *bonuses2)
ret.entries.push_back(GrowthInfo::Entry(b->Description() + " %+d", b->val * (base + castleBonus) / 100));
@ -2239,7 +2239,7 @@ void CGTownInstance::deserializationFix()
void CGTownInstance::recreateBuildingsBonuses()
{
boost::shared_ptr<BonusList> bl(new BonusList);
TBonusListPtr bl(new BonusList);
getExportedBonusList().getBonuses(bl, Selector::sourceType(Bonus::TOWN_STRUCTURE));
BOOST_FOREACH(Bonus *b, *bl)
removeBonus(b);

View File

@ -147,7 +147,7 @@ void BonusList::getModifiersWDescr(TModDescr &out) const
}
}
void BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector) const
void BonusList::getBonuses(TBonusListPtr out, const CSelector &selector) const
{
// BOOST_FOREACH(Bonus *i, *this)
// if(selector(i) && i->effectRange == Bonus::NO_LIMIT)
@ -156,7 +156,7 @@ void BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &se
getBonuses(out, selector, 0);
}
void BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const bool caching /*= false*/) const
void BonusList::getBonuses(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const bool caching /*= false*/) const
{
for (unsigned int i = 0; i < bonuses.size(); i++)
{
@ -170,7 +170,7 @@ void BonusList::getBonuses(boost::shared_ptr<BonusList> out, const CSelector &se
int BonusList::valOfBonuses(const CSelector &select) const
{
boost::shared_ptr<BonusList> ret(new BonusList());
TBonusListPtr ret(new BonusList());
CSelector limit = 0;
getBonuses(ret, select, limit, false);
ret->eliminateDuplicates();
@ -260,7 +260,7 @@ int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) cons
int IBonusBearer::valOfBonuses(const CSelector &selector, const std::string &cachingStr) const
{
CSelector limit = 0;
boost::shared_ptr<BonusList> hlp = getAllBonuses(selector, limit, NULL, cachingStr);
TBonusListPtr hlp = getAllBonuses(selector, limit, NULL, cachingStr);
return hlp->totalValue();
}
bool IBonusBearer::hasBonus(const CSelector &selector, const std::string &cachingStr /*= ""*/) const
@ -303,12 +303,12 @@ int IBonusBearer::getBonusesCount(const CSelector &selector, const std::string &
return getBonuses(selector, cachingStr)->size();
}
const boost::shared_ptr<BonusList> IBonusBearer::getBonuses(const CSelector &selector, const std::string &cachingStr /*= ""*/) const
const TBonusListPtr IBonusBearer::getBonuses(const CSelector &selector, const std::string &cachingStr /*= ""*/) const
{
return getAllBonuses(selector, 0, NULL, cachingStr);
}
const boost::shared_ptr<BonusList> IBonusBearer::getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr /*= ""*/) const
const TBonusListPtr IBonusBearer::getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr /*= ""*/) const
{
return getAllBonuses(selector, limit, NULL, cachingStr);
}
@ -422,7 +422,7 @@ bool IBonusBearer::isLiving() const //TODO: theoreticaly there exists "LIVING" b
return(!hasBonus(Selector::type(Bonus::UNDEAD) || Selector::type(Bonus::NON_LIVING), cachingStr.str()));
}
const boost::shared_ptr<BonusList> IBonusBearer::getSpellBonuses() const
const TBonusListPtr IBonusBearer::getSpellBonuses() const
{
std::stringstream cachingStr;
cachingStr << "source_" << Bonus::SPELL_EFFECT;
@ -468,7 +468,7 @@ void CBonusSystemNode::getParents(TNodes &out)
}
}
void CBonusSystemNode::getAllBonusesRec(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const bool caching /*= false*/) const
void CBonusSystemNode::getAllBonusesRec(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const bool caching /*= false*/) const
{
TCNodes lparents;
getParents(lparents);
@ -478,9 +478,9 @@ void CBonusSystemNode::getAllBonusesRec(boost::shared_ptr<BonusList> out, const
bonuses.getBonuses(out, selector, limit, caching);
}
const boost::shared_ptr<BonusList> CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const std::string &cachingStr /*= ""*/) const
const TBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root /*= NULL*/, const std::string &cachingStr /*= ""*/) const
{
boost::shared_ptr<BonusList> ret(new BonusList());
TBonusListPtr ret(new BonusList());
if (CBonusSystemNode::cachingEnabled)
{
// Exclusive access for one thread
@ -503,7 +503,7 @@ const boost::shared_ptr<BonusList> CBonusSystemNode::getAllBonuses(const CSelect
// pre-calculated bonus results. Limiters can't be cached so they have to be calculated.
if (cachingStr != "")
{
std::map<std::string, boost::shared_ptr<BonusList> >::iterator it(cachedRequests.find(cachingStr));
std::map<std::string, TBonusListPtr >::iterator it(cachedRequests.find(cachingStr));
if (cachedRequests.size() > 0 && it != cachedRequests.end())
{
ret = it->second;
@ -589,7 +589,7 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
void CBonusSystemNode::popBonuses(const CSelector &s)
{
boost::shared_ptr<BonusList> bl(new BonusList);
TBonusListPtr bl(new BonusList);
exportedBonuses.getBonuses(bl, s);
BOOST_FOREACH(Bonus *b, *bl)
removeBonus(b);

View File

@ -23,7 +23,9 @@ struct Bonus;
class CBonusSystemNode;
class ILimiter;
class IPropagator;
class BonusList;
typedef boost::shared_ptr<BonusList> TBonusListPtr;
typedef std::vector<std::pair<int,std::string> > TModDescr; //modifiers values and their descriptions
typedef std::set<CBonusSystemNode*> TNodes;
typedef std::set<const CBonusSystemNode*> TCNodes;
@ -139,7 +141,7 @@ namespace PrimarySkill
BONUS_NAME(HYPNOTIZED) \
BONUS_NAME(ADDITIONAL_RETALIATION) /*value - number of additional retaliations*/ \
BONUS_NAME(MAGIC_MIRROR) /* value - chance of redirecting in %*/ \
BONUS_NAME(ALWAYS_MINIMUM_DAMAGE) /*unit does its minimum damage from range; subtype: -1 - any attack, 0 - melee, 1 - ranged, value: additional damage, additional info - multiplicative anti-bonus for dmg in % [eg 20 means that creature will inflict 80% of normal dmg]*/ \
BONUS_NAME(ALWAYS_MINIMUM_DAMAGE) /*unit does its minimum damage from range; subtype: -1 - any attack, 0 - melee, 1 - ranged, value: additional damage penalty (it'll subtracted from dmg), additional info - multiplicative anti-bonus for dmg in % [eg 20 means that creature will inflict 80% of normal minimal dmg]*/ \
BONUS_NAME(ALWAYS_MAXIMUM_DAMAGE) /*eg. bless effect, subtype: -1 - any attack, 0 - melee, 1 - ranged, value: additional damage, additional info - multiplicative bonus for dmg in %*/ \
BONUS_NAME(ATTACKS_NEAREST_CREATURE) /*while in berserk*/ \
BONUS_NAME(IN_FRENZY) /*value - level*/ \
@ -272,6 +274,10 @@ struct DLL_EXPORT Bonus
h & duration & type & subtype & source & val & sid & description & additionalInfo & turnsRemain & valType & effectRange & limiter & propagator;
}
static bool compareByAdditionalInfo(const Bonus *a, const Bonus *b)
{
return a->additionalInfo < b->additionalInfo;
}
static bool OneDay(const Bonus *hb)
{
return hb->duration & Bonus::ONE_DAY;
@ -357,10 +363,10 @@ public:
// BonusList functions
int totalValue() const; //subtype -> subtype of bonus, if -1 then any
void getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const bool caching = false) const;
void getBonuses(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const bool caching = false) const;
void getModifiersWDescr(TModDescr &out) const;
void getBonuses(boost::shared_ptr<BonusList> out, const CSelector &selector) const;
void getBonuses(TBonusListPtr out, const CSelector &selector) const;
//special find functions
Bonus *getFirst(const CSelector &select);
@ -398,6 +404,7 @@ public:
friend inline std::vector<Bonus*>::iterator range_end(BonusList & x);
};
// Extensions for BOOST_FOREACH to enable iterating of BonusList objects
// Don't touch/call this functions
inline std::vector<Bonus*>::iterator range_begin(BonusList & x)
@ -466,13 +473,13 @@ public:
// * selector is predicate that tests if HeroBonus matches our criteria
// * root is node on which call was made (NULL will be replaced with this)
//interface
virtual const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const = 0;
virtual const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const = 0;
void getModifiersWDescr(TModDescr &out, const CSelector &selector, const std::string &cachingStr = "") const; //out: pairs<modifier value, modifier description>
int getBonusesCount(const CSelector &selector, const std::string &cachingStr = "") const;
int valOfBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
bool hasBonus(const CSelector &selector, const std::string &cachingStr = "") const;
const boost::shared_ptr<BonusList> getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const;
const boost::shared_ptr<BonusList> getBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
const TBonusListPtr getBonuses(const CSelector &selector, const CSelector &limit, const std::string &cachingStr = "") const;
const TBonusListPtr getBonuses(const CSelector &selector, const std::string &cachingStr = "") const;
//legacy interface
int valOfBonuses(Bonus::BonusType type, const CSelector &selector) const;
@ -495,7 +502,7 @@ public:
si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
int getPrimSkillLevel(int id) const; //0-attack, 1-defence, 2-spell power, 3-knowledge
const boost::shared_ptr<BonusList> getSpellBonuses() const;
const TBonusListPtr getSpellBonuses() const;
};
class DLL_EXPORT CBonusSystemNode : public IBonusBearer
@ -518,16 +525,16 @@ private:
// Setting a value to cachingStr before getting any bonuses caches the result for later requests.
// This string needs to be unique, that's why it has to be setted in the following manner:
// [property key]_[value] => only for selector
mutable std::map<std::string, boost::shared_ptr<BonusList> > cachedRequests;
mutable std::map<std::string, TBonusListPtr > cachedRequests;
void getAllBonusesRec(boost::shared_ptr<BonusList> out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const bool caching = false) const;
void getAllBonusesRec(TBonusListPtr out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const bool caching = false) const;
public:
explicit CBonusSystemNode();
virtual ~CBonusSystemNode();
const boost::shared_ptr<BonusList> getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const;
const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = NULL, const std::string &cachingStr = "") const;
void getParents(TCNodes &out) const; //retrieves list of parent nodes (nodes to inherit bonuses from),
const Bonus *getBonus(const CSelector &selector) const;

View File

@ -4370,7 +4370,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
if(attacker->hasBonusOfType(attackMode))
{
std::set<ui32> spellsToCast;
boost::shared_ptr<BonusList> spells = attacker->getBonuses(Selector::type(attackMode));
TBonusListPtr spells = attacker->getBonuses(Selector::type(attackMode));
BOOST_FOREACH(const Bonus *sf, *spells)
{
spellsToCast.insert (sf->subtype);
@ -4391,7 +4391,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
if(oneOfAttacked == NULL) //all attacked creatures have been killed
return;
int spellLevel = 0;
boost::shared_ptr<BonusList> spellsByType = attacker->getBonuses(Selector::typeSubtype(attackMode, spellID));
TBonusListPtr spellsByType = attacker->getBonuses(Selector::typeSubtype(attackMode, spellID));
BOOST_FOREACH(const Bonus *sf, *spellsByType)
{
amax(spellLevel, sf->additionalInfo % 1000); //pick highest level
@ -4452,7 +4452,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
}
}
int acidDamage = 0;
boost::shared_ptr<BonusList> acidBreath = attacker->getBonuses(Selector::type(Bonus::ACID_BREATH));
TBonusListPtr acidBreath = attacker->getBonuses(Selector::type(Bonus::ACID_BREATH));
BOOST_FOREACH(const Bonus *b, *acidBreath)
{
if (b->additionalInfo > rand()%100)
@ -4935,7 +4935,7 @@ void CGameHandler::runBattle()
{
if(gs->curB->heroes[i] && gs->curB->heroes[i]->hasBonusOfType(Bonus::OPENING_BATTLE_SPELL))
{
boost::shared_ptr<BonusList> bl = gs->curB->heroes[i]->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
TBonusListPtr bl = gs->curB->heroes[i]->getBonuses(Selector::type(Bonus::OPENING_BATTLE_SPELL));
BOOST_FOREACH (Bonus *b, *bl)
{
handleSpellCasting(b->subtype, 3, -1, 0, gs->curB->heroes[i]->tempOwner, NULL, gs->curB->heroes[1-i], b->val, SpellCasting::HERO_CASTING, NULL);