diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 82e3077d8..9d436ef09 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -60,7 +60,7 @@ AggressorAI::MoveInLineOfSight(Unit *u) } else if(sMapStore.LookupEntry(m_creature->GetMapId())->IsDungeon()) { - m_creature->AddThreat(u, 0.0f); + m_creature->AddThreat(u); u->SetInCombatWith(m_creature); } } @@ -155,7 +155,7 @@ AggressorAI::AttackStart(Unit *u) // DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", m_creature->GetName(), u->GetGUIDLow()); i_victimGuid = u->GetGUID(); - m_creature->AddThreat(u, 0.0f); + m_creature->AddThreat(u); m_creature->SetInCombatWith(u); u->SetInCombatWith(m_creature); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index fc2ab843b..0c227ff30 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -2057,7 +2057,7 @@ void Creature::SetInCombatWithZone() if (pPlayer->isAlive()) { pPlayer->SetInCombatWith(this); - AddThreat(pPlayer, 0.0f); + AddThreat(pPlayer); } } } diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index e7fa84a08..3e9c59e28 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -948,7 +948,7 @@ void CreatureEventAI::AttackStart(Unit *who) if (m_creature->Attack(who, MeleeEnabled)) { - m_creature->AddThreat(who, 0.0f); + m_creature->AddThreat(who); m_creature->SetInCombatWith(who); who->SetInCombatWith(m_creature); @@ -1010,7 +1010,7 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who) } else if (m_creature->GetMap()->IsDungeon()) { - m_creature->AddThreat(who, 0.0f); + m_creature->AddThreat(who); who->SetInCombatWith(m_creature); } } diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index aaa9391e6..3d5b529a7 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -138,7 +138,7 @@ void GuardAI::AttackStart(Unit *u) if(m_creature->Attack(u,true)) { i_victimGuid = u->GetGUID(); - m_creature->AddThreat(u, 0.0f); + m_creature->AddThreat(u); m_creature->SetInCombatWith(u); u->SetInCombatWith(m_creature); diff --git a/src/game/HostilRefManager.cpp b/src/game/HostilRefManager.cpp index 0fa7e379a..c9cd9cd97 100644 --- a/src/game/HostilRefManager.cpp +++ b/src/game/HostilRefManager.cpp @@ -40,7 +40,7 @@ void HostileRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry co ref = getFirst(); while(ref != NULL) { - float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell); + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, false, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell); if(pVictim == getOwner()) ref->addThreat(float (threat) / size); // It is faster to modify the threat durectly if possible else diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 9dfbc43fa..354ef371a 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -172,7 +172,7 @@ void PetAI::UpdateAI(const uint32 diff) return; //if pet misses its target, it will also be the first in threat list - m_creature->getVictim()->AddThreat(m_creature,0.0f); + m_creature->getVictim()->AddThreat(m_creature); if( _needToStop() ) _stopAttack(); diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp index bc41faee3..49cbc7e0c 100644 --- a/src/game/ReactorAI.cpp +++ b/src/game/ReactorAI.cpp @@ -49,7 +49,7 @@ ReactorAI::AttackStart(Unit *p) { DEBUG_LOG("Tag unit GUID: %u (TypeId: %u) as a victim", p->GetGUIDLow(), p->GetTypeId()); i_victimGuid = p->GetGUID(); - m_creature->AddThreat(p, 0.0f); + m_creature->AddThreat(p); m_creature->SetInCombatWith(p); p->SetInCombatWith(m_creature); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index b13d5133c..d3e1c0786 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1092,7 +1092,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) if (!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) ((Creature*)unit)->AI()->AttackedBy(realCaster); - unit->AddThreat(realCaster, 0.0f); + unit->AddThreat(realCaster); unit->SetInCombatWith(realCaster); realCaster->SetInCombatWith(unit); @@ -1116,7 +1116,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) if (unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO)) { realCaster->SetInCombatState(unit->GetCombatTimer() > 0); - unit->getHostileRefManager().threatAssist(realCaster, 0.0f); + unit->getHostileRefManager().threatAssist(realCaster, 0.0f, m_spellInfo); } } } @@ -3770,7 +3770,7 @@ void Spell::HandleThreatSpells(uint32 spellId) if(!threat) return; - m_targets.getUnitTarget()->AddThreat(m_caster, float(threat)); + m_targets.getUnitTarget()->AddThreat(m_caster, float(threat), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo); DEBUG_LOG("Spell %u, rank %u, added an additional %i threat", spellId, spellmgr.GetSpellRank(spellId), threat); } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 43f9e5a5c..e0db4c250 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -233,7 +233,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus &Aura::HandleUnused, //181 unused (3.0.8a) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT - &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 + &Aura::HandleNoImmediateEffect, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746, implemented in ThreatCalcHelper::calcThreat &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult @@ -2195,7 +2195,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 1515: // Tame beast // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness if( caster && m_target->CanHaveThreatList()) - m_target->AddThreat(caster, 10.0f); + m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); return; case 13139: // net-o-matic // root to self part of (root_target->charge->root_self sequence @@ -4039,7 +4039,7 @@ void Aura::HandleAuraModTotalThreat(bool apply, bool Real) float threatMod = apply ? float(m_modifier.m_amount) : float(-m_modifier.m_amount); - m_target->getHostileRefManager().threatAssist(caster, threatMod); + m_target->getHostileRefManager().threatAssist(caster, threatMod, GetSpellProto()); } void Aura::HandleModTaunt(bool apply, bool Real) @@ -6311,6 +6311,10 @@ void Aura::PeriodicTick() // This method can modify pdamage bool isCrit = IsCritFromAbilityAura(pCaster, pdamage); + // send critical in hit info for threat calculation + if (isCrit) + cleanDamage.hitOutCome = MELEE_HIT_CRIT; + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", @@ -6556,7 +6560,7 @@ void Aura::PeriodicTick() if(gain_amount) { int32 gain = pCaster->ModifyPower(power, gain_amount); - m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); + m_target->AddThreat(pCaster, float(gain) * 0.5f, pInfo.critical, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); } break; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index db09186e1..531b23878 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4681,7 +4681,7 @@ void Spell::EffectThreat(uint32 /*i*/) if(!unitTarget->CanHaveThreatList()) return; - unitTarget->AddThreat(m_caster, float(damage)); + unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo); } void Spell::EffectHealMaxHealth(uint32 /*i*/) diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index a8802d4d9..11b560482 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -30,12 +30,21 @@ //============================================================== // The pHatingUnit is not used yet -float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) +float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { + // all flat mods applied early + if(!pThreat) + return 0.0f; + if (pThreatSpell) + { if (Player* modOwner = pHatedUnit->GetSpellModOwner()) modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, pThreat); + if(crit) + pThreat *= pHatedUnit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRITICAL_THREAT,schoolMask); + } + float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, schoolMask); return threat; } @@ -357,7 +366,7 @@ void ThreatManager::clearReferences() //============================================================ -void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) +void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { //function deals with adding threat and adding players and pets into ThreatList //mobs, NPCs, guards have ThreatList and HateOfflineList @@ -378,7 +387,7 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask scho assert(getOwner()->GetTypeId()== TYPEID_UNIT); - float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, schoolMask, pThreatSpell); + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, crit, schoolMask, pThreatSpell); HostileReference* ref = iThreatContainer.addThreat(pVictim, threat); // Ref is not in the online refs, search the offline refs next diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h index 55460304c..7c8cf23fb 100644 --- a/src/game/ThreatManager.h +++ b/src/game/ThreatManager.h @@ -39,7 +39,7 @@ struct SpellEntry; class ThreatCalcHelper { public: - static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell); }; //============================================================== @@ -176,7 +176,8 @@ class MANGOS_DLL_SPEC ThreatManager void clearReferences(); - void addThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + void addThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell); + void addThreat(Unit* pVictim, float threat) { addThreat(pVictim,threat,false,SPELL_SCHOOL_MASK_NONE,NULL); } void modifyThreatPercent(Unit *pVictim, int32 pPercent); float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b28159b2b..c6bf862e6 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -761,9 +761,9 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if (pVictim->GetTypeId() != TYPEID_PLAYER) { if(spellProto && IsDamageToThreatSpell(spellProto)) - pVictim->AddThreat(this, damage*2, damageSchoolMask, spellProto); + pVictim->AddThreat(this, damage*2, (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto); else - pVictim->AddThreat(this, damage, damageSchoolMask, spellProto); + pVictim->AddThreat(this, damage, (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto); } else // victim is a player { @@ -1125,7 +1125,7 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) { - if (damageInfo==0) + if (!damageInfo) return; Unit *pVictim = damageInfo->target; @@ -1152,8 +1152,8 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) return; } - // Call default DealDamage - CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL); + // Call default DealDamage (send critical in hit info for threat calculation) + CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT ? MELEE_HIT_CRIT : MELEE_HIT_NORMAL); DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss); } @@ -10196,7 +10196,10 @@ bool Unit::CanHaveThreatList() const float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask) { - if(!HasAuraType(SPELL_AURA_MOD_THREAT)) + if (!HasAuraType(SPELL_AURA_MOD_THREAT)) + return threat; + + if (schoolMask == SPELL_SCHOOL_MASK_NONE) return threat; SpellSchools school = GetFirstSchoolInMask(schoolMask); @@ -10206,11 +10209,11 @@ float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask) //====================================================================== -void Unit::AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask, SpellEntry const *threatSpell) +void Unit::AddThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell /*= NULL*/) { // Only mobs can manage threat lists if(CanHaveThreatList()) - m_ThreatManager.addThreat(pVictim, threat, schoolMask, threatSpell); + m_ThreatManager.addThreat(pVictim, threat, crit, schoolMask, threatSpell); } //====================================================================== diff --git a/src/game/Unit.h b/src/game/Unit.h index b1787d6f7..490875d1a 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1336,7 +1336,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject // Threat related methods bool CanHaveThreatList() const; - void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + void AddThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell = NULL); + void AddThreat(Unit* pVictim) { AddThreat(pVictim, 0.0f, false, SPELL_SCHOOL_MASK_NORMAL, NULL); } float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); void DeleteThreatList(); bool SelectHostileTarget(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0a10f6567..8b4a55c34 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8657" + #define REVISION_NR "8658" #endif // __REVISION_NR_H__