diff --git a/CBattleInterface.cpp b/CBattleInterface.cpp index 5b00bb497..a7d8b2a6e 100644 --- a/CBattleInterface.cpp +++ b/CBattleInterface.cpp @@ -261,28 +261,6 @@ CBattleInterface::CBattleInterface(CCreatureSet * army1, CCreatureSet * army2, C SDL_SetColorKey(idToObstacle[obst[t].ID]->ourImages[n].bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(idToObstacle[obst[t].ID]->ourImages[n].bitmap->format,0,255,255)); } } - - //initializing spellToEffect - spellToEffect[17] = 1; //lightning bolt - spellToEffect[18] = 10; //implosion - spellToEffect[27] = 27; //shield - spellToEffect[28] = 2; //air shield - spellToEffect[35] = 41; //dispel - spellToEffect[41] = 36; //bless - spellToEffect[42] = 40; //curse - spellToEffect[43] = 4; //bloodlust - spellToEffect[45] = 56; //weakness - spellToEffect[46] = 54; //stone skin - spellToEffect[47] = 14; //disrupting ray - spellToEffect[48] = 0; //prayer - spellToEffect[49] = 20; //mirth - spellToEffect[50] = 30; //sorrow - spellToEffect[51] = 18; //fortune - spellToEffect[52] = 48; //misfortune - spellToEffect[53] = 31; //haste - spellToEffect[54] = 19; //slow - spellToEffect[56] = 17; //frenzy - spellToEffect[61] = 42; //forgetfulness } CBattleInterface::~CBattleInterface() @@ -1863,8 +1841,11 @@ void CBattleInterface::spellCasted(SpellCasted * sc) SDL_SetClipRect(screen, &buf); //restoring previous clip rect break; //for 15 and 16 cases } + case 17: //lightning bolt + displayEffect(1, sc->tile); + displayEffect(CGI->spellh->spells[sc->id].mainEffectAnim, sc->tile); case 35: //dispel - displayEffect(spellToEffect[sc->id], sc->tile); + displayEffect(CGI->spellh->spells[sc->id].mainEffectAnim, sc->tile); } //switch(sc->id) } @@ -1872,7 +1853,7 @@ void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse) { for(std::set::const_iterator ci = sse.stacks.begin(); ci!=sse.stacks.end(); ++ci) { - displayEffect(spellToEffect[sse.effect.id], LOCPLINT->cb->battleGetStackByID(*ci)->position); + displayEffect(CGI->spellh->spells[sse.effect.id].mainEffectAnim, LOCPLINT->cb->battleGetStackByID(*ci)->position); } redrawBackgroundWithHexes(activeStack); } diff --git a/CBattleInterface.h b/CBattleInterface.h index 85938ae25..ddb036fb0 100644 --- a/CBattleInterface.h +++ b/CBattleInterface.h @@ -165,7 +165,6 @@ private: std::map< int, CDefHandler * > idToProjectile; //projectiles of creaures (creatureID, defhandler) std::map< int, CDefHandler * > idToObstacle; //obstacles located on the battlefield std::map< int, bool > creDir; // - std::map< int, int > spellToEffect; //which effect should be played when different spells are casted (spellID, effectID) unsigned char animCount; int activeStack; //number of active stack; -1 - no one int mouseHoveredStack; //stack hovered by mouse; if -1 -> none diff --git a/config/spell_info.txt b/config/spell_info.txt index e38fc45bb..56684ce25 100644 --- a/config/spell_info.txt +++ b/config/spell_info.txt @@ -1,73 +1,73 @@ //additional spell info, not included in original heroes III files -//[spellID - -1 is the end of data in file] [-1 -> spell is negative for influenced creatures; 0 - spell is indifferent for them; 1 - spell is poitive for them] [spell range description in SRSL, none magic] [basic] [advanced] [expert] -0 0 X X X X -1 0 X X X X -2 0 X X X X -3 0 X X X X -4 0 X X X X -5 0 X X X X -6 0 X X X X -7 0 X X X X -8 0 X X X X -9 0 X X X X -10 0 X X X X -11 0 X X X X -12 0 0 0 0 0 -13 0 0 0 0 0 -14 0 X X X X -15 -1 0 0 0 0 -16 -1 0 0 0 0 -17 -1 0 0 0 0 -18 -1 0 0 0 0 -19 -1 0 0 0 0 -20 -1 1 1 1 1 -21 -1 0,1 0,1 0,1 0,1 -22 -1 0-2 0-2 0-2 0-2 -23 -1 0,1 0,1 0,1 0,1 -24 -1 X X X X -25 -1 X X X X -26 -1 X X X X -27 1 0 0 0 X -28 1 0 0 0 X -29 1 0 0 0 X -30 1 0 0 0 X -31 1 0 0 0 X -32 1 0 0 0 X -33 1 0 0 0 X -34 1 0 0 0 X -35 0 0 0 0 X -36 1 0 0 0 0 -37 1 0 0 0 0 -38 1 0 0 0 0 -39 1 0 0 0 0 -40 1 0 0 0 0 -41 1 0 0 0 X -42 -1 0 0 0 X -43 1 0 0 0 X -44 1 0 0 0 X -45 -1 0 0 0 X -46 1 0 0 0 X -47 -1 0 0 0 X -48 1 0 0 0 X -49 1 0 0 0 X -50 -1 0 0 0 X -51 1 0 0 0 X -52 -1 0 0 0 X -53 1 0 0 0 X -54 -1 0 0 0 X -55 1 0 0 0 0 -56 1 0 0 0 0 -57 -1 0 0 0 0 -58 1 0 0 0 X -59 -1 0 0 0-1 0-2 -60 -1 0 0 0 0 -61 -1 0 0 0 X -62 -1 0 0 0 0 -63 1 0 0 0 0 -64 0 X X X X -65 1 0 0 0 0 -66 0 X X X X -67 0 X X X X -68 0 X X X X -69 0 X X X X +//[spellID - -1 is the end of data in file] [-1 -> spell is negative for influenced creatures; 0 - spell is indifferent for them; 1 - spell is poitive for them] [main effect animation (AC format), -1 - none] [spell range description in SRSL, none magic] [basic] [advanced] [expert] +0 0 -1 X X X X +1 0 -1 X X X X +2 0 -1 X X X X +3 0 -1 X X X X +4 0 -1 X X X X +5 0 -1 X X X X +6 0 -1 X X X X +7 0 -1 X X X X +8 0 -1 X X X X +9 0 -1 X X X X +10 0 -1 X X X X +11 0 -1 X X X X +12 0 -1 0 0 0 0 +13 0 -1 0 0 0 0 +14 0 -1 X X X X +15 -1 64 0 0 0 0 +16 -1 46 0 0 0 0 +17 -1 38 0 0 0 0 +18 -1 10 0 0 0 0 +19 -1 -1 0 0 0 0 +20 -1 45 1 1 1 1 +21 -1 53 0,1 0,1 0,1 0,1 +22 -1 9 0-2 0-2 0-2 0-2 +23 -1 16 0,1 0,1 0,1 0,1 +24 -1 8 X X X X +25 -1 29 X X X X +26 -1 12 X X X X +27 1 27 0 0 0 X +28 1 2 0 0 0 X +29 1 -1 0 0 0 X +30 1 22 0 0 0 X +31 1 24 0 0 0 X +32 1 23 0 0 0 X +33 1 26 0 0 0 X +34 1 -1 0 0 0 X +35 0 41 0 0 0 X +36 1 -1 0 0 0 0 +37 1 -1 0 0 0 0 +38 1 -1 0 0 0 0 +39 1 -1 0 0 0 0 +40 1 -1 0 0 0 0 +41 1 36 0 0 0 X +42 -1 40 0 0 0 X +43 1 4 0 0 0 X +44 1 -1 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 +48 1 0 0 0 0 X +49 1 20 0 0 0 X +50 -1 30 0 0 0 X +51 1 18 0 0 0 X +52 -1 48 0 0 0 X +53 1 31 0 0 0 X +54 -1 19 0 0 0 X +55 1 -1 0 0 0 0 +56 1 17 0 0 0 0 +57 -1 -1 0 0 0 0 +58 1 -1 0 0 0 X +59 -1 -1 0 0 0-1 0-2 +60 -1 -1 0 0 0 0 +61 -1 42 0 0 0 X +62 -1 -1 0 0 0 0 +63 1 -1 0 0 0 0 +64 0 -1 X X X X +65 1 -1 0 0 0 0 +66 0 -1 X X X X +67 0 -1 X X X X +68 0 -1 X X X X +69 0 -1 X X X X -1 \ No newline at end of file diff --git a/hch/CSpellHandler.cpp b/hch/CSpellHandler.cpp index 30d1d2d8d..b7ebac654 100644 --- a/hch/CSpellHandler.cpp +++ b/hch/CSpellHandler.cpp @@ -255,6 +255,7 @@ void CSpellHandler::loadSpells() nsp.id = spells.size(); nsp.combatSpell = combSpells; nsp.creatureAbility = creatureAbility; + nsp.mainEffectAnim = -1; spells.push_back(nsp); } //loading of additional spell traits @@ -268,15 +269,18 @@ void CSpellHandler::loadSpells() { //reading header std::string dump; - for(int i=0; i<52; ++i) ast>>dump; + for(int i=0; i<60; ++i) ast>>dump; //reading exact info int spellID; ast>>spellID; while(spellID != -1) { int buf; - ast>>buf; + ast >> buf; spells[spellID].positiveness = buf; + ast >> buf; + spells[spellID].mainEffectAnim = buf; + spells[spellID].range.resize(4); for(int g=0; g<4; ++g) ast>>spells[spellID].range[g]; diff --git a/hch/CSpellHandler.h b/hch/CSpellHandler.h index e76de1153..8daaf3b1d 100644 --- a/hch/CSpellHandler.h +++ b/hch/CSpellHandler.h @@ -38,12 +38,12 @@ public: si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative std::vector range; //description of spell's range in SRSL by magic school level std::set rangeInHexes(unsigned int centralHex, ui8 schoolLvl ) const; //convert range to specific hexes - + si16 mainEffectAnim; //main spell effect animation, in AC format (or -1 when none) template void serialize(Handler &h, const int version) { h & id & name & abbName & descriptions & level & earth & water & fire & air & power & costs - & powers & probabilities & AIVals & attributes & combatSpell & creatureAbility & positiveness & range; + & powers & probabilities & AIVals & attributes & combatSpell & creatureAbility & positiveness & range & mainEffectAnim; } }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 69953522b..74ad89117 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2246,6 +2246,81 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message ) } } +ui32 calculateSpellDmg(const CSpell * sp, const CGHeroInstance * caster, const CStack * affectedCreature) +{ + ui32 ret = 0; //value to return + switch(sp->id) + { + case 15: //magic arrow + { + ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 16: //ice bolt + { + ret = caster->getPrimSkillLevel(2) * 20 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 17: //lightning bolt + { + ret = caster->getPrimSkillLevel(2) * 25 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 18: //implosion + { + ret = caster->getPrimSkillLevel(2) * 75 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 20: //frost ring + { + ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 21: //fireball + { + ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 22: //inferno + { + ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 23: //meteor shower + { + ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 24: //death ripple + { + ret = caster->getPrimSkillLevel(2) * 5 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 25: //destroy undead + { + ret = caster->getPrimSkillLevel(2) * 10 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + case 26: //armageddon + { + ret = caster->getPrimSkillLevel(2) * 50 + sp->powers[caster->getSpellSchoolLevel(sp)]; + } + } + //applying protections - when spell has more then one elements, only one protection should be applied (I think) + if(sp->air && affectedCreature->getEffect(30)) //air spell & protection from air + { + ret *= VLC->spellh->spells[30].powers[affectedCreature->getEffect(30)->level]; + ret /= 100; + } + else if(sp->fire && affectedCreature->getEffect(31)) //fire spell & protection from fire + { + ret *= VLC->spellh->spells[31].powers[affectedCreature->getEffect(31)->level]; + ret /= 100; + } + else if(sp->water && affectedCreature->getEffect(32)) //water spell & protection from water + { + ret *= VLC->spellh->spells[32].powers[affectedCreature->getEffect(32)->level]; + ret /= 100; + } + else if (sp->earth && affectedCreature->getEffect(33)) //earth spell & protection from earth + { + ret *= VLC->spellh->spells[33].powers[affectedCreature->getEffect(33)->level]; + ret /= 100; + } + + return ret; +} + bool CGameHandler::makeCustomAction( BattleAction &ba ) { switch(ba.actionType) @@ -2281,14 +2356,14 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) //TODO: check resistances -#define SPELL_CAST_TEMPLATE_2(EFFECT_ID, DAMAGE) \ +#define SPELL_CAST_TEMPLATE_2 \ StacksInjured si; \ for(std::set::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it) \ { \ BattleStackAttacked bsa; \ bsa.flags |= 2; \ - bsa.effect = EFFECT_ID; \ - bsa.damageAmount = DAMAGE; \ + bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim; \ + bsa.damageAmount = calculateSpellDmg(&VLC->spellh->spells[ba.additionalInfo], h, *it); \ bsa.stackAttacked = (*it)->ID; \ prepareAttacked(bsa,*it); \ si.stacks.insert(bsa); \ @@ -2306,13 +2381,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) //it should spoil anything for other spells std::set attackedHexes = s->rangeInHexes(ba.destinationTile, h->getSpellSchoolLevel(s)); std::set attackedCres; /*std::set to exclude multiple occurences of two hex creatures*/ - if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature - { - CStack * st = gs->curB->getStackT(ba.destinationTile); - if(st) - attackedCres.insert(st); - } - else if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert + if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert { if(h->getSpellSchoolLevel(s) < 3) /*not expert */ { @@ -2334,11 +2403,18 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) } } //if(h->getSpellSchoolLevel(s) < 3) } + else if(VLC->spellh->spells[ba.additionalInfo].attributes.find("CREATURE_TARGET") != std::string::npos) //spell to be cast on one specific creature + { + CStack * st = gs->curB->getStackT(ba.destinationTile); + if(st) + attackedCres.insert(st); + } else //custom range from attackedHexes { for(std::set::iterator it = attackedHexes.begin(); it != attackedHexes.end(); ++it) { CStack * st = gs->curB->getStackT(*it); + if(st) attackedCres.insert(st); } } @@ -2347,43 +2423,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) switch(ba.additionalInfo) //spell id { case 15: //magic arrow - { - SPELL_CAST_TEMPLATE_2(64, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]); - break; - } case 16: //ice bolt - { - SPELL_CAST_TEMPLATE_2(46, h->getPrimSkillLevel(2) * 20 + s->powers[h->getSpellSchoolLevel(s)]); - break; - } case 17: //lightning bolt - { - SPELL_CAST_TEMPLATE_2(38, h->getPrimSkillLevel(2) * 25 + s->powers[h->getSpellSchoolLevel(s)]); - break; - } case 18: //implosion - { - SPELL_CAST_TEMPLATE_2(10, h->getPrimSkillLevel(2) * 75 + s->powers[h->getSpellSchoolLevel(s)]); - break; - } case 20: //frost ring - { - SPELL_CAST_TEMPLATE_2(45, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]); - break; - } case 21: //fireball - { - SPELL_CAST_TEMPLATE_2(53, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]); - break; - } case 22: //inferno - { - SPELL_CAST_TEMPLATE_2(9, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]); - break; - } case 23: //meteor shower { - SPELL_CAST_TEMPLATE_2(16, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]); + SPELL_CAST_TEMPLATE_2; break; } case 24: //death ripple @@ -2396,7 +2444,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) attackedCres.insert(gs->curB->stacks[it]); } if(attackedCres.size() == 0) break; - SPELL_CAST_TEMPLATE_2(8, h->getPrimSkillLevel(2) * 5 + s->powers[h->getSpellSchoolLevel(s)]); + SPELL_CAST_TEMPLATE_2; break; } case 25: //destroy undead @@ -2409,7 +2457,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) attackedCres.insert(gs->curB->stacks[it]); } if(attackedCres.size() == 0) break; - SPELL_CAST_TEMPLATE_2(29, h->getPrimSkillLevel(2) * 10 + s->powers[h->getSpellSchoolLevel(s)]); + SPELL_CAST_TEMPLATE_2; break; } case 26: //armageddon @@ -2421,11 +2469,15 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) attackedCres.insert(gs->curB->stacks[it]); } if(attackedCres.size() == 0) break; - SPELL_CAST_TEMPLATE_2(12, h->getPrimSkillLevel(2) * 50 + s->powers[h->getSpellSchoolLevel(s)]); + SPELL_CAST_TEMPLATE_2; break; } case 27: //shield case 28: //air shield + case 30: //protection from air + case 31: //protection from fire + case 32: //protection from water + case 33: //protection from earth case 41: //bless case 42: //curse case 43: //bloodlust