From 824d2b52dbb78492879b63d2825718e6fcca4f38 Mon Sep 17 00:00:00 2001 From: mateuszb Date: Thu, 20 Jan 2011 19:57:12 +0000 Subject: [PATCH] * more or less fixed spells * certain hero specialties are still broken --- client/CBattleInterface.cpp | 30 ++-- lib/BattleState.cpp | 331 ++++++++++++++++++------------------ lib/BattleState.h | 18 +- lib/HeroBonus.h | 32 ++-- lib/NetPacks.h | 2 +- lib/NetPacksLib.cpp | 32 ++-- server/CGameHandler.cpp | 18 +- 7 files changed, 233 insertions(+), 230 deletions(-) diff --git a/client/CBattleInterface.cpp b/client/CBattleInterface.cpp index a6b57c388..4c188113e 100644 --- a/client/CBattleInterface.cpp +++ b/client/CBattleInterface.cpp @@ -2788,26 +2788,32 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc ) void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse) { - if(sse.effect.id != -1) //can be -1 for defensive stance effect + int effID = sse.effect.back().id; + if(effID != -1) //can be -1 for defensive stance effect { for(std::vector::const_iterator ci = sse.stacks.begin(); ci!=sse.stacks.end(); ++ci) { - displayEffect(CGI->spellh->spells[sse.effect.id]->mainEffectAnim, curInt->cb->battleGetStackByID(*ci)->position); + displayEffect(CGI->spellh->spells[effID]->mainEffectAnim, curInt->cb->battleGetStackByID(*ci)->position); } } - else if (sse.effect.source == Bonus::OTHER && sse.effect.type == Bonus::PRIMARY_SKILL && sse.stacks.size() == 1) + else if (sse.stacks.size() == 1 && sse.effect.size() == 1) { - //defensive stance (I hope) - const CStack * stack = LOCPLINT->cb->battleGetStackByID(*sse.stacks.begin()); - int txtid = 120; + const Bonus & bns = sse.effect.back(); + if (bns.source == Bonus::OTHER && bns.type == Bonus::PRIMARY_SKILL) + { + //defensive stance (I hope) + const CStack * stack = LOCPLINT->cb->battleGetStackByID(*sse.stacks.begin()); + int txtid = 120; - if(stack->count != 1) - txtid++; //move to plural text + if(stack->count != 1) + txtid++; //move to plural text - char txt[4000]; - int val = stack->Defense() - (stack->Defense() * 100 )/ (100 + sse.effect.val); - sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(), (stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str(), val); - console->addText(txt); + char txt[4000]; + int val = stack->Defense() - (stack->Defense() * 100 )/ (100 + bns.val); + sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(), (stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str(), val); + console->addText(txt); + } + } diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index e49912067..35435b695 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -1684,171 +1684,172 @@ const Bonus * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const return NULL; } -void CStack::stackEffectToFeature(BonusList & sf, const Bonus & sse) +void CStack::stackEffectToFeature(std::vector & 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]; + //why, why, WHY this code is here?!? +// 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(makeFeatureVal(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(makeFeatureVal(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 @@ -1904,7 +1905,7 @@ THex CStack::occupiedHex() const } BonusList CStack::getSpellBonuses() const { - return getBonuses(Selector::sourceTypeSel(Bonus::CASTED_SPELL)); + return getBonuses(Selector::sourceTypeSel(Bonus::SPELL_EFFECT)); } std::vector CStack::activeSpells() const diff --git a/lib/BattleState.h b/lib/BattleState.h index aa5625990..f9b8c7c02 100644 --- a/lib/BattleState.h +++ b/lib/BattleState.h @@ -148,23 +148,23 @@ public: bool canMove(int turn = 0) const; //if stack can move ui32 Speed(int turn = 0) const; //get speed of creature with all modificators BonusList getSpellBonuses() const; - void stackEffectToFeature(BonusList & sf, const Bonus & sse); + static void stackEffectToFeature(std::vector & sf, const Bonus & sse); std::vector activeSpells() const; //returns vector of active spell IDs sorted by time of cast const CGHeroInstance *getMyHero() const; //if stack belongs to hero (directly or was by him summoned) returns hero, NULL otherwise - static inline Bonus *featureGenerator(Bonus::BonusType type, si16 subtype, si32 value, ui16 turnsRemain, si32 additionalInfo = 0, si32 limit = Bonus::NO_LIMIT) + static inline Bonus featureGenerator(Bonus::BonusType type, si16 subtype, si32 value, ui16 turnsRemain, si32 additionalInfo = 0, si32 limit = Bonus::NO_LIMIT) { - Bonus *hb = makeFeature(type, Bonus::N_TURNS, subtype, value, Bonus::SPELL_EFFECT, turnsRemain, additionalInfo); - hb->effectRange = limit; - hb->source = Bonus::CASTED_SPELL; //right? + Bonus hb = makeFeatureVal(type, Bonus::N_TURNS, subtype, value, Bonus::SPELL_EFFECT, turnsRemain, additionalInfo); + hb.effectRange = limit; + hb.source = Bonus::SPELL_EFFECT; return hb; } - static inline Bonus *featureGeneratorVT(Bonus::BonusType type, si16 subtype, si32 value, ui16 turnsRemain, ui8 valType) + static inline Bonus featureGeneratorVT(Bonus::BonusType type, si16 subtype, si32 value, ui16 turnsRemain, ui8 valType) { - Bonus *ret(makeFeature(type, Bonus::N_TURNS, subtype, value, Bonus::SPELL_EFFECT, turnsRemain)); - ret->valType = valType; - ret->source = Bonus::CASTED_SPELL; //right? + Bonus ret = makeFeatureVal(type, Bonus::N_TURNS, subtype, value, Bonus::SPELL_EFFECT, turnsRemain); + ret.valType = valType; + ret.source = Bonus::SPELL_EFFECT; return ret; } diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index a59504781..6803096e1 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -184,10 +184,9 @@ struct DLL_EXPORT Bonus }; enum BonusSource { - ARTIFACT, - ARTIFACT_INSTANCE, - OBJECT, - CASTED_SPELL, + ARTIFACT, + ARTIFACT_INSTANCE, + OBJECT, CREATURE_ABILITY, TERRAIN_NATIVE, TERRAIN_OVERLAY, @@ -458,20 +457,27 @@ namespace NBonus }; //generates HeroBonus from given data -inline Bonus* makeFeature(Bonus::BonusType type, ui8 duration, si16 subtype, si32 value, Bonus::BonusSource source, ui16 turnsRemain = 0, si32 additionalInfo = 0) +inline Bonus makeFeatureVal(Bonus::BonusType type, ui8 duration, si16 subtype, si32 value, Bonus::BonusSource source, ui16 turnsRemain = 0, si32 additionalInfo = 0) { - Bonus* sf = new Bonus(); - sf->type = type; - sf->duration = duration; - sf->source = source; - sf->turnsRemain = turnsRemain; - sf->subtype = subtype; - sf->val = value; - sf->additionalInfo = additionalInfo; + Bonus sf; + sf.type = type; + sf.duration = duration; + sf.source = source; + sf.turnsRemain = turnsRemain; + sf.subtype = subtype; + sf.val = value; + sf.additionalInfo = additionalInfo; return sf; } +//generates HeroBonus from given data +inline Bonus * makeFeature(Bonus::BonusType type, ui8 duration, si16 subtype, si32 value, Bonus::BonusSource source, ui16 turnsRemain = 0, si32 additionalInfo = 0) +{ + return new Bonus(makeFeatureVal(type, duration, subtype, value, source, turnsRemain, additionalInfo)); +} + + class DLL_EXPORT CSelectorsConjunction { const CSelector first, second; diff --git a/lib/NetPacks.h b/lib/NetPacks.h index e5e017d58..ff10b1d12 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1327,7 +1327,7 @@ struct SetStackEffect : public CPackForClient //3010 void applyCl(CClient *cl); std::vector stacks; //affected stacks (IDs) - Bonus effect; //type of effect + std::vector effect; //bonuses to apply template void serialize(Handler &h, const int version) { h & stacks & effect; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index dc85ebcba..9635374e7 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -888,7 +888,7 @@ 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); + s->bonuses.removeSpells(Bonus::SPELL_EFFECT); BOOST_FOREACH(Bonus *it, tmpEffects) { @@ -1072,7 +1072,7 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs ) } } - s->bonuses.removeSpells(Bonus::CASTED_SPELL); //removing all effects + s->bonuses.removeSpells(Bonus::SPELL_EFFECT); //removing all effects s->bonuses = remainingEff; //assigning effects that should remain //removing all features from spells @@ -1135,27 +1135,17 @@ DLL_EXPORT void BattleSpellCast::applyGs( CGameState *gs ) } } -void actualizeEffect(CStack * s, Bonus & ef) +void actualizeEffect(CStack * s, const std::vector & ef) { - //actualizing effects vector - BOOST_FOREACH(Bonus *it, s->bonuses) - { - if(it->id == ef.id) - { - it->turnsRemain = std::max(it->turnsRemain, ef.turnsRemain); - } - } //actualizing features vector - BonusList sf; - s->stackEffectToFeature(sf, ef); - BOOST_FOREACH(const Bonus *fromEffect, sf) + BOOST_FOREACH(const Bonus &fromEffect, ef) { 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, fromEffect.turnsRemain); } } } @@ -1169,14 +1159,12 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs ) CStack *s = gs->curB->getStack(id); if(s) { - if(effect.id == 42 || !s->hasBonus(Selector::source(Bonus::CASTED_SPELL, effect.id)))//disrupting ray or not on the list - just add + int id = effect.begin()->id; //effects' source ID + if(id == 47 || !s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, id)))//disrupting ray or not on the list - just add { - s->addNewBonus(new Bonus(effect)); - BonusList sf; - s->stackEffectToFeature(sf, effect); - BOOST_FOREACH(Bonus *fromEffect, sf) + BOOST_FOREACH(Bonus &fromEffect, effect) { - s->addNewBonus(fromEffect); + s->addNewBonus( new Bonus(fromEffect)); } } else //just actualize diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1e7f89756..2e2a58ff5 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3037,7 +3037,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba ) { //defensive stance SetStackEffect sse; - sse.effect = Bonus(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, 20, -1, PrimarySkill::DEFENSE, Bonus::PERCENT_TO_ALL); + sse.effect.push_back( Bonus(Bonus::STACK_GETS_TURN, Bonus::PRIMARY_SKILL, Bonus::OTHER, 20, -1, PrimarySkill::DEFENSE, Bonus::PERCENT_TO_ALL) ); sse.stacks.push_back(ba.stackNumber); sendAndApply(&sse); @@ -3644,9 +3644,11 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio continue; sse.stacks.push_back((*it)->ID); } - sse.effect.id = spellID; - sse.effect.val = spellLvl; - sse.effect.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower); + Bonus pseudoBonus; + pseudoBonus.id = spellID; + pseudoBonus.val = spellLvl; + pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower); + CStack::stackEffectToFeature(sse.effect, pseudoBonus); if(!sse.stacks.empty()) sendAndApply(&sse); break; @@ -4444,7 +4446,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p COMPLAIN_RET("Destination tile doesn't exist!"); if(!h->movement) COMPLAIN_RET("Hero needs movement points to cast Dimension Door!"); - if(h->getBonusesCount(Bonus::CASTED_SPELL, Spells::DIMENSION_DOOR) >= s->powers[schoolLevel]) //limit casts per turn + if(h->getBonusesCount(Bonus::SPELL_EFFECT, Spells::DIMENSION_DOOR) >= s->powers[schoolLevel]) //limit casts per turn { InfoWindow iw; iw.player = h->tempOwner; @@ -4456,7 +4458,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p GiveBonus gb; gb.id = h->id; - gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::CASTED_SPELL, 0, Spells::DIMENSION_DOOR); + gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::NONE, Bonus::SPELL_EFFECT, 0, Spells::DIMENSION_DOOR); sendAndApply(&gb); if(!dest->isClear(curr)) //wrong dest tile @@ -4489,7 +4491,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p GiveBonus gb; gb.id = h->id; - gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::FLYING_MOVEMENT, Bonus::CASTED_SPELL, 0, Spells::FLY, subtype); + gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::FLYING_MOVEMENT, Bonus::SPELL_EFFECT, 0, Spells::FLY, subtype); sendAndApply(&gb); } break; @@ -4499,7 +4501,7 @@ bool CGameHandler::castSpell(const CGHeroInstance *h, int spellID, const int3 &p GiveBonus gb; gb.id = h->id; - gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::WATER_WALKING, Bonus::CASTED_SPELL, 0, Spells::FLY, subtype); + gb.bonus = Bonus(Bonus::ONE_DAY, Bonus::WATER_WALKING, Bonus::SPELL_EFFECT, 0, Spells::FLY, subtype); sendAndApply(&gb); } break;