diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/server/game/Combat/HostileRefManager.cpp | 7 | ||||
-rwxr-xr-x | src/server/game/Combat/ThreatManager.cpp | 16 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 32 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 45 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 2 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellMgr.cpp | 55 | ||||
-rwxr-xr-x | src/server/game/Spells/SpellMgr.h | 11 |
8 files changed, 111 insertions, 59 deletions
diff --git a/src/server/game/Combat/HostileRefManager.cpp b/src/server/game/Combat/HostileRefManager.cpp index 5d9e7d671c8..47e9a1d2508 100755 --- a/src/server/game/Combat/HostileRefManager.cpp +++ b/src/server/game/Combat/HostileRefManager.cpp @@ -40,10 +40,9 @@ void HostileRefManager::threatAssist(Unit* victim, float baseThreat, SpellInfo c threat /= getSize(); while (ref) { - if (victim == getOwner()) - ref->addThreat(threat); // It is faster to modify the threat durectly if possible - else - ref->getSource()->addThreat(victim, threat); + if (ThreatCalcHelper::isValidProcess(victim, ref->getSource()->getOwner(), threatSpell)) + ref->getSource()->doAddThreat(victim, threat); + ref = ref->next(); } } diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index bf3650f611e..858ef057baf 100755 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -36,8 +36,14 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float { if (threatSpell) { - if (threatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT) - return 0.0f; + if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(threatSpell->Id)) + if (threatEntry->pctMod != 1.0f) + threat *= threatEntry->pctMod; + + // Energize is not affected by Mods + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) + if (threatSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE || threatSpell->Effects[i].ApplyAuraName == SPELL_AURA_PERIODIC_ENERGIZE) + return threat; if (Player* modOwner = hatedUnit->GetSpellModOwner()) modOwner->ApplySpellMod(threatSpell->Id, SPELLMOD_THREAT, threat); @@ -46,7 +52,7 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float return hatedUnit->ApplyTotalThreatModifier(threat, schoolMask); } -bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* /*threatSpell*/) +bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* threatSpell) { //function deals with adding threat and adding players and pets into ThreatList //mobs, NPCs, guards have ThreatList and HateOfflineList @@ -68,6 +74,10 @@ bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellIn if (!hatedUnit->isAlive() || !hatingUnit->isAlive()) return false; + // spell not causing threat + if (threatSpell && threatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT) + return false; + ASSERT(hatingUnit->GetTypeId() == TYPEID_UNIT); return true; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4cea8f56005..1b3217a02e0 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -791,12 +791,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0); if (victim->GetTypeId() != TYPEID_PLAYER) - { - if (spellProto && IsDamageToThreatSpell(spellProto)) - victim->AddThreat(this, damage * 2.0f, damageSchoolMask, spellProto); - else victim->AddThreat(this, (float)damage, damageSchoolMask, spellProto); - } else // victim is a player { // random durability for items (HIT TAKEN) @@ -10334,6 +10329,9 @@ void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, uint32 damage, Powers p SendEnergizeSpellLog(victim, spellID, damage, powerType); // needs to be called after sending spell log victim->ModifyPower(powerType, damage); + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID); + victim->getHostileRefManager().threatAssist(this, float(damage) * 0.5f, spellInfo); } uint32 Unit::SpellDamageBonus(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) @@ -11622,30 +11620,6 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons return false; } -bool Unit::IsDamageToThreatSpell(SpellInfo const* spellInfo) const -{ - if (!spellInfo) - return false; - - switch(spellInfo->SpellFamilyName) - { - case SPELLFAMILY_WARLOCK: - if (spellInfo->SpellFamilyFlags[0] == 0x100) // Searing Pain - return true; - break; - case SPELLFAMILY_SHAMAN: - if (spellInfo->SpellFamilyFlags[0] == SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK) - return true; - break; - case SPELLFAMILY_DEATHKNIGHT: - if (spellInfo->SpellFamilyFlags[1] == 0x20000000) // Rune Strike - return true; - break; - } - - return false; -} - void Unit::MeleeDamageBonus(Unit* victim, uint32 *pdamage, WeaponAttackType attType, SpellInfo const* spellProto) { if (!victim) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e777f16b99a..fb41914d6f7 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1572,8 +1572,6 @@ class Unit : public WorldObject void SendPlaySpellVisual(uint32 id); void SendPlaySpellImpact(uint64 guid, uint32 id); - bool IsDamageToThreatSpell(SpellInfo const* spellInfo) const; - void DeMorph(); void SendAttackStateUpdate(CalcDamageInfo *damageInfo); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ed36a4ae208..bae14ed26bf 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4536,20 +4536,53 @@ void Spell::TakeReagents() void Spell::HandleThreatSpells() { - if (!m_targets.GetUnitTarget()) + if (m_UniqueTargetInfo.empty()) return; - if (!m_targets.GetUnitTarget()->CanHaveThreatList()) + if ((m_spellInfo->AttributesEx & SPELL_ATTR1_NO_THREAT) || + (m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO)) return; - uint16 threat = sSpellMgr->GetSpellThreat(m_spellInfo->Id); + float threat = 0.0f; + if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(m_spellInfo->Id)) + { + if (threatEntry->apPctMod != 0.0f) + threat += threatEntry->apPctMod * m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + + threat += threatEntry->flatMod; + } + else if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_NO_INITIAL_THREAT) == 0) + threat += m_spellInfo->SpellLevel; - if (!threat) + // past this point only multiplicative effects occur + if (threat == 0.0f) return; - m_targets.GetUnitTarget()->AddThreat(m_caster, float(threat)); + // since 2.0.1 threat from positive effects also is distributed among all targets, so the overall caused threat is at most the defined bonus + threat /= m_UniqueTargetInfo.size(); + + for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + { + if (ihit->missCondition != SPELL_MISS_NONE) + continue; + + Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); + if (!target) + continue; + + // positive spells distribute threat among all units that are in combat with target, like healing + if (m_spellInfo->_IsPositiveSpell()) + target->getHostileRefManager().threatAssist(m_caster, threat, m_spellInfo); + // for negative spells threat gets distributed among affected targets + else + { + if (!target->CanHaveThreatList()) + continue; - sLog->outStaticDebug("Spell %u, rank %u, added an additional %i threat", m_spellInfo->Id, m_spellInfo->GetRank(), threat); + target->AddThreat(m_caster, threat, m_spellInfo->GetSchoolMask(), m_spellInfo); + } + } + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); } void Spell::HandleEffects(Unit *pUnitTarget, Item *pItemTarget, GameObject *pGOTarget, uint32 i) diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 69f160cbb0f..584c41fdddd 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -186,7 +186,7 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_CONE_BACK = 0x00000002, SPELL_ATTR0_CU_CONE_LINE = 0x00000004, SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008, - SPELL_ATTR0_CU_NONE1 = 0x00000010, // UNUSED + SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010, SPELL_ATTR0_CU_NONE2 = 0x00000020, // UNUSED SPELL_ATTR0_CU_AURA_CC = 0x00000040, SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100, diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 3b546a94bfa..b44c7f58ef5 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -965,13 +965,19 @@ SpellBonusEntry const* SpellMgr::GetSpellBonusData(uint32 spellId) const return NULL; } -uint16 SpellMgr::GetSpellThreat(uint32 spellid) const +SpellThreatEntry const* SpellMgr::GetSpellThreatEntry(uint32 spellID) const { - SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellid); - if (itr == mSpellThreatMap.end()) - return 0; - - return itr->second; + SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellID); + if (itr != mSpellThreatMap.end()) + return &itr->second; + else + { + uint32 firstSpell = GetFirstSpellInChain(spellID); + SpellThreatMap::const_iterator itr = mSpellThreatMap.find(firstSpell); + if (itr != mSpellThreatMap.end()) + return &itr->second; + } + return NULL; } SkillLineAbilityMapBounds SpellMgr::GetSkillLineAbilityMapBounds(uint32 spell_id) const @@ -1940,8 +1946,8 @@ void SpellMgr::LoadSpellThreats() uint32 count = 0; - // 0 1 - QueryResult result = WorldDatabase.Query("SELECT entry, Threat FROM spell_threat"); + // 0 1 2 3 + QueryResult result = WorldDatabase.Query("SELECT entry, flatMod, pctMod, apPctMod FROM spell_threat"); if (!result) { sLog->outString(">> Loaded 0 aggro generating spells"); @@ -1954,7 +1960,6 @@ void SpellMgr::LoadSpellThreats() Field *fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); - uint16 Threat = fields[1].GetUInt16(); if (!GetSpellInfo(entry)) { @@ -1962,12 +1967,16 @@ void SpellMgr::LoadSpellThreats() continue; } - mSpellThreatMap[entry] = Threat; + SpellThreatEntry ste; + ste.flatMod = fields[1].GetInt16(); + ste.pctMod = fields[2].GetFloat(); + ste.apPctMod = fields[3].GetFloat(); - ++count; + mSpellThreatMap[entry] = ste; + count++; } while (result->NextRow()); - sLog->outString(">> Loaded %u aggro generating spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %u SpellThreatEntries in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -2634,6 +2643,18 @@ void SpellMgr::LoadSpellCustomAttr() case SPELL_AURA_MOD_STUN: spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC; break; + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_OBS_MOD_POWER: + case SPELL_AURA_POWER_BURN_MANA: + spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT; + break; } switch (spellInfo->Effects[j].Effect) @@ -2646,6 +2667,16 @@ void SpellMgr::LoadSpellCustomAttr() case SPELL_EFFECT_HEAL: spellInfo->AttributesCu |= SPELL_ATTR0_CU_DIRECT_DAMAGE; break; + case SPELL_EFFECT_POWER_DRAIN: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_HEAL_MAX_HEALTH: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_HEAL_PCT: + case SPELL_EFFECT_ENERGIZE_PCT: + case SPELL_EFFECT_ENERGIZE: + case SPELL_EFFECT_HEAL_MECHANICAL: + spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT; + break; case SPELL_EFFECT_CHARGE: case SPELL_EFFECT_CHARGE_DEST: case SPELL_EFFECT_JUMP: diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index e8ac3ce9862..64d21b7c3a5 100755 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -349,7 +349,14 @@ enum SpellGroupStackRule typedef std::map<SpellGroup, SpellGroupStackRule> SpellGroupStackMap; -typedef std::map<uint32, uint16> SpellThreatMap; +struct SpellThreatEntry +{ + int32 flatMod; // flat threat-value for this Spell - default: 0 + float pctMod; // threat-multiplier for this Spell - default: 1.0f + float apPctMod; // Pct of AP that is added as Threat - default: 0.0f +}; + +typedef std::map<uint32, SpellThreatEntry> SpellThreatMap; // Spell script target related declarations (accessed using SpellMgr functions) enum SpellScriptTargetType @@ -603,7 +610,7 @@ class SpellMgr SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const; // Spell threat table - uint16 GetSpellThreat(uint32 spellid) const; + SpellThreatEntry const* GetSpellThreatEntry(uint32 spellID) const; SkillLineAbilityMapBounds GetSkillLineAbilityMapBounds(uint32 spell_id) const; |