Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core/Threat] SpellThreat-Calculation revamped #2881

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
134 changes: 134 additions & 0 deletions sql/supplemental/2011_07_21_02_world_spell_threat.sql
@@ -0,0 +1,134 @@
-- ----------
-- Tank Class Passive Threat
-- ----------
DELETE FROM spell_linked_spell WHERE spell_effect IN (57340, 57339);
INSERT INTO spell_linked_spell VALUES
(7376, 57339, 2, 'Defensive Stance Passive - Tank Class Passive Threat'),
(21178, 57339, 2, 'Bear Form (Passive2) - Tank Class Passive Threat'),
(25780, 57340, 2, 'Righteous Fury - Tank Class Passive Threat'),
(48263, 57340, 2, 'Frost Presence - Tank Class Passive Threat');

-- ----------
-- restructure spell_threat
-- ----------
TRUNCATE TABLE `spell_threat`;
ALTER TABLE `spell_threat` CHANGE `Threat` `flatMod` int(6);
ALTER TABLE `spell_threat` ADD COLUMN `pctMod` FLOAT NOT NULL DEFAULT 1.0 COMMENT 'threat multiplier for damage/healing' AFTER `flatMod`;
ALTER TABLE `spell_threat` ADD COLUMN `apPctMod` FLOAT NOT NULL DEFAULT 0.0 COMMENT 'additional threat bonus from attack power' AFTER `pctMod`;
INSERT INTO `spell_threat` VALUES
-- Other
-- Src: SELECT id, SpellNameEN, RankEN FROM `Spell` WHERE `DescriptionEN` LIKE '%threat%' AND `SpellFamilyName` <> '0' AND NOT (Attributes & 0x40) GROUP BY SpellNameEN ORDER BY RankEN DESC;
(5676, 0, 2.00, 0.0), -- Searing Pain (Rank 1) (Warlock)
(28176, 0, 0.00, 0.0), -- Fel Armor - Heal (Rank 1) (Warlock) [Assumption]
(8056, 0, 2.00, 0.0), -- Frost Shock (Rank 1) (Shaman) [Assumption]
(26688, 0, 0.00, 0.0), -- Anesthetic Poison - Proc (Rank 1) (Rogue)
(15237, 0, 0.00, 0.0), -- Holy Nova - Heal (Rank 1) (Priest)
(23455, 0, 0.00, 0.0), -- Holy Nova - Damage (Rank 1) (Priest)
(32546, 0, 0.50, 0.0), -- Binding Heal (Rank 1) (Priest) [Assumption]
(33619, 0, 0.00, 0.0), -- Reflective Shield - Proc (Priest)
(2139, 180, 1.00, 0.0), -- Counterspell (Mage) [Assumption]
-- Death Knight
-- Src: http://www.tankspot.com/showthread.php?40485-Death-Knight-threat-values&p=113584#post113584
(63611, 0, 0.00, 0.0), -- Blood Presence - Heal
(45524, 240, 1.00, 0.0), -- Chains of Ice
(43265, 0, 1.90, 0.0), -- Death and Decay
(49576, 110, 1.00, 0.0), -- Death Grip
(48743, 0, 0.00, 0.0), -- Death Pact
(65142, 0, 0.00, 0.0), -- Ebon Plague
(47568, 0, 0.00, 0.0), -- Empower Rune Weapon
(51209, 112, 1.00, 0.0), -- Hungering Cold
(49039, 110, 1.00, 0.0), -- Lichborn
(56815, 0, 1.75, 0.0), -- Rune Strike
(50422, 0, 0.00, 0.0), -- Scent of Blood - Proc
(55090, 51, 1.00, 0.0), -- Scourge Strike (Rank 1)
(55265, 63, 1.00, 0.0), -- Scourge Strike (Rank 2)
(55270, 98, 1.00, 0.0), -- Scourge Strike (Rank 3)
(55271, 120, 1.00, 0.0), -- Scourge Strike (Rank 4)
(49916, 138, 1.00, 0.0), -- Strangulate
(50181, 0, 0.00, 0.0), -- Vendetta - Proc
-- Druid
-- Src: http://www.tankspot.com/showthread.php?47813-WOTLK-Bear-Threat-Values&p=200948#post200948
(17057, 0, 0.00, 0.0), -- Furor - Proc
(5211, 53, 1.00, 0.0), -- Bash (Rank 3)
(6798, 105, 1.00, 0.0), -- Bash (Rank 2)
(8983, 158, 1.00, 0.0), -- Bash (Rank 1)
(45334, 40, 1.00, 0.0), -- Feral Charge (Bear) - Root
(19675, 80, 1.00, 0.0), -- Feral Charge (Bear) - Interrupt
(34299, 0, 0.00, 0.0), -- Improved Leader of the Pack - Heal
(6807, 13, 1.00, 0.0), -- Maul (Rank 1)
(6808, 20, 1.00, 0.0), -- Maul (Rank 2)
(6809, 27, 1.00, 0.0), -- Maul (Rank 3)
(8972, 47, 1.00, 0.0), -- Maul (Rank 4)
(9745, 75, 1.00, 0.0), -- Maul (Rank 5)
(9880, 106, 1.00, 0.0), -- Maul (Rank 6)
(9881, 140, 1.00, 0.0), -- Maul (Rank 7)
(26996, 212, 1.00, 0.0), -- Maul (Rank 8)
(48479, 345, 1.00, 0.0), -- Maul (Rank 9)
(48480, 422, 1.00, 0.0), -- Maul (Rank 10)
(60089, 638, 1.00, 0.0), -- Faerie Fire (Feral) - Proc
(33745, 182, 0.50, 0.0), -- Lacerate (Rank 1)
(48567, 409, 0.50, 0.0), -- Lacerate (Rank 2)
(48568, 515, 0.50, 0.0), -- Lacerate (Rank 3)
(779, 0, 1.50, 0.0), -- Swipe (Bear) (Rank 1)
(5209, 98, 1.00, 0.0), -- Challenging Roar
(29166, 0, 10.0, 0.0), -- Innervate [base is 5 per 1 mana]
-- Paladin
-- Src: http://www.tankspot.com/showthread.php?39761-Paladin-Threat-Values-(Updated-for-3.2.2)&p=103813#post103813
(7294, 0, 2.00, 0.0), -- Retribution Aura
(20185, 0, 0.00, 0.0), -- Judgement of Light
(19742, 0, 0.00, 0.0), -- Blessing of Wisdom (Rank 1)
(25894, 0, 0.00, 0.0), -- Greater Blessing of Wisdom (Rank 1)
(20470, 0, 0.00, 0.0), -- Righteous Fury
(498, 0, 0.00, 0.0), -- Divine Protection
-- Warrior
-- Src: http://www.tankspot.com/showthread.php?39775-WoW-3.0-Threat-Values-(Warrior)&p=103972#post103972
(845, 8, 1.00, 0.0), -- Cleave (Rank 1)
(7369, 15, 1.00, 0.0), -- Cleave (Rank 2)
(11608, 25, 1.00, 0.0), -- Cleave (Rank 3)
(11609, 35, 1.00, 0.0), -- Cleave (Rank 4)
(20569, 48, 1.00, 0.0), -- Cleave (Rank 5)
(25231, 68, 1.00, 0.0), -- Cleave (Rank 6)
(47519, 95, 1.00, 0.0), -- Cleave (Rank 7)
(47520, 112, 1.00, 0.0), -- Cleave (Rank 8)
(78, 5, 1.00, 0.0), -- Heroic Strike (Rank 1)
(284, 10, 1.00, 0.0), -- Heroic Strike (Rank 2)
(285, 16, 1.00, 0.0), -- Heroic Strike (Rank 3)
(1608, 22, 1.00, 0.0), -- Heroic Strike (Rank 4)
(11564, 31, 1.00, 0.0), -- Heroic Strike (Rank 5)
(11565, 48, 1.00, 0.0), -- Heroic Strike (Rank 6)
(11566, 70, 1.00, 0.0), -- Heroic Strike (Rank 7)
(11567, 92, 1.00, 0.0), -- Heroic Strike (Rank 8)
(25286, 104, 1.00, 0.0), -- Heroic Strike (Rank 9)
(29707, 121, 1.00, 0.0), -- Heroic Strike (Rank 10)
(30324, 164, 1.00, 0.0), -- Heroic Strike (Rank 11)
(47449, 224, 1.00, 0.0), -- Heroic Strike (Rank 12)
(47450, 259, 1.00, 0.0), -- Heroic Strike (Rank 13)
(57755, 0, 1.50, 0.0), -- Heroic Throw
(6572, 7, 1.00, 0.0), -- Revenge (Rank 1)
(6574, 11, 1.00, 0.0), -- Revenge (Rank 2)
(7379, 15, 1.00, 0.0), -- Revenge (Rank 3)
(11600, 27, 1.00, 0.0), -- Revenge (Rank 4)
(11601, 41, 1.00, 0.0), -- Revenge (Rank 5)
(25288, 53, 1.00, 0.0), -- Revenge (Rank 6)
(25269, 58, 1.00, 0.0), -- Revenge (Rank 7)
(30357, 71, 1.00, 0.0), -- Revenge (Rank 8)
(57823, 121, 1.00, 0.0), -- Revenge (Rank 9)
(23922, 228, 1.00, 0.0), -- Shield Slam (Rank 1)
(23923, 268, 1.00, 0.0), -- Shield Slam (Rank 2)
(23924, 307, 1.00, 0.0), -- Shield Slam (Rank 3)
(23925, 347, 1.00, 0.0), -- Shield Slam (Rank 4)
(25258, 387, 1.00, 0.0), -- Shield Slam (Rank 5)
(30356, 426, 1.00, 0.0), -- Shield Slam (Rank 6)
(47487, 650, 1.00, 0.0), -- Shield Slam (Rank 7)
(47488, 770, 1.00, 0.0), -- Shield Slam (Rank 8)
(1464, 18, 1.00, 0.0), -- Slam (Rank 1)
(8820, 24, 1.00, 0.0), -- Slam (Rank 2)
(11604, 38, 1.00, 0.0), -- Slam (Rank 3)
(11605, 49, 1.00, 0.0), -- Slam (Rank 4)
(25241, 59, 1.00, 0.0), -- Slam (Rank 5)
(25242, 78, 1.00, 0.0), -- Slam (Rank 6)
(47474, 123, 1.00, 0.0), -- Slam (Rank 7)
(47475, 140, 1.00, 0.0), -- Slam (Rank 8)
(7386, 345, 1.00, 0.05), -- Sunder Armor
(20243, 0, 1.00, 0.05), -- Devastate (Rank 1)
(6343, 0, 1.85, 0.0); -- Thunder Clap (Rank 1)
7 changes: 3 additions & 4 deletions src/server/game/Combat/HostileRefManager.cpp
Expand Up @@ -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();
}
}
Expand Down
16 changes: 13 additions & 3 deletions src/server/game/Combat/ThreatManager.cpp
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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;
Expand Down
32 changes: 3 additions & 29 deletions src/server/game/Entities/Unit/Unit.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 0 additions & 2 deletions src/server/game/Entities/Unit/Unit.h
Expand Up @@ -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);
Expand Down
45 changes: 39 additions & 6 deletions src/server/game/Spells/Spell.cpp
Expand Up @@ -4530,20 +4530,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)
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/Spells/SpellInfo.h
Expand Up @@ -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,
Expand Down