mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
[8169] Implement new optional table spell_check and console command .debug spellcheck
* Table expected to be store data mirror same data in code: - explicit spell ids with related expected spell properties like effects, spell family or auras - implicit requirements for select some spell sets like spell family masks, icons or visual values * For check can be used .debug spellcheck _console_ only command. * Main purpose table and related command check code parts for outdated data at client switch. It also can be used for check data in patch writing time to be sure code correctness.
This commit is contained in:
parent
3b47b66ba9
commit
f99f477fe8
8 changed files with 327 additions and 17 deletions
|
|
@ -551,17 +551,6 @@ bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellI
|
|||
return false;
|
||||
}
|
||||
|
||||
bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId)
|
||||
{
|
||||
SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId);
|
||||
if (!spellproto) return false;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
if (spellproto->EffectApplyAuraName[i] == auraType)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
SpellCastResult GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
|
||||
{
|
||||
// talents that learn spells can have stance requirements that need ignore
|
||||
|
|
@ -2726,6 +2715,260 @@ void SpellMgr::LoadSkillLineAbilityMap()
|
|||
sLog.outString(">> Loaded %u SkillLineAbility MultiMap Data", count);
|
||||
}
|
||||
|
||||
void SpellMgr::CheckUsedSpells(char const* table)
|
||||
{
|
||||
uint32 countSpells = 0;
|
||||
uint32 countMasks = 0;
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
QueryResult *result = WorldDatabase.PQuery("SELECT spellid,SpellFamilyName,SpellFamilyMaskA,SpellFamilyMaskB,SpellIcon,SpellVisual,SpellCategory,EffectType,EffectAura,EffectIdx,Name,Code FROM %s",table);
|
||||
|
||||
if( !result )
|
||||
{
|
||||
barGoLink bar( 1 );
|
||||
|
||||
bar.step();
|
||||
|
||||
sLog.outString();
|
||||
sLog.outErrorDb("`%s` table is empty!",table);
|
||||
return;
|
||||
}
|
||||
|
||||
barGoLink bar( result->GetRowCount() );
|
||||
|
||||
do
|
||||
{
|
||||
Field *fields = result->Fetch();
|
||||
|
||||
bar.step();
|
||||
|
||||
uint32 spell = fields[0].GetUInt32();
|
||||
int32 family = fields[1].GetInt32();
|
||||
uint64 familyMaskA = fields[2].GetUInt64();
|
||||
uint32 familyMaskB = fields[3].GetUInt32();
|
||||
int32 spellIcon = fields[4].GetInt32();
|
||||
int32 spellVisual = fields[5].GetInt32();
|
||||
int32 category = fields[6].GetInt32();
|
||||
int32 effectType = fields[7].GetInt32();
|
||||
int32 auraType = fields[8].GetInt32();
|
||||
int32 effectIdx = fields[9].GetInt32();
|
||||
std::string name = fields[10].GetCppString();
|
||||
std::string code = fields[11].GetCppString();
|
||||
|
||||
// checks of correctness requirements itself
|
||||
|
||||
if (family < -1 || family > SPELLFAMILY_PET)
|
||||
{
|
||||
sLog.outError("Table '%s' for spell %u have wrong SpellFamily value(%u), skipped.",table,spell,family);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: spellIcon check need dbc loading
|
||||
if (spellIcon < -1)
|
||||
{
|
||||
sLog.outError("Table '%s' for spell %u have wrong SpellIcon value(%u), skipped.",table,spell,spellIcon);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: spellVisual check need dbc loading
|
||||
if (spellVisual < -1)
|
||||
{
|
||||
sLog.outError("Table '%s' for spell %u have wrong SpellVisual value(%u), skipped.",table,spell,spellVisual);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: for spellCategory better check need dbc loading
|
||||
if (category < -1 || category >=0 && sSpellCategoryStore.find(category) == sSpellCategoryStore.end())
|
||||
{
|
||||
sLog.outError("Table '%s' for spell %u have wrong SpellCategory value(%u), skipped.",table,spell,category);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (effectType < -1 || effectType >= TOTAL_SPELL_EFFECTS)
|
||||
{
|
||||
sLog.outError("Table '%s' for spell %u have wrong SpellEffect type value(%u), skipped.",table,spell,effectType);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auraType < -1 || auraType >= TOTAL_AURAS)
|
||||
{
|
||||
sLog.outError("Table '%s' for spell %u have wrong SpellAura type value(%u), skipped.",table,spell,auraType);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (effectIdx < -1 || effectIdx >= 3)
|
||||
{
|
||||
sLog.outError("Table '%s' for spell %u have wrong EffectIdx value(%u), skipped.",table,spell,effectIdx);
|
||||
continue;
|
||||
}
|
||||
|
||||
// now checks of requirements
|
||||
|
||||
if(spell)
|
||||
{
|
||||
++countSpells;
|
||||
|
||||
SpellEntry const* spellEntry = sSpellStore.LookupEntry(spell);
|
||||
if(!spellEntry)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' not exist but used in %s.",spell,name.c_str(),code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(family >= 0 && spellEntry->SpellFamilyName != family)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' family(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->SpellFamilyName,family,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(familyMaskA != UI64LIT(0xFFFFFFFFFFFFFFFF) || familyMaskB != 0xFFFFFFFF)
|
||||
{
|
||||
if(familyMaskA == UI64LIT(0x0000000000000000) && familyMaskB == 0x00000000)
|
||||
{
|
||||
if(spellEntry->SpellFamilyFlags != 0 || spellEntry->SpellFamilyFlags2 != 0)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' not fit to (" I64FMT "," I32FMT ") but used in %s.",spell,name.c_str(),familyMaskA,familyMaskB,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if((spellEntry->SpellFamilyFlags & familyMaskA)==0 && (spellEntry->SpellFamilyFlags2 & familyMaskB)==0)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' not fit to (" I64FMT "," I32FMT ") but used in %s.",spell,name.c_str(),familyMaskA,familyMaskB,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(spellIcon >= 0 && spellEntry->SpellIconID != spellIcon)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' icon(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->SpellIconID,spellIcon,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(spellVisual >= 0 && spellEntry->SpellVisual[0] != spellVisual)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' visual(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->SpellVisual[0],spellVisual,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(category >= 0 && spellEntry->Category != category)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' category(%u) <> %u but used in %s.",spell,name.c_str(),spellEntry->Category,category,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(effectIdx >= 0)
|
||||
{
|
||||
if(effectType >= 0 && spellEntry->Effect[effectIdx] != effectType)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' effect%d <> %u but used in %s.",spell,name.c_str(),effectIdx+1,effectType,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(auraType >= 0 && spellEntry->EffectApplyAuraName[effectIdx] != auraType)
|
||||
{
|
||||
sLog.outError("Spell %u '%s' aura%d <> %u but used in %s.",spell,name.c_str(),effectIdx+1,auraType,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(effectType >= 0 && !IsSpellHaveEffect(spellEntry,SpellEffects(effectType)))
|
||||
{
|
||||
sLog.outError("Spell %u '%s' not have effect %u but used in %s.",spell,name.c_str(),effectType,code.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if(auraType >= 0 && !IsSpellHaveAura(spellEntry,AuraType(auraType)))
|
||||
{
|
||||
sLog.outError("Spell %u '%s' not have aura %u but used in %s.",spell,name.c_str(),auraType,code.c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++countMasks;
|
||||
|
||||
bool found = false;
|
||||
for(uint32 spellId = 1; spellId < sSpellStore.GetNumRows(); ++spellId)
|
||||
{
|
||||
SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId);
|
||||
if(!spellEntry)
|
||||
continue;
|
||||
|
||||
if(family >=0 && spellEntry->SpellFamilyName != family)
|
||||
continue;
|
||||
|
||||
if(familyMaskA != UI64LIT(0xFFFFFFFFFFFFFFFF) || familyMaskB != 0xFFFFFFFF)
|
||||
{
|
||||
if(familyMaskA == UI64LIT(0x0000000000000000) && familyMaskB == 0x00000000)
|
||||
{
|
||||
if(spellEntry->SpellFamilyFlags != 0 || spellEntry->SpellFamilyFlags2 != 0)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((spellEntry->SpellFamilyFlags & familyMaskA)==0 && (spellEntry->SpellFamilyFlags2 & familyMaskB)==0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(spellIcon >= 0 && spellEntry->SpellIconID != spellIcon)
|
||||
continue;
|
||||
|
||||
if(spellVisual >= 0 && spellEntry->SpellVisual[0] != spellVisual)
|
||||
continue;
|
||||
|
||||
if(category >= 0 && spellEntry->Category != category)
|
||||
continue;
|
||||
|
||||
if(effectIdx >= 0)
|
||||
{
|
||||
if(effectType >=0 && spellEntry->Effect[effectIdx] != effectType)
|
||||
continue;
|
||||
|
||||
if(auraType >=0 && spellEntry->EffectApplyAuraName[effectIdx] != auraType)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(effectType >=0 && !IsSpellHaveEffect(spellEntry,SpellEffects(effectType)))
|
||||
continue;
|
||||
|
||||
if(auraType >=0 && !IsSpellHaveAura(spellEntry,AuraType(auraType)))
|
||||
continue;
|
||||
}
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
if(effectIdx >= 0)
|
||||
sLog.outError("Spells '%s' not found for family %i (" I64FMT "," I32FMT ") icon(%i) visual(%i) category(%i) effect%d(%i) aura%d(%i) but used in %s",
|
||||
name.c_str(),family,familyMaskA,familyMaskB,spellIcon,spellVisual,category,effectIdx+1,effectType,effectIdx+1,auraType,code.c_str());
|
||||
else
|
||||
sLog.outError("Spells '%s' not found for family %i (" I64FMT "," I32FMT ") icon(%i) visual(%i) category(%i) effect(%i) aura(%i) but used in %s",
|
||||
name.c_str(),family,familyMaskA,familyMaskB,spellIcon,spellVisual,category,effectType,auraType,code.c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
} while( result->NextRow() );
|
||||
|
||||
delete result;
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString( ">> Checked %u spells and %u spell masks", countSpells, countMasks );
|
||||
}
|
||||
|
||||
DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered)
|
||||
{
|
||||
// Explicit Diminishing Groups
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue