Skip to content

Instantly share code, notes, and snippets.

@x3n
Created January 3, 2011 18:45
Show Gist options
  • Save x3n/763765 to your computer and use it in GitHub Desktop.
Save x3n/763765 to your computer and use it in GitHub Desktop.
threat_multiplier.patch
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 38674a2..397e37f 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -4218,14 +4218,14 @@ void Spell::HandleThreatSpells(uint32 spellId)
if(!m_targets.getUnitTarget()->CanHaveThreatList())
return;
- uint16 threat = sSpellMgr.GetSpellThreat(spellId);
+ SpellThreatEntry const* threatEntry = sSpellMgr.GetSpellThreatEntry(spellId);
- if(!threat)
+ if(!threatEntry || !threatEntry->threat)
return;
- m_targets.getUnitTarget()->AddThreat(m_caster, float(threat), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
+ m_targets.getUnitTarget()->AddThreat(m_caster, float(threatEntry->threat), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
- DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell %u, rank %u, added an additional %i threat", spellId, sSpellMgr.GetSpellRank(spellId), threat);
+ DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell %u, rank %u, added an additional %i threat", spellId, sSpellMgr.GetSpellRank(spellId), threatEntry->threat);
}
void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,SpellEffectIndex i, float DamageMultiplier)
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index c2d6351..ff4f10b 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -1606,14 +1606,39 @@ void SpellMgr::LoadSpellElixirs()
sLog.outString( ">> Loaded %u spell elixir definitions", count );
}
+struct DoSpellThreat
+{
+ DoSpellThreat(SpellThreatMap& _threatMap, SpellThreatEntry const& _ste) : threatMap(_threatMap), ste(_ste) {}
+ void operator() (uint32 spell_id)
+ {
+ // add ranks only for not filled data (spells adding flat threat are usually different for ranks for example)
+ SpellThreatMap::const_iterator spellItr = threatMap.find(spell_id);
+ if (spellItr == threatMap.end())
+ threatMap[spell_id] = ste;
+
+ // just assert that entry is not redundant
+ else
+ {
+ SpellThreatEntry const& r_ste = spellItr->second;
+ if (ste.threat == r_ste.threat && ste.multiplier == r_ste.multiplier && ste.ap_multiplier == r_ste.ap_multiplier)
+ sLog.outErrorDb("Spell %u listed in `spell_threat` as custom rank has same data as Rank 1, so redundant", spell_id);
+ }
+ }
+
+ SpellThreatMap& threatMap;
+ SpellThreatEntry const& ste;
+};
+
+
void SpellMgr::LoadSpellThreats()
{
mSpellThreatMap.clear(); // need for reload case
uint32 count = 0;
+ uint32 customRank = 0;
- // 0 1
- QueryResult *result = WorldDatabase.Query("SELECT entry, Threat FROM spell_threat");
+ // 0 1 2 3
+ QueryResult *result = WorldDatabase.Query("SELECT entry, Threat, Multiplier, AP_Multiplier FROM spell_threat");
if( !result )
{
@@ -1626,6 +1651,9 @@ void SpellMgr::LoadSpellThreats()
return;
}
+ std::set<uint32> firstRankSpells;
+ std::set<uint32> firstRankSpellsWithCustomRanks;
+
barGoLink bar( (int)result->GetRowCount() );
do
@@ -1635,7 +1663,6 @@ void SpellMgr::LoadSpellThreats()
bar.step();
uint32 entry = fields[0].GetUInt32();
- uint16 Threat = fields[1].GetUInt16();
if (!sSpellStore.LookupEntry(entry))
{
@@ -1643,11 +1670,58 @@ void SpellMgr::LoadSpellThreats()
continue;
}
- mSpellThreatMap[entry] = Threat;
+ SpellThreatEntry ste;
+ ste.threat = fields[1].GetUInt16();
+ ste.multiplier = fields[2].GetFloat();
+ ste.ap_multiplier = fields[3].GetFloat();
+
+ mSpellThreatMap[entry] = ste;
+
+
+ uint32 first_id = GetFirstSpellInChain(entry);
+
+ // by default, spell ranks are expected to have same data
+ if(first_id)
+ {
+ firstRankSpells.insert(first_id);
+
+ if(first_id != entry)
+ {
+ // let have independent data in table for spells with flat threat bonus
+ if(!ste.threat)
+ {
+ sLog.outErrorDb("Spell %u listed in `spell_threat` is not first rank (%u) in chain", entry, first_id);
+ // prevent loading since it won't have an effect anyway
+ continue;
+ }
+ // for later check that first rank also added
+ else
+ {
+ firstRankSpellsWithCustomRanks.insert(first_id);
+ ++customRank;
+ }
+ }
+ }
++count;
} while( result->NextRow() );
+ // check that first rank added for custom ranks
+ for (std::set<uint32>::const_iterator itr = firstRankSpellsWithCustomRanks.begin(); itr != firstRankSpellsWithCustomRanks.end(); ++itr)
+ if (mSpellThreatMap.find(*itr) == mSpellThreatMap.end())
+ sLog.outErrorDb("Spell %u must be listed in `spell_threat` as first rank for listed custom ranks of spell but not found!", *itr);
+
+ // fill absent non first ranks data base at first rank data
+ for(std::set<uint32>::const_iterator itr = firstRankSpells.begin(); itr != firstRankSpells.end(); ++itr)
+ {
+ SpellThreatMap::const_iterator speItr = mSpellThreatMap.find(*itr);
+ if (speItr != mSpellThreatMap.end())
+ {
+ DoSpellThreat worker(mSpellThreatMap, speItr->second);
+ doForHighRanks(speItr->first, worker);
+ }
+ }
+
delete result;
sLog.outString();
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index 40e45a5..d22bec9 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -612,9 +612,16 @@ typedef UNORDERED_MAP<uint32, SpellBonusEntry> SpellBonusMap;
#define ELIXIR_SHATTRATH_MASK 0x08
#define ELIXIR_WELL_FED 0x10 // Some foods have SPELLFAMILY_POTION
+struct SpellThreatEntry
+{
+ uint16 threat;
+ float multiplier;
+ float ap_multiplier;
+};
+
typedef std::map<uint32, uint8> SpellElixirMap;
typedef std::map<uint32, float> SpellProcItemEnchantMap;
-typedef std::map<uint32, uint16> SpellThreatMap;
+typedef std::map<uint32, SpellThreatEntry> SpellThreatMap;
// Spell script target related declarations (accessed using SpellMgr functions)
enum SpellTargetType
@@ -836,13 +843,13 @@ class SpellMgr
return SPELL_NORMAL;
}
- uint16 GetSpellThreat(uint32 spellid) const
+ SpellThreatEntry const* GetSpellThreatEntry(uint32 spellid) const
{
SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellid);
- if(itr==mSpellThreatMap.end())
- return 0;
+ if (itr != mSpellThreatMap.end())
+ return &itr->second;
- return itr->second;
+ return NULL;
}
// Spell proc events
diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp
index d814552..e17dbba 100644
--- a/src/game/ThreatManager.cpp
+++ b/src/game/ThreatManager.cpp
@@ -24,6 +24,7 @@
#include "Player.h"
#include "ObjectAccessor.h"
#include "UnitEvents.h"
+#include "SpellMgr.h"
//==============================================================
//================= ThreatCalcHelper ===========================
@@ -38,11 +39,21 @@ float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* /*pHatingUnit*/, floa
if (pThreatSpell)
{
+ SpellThreatEntry const* threatEntry = sSpellMgr.GetSpellThreatEntry(pThreatSpell->Id);
+
if (Player* modOwner = pHatedUnit->GetSpellModOwner())
+ {
modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, pThreat);
- if(crit)
+ if(threatEntry && threatEntry->ap_multiplier)
+ pThreat += modOwner->CalculateDamage(BASE_ATTACK, false) * threatEntry->ap_multiplier;
+ }
+
+ if (crit)
pThreat *= pHatedUnit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRITICAL_THREAT,schoolMask);
+
+ if (threatEntry)
+ pThreat *= threatEntry->multiplier;
}
float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, schoolMask);
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 8051720..dde1861 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -950,10 +950,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
}
if (pVictim->GetTypeId() != TYPEID_PLAYER)
{
- if(spellProto && IsDamageToThreatSpell(spellProto))
- pVictim->AddThreat(this, float(damage*2), (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto);
- else
- pVictim->AddThreat(this, float(damage), (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto);
+ pVictim->AddThreat(this, float(damage), (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto);
}
else // victim is a player
{
@@ -7176,22 +7173,6 @@ bool Unit::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex i
return false;
}
-bool Unit::IsDamageToThreatSpell(SpellEntry const * spellInfo) const
-{
- if (!spellInfo)
- return false;
-
- uint32 family = spellInfo->SpellFamilyName;
- uint64 flags = spellInfo->SpellFamilyFlags;
-
- if ((family == 5 && flags == 256) || //Searing Pain
- (family == 6 && flags == 8192) || //Mind Blast
- (family == 11 && flags == 1048576)) //Earth Shock
- return true;
-
- return false;
-}
-
/**
* Calculates caster part of melee damage bonuses,
* also includes different bonuses dependent from target auras
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 35e1726..f3901fe 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1464,8 +1464,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL);
void CastSpell(float x, float y, float z, SpellEntry const *spellInfo, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid(), SpellEntry const* triggeredBy = NULL);
- bool IsDamageToThreatSpell(SpellEntry const * spellInfo) const;
-
void DeMorph();
void SendAttackStateUpdate(CalcDamageInfo *damageInfo);
ALTER TABLE spell_threat ADD COLUMN Multiplier FLOAT NOT NULL DEFAULT 1.0 AFTER Threat;
ALTER TABLE spell_threat ADD COLUMN AP_Multiplier FLOAT NOT NULL DEFAULT 0.0 AFTER Multiplier;
@x3n
Copy link
Author

x3n commented Jan 4, 2011

added queries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment