mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
[7363] Propertly set cooldown at server side for category spells at cooldown event send to client.
Also support item dependent cooldown set propetly at cooldown event send to client. Last will used in follow potion cooldown delay in combat patch.
This commit is contained in:
parent
2b9eeb782e
commit
ed6123c804
6 changed files with 92 additions and 93 deletions
|
|
@ -17626,6 +17626,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)
|
void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time)
|
||||||
{
|
{
|
||||||
SpellCooldown sc;
|
SpellCooldown sc;
|
||||||
|
|
@ -17634,20 +17716,12 @@ void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time)
|
||||||
m_spellCooldowns[spellid] = sc;
|
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) )
|
// start cooldowns at server side, if any
|
||||||
return;
|
AddSpellAndCategoryCooldowns(spellInfo,itemId,spell);
|
||||||
|
|
||||||
// Get spell cooldown
|
// Send activate cooldown timer (possible 0) at client side
|
||||||
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
|
|
||||||
WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8));
|
WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8));
|
||||||
data << spellInfo->Id;
|
data << spellInfo->Id;
|
||||||
data << GetGUID();
|
data << GetGUID();
|
||||||
|
|
|
||||||
|
|
@ -1491,8 +1491,9 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
return itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0;
|
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 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 ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs );
|
||||||
void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); }
|
void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); }
|
||||||
void RemoveArenaSpellCooldowns();
|
void RemoveArenaSpellCooldowns();
|
||||||
|
|
|
||||||
|
|
@ -2528,85 +2528,7 @@ void Spell::SendSpellCooldown()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// init cooldown values
|
_player->AddSpellAndCategoryCooldowns(m_spellInfo,m_CastItem ? m_CastItem->GetEntry() : 0, this);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spell::update(uint32 difftime)
|
void Spell::update(uint32 difftime)
|
||||||
|
|
|
||||||
|
|
@ -1117,6 +1117,7 @@ void Aura::_RemoveAura()
|
||||||
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
|
if(caster && caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
{
|
||||||
if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
|
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());
|
((Player*)caster)->SendCooldownEvent(GetSpellProto());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4078,6 +4078,7 @@ void Unit::RemoveGameObject(GameObject* gameObj, bool del)
|
||||||
SpellEntry const* createBySpell = sSpellStore.LookupEntry(gameObj->GetSpellId());
|
SpellEntry const* createBySpell = sSpellStore.LookupEntry(gameObj->GetSpellId());
|
||||||
// Need activate spell use for owner
|
// Need activate spell use for owner
|
||||||
if (createBySpell && createBySpell->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
|
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);
|
((Player*)this)->SendCooldownEvent(createBySpell);
|
||||||
}
|
}
|
||||||
gameObj->SetOwnerGUID(0);
|
gameObj->SetOwnerGUID(0);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "7362"
|
#define REVISION_NR "7363"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue