diff options
-rw-r--r-- | sql/updates/7280_world_spell_group.sql | 2 | ||||
-rw-r--r-- | sql/updates/7283_world_command.sql | 4 | ||||
-rw-r--r-- | sql/updates/7283_world_spell_group.sql | 126 | ||||
-rw-r--r-- | sql/updates/7283_world_spell_group_stack_rules.sql | 20 | ||||
-rw-r--r-- | sql/updates/7283_world_spell_stack_masks.sql | 1 | ||||
-rw-r--r-- | sql/world.sql | 174 | ||||
-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 |
13 files changed, 479 insertions, 202 deletions
diff --git a/sql/updates/7280_world_spell_group.sql b/sql/updates/7280_world_spell_group.sql index ee19c117ffe..c3082a64e9f 100644 --- a/sql/updates/7280_world_spell_group.sql +++ b/sql/updates/7280_world_spell_group.sql @@ -184,4 +184,4 @@ INSERT INTO `spell_group` (`id`, `spell_id`) VALUES (5, 18194), (5, 18222), (5, 22730), -(5, 25661);
\ No newline at end of file +(5, 25661); diff --git a/sql/updates/7283_world_command.sql b/sql/updates/7283_world_command.sql new file mode 100644 index 00000000000..86fa40f3a84 --- /dev/null +++ b/sql/updates/7283_world_command.sql @@ -0,0 +1,4 @@ +DELETE FROM `command` WHERE `name` = 'reload spell_group_stack_rules'; +DELETE FROM `command` WHERE `name` = 'reload spell_elixir'; +DELETE FROM `command` WHERE `name` = 'reload spell_stack_masks'; +INSERT INTO `command` VALUES ('reload spell_group_stack_rules','3','Syntax: .reload spell_group\nReload spell_group_stack_rules table.'); diff --git a/sql/updates/7283_world_spell_group.sql b/sql/updates/7283_world_spell_group.sql new file mode 100644 index 00000000000..2a059a5c13c --- /dev/null +++ b/sql/updates/7283_world_spell_group.sql @@ -0,0 +1,126 @@ +ALTER TABLE spell_group +MODIFY spell_id INT(11) NOT NULL DEFAULT 0; +DELETE FROM spell_group WHERE id IN(5, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011); +INSERT INTO spell_group (id, spell_id) VALUES + -- Well Fed +(1001, 19705), +(1001, 19706), +(1001, 19708), +(1001, 19709), +(1001, 19710), +(1001, 19711), +(1001, 24799), +(1001, 24870), +(1001, 25694), +(1001, 25941), +(1001, 33254), +(1001, 33256), +(1001, 33257), +(1001, 33259), +(1001, 33261), +(1001, 33263), +(1001, 33265), +(1001, 33268), +(1001, 33272), +(1001, 35272), +(1001, 40323), +(1001, 42293), +(1001, 43764), +(1001, 43771), +(1001, 44097), +(1001, 44098), +(1001, 44099), +(1001, 44100), +(1001, 44101), +(1001, 44102), +(1001, 44104), +(1001, 44105), +(1001, 44106), +(1001, 45245), +(1001, 45619), +(1001, 46682), +(1001, 46687), +(1001, 46899), +(1001, 53284), +(1001, 57079), +(1001, 57097), +(1001, 57100), +(1001, 57102), +(1001, 57107), +(1001, 57111), +(1001, 57139), +(1001, 57286), +(1001, 57288), +(1001, 57291), +(1001, 57294), +(1001, 57325), +(1001, 57327), +(1001, 57329), +(1001, 57332), +(1001, 57334), +(1001, 57356), +(1001, 57358), +(1001, 57360), +(1001, 57363), +(1001, 57365), +(1001, 57367), +(1001, 57371), +(1001, 57373), +(1001, 57399), +(1001, 58468), +(1001, 58479), +(1001, 59230), +(1001, 59690), +(1001, 59699), +(1001, 62349), +(1001, 64057), +(1001, 65247), +(1001, 65365), +(1001, 65410), +(1001, 65412), +(1001, 65414), +(1001, 65415), +(1001, 65416), +(1001, 66623), +(1001, 66624), +(1001, 69559), +(1001, 18125), +(1001, 18141), +(1001, 23697), + -- Blessing of Might +(1002, 19740), +(1002, 25782), +(1002, 56520), +-- Battle Shout +(1003, 6673), +-- Blessing of Might, Battle Shout +(1004, -1002), +(1004, -1003), +-- Blessing of Wisdom +(1005, 19742), +(1005, 25894), +(1005, 56521), +-- Blessing of Kings +(1006, 20217), +(1006, 25898), +(1006, 43223), +(1006, 56525), +(1006, 58054), +-- Blessing of Sanctuary +(1007, 20911), +(1007, 25899), +-- Blessing of Protection +(1008, 41450), +(1008, 23415), +-- Blessing of Light +(1009, 32770), +-- Blessings +(1010, -1002), +(1010, -1005), +(1010, -1006), +(1010, -1007), +(1010, -1008), +(1010, -1009), +-- Commanding shout, Battle Shout +(1011, 469), +(1011, -1003); diff --git a/sql/updates/7283_world_spell_group_stack_rules.sql b/sql/updates/7283_world_spell_group_stack_rules.sql new file mode 100644 index 00000000000..8b316be24eb --- /dev/null +++ b/sql/updates/7283_world_spell_group_stack_rules.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS `spell_group_stack_rules`; +CREATE TABLE `spell_group_stack_rules` ( + `group_id` INT(11) UNSIGNED NOT NULL DEFAULT 0, + `stack_rule` TINYINT(3) NOT NULL DEFAULT 0, + PRIMARY KEY (`group_id`) +)ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT INTO spell_group_stack_rules (group_id, stack_rule) VALUES +(1, 1), +(2, 1), +(1001, 1), +(1002, 1), +(1003, 1), +(1004, 1), +(1005, 1), +(1006, 1), +(1007, 1), +(1008, 1), +(1009, 1), +(1010, 2), +(1011, 1); diff --git a/sql/updates/7283_world_spell_stack_masks.sql b/sql/updates/7283_world_spell_stack_masks.sql new file mode 100644 index 00000000000..24cebf178de --- /dev/null +++ b/sql/updates/7283_world_spell_stack_masks.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS `spell_stack_masks`; diff --git a/sql/world.sql b/sql/world.sql index 05336b33a0b..53c19169687 100644 --- a/sql/world.sql +++ b/sql/world.sql @@ -607,6 +607,7 @@ INSERT INTO `command` VALUES ('reload spell_bonus_data','3','Syntax: .reload spell_bonus_data\nReload spell_bonus_data table.'), ('reload spell_disabled','3','Syntax: .reload spell_disabled\nReload spell_disabled table.'), ('reload spell_group','3','Syntax: .reload spell_group\nReload spell_group table.'), +('reload spell_group_stack_rules','3','Syntax: .reload spell_group\nReload spell_group_stack_rules table.'), ('reload spell_learn_spell','3','Syntax: .reload spell_learn_spell\nReload spell_learn_spell table.'), ('reload spell_linked_spell','3','Usage: .reload spell_linked_spell\r\nReloads the spell_linked_spell DB table.'), ('reload spell_loot_template','3','Syntax: .reload spell_loot_template\nReload spell_loot_template table.'), @@ -5100,17 +5101,17 @@ DROP TABLE IF EXISTS `spell_group`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `spell_group` ( `id` int(11) unsigned NOT NULL DEFAULT 0, - `spell_id` int(11) unsigned NOT NULL DEFAULT 0, + `spell_id` int(11) NOT NULL DEFAULT 0, PRIMARY KEY (`id`, `spell_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell System'; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `spell_elixir` +-- Dumping data for table `spell_group` -- LOCK TABLES `spell_group` WRITE; -/*!40000 ALTER TABLE `spell_elixir` DISABLE KEYS */; +/*!40000 ALTER TABLE `spell_group` DISABLE KEYS */; INSERT INTO `spell_group` (`id`, `spell_id`) VALUES -- SPELL_GROUP_ELIXIR_BATTLE (1, 2367), @@ -5284,14 +5285,128 @@ INSERT INTO `spell_group` (`id`, `spell_id`) VALUES (4, 41611), (4, 46837), (4, 46839), - -- SPELL_GROUP_WELL_FED -(5, 18191), -(5, 18192), -(5, 18193), -(5, 18194), -(5, 18222), -(5, 22730), -(5, 25661); + -- Well Fed +(1001, 19705), +(1001, 19706), +(1001, 19708), +(1001, 19709), +(1001, 19710), +(1001, 19711), +(1001, 24799), +(1001, 24870), +(1001, 25694), +(1001, 25941), +(1001, 33254), +(1001, 33256), +(1001, 33257), +(1001, 33259), +(1001, 33261), +(1001, 33263), +(1001, 33265), +(1001, 33268), +(1001, 33272), +(1001, 35272), +(1001, 40323), +(1001, 42293), +(1001, 43764), +(1001, 43771), +(1001, 44097), +(1001, 44098), +(1001, 44099), +(1001, 44100), +(1001, 44101), +(1001, 44102), +(1001, 44104), +(1001, 44105), +(1001, 44106), +(1001, 45245), +(1001, 45619), +(1001, 46682), +(1001, 46687), +(1001, 46899), +(1001, 53284), +(1001, 57079), +(1001, 57097), +(1001, 57100), +(1001, 57102), +(1001, 57107), +(1001, 57111), +(1001, 57139), +(1001, 57286), +(1001, 57288), +(1001, 57291), +(1001, 57294), +(1001, 57325), +(1001, 57327), +(1001, 57329), +(1001, 57332), +(1001, 57334), +(1001, 57356), +(1001, 57358), +(1001, 57360), +(1001, 57363), +(1001, 57365), +(1001, 57367), +(1001, 57371), +(1001, 57373), +(1001, 57399), +(1001, 58468), +(1001, 58479), +(1001, 59230), +(1001, 59690), +(1001, 59699), +(1001, 62349), +(1001, 64057), +(1001, 65247), +(1001, 65365), +(1001, 65410), +(1001, 65412), +(1001, 65414), +(1001, 65415), +(1001, 65416), +(1001, 66623), +(1001, 66624), +(1001, 69559), +(1001, 18125), +(1001, 18141), +(1001, 23697), + -- Blessing of Might +(1002, 19740), +(1002, 25782), +(1002, 56520), +-- Battle Shout +(1003, 6673), +-- Blessing of Might, Battle Shout +(1004, -1002), +(1004, -1003), +-- Blessing of Wisdom +(1005, 19742), +(1005, 25894), +(1005, 56521), +-- Blessing of Kings +(1006, 20217), +(1006, 25898), +(1006, 43223), +(1006, 56525), +(1006, 58054), +-- Blessing of Sanctuary +(1007, 20911), +(1007, 25899), +-- Blessing of Protection +(1008, 41450), +(1008, 23415), +-- Blessing of Light +(1009, 32770), +-- Blessings +(1010, -1002), +(1010, -1005), +(1010, -1006), +(1010, -1007), +(1010, -1008), +(1010, -1009), +-- Commanding shout, Battle Shout +(1011, 469), +(1011, -1003); /*!40000 ALTER TABLE `spell_group` ENABLE KEYS */; UNLOCK TABLES; @@ -6761,26 +6876,41 @@ LOCK TABLES `spell_scripts` WRITE; UNLOCK TABLES; -- --- Table structure for table `spell_stack_masks` +-- Table structure for table `spell_group_stack_rules` -- -DROP TABLE IF EXISTS `spell_stack_masks`; +DROP TABLE IF EXISTS `spell_group_stack_rules`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `spell_stack_masks` ( - `id` int(32) unsigned NOT NULL default '0', - `mask` int(64) unsigned NOT NULL default '0', - PRIMARY KEY (`id`) +DROP TABLE IF EXISTS `spell_group_stack_rules`; +CREATE TABLE `spell_group_stack_rules` ( + `group_id` INT(11) UNSIGNED NOT NULL DEFAULT 0, + `stack_rule` TINYINT(3) NOT NULL DEFAULT 0, + PRIMARY KEY (`group_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Dumping data for table `spell_stack_masks` +-- Dumping data for table `spell_group_stack_rules` -- -LOCK TABLES `spell_stack_masks` WRITE; -/*!40000 ALTER TABLE `spell_stack_masks` DISABLE KEYS */; -/*!40000 ALTER TABLE `spell_stack_masks` ENABLE KEYS */; +LOCK TABLES `spell_group_stack_rules` WRITE; +/*!40000 ALTER TABLE `spell_group_stack_rules` DISABLE KEYS */; +INSERT INTO spell_group_stack_rules (`group_id`, `stack_rule`) VALUES +(1, 1), +(2, 1), +(1001, 1), +(1002, 1), +(1003, 1), +(1004, 1), +(1005, 1), +(1006, 1), +(1007, 1), +(1008, 1), +(1009, 1), +(1010, 2), +(1011, 1); +/*!40000 ALTER TABLE `spell_group_stack_rules` ENABLE KEYS */; UNLOCK TABLES; -- @@ -6797,7 +6927,7 @@ CREATE TABLE `spell_ranks` ( ) ENGINE=MYISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Spell Rank Data'; -- --- Dumping data for table `spell_stack_masks` +-- Dumping data for table `spell_ranks` -- LOCK TABLES `spell_ranks` WRITE; 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(); |