mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Spells: fix possible crash when loading spell_proc table
This commit is contained in:
@@ -1836,14 +1836,14 @@ void SpellMgr::LoadSpellProcs()
|
||||
int32 spellId = fields[0].GetInt32();
|
||||
|
||||
bool allRanks = false;
|
||||
if (spellId <=0)
|
||||
if (spellId < 0)
|
||||
{
|
||||
allRanks = true;
|
||||
spellId = -spellId;
|
||||
}
|
||||
|
||||
SpellInfo const* spellEntry = GetSpellInfo(spellId);
|
||||
if (!spellEntry)
|
||||
SpellInfo const* spellInfo = GetSpellInfo(spellId);
|
||||
if (!spellInfo)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_proc` does not exist", spellId);
|
||||
continue;
|
||||
@@ -1851,9 +1851,9 @@ void SpellMgr::LoadSpellProcs()
|
||||
|
||||
if (allRanks)
|
||||
{
|
||||
if (GetFirstSpellInChain(spellId) != uint32(spellId))
|
||||
if (spellInfo->GetFirstRankSpell()->Id != uint32(spellId))
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_proc` is not first rank of spell.", fields[0].GetInt32());
|
||||
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_proc` is not first rank of spell.", spellId);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1876,79 +1876,77 @@ void SpellMgr::LoadSpellProcs()
|
||||
baseProcEntry.cooldown = uint32(cooldown);
|
||||
baseProcEntry.charges = fields[14].GetUInt32();
|
||||
|
||||
while (true)
|
||||
while (spellInfo)
|
||||
{
|
||||
if (mSpellProcMap.find(spellId) != mSpellProcMap.end())
|
||||
if (mSpellProcMap.find(spellInfo->Id) != mSpellProcMap.end())
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_proc` has duplicate entry in the table", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_proc` has duplicate entry in the table", spellInfo->Id);
|
||||
break;
|
||||
}
|
||||
SpellProcEntry procEntry = SpellProcEntry(baseProcEntry);
|
||||
|
||||
// take defaults from dbcs
|
||||
if (!procEntry.typeMask)
|
||||
procEntry.typeMask = spellEntry->ProcFlags;
|
||||
procEntry.typeMask = spellInfo->ProcFlags;
|
||||
if (!procEntry.charges)
|
||||
procEntry.charges = spellEntry->ProcCharges;
|
||||
procEntry.charges = spellInfo->ProcCharges;
|
||||
if (!procEntry.chance && !procEntry.ratePerMinute)
|
||||
procEntry.chance = float(spellEntry->ProcChance);
|
||||
procEntry.chance = float(spellInfo->ProcChance);
|
||||
|
||||
// validate data
|
||||
if (procEntry.schoolMask & ~SPELL_SCHOOL_MASK_ALL)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `schoolMask` set: %u", spellId, procEntry.schoolMask);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `schoolMask` set: %u", spellInfo->Id, procEntry.schoolMask);
|
||||
if (procEntry.spellFamilyName && (procEntry.spellFamilyName < 3 || procEntry.spellFamilyName > 17 || procEntry.spellFamilyName == 14 || procEntry.spellFamilyName == 16))
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `spellFamilyName` set: %u", spellId, procEntry.spellFamilyName);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `spellFamilyName` set: %u", spellInfo->Id, procEntry.spellFamilyName);
|
||||
if (procEntry.chance < 0)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has negative value in `chance` field", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has negative value in `chance` field", spellInfo->Id);
|
||||
procEntry.chance = 0;
|
||||
}
|
||||
if (procEntry.ratePerMinute < 0)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has negative value in `ratePerMinute` field", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has negative value in `ratePerMinute` field", spellInfo->Id);
|
||||
procEntry.ratePerMinute = 0;
|
||||
}
|
||||
if (cooldown < 0)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has negative value in `cooldown` field", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has negative value in `cooldown` field", spellInfo->Id);
|
||||
procEntry.cooldown = 0;
|
||||
}
|
||||
if (procEntry.chance == 0 && procEntry.ratePerMinute == 0)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u doesn't have `chance` and `ratePerMinute` values defined, proc will not be triggered", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u doesn't have `chance` and `ratePerMinute` values defined, proc will not be triggered", spellInfo->Id);
|
||||
if (procEntry.charges > 99)
|
||||
{
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has too big value in `charges` field", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has too big value in `charges` field", spellInfo->Id);
|
||||
procEntry.charges = 99;
|
||||
}
|
||||
if (!procEntry.typeMask)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u doesn't have `typeMask` value defined, proc will not be triggered", spellId);
|
||||
if (procEntry.spellTypeMask & ~PROC_SPELL_PHASE_MASK_ALL)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `spellTypeMask` set: %u", spellId, procEntry.spellTypeMask);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u doesn't have `typeMask` value defined, proc will not be triggered", spellInfo->Id);
|
||||
if (procEntry.spellTypeMask & ~PROC_SPELL_TYPE_MASK_ALL)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `spellTypeMask` set: %u", spellInfo->Id, procEntry.spellTypeMask);
|
||||
if (procEntry.spellTypeMask && !(procEntry.typeMask & (SPELL_PROC_FLAG_MASK | PERIODIC_PROC_FLAG_MASK)))
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has `spellTypeMask` value defined, but it won't be used for defined `typeMask` value", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has `spellTypeMask` value defined, but it won't be used for defined `typeMask` value", spellInfo->Id);
|
||||
if (!procEntry.spellPhaseMask && procEntry.typeMask & REQ_SPELL_PHASE_PROC_FLAG_MASK)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u doesn't have `spellPhaseMask` value defined, but it's required for defined `typeMask` value, proc will not be triggered", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u doesn't have `spellPhaseMask` value defined, but it's required for defined `typeMask` value, proc will not be triggered", spellInfo->Id);
|
||||
if (procEntry.spellPhaseMask & ~PROC_SPELL_PHASE_MASK_ALL)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `spellPhaseMask` set: %u", spellId, procEntry.spellPhaseMask);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `spellPhaseMask` set: %u", spellInfo->Id, procEntry.spellPhaseMask);
|
||||
if (procEntry.spellPhaseMask && !(procEntry.typeMask & REQ_SPELL_PHASE_PROC_FLAG_MASK))
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has `spellPhaseMask` value defined, but it won't be used for defined `typeMask` value", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has `spellPhaseMask` value defined, but it won't be used for defined `typeMask` value", spellInfo->Id);
|
||||
if (procEntry.hitMask & ~PROC_HIT_MASK_ALL)
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `hitMask` set: %u", spellId, procEntry.hitMask);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has wrong `hitMask` set: %u", spellInfo->Id, procEntry.hitMask);
|
||||
if (procEntry.hitMask && !(procEntry.typeMask & TAKEN_HIT_PROC_FLAG_MASK || (procEntry.typeMask & DONE_HIT_PROC_FLAG_MASK && (!procEntry.spellPhaseMask || procEntry.spellPhaseMask & (PROC_SPELL_PHASE_HIT | PROC_SPELL_PHASE_FINISH)))))
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has `hitMask` value defined, but it won't be used for defined `typeMask` and `spellPhaseMask` values", spellId);
|
||||
sLog->outError(LOG_FILTER_SQL, "`spell_proc` table entry for spellId %u has `hitMask` value defined, but it won't be used for defined `typeMask` and `spellPhaseMask` values", spellInfo->Id);
|
||||
|
||||
mSpellProcMap[spellId] = procEntry;
|
||||
mSpellProcMap[spellInfo->Id] = procEntry;
|
||||
|
||||
if (allRanks)
|
||||
{
|
||||
spellId = GetNextSpellInChain(spellId);
|
||||
spellEntry = GetSpellInfo(spellId);
|
||||
}
|
||||
spellInfo = spellInfo->GetNextRankSpell();
|
||||
else
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
}
|
||||
while (result->NextRow());
|
||||
|
||||
sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u spell proc conditions and data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user