mirror of
https://github.com/mangosfour/server.git
synced 2025-12-16 22:37:02 +00:00
[11022] Create template for loading spell ranks from DB to allow better code re-use.
This commit is contained in:
parent
1b1a7ebd24
commit
77d8b41cc4
2 changed files with 145 additions and 115 deletions
|
|
@ -306,7 +306,7 @@ bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 spellId_2)
|
||||||
&& spellInfo_1->EffectApplyAuraName[i] == spellInfo_2->EffectApplyAuraName[j]
|
&& spellInfo_1->EffectApplyAuraName[i] == spellInfo_2->EffectApplyAuraName[j]
|
||||||
&& spellInfo_1->EffectMiscValue[i] == spellInfo_2->EffectMiscValue[j]
|
&& spellInfo_1->EffectMiscValue[i] == spellInfo_2->EffectMiscValue[j]
|
||||||
&& spellInfo_1->EffectItemType[i] == spellInfo_2->EffectItemType[j]
|
&& spellInfo_1->EffectItemType[i] == spellInfo_2->EffectItemType[j]
|
||||||
&& (spellInfo_1->Effect[i] != 0 || spellInfo_1->EffectApplyAuraName[i] != 0 ||
|
&& (spellInfo_1->Effect[i] != 0 || spellInfo_1->EffectApplyAuraName[i] != 0 ||
|
||||||
spellInfo_1->EffectMiscValue[i] != 0 || spellInfo_1->EffectItemType[i] != 0))
|
spellInfo_1->EffectMiscValue[i] != 0 || spellInfo_1->EffectItemType[i] != 0))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1046,11 +1046,69 @@ void SpellMgr::LoadSpellTargetPositions()
|
||||||
sLog.outString( ">> Loaded %u spell teleport coordinates", count );
|
sLog.outString( ">> Loaded %u spell teleport coordinates", count );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename EntryType, typename WorkerType, typename StorageType>
|
||||||
|
struct SpellRankHelper
|
||||||
|
{
|
||||||
|
SpellRankHelper(SpellMgr &_mgr, StorageType &_storage): mgr(_mgr), worker(_storage), customRank(0) {}
|
||||||
|
void RecordRank(EntryType &entry, uint32 spell_id)
|
||||||
|
{
|
||||||
|
const SpellEntry *spell = sSpellStore.LookupEntry(spell_id);
|
||||||
|
if (!spell)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("Spell %u listed in `%s` does not exist", spell_id, worker.TableName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 first_id = mgr.GetFirstSpellInChain(spell_id);
|
||||||
|
|
||||||
|
// most spell ranks expected same data
|
||||||
|
if(first_id)
|
||||||
|
{
|
||||||
|
firstRankSpells.insert(first_id);
|
||||||
|
|
||||||
|
if (first_id != spell_id)
|
||||||
|
{
|
||||||
|
if (!worker.IsValidCustomRank(entry, spell_id, first_id))
|
||||||
|
return;
|
||||||
|
// for later check that first rank also added
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstRankSpellsWithCustomRanks.insert(first_id);
|
||||||
|
++customRank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.AddEntry(entry, spell);
|
||||||
|
}
|
||||||
|
void FillHigherRanks()
|
||||||
|
{
|
||||||
|
// check that first rank added for custom ranks
|
||||||
|
for (std::set<uint32>::const_iterator itr = firstRankSpellsWithCustomRanks.begin(); itr != firstRankSpellsWithCustomRanks.end(); ++itr)
|
||||||
|
if (!worker.HasEntry(*itr))
|
||||||
|
sLog.outErrorDb("Spell %u must be listed in `%s` as first rank for listed custom ranks of spell but not found!", *itr, worker.TableName());
|
||||||
|
|
||||||
|
// fill absent non first ranks data base at first rank data
|
||||||
|
for (std::set<uint32>::const_iterator itr = firstRankSpells.begin(); itr != firstRankSpells.end(); ++itr)
|
||||||
|
{
|
||||||
|
if (worker.SetStateToEntry(*itr))
|
||||||
|
mgr.doForHighRanks(*itr, worker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::set<uint32> firstRankSpells;
|
||||||
|
std::set<uint32> firstRankSpellsWithCustomRanks;
|
||||||
|
|
||||||
|
SpellMgr &mgr;
|
||||||
|
WorkerType worker;
|
||||||
|
uint32 customRank;
|
||||||
|
};
|
||||||
|
|
||||||
struct DoSpellProcEvent
|
struct DoSpellProcEvent
|
||||||
{
|
{
|
||||||
DoSpellProcEvent(SpellProcEventMap& _spe_map, SpellProcEventEntry const& _spe) : spe_map(_spe_map), spe(_spe) {}
|
DoSpellProcEvent(SpellProcEventMap& _spe_map) : spe_map(_spe_map), customProc(0), count(0) {}
|
||||||
void operator() (uint32 spell_id)
|
void operator() (uint32 spell_id)
|
||||||
{
|
{
|
||||||
|
SpellProcEventEntry const& spe = state->second;
|
||||||
// add ranks only for not filled data (some ranks have ppm data different for ranks for example)
|
// add ranks only for not filled data (some ranks have ppm data different for ranks for example)
|
||||||
SpellProcEventMap::const_iterator spellItr = spe_map.find(spell_id);
|
SpellProcEventMap::const_iterator spellItr = spe_map.find(spell_id);
|
||||||
if (spellItr == spe_map.end())
|
if (spellItr == spe_map.end())
|
||||||
|
|
@ -1096,16 +1154,90 @@ struct DoSpellProcEvent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* TableName() { return "spell_proc_event"; }
|
||||||
|
bool IsValidCustomRank(SpellProcEventEntry const &spe, uint32 entry, uint32 first_id)
|
||||||
|
{
|
||||||
|
// let have independent data in table for spells with ppm rates (exist rank dependent ppm rate spells)
|
||||||
|
if (!spe.ppmRate)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("Spell %u listed in `spell_proc_event` is not first rank (%u) in chain", entry, first_id);
|
||||||
|
// prevent loading since it won't have an effect anyway
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool AddEntry(SpellProcEventEntry const &spe, SpellEntry const *spell)
|
||||||
|
{
|
||||||
|
spe_map[spell->Id] = spe;
|
||||||
|
|
||||||
|
bool isCustom = false;
|
||||||
|
|
||||||
|
if (spe.procFlags == 0)
|
||||||
|
{
|
||||||
|
if (spell->procFlags==0)
|
||||||
|
sLog.outErrorDb("Spell %u listed in `spell_proc_event` probally not triggered spell (no proc flags)", spell->Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (spell->procFlags==spe.procFlags)
|
||||||
|
sLog.outErrorDb("Spell %u listed in `spell_proc_event` has exactly same proc flags as in spell.dbc, field value redundant", spell->Id);
|
||||||
|
else
|
||||||
|
isCustom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spe.customChance == 0)
|
||||||
|
{
|
||||||
|
/* enable for re-check cases, 0 chance ok for some cases because in some cases it set by another spell/talent spellmod)
|
||||||
|
if (spell->procChance==0 && !spe.ppmRate)
|
||||||
|
sLog.outErrorDb("Spell %u listed in `spell_proc_event` probally not triggered spell (no chance or ppm)", spell->Id);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (spell->procChance==spe.customChance)
|
||||||
|
sLog.outErrorDb("Spell %u listed in `spell_proc_event` has exactly same custom chance as in spell.dbc, field value redundant", spell->Id);
|
||||||
|
else
|
||||||
|
isCustom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// totally redundant record
|
||||||
|
if (!spe.schoolMask && !spe.procFlags &&
|
||||||
|
!spe.procEx && !spe.ppmRate && !spe.customChance && !spe.cooldown)
|
||||||
|
{
|
||||||
|
bool empty = !spe.spellFamilyName ? true : false;
|
||||||
|
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||||
|
{
|
||||||
|
if (spe.spellFamilyMask[i] || spe.spellFamilyMask2[i])
|
||||||
|
{
|
||||||
|
empty = false;
|
||||||
|
uint32 const* ptr = spell->GetEffectSpellClassMask(SpellEffectIndex(i));
|
||||||
|
if ((((uint64*)ptr)[0] != 0 && spe.spellFamilyMask[i] == ((uint64*)ptr)[0]) && (ptr[2] == 0 || spe.spellFamilyMask2[i] == ptr[2]))
|
||||||
|
sLog.outErrorDb("Spell %u listed in `spell_proc_event` has same class mask as in Spell.dbc (EffectIndex %u) and doesn't have any other data", spell->Id, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (empty)
|
||||||
|
sLog.outErrorDb("Spell %u listed in `spell_proc_event` doesn't have any useful data", spell->Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustom)
|
||||||
|
++customProc;
|
||||||
|
else
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasEntry(uint32 spellId) { return spe_map.count(spellId) > 0; }
|
||||||
|
bool SetStateToEntry(uint32 spellId) { return (state = spe_map.find(spellId)) != spe_map.end(); }
|
||||||
SpellProcEventMap& spe_map;
|
SpellProcEventMap& spe_map;
|
||||||
SpellProcEventEntry const& spe;
|
SpellProcEventMap::const_iterator state;
|
||||||
|
|
||||||
|
uint32 customProc;
|
||||||
|
uint32 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
void SpellMgr::LoadSpellProcEvents()
|
void SpellMgr::LoadSpellProcEvents()
|
||||||
{
|
{
|
||||||
mSpellProcEventMap.clear(); // need for reload case
|
mSpellProcEventMap.clear(); // need for reload case
|
||||||
|
|
||||||
uint32 count = 0;
|
|
||||||
|
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
||||||
QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMaskA0, SpellFamilyMaskA1, SpellFamilyMaskA2, SpellFamilyMaskB0, SpellFamilyMaskB1, SpellFamilyMaskB2, SpellFamilyMaskC0, SpellFamilyMaskC1, SpellFamilyMaskC2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
|
QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMaskA0, SpellFamilyMaskA1, SpellFamilyMaskA2, SpellFamilyMaskB0, SpellFamilyMaskB1, SpellFamilyMaskB2, SpellFamilyMaskC0, SpellFamilyMaskC1, SpellFamilyMaskC2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
|
||||||
if( !result )
|
if( !result )
|
||||||
|
|
@ -1113,16 +1245,13 @@ void SpellMgr::LoadSpellProcEvents()
|
||||||
barGoLink bar( 1 );
|
barGoLink bar( 1 );
|
||||||
bar.step();
|
bar.step();
|
||||||
sLog.outString();
|
sLog.outString();
|
||||||
sLog.outString( ">> Loaded %u spell proc event conditions", count );
|
sLog.outString( ">> No spell proc event conditions loaded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<uint32> firstRankSpells;
|
SpellRankHelper<SpellProcEventEntry, DoSpellProcEvent, SpellProcEventMap> rankHelper(*this, mSpellProcEventMap);
|
||||||
std::set<uint32> firstRankSpellsWithCustomRanks;
|
|
||||||
|
|
||||||
barGoLink bar( (int)result->GetRowCount() );
|
barGoLink bar( (int)result->GetRowCount() );
|
||||||
uint32 customProc = 0;
|
|
||||||
uint32 customRank = 0;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Field *fields = result->Fetch();
|
Field *fields = result->Fetch();
|
||||||
|
|
@ -1131,13 +1260,6 @@ void SpellMgr::LoadSpellProcEvents()
|
||||||
|
|
||||||
uint32 entry = fields[0].GetUInt32();
|
uint32 entry = fields[0].GetUInt32();
|
||||||
|
|
||||||
const SpellEntry *spell = sSpellStore.LookupEntry(entry);
|
|
||||||
if (!spell)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` does not exist", entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpellProcEventEntry spe;
|
SpellProcEventEntry spe;
|
||||||
|
|
||||||
spe.schoolMask = fields[1].GetUInt32();
|
spe.schoolMask = fields[1].GetUInt32();
|
||||||
|
|
@ -1154,108 +1276,16 @@ void SpellMgr::LoadSpellProcEvents()
|
||||||
spe.customChance = fields[15].GetFloat();
|
spe.customChance = fields[15].GetFloat();
|
||||||
spe.cooldown = fields[16].GetUInt32();
|
spe.cooldown = fields[16].GetUInt32();
|
||||||
|
|
||||||
uint32 first_id = GetFirstSpellInChain(entry);
|
rankHelper.RecordRank(spe, entry);
|
||||||
|
|
||||||
// most spell ranks expected same data
|
} while (result->NextRow());
|
||||||
if(first_id)
|
|
||||||
{
|
|
||||||
firstRankSpells.insert(first_id);
|
|
||||||
|
|
||||||
if ( first_id != entry)
|
rankHelper.FillHigherRanks();
|
||||||
{
|
|
||||||
// let have independent data in table for spells with ppm rates (exist rank dependent ppm rate spells)
|
|
||||||
if (!spe.ppmRate)
|
|
||||||
{
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` 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 als added
|
|
||||||
else
|
|
||||||
{
|
|
||||||
firstRankSpellsWithCustomRanks.insert(first_id);
|
|
||||||
++customRank;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mSpellProcEventMap[entry] = spe;
|
|
||||||
|
|
||||||
bool isCustom = false;
|
|
||||||
|
|
||||||
if (spe.procFlags == 0)
|
|
||||||
{
|
|
||||||
if (spell->procFlags==0)
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` probally not triggered spell (no proc flags)", entry);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (spell->procFlags==spe.procFlags)
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` have exactly same proc flags as in spell.dbc, field value redundent", entry);
|
|
||||||
else
|
|
||||||
isCustom = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spe.customChance == 0)
|
|
||||||
{
|
|
||||||
/* enable for re-check cases, 0 chance ok for some cases because in some cases it set by another spell/talent spellmod)
|
|
||||||
if (spell->procChance==0 && !spe.ppmRate)
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` probally not triggered spell (no chance or ppm)", entry);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (spell->procChance==spe.customChance)
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` have exactly same custom chance as in spell.dbc, field value redundent", entry);
|
|
||||||
else
|
|
||||||
isCustom = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// totally redundant record
|
|
||||||
if (!spe.schoolMask && !spe.procFlags &&
|
|
||||||
!spe.procEx && !spe.ppmRate && !spe.customChance && !spe.cooldown)
|
|
||||||
{
|
|
||||||
bool empty = !spe.spellFamilyName ? true : false;
|
|
||||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
|
||||||
{
|
|
||||||
if (spe.spellFamilyMask[i] || spe.spellFamilyMask2[i])
|
|
||||||
{
|
|
||||||
empty = false;
|
|
||||||
uint32 const* ptr = spell->GetEffectSpellClassMask(SpellEffectIndex(i));
|
|
||||||
if ((((uint64*)ptr)[0] != 0 && spe.spellFamilyMask[i] == ((uint64*)ptr)[0]) && (ptr[2] == 0 || spe.spellFamilyMask2[i] == ptr[2]))
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` have same class mask as in Spell.dbc (EffectIndex %u) and doesn't have any other data", entry, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (empty)
|
|
||||||
sLog.outErrorDb("Spell %u listed in `spell_proc_event` not have any useful data", entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCustom)
|
|
||||||
++customProc;
|
|
||||||
else
|
|
||||||
++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 (mSpellProcEventMap.find(*itr) == mSpellProcEventMap.end())
|
|
||||||
sLog.outErrorDb("Spell %u must be listed in `spell_proc_event` 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)
|
|
||||||
{
|
|
||||||
SpellProcEventMap::const_iterator speItr = mSpellProcEventMap.find(*itr);
|
|
||||||
if (speItr != mSpellProcEventMap.end())
|
|
||||||
{
|
|
||||||
DoSpellProcEvent worker(mSpellProcEventMap, speItr->second);
|
|
||||||
doForHighRanks(speItr->first,worker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete result;
|
delete result;
|
||||||
|
|
||||||
sLog.outString();
|
sLog.outString();
|
||||||
sLog.outString( ">> Loaded %u extra spell proc event conditions +%u custom proc (inc. +%u custom ranks)", count, customProc, customRank );
|
sLog.outString( ">> Loaded %u extra spell proc event conditions +%u custom proc (inc. +%u custom ranks)", rankHelper.worker.count, rankHelper.worker.customProc, rankHelper.customRank);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DoSpellProcItemEnchant
|
struct DoSpellProcItemEnchant
|
||||||
|
|
@ -2495,7 +2525,7 @@ void SpellMgr::LoadSpellChains()
|
||||||
mSpellChains[forward_id] = node;
|
mSpellChains[forward_id] = node;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// need temporary store for later rank calculation
|
// need temporary store for later rank calculation
|
||||||
prevRanks[forward_id] = spell_id;
|
prevRanks[forward_id] = spell_id;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "11021"
|
#define REVISION_NR "11022"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue