diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 1 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 8 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2fmt.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 17 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 151 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.h | 7 |
8 files changed, 129 insertions, 59 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 0fcf1742382..875505425f5 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -42,6 +42,7 @@ DB2Storage<PhaseGroupEntry> sPhaseGroupStore(PhaseGroupEntryfmt) DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore(SpellAuraRestrictionsEntryfmt); DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore(SpellCastingRequirementsEntryfmt); DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore(SpellClassOptionsEntryfmt); +DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore(SpellLearnSpellEntryfmt); DB2Storage<SpellMiscEntry> sSpellMiscStore(SpellMiscEntryfmt); DB2Storage<SpellPowerEntry> sSpellPowerStore(SpellPowerEntryfmt); SpellPowerBySpellIDMap sSpellPowerBySpellIDStore; @@ -142,6 +143,7 @@ void DB2Manager::LoadStores(std::string const& dataPath) LoadDB2(availableDb2Locales, bad_db2_files, _stores, sSpellAuraRestrictionsStore, db2Path, "SpellAuraRestrictions.db2"); LoadDB2(availableDb2Locales, bad_db2_files, _stores, sSpellCastingRequirementsStore, db2Path, "SpellCastingRequirements.db2"); LoadDB2(availableDb2Locales, bad_db2_files, _stores, sSpellClassOptionsStore, db2Path, "SpellClassOptions.db2"); + LoadDB2(availableDb2Locales, bad_db2_files, _stores, sSpellLearnSpellStore, db2Path, "SpellLearnSpell.db2"); LoadDB2(availableDb2Locales, bad_db2_files, _stores, sSpellMiscStore, db2Path, "SpellMisc.db2"); LoadDB2(availableDb2Locales, bad_db2_files, _stores, sSpellPowerStore, db2Path, "SpellPower.db2"); LoadDB2(availableDb2Locales, bad_db2_files, _stores, sSpellReagentsStore, db2Path, "SpellReagents.db2"); diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 43aa1397c5b..f721fd4bc19 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -35,6 +35,7 @@ extern DB2Storage<PhaseGroupEntry> sPhaseGroupStore; extern DB2Storage<SpellAuraRestrictionsEntry> sSpellAuraRestrictionsStore; extern DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore; extern DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore; +extern DB2Storage<SpellLearnSpellEntry> sSpellLearnSpellStore; extern DB2Storage<SpellMiscEntry> sSpellMiscStore; extern DB2Storage<SpellPowerEntry> sSpellPowerStore; extern SpellPowerBySpellIDMap sSpellPowerBySpellIDStore; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 70c54008401..7c68e5bb39a 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -288,6 +288,14 @@ struct SpellClassOptionsEntry uint32 SpellClassSet; // 3 }; +struct SpellLearnSpellEntry +{ + uint32 ID; // 0 + uint32 LearnSpellID; // 1 + uint32 SpellID; // 2 + uint32 OverridesSpellID; // 3 +}; + struct SpellMiscEntry { uint32 ID; // 0 diff --git a/src/server/game/DataStores/DB2fmt.h b/src/server/game/DataStores/DB2fmt.h index 8076685dc03..3a56fb75ca5 100644 --- a/src/server/game/DataStores/DB2fmt.h +++ b/src/server/game/DataStores/DB2fmt.h @@ -37,6 +37,7 @@ char const PhaseGroupEntryfmt[] = "nii"; char const SpellAuraRestrictionsEntryfmt[] = "diiiiiiii"; char const SpellCastingRequirementsEntryfmt[] = "dixxixi"; char const SpellClassOptionsEntryfmt[] = "niiiiii"; +char const SpellLearnSpellEntryfmt[] = "niii"; char const SpellMiscEntryfmt[] = "niiiiiiiiiiiiiiiiifiiiiix"; char const SpellPowerEntryfmt[] = "niiiiiixxxffix"; char const SpellReagentsEntryfmt[] = "niiiiiiiiiiiiiiiixx"; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index a26a728de81..559e40137c3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3658,13 +3658,16 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent for (SpellLearnSpellMap::const_iterator itr2 = spell_bounds.first; itr2 != spell_bounds.second; ++itr2) { - if (!itr2->second.autoLearned) + if (!itr2->second.AutoLearned) { - if (!IsInWorld() || !itr2->second.active) // at spells loading, no output, but allow save - AddSpell(itr2->second.spell, itr2->second.active, true, true, false); + if (!IsInWorld() || !itr2->second.Active) // at spells loading, no output, but allow save + AddSpell(itr2->second.Spell, itr2->second.Active, true, true, false); else // at normal learning - LearnSpell(itr2->second.spell, true); + LearnSpell(itr2->second.Spell, true); } + + if (itr2->second.OverridesSpell && itr2->second.Active) + AddOverrideSpell(itr2->second.OverridesSpell, itr2->second.Spell); } if (!GetSession()->PlayerLoading()) @@ -3873,7 +3876,11 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) SpellLearnSpellMapBounds spell_bounds = sSpellMgr->GetSpellLearnSpellMapBounds(spell_id); for (SpellLearnSpellMap::const_iterator itr2 = spell_bounds.first; itr2 != spell_bounds.second; ++itr2) - RemoveSpell(itr2->second.spell, disabled); + { + RemoveSpell(itr2->second.Spell, disabled); + if (itr2->second.OverridesSpell) + RemoveOverrideSpell(itr2->second.OverridesSpell, itr2->second.Spell); + } // activate lesser rank in spellbook/action bar, and cast it if need bool prev_activate = false; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 387a01dbf0a..6e70c4ef696 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -543,6 +543,7 @@ SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto) // todo 6.x SpellEffectInfoVector effects = proto->GetEffectsForDifficulty(diff); ASSERT(effects.size() <= MAX_SPELL_EFFECTS); + memset(EffectBasePoints, 0, sizeof(EffectBasePoints)); for (SpellEffectInfo const* effect : effects) if (effect) EffectBasePoints[effect->EffectIndex] = effect->BasePoints; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 5dd41eb9bcf..77044f67fc1 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -677,7 +677,7 @@ bool SpellMgr::IsSpellLearnToSpell(uint32 spell_id1, uint32 spell_id2) const { SpellLearnSpellMapBounds bounds = GetSpellLearnSpellMapBounds(spell_id1); for (SpellLearnSpellMap::const_iterator i = bounds.first; i != bounds.second; ++i) - if (i->second.spell == spell_id2) + if (i->second.Spell == spell_id2) return true; return false; } @@ -1484,9 +1484,10 @@ void SpellMgr::LoadSpellLearnSpells() uint32 spell_id = fields[0].GetUInt32(); SpellLearnSpellNode node; - node.spell = fields[1].GetUInt32(); - node.active = fields[2].GetBool(); - node.autoLearned = false; + node.Spell = fields[1].GetUInt32(); + node.OverridesSpell = 0; + node.Active = fields[2].GetBool(); + node.AutoLearned = false; SpellInfo const* spellInfo = GetSpellInfo(spell_id); if (!spellInfo) @@ -1495,15 +1496,15 @@ void SpellMgr::LoadSpellLearnSpells() continue; } - if (!GetSpellInfo(node.spell)) + if (!GetSpellInfo(node.Spell)) { - TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_learn_spell` learning not existed spell %u", spell_id, node.spell); + TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_learn_spell` learning not existed spell %u", spell_id, node.Spell); continue; } if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IS_TALENT)) { - TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_learn_spell` attempt learning talent spell %u, skipped", spell_id, node.spell); + TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_learn_spell` attempt learning talent spell %u, skipped", spell_id, node.Spell); continue; } @@ -1529,27 +1530,28 @@ void SpellMgr::LoadSpellLearnSpells() if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL) { SpellLearnSpellNode dbc_node; - dbc_node.spell = effect->TriggerSpell; - dbc_node.active = true; // all dbc based learned spells is active (show in spell book or hide by client itself) + dbc_node.Spell = effect->TriggerSpell; + dbc_node.Active = true; // all dbc based learned spells is active (show in spell book or hide by client itself) + dbc_node.OverridesSpell = 0; // ignore learning not existed spells (broken/outdated/or generic learnig spell 483 - if (!GetSpellInfo(dbc_node.spell)) + if (!GetSpellInfo(dbc_node.Spell)) continue; // talent or passive spells or skill-step spells auto-cast and not need dependent learning, // pet teaching spells must not be dependent learning (cast) // other required explicit dependent learning - dbc_node.autoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || entry->HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); + dbc_node.AutoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || entry->HasAttribute(SPELL_ATTR0_CU_IS_TALENT) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spell); bool found = false; for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr) { - if (itr->second.spell == dbc_node.spell) + if (itr->second.Spell == dbc_node.Spell) { TC_LOG_ERROR("sql.sql", "Spell %u auto-learn spell %u in spell.dbc then the record in `spell_learn_spell` is redundant, please fix DB.", - spell, dbc_node.spell); + spell, dbc_node.Spell); found = true; break; } @@ -1564,6 +1566,55 @@ void SpellMgr::LoadSpellLearnSpells() } } + for (uint32 i = 0; i < sSpellLearnSpellStore.GetNumRows(); ++i) + { + SpellLearnSpellEntry const* spellLearnSpell = sSpellLearnSpellStore.LookupEntry(i); + if (!spellLearnSpell) + continue; + + if (!GetSpellInfo(spellLearnSpell->SpellID)) + continue; + + SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spellLearnSpell->LearnSpellID); + bool found = false; + for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr) + { + if (itr->second.Spell == spellLearnSpell->SpellID) + { + TC_LOG_ERROR("sql.sql", "Found redundant record (entry: %u, SpellID: %u) in `spell_learn_spell`, spell added automatically from SpellLearnSpell.db2", spellLearnSpell->LearnSpellID, spellLearnSpell->SpellID); + found = true; + break; + } + } + + if (found) + continue; + + // Check if it is already found in Spell.dbc, ignore silently if yes + SpellLearnSpellMapBounds dbc_node_bounds = GetSpellLearnSpellMapBounds(spellLearnSpell->LearnSpellID); + found = false; + for (SpellLearnSpellMap::const_iterator itr = dbc_node_bounds.first; itr != dbc_node_bounds.second; ++itr) + { + if (itr->second.Spell == spellLearnSpell->SpellID) + { + found = true; + break; + } + } + + if (found) + continue; + + SpellLearnSpellNode dbcLearnNode; + dbcLearnNode.Spell = spellLearnSpell->SpellID; + dbcLearnNode.OverridesSpell = spellLearnSpell->OverridesSpellID; + dbcLearnNode.Active = true; + dbcLearnNode.AutoLearned = false; + + mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spellLearnSpell->LearnSpellID, dbcLearnNode)); + ++dbc_count; + } + uint32 mastery_count = 0; for (uint32 i = 0; i < sChrSpecializationStore.GetNumRows(); ++i) { @@ -1571,57 +1622,55 @@ void SpellMgr::LoadSpellLearnSpells() if (!chrSpec) continue; - for (uint32 c = CLASS_WARRIOR; c < MAX_CLASSES; ++c) + if (chrSpec->ClassID >= MAX_CLASSES) + continue; + + uint32 masteryMainSpell = MasterySpells[chrSpec->ClassID]; + + for (uint32 m = 0; m < MAX_MASTERY_SPELLS; ++m) { - if (chrSpec->ClassID != c) + uint32 mastery = chrSpec->MasterySpellID[m]; + if (!mastery) continue; - uint32 masteryMainSpell = MasterySpells[c]; - - for (uint32 m = 0; m < MAX_MASTERY_SPELLS; ++m) + SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(masteryMainSpell); + bool found = false; + for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr) { - uint32 mastery = chrSpec->MasterySpellID[m]; - if (!mastery) - continue; - - SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(masteryMainSpell); - bool found = false; - for (SpellLearnSpellMap::const_iterator itr = db_node_bounds.first; itr != db_node_bounds.second; ++itr) + if (itr->second.Spell == mastery) { - if (itr->second.spell == mastery) - { - TC_LOG_ERROR("sql.sql", "Found redundant record (entry: %u, SpellID: %u) in `spell_learn_spell`, spell added automatically as mastery learned spell from ChrSpecialization.dbc", masteryMainSpell, mastery); - found = true; - break; - } + TC_LOG_ERROR("sql.sql", "Found redundant record (entry: %u, SpellID: %u) in `spell_learn_spell`, spell added automatically as mastery learned spell from ChrSpecialization.dbc", masteryMainSpell, mastery); + found = true; + break; } + } - if (found) - continue; + if (found) + continue; - // Check if it is already found in Spell.dbc, ignore silently if yes - SpellLearnSpellMapBounds dbc_node_bounds = GetSpellLearnSpellMapBounds(masteryMainSpell); - found = false; - for (SpellLearnSpellMap::const_iterator itr = dbc_node_bounds.first; itr != dbc_node_bounds.second; ++itr) + // Check if it is already found in Spell.dbc, ignore silently if yes + SpellLearnSpellMapBounds dbc_node_bounds = GetSpellLearnSpellMapBounds(masteryMainSpell); + found = false; + for (SpellLearnSpellMap::const_iterator itr = dbc_node_bounds.first; itr != dbc_node_bounds.second; ++itr) + { + if (itr->second.Spell == mastery) { - if (itr->second.spell == mastery) - { - found = true; - break; - } + found = true; + break; } + } - if (found) - continue; + if (found) + continue; - SpellLearnSpellNode masteryNode; - masteryNode.spell = mastery; - masteryNode.active = true; - masteryNode.autoLearned = false; + SpellLearnSpellNode masteryNode; + masteryNode.Spell = mastery; + masteryNode.OverridesSpell = 0; + masteryNode.Active = true; + masteryNode.AutoLearned = false; - mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(masteryMainSpell, masteryNode)); - ++mastery_count; - } + mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(masteryMainSpell, masteryNode)); + ++mastery_count; } } diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 36ffe105c54..9033ccddeca 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -535,9 +535,10 @@ typedef std::map<uint32, SpellLearnSkillNode> SpellLearnSkillMap; struct SpellLearnSpellNode { - uint32 spell; - bool active; // show in spellbook or not - bool autoLearned; + uint32 Spell; + uint32 OverridesSpell; + bool Active; // show in spellbook or not + bool AutoLearned; // This marks the spell as automatically learned from another source that - will only be used for unlearning }; typedef std::multimap<uint32, SpellLearnSpellNode> SpellLearnSpellMap; |