mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-17 16:10:49 +01:00
@@ -41,6 +41,7 @@ struct SpellHistory::PersistenceHelper<Player>
|
|||||||
if (!sSpellMgr->GetSpellInfo(*spellId))
|
if (!sSpellMgr->GetSpellInfo(*spellId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
cooldownEntry->SpellId = *spellId;
|
||||||
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[2].GetUInt32()));
|
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[2].GetUInt32()));
|
||||||
cooldownEntry->ItemId = fields[1].GetUInt32();
|
cooldownEntry->ItemId = fields[1].GetUInt32();
|
||||||
cooldownEntry->CategoryId = fields[3].GetUInt32();
|
cooldownEntry->CategoryId = fields[3].GetUInt32();
|
||||||
@@ -72,6 +73,7 @@ struct SpellHistory::PersistenceHelper<Pet>
|
|||||||
if (!sSpellMgr->GetSpellInfo(*spellId))
|
if (!sSpellMgr->GetSpellInfo(*spellId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
cooldownEntry->SpellId = *spellId;
|
||||||
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[1].GetUInt32()));
|
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[1].GetUInt32()));
|
||||||
cooldownEntry->ItemId = 0;
|
cooldownEntry->ItemId = 0;
|
||||||
cooldownEntry->CategoryId = fields[2].GetUInt32();
|
cooldownEntry->CategoryId = fields[2].GetUInt32();
|
||||||
@@ -280,32 +282,7 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
|
|||||||
int32 cooldown = -1;
|
int32 cooldown = -1;
|
||||||
int32 categoryCooldown = -1;
|
int32 categoryCooldown = -1;
|
||||||
|
|
||||||
// some special item spells without correct cooldown in SpellInfo
|
GetCooldownDurations(spellInfo, itemId, &cooldown, &categoryId, &categoryCooldown);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::time_point curTime = Clock::now();
|
Clock::time_point curTime = Clock::now();
|
||||||
Clock::time_point catrecTime;
|
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*/)
|
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
|
// Send activate cooldown timer (possible 0) at client side
|
||||||
if (Player* player = GetPlayerOwner())
|
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);
|
WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
|
||||||
data << uint32(spellInfo->Id);
|
data << uint32(spellInfo->Id);
|
||||||
data << uint64(_owner->GetGUID());
|
data << uint64(_owner->GetGUID());
|
||||||
player->SendDirectMessage(&data);
|
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*/)
|
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& cooldownEntry = _spellCooldowns[spellId];
|
||||||
|
cooldownEntry.SpellId = spellId;
|
||||||
cooldownEntry.CooldownEnd = cooldownEnd;
|
cooldownEntry.CooldownEnd = cooldownEnd;
|
||||||
cooldownEntry.ItemId = itemId;
|
cooldownEntry.ItemId = itemId;
|
||||||
cooldownEntry.CategoryId = categoryId;
|
cooldownEntry.CategoryId = categoryId;
|
||||||
@@ -478,21 +471,7 @@ bool SpellHistory::HasCooldown(SpellInfo const* spellInfo, uint32 itemId /*= 0*/
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
uint32 category = 0;
|
uint32 category = 0;
|
||||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId))
|
GetCooldownDurations(spellInfo, itemId, nullptr, &itemId, nullptr);
|
||||||
{
|
|
||||||
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();
|
|
||||||
|
|
||||||
if (!category)
|
if (!category)
|
||||||
return false;
|
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()
|
void SpellHistory::SaveCooldownStateBeforeDuel()
|
||||||
{
|
{
|
||||||
_spellCooldownsBeforeDuel = _spellCooldowns;
|
_spellCooldownsBeforeDuel = _spellCooldowns;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
|
|
||||||
struct CooldownEntry
|
struct CooldownEntry
|
||||||
{
|
{
|
||||||
|
uint32 SpellId = 0;
|
||||||
Clock::time_point CooldownEnd;
|
Clock::time_point CooldownEnd;
|
||||||
uint32 ItemId = 0;
|
uint32 ItemId = 0;
|
||||||
uint32 CategoryId = 0;
|
uint32 CategoryId = 0;
|
||||||
@@ -135,6 +136,8 @@ private:
|
|||||||
typedef std::unordered_map<uint32, uint32> PacketCooldowns;
|
typedef std::unordered_map<uint32, uint32> PacketCooldowns;
|
||||||
void BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns) const;
|
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;
|
Unit* _owner;
|
||||||
CooldownStorageType _spellCooldowns;
|
CooldownStorageType _spellCooldowns;
|
||||||
CooldownStorageType _spellCooldownsBeforeDuel;
|
CooldownStorageType _spellCooldownsBeforeDuel;
|
||||||
|
|||||||
@@ -1343,6 +1343,15 @@ class spell_dk_raise_dead : public SpellScriptLoader
|
|||||||
GetCaster()->CastSpell(targets, spellInfo, NULL, TRIGGERED_FULL_MASK);
|
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
|
void Register() override
|
||||||
{
|
{
|
||||||
OnCheckCast += SpellCheckCastFn(spell_dk_raise_dead_SpellScript::CheckCast);
|
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);
|
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_1, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||||
OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY);
|
OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY);
|
||||||
|
AfterCast += SpellCastFn(spell_dk_raise_dead_SpellScript::OverrideCooldown);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user