diff --git a/AI/GeniusAI/CGeniusAI.cpp b/AI/GeniusAI/CGeniusAI.cpp index 67b148b92..00269df37 100644 --- a/AI/GeniusAI/CGeniusAI.cpp +++ b/AI/GeniusAI/CGeniusAI.cpp @@ -476,7 +476,7 @@ void CBattleLogic::MakeStatistics(int currentCreatureId) CGHeroInstance *attackerHero = (m_side)? m_hero1 : m_hero2; CGHeroInstance *defendingHero = (m_side)? m_hero2 : m_hero1; - int attackDefenseBonus = currentStack->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0) - (st->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0)); + int attackDefenseBonus = currentStack->Attack() - st->Defense(); float damageFactor = 1.0f; if(attackDefenseBonus < 0) //decreasing dmg { diff --git a/CGameState.cpp b/CGameState.cpp index db7c750b6..20040d6ed 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -445,10 +445,8 @@ std::pair< std::vector, int > BattleInfo::getPath(int start, int dest, bool CStack::CStack(CCreature * C, int A, int O, int I, bool AO, int S) :ID(I), creature(C), amount(A), baseAmount(A), firstHPleft(C->hitPoints), owner(O), slot(S), attackerOwned(AO), position(-1), - counterAttacks(1), shots(C->shots), state(), effects() + counterAttacks(1), shots(C->shots), state(), effects(), speed(creature->speed), abilities(C->abilities), attack(C->attack), defense(C->defence) { - speed = creature->speed; - abilities = C->abilities; state.insert(ALIVE); } @@ -529,6 +527,54 @@ si8 CStack::Luck() const return ret; } +si32 CStack::Attack() const +{ + si32 ret = attack; //value to be returned + + if(getEffect(56)) //frenzy for attacker + { + ret += (VLC->spellh->spells[56].powers[getEffect(56)->level]/100.0) * defense; + } + + if(getEffect(48)) //attacker's prayer handling + { + ret += VLC->spellh->spells[48].powers[getEffect(48)->level]; + } + + if(getEffect(45)) //weakness handling + { + ret -= VLC->spellh->spells[45].powers[getEffect(45)->level]; + } + + return ret; +} + +si32 CStack::Defense() const +{ + si32 ret = defense; + + if(getEffect(56)) //frenzy for defender + { + return 0; + } + + if(getEffect(48)) //defender's prayer handling + { + ret += VLC->spellh->spells[48].powers[getEffect(48)->level]; + } + if(getEffect(47)) //defender's disrupting ray handling + { + int howMany = howManyEffectsSet(47); + ret -= VLC->spellh->spells[47].powers[getEffect(47)->level] * howMany; + } + if(getEffect(46)) //stone skin handling + { + ret += VLC->spellh->spells[46].powers[getEffect(46)->level]; + } + + return ret; +} + bool CStack::willMove() { return !vstd::contains(state,DEFENDING) @@ -1699,48 +1745,74 @@ bool CGameState::checkForVisitableDir(const int3 & src, const int3 & dst) const int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting) { - int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0), - defenderDefenseBonus = defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0), - attackDefenseBonus = 0, + int attackDefenseBonus = attacker->Attack() - defender->Defense(), minDmg = attacker->creature->damageMin * attacker->amount, maxDmg = attacker->creature->damageMax * attacker->amount; //calculating total attack/defense skills modifier - if(attacker->getEffect(56)) //frenzy for attacker - { - attackerAttackBonus += (VLC->spellh->spells[56].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0)); - } - if(defender->getEffect(56)) //frenzy for defender - { - defenderDefenseBonus = 0; - } - attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus; - if(defender->getEffect(48)) //defender's prayer handling - { - attackDefenseBonus -= VLC->spellh->spells[48].powers[defender->getEffect(48)->level]; - } - if(attacker->getEffect(48)) //attacker's prayer handling - { - attackDefenseBonus += VLC->spellh->spells[48].powers[attacker->getEffect(48)->level]; - } - if(defender->getEffect(47)) //defender's disrupting ray handling - { - int howMany = defender->howManyEffectsSet(47); - attackDefenseBonus += VLC->spellh->spells[47].powers[attacker->getEffect(47)->level] * howMany; - } - if(defender->getEffect(46)) //stone skin handling - { - attackDefenseBonus -= VLC->spellh->spells[46].powers[defender->getEffect(46)->level]; - } - if(attacker->getEffect(45)) //weakness handling - { - attackDefenseBonus -= VLC->spellh->spells[45].powers[attacker->getEffect(45)->level]; - } + if(!shooting && attacker->getEffect(43)) //bloodlust handling { attackDefenseBonus += VLC->spellh->spells[43].powers[attacker->getEffect(43)->level]; } + if(shooting && attacker->getEffect(44)) //precision handling + { + attackDefenseBonus += VLC->spellh->spells[44].powers[attacker->getEffect(44)->level]; + } + + if(attacker->getEffect(55)) //slayer handling + { + std::vector affectedIds; + switch(attacker->getEffect(55)->level) + { + case 3: //expert + { + affectedIds.push_back(40); //giant + affectedIds.push_back(41); //titan + affectedIds.push_back(152); //lord of thunder + } //continue adding ... + case 2: //advanced + { + affectedIds.push_back(12); //angel + affectedIds.push_back(13); //archangel + affectedIds.push_back(54); //devil + affectedIds.push_back(55); //arch devil + affectedIds.push_back(150); //supreme archangel + affectedIds.push_back(153); //antichrist + } //continue adding ... + case 0: case 1: //none and basic + { + affectedIds.push_back(26); //green dragon + affectedIds.push_back(27); //gold dragon + affectedIds.push_back(82); //red dragon + affectedIds.push_back(83); //black dragon + affectedIds.push_back(96); //behemot + affectedIds.push_back(97); //ancient behemot + affectedIds.push_back(110); //hydra + affectedIds.push_back(111); //chaos hydra + affectedIds.push_back(132); //azure dragon + affectedIds.push_back(133); //crystal dragon + affectedIds.push_back(134); //faerie dragon + affectedIds.push_back(135); //rust dragon + affectedIds.push_back(151); //diamond dragon + affectedIds.push_back(154); //blood dragon + affectedIds.push_back(155); //darkness dragon + affectedIds.push_back(156); //ghost behemot + affectedIds.push_back(157); //hell hydra + break; + } + } + for(int g=0; gcreature->idNumber == affectedIds[g]) + { + attackDefenseBonus += VLC->spellh->spells[55].powers[attacker->getEffect(55)->level]; + break; + } + } + } + float dmgBonusMultiplier = 1.0f; //bonus from attack/defense skills @@ -1819,26 +1891,18 @@ int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, con //handling spell effects if(!shooting && defender->getEffect(27)) //shield { - if(defender->getEffect(27)->level<=1) //none or basic - dmgBonusMultiplier *= 0.85f; - else //adv or expert - dmgBonusMultiplier *= 0.7f; + dmgBonusMultiplier *= float(VLC->spellh->spells[27].powers[attacker->getEffect(27)->level]) / 100.0f; } else if(shooting && defender->getEffect(28)) //air shield { - if(defender->getEffect(28)->level<=1) //none or basic - dmgBonusMultiplier *= 0.75f; - else //adv or expert - dmgBonusMultiplier *= 0.5f; + dmgBonusMultiplier *= float(VLC->spellh->spells[28].powers[attacker->getEffect(28)->level]) / 100.0f; } if(attacker->getEffect(42)) //curse handling (partial, the rest is below) { - if(attacker->getEffect(42)->level>=2) //adv or expert - dmgBonusMultiplier *= 0.8f; + dmgBonusMultiplier *= 0.8f * float(VLC->spellh->spells[42].powers[attacker->getEffect(42)->level]); //the second factor is 1 or 0 } - minDmg *= dmgBonusMultiplier; maxDmg *= dmgBonusMultiplier; diff --git a/CGameState.h b/CGameState.h index ba4a61e88..8e2fb7544 100644 --- a/CGameState.h +++ b/CGameState.h @@ -151,7 +151,9 @@ public: ui16 position; //position on battlefield ui8 counterAttacks; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1) si16 shots; //how many shots left - ui8 speed; + ui8 speed; //speed of stack with hero bonus + si32 attack; //attack of stack with hero bonus + si32 defense; //defense of stack with hero bonus si8 morale, luck; //base stack luck/morale std::set abilities; @@ -168,14 +170,16 @@ public: }; std::vector effects; - CStack(CCreature * C, int A, int O, int I, bool AO, int S); - CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1), abilities(), state(), effects() {} + CStack(CCreature * C, int A, int O, int I, bool AO, int S); //c-tor + CStack() : ID(-1), creature(NULL), amount(-1), baseAmount(-1), firstHPleft(-1), owner(255), slot(255), attackerOwned(true), position(-1), counterAttacks(1), abilities(), state(), effects() {} //c-tor const StackEffect * getEffect(ui16 id) const; //effect id (SP) ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack bool willMove(); //if stack has remaining move this turn - ui32 Speed() const; - si8 Morale() const; - si8 Luck() const; + ui32 Speed() const; //get speed of creature with all modificators + si8 Morale() const; //get morale of stack with all modificators + si8 Luck() const; //get luck of stack with all modificators + si32 Attack() const; //get attack of stack with all modificators + si32 Defense() const; //get defense of stack with all modificators template void save(Handler &h, const int version) { h & creature->idNumber; @@ -190,13 +194,13 @@ public: template void serialize(Handler &h, const int version) { h & ID & amount & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks - & shots & morale & luck & speed; + & shots & morale & luck & speed & attack & defense; if(h.saving) save(h,version); else load(h,version); } - bool alive() const + bool alive() const //determines if stack is alive { return vstd::contains(state,ALIVE); } diff --git a/config/spell_info.txt b/config/spell_info.txt index 56684ce25..e198569e4 100644 --- a/config/spell_info.txt +++ b/config/spell_info.txt @@ -44,7 +44,7 @@ 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 +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 @@ -55,7 +55,7 @@ 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 +55 1 28 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 diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ccddb53dc..6aca5dce1 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -835,6 +835,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army //TODO: check if terrain is native, add bonuses for neutral stacks, bonuses from town stacks.back()->morale = hero1->getCurrentMorale(i->first,false); stacks.back()->luck = hero1->getCurrentLuck(i->first,false); + stacks.back()->attack += hero1->getPrimSkillLevel(0); + stacks.back()->defense += hero1->getPrimSkillLevel(1); } else { @@ -884,6 +886,8 @@ void CGameHandler::setupBattle( BattleInfo * curB, int3 tile, CCreatureSet &army stacks.back()->speed += hero2->valOfBonuses(HeroBonus::STACKS_SPEED); stacks.back()->morale = hero2->getCurrentMorale(i->first,false); stacks.back()->luck = hero2->getCurrentLuck(i->first,false); + stacks.back()->attack += hero2->getPrimSkillLevel(0); + stacks.back()->defense += hero2->getPrimSkillLevel(1); } else { @@ -2455,6 +2459,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) case 41: //bless case 42: //curse case 43: //bloodlust + case 44: //precision case 45: //weakness case 46: //stone skin case 47: //disrupting ray @@ -2465,6 +2470,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba ) case 52: //misfortune case 53: //haste case 54: //slow + case 55: //slayer case 61: //forgetfulness { SetStackEffect sse;