[11023] Implement support for threat multiplier and AP based threat bonus for spells.

* Higher ranks are now automatically filled when not listed in spell_threat
* Added some loading checks to detect inconsistent data

Signed-off-by: Lynx3d <lynx3d@some-imaginary-isp.org>
This commit is contained in:
x3n 2011-01-17 11:54:13 +01:00 committed by Lynx3d
parent 77d8b41cc4
commit d35be7f4c1
12 changed files with 238 additions and 177 deletions

View file

@ -1636,26 +1636,77 @@ void SpellMgr::LoadSpellElixirs()
sLog.outString( ">> Loaded %u spell elixir definitions", count );
}
struct DoSpellThreat
{
DoSpellThreat(SpellThreatMap& _threatMap) : threatMap(_threatMap), count(0) {}
void operator() (uint32 spell_id)
{
SpellThreatEntry const &ste = state->second;
// add ranks only for not filled data (spells adding flat threat are usually different for ranks)
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_bonus == r_ste.ap_bonus)
sLog.outErrorDb("Spell %u listed in `spell_threat` as custom rank has same data as Rank 1, so redundant", spell_id);
}
}
const char* TableName() { return "spell_threat"; }
bool IsValidCustomRank(SpellThreatEntry const &ste, uint32 entry, uint32 first_id)
{
if (!ste.threat)
{
sLog.outErrorDb("Spell %u listed in `spell_threat` is not first rank (%u) in chain and has no threat", entry, first_id);
// prevent loading unexpected data
return false;
}
return true;
}
void AddEntry(SpellThreatEntry const &ste, SpellEntry const *spell)
{
threatMap[spell->Id] = ste;
// flat threat bonus and attack power bonus currently only work properly when all
// effects have same targets, otherwise, we'd need to seperate it by effect index
if (ste.threat || ste.ap_bonus != 0.f)
{
const uint32 *targetA = spell->EffectImplicitTargetA;
const uint32 *targetB = spell->EffectImplicitTargetB;
if ((targetA[EFFECT_INDEX_1] && targetA[EFFECT_INDEX_1] != targetA[EFFECT_INDEX_0]) ||
(targetA[EFFECT_INDEX_2] && targetA[EFFECT_INDEX_2] != targetA[EFFECT_INDEX_0]))
sLog.outErrorDb("Spell %u listed in `spell_threat` has effects with different targets, threat may be assigned incorrectly", spell->Id);
}
++count;
}
bool HasEntry(uint32 spellId) { return threatMap.count(spellId) > 0; }
bool SetStateToEntry(uint32 spellId) { return (state = threatMap.find(spellId)) != threatMap.end(); }
SpellThreatMap& threatMap;
SpellThreatMap::const_iterator state;
uint32 count;
};
void SpellMgr::LoadSpellThreats()
{
mSpellThreatMap.clear(); // need for reload case
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, Threat, multiplier, ap_bonus FROM spell_threat");
if( !result )
{
barGoLink bar( 1 );
bar.step();
sLog.outString();
sLog.outString( ">> Loaded %u aggro generating spells", count );
sLog.outString( ">> No spell threat entries loaded.");
return;
}
SpellRankHelper<SpellThreatEntry, DoSpellThreat, SpellThreatMap> rankHelper(*this, mSpellThreatMap);
barGoLink bar( (int)result->GetRowCount() );
do
@ -1665,23 +1716,22 @@ void SpellMgr::LoadSpellThreats()
bar.step();
uint32 entry = fields[0].GetUInt32();
uint16 Threat = fields[1].GetUInt16();
if (!sSpellStore.LookupEntry(entry))
{
sLog.outErrorDb("Spell %u listed in `spell_threat` does not exist", entry);
continue;
}
SpellThreatEntry ste;
ste.threat = fields[1].GetUInt16();
ste.multiplier = fields[2].GetFloat();
ste.ap_bonus = fields[3].GetFloat();
mSpellThreatMap[entry] = Threat;
rankHelper.RecordRank(ste, entry);
++count;
} while( result->NextRow() );
rankHelper.FillHigherRanks();
delete result;
sLog.outString();
sLog.outString( ">> Loaded %u aggro generating spells", count );
sLog.outString( ">> Loaded %u spell threat entries", rankHelper.worker.count );
}
bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const