[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:
VladimirMangos 2009-03-01 05:42:47 +03:00
parent 2b9eeb782e
commit ed6123c804
6 changed files with 92 additions and 93 deletions

View file

@ -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();

View file

@ -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();

View file

@ -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)

View file

@ -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());
} }
} }

View file

@ -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);

View file

@ -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__