Threat, Guinea Pigs Are Needed, Test It Or When It Goes To Be Pushed Don't Cry :p

Threat is currently a tricky beast to handle in Trinity.

The main issues are:

  1. spell_threat is outdated. Most last ranks of spells don’t get their respective static modifier

  2. Tanks are missing one out of two threat-multipliers

  3. spells can’t be modified percent-wise. (however, there is a function, with rather rudimentary functionality)

  4. A partial reconstruction, using the the guides at Tankspot Death Knight, Druid, Paladin, Warrior. These compilations are by no means perfect, but the best i’ve fund so far.

I’m uncertain whether the static amount of threat on each spell is the same for each rank. So I only used the last rank for those. - got tired. assumed it to be like this

Since this is just braindead typing, I’ll ad more, when i come around to it. - Done

  1. I’m not entirely sure, when the additional 43% Threat should be applied. I choose the most logical method and attached it to the existing passives, that already increase threat.

  2. I’m not too happy with this change, but it’s a start.^^

Basically, the whole threat-calculation is now in ThreatCalcHelper::calcThreat, the hard-coded spells for high threat went into the database and non-periodic energize-effects will now also cause threat.

issues:

  • In some minor cases (power-gain), stance-modifiers are applied, when they should not. - ugly, but done

  • develop an alternative to hardcoding Attackpower-dependent threat into ThreatCalcHelper::calcThreat

  • With this system spells, that do not modify health or power, do not cause threat. Reinstate Spell::HandleThreatSpells and apply static threat there to solve this…? - casting a spell causes threatAssist. Amount is SpellLevel. If you wonder why, see this information and compare it to other spells with low static threat.

I’d appreciate any feedback given /emoticons/default_smile.png

/e: apparently, Paladins Healing should be reduced by another 50% (while tanking?). The only Spell applicable would be Salvation (Aura:10, BP:-51), but is not limited to a specific set of spells.

/e²: Updated

  • corrected mixed up receiver in ThreatAssist-calls /emoticons/default_rolleyes.gif

  • added static threat == SpellLevel (reduced content of spell_threat as a result)

  • every Spell can and will cause threat by default

  • added some more non-tank spells with non-standard threat to SQL

  • dropped parameter pSingleTarget for threatAssist (wasn’t used anyway)

  • temporarily added log-output to ease backtracing the calculation a bit

new issue: initial threat not entirely working, because m_targets.getUnitTarget() seems to be NULL in an awful lot of cases. And if so, how did the old code do anything good…?

/e³: code available on github (along with some other stuff) => https://github.com/Sarjuuk/TrinityCore/commits/master

hi

i used the fix from there for the additional 43% threat und used your new table-structure from spell_threat and of course your fix from 3.

I tested it and the threatmultiplication worked fine for me /emoticons/default_smile.png

I think, this is a big step to a working threatcalculation /emoticons/default_biggrin.png

nice one.

i checked

any news? how much does it work?

give us some new infos ^^

currently without a client, so i cant say if it does, what it is supposed to do. All i can say is, that it does compile /emoticons/default_wink.png

Lynxed and x3n did something very similar for mangos in the meantime. While not everything is applicable and i do disagree on some changes, i still reused some of their code.

So basically for future reference: This work is based on the work of Lynxed and x3n for mangos.

intended for rev: b28881f6485f4bc7052b552d46acdfa3bf3d713a

with logspam: http://paste2.org/p/1200949

without logspam: http://paste2.org/p/1200950

sql: http://paste2.org/p/1200951

changed:

  • moved apPctMod to table. its only for two (one?) spells, but yeah…

  • reinstated HandleThreatSpells(). for one it is required for the changed done by Lynxed and x3n, on the other hand it solved the onCast-Issue without adding weird parameters and checks to the addThreat/threatAssist-Functions

  • energize is now checked for in calcThreat. Here too, no more weird parameters.

  • Icy Touch and Intimidate are already correctly handled, so no longer in sql

so whats left…

… if this alls works out as intended, only the -50% to Paladin-healing while tanking

SpellMgr::LoadSpellCustomAttr()

[CODE]case: 33790 // Salvation: affecting Beacon of-, Holy-, Flash of- Light, Holy Shock - Heal

spellInfo->EffectSpellClassMask[0] = flag96(0xC0000000, 0x1010000, 0);

count++;

break;[/CODE]

Forgot to edit SpellAuraEffects.cpp?

[CODE]

[ 15%] [ 16%] Building CXX object src/server/game/CMakeFiles/game.dir/Spells/SpellScript.cpp.o

Building CXX object src/server/game/CMakeFiles/game.dir/Spells/Auras/SpellAuraEffects.cpp.o

/trinitycore/src/server/game/Spells/Auras/SpellAuraEffects.cpp: In member function ‘void AuraEffect::PeriodicTick(AuraApplication*, Unit*) const’:

/trinitycore/src/server/game/Spells/Auras/SpellAuraEffects.cpp:1787: error: no matching function for call to ‘HostileRefManager::threatAssist(Unit*&, float, const SpellEntry*, bool)’

/trinitycore/src/server/game/Combat/HostileRefManager.h:45: note: candidates are: void HostileRefManager::threatAssist(Unit*, float, const SpellEntry*)

/trinitycore/src/server/game/Spells/Auras/SpellAuraEffects.cpp:1824: error: no matching function for call to ‘HostileRefManager::threatAssist(Unit*&, float, const SpellEntry*, bool)’

/trinitycore/src/server/game/Combat/HostileRefManager.h:45: note: candidates are: void HostileRefManager::threatAssist(Unit*, float, const SpellEntry*)

make[2]: *** [src/server/game/CMakeFiles/game.dir/Spells/Auras/SpellAuraEffects.cpp.o] Error 1

make[2]: *** Waiting for unfinished jobs…

make[1]: *** [src/server/game/CMakeFiles/game.dir/all] Error 2

make[1]: *** Waiting for unfinished jobs…

[ 81%] Built target scripts

make: *** [all] Error 2[/CODE]

EDIT: fixed it; (not sure if it’s correct way to fix it, but it compiles.)



diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp

index 5b406af..125203d 100755

--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp

+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp

@@ -1784,7 +1784,7 @@ void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit * caster) const

         	int32 gain = target->ModifyPower(power,amount);


         	if (caster)

-                target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto(), true);

+                target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());

         	break;

     	}

     	case SPELL_AURA_PERIODIC_ENERGIZE:

@@ -1821,7 +1821,7 @@ void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit * caster) const

         	int32 gain = target->ModifyPower(power,amount);


         	if (caster)

-                target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto(), true);

+                target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());

         	break;

     	}

     	case SPELL_AURA_POWER_BURN_MANA:

what you are having, is a relic of the previous patch^^

  1. spell_threat is outdated.

Indeed.

It was for this reason that I started working on updating the spell threat time ago. Alas, I have never finished it, but I still managed to get some insight - in fact using the same data for research. You have arrived at many of the same conclusions as I had then:

[ol][li]Adding damage-to-threat multiplier to DB[/li]OK

[li]Additional threat multiplier for tank classes[/li]Almost OK but for two details:
Firstly I’d rather see 57339 as the modifier, as it is not death persistent
Secondly: Paladins can hit RF multiple times even when it is already active, which leads to threat modifier stacking. The paladin part should be done in the core (HandleAuraSpecificMods()) with appropriate checks for presence of the threat modifier aura.

[li]The code[/li]I doubt that all spells should cause ‘cast’ threat - the threat handled in HandleThreatSpells(). Using spell level as default cast threat is only OK with buffs, debufs and non-damage offensive spells a. Dmg and heal spells should only cause the dmg/heal-based threat. Energizes should probably be handled the same way as dmg/heal in this respect. Of course if the DB table has cast threat for a dmg spell, then it is still to be used (Maul, HS).

SPELL_ATTR3_NO_INITIAL_AGGRO needs to be checked in HandleAuraSpecificMods().

A word on efficiency: In threatAssist case AddThreat is called potentially many times, each time invoking ThreatCalcHelper::calcThreat() with its ThreatEntry searches and energize checks. That is not cool. This function could be split into two. The first one - dependent only on the spell - would do ThreatEntry-based stuff and determine if the spell is an energize. The second one would do the victim-dependent stuff. Then there would be another version of AddThreat(…) used only by threatAssist and it would only call the victim-based threat calc part, the spell entry based part being precalculated only once up in threatAssist.
Also SPELL_ATTR1_NO_THREAT should be checked earlier than in calcThreat. threatAssist and AddThreat would be good places.


a Defining this class of spells based on SpellEntry parameters is not quite as simple as it sounds in words. It may be better to do it at startup in SpellMgr by defining a SPELL_ATTR0_CU_* for it rather than calculating it again and again on the fly. But that is to be seen yet.

[li]Paladin healing threat reduction[/li]AFAIK indeed all paladin healing should generate only half the threat. As you said, 33790 is the only candidate for that. It needs to go to playercreateinfo_spell.

[/ol]

That’s it, then. Let’s sort out those things I mentioned and I’ll take care of pushing it.

just my thoughts in short:

[ul][li]death-persistance for tank-class passives:[/li]you’ve got a point. But in case of Frost Presence, which itself is death-persistant i’d like to keep the death-persistant passive.

[li]stacking the passive (ex. Righteous Fury)[/li]using .list aura i couldn’t reproduce the issue. I’d prefer to keep it DB-only

[li]reduce paladin-healing-threat:[/li]ok, will need to find any healing proc or direct cast for a complete mask (hopefully, they all have FamilyFlags)

[li]CastThreat for Damage/Healing spells:[/li]you’re right. if they had this, it would be listed like in the buff/debuff-cases. i’ll work it in.

[li]checking SPELL_ATTR1_NO_THREAT early on:[/li]good point, will adapt.

[li]overall efficiency:[/li]ah … well … no promisses, i’ll see what i can do.

[/ul]

paladin healing:


Seal of Light - Proc:      0x00040000 0x0        0x0

Judgement of Light - Proc: 0x00080000 0x0        0x0

Holy Shock - Heal:         0x0        0x00010000 0x0

Holy Light:                0x80000000 0x0        0x0

Flash of Light:            0x40000000 0x0        0x0

Beacon of Light - proc:    0x0        0x01000000 0x0

Infusion of Light - proc:  0x0        0x0        0x0

Ardent Defender - proc:    0x0        0x0        0x0

Divine Storm - heal:       0x0        0x0        0x0

Glyph of Holy Light:       not found

Sheath of Light proc:      not found

----------------------------------------------------

Final:                     0xC00C0000 0x01010000 0x0

Looks promising though, keep the good work up. I wont pretend I understand all of this, but threat does need a revamp =o

thats it … i hope /emoticons/default_wink.png

what should be researched is the flat threat of the ranks of the following spells. currently only the last rank amount is known:

Death Knight: Scourge Strike,

Druid: Bash

Warrior: Cleave, Heroic Strike, Revenge, Shield Slam, Slam

changes:

  • reordered the content of spell_threat to use the first rank of spells, if available

  • added the custom SpellClassMask for Salvation and added it so playercreateinfo_spell (How i got the mask is in the previous post)

  • Druid, Paladin and Warrior no longer use the death-persistant Tank Class Threat Passive (although it should have been removed, when the trigger_aura was removed in case of death)

  • introduced a custom Attribute to efficiently check, whether a spell causes onCast-Threat or not

  • moved the check for SPELL_ATTR1_NO_THREAT to addThreat(), threatAssist() and HandleThreatSpells() respectively

  • added check for SPELL_ATTR3_NO_INITIAL_AGGRO in HandleThreatSpells()

  • hopefully increased overall performance by reducing redundant calcThreat()-calls^^

Code:

[SPOILER]

[CODE]diff --git a/src/server/game/Combat/HostileRefManager.cpp b/src/server/game/Combat/HostileRefManager.cpp

index c7b40a9…5c1a506 100755

— a/src/server/game/Combat/HostileRefManager.cpp

+++ b/src/server/game/Combat/HostileRefManager.cpp

@@ -32,19 +32,17 @@ HostileRefManager::~HostileRefManager()

// The pVictim is hated than by them as well

// use for buffs and healing threat functionality

-void HostileRefManager::threatAssist(Unit *pVictim, float fThreat, SpellEntry const *pThreatSpell, bool pSingleTarget)

+void HostileRefManager::threatAssist(Unit *pVictim, float fThreat, SpellEntry const *pThreatSpell)

{

  • HostileReference* ref;

  • float size = pSingleTarget ? 1.0f : getSize(); // if pSingleTarget do not divide threat

  • ref = getFirst();

  • while (ref != NULL)

  • HostileReference* ref = getFirst();

  • float threat = ThreatCalcHelper::calcThreat(pVictim, NULL, fThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell);

  • threat /= getSize();

  • while (ref)

    {

  •    float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, fThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell);
    
  •    if (pVictim == getOwner())
    
  •        ref->addThreat(threat / size);          // It is faster to modify the threat durectly if possible
    
  •    else
    
  •        ref->getSource()->addThreat(pVictim, threat / size);
    
  •    if (!(ThreatCalcHelper::checkValidity(pVictim, ref->getSource()->getOwner(), pThreatSpell)))
    
  •        continue;
    
  •    ref->getSource()->doAddThreat(pVictim, threat);
    
       ref = ref->next();
    

    }

}

diff --git a/src/server/game/Combat/HostileRefManager.h b/src/server/game/Combat/HostileRefManager.h

index 0a8ad47…b49268c 100755

— a/src/server/game/Combat/HostileRefManager.h

+++ b/src/server/game/Combat/HostileRefManager.h

@@ -42,7 +42,7 @@ class HostileRefManager : public RefManager<Unit, ThreatManager>

     // send threat to all my hateres for the pVictim

     // The pVictim is hated than by them as well

     // use for buffs and healing threat functionality
  •    void threatAssist(Unit *pVictim, float fThreat, SpellEntry const *threatSpell = 0, bool pSingleTarget = false);
    
  •    void threatAssist(Unit *pVictim, float fThreat, SpellEntry const *threatSpell = 0);
    
    
       void addTempThreat(float fThreat, bool apply);
    

diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp

index abf9ee0…cbc4ffa 100755

— a/src/server/game/Combat/ThreatManager.cpp

+++ b/src/server/game/Combat/ThreatManager.cpp

@@ -36,8 +36,14 @@ float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* /pHatingUnit/, floa

{

 if (pThreatSpell)

 {
  •    if (pThreatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT)
    
  •        return 0.0f;
    
  •    if (SpellThreatEntry const * ThreatEntry = sSpellMgr->GetSpellThreatEntry(pThreatSpell->Id))
    
  •        if (ThreatEntry->pctMod != 1.0f)
    
  •            fThreat *= ThreatEntry->pctMod;
    
  •    // Energize is not affected by Mods
    
  •    for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
    
  •        if (pThreatSpell->Effect[i] == SPELL_EFFECT_ENERGIZE || pThreatSpell->EffectApplyAuraName[i] == SPELL_AURA_PERIODIC_ENERGIZE)
    
  •            return fThreat;
    
    
       if (Player* modOwner = pHatedUnit->GetSpellModOwner())
    
           modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, fThreat);
    

@@ -46,6 +52,34 @@ float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* /pHatingUnit/, floa

 return pHatedUnit->ApplyTotalThreatModifier(fThreat, schoolMask);

}

+bool ThreatCalcHelper::checkValidity(Unit pHatedUnit, Unit pHatingUnit, SpellEntry const *pThreatSpell)

+{

  • //function deals with adding threat and adding players and pets into ThreatList

  • //mobs, NPCs, guards have ThreatList and HateOfflineList

  • //players and pets have only InHateListOf

  • //HateOfflineList is used co contain unattackable victims (in-flight, in-water, GM etc.)

  • // not to self

  • if (pHatedUnit == pHatingUnit)

  •    return false;
    
  • // not to GM

  • if (!pHatedUnit || (pHatedUnit->GetTypeId() == TYPEID_PLAYER && pHatedUnit->ToPlayer()->isGameMaster()))

  •    return false;
    
  • // not to dead and not for dead

  • if (!pHatedUnit->isAlive() || !pHatingUnit->isAlive())

  •    return false;
    
  • // spell not causing threat

  • if (pThreatSpell && pThreatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT)

  •    return false;
    
  • ASSERT(pHatingUnit->GetTypeId() == TYPEID_UNIT);

  • return true;

+}

//============================================================

//================= HostileReference ==========================

//============================================================

@@ -357,44 +391,31 @@ void ThreatManager::clearReferences()

void ThreatManager::addThreat(Unit* pVictim, float fThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell)

{

  • //function deals with adding threat and adding players and pets into ThreatList

  • //mobs, NPCs, guards have ThreatList and HateOfflineList

  • //players and pets have only InHateListOf

  • //HateOfflineList is used co contain unattackable victims (in-flight, in-water, GM etc.)

  • // not to self

  • if (pVictim == getOwner())

  • if (!(ThreatCalcHelper::checkValidity(pVictim, getOwner(), pThreatSpell)))

    return;
    
  • // not to GM

  • if (!pVictim || (pVictim->GetTypeId() == TYPEID_PLAYER && pVictim->ToPlayer()->isGameMaster()))

  •    return;
    
  • // not to dead and not for dead

  • if (!pVictim->isAlive() || !getOwner()->isAlive())

  •    return;
    
  • ASSERT(getOwner()->GetTypeId() == TYPEID_UNIT);

  • float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, fThreat, schoolMask, pThreatSpell);

  • doAddThreat(pVictim, ThreatCalcHelper::calcThreat(pVictim, iOwner, fThreat, schoolMask, pThreatSpell));

+}

+void ThreatManager::doAddThreat(Unit* pVictim, float fThreat)

+{

 // must check > 0.0f, otherwise dead loop
  • if (threat > 0.0f && pVictim->GetReducedThreatPercent())
  • if (fThreat > 0.0f && pVictim->GetReducedThreatPercent())

    {

  •    uint32 reducedThreadPercent = pVictim->GetReducedThreatPercent();
    
  •    uint32 reducedThreatPercent = pVictim->GetReducedThreatPercent();
    
    
       Unit *unit = pVictim->GetMisdirectionTarget();
    
       if (unit)
    
           if (Aura* pAura = unit->GetAura(63326)) // Glyph of Vigilance
    
  •            reducedThreadPercent += SpellMgr::CalculateSpellEffectAmount(pAura->GetSpellProto(), 0);
    
  •            reducedThreatPercent += SpellMgr::CalculateSpellEffectAmount(pAura->GetSpellProto(), 0);
    
  •    float reducedThreat = threat * reducedThreadPercent / 100;
    
  •    threat -= reducedThreat;
    
  •    float reducedThreat = fThreat * reducedThreatPercent / 100;
    
  •    fThreat -= reducedThreat;
    
       if (unit)
    
           _addThreat(unit, reducedThreat);
    

    }

  • _addThreat(pVictim, threat);
  • _addThreat(pVictim, fThreat);

}

void ThreatManager::_addThreat(Unit *pVictim, float fThreat)

diff --git a/src/server/game/Combat/ThreatManager.h b/src/server/game/Combat/ThreatManager.h

index b8b3a2b…da4b09b 100755

— a/src/server/game/Combat/ThreatManager.h

+++ b/src/server/game/Combat/ThreatManager.h

@@ -43,6 +43,7 @@ class ThreatCalcHelper

{

 public:

     static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
  •    static bool checkValidity(Unit* pHatedUnit, Unit* pHatingUnit, SpellEntry const *pThreatSpell = NULL);
    

};

//==============================================================

@@ -196,6 +197,8 @@ class ThreatManager

     void clearReferences();


     void addThreat(Unit* pVictim, float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
  •    void doAddThreat(Unit* pVictim, float fThreat);
    
     void modifyThreatPercent(Unit *pVictim, int32 iPercent);


     float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false);

diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp

index 5f3a6e2…e1155dd 100755

— a/src/server/game/Entities/Unit/Unit.cpp

+++ b/src/server/game/Entities/Unit/Unit.cpp

@@ -693,12 +693,7 @@ uint32 Unit::DealDamage(Unit pVictim, uint32 damage, CleanDamage const cleanDa

         pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0);


     if (pVictim->GetTypeId() != TYPEID_PLAYER)
  •    {
    
  •        if (spellProto && IsDamageToThreatSpell(spellProto))
    
  •            pVictim->AddThreat(this, damage * 2.0f, damageSchoolMask, spellProto);
    
  •        else
    
  •            pVictim->AddThreat(this, (float)damage, damageSchoolMask, spellProto);
    
  •    }
    
  •        pVictim->AddThreat(this, (float)damage, damageSchoolMask, spellProto);
    
       else                                                // victim is a player
    
       {
    
           // random durability for items (HIT TAKEN)
    

@@ -9947,6 +9942,9 @@ void Unit::EnergizeBySpell(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers

 SendEnergizeSpellLog(pVictim, SpellID, Damage, powertype);

 // needs to be called after sending spell log

 pVictim->ModifyPower(powertype, Damage);
  • SpellEntry const *spellInfo = sSpellStore.LookupEntry(SpellID);

  • pVictim->getHostileRefManager().threatAssist(this, float(Damage) * 0.5f, spellInfo);

}

uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)

@@ -11182,30 +11180,6 @@ bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) con

 return false;

}

-bool Unit::IsDamageToThreatSpell(SpellEntry 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 *pVictim, uint32 *pdamage, WeaponAttackType attType, SpellEntry const *spellProto)

{

 if (!pVictim)

diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h

index 97599a4…07a7654 100755

— a/src/server/game/Entities/Unit/Unit.h

+++ b/src/server/game/Entities/Unit/Unit.h

@@ -1472,8 +1472,6 @@ class Unit : public WorldObject

     Aura * AddAura(SpellEntry const *spellInfo, uint8 effMask, Unit *target);

     void SetAuraStack(uint32 spellId, Unit *target, uint32 stack);
  •    bool IsDamageToThreatSpell(SpellEntry 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 9ea8100…ff1a300 100755

— a/src/server/game/Spells/Spell.cpp

+++ b/src/server/game/Spells/Spell.cpp

@@ -3428,8 +3428,7 @@ void Spell::_handle_immediate_phase()

{

 m_spellAura = NULL;

 // handle some immediate features of the spell here
  • HandleThreatSpells(m_spellInfo->Id);

  • HandleThreatSpells();

    PrepareScriptHitHandlers();

    for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)

@@ -4615,22 +4614,51 @@ void Spell::TakeReagents()

 }

}

-void Spell::HandleThreatSpells(uint32 spellId)

+void Spell::HandleThreatSpells()

{

  • if (!m_targets.getUnitTarget() || !spellId)
  • 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(spellId);
  • 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);
    
  • if (!threat)

  •    return;
    
  •    threat += threatEntry->flatMod;
    
  • }

  • else if ((m_customAttr & SPELL_ATTR0_CU_NO_INITIAL_THREAT) == 0)

  •    threat += m_spellInfo->spellLevel;
    
  • // 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::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)

  • {

  •    if (ihit->missCondition != SPELL_MISS_NONE)
    
  •        continue;
    
  • m_targets.getUnitTarget()->AddThreat(m_caster, float(threat));
  •    Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
    
  •    if (!target)
    
  •        continue;
    
  • sLog->outStaticDebug(“Spell %u, rank %u, added an additional %i threat”, spellId, sSpellMgr->GetSpellRank(spellId), threat);
  •    // positive spells distribute threat among all units that are in combat with target, like healing
    
  •    if (IsPositiveSpell(m_spellInfo->Id))
    
  •        target->getHostileRefManager().threatAssist(m_caster, threat, m_spellInfo);
    
  •    // for negative spells threat gets distributed among affected targets
    
  •    else
    
  •    {
    
  •        if (!target->CanHaveThreatList())
    
  •            continue;
    
  •        target->AddThreat(m_caster, threat, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
    
  •    }
    
  • }

  • sLog->outStaticDebug(“Spell %u, added an additional %f threat for %s %u target(s)”, m_spellInfo->Id, threat, IsPositiveSpell(m_spellInfo->Id) ? “assisting” : “harming”, uint32(m_UniqueTargetInfo.size()));

}

void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i)

diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h

index 34ddf5c…378c64c 100755

— a/src/server/game/Spells/Spell.h

+++ b/src/server/game/Spells/Spell.h

@@ -493,7 +493,7 @@ class Spell

     void SendPlaySpellVisual(uint32 SpellID);


     void HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i);
  •    void HandleThreatSpells(uint32 spellId);
    
  •    void HandleThreatSpells();
    
    
       const SpellEntry * const m_spellInfo;
    
       Item* m_CastItem;
    

diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp

index 9211aab…b250ea3 100755

— a/src/server/game/Spells/SpellMgr.cpp

+++ b/src/server/game/Spells/SpellMgr.cpp

@@ -1633,26 +1633,19 @@ 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 %u aggro generating spells", count);
    
  •    sLog->outString(">> Loaded 0 aggro generating spells");
    
       sLog->outString();
    
       return;
    

    }

 do

 {

     Field *fields = result->Fetch();
     uint32 entry = fields[0].GetUInt32();
  •    uint16 Threat = fields[1].GetUInt16();
    
    
       if (!sSpellStore.LookupEntry(entry))
    
       {
    

@@ -1660,12 +1653,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();

}

@@ -3478,6 +3475,16 @@ void SpellMgr::LoadSpellCustomAttr()

             case SPELL_EFFECT_HEAL:

                 mSpellCustomAttr[i] |= SPELL_ATTR0_CU_DIRECT_DAMAGE;

                 count++;
  •            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:
    
  •                mSpellCustomAttr[i] |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
    
  •                count++;
    
                   break;
    
               case SPELL_EFFECT_CHARGE:
    
               case SPELL_EFFECT_CHARGE_DEST:
    

@@ -3555,6 +3562,19 @@ void SpellMgr::LoadSpellCustomAttr()

                 mSpellCustomAttr[i] |= SPELL_ATTR0_CU_AURA_CC;

                 count++;

                 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:
    
  •                mSpellCustomAttr[i] |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
    
  •                count++;
    
  •                break;
    
           }
    
       }
    

@@ -3863,6 +3883,10 @@ void SpellMgr::LoadSpellCustomAttr()

         spellInfo->rangeIndex = 13;

         count++;

         break;
  •    case 47502: // Salvation: Reduced Healing-Threat
    
  •        spellInfo->EffectSpellClassMask[0] = flag96(0xC00C0000, 0x1010000, 0);
    
  •        count++;
    
  •        break;
    
       case 48743: // Death Pact
    
           spellInfo->AttributesEx &= ~SPELL_ATTR1_CANT_TARGET_SELF;
    
           count++;
    

diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h

index 6a4ed30…412731c 100755

— a/src/server/game/Spells/SpellMgr.h

+++ b/src/server/game/Spells/SpellMgr.h

@@ -637,6 +637,13 @@ enum ProcFlagsEx

 PROC_EX_EVADE | PROC_EX_IMMUNE | PROC_EX_DEFLECT | \

 PROC_EX_ABSORB | PROC_EX_REFLECT | PROC_EX_INTERRUPT)

+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

+};

struct SpellProcEventEntry

{

 uint32      schoolMask;                                 // if nonzero - bit mask for matching proc condition based on spell candidate's school: Fire=2, Mask=1<<(2-1)=2

@@ -698,7 +705,7 @@ enum SpellGroupStackRule

typedef std::map<SpellGroup, SpellGroupStackRule> SpellGroupStackMap;

-typedef std::map<uint32, uint16> SpellThreatMap;

+typedef std::map<uint32, SpellThreatEntry> SpellThreatMap;

// Spell script target related declarations (accessed using SpellMgr functions)

enum SpellScriptTargetType

@@ -879,27 +886,27 @@ inline bool IsProfessionSkill(uint32 skill)

enum SpellCustomAttributes

{

  • SPELL_ATTR0_CU_ENCHANT_PROC = 0x00000001,

  • 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_NONE2 = 0x00000020, // UNUSED

  • SPELL_ATTR0_CU_AURA_CC = 0x00000040,

  • SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100,

  • SPELL_ATTR0_CU_CHARGE = 0x00000200,

  • SPELL_ATTR0_CU_LINK_CAST = 0x00000400,

  • SPELL_ATTR0_CU_LINK_HIT = 0x00000800,

  • SPELL_ATTR0_CU_LINK_AURA = 0x00001000,

  • SPELL_ATTR0_CU_LINK_REMOVE = 0x00002000,

  • SPELL_ATTR0_CU_PICKPOCKET = 0x00004000,

  • SPELL_ATTR0_CU_EXCLUDE_SELF = 0x00008000,

  • SPELL_ATTR0_CU_NEGATIVE_EFF0 = 0x00010000,

  • SPELL_ATTR0_CU_NEGATIVE_EFF1 = 0x00020000,

  • SPELL_ATTR0_CU_NEGATIVE_EFF2 = 0x00040000,

  • SPELL_ATTR0_CU_IGNORE_ARMOR = 0x00080000,

  • SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2,

  • SPELL_ATTR0_CU_ENCHANT_PROC = 0x00000001,

  • SPELL_ATTR0_CU_CONE_BACK = 0x00000002,

  • SPELL_ATTR0_CU_CONE_LINE = 0x00000004,

  • SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008,

  • 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,

  • SPELL_ATTR0_CU_CHARGE = 0x00000200,

  • SPELL_ATTR0_CU_LINK_CAST = 0x00000400,

  • SPELL_ATTR0_CU_LINK_HIT = 0x00000800,

  • SPELL_ATTR0_CU_LINK_AURA = 0x00001000,

  • SPELL_ATTR0_CU_LINK_REMOVE = 0x00002000,

  • SPELL_ATTR0_CU_PICKPOCKET = 0x00004000,

  • SPELL_ATTR0_CU_EXCLUDE_SELF = 0x00008000,

  • SPELL_ATTR0_CU_NEGATIVE_EFF0 = 0x00010000,

  • SPELL_ATTR0_CU_NEGATIVE_EFF1 = 0x00020000,

  • SPELL_ATTR0_CU_NEGATIVE_EFF2 = 0x00040000,

  • SPELL_ATTR0_CU_IGNORE_ARMOR = 0x00080000,

  • SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2,

};

@@ -1017,13 +1024,19 @@ class SpellMgr

         return rule;

     }
  •    uint16 GetSpellThreat(uint32 spellid) const
    
  •    SpellThreatEntry const* 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;
    
       }
    
    
       // Spell proc events[/CODE][/SPOILER]
    

SQL:

[CODE]-- ----------

– Paladin: Salvation


DELETE FROM playercreateinfo_spell WHERE spell = 33790;

INSERT INTO playercreateinfo_spell VALUES (1514, 2, 33790, ‘Paladin: -50% Healing-Threat’, 1);


– Tank Class Passive Threat


DELETE FROM spell_linked_spell WHERE spell_trigger IN (7376, 21178, 25780, 48263);

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, 57339, 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;

– (*) first rank only. Check spell_ranks whether all spells are covered.

INSERT INTO spell_threat VALUES

– Other (Found by: 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 (Warlock)

(28176, 0, 0.00, 0.0), – *Fel Armor - Heal (Warlock) [Assumption]

(8056, 0, 2.00, 0.0), – *Frost Shock (Shaman) [Assumption]

(26688, 0, 0.00, 0.0), – *Anesthetic Poison - Proc (Rogue)

(15237, 0, 0.00, 0.0), – *Holy Nova - Heal (Priest)

(23455, 0, 0.00, 0.0), – *Holy Nova - Damage (Priest)

(32546, 0, 0.50, 0.0), – *Binding Heal (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, 120, 1.00, 0.0), – *Scourge Strike

(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, 158, 1.00, 0.0), – *Bash

(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)

(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

(25894, 0, 0.00, 0.0), – *Greater Blessing of Wisdom

(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, 112, 1.00, 0.0), – *Cleave

(78, 259, 1.00, 0.0), – *Heroic Strike

(57755, 0, 1.50, 0.0), – Heroic Throw

(6572, 121, 1.00, 0.0), – *Revenge

(23922, 770, 1.00, 0.0), – *Shield Slam

(1464, 140, 1.00, 0.0), – *Slam

(7386, 345, 1.00, 0.05), – Sunder Armor

(20243, 0, 1.00, 0.05), – *Devastate [maybe redundant because of casting Sunder Armor?]

(6343, 0, 1.85, 0.0); – *Thunder Clap[/CODE]

PS: i fail at naming. doAddThreat() and checkValidity() are open for a rename^^

PPS: Paste2 just failed me /emoticons/default_sad.png

/e: who’s brilliant idea was to block the upload of *.sql files…

/e²: diffed again against 180b739 Core/Entities: Avoid unique key violations during character inventory saving

if it’s still not working i’m out of ideas

going to test them

SQL:
[/SPOILER][SPOILER]

[CODE]-- ----------

– Paladin: Salvation


DELETE FROM playercreateinfo_spell WHERE spell = 33790;

INSERT INTO playercreateinfo_spell VALUES (1514, 2, 33790, ‘Paladin: -50% Healing-Threat’, 1);


– Tank Class Passive Threat


DELETE FROM spell_linked_spell WHERE spell_trigger IN (7376, 21178, 25780, 48263);

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, 57339, 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;

– (*) first rank only. Check spell_ranks whether all spells are covered.

INSERT INTO spell_threat VALUES

– Other (Found by: 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 (Warlock)

(28176, 0, 0.00, 0.0), – *Fel Armor - Heal (Warlock) [Assumption]

(8056, 0, 2.00, 0.0), – *Frost Shock (Shaman) [Assumption]

(26688, 0, 0.00, 0.0), – *Anesthetic Poison - Proc (Rogue)

(15237, 0, 0.00, 0.0), – *Holy Nova - Heal (Priest)

(23455, 0, 0.00, 0.0), – *Holy Nova - Damage (Priest)

(32546, 0, 0.50, 0.0), – *Binding Heal (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, 120, 1.00, 0.0), – *Scourge Strike

(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, 158, 1.00, 0.0), – *Bash

(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)

(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

(25894, 0, 0.00, 0.0), – *Greater Blessing of Wisdom

(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, 112, 1.00, 0.0), – *Cleave

(78, 259, 1.00, 0.0), – *Heroic Strike

(57755, 0, 1.50, 0.0), – Heroic Throw

(6572, 121, 1.00, 0.0), – *Revenge

(23922, 770, 1.00, 0.0), – *Shield Slam

(1464, 140, 1.00, 0.0), – *Slam

(7386, 345, 1.00, 0.05), – Sunder Armor

(20243, 0, 1.00, 0.05), – *Devastate [maybe redundant because of casting Sunder Armor?]

(6343, 0, 1.85, 0.0); – *Thunder Clap[/CODE]
[/SPOILER]

PS: i fail at naming. doAddThreat() and checkValidity() are open for a rename^^

PPS: Paste2 just failed me /emoticons/default_sad.png

/e: who’s brilliant idea was to block the upload of *.sql files…

patch doesn’t apply using git apply…

Hi, I can’t rewiev the code tonight, but I’ll get to it in a day or two. So today just a quickie:

Ok, but check that Frost Presence doesn’t get recast after the dead DK is revived. And if it is, check that the passive threat mod doesn’t stack that way.

It has been some time since I toyed with it, so the stacking issue may no longer exist. If it is indeed so, it can stay DB side.

Won’t happen now, I guess, seeing as ranks no longer exist on retail. But there is an easy way to estimate the values: Look at Maul and Lacerate. You’ll notice that the flat threat to direct dmg ratio is pretty much constant for each ability (factoring in rounding errors). Knowing this it will be easy to populate the table with the lower ranks.

emulated reduced Threat for spellRanks in SQL

didn’t update the code

last uncertainty left is, whether Devastate needs it’s 5% AP-Mod or if the triggered Sunder Armor already does that.

There’s a error in playercreateinfo_spell, and you should use 0 for first field instead of 1514 for all races.

fixed SQL:

[CODE]


– Paladin: Salvation


DELETE FROM playercreateinfo_spell WHERE spell = 33790;
INSERT INTO playercreateinfo_spell VALUES
(0, 2, 33790, ‘Paladin: -50% Healing-Threat’);
[/sql][/CODE]

*zonk

a stupid typo, thank you.

was intended to be 1541 = [Draenai + BloodElf + Dwarf + Human] instead of 1514

/e:updated previous post

that doesn’t work because the race field uses tinyint, and max number for tinyint is 255. So 1514 would result 255 instead.

Tested, the fix does NOT work. First Try Loginserver stopped working after just 1 minute, second try the core hanged up. No chrashlogs cause it seems not to be a crash as usual, server just stops and nothing happens.

As we tried this in the early morning there weren´t much users on so we could possibly localize the error source. One of the players (warlock) tested his ROTA with a training dummy. This seemed to be the reason for this…maybe it helps you.