diff --git a/client/CCastleInterface.cpp b/client/CCastleInterface.cpp index 5fc28c0f6..41b955596 100644 --- a/client/CCastleInterface.cpp +++ b/client/CCastleInterface.cpp @@ -1155,7 +1155,7 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState) ch = ci->town->visitingHero; }; if (bl.size()) - summ+=AddToString (CGI->arth->artifacts[bl.front().id]->Name()+" %+d", descr, bl.totalValue()); + summ+=AddToString (CGI->arth->artifacts[bl.front()->id]->Name()+" %+d", descr, bl.totalValue()); //TODO: player bonuses diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 99378920a..dcef885f0 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -129,13 +129,13 @@ void GiveBonus::applyCl( CClient *cl ) case HERO: { const CGHeroInstance *h = GS(cl)->getHero(id); - INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, h->bonuses.back(),true); + INTERFACE_CALL_IF_PRESENT(h->tempOwner, heroBonusChanged, h, *h->bonuses.back(),true); } break; case PLAYER: { const PlayerState *p = GS(cl)->getPlayer(id); - INTERFACE_CALL_IF_PRESENT(id, playerBonusChanged, p->bonuses.back(), true); + INTERFACE_CALL_IF_PRESENT(id, playerBonusChanged, *p->bonuses.back(), true); } break; } diff --git a/hch/CArtHandler.cpp b/hch/CArtHandler.cpp index 46d607b92..d4c5b78ff 100644 --- a/hch/CArtHandler.cpp +++ b/hch/CArtHandler.cpp @@ -183,8 +183,8 @@ int CArtifact::getArtClassSerial() const void CScroll::Init() { - bonuses.push_back (Bonus (Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT, 1, id, spellid, Bonus::INDEPENDENT_MAX)); - //boost::algorithm::replace_first(description, "[spell name]", VLC->spellh->spells[spellid].name); +// addNewBonus (Bonus (Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT, 1, id, spellid, Bonus::INDEPENDENT_MAX)); +// //boost::algorithm::replace_first(description, "[spell name]", VLC->spellh->spells[spellid].name); } CArtHandler::CArtHandler() @@ -489,7 +489,7 @@ void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int sub added.limiter = limiter; if(type == Bonus::MORALE || Bonus::LUCK) added.description = "\n" + artifacts[aid]->Name() + (val > 0 ? " +" : " ") + boost::lexical_cast(val); - artifacts[aid]->bonuses.push_back(added); + artifacts[aid]->addNewBonus(added); } void CArtHandler::addBonuses() diff --git a/hch/CCreatureHandler.cpp b/hch/CCreatureHandler.cpp index ba3fdd320..6aed3a394 100644 --- a/hch/CCreatureHandler.cpp +++ b/hch/CCreatureHandler.cpp @@ -78,17 +78,17 @@ bool CCreature::isDoubleWide() const bool CCreature::isFlying() const { - return vstd::contains(bonuses, Bonus::FLYING); + return hasBonusOfType(Bonus::FLYING); } bool CCreature::isShooting() const { - return vstd::contains(bonuses, Bonus::SHOOTER); + return hasBonusOfType(Bonus::SHOOTER); } bool CCreature::isUndead() const { - return vstd::contains(bonuses, Bonus::UNDEAD); + return hasBonusOfType(Bonus::UNDEAD); } /** @@ -127,7 +127,7 @@ CCreature::CCreature() void CCreature::addBonus(int val, int type, int subtype /*= -1*/) { Bonus added(Bonus::PERMANENT, type, Bonus::CREATURE_ABILITY, val, idNumber, subtype, Bonus::BASE_NUMBER); - bonuses.push_back(added); + addNewBonus(added); } // void CCreature::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const // { @@ -312,12 +312,12 @@ void CCreatureHandler::loadCreatures() if(boost::algorithm::find_first(ncre.abilityRefs, "const_raises_morale")) { ncre.addBonus(+1, Bonus::MORALE);; - ncre.bonuses.back().effectRange = Bonus::ONLY_ALLIED_ARMY; + ncre.bonuses.back()->effectRange = Bonus::ONLY_ALLIED_ARMY; } if(boost::algorithm::find_first(ncre.abilityRefs, "const_lowers_morale")) { ncre.addBonus(-1, Bonus::MORALE);; - ncre.bonuses.back().effectRange = Bonus::ONLY_ENEMY_ARMY; + ncre.bonuses.back()->effectRange = Bonus::ONLY_ENEMY_ARMY; } if(boost::algorithm::find_first(ncre.abilityRefs, "KING_1")) ncre.addBonus(0, Bonus::KING1); @@ -380,13 +380,13 @@ void CCreatureHandler::loadCreatures() cre->doubleWide = true; else if(type == "ENEMY_MORALE_DECREASING") { - cre->addBonus(-1, Bonus::MORALE);; - cre->bonuses.back().effectRange = Bonus::ONLY_ENEMY_ARMY; + cre->addBonus(-1, Bonus::MORALE); + cre->bonuses.back()->effectRange = Bonus::ONLY_ENEMY_ARMY; } else if(type == "ENEMY_LUCK_DECREASING") { - cre->addBonus(-1, Bonus::LUCK);; - cre->bonuses.back().effectRange = Bonus::ONLY_ENEMY_ARMY; + cre->addBonus(-1, Bonus::LUCK); + cre->bonuses.back()->effectRange = Bonus::ONLY_ENEMY_ARMY; } else tlog1 << "Error: invalid type " << type << " in cr_abils.txt" << std::endl; @@ -402,7 +402,7 @@ void CCreatureHandler::loadCreatures() nsf.duration = Bonus::ONE_BATTLE; nsf.turnsRemain = 0; - cre->bonuses += nsf; + cre->addNewBonus(nsf); break; } case '-': //remove ability @@ -424,7 +424,8 @@ void CCreatureHandler::loadCreatures() Bonus::BonusType ecf = static_cast(typeNo); - creatures[creatureID]->bonuses -= ecf; + Bonus *b = creatures[creatureID]->getBonus(Selector::type(ecf)); + creatures[creatureID]->removeBonus(b); break; } case '0': //end reading diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 5aeaff25b..a6cbbb272 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -1016,15 +1016,15 @@ void CGHeroInstance::initObj() bonus.valType = Bonus::ADDITIVE_VALUE; bonus.subtype = PrimarySkill::ATTACK; - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); bonus.subtype = PrimarySkill::DEFENSE; - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); //values will be calculated later bonus.type = Bonus::STACKS_SPEED; bonus.val = 1; //+1 speed - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); } break; case 2://secondary skill @@ -1033,7 +1033,7 @@ void CGHeroInstance::initObj() bonus.valType = Bonus::BASE_NUMBER; // to receive nonzero value bonus.subtype = it->subtype; //skill id bonus.val = it->val; //value per level, in percent - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); switch (it->additionalinfo) { case 0: //normal @@ -1044,12 +1044,12 @@ void CGHeroInstance::initObj() break; } bonus.type = Bonus::SECONDARY_SKILL_PREMY; //value will be calculated later - speciality.bonuses.push_back(bonus); + speciality.addNewBonus(bonus); break; case 3://spell damage bonus, level dependant but calculated elsehwere bonus.type = Bonus::SPECIAL_SPELL_LEV; bonus.subtype = it->subtype; - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 4://creature stat boost switch (it->subtype) @@ -1077,30 +1077,30 @@ void CGHeroInstance::initObj() } bonus.valType = Bonus::ADDITIVE_VALUE; bonus.limiter = new CCreatureTypeLimiter (*VLC->creh->creatures[it->additionalinfo], true); - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 5://spell damage bonus in percent bonus.type = Bonus::SPECIFIC_SPELL_DAMAGE; bonus.valType = Bonus::BASE_NUMBER; // current spell system is screwed bonus.subtype = it->subtype; //spell id - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 6://damage bonus for bless (Adela) bonus.type = Bonus::SPECIAL_BLESS_DAMAGE; bonus.subtype = it->subtype; //spell id if you ever wanted to use it otherwise bonus.additionalInfo = it->additionalinfo; //damage factor - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 7://maxed mastery for spell bonus.type = Bonus::MAXED_SPELL; bonus.subtype = it->subtype; //spell i - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 8://peculiar spells - enchantments bonus.type = Bonus::SPECIAL_PECULIAR_ENCHANT; bonus.subtype = it->subtype; //spell id bonus.additionalInfo = it->additionalinfo;//0, 1 for Coronius - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 9://upgrade creatures { @@ -1108,27 +1108,27 @@ void CGHeroInstance::initObj() bonus.type = Bonus::SPECIAL_UPGRADE; bonus.subtype = it->subtype; //base id bonus.additionalInfo = it->additionalinfo; //target id - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); for (std::set::iterator i = (*creatures)[it->subtype]->upgrades.begin(); i != (*creatures)[it->subtype]->upgrades.end(); i++) { bonus.subtype = *i; //propagate for regular upgrades of base creature - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); } break; } case 10://resource generation bonus.type = Bonus::GENERATE_RESOURCE; bonus.subtype = it->subtype; - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 11://starting skill with mastery (Adrienne) - cb->changeSecSkill (id, it->val, it->additionalinfo); //simply give it and forget + cb->changeSecSkill(id, it->val, it->additionalinfo); //simply give it and forget break; case 12://army speed bonus.type = Bonus::STACKS_SPEED; - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; case 13://Dragon bonuses (Mutare) bonus.type = Bonus::PRIMARY_SKILL; @@ -1143,7 +1143,7 @@ void CGHeroInstance::initObj() break; } bonus.limiter = new HasAnotherBonusLimiter(Bonus::DRAGON_NATURE); - speciality.bonuses.push_back (bonus); + speciality.addNewBonus(bonus); break; default: tlog2 << "Unexpected hero speciality " << type <<'\n'; @@ -1161,7 +1161,8 @@ void CGHeroInstance::UpdateSpeciality() if (speciality.growthsWithLevel) { std::vector* creatures = &VLC->creh->creatures; - for (std::list::iterator it = speciality.bonuses.begin(); it != speciality.bonuses.end(); it++) + + BOOST_FOREACH(Bonus *it, speciality.bonuses) { switch (it->type) { @@ -1248,7 +1249,7 @@ void CGHeroInstance::updateSkill(int which, int val) { Bonus bonus(Bonus::PERMANENT, Bonus::SECONDARY_SKILL_PREMY, id, skillVal, ID, which, Bonus::BASE_NUMBER); bonus.source = Bonus::SECONDARY_SKILL; - bonuses.push_back (bonus); + addNewBonus (bonus); } } } @@ -1505,7 +1506,7 @@ int CGHeroInstance::getSpellCost(const CSpell *sp) const void CGHeroInstance::pushPrimSkill(int which, int val) { - bonuses.push_back(Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::HERO_BASE_SKILL, val, id, which)); + addNewBonus(Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::HERO_BASE_SKILL, val, id, which)); } // void CGHeroInstance::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root /*= NULL*/) const @@ -2131,7 +2132,7 @@ void CGTownInstance::initObj() //add special bonuses from buildings if(subID == 4 && vstd::contains(builtBuildings, 17)) { - bonuses.push_back( Bonus(Bonus::PERMANENT, Bonus::DARKNESS, Bonus::TOWN_STRUCTURE, 20, 17) ); + addNewBonus( Bonus(Bonus::PERMANENT, Bonus::DARKNESS, Bonus::TOWN_STRUCTURE, 20, 17) ); } } diff --git a/lib/CGameState.cpp b/lib/CGameState.cpp index 3fecf9afd..ee3b3ac10 100644 --- a/lib/CGameState.cpp +++ b/lib/CGameState.cpp @@ -708,11 +708,11 @@ ui32 CStack::Speed( int turn /*= 0*/ ) const int speed = valOfBonuses(Selector::type(Bonus::STACKS_SPEED) && Selector::turns(turn)); int percentBonus = 0; - BOOST_FOREACH(const Bonus &b, bonuses) + BOOST_FOREACH(const Bonus *b, bonuses) { - if(b.type == Bonus::STACKS_SPEED) + if(b->type == Bonus::STACKS_SPEED) { - percentBonus += b.additionalInfo; + percentBonus += b->additionalInfo; } } @@ -729,7 +729,7 @@ ui32 CStack::Speed( int turn /*= 0*/ ) const const Bonus * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const { - for (BonusList::const_iterator it = bonuses.begin(); it != bonuses.end(); it++) + BOOST_FOREACH(Bonus *it, bonuses) { if(it->source == Bonus::SPELL_EFFECT && it->id == id) { @@ -742,179 +742,179 @@ const Bonus * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const void CStack::stackEffectToFeature(BonusList & sf, const Bonus & sse) { - si32 power = VLC->spellh->spells[sse.id].powers[sse.val]; - Bonus * bonus = getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, sse.id)); - if (bonus) - { - switch(bonus->additionalInfo) - { - case 0: //normal - switch(type->level) - { - case 1: case 2: - power += 3; //it doesn't necessarily make sense for some spells, use it wisely - break; - case 3: case 4: - power += 2; - break; - case 5: case 6: - power += 1; - break; - } - break; - case 1: //only Coronius as yet - power = std::max(5 - type->level, 0); - break; - } - } - - switch(sse.id) - { - case 27: //shield - sf.push_back(featureGenerator(Bonus::GENERAL_DAMAGE_REDUCTION, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 28: //air shield - sf.push_back(featureGenerator(Bonus::GENERAL_DAMAGE_REDUCTION, 1, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 29: //fire shield - sf.push_back(featureGenerator(Bonus::FIRE_SHIELD, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 30: //protection from air - sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 31: //protection from fire - sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 1, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 32: //protection from water - sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 2, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 33: //protection from earth - sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 3, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 34: //anti-magic - sf.push_back(featureGenerator(Bonus::LEVEL_SPELL_IMMUNITY, 0, power - 1, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 41: //bless - if (hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, 41)) //TODO: better handling of bonus percentages - { - int damagePercent = dynamic_cast(armyObj)->level * valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / type->level; - sf.push_back(featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, sse.turnsRemain)); - sf.back().id = sse.id; - sf.back().valType = Bonus::PERCENT_TO_ALL; - } - sf.push_back(featureGenerator(Bonus::ALWAYS_MAXIMUM_DAMAGE, -1, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 42: //curse - sf.push_back(featureGenerator(Bonus::ALWAYS_MINIMUM_DAMAGE, -1, -1 * power, sse.turnsRemain, sse.val >= 2 ? 20 : 0)); - sf.back().id = sse.id; - break; - case 43: //bloodlust - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain, 0, Bonus::ONLY_MELEE_FIGHT)); - sf.back().id = sse.id; - break; - case 44: //precision - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain, 0, Bonus::ONLY_DISTANCE_FIGHT)); - sf.back().id = sse.id; - break; - case 45: //weakness - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, -1 * power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 46: //stone skin - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 47: //disrupting ray - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -1 * power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 48: //prayer - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain)); - sf.back().id = sse.id; - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, power, sse.turnsRemain)); - sf.back().id = sse.id; - sf.push_back(featureGenerator(Bonus::STACKS_SPEED, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 49: //mirth - sf.push_back(featureGenerator(Bonus::MORALE, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 50: //sorrow - sf.push_back(featureGenerator(Bonus::MORALE, 0, -1 * power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 51: //fortune - sf.push_back(featureGenerator(Bonus::LUCK, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 52: //misfortune - sf.push_back(featureGenerator(Bonus::LUCK, 0, -1 * power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 53: //haste - sf.push_back(featureGenerator(Bonus::STACKS_SPEED, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 54: //slow - sf.push_back(featureGeneratorVT(Bonus::STACKS_SPEED, 0, -1 * ( 100 - power ), sse.turnsRemain, Bonus::PERCENT_TO_ALL)); - sf.back().id = sse.id; - break; - case 55: //slayer - if (bonus) //Coronius - { - sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain)); - sf.back().id = sse.id; - } - sf.push_back(featureGenerator(Bonus::SLAYER, 0, sse.val, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 56: //frenzy - sf.push_back(featureGenerator(Bonus::IN_FRENZY, 0, VLC->spellh->spells[56].powers[sse.val]/100.0, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 58: //counterstrike - sf.push_back(featureGenerator(Bonus::ADDITIONAL_RETALIATION, 0, power, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 59: //bersek - sf.push_back(featureGenerator(Bonus::ATTACKS_NEAREST_CREATURE, 0, sse.val, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 60: //hypnotize - sf.push_back(featureGenerator(Bonus::HYPNOTIZED, 0, sse.val, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 61: //forgetfulness - sf.push_back(featureGenerator(Bonus::FORGETFULL, 0, sse.val, sse.turnsRemain)); - sf.back().id = sse.id; - break; - case 62: //blind - sf.push_back(makeFeature(Bonus::NOT_ACTIVE, Bonus::UNITL_BEING_ATTACKED | Bonus::N_TURNS, 0, 0, Bonus::SPELL_EFFECT, sse.turnsRemain)); - sf.back().id = sse.id; - sf.push_back(makeFeature(Bonus::GENERAL_ATTACK_REDUCTION, Bonus::UNTIL_ATTACK | Bonus::N_TURNS, 0, power, Bonus::SPELL_EFFECT, sse.turnsRemain)); - sf.back().id = sse.id; - break; - } -} +// si32 power = VLC->spellh->spells[sse.id].powers[sse.val]; +// Bonus * bonus = getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, sse.id)); +// if (bonus) +// { +// switch(bonus->additionalInfo) +// { +// case 0: //normal +// switch(type->level) +// { +// case 1: case 2: +// power += 3; //it doesn't necessarily make sense for some spells, use it wisely +// break; +// case 3: case 4: +// power += 2; +// break; +// case 5: case 6: +// power += 1; +// break; +// } +// break; +// case 1: //only Coronius as yet +// power = std::max(5 - type->level, 0); +// break; +// } +// } +// +// switch(sse.id) +// { +// case 27: //shield +// sf.push_back(featureGenerator(Bonus::GENERAL_DAMAGE_REDUCTION, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 28: //air shield +// sf.push_back(featureGenerator(Bonus::GENERAL_DAMAGE_REDUCTION, 1, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 29: //fire shield +// sf.push_back(featureGenerator(Bonus::FIRE_SHIELD, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 30: //protection from air +// sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 31: //protection from fire +// sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 1, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 32: //protection from water +// sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 2, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 33: //protection from earth +// sf.push_back(featureGenerator(Bonus::SPELL_DAMAGE_REDUCTION, 3, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 34: //anti-magic +// sf.push_back(featureGenerator(Bonus::LEVEL_SPELL_IMMUNITY, 0, power - 1, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 41: //bless +// if (hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, 41)) //TODO: better handling of bonus percentages +// { +// int damagePercent = dynamic_cast(armyObj)->level * valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / type->level; +// sf.push_back(featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, sse.turnsRemain)); +// sf.back().id = sse.id; +// sf.back().valType = Bonus::PERCENT_TO_ALL; +// } +// sf.push_back(featureGenerator(Bonus::ALWAYS_MAXIMUM_DAMAGE, -1, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 42: //curse +// sf.push_back(featureGenerator(Bonus::ALWAYS_MINIMUM_DAMAGE, -1, -1 * power, sse.turnsRemain, sse.val >= 2 ? 20 : 0)); +// sf.back().id = sse.id; +// break; +// case 43: //bloodlust +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain, 0, Bonus::ONLY_MELEE_FIGHT)); +// sf.back().id = sse.id; +// break; +// case 44: //precision +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain, 0, Bonus::ONLY_DISTANCE_FIGHT)); +// sf.back().id = sse.id; +// break; +// case 45: //weakness +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, -1 * power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 46: //stone skin +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 47: //disrupting ray +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, -1 * power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 48: //prayer +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// sf.push_back(featureGenerator(Bonus::STACKS_SPEED, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 49: //mirth +// sf.push_back(featureGenerator(Bonus::MORALE, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 50: //sorrow +// sf.push_back(featureGenerator(Bonus::MORALE, 0, -1 * power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 51: //fortune +// sf.push_back(featureGenerator(Bonus::LUCK, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 52: //misfortune +// sf.push_back(featureGenerator(Bonus::LUCK, 0, -1 * power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 53: //haste +// sf.push_back(featureGenerator(Bonus::STACKS_SPEED, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 54: //slow +// sf.push_back(featureGeneratorVT(Bonus::STACKS_SPEED, 0, -1 * ( 100 - power ), sse.turnsRemain, Bonus::PERCENT_TO_ALL)); +// sf.back().id = sse.id; +// break; +// case 55: //slayer +// if (bonus) //Coronius +// { +// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// } +// sf.push_back(featureGenerator(Bonus::SLAYER, 0, sse.val, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 56: //frenzy +// sf.push_back(featureGenerator(Bonus::IN_FRENZY, 0, VLC->spellh->spells[56].powers[sse.val]/100.0, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 58: //counterstrike +// sf.push_back(featureGenerator(Bonus::ADDITIONAL_RETALIATION, 0, power, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 59: //bersek +// sf.push_back(featureGenerator(Bonus::ATTACKS_NEAREST_CREATURE, 0, sse.val, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 60: //hypnotize +// sf.push_back(featureGenerator(Bonus::HYPNOTIZED, 0, sse.val, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 61: //forgetfulness +// sf.push_back(featureGenerator(Bonus::FORGETFULL, 0, sse.val, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// case 62: //blind +// sf.push_back(makeFeature(Bonus::NOT_ACTIVE, Bonus::UNITL_BEING_ATTACKED | Bonus::N_TURNS, 0, 0, Bonus::SPELL_EFFECT, sse.turnsRemain)); +// sf.back().id = sse.id; +// sf.push_back(makeFeature(Bonus::GENERAL_ATTACK_REDUCTION, Bonus::UNTIL_ATTACK | Bonus::N_TURNS, 0, power, Bonus::SPELL_EFFECT, sse.turnsRemain)); +// sf.back().id = sse.id; +// break; +// } + } ui8 CStack::howManyEffectsSet(ui16 id) const { ui8 ret = 0; - for (BonusList::const_iterator it = bonuses.begin(); it != bonuses.end(); it++) - if(it->source == Bonus::SPELL_EFFECT && it->id == id) //effect found - { - ++ret; - } + BOOST_FOREACH(const Bonus *it, bonuses) + if(it->source == Bonus::SPELL_EFFECT && it->id == id) //effect found + { + ++ret; + } return ret; } @@ -968,7 +968,7 @@ std::vector CStack::activeSpells() const std::vector ret; BonusList spellEffects = getSpellBonuses(); - for(BonusList::const_iterator it = spellEffects.begin(); it != spellEffects.end(); it++) + BOOST_FOREACH(const Bonus *it, spellEffects) { if (!vstd::contains(ret, it->id)) //do not duplicate spells with multiple effects ret.push_back(it->id); @@ -1427,8 +1427,8 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed ) { continue; } - Bonus bb(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::CAMPAIGN_BONUS, val, si->whichMapInCampaign, g); - hero->bonuses.push_back(bb); + Bonus *bb = new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::CAMPAIGN_BONUS, val, si->whichMapInCampaign, g); + hero->addNewBonus(bb); } } break; @@ -2262,7 +2262,7 @@ UpgradeInfo CGameState::getUpgradeInfo(const CStackInstance &stack) else if(h) { //hero speciality BonusList lista = h->speciality.getBonuses(Selector::typeSybtype(Bonus::SPECIAL_UPGRADE, base->idNumber)); - for (BonusList::iterator it = lista.begin(); it != lista.end(); it++) + BOOST_FOREACH(const Bonus *it, lista) { ui16 nid = it->additionalInfo; if (nid != base->idNumber) //in very specific case the upgrade is avaliable by default (?) @@ -3136,11 +3136,11 @@ std::pair BattleInfo::calculateDmgRange( const CStack* attacker, con for(int g = 0; g < VLC->creh->creatures.size(); ++g) { - BOOST_FOREACH(const Bonus &b, VLC->creh->creatures[g]->bonuses) + BOOST_FOREACH(const Bonus *b, VLC->creh->creatures[g]->bonuses) { - if ( (b.type == Bonus::KING3 && spLevel >= 3) || //expert - (b.type == Bonus::KING2 && spLevel >= 2) || //adv + - (b.type == Bonus::KING1 && spLevel >= 0) ) //none or basic + + if ( (b->type == Bonus::KING3 && spLevel >= 3) || //expert + (b->type == Bonus::KING2 && spLevel >= 2) || //adv + + (b->type == Bonus::KING1 && spLevel >= 0) ) //none or basic + { affectedIds.push_back(g); break; @@ -3237,7 +3237,8 @@ std::pair BattleInfo::calculateDmgRange( const CStack* attacker, con public: static bool hasAdvancedAirShield(const CStack * stack) { - for (BonusList::const_iterator it = stack->bonuses.begin(); it != stack->bonuses.end(); it++) + + BOOST_FOREACH(const Bonus *it, stack->bonuses) { if (it->source == Bonus::SPELL_EFFECT && it->id == 28 && it->val >= 2) { @@ -3332,7 +3333,7 @@ si8 CGameState::battleMaxSpellLevel() const CGHeroInstance *h1 = curB->heroes[0]; if(h1) { - for(std::list::const_iterator i = h1->bonuses.begin(); i != h1->bonuses.end(); i++) + BOOST_FOREACH(const Bonus *i, h1->bonuses) if(i->type == Bonus::BLOCK_SPELLS_ABOVE_LEVEL) amin(levelLimit, i->val); } @@ -3340,7 +3341,8 @@ si8 CGameState::battleMaxSpellLevel() const CGHeroInstance *h2 = curB->heroes[1]; if(h2) { - for(std::list::const_iterator i = h2->bonuses.begin(); i != h2->bonuses.end(); i++) + + BOOST_FOREACH(const Bonus *i, h2->bonuses) if(i->type == Bonus::BLOCK_SPELLS_ABOVE_LEVEL) amin(levelLimit, i->val); } @@ -3437,16 +3439,20 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, int stackID, b { CStack * ret = new CStack(&base, attackerOwned ? side1 : side2, stackID, attackerOwned, slot); - //native terrain bonuses - int faction = ret->type->faction; - if(faction >= 0 && VLC->heroh->nativeTerrains[faction] == terrain) - { - ret->bonuses.push_back(makeFeature(Bonus::STACKS_SPEED, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_NATIVE)); - ret->bonuses.push_back(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::ATTACK, 1, Bonus::TERRAIN_NATIVE)); - ret->bonuses.push_back(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::DEFENSE, 1, Bonus::TERRAIN_NATIVE)); - } + //TODO: bonus na bitwę z limiterem - ret->position = position; +////////////////////////////////////////////////////////////////////////// + + //native terrain bonuses +// int faction = ret->type->faction; +// if(faction >= 0 && VLC->heroh->nativeTerrains[faction] == terrain) +// { +// ret->addNewBonus(makeFeature(Bonus::STACKS_SPEED, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_NATIVE)); +// ret->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::ATTACK, 1, Bonus::TERRAIN_NATIVE)); +// ret->addNewBonus(makeFeature(Bonus::PRIMARY_SKILL, Bonus::ONE_BATTLE, PrimarySkill::DEFENSE, 1, Bonus::TERRAIN_NATIVE)); +// } +// +// ret->position = position; return ret; } diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 458696722..62bbddcbc 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -25,7 +25,7 @@ int DLL_EXPORT BonusList::totalValue() const int indepMax = 0; bool hasIndepMax = false; - for(const_iterator i = begin(); i != end(); i++) + BOOST_FOREACH(Bonus *i, *this) { switch(i->valType) { @@ -65,38 +65,38 @@ int DLL_EXPORT BonusList::totalValue() const } const DLL_EXPORT Bonus * BonusList::getFirst(const CSelector &selector) const { - for (const_iterator i = begin(); i != end(); i++) - if(selector(*i)) + BOOST_FOREACH(Bonus *i, *this) + if(selector(i)) return &*i; return NULL; } DLL_EXPORT Bonus * BonusList::getFirst(const CSelector &select) { - for (iterator i = begin(); i != end(); i++) - if(select(*i)) + BOOST_FOREACH(Bonus *i, *this) + if(select(i)) return &*i; return NULL; } void DLL_EXPORT BonusList::getModifiersWDescr(TModDescr &out) const { - for(const_iterator i = begin(); i != end(); i++) + BOOST_FOREACH(Bonus *i, *this) out.push_back(std::make_pair(i->val, i->Description())); } void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *source /*= NULL*/) const { - for(const_iterator i = begin(); i != end(); i++) - if(selector(*i) && i->effectRange == Bonus::NO_LIMIT) - out.push_back(*i); + BOOST_FOREACH(Bonus *i, *this) + if(selector(i) && i->effectRange == Bonus::NO_LIMIT) + out.push_back(i); } void DLL_EXPORT BonusList::getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit, const CBonusSystemNode *source /*= NULL*/) const { - for(const_iterator i = begin(); i != end(); i++) - if(selector(*i) && (!limit || limit(*i))) - out.push_back(*i); + BOOST_FOREACH(Bonus *i, *this) + if(selector(i) && (!limit || limit(i))) + out.push_back(i); } namespace HHLP @@ -108,9 +108,9 @@ namespace HHLP SourceComp(Bonus::BonusSource _src) : src(_src) { } - bool operator()(const Bonus & bon) + bool operator()(const Bonus * bon) { - return bon.source == src; + return bon->source == src; } }; } @@ -126,7 +126,8 @@ void BonusList::limit(const CBonusSystemNode &node) limit_start: for(iterator i = begin(); i != end(); i++) { - if(i->limiter && i->limiter->limit(*i, node)) + Bonus *b = *i; + if(b->limiter && b->limiter->limit(b, node)) { iterator toErase = i; if(i != begin()) @@ -344,6 +345,31 @@ void CBonusSystemNode::detachFrom(const CBonusSystemNode *parent) } +void CBonusSystemNode::popBonuses(const CSelector &s) +{ + //TODO + //prop + + bonuses.remove_if(s); + BOOST_FOREACH(CBonusSystemNode *child, children) + child->popBonuses(s); +} + +void CBonusSystemNode::addNewBonus(const Bonus &b) +{ + addNewBonus(new Bonus(b)); +} + +void CBonusSystemNode::addNewBonus(Bonus *b) +{ + +} + +void CBonusSystemNode::removeBonus(Bonus *b) +{ + //TODO +} + int NBonus::valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype /*= -1*/) { if(obj) @@ -473,7 +499,7 @@ namespace Selector { Bonus dummy; dummy.type = type; - return sel(dummy); + return sel(&dummy); } bool DLL_EXPORT matchesTypeSubtype(const CSelector &sel, TBonusType type, TBonusSubtype subtype) @@ -481,16 +507,16 @@ namespace Selector Bonus dummy; dummy.type = type; dummy.subtype = subtype; - return sel(dummy); + return sel(&dummy); } } DLL_EXPORT std::ostream & operator<<(std::ostream &out, const BonusList &bonusList) { int i = 0; - BOOST_FOREACH(const Bonus &b, bonusList) + BOOST_FOREACH(const Bonus *b, bonusList) { - out << "Bonus " << i++ << "\n" << b << std::endl; + out << "Bonus " << i++ << "\n" << *b << std::endl; } return out; } @@ -520,12 +546,12 @@ ILimiter::~ILimiter() { } -bool ILimiter::limit(const Bonus &b, const CBonusSystemNode &node) const /*return true to drop the bonus */ +bool ILimiter::limit(const Bonus *b, const CBonusSystemNode &node) const /*return true to drop the bonus */ { return false; } -bool CCreatureTypeLimiter::limit(const Bonus &b, const CBonusSystemNode &node) const +bool CCreatureTypeLimiter::limit(const Bonus *b, const CBonusSystemNode &node) const { switch (node.nodeType) { @@ -566,7 +592,7 @@ HasAnotherBonusLimiter::HasAnotherBonusLimiter( TBonusType bonus, TBonusSubtype { } -bool HasAnotherBonusLimiter::limit( const Bonus &b, const CBonusSystemNode &node ) const +bool HasAnotherBonusLimiter::limit( const Bonus *b, const CBonusSystemNode &node ) const { if(isSubtypeRelevant) { diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 10b250181..06d1847d5 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -28,7 +28,7 @@ class ILimiter; typedef std::vector > TModDescr; //modifiers values and their descriptions typedef std::set TNodes; typedef std::set TCNodes; -typedef boost::function CSelector; +typedef boost::function CSelector; namespace PrimarySkill { @@ -253,25 +253,25 @@ struct DLL_EXPORT Bonus h & duration & type & subtype & source & val & id & description & additionalInfo & turnsRemain & valType & effectRange & limiter; } - static bool OneDay(const Bonus &hb) + static bool OneDay(const Bonus *hb) { - return hb.duration & Bonus::ONE_DAY; + return hb->duration & Bonus::ONE_DAY; } - static bool OneWeek(const Bonus &hb) + static bool OneWeek(const Bonus *hb) { - return hb.duration & Bonus::ONE_WEEK; + return hb->duration & Bonus::ONE_WEEK; } - static bool OneBattle(const Bonus &hb) + static bool OneBattle(const Bonus *hb) { - return hb.duration & Bonus::ONE_BATTLE; + return hb->duration & Bonus::ONE_BATTLE; } - static bool UntilAttack(const Bonus &hb) + static bool UntilAttack(const Bonus *hb) { - return hb.duration & Bonus::UNTIL_ATTACK; + return hb->duration & Bonus::UNTIL_ATTACK; } - static bool UntilBeingAttacked(const Bonus &hb) + static bool UntilBeingAttacked(const Bonus *hb) { - return hb.duration & Bonus::UNITL_BEING_ATTACKED; + return hb->duration & Bonus::UNITL_BEING_ATTACKED; } static bool IsFrom(const Bonus &hb, ui8 source, ui32 id) //if id==0xffffff then id doesn't matter { @@ -308,7 +308,7 @@ struct DLL_EXPORT stackExperience : public Bonus DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus); -class BonusList : public std::list +class BonusList : public std::list { public: int DLL_EXPORT totalValue() const; //subtype -> subtype of bonus, if -1 then any @@ -325,7 +325,7 @@ public: template void serialize(Handler &h, const int version) { - h & static_cast&>(*this); + h & static_cast&>(*this); } }; @@ -336,7 +336,7 @@ class DLL_EXPORT ILimiter public: virtual ~ILimiter(); - virtual bool limit(const Bonus &b, const CBonusSystemNode &node) const; //return true to drop the bonus + virtual bool limit(const Bonus *b, const CBonusSystemNode &node) const; //return true to drop the bonus template void serialize(Handler &h, const int version) {} @@ -348,7 +348,7 @@ public: BonusList bonuses; //wielded bonuses (local and up-propagated here) std::vector exportedBonuses; - std::vector parents, //parents -> we inherit bonuses from them, we may attach our bonuses to them + std::vector parents, //parents -> we inherit bonuses from them, we may attach our bonuses to them children; ui8 nodeType; @@ -396,6 +396,11 @@ public: void attachTo(const CBonusSystemNode *parent); void detachFrom(const CBonusSystemNode *parent); + void addNewBonus(Bonus *b); //b will be deleted with destruction of node + void addNewBonus(const Bonus &b); //b will copied + void removeBonus(Bonus *b); + + void popBonuses(const CSelector &s); template void serialize(Handler &h, const int version) { @@ -441,7 +446,7 @@ public: :first(First), second(Second) { } - bool operator()(const Bonus &bonus) const + bool operator()(const Bonus *bonus) const { return first(bonus) && second(bonus); } @@ -456,7 +461,7 @@ public: :first(First), second(Second) { } - bool operator()(const Bonus &bonus) const + bool operator()(const Bonus *bonus) const { return first(bonus) || second(bonus); } @@ -473,9 +478,9 @@ public: : ptr(Ptr), val(Val) { } - bool operator()(const Bonus &bonus) const + bool operator()(const Bonus *bonus) const { - return bonus.*ptr == val; + return bonus->*ptr == val; } CSelectFieldEqual& operator()(const T &setVal) { @@ -489,11 +494,11 @@ class CWillLastTurns public: int turnsRequested; - bool operator()(const Bonus &bonus) const + bool operator()(const Bonus *bonus) const { return turnsRequested <= 0 //every present effect will last zero (or "less") turns - || !(bonus.duration & Bonus::N_TURNS) //so do every not expriing after N-turns effect - || bonus.turnsRemain > turnsRequested; + || !(bonus->duration & Bonus::N_TURNS) //so do every not expriing after N-turns effect + || bonus->turnsRemain > turnsRequested; } CWillLastTurns& operator()(const int &setVal) { @@ -511,7 +516,7 @@ public: CCreatureTypeLimiter(); CCreatureTypeLimiter(const CCreature &Creature, ui8 IncludeUpgrades = true); - bool limit(const Bonus &b, const CBonusSystemNode &node) const; + bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE; template void serialize(Handler &h, const int version) { @@ -529,7 +534,7 @@ public: HasAnotherBonusLimiter(TBonusType bonus); HasAnotherBonusLimiter(TBonusType bonus, TBonusSubtype _subtype); - bool limit(const Bonus &b, const CBonusSystemNode &node) const; + bool limit(const Bonus *b, const CBonusSystemNode &node) const OVERRIDE; template void serialize(Handler &h, const int version) { diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 7994b06da..6499d82cb 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -185,33 +185,26 @@ DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs ) DLL_EXPORT void GiveBonus::applyGs( CGameState *gs ) { - BonusList *bonuses = NULL; + CBonusSystemNode *cbsn = NULL; switch(who) { case HERO: - { - CGHeroInstance *h = gs->getHero(id); - assert(h); - bonuses = &h->bonuses; - } + cbsn = gs->getHero(id); break; case PLAYER: - { - PlayerState *p = gs->getPlayer(id); - assert(p); - bonuses = &p->bonuses; - } + cbsn = gs->getPlayer(id); break; case TOWN: - { - CGTownInstance *t = gs->getTown(id); - assert(t); - bonuses = &t->bonuses; - } + cbsn = gs->getTown(id); + break; } - bonuses->push_back(bonus); - std::string &descr = bonuses->back().description; + assert(cbsn); + + Bonus *b = new Bonus(bonus); + cbsn->addNewBonus(b); + + std::string &descr = b->description; if(!bdescr.message.size() && bonus.source == Bonus::OBJECT @@ -248,13 +241,13 @@ DLL_EXPORT void PlayerEndsGame::applyGs( CGameState *gs ) DLL_EXPORT void RemoveBonus::applyGs( CGameState *gs ) { - std::list &bonuses = (who == HERO ? gs->getHero(whoID)->bonuses : gs->getPlayer(whoID)->bonuses); + BonusList &bonuses = (who == HERO ? gs->getHero(whoID)->bonuses : gs->getPlayer(whoID)->bonuses); - for(std::list::iterator i = bonuses.begin(); i != bonuses.end(); i++) + for(BonusList::iterator i = bonuses.begin(); i != bonuses.end(); i++) { - if(i->source == source && i->id == id) + if((*i)->source == source && (*i)->id == id) { - bonus = *i; //backup bonus (to show to interfaces later) + bonus = **i; //backup bonus (to show to interfaces later) bonuses.erase(i); break; } @@ -654,50 +647,45 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs ) if (specialWeek != NO_ACTION) //first pack applied, reset all effects and aplly new { - BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes) - h->bonuses.remove_if(Bonus::OneDay); + //TODO? won't work for battles lasting several turns (not an issue now but...) + gs->globalEffects.popBonuses(Bonus::OneDay); //works for children -> all game objs if(gs->getDate(1)) //new week, Monday that is { - for( std::map::iterator i=gs->players.begin() ; i!=gs->players.end();i++) - i->second.bonuses.remove_if(Bonus::OneWeek); - BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes) - h->bonuses.remove_if(Bonus::OneWeek); + gs->globalEffects.popBonuses(Bonus::OneWeek); //works for children -> all game objs - gs->globalEffects.bonuses.remove_if(Bonus::OneWeek); - - Bonus b; - b.duration = Bonus::ONE_WEEK; - b.source = Bonus::SPECIAL_WEEK; - b.effectRange = Bonus::NO_LIMIT; - b.valType = Bonus::BASE_NUMBER; //certainly not intuitive + Bonus *b = new Bonus(); + b->duration = Bonus::ONE_WEEK; + b->source = Bonus::SPECIAL_WEEK; + b->effectRange = Bonus::NO_LIMIT; + b->valType = Bonus::BASE_NUMBER; //certainly not intuitive switch (specialWeek) { case DOUBLE_GROWTH: - b.val = 100; - b.type = Bonus::CREATURE_GROWTH_PERCENT; - b.limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[creatureid], false); + b->val = 100; + b->type = Bonus::CREATURE_GROWTH_PERCENT; + b->limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[creatureid], false); break; case BONUS_GROWTH: - b.val = 5; - b.type = Bonus::CREATURE_GROWTH; - b.limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[creatureid], false); + b->val = 5; + b->type = Bonus::CREATURE_GROWTH; + b->limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[creatureid], false); break; case DEITYOFFIRE: - b.val = 15; - b.type = Bonus::CREATURE_GROWTH; - b.limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[42], true); + b->val = 15; + b->type = Bonus::CREATURE_GROWTH; + b->limiter = new CCreatureTypeLimiter(*VLC->creh->creatures[42], true); break; case PLAGUE: - b.val = -100; //no basic creatures - b.type = Bonus::CREATURE_GROWTH_PERCENT; + b->val = -100; //no basic creatures + b->type = Bonus::CREATURE_GROWTH_PERCENT; break; default: - b.val = 0; + b->val = 0; } - if (b.val) - gs->globalEffects.bonuses.push_back(b); + if (b->val) + gs->globalEffects.addNewBonus(b); } } else //second pack is applied @@ -709,8 +697,6 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs ) i->second.daysWithoutCastle = 0; else i->second.daysWithoutCastle++; - - i->second.bonuses.remove_if(Bonus::OneDay); } if(resetBuilded) //reset amount of structures set in this turn in towns { @@ -786,28 +772,29 @@ DLL_EXPORT void BattleNextRound::applyGs( CGameState *gs ) //remove effects and restore only those with remaining turns in duration BonusList tmpEffects = s->bonuses; s->bonuses.removeSpells(Bonus::CASTED_SPELL); - for (BonusList::iterator it = tmpEffects.begin(); it != tmpEffects.end(); it++) + + BOOST_FOREACH(Bonus *it, tmpEffects) { it->turnsRemain--; if(it->turnsRemain > 0) - s->bonuses.push_back(*it); + s->addNewBonus(it); } //the same as above for features BonusList tmpFeatures = s->bonuses; s->bonuses.clear(); - BOOST_FOREACH(Bonus &b, tmpFeatures) + BOOST_FOREACH(Bonus *b, tmpFeatures) { - if((b.duration & Bonus::N_TURNS) != 0) + if((b->duration & Bonus::N_TURNS) != 0) { - b.turnsRemain--; - if(b.turnsRemain > 0) - s->bonuses.push_back(b); + b->turnsRemain--; + if(b->turnsRemain > 0) + s->addNewBonus(b); } else { - s->bonuses.push_back(b); + s->addNewBonus(b); } } } @@ -954,9 +941,10 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs ) if(s && !vstd::contains(resisted, s->ID)) //if stack exists and it didn't resist { BonusList remainingEff; + //WTF? for (BonusList::iterator it = remainingEff.begin(); it != remainingEff.end(); it++) { - if (onlyHelpful && VLC->spellh->spells[ it->id ].positiveness != 1) + if (onlyHelpful && VLC->spellh->spells[ (*it)->id ].positiveness != 1) { remainingEff.push_back(*it); } @@ -968,11 +956,11 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs ) //removing all features from spells BonusList tmpFeatures = s->bonuses; s->bonuses.clear(); - BOOST_FOREACH(Bonus &b, tmpFeatures) + BOOST_FOREACH(Bonus *b, tmpFeatures) { - const CSpell *sp = b.sourceSpell(); - if(sp && sp->positiveness != 1) //if(b.source != HeroBonus::SPELL_EFFECT || b.positiveness != 1) - s->bonuses.push_back(b); + const CSpell *sp = b->sourceSpell(); + if(sp && sp->positiveness != 1) //if(b->source != HeroBonus::SPELL_EFFECT || b.positiveness != 1) + s->addNewBonus(b); } } } @@ -1005,7 +993,7 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs ) bool ac[BFIELD_SIZE]; std::set occupyable; bool twoHex = VLC->creh->creatures[creID]->isDoubleWide(); - bool flying = vstd::contains(VLC->creh->creatures[creID]->bonuses, Bonus::FLYING); + bool flying = VLC->creh->creatures[creID]->isFlying();// vstd::contains(VLC->creh->creatures[creID]->bonuses, Bonus::FLYING); gs->curB->getAccessibilityMap(ac, twoHex, !side, true, occupyable, flying); for(int g=0; gcurB->generateNewStack(CStackInstance(creID, h->getPrimSkillLevel(2) * VLC->spellh->spells[id].powers[skill], h), gs->curB->stacks.size(), !side, 255, ter, pos); summonedStack->state.insert(SUMMONED); - //summonedStack->bonuses.push_back( makeFeature(HeroBonus::SUMMONED, HeroBonus::ONE_BATTLE, 0, 0, HeroBonus::BONUS_FROM_HERO) ); + //summonedStack->addNewBonus( makeFeature(HeroBonus::SUMMONED, HeroBonus::ONE_BATTLE, 0, 0, HeroBonus::BONUS_FROM_HERO) ); gs->curB->stacks.push_back(summonedStack); } @@ -1027,7 +1015,7 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs ) void actualizeEffect(CStack * s, Bonus & ef) { //actualizing effects vector - for (BonusList::iterator it = s->bonuses.begin(); it != s->bonuses.end(); it++) + BOOST_FOREACH(Bonus *it, s->bonuses) { if(it->id == ef.id) { @@ -1038,13 +1026,13 @@ void actualizeEffect(CStack * s, Bonus & ef) BonusList sf; s->stackEffectToFeature(sf, ef); - BOOST_FOREACH(const Bonus &fromEffect, sf) + BOOST_FOREACH(const Bonus *fromEffect, sf) { - BOOST_FOREACH(Bonus &stackBonus, s->bonuses) //TODO: optimize + BOOST_FOREACH(Bonus *stackBonus, s->bonuses) //TODO: optimize { - if(stackBonus.source == Bonus::SPELL_EFFECT && stackBonus.type == fromEffect.type && stackBonus.subtype == fromEffect.subtype) + if(stackBonus->source == Bonus::SPELL_EFFECT && stackBonus->type == fromEffect->type && stackBonus->subtype == fromEffect->subtype) { - stackBonus.turnsRemain = std::max(stackBonus.turnsRemain, ef.turnsRemain); + stackBonus->turnsRemain = std::max(stackBonus->turnsRemain, ef.turnsRemain); } } } @@ -1060,12 +1048,12 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs ) { if(effect.id == 42 || !s->hasBonus(Selector::source(Bonus::CASTED_SPELL, effect.id)))//disrupting ray or not on the list - just add { - s->bonuses.push_back(effect); + s->addNewBonus(new Bonus(effect)); BonusList sf; s->stackEffectToFeature(sf, effect); - BOOST_FOREACH(const Bonus &fromEffect, sf) + BOOST_FOREACH(Bonus *fromEffect, sf) { - s->bonuses.push_back(fromEffect); + s->addNewBonus(fromEffect); } } else //just actualize @@ -1109,7 +1097,7 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs ) changedStack->state.insert(ALIVE); if(healedStacks[g].lowLevelResurrection) changedStack->state.insert(SUMMONED); - //changedStack->bonuses.push_back( makeFeature(HeroBonus::SUMMONED, HeroBonus::ONE_BATTLE, 0, 0, HeroBonus::BONUS_FROM_HERO) ); + //changedStack->addNewBonus( makeFeature(HeroBonus::SUMMONED, HeroBonus::ONE_BATTLE, 0, 0, HeroBonus::BONUS_FROM_HERO) ); } //int missingHPfirst = changedStack->MaxHealth() - changedStack->firstHPleft; int res = std::min( healedStacks[g].healedHP / changedStack->MaxHealth() , changedStack->baseAmount - changedStack->count ); @@ -1127,9 +1115,10 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs ) //removal of negative effects if(resurrected) { + for (BonusList::iterator it = changedStack->bonuses.begin(); it != changedStack->bonuses.end(); it++) { - if(VLC->spellh->spells[it->id].positiveness < 0) + if(VLC->spellh->spells[(*it)->id].positiveness < 0) { changedStack->bonuses.erase(it); } @@ -1139,12 +1128,12 @@ DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs ) BonusList tmpFeatures = changedStack->bonuses; changedStack->bonuses.clear(); - BOOST_FOREACH(Bonus &b, tmpFeatures) + BOOST_FOREACH(Bonus *b, tmpFeatures) { - const CSpell *s = b.sourceSpell(); + const CSpell *s = b->sourceSpell(); if(s && s->positiveness >= 0) { - changedStack->bonuses.push_back(b); + changedStack->addNewBonus(b); } } } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 6aa8cee46..3da69efd4 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -365,18 +365,18 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance { BonusList bl; hero1->getBonuses(bl, Selector::type(Bonus::OPENING_BATTLE_SPELL)); - BOOST_FOREACH (Bonus b, bl) + BOOST_FOREACH (Bonus *b, bl) { - handleSpellCasting(b.subtype, 3, -1, 0, hero1->tempOwner, NULL, hero2, b.val); + handleSpellCasting(b->subtype, 3, -1, 0, hero1->tempOwner, NULL, hero2, b->val); } } if (hero2 && hero2->hasBonusOfType(Bonus::OPENING_BATTLE_SPELL)) { BonusList bl; hero2->getBonuses(bl, Selector::type(Bonus::OPENING_BATTLE_SPELL)); - BOOST_FOREACH (Bonus b, bl) + BOOST_FOREACH (Bonus *b, bl) { - handleSpellCasting(b.subtype, 3, -1, 1, hero2->tempOwner, NULL, hero1, b.val); + handleSpellCasting(b->subtype, 3, -1, 1, hero2->tempOwner, NULL, hero1, b->val); } } @@ -1664,15 +1664,15 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc { if(town->subID == 0 && vstd::contains(town->builtBuildings,22)) //castle, brotherhood of sword built for(int g=0; gbonuses.push_back(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 2, Bonus::TOWN_STRUCTURE)); + stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 2, Bonus::TOWN_STRUCTURE)); else if(vstd::contains(town->builtBuildings,5)) //tavern is built for(int g=0; gbonuses.push_back(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 1, Bonus::TOWN_STRUCTURE)); + stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 1, Bonus::TOWN_STRUCTURE)); if(town->subID == 1 && vstd::contains(town->builtBuildings,21)) //rampart, fountain of fortune is present for(int g=0; gbonuses.push_back(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, 2, Bonus::TOWN_STRUCTURE)); + stacks[g]->addNewBonus(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, 2, Bonus::TOWN_STRUCTURE)); } } @@ -1726,9 +1726,9 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc for(int g=0; gtype->isGood()) - stacks[g]->bonuses.push_back(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_OVERLAY)); + stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_OVERLAY)); else if (stacks[g]->type->isEvil()) - stacks[g]->bonuses.push_back(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)); + stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)); } break; } @@ -1738,7 +1738,7 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc { if(stacks[g]->type->faction == -1) //+2 luck bonus for neutral creatures { - stacks[g]->bonuses.push_back(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, 2, Bonus::TERRAIN_OVERLAY)); + stacks[g]->addNewBonus(makeFeature(Bonus::LUCK, Bonus::ONE_BATTLE, 0, 2, Bonus::TERRAIN_OVERLAY)); } } break; @@ -1748,9 +1748,9 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc for(int g=0; gtype->isGood()) - stacks[g]->bonuses.push_back(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)); + stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, -1, Bonus::TERRAIN_OVERLAY)); else if (stacks[g]->type->isEvil()) - stacks[g]->bonuses.push_back(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_OVERLAY)); + stacks[g]->addNewBonus(makeFeature(Bonus::MORALE, Bonus::ONE_BATTLE, 0, 1, Bonus::TERRAIN_OVERLAY)); } break; } @@ -1758,8 +1758,8 @@ void CGameHandler::setupBattle(BattleInfo * curB, int3 tile, const CArmedInstanc { for(int g=0; gbonuses.push_back(makeFeature(Bonus::NO_MORALE, Bonus::ONE_BATTLE, 0, 0, Bonus::TERRAIN_OVERLAY)); - stacks[g]->bonuses.push_back(makeFeature(Bonus::NO_LUCK, Bonus::ONE_BATTLE, 0, 0, Bonus::TERRAIN_OVERLAY)); + stacks[g]->addNewBonus(makeFeature(Bonus::NO_MORALE, Bonus::ONE_BATTLE, 0, 0, Bonus::TERRAIN_OVERLAY)); + stacks[g]->addNewBonus(makeFeature(Bonus::NO_LUCK, Bonus::ONE_BATTLE, 0, 0, Bonus::TERRAIN_OVERLAY)); } const CGHeroInstance * cHero = NULL; @@ -4213,11 +4213,11 @@ static std::vector calculateResistedStacks(const CSpell * sp, const CGHero bl.insert(bl.end(), b2.begin(), b2.end()); - BOOST_FOREACH(Bonus bb, bl) + BOOST_FOREACH(Bonus *bb, bl) { - if( (bb.type == Bonus::SPELL_IMMUNITY && bb.subtype == sp->id || //100% sure spell immunity - bb.type == Bonus::LEVEL_SPELL_IMMUNITY && bb.val >= sp->level) //some creature abilities have level 0 - && bb.source != Bonus::CREATURE_ABILITY) + if( (bb->type == Bonus::SPELL_IMMUNITY && bb->subtype == sp->id || //100% sure spell immunity + bb->type == Bonus::LEVEL_SPELL_IMMUNITY && bb->val >= sp->level) //some creature abilities have level 0 + && bb->source != Bonus::CREATURE_ABILITY) { ret.push_back((*it)->ID); continue; @@ -5026,9 +5026,9 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat ) const CStack * attacker = gs->curB->getStack(bat.stackAttacking); if( attacker->hasBonusOfType(Bonus::SPELL_AFTER_ATTACK) ) { - BOOST_FOREACH(const Bonus & sf, attacker->getBonuses(Selector::type(Bonus::SPELL_AFTER_ATTACK))) + BOOST_FOREACH(const Bonus *sf, attacker->getBonuses(Selector::type(Bonus::SPELL_AFTER_ATTACK))) { - if (sf.type == Bonus::SPELL_AFTER_ATTACK) + if (sf->type == Bonus::SPELL_AFTER_ATTACK) { const CStack * oneOfAttacked = NULL; for(int g=0; gsubtype; + int spellLevel = sf->val; + int chance = sf->additionalInfo % 1000; + //int meleeRanged = sf->additionalInfo / 1000; int destination = oneOfAttacked->position; //check if spell should be casted (probability handling) if( rand()%100 >= chance )