From 7e9033c44fd21c60153db006f8305244b860b814 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Sat, 23 Apr 2011 09:57:51 +0000 Subject: [PATCH] Fixed #668 and #718. Hero is now properly attached to his special. Compile fix for ERM Parser. --- config/spell_info.txt | 2 +- lib/BattleState.cpp | 40 +-------------------------- lib/CCreatureSet.cpp | 2 +- lib/CObjectHandler.cpp | 1 + lib/CSpellHandler.cpp | 1 + lib/ERMParser.cpp | 2 +- lib/NetPacks.h | 3 +- lib/NetPacksLib.cpp | 28 +++++++++++++++++-- server/CGameHandler.cpp | 61 +++++++++++++++++++++++++++++++++++++---- 9 files changed, 89 insertions(+), 51 deletions(-) diff --git a/config/spell_info.txt b/config/spell_info.txt index 496cf4fde..03a001860 100644 --- a/config/spell_info.txt +++ b/config/spell_info.txt @@ -47,7 +47,7 @@ 44 1 25 0 0 0 X 45 -1 56 0 0 0 X 46 1 54 0 0 0 X -47 -1 14 0 0 0 X +47 -1 14 0 0 0 0 48 1 0 0 0 0 X 49 1 20 0 0 0 X 50 -1 30 0 0 0 X diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index d836cda74..443273205 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -2011,34 +2011,8 @@ const Bonus * CStack::getEffect( ui16 id, int turn /*= 0*/ ) const } void CStack::stackEffectToFeature(std::vector & sf, const Bonus & sse) -{ +{ si32 power = VLC->spellh->spells[sse.sid]->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.sid) { case 27: //shield @@ -2075,13 +2049,6 @@ void CStack::stackEffectToFeature(std::vector & sf, const Bonus & sse) sf.back().sid = sse.sid; 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().sid = sse.sid; -// sf.back().valType = Bonus::PERCENT_TO_ALL; -// } sf.push_back(featureGenerator(Bonus::ALWAYS_MAXIMUM_DAMAGE, -1, power, sse.turnsRemain)); sf.back().sid = sse.sid; break; @@ -2143,11 +2110,6 @@ void CStack::stackEffectToFeature(std::vector & sf, const Bonus & sse) sf.back().sid = sse.sid; break; case 55: //slayer -// if (bonus) //Coronius -// { -// sf.push_back(featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, sse.turnsRemain)); -// sf.back().sid = sse.sid; -// } sf.push_back(featureGenerator(Bonus::SLAYER, 0, sse.val, sse.turnsRemain)); sf.back().sid = sse.sid; break; diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 271ada9ab..d70b3fb52 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -583,7 +583,7 @@ std::string CStackInstance::bonusToString(Bonus *bonus, bool description) const boost::algorithm::replace_first(text, "%s", VLC->creh->creatures[bonus->subtype]->namePl); break; case Bonus::SPELL_AFTER_ATTACK: - boost::algorithm::replace_first(text, "%d", boost::lexical_cast(bonus->additionalInfo)); + boost::algorithm::replace_first(text, "%d", boost::lexical_cast(bonus->additionalInfo % 1000)); boost::algorithm::replace_first(text, "%s", VLC->spellh->spells[bonus->subtype]->name); break; default: diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 39e5a77c5..002244478 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -735,6 +735,7 @@ CGHeroInstance::CGHeroInstance() boat = NULL; secSkills.push_back(std::make_pair(-1, -1)); speciality.nodeType = CBonusSystemNode::SPECIALITY; + attachTo(&speciality); //do we evert need to detach it? } void CGHeroInstance::initHero(int SUBID) diff --git a/lib/CSpellHandler.cpp b/lib/CSpellHandler.cpp index 9fd83cad4..9d2ebd1a6 100644 --- a/lib/CSpellHandler.cpp +++ b/lib/CSpellHandler.cpp @@ -291,6 +291,7 @@ void CSpellHandler::loadSpells() nsp->mainEffectAnim = -1; spells.push_back(nsp); } + boost::replace_first (spells[47]->attributes, "2", ""); // disrupting ray will now affect single creature //loading of additional spell traits std::ifstream ast; ast.open(DATA_DIR "/config/spell_info.txt", std::ios::binary); diff --git a/lib/ERMParser.cpp b/lib/ERMParser.cpp index a0408376b..de598857b 100644 --- a/lib/ERMParser.cpp +++ b/lib/ERMParser.cpp @@ -559,6 +559,6 @@ void ERMParser::repairEncoding( char * str, int len ) const #else ERMParser::ERMParser(std::string file){} -std::vector ERMParser::parseFile() {} +std::vector ERMParser::parseFile() {std::vector dummy; return dummy;} //compile fix #endif diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 3e4d003c7..5221119ff 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1364,9 +1364,10 @@ struct SetStackEffect : public CPackForClient //3010 std::vector stacks; //affected stacks (IDs) std::vector effect; //bonuses to apply + std::vector> uniqueBonuses; //bonuses per single stack template void serialize(Handler &h, const int version) { - h & stacks & effect; + h & stacks & effect & uniqueBonuses; } }; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index c7f16ea2f..74852e59c 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1121,17 +1121,27 @@ void actualizeEffect(CStack * s, const std::vector & ef) } } } - +} +void actualizeEffect(CStack * s, const Bonus & ef) +{ + BOOST_FOREACH(Bonus *stackBonus, s->bonuses) //TODO: optimize + { + if(stackBonus->source == Bonus::SPELL_EFFECT && stackBonus->type == ef.type && stackBonus->subtype == ef.subtype) + { + stackBonus->turnsRemain = std::max(stackBonus->turnsRemain, ef.turnsRemain); + } + } } DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs ) { + int id = effect.begin()->sid; //effects' source ID + BOOST_FOREACH(ui32 id, stacks) { CStack *s = gs->curB->getStack(id); if(s) { - int id = effect.begin()->sid; //effects' source ID if(id == 47 || !s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, id)))//disrupting ray or not on the list - just add { BOOST_FOREACH(Bonus &fromEffect, effect) @@ -1147,6 +1157,20 @@ DLL_EXPORT void SetStackEffect::applyGs( CGameState *gs ) else tlog1 << "Cannot find stack " << id << std::endl; } + typedef std::pair p; + BOOST_FOREACH(p para, uniqueBonuses) + { + CStack *s = gs->curB->getStack(para.first); + if (s) + { + if (!s->hasBonus(Selector::source(Bonus::SPELL_EFFECT, id) && Selector::typeSybtype(para.second.type, para.second.subtype))) + s->addNewBonus(new Bonus(para.second)); + else + actualizeEffect(s, effect); + } + else + tlog1 << "Cannot find stack " << para.first << std::endl; + } } DLL_EXPORT void StacksInjured::applyGs( CGameState *gs ) diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index f7edd91f0..83f037183 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -3439,6 +3439,7 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio sendAndApply(&si); break; } + // permanent effects case 27: //shield case 28: //air shield case 29: //fire shield @@ -3470,17 +3471,65 @@ void CGameHandler::handleSpellCasting( int spellID, int spellLvl, int destinatio case 62: //blind { SetStackEffect sse; - for(std::set::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) - { - if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell - continue; - sse.stacks.push_back((*it)->ID); - } Bonus pseudoBonus; pseudoBonus.sid = spellID; pseudoBonus.val = spellLvl; pseudoBonus.turnsRemain = gs->curB->calculateSpellDuration(spell, caster, usedSpellPower); CStack::stackEffectToFeature(sse.effect, pseudoBonus); + + const Bonus * bonus = caster->getBonus(Selector::typeSybtype(Bonus::SPECIAL_PECULIAR_ENCHANT, spellID)); + si32 power; + for(std::set::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) + { + if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell + continue; + sse.stacks.push_back((*it)->ID); + + //Apply hero specials - peculiar enchants + ui8 tier = (*it)->base->type->level; + if (bonus) + { + switch(bonus->additionalInfo) + { + case 0: //normal + { + switch(tier) + { + case 1: case 2: + power = 3; + break; + case 3: case 4: + power = 2; + break; + case 5: case 6: + power = 1; + break; + } + Bonus specialBonus(sse.effect.back()); + specialBonus.val = power; //it doesn't necessarily make sense for some spells, use it wisely + sse.uniqueBonuses.push_back (std::pair ((*it)->ID, specialBonus)); //additional premy to given effect + } + break; + case 1: //only Coronius as yet + { + power = std::max(5 - tier, 0); + Bonus specialBonus = CStack::featureGenerator(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK, power, pseudoBonus.turnsRemain); + specialBonus.sid = spellID; + sse.uniqueBonuses.push_back (std::pair ((*it)->ID, specialBonus)); //additional attack to Slayer effect + } + break; + } + } + if (caster->hasBonusOfType(Bonus::SPECIAL_BLESS_DAMAGE, spellID)) //TODO: better handling of bonus percentages + { + int damagePercent = caster->level * caster->valOfBonuses(Bonus::SPECIAL_BLESS_DAMAGE, 41) / tier; + Bonus specialBonus = CStack::featureGenerator(Bonus::CREATURE_DAMAGE, 0, damagePercent, pseudoBonus.turnsRemain); + specialBonus.valType = Bonus::PERCENT_TO_ALL; + specialBonus.sid = spellID; + sse.uniqueBonuses.push_back (std::pair ((*it)->ID, specialBonus)); + } + } + if(!sse.stacks.empty()) sendAndApply(&sse); break;