mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-18 22:19:54 -04:00
[7363] Propertly set cooldown at server side for category spells at cooldown event send to client. Author: VladimirMangos
Also support item dependent cooldown set propetly at cooldown event send to client.
Last will used in follow potion cooldown delay in combat patch.
--HG--
branch : trunk
This commit is contained in:
+86
-12
@@ -18030,6 +18030,88 @@ void Player::UpdatePvP(bool state, bool ovrride)
|
||||
}
|
||||
}
|
||||
|
||||
void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell)
|
||||
{
|
||||
// init cooldown values
|
||||
uint32 cat = 0;
|
||||
int32 rec = -1;
|
||||
int32 catrec = -1;
|
||||
|
||||
// some special item spells without correct cooldown in SpellInfo
|
||||
// cooldown information stored in item prototype
|
||||
// This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client.
|
||||
|
||||
if(itemId)
|
||||
{
|
||||
if(ItemPrototype const* proto = ObjectMgr::GetItemPrototype(itemId))
|
||||
{
|
||||
for(int idx = 0; idx < 5; ++idx)
|
||||
{
|
||||
if(proto->Spells[idx].SpellId == spellInfo->Id)
|
||||
{
|
||||
cat = proto->Spells[idx].SpellCategory;
|
||||
rec = proto->Spells[idx].SpellCooldown;
|
||||
catrec = proto->Spells[idx].SpellCategoryCooldown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if no cooldown found above then base at DBC data
|
||||
if(rec < 0 && catrec < 0)
|
||||
{
|
||||
cat = spellInfo->Category;
|
||||
rec = spellInfo->RecoveryTime;
|
||||
catrec = spellInfo->CategoryRecoveryTime;
|
||||
}
|
||||
|
||||
// shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
|
||||
// prevent 0 cooldowns set by another way
|
||||
if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(spellInfo) && spellInfo->Id != SPELL_ID_AUTOSHOT))
|
||||
rec = GetAttackTime(RANGED_ATTACK);
|
||||
|
||||
// Now we have cooldown data (if found any), time to apply mods
|
||||
if(rec > 0)
|
||||
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell);
|
||||
|
||||
if(catrec > 0)
|
||||
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell);
|
||||
|
||||
// replace negative cooldowns by 0
|
||||
if (rec < 0) rec = 0;
|
||||
if (catrec < 0) catrec = 0;
|
||||
|
||||
// no cooldown after applying spell mods
|
||||
if( rec == 0 && catrec == 0)
|
||||
return;
|
||||
|
||||
time_t curTime = time(NULL);
|
||||
|
||||
time_t catrecTime = catrec ? curTime+catrec/IN_MILISECONDS : 0; // in secs
|
||||
time_t recTime = rec ? curTime+rec/IN_MILISECONDS : catrecTime;// in secs
|
||||
|
||||
// self spell cooldown
|
||||
if(recTime > 0)
|
||||
AddSpellCooldown(spellInfo->Id, itemId, recTime);
|
||||
|
||||
// category spells
|
||||
if (catrec > 0)
|
||||
{
|
||||
SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat);
|
||||
if(i_scstore != sSpellCategoryStore.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;
|
||||
|
||||
AddSpellCooldown(*i_scset, itemId, catrecTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time)
|
||||
{
|
||||
SpellCooldown sc;
|
||||
@@ -18038,20 +18120,12 @@ void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time)
|
||||
m_spellCooldowns[spellid] = sc;
|
||||
}
|
||||
|
||||
void Player::SendCooldownEvent(SpellEntry const *spellInfo)
|
||||
void Player::SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId, Spell* spell)
|
||||
{
|
||||
if ( !(spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) )
|
||||
return;
|
||||
// start cooldowns at server side, if any
|
||||
AddSpellAndCategoryCooldowns(spellInfo,itemId,spell);
|
||||
|
||||
// Get spell cooldown
|
||||
int32 cooldown = GetSpellRecoveryTime(spellInfo);
|
||||
// Apply spellmods
|
||||
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, cooldown);
|
||||
if (cooldown < 0)
|
||||
cooldown = 0;
|
||||
// Add cooldown
|
||||
AddSpellCooldown(spellInfo->Id, 0, time(NULL) + cooldown / IN_MILISECONDS);
|
||||
// Send activate
|
||||
// Send activate cooldown timer (possible 0) at client side
|
||||
WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8));
|
||||
data << spellInfo->Id;
|
||||
data << GetGUID();
|
||||
|
||||
+2
-1
@@ -1491,8 +1491,9 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
time_t t = time(NULL);
|
||||
return itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0;
|
||||
}
|
||||
void AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell = NULL);
|
||||
void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time);
|
||||
void SendCooldownEvent(SpellEntry const *spellInfo);
|
||||
void SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId = 0, Spell* spell = NULL);
|
||||
void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs );
|
||||
void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); }
|
||||
void RemoveArenaSpellCooldowns();
|
||||
|
||||
+1
-79
@@ -2440,85 +2440,7 @@ void Spell::SendSpellCooldown()
|
||||
return;
|
||||
}
|
||||
|
||||
// init cooldown values
|
||||
uint32 cat = 0;
|
||||
int32 rec = -1;
|
||||
int32 catrec = -1;
|
||||
|
||||
// some special item spells without correct cooldown in SpellInfo
|
||||
// cooldown information stored in item prototype
|
||||
// This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client.
|
||||
|
||||
if(m_CastItem)
|
||||
{
|
||||
ItemPrototype const* proto = m_CastItem->GetProto();
|
||||
if(proto)
|
||||
{
|
||||
for(int idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx)
|
||||
{
|
||||
if(proto->Spells[idx].SpellId == m_spellInfo->Id)
|
||||
{
|
||||
cat = proto->Spells[idx].SpellCategory;
|
||||
rec = proto->Spells[idx].SpellCooldown;
|
||||
catrec = proto->Spells[idx].SpellCategoryCooldown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if no cooldown found above then base at DBC data
|
||||
if(rec < 0 && catrec < 0)
|
||||
{
|
||||
cat = m_spellInfo->Category;
|
||||
rec = m_spellInfo->RecoveryTime;
|
||||
catrec = m_spellInfo->CategoryRecoveryTime;
|
||||
}
|
||||
|
||||
// shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
|
||||
// prevent 0 cooldowns set by another way
|
||||
if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(m_spellInfo) && m_spellInfo->Id != SPELL_ID_AUTOSHOT))
|
||||
rec = _player->GetAttackTime(RANGED_ATTACK);
|
||||
|
||||
// Now we have cooldown data (if found any), time to apply mods
|
||||
if(rec > 0)
|
||||
_player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, rec, this);
|
||||
|
||||
if(catrec > 0)
|
||||
_player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, catrec, this);
|
||||
|
||||
// replace negative cooldowns by 0
|
||||
if (rec < 0) rec = 0;
|
||||
if (catrec < 0) catrec = 0;
|
||||
|
||||
// no cooldown after applying spell mods
|
||||
if( rec == 0 && catrec == 0)
|
||||
return;
|
||||
|
||||
time_t curTime = time(NULL);
|
||||
|
||||
time_t catrecTime = catrec ? curTime+catrec/IN_MILISECONDS : 0;
|
||||
time_t recTime = rec ? curTime+rec/IN_MILISECONDS : catrecTime;
|
||||
|
||||
// self spell cooldown
|
||||
if(recTime > 0)
|
||||
_player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, recTime);
|
||||
|
||||
// category spells
|
||||
if (catrec > 0)
|
||||
{
|
||||
SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat);
|
||||
if(i_scstore != sSpellCategoryStore.end())
|
||||
{
|
||||
for(SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
|
||||
{
|
||||
if(*i_scset == m_spellInfo->Id) // skip main spell, already handled above
|
||||
continue;
|
||||
|
||||
_player->AddSpellCooldown(*i_scset, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
_player->AddSpellAndCategoryCooldowns(m_spellInfo,m_CastItem ? m_CastItem->GetEntry() : 0, this);
|
||||
}
|
||||
|
||||
void Spell::update(uint32 difftime)
|
||||
|
||||
@@ -976,6 +976,7 @@ void Aura::_RemoveAura()
|
||||
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
|
||||
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
|
||||
((Player*)caster)->SendCooldownEvent(GetSpellProto());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4457,6 +4457,7 @@ void Unit::RemoveGameObject(GameObject* gameObj, bool del)
|
||||
SpellEntry const* createBySpell = sSpellStore.LookupEntry(gameObj->GetSpellId());
|
||||
// Need activate spell use for owner
|
||||
if (createBySpell && createBySpell->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
|
||||
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
|
||||
((Player*)this)->SendCooldownEvent(createBySpell);
|
||||
}
|
||||
gameObj->SetOwnerGUID(0);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "7362"
|
||||
#define REVISION_NR "7363"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
||||
Reference in New Issue
Block a user