diff options
author | QAston <none@none> | 2010-02-02 22:35:01 +0100 |
---|---|---|
committer | QAston <none@none> | 2010-02-02 22:35:01 +0100 |
commit | 10695f9131336b26c352b19ce2a39e8c2ca0af8e (patch) | |
tree | 8133420b42fa204ed5f11553df7e04e50a735bed /src | |
parent | 70425115f0650807fb08ca5d70a782c532e7c926 (diff) |
*Drop spell_stack_masks table
*Add spell_group_stack_rules table (for more info see wiki)
*The table is maintained by core team
*Move some spell specific out of core to the new table
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Chat.cpp | 2 | ||||
-rw-r--r-- | src/game/Chat.h | 2 | ||||
-rw-r--r-- | src/game/Level3.cpp | 10 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 43 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 158 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 133 | ||||
-rw-r--r-- | src/game/World.cpp | 6 |
7 files changed, 175 insertions, 179 deletions
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 920a9416ed7..4d68048b8b8 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -508,7 +508,7 @@ ChatCommand * ChatHandler::getCommandTable() { "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL }, { "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL }, { "spell_disabled", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellDisabledCommand, "", NULL }, - { "spell_stack_masks", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellStackMasksCommand, "", NULL }, + { "spell_group_stack_rules", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellGroupStackRulesCommand, "", NULL }, { "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", NULL }, { "auctions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAuctionsCommand, "", NULL }, { "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 4edd705c5dd..2fe4e245e6e 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -421,7 +421,7 @@ class TRINITY_DLL_SPEC ChatHandler bool HandleReloadSpellThreatsCommand(const char* args); bool HandleReloadSpellPetAurasCommand(const char* args); bool HandleReloadSpellDisabledCommand(const char* args); - bool HandleReloadSpellStackMasksCommand(const char* args); + bool HandleReloadSpellGroupStackRulesCommand(const char* args); bool HandleReloadAuctionsCommand(const char* args); bool HandleReloadWpScriptsCommand(const char* args); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 75429eca352..5e3b0c57b97 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -659,7 +659,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*) HandleReloadSpellScriptTargetCommand("a"); HandleReloadSpellTargetPositionCommand("a"); HandleReloadSpellThreatsCommand("a"); - HandleReloadSpellStackMasksCommand("a"); + HandleReloadSpellGroupStackRulesCommand("a"); HandleReloadSpellPetAurasCommand("a"); HandleReloadSpellDisabledCommand("a"); return true; @@ -1094,11 +1094,11 @@ bool ChatHandler::HandleReloadSpellThreatsCommand(const char*) return true; } -bool ChatHandler::HandleReloadSpellStackMasksCommand(const char*) +bool ChatHandler::HandleReloadSpellGroupStackRulesCommand(const char*) { - sLog.outString( "Re-Loading Spell stacking masks..." ); - spellmgr.LoadSpellStackMasks(); - SendGlobalGMSysMessage("DB table `spell_stack_masks` (spell stacking masks) reloaded."); + sLog.outString( "Re-Loading Spell Group Stack Rules..." ); + spellmgr.LoadSpellGroupStackRules(); + SendGlobalGMSysMessage("DB table `spell_group_stack_rules` (spell stacking definitions) reloaded."); return true; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 7a61a717fe4..63ec61ad826 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3216,44 +3216,29 @@ void Spell::EffectEnergize(uint32 i) } // get all available elixirs by mask and spell level - std::list<uint32> avalibleElixirs; + std::set<uint32> avalibleElixirs; if (!guardianFound) - { - SpellGroupSpellMapBounds guardianGroup = spellmgr.GetSpellGroupSpellMapBounds(SPELL_GROUP_ELIXIR_GUARDIAN); - for ( SpellGroupSpellMap::const_iterator itr = guardianGroup.first; itr != guardianGroup.second ; ++itr) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->second); - if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel())) - continue; - if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_SHATTRATH)) - continue; - if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_UNSTABLE)) - continue; - avalibleElixirs.push_back(itr->second); - } - } + spellmgr.GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_GUARDIAN, avalibleElixirs); if (!battleFound) + spellmgr.GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, avalibleElixirs); + for (std::set<uint32>::iterator itr = avalibleElixirs.begin(); itr != avalibleElixirs.end() ;) { - SpellGroupSpellMapBounds battleGroup = spellmgr.GetSpellGroupSpellMapBounds(SPELL_GROUP_ELIXIR_BATTLE); - for ( SpellGroupSpellMap::const_iterator itr = battleGroup.first; itr != battleGroup.second ; ++itr) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->second); - if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel())) - continue; - if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_SHATTRATH)) - continue; - if(spellmgr.IsSpellMemberOfSpellGroup(itr->second, SPELL_GROUP_ELIXIR_UNSTABLE)) - continue; - avalibleElixirs.push_back(itr->second); - } + SpellEntry const *spellInfo = sSpellStore.LookupEntry(*itr); + if (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()) + avalibleElixirs.erase(itr++); + else if(spellmgr.IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_SHATTRATH)) + avalibleElixirs.erase(itr++); + else if(spellmgr.IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_UNSTABLE)) + avalibleElixirs.erase(itr++); + else + ++itr; } - avalibleElixirs.unique(); if (!avalibleElixirs.empty()) { // cast random elixir on target uint32 rand_spell = urand(0,avalibleElixirs.size()-1); - std::list<uint32>::iterator itr = avalibleElixirs.begin(); + std::set<uint32>::iterator itr = avalibleElixirs.begin(); std::advance(itr, rand_spell); m_caster->CastSpell(unitTarget,*itr,true,m_CastItem); } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index e233dc05691..34a6c30db48 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -510,14 +510,6 @@ SpellSpecific GetSpellSpecific(SpellEntry const * spellInfo) else if(drink) return SPELL_SPECIFIC_DRINK; } - // Well Fed buffs (must be exclusive with Food / Drink replenishment effects, or else Well Fed will cause them to be removed) - // SpellIcon 2560 is Spell 46687, does not have this flag - else if ((spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) || spellInfo->SpellIconID == 2560) - return SPELL_SPECIFIC_WELL_FED; - // this may be a hack - //else if((spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) - // && !spellInfo->Category) - // return SPELL_WELL_FED; // scrolls effects else { @@ -555,8 +547,6 @@ SpellSpecific GetSpellSpecific(SpellEntry const * spellInfo) } case SPELLFAMILY_WARRIOR: { - if (spellInfo->SpellFamilyFlags[1] & 0x000080) - return SPELL_SPECIFIC_POSITIVE_SHOUT; if (spellInfo->Id == 12292) // Death Wish return SPELL_SPECIFIC_WARRIOR_ENRAGE; @@ -579,12 +569,6 @@ SpellSpecific GetSpellSpecific(SpellEntry const * spellInfo) } case SPELLFAMILY_PRIEST: { - // "Well Fed" buff from Blessed Sunfruit, Blessed Sunfruit Juice, Alterac Spring Water - if ((spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_SITTING) && - (spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK) && - (spellInfo->SpellIconID == 52 || spellInfo->SpellIconID == 79)) - return SPELL_SPECIFIC_WELL_FED; - // Divine Spirit and Prayer of Spirit if (spellInfo->SpellFamilyFlags[0] & 0x20) return SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT; @@ -608,9 +592,6 @@ SpellSpecific GetSpellSpecific(SpellEntry const * spellInfo) if (IsSealSpell(spellInfo)) return SPELL_SPECIFIC_SEAL; - if (spellInfo->SpellFamilyFlags[0] & 0x11010002) - return SPELL_SPECIFIC_BLESSING; - if (spellInfo->SpellFamilyFlags[0] & 0x00002190) return SPELL_SPECIFIC_HAND; @@ -632,9 +613,6 @@ SpellSpecific GetSpellSpecific(SpellEntry const * spellInfo) break; } - case SPELLFAMILY_POTION: - return spellmgr.GetSpellElixirSpecific(spellInfo->Id); - case SPELLFAMILY_DEATHKNIGHT: if (spellInfo->Id == SPELL_BLOOD_PRESENCE_48266 || spellInfo->Id == SPELL_FROST_PRESENCE_48263 || spellInfo->Id == SPELL_UNHOLY_PRESENCE_48265) //if (spellInfo->Category == 47) @@ -662,9 +640,6 @@ SpellSpecific GetSpellSpecific(SpellEntry const * spellInfo) } } } - // elixirs can have different families, but potion most ofc. - if(SpellSpecific sp = spellmgr.GetSpellElixirSpecific(spellInfo->Id)) - return sp; return SPELL_SPECIFIC_NORMAL; } @@ -680,10 +655,8 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s case SPELL_SPECIFIC_STING: case SPELL_SPECIFIC_CURSE: case SPELL_SPECIFIC_ASPECT: - case SPELL_SPECIFIC_POSITIVE_SHOUT: case SPELL_SPECIFIC_JUDGEMENT: case SPELL_SPECIFIC_WARLOCK_CORRUPTION: - case SPELL_SPECIFIC_BLESSING: return spellSpec1==spellSpec2; default: return false; @@ -701,13 +674,11 @@ bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1, SpellSpecific case SPELL_SPECIFIC_ELEMENTAL_SHIELD: case SPELL_SPECIFIC_MAGE_POLYMORPH: case SPELL_SPECIFIC_PRESENCE: - case SPELL_SPECIFIC_WELL_FED: case SPELL_SPECIFIC_CHARM: case SPELL_SPECIFIC_SCROLL: case SPELL_SPECIFIC_WARRIOR_ENRAGE: case SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE: case SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT: - case SPELL_SPECIFIC_POSITIVE_SHOUT: return spellSpec1==spellSpec2; case SPELL_SPECIFIC_FOOD: return spellSpec2==SPELL_SPECIFIC_FOOD @@ -719,16 +690,6 @@ bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1, SpellSpecific return spellSpec2==SPELL_SPECIFIC_FOOD || spellSpec2==SPELL_SPECIFIC_DRINK || spellSpec2==SPELL_SPECIFIC_FOOD_AND_DRINK; - case SPELL_SPECIFIC_BATTLE_ELIXIR: - return spellSpec2==SPELL_SPECIFIC_BATTLE_ELIXIR - || spellSpec2==SPELL_SPECIFIC_FLASK_ELIXIR; - case SPELL_SPECIFIC_GUARDIAN_ELIXIR: - return spellSpec2==SPELL_SPECIFIC_GUARDIAN_ELIXIR - || spellSpec2==SPELL_SPECIFIC_FLASK_ELIXIR; - case SPELL_SPECIFIC_FLASK_ELIXIR: - return spellSpec2==SPELL_SPECIFIC_BATTLE_ELIXIR - || spellSpec2==SPELL_SPECIFIC_GUARDIAN_ELIXIR - || spellSpec2==SPELL_SPECIFIC_FLASK_ELIXIR; default: return false; } @@ -1488,6 +1449,8 @@ void SpellMgr::LoadSpellGroups() barGoLink bar( result->GetRowCount() ); + std::set<uint32> groups; + do { Field *fields = result->Fetch(); @@ -1495,45 +1458,73 @@ void SpellMgr::LoadSpellGroups() bar.step(); uint32 group_id = fields[0].GetUInt32(); - uint32 spell_id = fields[1].GetUInt32(); - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); - - if (!spellInfo) + if (group_id <= SPELL_GROUP_DB_RANGE_MIN && group_id >= SPELL_GROUP_CORE_RANGE_MAX) { - sLog.outErrorDb("Spell %u listed in `spell_group` does not exist", spell_id); + sLog.outErrorDb("SpellGroup id %u listed in `spell_groups` is in core range, but is not defined in core!", group_id); continue; } + int32 spell_id = fields[1].GetInt32(); + + groups.insert(std::set<uint32>::value_type(group_id)); + mSpellGroupSpell.insert(SpellGroupSpellMap::value_type((SpellGroup)group_id, spell_id)); - if (GetSpellRank(spell_id) > 1) + } while( result->NextRow() ); + + for (SpellGroupSpellMap::iterator itr = mSpellGroupSpell.begin(); itr!= mSpellGroupSpell.end() ; ) + { + if (itr->second < 0) { - sLog.outErrorDb("Spell %u listed in `spell_group` is not first rank of spell", spell_id); - continue; + if (groups.find(abs(itr->second)) == groups.end()) + { + sLog.outErrorDb("SpellGroup id %u listed in `spell_groups` does not exist", abs(itr->second)); + mSpellGroupSpell.erase(itr++); + } + else + ++itr; } - - if (IsSpellMemberOfSpellGroup(spell_id, (SpellGroup)group_id)) + else { - sLog.outErrorDb("Spell %u listed in `spell_group` is added twice to one group %u", spell_id, group_id); - continue; + SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->second); + + if (!spellInfo) + { + sLog.outErrorDb("Spell %u listed in `spell_group` does not exist", itr->second); + mSpellGroupSpell.erase(itr++); + } + else if (GetSpellRank(itr->second) > 1) + { + sLog.outErrorDb("Spell %u listed in `spell_group` is not first rank of spell", itr->second); + mSpellGroupSpell.erase(itr++); + } + else + ++itr; } - mSpellSpellGroup.insert(SpellSpellGroupMap::value_type(spell_id, (SpellGroup)group_id)); - mSpellGroupSpell.insert(SpellGroupSpellMap::value_type((SpellGroup)group_id, spell_id)); + } - ++count; - } while( result->NextRow() ); + for (std::set<uint32>::iterator groupItr = groups.begin() ; groupItr != groups.end() ; ++groupItr) + { + std::set<uint32> spells; + GetSetOfSpellsInSpellGroup(SpellGroup(*groupItr), spells); + + for (std::set<uint32>::iterator spellItr = spells.begin() ; spellItr != spells.end() ; ++spellItr) + { + ++count; + mSpellSpellGroup.insert(SpellSpellGroupMap::value_type(*spellItr, SpellGroup(*groupItr))); + } + } sLog.outString(); sLog.outString( ">> Loaded %u spell group definitions", count ); } -void SpellMgr::LoadSpellStackMasks() +void SpellMgr::LoadSpellGroupStackRules() { - mSpellStackMasks.clear(); // need for reload case + mSpellGroupStack.clear(); // need for reload case uint32 count = 0; - // 0 1 - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, mask FROM spell_stack_masks"); + // 0 1 + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT group_id, stack_rule FROM spell_group_stack_rules"); if( !result ) { @@ -1542,7 +1533,7 @@ void SpellMgr::LoadSpellStackMasks() bar.step(); sLog.outString(); - sLog.outString( ">> Loaded %u spell stacking masks definitions", count ); + sLog.outString( ">> Loaded %u spell group stack rules", count ); return; } @@ -1554,24 +1545,29 @@ void SpellMgr::LoadSpellStackMasks() bar.step(); - uint32 id = fields[0].GetUInt32(); - uint8 mask = fields[1].GetUInt32(); + uint32 group_id = fields[0].GetUInt32(); + uint8 stack_rule = fields[1].GetUInt32(); + if (stack_rule >= SPELL_GROUP_STACK_RULE_MAX) + { + sLog.outErrorDb("SpellGroupStackRule %u listed in `spell_group_stack_rules` does not exist", stack_rule); + continue; + } - SpellEntry const* spellInfo = sSpellStore.LookupEntry(id); + SpellGroupSpellMapBounds spellGroup = GetSpellGroupSpellMapBounds((SpellGroup)group_id); - if (!spellInfo) + if (spellGroup.first == spellGroup.second) { - sLog.outErrorDb("Spell %u listed in `spell_stack_masks` does not exist", id); + sLog.outErrorDb("SpellGroup id %u listed in `spell_group_stack_rules` does not exist", group_id); continue; } - mSpellStackMasks[id] = mask; + mSpellGroupStack[(SpellGroup)group_id] = (SpellGroupStackRule)stack_rule; ++count; } while( result->NextRow() ); sLog.outString(); - sLog.outString( ">> Loaded %u spell stacking masks definitions", count ); + sLog.outString( ">> Loaded %u spell group stack rules", count ); } void SpellMgr::LoadSpellThreats() @@ -3075,12 +3071,14 @@ bool SpellMgr::CanAurasStack(SpellEntry const *spellInfo_1, SpellEntry const *sp || sameCaster && IsSingleFromSpellSpecificPerCaster(spellSpec_1, spellSpec_2)) return false; - // Stacking Checks by family masks - uint32 spellSpecMask_1 = GetSpellStackMask(spellInfo_1->Id); - uint32 spellSpecMask_2 = GetSpellStackMask(spellInfo_2->Id); - if (spellSpecMask_1 && spellSpecMask_2) - if ((spellSpecMask_1 & spellSpecMask_2) != 0) + SpellGroupStackRule stackRule = CheckSpellGroupStackRules(spellInfo_1->Id, spellInfo_2->Id); + if (stackRule) + { + if (stackRule == SPELL_GROUP_STACK_RULE_EXCLUSIVE) return false; + if (sameCaster && stackRule == SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER) + return false; + } if(spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName) return true; @@ -3092,18 +3090,8 @@ bool SpellMgr::CanAurasStack(SpellEntry const *spellInfo_1, SpellEntry const *sp return true; // check same periodic auras - for (uint32 i = 0; i < 3; ++i) + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - // area auras should not stack (shaman totem) - if(spellInfo_1->Effect[i] != SPELL_EFFECT_APPLY_AURA - && spellInfo_1->Effect[i] != SPELL_EFFECT_PERSISTENT_AREA_AURA) - continue; - - // not channeled AOE effects should not stack (blizzard should, but Consecration should not) - if((IsAreaEffectTarget[spellInfo_1->EffectImplicitTargetA[i]] || IsAreaEffectTarget[spellInfo_1->EffectImplicitTargetB[i]]) - && !IsChanneledSpell(spellInfo_1)) - continue; - switch(spellInfo_1->EffectApplyAuraName[i]) { // DOT or HOT from different casters will stack @@ -3157,7 +3145,7 @@ bool SpellMgr::CanAurasStack(SpellEntry const *spellInfo_1, SpellEntry const *sp spellInfo_2 = sSpellStore.LookupEntry(spellId_2); //if spells do not have the same effect or aura or miscvalue, they will stack - for (uint32 i = 0; i < 3; ++i) + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) if(spellInfo_1->Effect[i] != spellInfo_2->Effect[i] || spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i] || spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i]) // paladin resist aura diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index a204789f7da..36ad5d9c3bd 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -145,7 +145,6 @@ enum SpellSpecific { SPELL_SPECIFIC_NORMAL = 0, SPELL_SPECIFIC_SEAL = 1, - SPELL_SPECIFIC_BLESSING = 2, SPELL_SPECIFIC_AURA = 3, SPELL_SPECIFIC_STING = 4, SPELL_SPECIFIC_CURSE = 5, @@ -155,13 +154,8 @@ enum SpellSpecific SPELL_SPECIFIC_MAGE_ARMOR = 9, SPELL_SPECIFIC_ELEMENTAL_SHIELD = 10, SPELL_SPECIFIC_MAGE_POLYMORPH = 11, - SPELL_SPECIFIC_POSITIVE_SHOUT = 12, SPELL_SPECIFIC_JUDGEMENT = 13, - SPELL_SPECIFIC_BATTLE_ELIXIR = 14, - SPELL_SPECIFIC_GUARDIAN_ELIXIR = 15, - SPELL_SPECIFIC_FLASK_ELIXIR = 16, SPELL_SPECIFIC_WARLOCK_CORRUPTION= 17, - SPELL_SPECIFIC_WELL_FED = 18, SPELL_SPECIFIC_FOOD = 19, SPELL_SPECIFIC_DRINK = 20, SPELL_SPECIFIC_FOOD_AND_DRINK = 21, @@ -173,8 +167,6 @@ enum SpellSpecific SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT = 27, SPELL_SPECIFIC_HAND = 28, SPELL_SPECIFIC_PHASE = 29, - SPELL_SPECIFIC_BLESSING_OF_MIGHT = 30, - SPELL_SPECIFIC_BATTLE_SHOUT = 31 }; #define SPELL_LINKED_MAX_SPELLS 200000 @@ -639,19 +631,30 @@ enum SpellGroup SPELL_GROUP_ELIXIR_GUARDIAN = 2, SPELL_GROUP_ELIXIR_UNSTABLE = 3, SPELL_GROUP_ELIXIR_SHATTRATH = 4, - SPELL_GROUP_WELL_FED = 5, + SPELL_GROUP_CORE_RANGE_MAX = 5, }; -// spell_id, group_id -typedef std::multimap<uint32, SpellGroup> SpellSpellGroupMap; +#define SPELL_GROUP_DB_RANGE_MIN 1000 + +// spell_id, group_id // native if true, inherited if false +typedef std::multimap<uint32, SpellGroup > SpellSpellGroupMap; typedef std::pair<SpellSpellGroupMap::const_iterator,SpellSpellGroupMap::const_iterator> SpellSpellGroupMapBounds; // group_id, spell_id -typedef std::multimap<SpellGroup, uint32> SpellGroupSpellMap; +typedef std::multimap<SpellGroup, int32> SpellGroupSpellMap; typedef std::pair<SpellGroupSpellMap::const_iterator,SpellGroupSpellMap::const_iterator> SpellGroupSpellMapBounds; +enum SpellGroupStackRule +{ + SPELL_GROUP_STACK_RULE_DEFAULT = 0, + SPELL_GROUP_STACK_RULE_EXCLUSIVE = 1, + SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER = 2, +}; +#define SPELL_GROUP_STACK_RULE_MAX 3 + +typedef std::map<SpellGroup, SpellGroupStackRule> SpellGroupStackMap; + typedef std::map<uint32, uint16> SpellThreatMap; -typedef std::map<uint32, uint32> SpellStackMaskMap; // Spell script target related declarations (accessed using SpellMgr functions) enum SpellScriptTargetType @@ -889,46 +892,73 @@ class SpellMgr { return SpellGroupSpellMapBounds(mSpellGroupSpell.lower_bound(group_id),mSpellGroupSpell.upper_bound(group_id)); } - SpellSpecific GetSpellElixirSpecific(uint32 spellid) const + void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells) const { - SpellSpecific spec = SPELL_SPECIFIC_NORMAL; - SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds(spellid); - for ( SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second ; ++itr) + std::set<SpellGroup> usedGroups; + GetSetOfSpellsInSpellGroup(group_id, foundSpells, usedGroups); + } + void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells, std::set<SpellGroup>& usedGroups) const + { + if (usedGroups.find(group_id) != usedGroups.end()) + return; + usedGroups.insert(group_id); + + SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds(group_id); + for ( SpellGroupSpellMap::const_iterator itr = groupSpell.first; itr != groupSpell.second ; ++itr) { - if (itr->second == SPELL_GROUP_ELIXIR_BATTLE - || itr->second == SPELL_GROUP_ELIXIR_GUARDIAN) + if (itr->second < 0) { - if (spec) - { - spec = SPELL_SPECIFIC_FLASK_ELIXIR; - break; - } - else if (itr->second == SPELL_GROUP_ELIXIR_BATTLE) - spec = SPELL_SPECIFIC_BATTLE_ELIXIR; - else if (itr->second == SPELL_GROUP_ELIXIR_GUARDIAN) - spec = SPELL_SPECIFIC_GUARDIAN_ELIXIR; + SpellGroup currGroup = (SpellGroup)abs(itr->second); + GetSetOfSpellsInSpellGroup(currGroup, foundSpells, usedGroups); + } + else + { + foundSpells.insert(itr->second); } } - return spec; } - // Used for stacking in spellmgr, and possibly in cancast checks - SpellStackMaskMap const& GetSpellStackMasksMap() const { return mSpellStackMasks; } - uint32 GetSpellStackMask(uint32 spellid) const + SpellGroupStackRule CheckSpellGroupStackRules(uint32 spellid_1, uint32 spellid_2) const { - SpellStackMaskMap::const_iterator itr = mSpellStackMasks.find(spellid); - if(itr!=mSpellStackMasks.end()) - return itr->second; - - // Not found, try lookup for 1 spell rank if exist - if (uint32 rank_1 = GetFirstSpellInChain(spellid)) + spellid_1 = GetFirstSpellInChain(spellid_1); + spellid_2 = GetFirstSpellInChain(spellid_2); + // find SpellGroups which are common for both spells + SpellSpellGroupMapBounds spellGroup1 = GetSpellSpellGroupMapBounds(spellid_1); + std::set<SpellGroup> groups; + for ( SpellSpellGroupMap::const_iterator itr = spellGroup1.first; itr != spellGroup1.second ; ++itr) { - SpellStackMaskMap::const_iterator itr2 = mSpellStackMasks.find(rank_1); - if(itr2 != mSpellStackMasks.end()) - return itr2->second; + if (IsSpellMemberOfSpellGroup(spellid_2, itr->second)) + { + bool add = true; + SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds(itr->second); + for ( SpellGroupSpellMap::const_iterator itr2 = groupSpell.first; itr2 != groupSpell.second ; ++itr2) + { + if (itr2->second < 0) + { + SpellGroup currGroup = (SpellGroup)abs(itr2->second); + if (IsSpellMemberOfSpellGroup(spellid_1, currGroup) && IsSpellMemberOfSpellGroup(spellid_2, currGroup)) + { + add = false; + break; + } + } + } + if (add) + groups.insert(itr->second); + } } - return 0x0; + SpellGroupStackRule rule = SPELL_GROUP_STACK_RULE_DEFAULT; + + for (std::set<SpellGroup>::iterator itr = groups.begin() ; itr!= groups.end() ; ++itr) + { + SpellGroupStackMap::const_iterator found = mSpellGroupStack.find(*itr); + if (found != mSpellGroupStack.end()) + rule = found->second; + if (rule) + break; + } + return rule; } uint16 GetSpellThreat(uint32 spellid) const @@ -1072,19 +1102,12 @@ class SpellMgr uint8 IsHighRankOfSpell(uint32 spell1,uint32 spell2) const { - SpellChainMap::const_iterator itr = mSpellChains.find(spell1); + SpellChainMap::const_iterator itr1 = mSpellChains.find(spell1); + SpellChainMap::const_iterator itr2 = mSpellChains.find(spell2); - uint32 rank2 = GetSpellRank(spell2); - - // not ordered correctly by rank value - if(itr == mSpellChains.end() || !rank2 || itr->second.rank <= rank2) - return false; - - // check present in same rank chain - for (; itr != mSpellChains.end(); itr = mSpellChains.find(itr->second.prev)) - if(itr->second.prev==spell2) + if (itr1->second.first == itr2->second.first) + if (itr1->second.rank <= itr2->second.rank) return true; - return false; } @@ -1264,7 +1287,7 @@ class SpellMgr void LoadPetLevelupSpellMap(); void LoadPetDefaultSpells(); void LoadSpellAreas(); - void LoadSpellStackMasks(); + void LoadSpellGroupStackRules(); private: bool _isPositiveSpell(uint32 spellId, bool deep) const; @@ -1286,7 +1309,7 @@ class SpellMgr SpellPetAuraMap mSpellPetAuraMap; SpellCustomAttribute mSpellCustomAttr; SpellLinkedMap mSpellLinkedMap; - SpellStackMaskMap mSpellStackMasks; + SpellGroupStackMap mSpellGroupStack; SpellEnchantProcEventMap mSpellEnchantProcEventMap; EnchantCustomAttribute mEnchantCustomAttr; PetLevelupSpellMap mPetLevelupSpellMap; diff --git a/src/game/World.cpp b/src/game/World.cpp index 9f38e10e471..f23d4a23d22 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1311,7 +1311,7 @@ void World::SetInitialWorldSettings() sLog.outString("Loading Spell Required Data..."); spellmgr.LoadSpellRequired(); - sLog.outString("Loading Spell Elixir types..."); + sLog.outString("Loading Spell Group types..."); spellmgr.LoadSpellGroups(); sLog.outString("Loading Spell Learn Skills..."); @@ -1329,8 +1329,8 @@ void World::SetInitialWorldSettings() sLog.outString("Loading Aggro Spells Definitions..."); spellmgr.LoadSpellThreats(); - sLog.outString("Loading Spell Stacking masks..."); - spellmgr.LoadSpellStackMasks(); + sLog.outString("Loading Spell Group Stack Rules..."); + spellmgr.LoadSpellGroupStackRules(); sLog.outString("Loading NPC Texts..."); objmgr.LoadGossipText(); |