aboutsummaryrefslogtreecommitdiff
path: root/src/game/SpellMgr.cpp
diff options
context:
space:
mode:
authormegamage <none@none>2009-07-16 10:13:12 +0800
committermegamage <none@none>2009-07-16 10:13:12 +0800
commite1762e3e6d6a9cc82f2244b5c6d4e26d3315caf6 (patch)
tree9de6c38c8832b8627a782fe75ba418dd240b3b01 /src/game/SpellMgr.cpp
parent6f256824233ae004cf3fc93d1626e91c279452ea (diff)
[8169] Implement new optional table `spell_check` and console command .debug spellcheck Author: VladimirMangos
* 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. --HG-- branch : trunk
Diffstat (limited to 'src/game/SpellMgr.cpp')
-rw-r--r--src/game/SpellMgr.cpp266
1 files changed, 255 insertions, 11 deletions
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 9e0b69d0777..dfa25cef538 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -889,17 +889,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
@@ -2593,6 +2582,261 @@ 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();
+ flag96 familyMask(familyMaskA, familyMaskB);
+ 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)
+ {
+ 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 & familyMask))
+ {
+ 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)
+ continue;
+ }
+ else
+ {
+ if(!(spellEntry->SpellFamilyFlags & familyMask))
+ 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