Core/Spells: Improved spell category cooldown handling
* Category cooldown is stored with the spell that started the cooldown (and only resetting cooldown on that spell will clear cooldowns on entire category - this fully mirrors client behavior) * This significantly reduces the amount of data saved to database for cooldowns * Spell casts from items that have a different category specified than on spell will now check for cooldown during the cast Closes #15349
This commit is contained in:
@@ -1397,6 +1397,8 @@ CREATE TABLE `character_spell_cooldown` (
|
||||
`spell` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Spell Identifier',
|
||||
`item` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Item Identifier',
|
||||
`time` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`categoryId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Spell category Id',
|
||||
`categoryEnd` int(10) unsigned NOT NULL DEFAULT '0';
|
||||
PRIMARY KEY (`guid`,`spell`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -2849,6 +2851,8 @@ CREATE TABLE `pet_spell_cooldown` (
|
||||
`guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier, Low part',
|
||||
`spell` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Spell Identifier',
|
||||
`time` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`categoryId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Spell category Id',
|
||||
`categoryEnd` int(10) unsigned NOT NULL DEFAULT '0';
|
||||
PRIMARY KEY (`guid`,`spell`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -3071,7 +3075,7 @@ CREATE TABLE `updates` (
|
||||
|
||||
LOCK TABLES `updates` WRITE;
|
||||
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
|
||||
INSERT INTO `updates` VALUES ('2014_10_20_00_characters.sql','A5882DA0979CF4DAE33DA011EBAA006C24BE7230','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_00_characters.sql','E2AC4758133EE19B7F08464A445802154D1261C8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_01_characters.sql','20029E6323D9773B32C34D84FFED1711CC60F09F','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_02_characters.sql','8A7A16886EE71E7ACDDB3DDA6D0ECAC2FD2FDCA8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_24_00_characters.sql','D008FE81AE844FCA686439D6ECC5108FB0DD1EB9','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_25_00_characters.sql','A39C7BE46686B54776BDAB9D7A882D91EDEC51A4','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_26_00_characters.sql','C787954CC35FE34B4101FDE6527F14C027F4947C','ARCHIVED','2015-03-21 15:55:55',0),('2014_11_12_00_characters.sql','B160BB2313F1BD5F3B076A5A9279DC10D4796E34','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_23_00_characters.sql','3D9D648B2387B357F4BD090B33F80682F7924882','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_28_00_characters.sql','5362922FF4483A336311D73082A5727309CD9219','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_31_00_characters.sql','498DDF2DD936CF156D74A8208DC93DCE9FCAB5AA','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_02_00_characters.sql','E5940BE836F253982E07930120422E598D08BDE1','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_10_00_characters.sql','30796056C8623699B2FE1BF626A19D38262E9284','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_16_00_characters.sql','96642760A54C8D799AAFE438049A63AA521656F2','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_27_00_characters.sql','EB710E3EB9F2CAFD84AB62CDC84E898403A80A4F','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_00_characters.sql','405BEB4ED207DC6076442A37EE2AFB1F21E274A0','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_01_characters.sql','35F582D4F33BF55D1685A1BA89273ED895FD09C5','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_17_00_characters.sql','8D21FC5A55BF8B55D6DCDCE5F02CF2B640230E94','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_10_00_characters.sql','E565B89B145C340067742DFF2DEF1B74F5F1BD4E','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_01_characters.sql','20BD68468C57FCF7E665B4DA185DCD52FACE8B3F','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_02_characters.sql','0296995DCD3676BA9AE6024CA7C91C5F39D927A3','ARCHIVED','2015-03-21 15:56:46',0),('2015_03_29_00_characters.sql','95D6A46BB746A8BD3EE3FE2086DF1A07F7C33B92','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_21_00_characters.sql','F2032B9BF4EDA7EDE5065554724ED392FD91657D','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_28_00_characters.sql','949F62DB3A3461D420A1230ECF7A6A3ED6435703','ARCHIVED','2015-05-02 15:43:06',0),('2015_05_08_00_characters.sql','0F14B7821618D1C872625B6EDDAA9A667B211167','ARCHIVED','2015-07-10 19:32:17',0),('2015_05_22_00_characters.sql','65B82152413FAB23BE413656E59A486A74447FF7','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_08_00_characters.sql','DAB25360ACB5244C8F8E6214CF6BD97160588A5B','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_11_00_characters.sql','B421B6C0E57BD0FD587071358863D9DABF4BA849','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_12_00_characters.sql','E98E7FD61EF6426E7EDE8ED9AD8C15D8D7132589','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_28_00_characters.sql','0711BC3A658D189EF71B0CB68DCFF2E9B781C4A0','RELEASED','2015-07-29 16:23:56',0),('2015_08_08_00_characters.sql','EA12BB2DC24FAF2300A96D0888A45BBEA158D5DC','RELEASED','2015-08-08 16:34:07',0),('2015_08_12_00_characters.sql','4FD7F89FE5DA51D4E0C33E520719986AA3EBD31B','RELEASED','2015-08-12 12:35:20',0);
|
||||
INSERT INTO `updates` VALUES ('2014_10_20_00_characters.sql','A5882DA0979CF4DAE33DA011EBAA006C24BE7230','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_00_characters.sql','E2AC4758133EE19B7F08464A445802154D1261C8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_01_characters.sql','20029E6323D9773B32C34D84FFED1711CC60F09F','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_02_characters.sql','8A7A16886EE71E7ACDDB3DDA6D0ECAC2FD2FDCA8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_24_00_characters.sql','D008FE81AE844FCA686439D6ECC5108FB0DD1EB9','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_25_00_characters.sql','A39C7BE46686B54776BDAB9D7A882D91EDEC51A4','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_26_00_characters.sql','C787954CC35FE34B4101FDE6527F14C027F4947C','ARCHIVED','2015-03-21 15:55:55',0),('2014_11_12_00_characters.sql','B160BB2313F1BD5F3B076A5A9279DC10D4796E34','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_23_00_characters.sql','3D9D648B2387B357F4BD090B33F80682F7924882','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_28_00_characters.sql','5362922FF4483A336311D73082A5727309CD9219','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_31_00_characters.sql','498DDF2DD936CF156D74A8208DC93DCE9FCAB5AA','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_02_00_characters.sql','E5940BE836F253982E07930120422E598D08BDE1','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_10_00_characters.sql','30796056C8623699B2FE1BF626A19D38262E9284','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_16_00_characters.sql','96642760A54C8D799AAFE438049A63AA521656F2','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_27_00_characters.sql','EB710E3EB9F2CAFD84AB62CDC84E898403A80A4F','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_00_characters.sql','405BEB4ED207DC6076442A37EE2AFB1F21E274A0','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_01_characters.sql','35F582D4F33BF55D1685A1BA89273ED895FD09C5','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_17_00_characters.sql','8D21FC5A55BF8B55D6DCDCE5F02CF2B640230E94','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_10_00_characters.sql','E565B89B145C340067742DFF2DEF1B74F5F1BD4E','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_01_characters.sql','20BD68468C57FCF7E665B4DA185DCD52FACE8B3F','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_02_characters.sql','0296995DCD3676BA9AE6024CA7C91C5F39D927A3','ARCHIVED','2015-03-21 15:56:46',0),('2015_03_29_00_characters.sql','95D6A46BB746A8BD3EE3FE2086DF1A07F7C33B92','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_21_00_characters.sql','F2032B9BF4EDA7EDE5065554724ED392FD91657D','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_28_00_characters.sql','949F62DB3A3461D420A1230ECF7A6A3ED6435703','ARCHIVED','2015-05-02 15:43:06',0),('2015_05_08_00_characters.sql','0F14B7821618D1C872625B6EDDAA9A667B211167','ARCHIVED','2015-07-10 19:32:17',0),('2015_05_22_00_characters.sql','65B82152413FAB23BE413656E59A486A74447FF7','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_08_00_characters.sql','DAB25360ACB5244C8F8E6214CF6BD97160588A5B','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_11_00_characters.sql','B421B6C0E57BD0FD587071358863D9DABF4BA849','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_12_00_characters.sql','E98E7FD61EF6426E7EDE8ED9AD8C15D8D7132589','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_28_00_characters.sql','0711BC3A658D189EF71B0CB68DCFF2E9B781C4A0','RELEASED','2015-07-29 16:23:56',0),('2015_08_08_00_characters.sql','EA12BB2DC24FAF2300A96D0888A45BBEA158D5DC','RELEASED','2015-08-08 16:34:07',0),('2015_08_12_00_characters.sql','4FD7F89FE5DA51D4E0C33E520719986AA3EBD31B','RELEASED','2015-08-12 12:35:20',0),('2015_09_05_00_characters.sql','4C22BB29365BE4B6B95E64DAD84B63CA002304EA','RELEASED','2015-09-05 12:35:20',0),('2015_09_09_00_characters.sql','AFC32E693BC17CFD9A17919FE5317B8FE337ACAD','RELEASED','2015-09-09 12:35:20',0),('2015_09_10_00_characters.sql','4555A7F35C107E54C13D74D20F141039ED42943E','RELEASED','2015-09-10 22:50:42',0);
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE `character_spell_cooldown`
|
||||
ADD `categoryId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Spell category Id' AFTER `time`,
|
||||
ADD `categoryEnd` int(10) unsigned NOT NULL DEFAULT '0' AFTER `categoryId`;
|
||||
|
||||
ALTER TABLE `pet_spell_cooldown`
|
||||
ADD `categoryId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Spell category Id' AFTER `time`,
|
||||
ADD `categoryEnd` int(10) unsigned NOT NULL DEFAULT '0' AFTER `categoryId`;
|
||||
@@ -115,7 +115,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_SEL_MAIL_COUNT, "SELECT COUNT(*) FROM mail WHERE receiver = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SOCIALLIST, "SELECT friend, flags, note FROM character_social JOIN characters ON characters.guid = character_social.friend WHERE character_social.guid = ? AND deleteinfos_name IS NULL LIMIT 255", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS, "SELECT spell, item, time FROM character_spell_cooldown WHERE guid = ? AND time > UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS, "SELECT spell, item, time, categoryId, categoryEnd FROM character_spell_cooldown WHERE guid = ? AND time > UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SPELL_CHARGES, "SELECT categoryId, rechargeStart, rechargeEnd FROM character_spell_charges WHERE guid = ? AND rechargeEnd > UNIX_TIMESTAMP() ORDER BY rechargeEnd", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_DECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_GUILD_MEMBER, "SELECT guildid, rank FROM guild_member WHERE guid = ?", CONNECTION_BOTH);
|
||||
@@ -530,7 +530,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET knownTitles = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_RES_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET chosenTitle = 0 WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SPELL_COOLDOWNS, "DELETE FROM character_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_SPELL_COOLDOWN, "INSERT INTO character_spell_cooldown (guid, spell, item, time) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_SPELL_COOLDOWN, "INSERT INTO character_spell_cooldown (guid, spell, item, time, categoryId, categoryEnd) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SPELL_CHARGES, "DELETE FROM character_spell_charges WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_SPELL_CHARGES, "INSERT INTO character_spell_charges (guid, categoryId, rechargeStart, rechargeEnd) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER, "DELETE FROM characters WHERE guid = ?", CONNECTION_ASYNC);
|
||||
@@ -631,13 +631,13 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_SEL_PET_AURA, "SELECT casterGuid, spell, effectMask, recalculateMask, stackCount, maxDuration, remainTime, remainCharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_AURA_EFFECT, "SELECT casterGuid, spell, effectMask, effectIndex, amount, baseAmount FROM pet_aura_effect WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_SPELL, "SELECT spell, active FROM pet_spell WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_SPELL_COOLDOWN, "SELECT spell, time FROM pet_spell_cooldown WHERE guid = ? AND time > UNIX_TIMESTAMP()", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_SPELL_COOLDOWN, "SELECT spell, time, categoryId, categoryEnd FROM pet_spell_cooldown WHERE guid = ? AND time > UNIX_TIMESTAMP()", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_DECLINED_NAME, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_PET_AURAS, "DELETE FROM pet_aura WHERE guid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_DEL_PET_AURA_EFFECTS, "DELETE FROM pet_aura_effect WHERE guid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_DEL_PET_SPELLS, "DELETE FROM pet_spell WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PET_SPELL_COOLDOWNS, "DELETE FROM pet_spell_cooldown WHERE guid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_INS_PET_SPELL_COOLDOWN, "INSERT INTO pet_spell_cooldown (guid, spell, time) VALUES (?, ?, ?)", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_INS_PET_SPELL_COOLDOWN, "INSERT INTO pet_spell_cooldown (guid, spell, time, categoryId, categoryEnd) VALUES (?, ?, ?, ?, ?)", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_PET_SPELL_CHARGES, "SELECT categoryId, rechargeStart, rechargeEnd FROM pet_spell_charges WHERE guid = ? AND rechargeEnd > UNIX_TIMESTAMP() ORDER BY rechargeEnd", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_PET_SPELL_CHARGES, "DELETE FROM pet_spell_charges WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PET_SPELL_CHARGES, "INSERT INTO pet_spell_charges (guid, categoryId, rechargeStart, rechargeEnd) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
@@ -130,7 +130,6 @@ DBCStorage<SkillRaceClassInfoEntry> sSkillRaceClassInfoStore(SkillRaceCl
|
||||
SkillRaceClassInfoMap SkillRaceClassInfoBySkill;
|
||||
DBCStorage<SpellAuraOptionsEntry> sSpellAuraOptionsStore(SpellAuraOptionsfmt);
|
||||
DBCStorage<SpellCategoriesEntry> sSpellCategoriesStore(SpellCategoriesfmt);
|
||||
SpellCategoryStore sSpellsByCategoryStore;
|
||||
DBCStorage<SpellCategoryEntry> sSpellCategoryStore(SpellCategoryfmt);
|
||||
DBCStorage<SpellCooldownsEntry> sSpellCooldownsStore(SpellCooldownsfmt);
|
||||
DBCStorage<SpellEffectEntry> sSpellEffectStore(SpellEffectfmt);
|
||||
@@ -447,16 +446,6 @@ void LoadDBCStores(const std::string& dataPath, uint32 defaultLocale)
|
||||
if (sSkillLineStore.LookupEntry(entry->SkillID))
|
||||
SkillRaceClassInfoBySkill.emplace(entry->SkillID, entry);
|
||||
|
||||
for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
|
||||
{
|
||||
SpellEntry const* spell = sSpellStore.LookupEntry(i);
|
||||
if (!spell)
|
||||
continue;
|
||||
|
||||
if (SpellCategoriesEntry const* category = sSpellCategoriesStore.LookupEntry(spell->CategoriesID))
|
||||
sSpellsByCategoryStore[category->Category].insert(i);
|
||||
}
|
||||
|
||||
for (uint32 j = 0; j < sSpellEffectScalingStore.GetNumRows(); j++)
|
||||
{
|
||||
SpellEffectScalingEntry const* spellEffectScaling = sSpellEffectScalingStore.LookupEntry(j);
|
||||
|
||||
@@ -185,7 +185,6 @@ extern DBCStorage<SkillLineEntry> sSkillLineStore;
|
||||
extern DBCStorage<SkillRaceClassInfoEntry> sSkillRaceClassInfoStore;
|
||||
extern DBCStorage<SpellAuraOptionsEntry> sSpellAuraOptionsStore;
|
||||
extern DBCStorage<SpellCategoriesEntry> sSpellCategoriesStore;
|
||||
extern SpellCategoryStore sSpellsByCategoryStore;
|
||||
extern DBCStorage<SpellCategoryEntry> sSpellCategoryStore;
|
||||
extern DBCStorage<SpellCooldownsEntry> sSpellCooldownsStore;
|
||||
extern DBCStorage<SpellEffectEntry> sSpellEffectStore;
|
||||
|
||||
@@ -1093,9 +1093,6 @@ struct SpellCategoriesEntry
|
||||
uint32 ChargeCategory; // 9
|
||||
};
|
||||
|
||||
typedef std::set<uint32> SpellCategorySet;
|
||||
typedef std::map<uint32, SpellCategorySet > SpellCategoryStore;
|
||||
|
||||
struct SpellCategoryEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
|
||||
@@ -22779,7 +22779,7 @@ void Player::ApplyEquipCooldown(Item* pItem)
|
||||
continue;
|
||||
|
||||
// Don't replace longer cooldowns by equip cooldown if we have any.
|
||||
if (GetSpellHistory()->GetRemainingCooldown(effectData->SpellID) > 30 * IN_MILLISECONDS)
|
||||
if (GetSpellHistory()->GetRemainingCooldown(sSpellMgr->AssertSpellInfo(effectData->SpellID)) > 30 * IN_MILLISECONDS)
|
||||
continue;
|
||||
|
||||
GetSpellHistory()->AddCooldown(effectData->SpellID, pItem->GetEntry(), std::chrono::seconds(30));
|
||||
|
||||
@@ -1485,7 +1485,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
|
||||
{
|
||||
// This additional check is needed to add a minimal delay before cooldown in in effect
|
||||
// to allow all bubbles broken by a single damage source proc mana return
|
||||
if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetId()) <= 11)
|
||||
if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetSpellInfo()) <= 11)
|
||||
break;
|
||||
}
|
||||
else // and add if needed
|
||||
|
||||
@@ -4698,7 +4698,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
return SPELL_FAILED_NOT_READY;
|
||||
}
|
||||
|
||||
if (!m_caster->GetSpellHistory()->IsReady(m_spellInfo))
|
||||
if (!m_caster->GetSpellHistory()->IsReady(m_spellInfo, m_castItemEntry))
|
||||
{
|
||||
if (m_triggeredByAuraSpell)
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
|
||||
@@ -42,6 +42,8 @@ struct SpellHistory::PersistenceHelper<Player>
|
||||
|
||||
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[2].GetUInt32()));
|
||||
cooldownEntry->ItemId = fields[1].GetUInt32();
|
||||
cooldownEntry->CategoryId = fields[3].GetUInt32();
|
||||
cooldownEntry->CategoryEnd = Clock::from_time_t(time_t(fields[4].GetUInt32()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,6 +63,8 @@ struct SpellHistory::PersistenceHelper<Player>
|
||||
stmt->setUInt32(index++, cooldown.first);
|
||||
stmt->setUInt32(index++, cooldown.second.ItemId);
|
||||
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
|
||||
stmt->setUInt32(index++, cooldown.second.CategoryId);
|
||||
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CategoryEnd)));
|
||||
}
|
||||
|
||||
static void WriteCharge(PreparedStatement* stmt, uint8& index, uint32 chargeCategory, ChargeEntry const& charge)
|
||||
@@ -89,6 +93,8 @@ struct SpellHistory::PersistenceHelper<Pet>
|
||||
|
||||
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[1].GetUInt32()));
|
||||
cooldownEntry->ItemId = 0;
|
||||
cooldownEntry->CategoryId = fields[2].GetUInt32();
|
||||
cooldownEntry->CategoryEnd = Clock::from_time_t(time_t(fields[3].GetUInt32()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -107,6 +113,8 @@ struct SpellHistory::PersistenceHelper<Pet>
|
||||
{
|
||||
stmt->setUInt32(index++, cooldown.first);
|
||||
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
|
||||
stmt->setUInt32(index++, cooldown.second.CategoryId);
|
||||
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CategoryEnd)));
|
||||
}
|
||||
|
||||
static void WriteCharge(PreparedStatement* stmt, uint8& index, uint32 chargeCategory, ChargeEntry const& charge)
|
||||
@@ -129,7 +137,11 @@ void SpellHistory::LoadFromDB(PreparedQueryResult cooldownsResult, PreparedQuery
|
||||
uint32 spellId;
|
||||
CooldownEntry cooldown;
|
||||
if (StatementInfo::ReadCooldown(cooldownsResult->Fetch(), &spellId, &cooldown))
|
||||
{
|
||||
_spellCooldowns[spellId] = cooldown;
|
||||
if (cooldown.CategoryId)
|
||||
_categoryCooldowns[cooldown.CategoryId] = &_spellCooldowns[spellId];
|
||||
}
|
||||
|
||||
} while (cooldownsResult->NextRow());
|
||||
}
|
||||
@@ -191,10 +203,18 @@ void SpellHistory::Update()
|
||||
{
|
||||
SQLTransaction t;
|
||||
Clock::time_point now = Clock::now();
|
||||
for (auto itr = _categoryCooldowns.begin(); itr != _categoryCooldowns.end();)
|
||||
{
|
||||
if (itr->second->CategoryEnd < now)
|
||||
itr = _categoryCooldowns.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
|
||||
for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
|
||||
{
|
||||
if (itr->second.CooldownEnd < now)
|
||||
itr = _spellCooldowns.erase(itr);
|
||||
itr = EraseCooldown(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
@@ -212,7 +232,7 @@ void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, Item const* item,
|
||||
HandleCooldowns(spellInfo, item ? item->GetEntry() : 0, spell);
|
||||
}
|
||||
|
||||
void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, uint32 ItemID, Spell* spell /*= nullptr*/)
|
||||
void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, uint32 itemID, Spell* spell /*= nullptr*/)
|
||||
{
|
||||
if (ConsumeCharge(spellInfo->ChargeCategoryEntry))
|
||||
return;
|
||||
@@ -220,11 +240,11 @@ void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, uint32 ItemID, Sp
|
||||
if (Player* player = _owner->ToPlayer())
|
||||
{
|
||||
// potions start cooldown until exiting combat
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(ItemID))
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemID))
|
||||
{
|
||||
if (itemTemplate->IsPotion() || spellInfo->IsCooldownStartedOnEvent())
|
||||
{
|
||||
player->SetLastPotionId(ItemID);
|
||||
player->SetLastPotionId(itemID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -233,16 +253,16 @@ void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, uint32 ItemID, Sp
|
||||
if (spellInfo->IsCooldownStartedOnEvent() || spellInfo->IsPassive() || (spell && spell->IsIgnoringCooldowns()))
|
||||
return;
|
||||
|
||||
StartCooldown(spellInfo, ItemID, spell);
|
||||
StartCooldown(spellInfo, itemID, spell);
|
||||
}
|
||||
|
||||
bool SpellHistory::IsReady(SpellInfo const* spellInfo) const
|
||||
bool SpellHistory::IsReady(SpellInfo const* spellInfo, uint32 itemId /*= 0*/) const
|
||||
{
|
||||
if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
|
||||
if (IsSchoolLocked(spellInfo->GetSchoolMask()))
|
||||
return false;
|
||||
|
||||
if (HasCooldown(spellInfo->Id))
|
||||
if (HasCooldown(spellInfo->Id, itemId))
|
||||
return false;
|
||||
|
||||
if (!HasCharge(spellInfo->ChargeCategoryEntry))
|
||||
@@ -265,11 +285,9 @@ void SpellHistory::WritePacket(WorldPackets::Spells::SendSpellHistory* sendSpell
|
||||
Clock::time_point now = Clock::now();
|
||||
for (auto const& p : _spellCooldowns)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(p.first);
|
||||
WorldPackets::Spells::SpellHistoryEntry historyEntry;
|
||||
historyEntry.SpellID = p.first;
|
||||
historyEntry.ItemID = p.second.ItemId;
|
||||
historyEntry.Category = spellInfo->GetCategory();
|
||||
|
||||
if (p.second.OnHold)
|
||||
historyEntry.OnHold = true;
|
||||
@@ -279,10 +297,13 @@ void SpellHistory::WritePacket(WorldPackets::Spells::SendSpellHistory* sendSpell
|
||||
if (cooldownDuration.count() <= 0)
|
||||
continue;
|
||||
|
||||
if (spellInfo->GetCategory())
|
||||
historyEntry.CategoryRecoveryTime = uint32(cooldownDuration.count());
|
||||
else
|
||||
historyEntry.RecoveryTime = uint32(cooldownDuration.count());
|
||||
historyEntry.RecoveryTime = uint32(cooldownDuration.count());
|
||||
std::chrono::milliseconds categoryDuration = std::chrono::duration_cast<std::chrono::milliseconds>(p.second.CategoryEnd - now);
|
||||
if (categoryDuration.count() > 0)
|
||||
{
|
||||
historyEntry.Category = p.second.CategoryId;
|
||||
historyEntry.CategoryRecoveryTime = uint32(categoryDuration.count());
|
||||
}
|
||||
}
|
||||
|
||||
sendSpellHistory->Entries.push_back(historyEntry);
|
||||
@@ -324,7 +345,7 @@ void SpellHistory::WritePacket(WorldPackets::Pet::PetSpells* petSpells)
|
||||
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(p.first);
|
||||
WorldPackets::Pet::PetSpellCooldown petSpellCooldown;
|
||||
petSpellCooldown.SpellID = p.first;
|
||||
petSpellCooldown.Category = spellInfo->GetCategory();
|
||||
petSpellCooldown.Category = p.second.CategoryId;
|
||||
|
||||
if (!p.second.OnHold)
|
||||
{
|
||||
@@ -332,10 +353,10 @@ void SpellHistory::WritePacket(WorldPackets::Pet::PetSpells* petSpells)
|
||||
if (cooldownDuration.count() <= 0)
|
||||
continue;
|
||||
|
||||
if (spellInfo->GetCategory())
|
||||
petSpellCooldown.CategoryDuration = uint32(cooldownDuration.count());
|
||||
else
|
||||
petSpellCooldown.Duration = uint32(cooldownDuration.count());
|
||||
petSpellCooldown.Duration = uint32(cooldownDuration.count());
|
||||
std::chrono::milliseconds categoryDuration = std::chrono::duration_cast<std::chrono::milliseconds>(p.second.CategoryEnd - now);
|
||||
if (categoryDuration.count() > 0)
|
||||
petSpellCooldown.CategoryDuration = uint32(categoryDuration.count());
|
||||
}
|
||||
|
||||
petSpells->Cooldowns.push_back(historyEntry);
|
||||
@@ -471,7 +492,7 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
|
||||
// self spell cooldown
|
||||
if (recTime != curTime)
|
||||
{
|
||||
AddCooldown(spellInfo->Id, itemId, recTime, onHold);
|
||||
AddCooldown(spellInfo->Id, itemId, recTime, categoryId, catrecTime, onHold);
|
||||
|
||||
if (needsCooldownPacket)
|
||||
{
|
||||
@@ -485,22 +506,6 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// category spells
|
||||
if (categoryId && catrecTime != curTime)
|
||||
{
|
||||
SpellCategoryStore::const_iterator i_scstore = sSpellsByCategoryStore.find(categoryId);
|
||||
if (i_scstore != sSpellsByCategoryStore.end())
|
||||
{
|
||||
for (SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
|
||||
{
|
||||
if (*i_scset == spellInfo->Id) // skip main spell, already handled above
|
||||
continue;
|
||||
|
||||
AddCooldown(*i_scset, itemId, catrecTime, onHold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHistory::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /*= 0*/, Spell* spell /*= nullptr*/, bool startCooldown /*= true*/)
|
||||
@@ -509,43 +514,22 @@ void SpellHistory::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /
|
||||
if (startCooldown)
|
||||
StartCooldown(spellInfo, itemId, spell);
|
||||
|
||||
// Send activate cooldown timer (possible 0) at client side
|
||||
if (Player* player = GetPlayerOwner())
|
||||
{
|
||||
// Send activate cooldown timer (possible 0) at client side
|
||||
player->SendDirectMessage(WorldPackets::Spells::CooldownEvent(player != _owner, spellInfo->Id).Write());
|
||||
|
||||
uint32 category = spellInfo->GetCategory();
|
||||
if (category && spellInfo->CategoryRecoveryTime)
|
||||
{
|
||||
SpellCategoryStore::const_iterator ct = sSpellsByCategoryStore.find(category);
|
||||
if (ct != sSpellsByCategoryStore.end())
|
||||
{
|
||||
for (auto const& cooldownPair : _spellCooldowns)
|
||||
{
|
||||
uint32 categorySpell = cooldownPair.first;
|
||||
if (!ct->second.count(categorySpell))
|
||||
continue;
|
||||
|
||||
if (categorySpell == spellInfo->Id) // skip main spell, already handled above
|
||||
continue;
|
||||
|
||||
SpellInfo const* spellInfo2 = sSpellMgr->AssertSpellInfo(categorySpell);
|
||||
if (!spellInfo2->IsCooldownStartedOnEvent())
|
||||
continue;
|
||||
|
||||
player->SendDirectMessage(WorldPackets::Spells::CooldownEvent(player != _owner, categorySpell).Write());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHistory::AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, bool onHold /*= false*/)
|
||||
void SpellHistory::AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, uint32 categoryId, Clock::time_point categoryEnd, bool onHold /*= false*/)
|
||||
{
|
||||
CooldownEntry& cooldownEntry = _spellCooldowns[spellId];
|
||||
cooldownEntry.CooldownEnd = cooldownEnd;
|
||||
cooldownEntry.ItemId = itemId;
|
||||
cooldownEntry.CategoryId = categoryId;
|
||||
cooldownEntry.CategoryEnd = categoryEnd;
|
||||
cooldownEntry.OnHold = onHold;
|
||||
|
||||
if (categoryId)
|
||||
_categoryCooldowns[categoryId] = &cooldownEntry;
|
||||
}
|
||||
|
||||
void SpellHistory::ModifyCooldown(uint32 spellId, int32 cooldownModMs)
|
||||
@@ -559,7 +543,7 @@ void SpellHistory::ModifyCooldown(uint32 spellId, int32 cooldownModMs)
|
||||
if (itr->second.CooldownEnd + offset > now)
|
||||
itr->second.CooldownEnd += offset;
|
||||
else
|
||||
_spellCooldowns.erase(itr);
|
||||
EraseCooldown(itr);
|
||||
|
||||
if (Player* playerOwner = GetPlayerOwner())
|
||||
{
|
||||
@@ -594,7 +578,7 @@ void SpellHistory::ResetCooldown(CooldownStorageType::iterator& itr, bool update
|
||||
}
|
||||
}
|
||||
|
||||
itr = _spellCooldowns.erase(itr);
|
||||
itr = EraseCooldown(itr);
|
||||
}
|
||||
|
||||
void SpellHistory::ResetAllCooldowns()
|
||||
@@ -609,31 +593,69 @@ void SpellHistory::ResetAllCooldowns()
|
||||
SendClearCooldowns(cooldowns);
|
||||
}
|
||||
|
||||
_categoryCooldowns.clear();
|
||||
_spellCooldowns.clear();
|
||||
}
|
||||
|
||||
bool SpellHistory::HasCooldown(uint32 spellId) const
|
||||
bool SpellHistory::HasCooldown(SpellInfo const* spellInfo, uint32 itemId /*= 0*/) const
|
||||
{
|
||||
return _spellCooldowns.count(spellId) != 0;
|
||||
if (_spellCooldowns.count(spellInfo->Id) != 0)
|
||||
return true;
|
||||
|
||||
uint32 category = 0;
|
||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId))
|
||||
{
|
||||
for (ItemEffectEntry const* itemEffect : itemTemplate->Effects)
|
||||
{
|
||||
if (itemEffect->SpellID == spellInfo->Id)
|
||||
{
|
||||
category = itemEffect->Category;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!category)
|
||||
category = spellInfo->GetCategory();
|
||||
|
||||
if (!category)
|
||||
return false;
|
||||
|
||||
return _categoryCooldowns.count(category) != 0;
|
||||
}
|
||||
|
||||
uint32 SpellHistory::GetRemainingCooldown(uint32 spellId) const
|
||||
bool SpellHistory::HasCooldown(uint32 spellId, uint32 itemId /*= 0*/) const
|
||||
{
|
||||
auto itr = _spellCooldowns.find(spellId);
|
||||
if (itr == _spellCooldowns.end())
|
||||
return 0;
|
||||
return HasCooldown(sSpellMgr->AssertSpellInfo(spellId), itemId);
|
||||
}
|
||||
|
||||
uint32 SpellHistory::GetRemainingCooldown(SpellInfo const* spellInfo) const
|
||||
{
|
||||
Clock::time_point end;
|
||||
auto itr = _spellCooldowns.find(spellInfo->Id);
|
||||
if (itr != _spellCooldowns.end())
|
||||
end = itr->second.CooldownEnd;
|
||||
else
|
||||
{
|
||||
auto catItr = _categoryCooldowns.find(spellInfo->GetCategory());
|
||||
if (catItr == _categoryCooldowns.end())
|
||||
return 0;
|
||||
|
||||
end = catItr->second->CategoryEnd;
|
||||
}
|
||||
|
||||
Clock::time_point now = Clock::now();
|
||||
if (itr->second.CooldownEnd < now)
|
||||
if (end < now)
|
||||
return 0;
|
||||
|
||||
Clock::duration remaining = itr->second.CooldownEnd - now;
|
||||
Clock::duration remaining = end - now;
|
||||
return uint32(std::chrono::duration_cast<std::chrono::milliseconds>(remaining).count());
|
||||
}
|
||||
|
||||
void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTime)
|
||||
{
|
||||
Clock::time_point lockoutEnd = Clock::now() + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(lockoutTime));
|
||||
Clock::time_point now = Clock::now();
|
||||
Clock::time_point lockoutEnd = now + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(lockoutTime));
|
||||
for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
|
||||
if (SpellSchoolMask(1 << i) & schoolMask)
|
||||
_schoolLockouts[i] = lockoutEnd;
|
||||
@@ -671,10 +693,10 @@ void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTim
|
||||
if (spellInfo->PreventionType != SPELL_PREVENTION_TYPE_SILENCE)
|
||||
continue;
|
||||
|
||||
if ((schoolMask & spellInfo->GetSchoolMask()) && GetRemainingCooldown(spellId) < lockoutTime)
|
||||
if ((schoolMask & spellInfo->GetSchoolMask()) && GetRemainingCooldown(spellInfo) < lockoutTime)
|
||||
{
|
||||
spellCooldown.SpellCooldowns.emplace_back(spellId, lockoutTime);
|
||||
AddCooldown(spellId, 0, lockoutEnd);
|
||||
AddCooldown(spellId, 0, lockoutEnd, 0, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +46,11 @@ public:
|
||||
|
||||
struct CooldownEntry
|
||||
{
|
||||
CooldownEntry() : ItemId(0), OnHold(false) { }
|
||||
CooldownEntry(Clock::time_point endTime, uint32 itemId) : CooldownEnd(endTime), ItemId(itemId), OnHold(false) { }
|
||||
|
||||
Clock::time_point CooldownEnd;
|
||||
uint32 ItemId;
|
||||
bool OnHold;
|
||||
uint32 ItemId = 0;
|
||||
uint32 CategoryId = 0;
|
||||
Clock::time_point CategoryEnd;
|
||||
bool OnHold = false;
|
||||
};
|
||||
|
||||
struct ChargeEntry
|
||||
@@ -65,6 +64,7 @@ public:
|
||||
};
|
||||
|
||||
typedef std::unordered_map<uint32 /*spellId*/, CooldownEntry> CooldownStorageType;
|
||||
typedef std::unordered_map<uint32 /*categoryId*/, CooldownEntry*> CategoryCooldownStorageType;
|
||||
typedef std::unordered_map<uint32 /*categoryId*/, std::deque<ChargeEntry>> ChargeStorageType;
|
||||
typedef std::unordered_map<uint32 /*categoryId*/, Clock::time_point> GlobalCooldownStorageType;
|
||||
|
||||
@@ -79,8 +79,8 @@ public:
|
||||
void Update();
|
||||
|
||||
void HandleCooldowns(SpellInfo const* spellInfo, Item const* item, Spell* spell = nullptr);
|
||||
void HandleCooldowns(SpellInfo const* spellInfo, uint32 ItemID, Spell* spell = nullptr);
|
||||
bool IsReady(SpellInfo const* spellInfo) const;
|
||||
void HandleCooldowns(SpellInfo const* spellInfo, uint32 itemID, Spell* spell = nullptr);
|
||||
bool IsReady(SpellInfo const* spellInfo, uint32 itemId = 0) const;
|
||||
template<class PacketType>
|
||||
void WritePacket(PacketType* packet) const;
|
||||
|
||||
@@ -93,10 +93,11 @@ public:
|
||||
template<class Type, class Period>
|
||||
void AddCooldown(uint32 spellId, uint32 itemId, std::chrono::duration<Type, Period> cooldownDuration)
|
||||
{
|
||||
AddCooldown(spellId, itemId, Clock::now() + std::chrono::duration_cast<Clock::duration>(cooldownDuration));
|
||||
Clock::time_point now = Clock::now();
|
||||
AddCooldown(spellId, itemId, now + std::chrono::duration_cast<Clock::duration>(cooldownDuration), 0, now);
|
||||
}
|
||||
|
||||
void AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, bool onHold = false);
|
||||
void AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, uint32 categoryId, Clock::time_point categoryEnd, bool onHold = false);
|
||||
void ModifyCooldown(uint32 spellId, int32 cooldownModMs);
|
||||
void ResetCooldown(uint32 spellId, bool update = false);
|
||||
void ResetCooldown(CooldownStorageType::iterator& itr, bool update = false);
|
||||
@@ -121,8 +122,9 @@ public:
|
||||
}
|
||||
|
||||
void ResetAllCooldowns();
|
||||
bool HasCooldown(uint32 spellId) const;
|
||||
uint32 GetRemainingCooldown(uint32 spellId) const;
|
||||
bool HasCooldown(SpellInfo const* spellInfo, uint32 itemId = 0) const;
|
||||
bool HasCooldown(uint32 spellId, uint32 itemId = 0) const;
|
||||
uint32 GetRemainingCooldown(SpellInfo const* spellInfo) const;
|
||||
|
||||
// School lockouts
|
||||
void LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTime);
|
||||
@@ -145,9 +147,15 @@ public:
|
||||
private:
|
||||
Player* GetPlayerOwner() const;
|
||||
void SendClearCooldowns(std::vector<int32> const& cooldowns) const;
|
||||
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
|
||||
{
|
||||
_categoryCooldowns.erase(itr->second.CategoryId);
|
||||
return _spellCooldowns.erase(itr);
|
||||
}
|
||||
|
||||
Unit* _owner;
|
||||
CooldownStorageType _spellCooldowns;
|
||||
CategoryCooldownStorageType _categoryCooldowns;
|
||||
Clock::time_point _schoolLockouts[MAX_SPELL_SCHOOL];
|
||||
ChargeStorageType _categoryCharges;
|
||||
GlobalCooldownStorageType _globalCooldowns;
|
||||
|
||||
@@ -149,7 +149,7 @@ class spell_dk_anti_magic_shell : public SpellScriptLoader
|
||||
{
|
||||
// Cannot reduce cooldown by more than 50%
|
||||
int32 val = std::min(glyph->GetAmount(), int32(absorbedAmount) * 100 / maxHealth);
|
||||
player->GetSpellHistory()->ModifyCooldown(GetId(), -int32(player->GetSpellHistory()->GetRemainingCooldown(GetId()) * val / 100));
|
||||
player->GetSpellHistory()->ModifyCooldown(GetId(), -int32(player->GetSpellHistory()->GetRemainingCooldown(GetSpellInfo()) * val / 100));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user