diff --git a/lib/BattleState.cpp b/lib/BattleState.cpp index 6ba349098..ee4e0d6ac 100644 --- a/lib/BattleState.cpp +++ b/lib/BattleState.cpp @@ -918,6 +918,14 @@ ui32 CStack::Speed( int turn /*= 0*/ , bool useBind /* = false*/) const return speed; } +ui32 CStack::level() const +{ + if (base) + return base->getLevel(); //creatture or commander + else + return std::max(1, (int)getCreature()->level); //war machine, clone etc +} + si32 CStack::magicResistance() const { si32 magicResistance; diff --git a/lib/BattleState.h b/lib/BattleState.h index 9bf813743..5fe5dac22 100644 --- a/lib/BattleState.h +++ b/lib/BattleState.h @@ -169,6 +169,7 @@ public: bool canMove(int turn = 0) const; //if stack can move bool canBeHealed() const; //for first aid tent - only harmed stacks that are not war machines ui32 Speed(int turn = 0, bool useBind = false) const; //get speed of creature with all modificators + ui32 level() const; si32 magicResistance() const; //include aura of resistance static void stackEffectToFeature(std::vector & sf, const Bonus & sse); std::vector activeSpells() const; //returns vector of active spell IDs sorted by time of cast diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 8d0cc5b08..7b4138971 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -676,6 +676,7 @@ CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s) void CArtifactInstance::init() { id = ArtifactInstanceID(); + id = static_cast(ArtifactID::NONE); //to be randomized setNodeType(ARTIFACT_INSTANCE); } diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 7335fedcd..dd4613f6b 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -513,6 +513,11 @@ int CStackInstance::getExpRank() const } } +int CStackInstance::getLevel() const +{ + return std::max (1, (int)type->level); +} + si32 CStackInstance::magicResistance() const { si32 val = valOfBonuses(Selector::type(Bonus::MAGIC_RESISTANCE)); @@ -717,6 +722,11 @@ int CCommanderInstance::getExpRank() const return VLC->heroh->level (experience); } +int CCommanderInstance::getLevel() const +{ + return std::max (1, getExpRank()); +} + void CCommanderInstance::levelUp () { level++; diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 37517768e..b953e5c76 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -63,6 +63,7 @@ public: int getQuantityID() const; std::string getQuantityTXT(bool capitalized = true) const; virtual int getExpRank() const; + virtual int getLevel() const; //different for regular stack and commander si32 magicResistance() const; CreatureID getCreatureID() const; //-1 if not available std::string getName() const; //plural or singular @@ -104,6 +105,7 @@ public: ui64 getPower() const {return 0;}; int getExpRank() const; + int getLevel() const OVERRIDE; ArtBearer::ArtBearer bearerType() const OVERRIDE; //from CArtifactSet template void serialize(Handler &h, const int version) diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index c0f83a7f1..36cbeead9 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -3842,9 +3842,11 @@ void CGArtifact::initObj() } if(ID == Obj::SPELL_SCROLL) subID = 1; - + assert(storedArtifact->artType); assert(storedArtifact->getParentNodes().size()); + + //assert(storedArtifact->artType->id == subID); //this does not stop desync } void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const diff --git a/lib/Mapping/MapFormatH3M.cpp b/lib/Mapping/MapFormatH3M.cpp index db6a82f1d..0f07a64e3 100644 --- a/lib/Mapping/MapFormatH3M.cpp +++ b/lib/Mapping/MapFormatH3M.cpp @@ -677,7 +677,7 @@ CArtifactInstance * CMapLoaderH3M::createArtifact(int aid, int spellID /*= -1*/) } else //FIXME: create combined artifact instance for random combined artifacts, just in case { - a = new CArtifactInstance(); + a = new CArtifactInstance(); //random, empty } map->addNewArtifactInstance(a); @@ -1092,7 +1092,7 @@ void CMapLoaderH3M::readObjects() case Obj::RANDOM_RELIC_ART: case Obj::SPELL_SCROLL: { - int artID = -1; + int artID = ArtifactID::NONE; //random, set later int spellID = -1; CGArtifact * art = new CGArtifact(); nobj = art; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index cb569e766..a583f49f2 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -5357,7 +5357,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat ) return; } - if (attacker->hasBonusOfType(Bonus::DEATH_STARE)) // spell id 79 + if (attacker->hasBonusOfType(Bonus::DEATH_STARE) && bat.bsa.size()) { // mechanics of Death Stare as in H3: // each gorgon have 10% chance to kill (counted separately in H3) -> binomial distribution @@ -5374,10 +5374,10 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat ) int maxToKill = (attacker->count * chanceToKill + 99) / 100; vstd::amin(staredCreatures, maxToKill); - staredCreatures += attacker->type->level * attacker->valOfBonuses(Bonus::DEATH_STARE, 1); + staredCreatures += (attacker->level() * attacker->valOfBonuses(Bonus::DEATH_STARE, 1)) / gs->curB->battleGetStackByID(bat.bsa[0].stackAttacked)->level(); if (staredCreatures) { - if (bat.bsa.size() && bat.bsa[0].newAmount > 0) //TODO: death stare was not originally available for multiple-hex attacks, but... + if (bat.bsa[0].newAmount > 0) //TODO: death stare was not originally available for multiple-hex attacks, but... handleSpellCasting(SpellID::DEATH_STARE, 0, gs->curB->battleGetStackByID(bat.bsa[0].stackAttacked)->position, !attacker->attackerOwned, attacker->owner, NULL, NULL, staredCreatures, ECastingMode::AFTER_ATTACK_CASTING, attacker); }