diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/DBCStructure.h | 70 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 346 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 2 | ||||
-rw-r--r-- | src/game/World.cpp | 6 |
4 files changed, 121 insertions, 303 deletions
diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 557ff02db07..6b736d0f4f7 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1421,41 +1421,41 @@ struct SpellEntry int32 EffectMiscValueB[MAX_SPELL_EFFECTS]; // 119-121 m_effectMiscValueB uint32 EffectTriggerSpell[MAX_SPELL_EFFECTS]; // 122-124 m_effectTriggerSpell float EffectPointsPerComboPoint[MAX_SPELL_EFFECTS]; // 125-127 m_effectPointsPerCombo - flag96 EffectSpellClassMask[MAX_SPELL_EFFECTS]; // 127-133 - uint32 SpellVisual[2]; // 134-135 m_spellVisualID - uint32 SpellIconID; // 136 m_spellIconID - uint32 activeIconID; // 137 m_activeIconID - //uint32 spellPriority; // 138 not used - char* SpellName[16]; // 139-154 m_name_lang - //uint32 SpellNameFlag; // 155 not used - char* Rank[16]; // 156-171 m_nameSubtext_lang - //uint32 RankFlags; // 172 not used - //char* Description[16]; // 173-188 m_description_lang not used - //uint32 DescriptionFlags; // 189 not used - //char* ToolTip[16]; // 190-205 m_auraDescription_lang not used - //uint32 ToolTipFlags; // 206 not used - uint32 ManaCostPercentage; // 207 m_manaCostPct - uint32 StartRecoveryCategory; // 208 m_startRecoveryCategory - uint32 StartRecoveryTime; // 209 m_startRecoveryTime - uint32 MaxTargetLevel; // 210 m_maxTargetLevel - uint32 SpellFamilyName; // 211 m_spellClassSet - flag96 SpellFamilyFlags; // 212-214 - uint32 MaxAffectedTargets; // 215 m_maxTargets - uint32 DmgClass; // 216 m_defenseType - uint32 PreventionType; // 217 m_preventionType - //uint32 StanceBarOrder; // 218 m_stanceBarOrder not used - float DmgMultiplier[3]; // 219-221 m_effectChainAmplitude - //uint32 MinFactionId; // 222 m_minFactionID not used - //uint32 MinReputation; // 223 m_minReputation not used - //uint32 RequiredAuraVision; // 224 m_requiredAuraVision not used - uint32 TotemCategory[2]; // 225-226 m_requiredTotemCategoryID - int32 AreaGroupId; // 227 m_requiredAreaGroupId - uint32 SchoolMask; // 228 m_schoolMask - uint32 runeCostID; // 229 m_runeCostID - //uint32 spellMissileID; // 230 m_spellMissileID not used - //uint32 PowerDisplayId; // 231 PowerDisplay.dbc, new in 3.1 - //float unk_320_4[3]; // 232-234 3.2.0 - //uint32 spellDescriptionVariableID; // 235 3.2.0 + flag96 EffectSpellClassMask[MAX_SPELL_EFFECTS]; // 127-136 + uint32 SpellVisual[2]; // 137-138 m_spellVisualID + uint32 SpellIconID; // 139 m_spellIconID + uint32 activeIconID; // 140 m_activeIconID + //uint32 spellPriority; // 141 not used + char* SpellName[16]; // 142-157 m_name_lang + //uint32 SpellNameFlag; // 158 not used + char* Rank[16]; // 159-174 m_nameSubtext_lang + //uint32 RankFlags; // 175 not used + //char* Description[16]; // 176-191 m_description_lang not used + //uint32 DescriptionFlags; // 192 not used + //char* ToolTip[16]; // 193-208 m_auraDescription_lang not used + //uint32 ToolTipFlags; // 209 not used + uint32 ManaCostPercentage; // 210 m_manaCostPct + uint32 StartRecoveryCategory; // 211 m_startRecoveryCategory + uint32 StartRecoveryTime; // 212 m_startRecoveryTime + uint32 MaxTargetLevel; // 213 m_maxTargetLevel + uint32 SpellFamilyName; // 214 m_spellClassSet + flag96 SpellFamilyFlags; // 215-217 + uint32 MaxAffectedTargets; // 218 m_maxTargets + uint32 DmgClass; // 219 m_defenseType + uint32 PreventionType; // 220 m_preventionType + //uint32 StanceBarOrder; // 221 m_stanceBarOrder not used + float DmgMultiplier[3]; // 222-224 m_effectChainAmplitude + //uint32 MinFactionId; // 225 m_minFactionID not used + //uint32 MinReputation; // 226 m_minReputation not used + //uint32 RequiredAuraVision; // 227 m_requiredAuraVision not used + uint32 TotemCategory[2]; // 228-229 m_requiredTotemCategoryID + int32 AreaGroupId; // 230 m_requiredAreaGroupId + uint32 SchoolMask; // 231 m_schoolMask + uint32 runeCostID; // 232 m_runeCostID + //uint32 spellMissileID; // 233 m_spellMissileID not used + //uint32 PowerDisplayId; // 234 PowerDisplay.dbc, new in 3.1 + //float unk_320_4[3]; // 235-237 3.2.0 + //uint32 spellDescriptionVariableID; // 238 3.2.0 // helpers int32 CalculateSimpleValue(uint8 eff) const { return EffectBasePoints[eff]+int32(EffectBaseDice[eff]); } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 34a25020d9b..cf71f8fe227 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -3231,302 +3231,120 @@ void SpellMgr::LoadSpellRequired() sLog.outString( ">> Loaded %u spell required records", rows ); } -struct SpellRankEntry -{ - uint32 SkillId; - char const *SpellName; - uint32 DurationIndex; - uint32 RangeIndex; - uint32 SpellVisual; - uint32 ProcFlags; - flag96 SpellFamilyFlags; - uint32 TargetAuraState; - uint32 ManaCost; - uint32 CastingTimeIndex; - flag96 Effect; - flag96 Aura; - uint16 TalentID; - - bool operator < (const SpellRankEntry & _Right) const - { - return (SkillId != _Right.SkillId ? SkillId < _Right.SkillId - : SpellName != _Right.SpellName ? SpellName < _Right.SpellName - : ProcFlags != _Right.ProcFlags ? ProcFlags < _Right.ProcFlags - - : Effect != _Right.Effect ? Effect < _Right.Effect - : Aura != _Right.Aura ? Aura < _Right.Aura - : TalentID != _Right.TalentID ? TalentID < _Right.TalentID - : (CastingTimeIndex != _Right.CastingTimeIndex) && (!CastingTimeIndex || !_Right.CastingTimeIndex || CastingTimeIndex == 1 || !_Right.CastingTimeIndex == 1) ? CastingTimeIndex < _Right.CastingTimeIndex - - : SpellFamilyFlags != _Right.SpellFamilyFlags ? SpellFamilyFlags < _Right.SpellFamilyFlags - : (SpellVisual != _Right.SpellVisual) && (!SpellVisual || !_Right.SpellVisual) ? SpellVisual < _Right.SpellVisual - : (ManaCost != _Right.ManaCost) && (!ManaCost || !_Right.ManaCost) ? ManaCost < _Right.ManaCost - : (DurationIndex != _Right.DurationIndex) && (!DurationIndex || !_Right.DurationIndex)? DurationIndex < _Right.DurationIndex - : (RangeIndex != _Right.RangeIndex) && (!RangeIndex || !_Right.RangeIndex || RangeIndex == 1 || !_Right.RangeIndex == 1) ? RangeIndex < _Right.RangeIndex - : TargetAuraState < _Right.TargetAuraState - ); - } -}; - -struct SpellRankValue -{ - uint32 Id; - char const *Rank; - bool strict; -}; - -void SpellMgr::LoadSpellChains() +void SpellMgr::LoadSpellRanks() { mSpellChains.clear(); // need for reload case - std::vector<uint32> ChainedSpells; - for (uint32 ability_id = 0; ability_id < sSkillLineAbilityStore.GetNumRows(); ++ability_id) - { - SkillLineAbilityEntry const *AbilityInfo=sSkillLineAbilityStore.LookupEntry(ability_id); - if (!AbilityInfo) - continue; - if (!AbilityInfo->forward_spellid) - continue; - ChainedSpells.push_back(AbilityInfo->forward_spellid); - } - - std::multimap<SpellRankEntry, SpellRankValue> RankMap; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT first_spell_id, spell_id, rank from spell_ranks ORDER BY first_spell_id , rank"); - for (uint32 ability_id = 0; ability_id < sSkillLineAbilityStore.GetNumRows(); ++ability_id) + if (!result) { - SkillLineAbilityEntry const *AbilityInfo=sSkillLineAbilityStore.LookupEntry(ability_id); - if (!AbilityInfo) - continue; - - //get only spell with lowest ability_id to prevent doubles - uint32 spell_id = AbilityInfo->spellId; - bool found = false; - for (uint32 i = 0; i < ChainedSpells.size(); ++i) - { - if (ChainedSpells.at(i) == spell_id) - found = true; - } - if (found) - continue; - - if(mSkillLineAbilityMap.lower_bound(spell_id)->second->id != ability_id) - continue; - SpellEntry const *SpellInfo=sSpellStore.LookupEntry(spell_id); - if (!SpellInfo) - continue; - std::string sRank = SpellInfo->Rank[sWorld.GetDefaultDbcLocale()]; - if(sRank.empty()) - continue; - //exception to polymorph spells-make pig and turtle other chain than sheep - if (SpellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (SpellInfo->SpellFamilyFlags[0] & 0x1000000) && SpellInfo->SpellIconID != 82) - continue; + barGoLink bar(1); + bar.step(); - SpellRankEntry entry; - SpellRankValue value; - entry.SkillId = AbilityInfo->skillId; - entry.SpellName = SpellInfo->SpellName[sWorld.GetDefaultDbcLocale()]; - entry.DurationIndex = SpellInfo->DurationIndex; - entry.RangeIndex = SpellInfo->rangeIndex; - entry.ProcFlags = SpellInfo->procFlags; - entry.SpellFamilyFlags = SpellInfo->SpellFamilyFlags; - entry.TargetAuraState = SpellInfo->TargetAuraState; - entry.SpellVisual = SpellInfo->SpellVisual[0]; - entry.ManaCost = SpellInfo->manaCost; - entry.CastingTimeIndex = 0; - entry.TalentID = 0; - for (;;) - { - AbilityInfo = mSkillLineAbilityMap.lower_bound(spell_id)->second; - value.Id = spell_id; - value.Rank = SpellInfo->Rank[sWorld.GetDefaultDbcLocale()]; - value.strict = false; - RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(entry,value)); - spell_id = AbilityInfo->forward_spellid; - SpellInfo = sSpellStore.LookupEntry(spell_id); - if (!SpellInfo) - break; - } + sLog.outString(); + sLog.outString(">> Loaded 0 spell rank records"); + sLog.outErrorDb("`spell_ranks` table is empty!"); + return; } - barGoLink bar(RankMap.size()); + barGoLink bar(result->GetRowCount()); - uint32 count = 0; + uint32 rows = 0; + bool finished = false; - for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr = RankMap.begin(); itr!=RankMap.end();) + do { - SpellRankEntry entry = itr->first; - //trac errors in extracted data - std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator> RankErrorMap; - for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry); itr2 != RankMap.upper_bound(entry); ++itr2) + // spellid, rank + std::list<std::pair<int32, int32>> rankChain; + int32 currentSpell = -1; + int32 lastSpell = -1; + + // fill one chain + while(currentSpell == lastSpell && !finished) { bar.step(); - RankErrorMap.insert(std::pair<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>(itr2->second.Rank,itr2)); - } - bool error = false; - //if strict == true strict check is not needed - if (!itr->second.strict) - //check for rank duplicates, if there are any do strict check - for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>::iterator itr2 = RankErrorMap.begin(); itr2!=RankErrorMap.end();) + Field *fields = result->Fetch(); + + currentSpell = fields[0].GetUInt32(); + if (lastSpell == -1) + lastSpell = currentSpell; + uint32 spell_id = fields[1].GetUInt32(); + uint32 rank = fields[2].GetUInt32(); + + // don't drop the row if we're moving to the next rank + if (currentSpell == lastSpell) { - char const *err_entry = itr2->first; - uint32 rank_count=RankErrorMap.count(itr2->first); - if (rank_count > 1) - { - error = true; - break; - } - else - ++itr2; + rankChain.push_back(std::make_pair(spell_id, rank)); + if (!result->NextRow()) + finished = true; } - bool allHaveTalents = true; - if (error) + else + break; + } + // check if chain is made with valid first spell + SpellEntry const * first = sSpellStore.LookupEntry(lastSpell); + if (!first) { - std::list<uint32> ConflictedSpells; - for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry); itr2 != RankMap.upper_bound(entry); itr2 = RankMap.lower_bound(entry)) - { - ConflictedSpells.push_back(itr2->second.Id); - if (!GetTalentSpellPos(itr2->second.Id)) - allHaveTalents = false; - RankMap.erase(itr2); - } - SpellRankEntry nextEntry, currEntry; - for (; !ConflictedSpells.empty(); ConflictedSpells.pop_front()) - { - SpellEntry const *SpellInfo = sSpellStore.LookupEntry(ConflictedSpells.front()); - currEntry.SkillId = entry.SkillId; - currEntry.SpellName = SpellInfo->SpellName[sWorld.GetDefaultDbcLocale()]; - currEntry.DurationIndex = SpellInfo->DurationIndex; - currEntry.RangeIndex = SpellInfo->rangeIndex; - currEntry.ProcFlags = SpellInfo->procFlags; - currEntry.SpellFamilyFlags = SpellInfo->SpellFamilyFlags; - //compare talents only when all spells from chain have entry - //to prevent wrong results with spells which have first rank talented and other not - if (allHaveTalents) - currEntry.TalentID=GetTalentSpellPos(ConflictedSpells.front())->talent_id; - else - currEntry.TalentID = 0; - currEntry.TargetAuraState = SpellInfo->TargetAuraState; - currEntry.SpellVisual = SpellInfo->SpellVisual[0]; - currEntry.ManaCost = SpellInfo->manaCost; - - //compare effects and casting time - currEntry.CastingTimeIndex = SpellInfo->CastingTimeIndex; - currEntry.Effect[0] = SpellInfo->Effect[0]; - currEntry.Effect[1] = SpellInfo->Effect[1]; - currEntry.Effect[2] = SpellInfo->Effect[2]; - - currEntry.Aura[0] = SpellInfo->EffectApplyAuraName[0]; - currEntry.Aura[1] = SpellInfo->EffectApplyAuraName[1]; - currEntry.Aura[2] = SpellInfo->EffectApplyAuraName[2]; - - SpellRankValue currValue; - currValue.Id = ConflictedSpells.front(); - currValue.Rank = SpellInfo->Rank[sWorld.GetDefaultDbcLocale()]; - currValue.strict = true; - RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(currEntry,currValue)); - } - itr = RankMap.begin(); + sLog.outErrorDb("Spell rank identifier(first_spell_id) %u listed in `spell_ranks` does not exist!", lastSpell); continue; } - else - for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>::iterator itr2 = RankErrorMap.begin(); itr2!=RankErrorMap.end();) - { - char const *err_entry = itr2->first; - uint32 rank_count = RankErrorMap.count(itr2->first); - if (rank_count > 1) - for (itr2 = RankErrorMap.lower_bound(err_entry); itr2 != RankErrorMap.upper_bound(err_entry); ++itr2) - { - // I removed this pointless error message since there is NOTHING that can be - // done about it. Spell chain data is read from DBC... - // If you *REALLY* need to see this, uncomment this line and the one below - // sLog.outDebug("There is a duplicate rank entry (%s) for spell: %u",itr2->first,itr2->second->second.Id); - if (itr2->second->second.Id != 47541 && itr2->second->second.Id != 45902 && itr2->second->second.Id != 7620) - { - // Part two of pointless error messages... - // sLog.outDebug("Spell %u removed from chain data.",itr2->second->second.Id); - RankMap.erase(itr2->second); - } - } - else - ++itr2; - } - - //order spells by spellLevel - std::list<uint32> RankedSpells; - uint32 min_spell_lvl = 0; - std::multimap<SpellRankEntry, SpellRankValue>::iterator min_itr; - for (; RankMap.count(entry);) + // check if chain is long enough + if (rankChain.size() < 2) { - for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry); itr2!=RankMap.upper_bound(entry); ++itr2) - { - SpellEntry const *SpellInfo=sSpellStore.LookupEntry(itr2->second.Id); - if (SpellInfo->spellLevel<min_spell_lvl || itr2 == RankMap.lower_bound(entry)) - { - min_spell_lvl = SpellInfo->spellLevel; - min_itr = itr2; - } - } - RankedSpells.push_back(min_itr->second.Id); - RankMap.erase(min_itr); + sLog.outErrorDb("There is only 1 spell rank for identifier(first_spell_id) %u in `spell_ranks`, entry is not needed!", lastSpell); + continue; } - - //use data from talent.dbc - uint16 talent_id = 0; - for (std::list<uint32>::iterator itr2 = RankedSpells.begin(); itr2 != RankedSpells.end();) + int32 curRank = 0; + bool valid = true; + // check spells in chain + for (std::list<std::pair<int32, int32>>::iterator itr = rankChain.begin() ; itr!= rankChain.end(); ++itr) { - if (TalentSpellPos const *TalentPos = GetTalentSpellPos(*itr2)) + SpellEntry const * spell = sSpellStore.LookupEntry(itr->first); + if (!spell) { - talent_id = TalentPos->talent_id; - RankedSpells.erase(itr2); - itr2 = RankedSpells.begin(); + sLog.outErrorDb("Spell %u (rank %u) listed in `spell_ranks` for chain %u does not exist!", itr->first, itr->second, lastSpell); + valid = false; + break; + } + ++curRank; + if (itr->second != curRank) + { + sLog.outErrorDb("Spell %u (rank %u) listed in `spell_ranks` for chain %u does not have proper rank value(should be %u)!", itr->first, itr->second, lastSpell, curRank); + valid = false; + continue; } - else - ++itr2; - } - if (talent_id) - { - TalentEntry const *TalentInfo = sTalentStore.LookupEntry(talent_id); - for (uint8 rank = MAX_TALENT_RANK; rank > 0; --rank) - if (TalentInfo->RankID[rank-1]) - RankedSpells.push_front(TalentInfo->RankID[rank-1]); } - - //do not proceed for spells with less than 2 ranks - itr = RankMap.begin(); - if (RankedSpells.size() < 2) + if (!valid) continue; - - ++count; - - uint32 spell_rank = 1; - for (std::list<uint32>::iterator itr2 = RankedSpells.begin(); itr2 != RankedSpells.end(); ++spell_rank) - { - uint32 spell_id = *itr2; - mSpellChains[spell_id].rank = spell_rank; - mSpellChains[spell_id].first = RankedSpells.front(); - mSpellChains[spell_id].last = RankedSpells.back(); - - ++itr2; - if (spell_rank<2) - mSpellChains[spell_id].prev = 0; - - if (spell_id == RankedSpells.back()) - mSpellChains[spell_id].next = 0; - else + int32 prevRank = 0; + // insert the chain + std::list<std::pair<int32, int32>>::iterator itr = rankChain.begin(); + do + { + int32 addedSpell = itr->first; + mSpellChains[addedSpell].first = lastSpell; + mSpellChains[addedSpell].last = rankChain.back().first; + mSpellChains[addedSpell].rank = itr->second; + mSpellChains[addedSpell].prev = prevRank; + prevRank = addedSpell; + ++itr; + if (itr == rankChain.end()) { - mSpellChains[*itr2].prev = spell_id; - mSpellChains[spell_id].next = *itr2; + mSpellChains[addedSpell].next = 0; + break; } + else + mSpellChains[addedSpell].next = itr->first; } - } + while (true); - //uncomment these two lines to print yourself list of spell_chains on startup - //for(UNORDERED_MAP<uint32, SpellChainNode>::iterator itr = mSpellChains.begin(); itr != mSpellChains.end(); ++itr) - //sLog.outString("Id: %u, Rank: %d , %s, %u, %u, %u, %u",itr->first,itr->second.rank, sSpellStore.LookupEntry(itr->first)->Rank[sWorld.GetDefaultDbcLocale()], itr->second.first, itr->second.last,itr->second.next, itr->second.prev); + ++rows; + } while (!finished); sLog.outString(); - sLog.outString(">> Loaded %u spell chains",count); + sLog.outString( ">> Loaded %u spell rank records", rows ); } // set data in core for now diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 0336b615f5e..550f9d7bf37 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -1207,7 +1207,7 @@ class SpellMgr static SpellMgr& Instance(); // Loading data at server startup - void LoadSpellChains(); + void LoadSpellRanks(); void LoadSpellRequired(); void LoadSpellLearnSkills(); void LoadSpellLearnSpells(); diff --git a/src/game/World.cpp b/src/game/World.cpp index f8590ce8784..939426d86d1 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1305,8 +1305,8 @@ void World::SetInitialWorldSettings() sLog.outString("Loading Game Object Templates..."); // must be after LoadPageTexts objmgr.LoadGameobjectInfo(); - sLog.outString("Loading Spell Chain Data..."); - spellmgr.LoadSpellChains(); + sLog.outString("Loading Spell Rank Data..."); + spellmgr.LoadSpellRanks(); sLog.outString("Loading Spell Required Data..."); spellmgr.LoadSpellRequired(); @@ -1315,7 +1315,7 @@ void World::SetInitialWorldSettings() spellmgr.LoadSpellElixirs(); sLog.outString("Loading Spell Learn Skills..."); - spellmgr.LoadSpellLearnSkills(); // must be after LoadSpellChains + spellmgr.LoadSpellLearnSkills(); // must be after LoadSpellRanks sLog.outString("Loading Spell Learn Spells..."); spellmgr.LoadSpellLearnSpells(); |