diff options
author | Shauren <shauren.trinity@gmail.com> | 2015-11-15 00:31:17 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2015-11-15 00:31:17 +0100 |
commit | ecbbcc8972f43376c65cb726c37cf777ee968f66 (patch) | |
tree | 82d16f060f882bd68bcc1c4bac39a4516bb14228 | |
parent | f01ef901efab7f5b705948880c79eaf23061791e (diff) |
Core/Spells: Fixed Raise Dead cooldown
Closes #15862
-rw-r--r-- | src/server/game/Spells/SpellHistory.cpp | 111 | ||||
-rw-r--r-- | src/server/game/Spells/SpellHistory.h | 3 | ||||
-rw-r--r-- | src/server/scripts/Spells/spell_dk.cpp | 10 |
3 files changed, 79 insertions, 45 deletions
diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index f8593fc8005..0dd4ff8c100 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -41,6 +41,7 @@ struct SpellHistory::PersistenceHelper<Player> if (!sSpellMgr->GetSpellInfo(*spellId)) return false; + cooldownEntry->SpellId = *spellId; cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[2].GetUInt32())); cooldownEntry->ItemId = fields[1].GetUInt32(); cooldownEntry->CategoryId = fields[3].GetUInt32(); @@ -72,6 +73,7 @@ struct SpellHistory::PersistenceHelper<Pet> if (!sSpellMgr->GetSpellInfo(*spellId)) return false; + cooldownEntry->SpellId = *spellId; cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[1].GetUInt32())); cooldownEntry->ItemId = 0; cooldownEntry->CategoryId = fields[2].GetUInt32(); @@ -280,32 +282,7 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel int32 cooldown = -1; int32 categoryCooldown = -1; - // some special item spells without correct cooldown in SpellInfo - // cooldown information stored in item prototype - if (itemId) - { - if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId)) - { - for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx) - { - if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id) - { - categoryId = proto->Spells[idx].SpellCategory; - cooldown = proto->Spells[idx].SpellCooldown; - categoryCooldown = proto->Spells[idx].SpellCategoryCooldown; - break; - } - } - } - } - - // if no cooldown found above then base at DBC data - if (cooldown < 0 && categoryCooldown < 0) - { - categoryId = spellInfo->GetCategory(); - cooldown = spellInfo->RecoveryTime; - categoryCooldown = spellInfo->CategoryRecoveryTime; - } + GetCooldownDurations(spellInfo, itemId, &cooldown, &categoryId, &categoryCooldown); Clock::time_point curTime = Clock::now(); Clock::time_point catrecTime; @@ -381,23 +358,39 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel void SpellHistory::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /*= 0*/, Spell* spell /*= nullptr*/, bool startCooldown /*= true*/) { - // start cooldowns at server side, if any - if (startCooldown) - StartCooldown(spellInfo, itemId, spell); - // Send activate cooldown timer (possible 0) at client side if (Player* player = GetPlayerOwner()) { + uint32 category = spellInfo->GetCategory(); + GetCooldownDurations(spellInfo, itemId, nullptr, &category, nullptr); + + auto categoryItr = _categoryCooldowns.find(category); + if (categoryItr != _categoryCooldowns.end() && categoryItr->second->SpellId != spellInfo->Id) + { + WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8); + data << uint32(categoryItr->second->SpellId); + data << uint64(_owner->GetGUID()); + player->SendDirectMessage(&data); + + if (startCooldown) + StartCooldown(sSpellMgr->EnsureSpellInfo(categoryItr->second->SpellId), itemId, spell); + } + WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8); data << uint32(spellInfo->Id); data << uint64(_owner->GetGUID()); player->SendDirectMessage(&data); } + + // start cooldowns at server side, if any + if (startCooldown) + StartCooldown(spellInfo, itemId, spell); } 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.SpellId = spellId; cooldownEntry.CooldownEnd = cooldownEnd; cooldownEntry.ItemId = itemId; cooldownEntry.CategoryId = categoryId; @@ -478,21 +471,7 @@ bool SpellHistory::HasCooldown(SpellInfo const* spellInfo, uint32 itemId /*= 0*/ return true; uint32 category = 0; - if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId)) - { - for (uint32 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) - { - if (uint32(itemTemplate->Spells[i].SpellId) == spellInfo->Id) - { - category = itemTemplate->Spells[i].SpellCategory; - break; - } - } - } - - if (!category) - category = spellInfo->GetCategory(); - + GetCooldownDurations(spellInfo, itemId, nullptr, &itemId, nullptr); if (!category) return false; @@ -651,6 +630,48 @@ void SpellHistory::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCoo } } +void SpellHistory::GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, int32* cooldown, uint32* categoryId, int32* categoryCooldown) +{ + ASSERT(cooldown || categoryId || categoryCooldown); + int32 tmpCooldown = -1; + uint32 tmpCategoryId = 0; + int32 tmpCategoryCooldown = -1; + + // some special item spells without correct cooldown in SpellInfo + // cooldown information stored in item prototype + if (itemId) + { + if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId)) + { + for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx) + { + if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id) + { + tmpCooldown = proto->Spells[idx].SpellCooldown; + tmpCategoryId = proto->Spells[idx].SpellCategory; + tmpCategoryCooldown = proto->Spells[idx].SpellCategoryCooldown; + break; + } + } + } + } + + // if no cooldown found above then base at DBC data + if (tmpCooldown < 0 && tmpCategoryCooldown < 0) + { + tmpCooldown = spellInfo->RecoveryTime; + tmpCategoryId = spellInfo->GetCategory(); + tmpCategoryCooldown = spellInfo->CategoryRecoveryTime; + } + + if (cooldown) + *cooldown = tmpCooldown; + if (categoryId) + *categoryId = tmpCategoryId; + if (categoryCooldown) + *categoryCooldown = tmpCategoryCooldown; +} + void SpellHistory::SaveCooldownStateBeforeDuel() { _spellCooldownsBeforeDuel = _spellCooldowns; diff --git a/src/server/game/Spells/SpellHistory.h b/src/server/game/Spells/SpellHistory.h index 6a1da28f08f..db65cd50c3e 100644 --- a/src/server/game/Spells/SpellHistory.h +++ b/src/server/game/Spells/SpellHistory.h @@ -38,6 +38,7 @@ public: struct CooldownEntry { + uint32 SpellId = 0; Clock::time_point CooldownEnd; uint32 ItemId = 0; uint32 CategoryId = 0; @@ -135,6 +136,8 @@ private: typedef std::unordered_map<uint32, uint32> PacketCooldowns; void BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns) const; + static void GetCooldownDurations(SpellInfo const* spellInfo, uint32 itemId, int32* cooldown, uint32* categoryId, int32* categoryCooldown); + Unit* _owner; CooldownStorageType _spellCooldowns; CooldownStorageType _spellCooldownsBeforeDuel; diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index cd0052c24bc..88271dc7139 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -1343,6 +1343,15 @@ class spell_dk_raise_dead : public SpellScriptLoader GetCaster()->CastSpell(targets, spellInfo, NULL, TRIGGERED_FULL_MASK); } + void OverrideCooldown() + { + // Because the ghoul is summoned by one of triggered spells SendCooldownEvent is not sent for this spell + // but the client has locked it by itself so we need some link between this spell and the real spell summoning. + // Luckily such link already exists - spell category + // This starts infinite category cooldown which can later be used by SendCooldownEvent to send packet for this spell + GetCaster()->GetSpellHistory()->StartCooldown(GetSpellInfo(), 0, nullptr, true); + } + void Register() override { OnCheckCast += SpellCheckCastFn(spell_dk_raise_dead_SpellScript::CheckCast); @@ -1351,6 +1360,7 @@ class spell_dk_raise_dead : public SpellScriptLoader OnCast += SpellCastFn(spell_dk_raise_dead_SpellScript::ConsumeReagents); OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY); + AfterCast += SpellCastFn(spell_dk_raise_dead_SpellScript::OverrideCooldown); } private: |