Skip to content

Commit

Permalink
[s0237] Implement server side global cooldown check.
Browse files Browse the repository at this point in the history
Signed-off-by: VladimirMangos <vladimir@getmangos.com>

Also pet/controlled unit global cooldown code replaced by new placed in charmInfo structure.

Thanks to nos4r2zod for testing and gcd range check implement.

(based on commit defa062)
  • Loading branch information
darkstalker authored and VladimirMangos committed Sep 25, 2010
1 parent d5f6ffc commit 6ba4e25
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 24 deletions.
12 changes: 0 additions & 12 deletions src/game/Creature.cpp
Expand Up @@ -137,7 +137,6 @@ m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)

m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
m_GlobalCooldown = 0;

m_splineFlags = SPLINEFLAG_WALKMODE;
}
Expand Down Expand Up @@ -394,11 +393,6 @@ uint32 Creature::ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData *

void Creature::Update(uint32 diff)
{
if(m_GlobalCooldown <= diff)
m_GlobalCooldown = 0;
else
m_GlobalCooldown -= diff;

if (m_needNotify)
{
m_needNotify = false;
Expand Down Expand Up @@ -1999,8 +1993,6 @@ void Creature::AddCreatureSpellCooldown(uint32 spellid)

if(spellInfo->Category)
_AddCreatureCategoryCooldown(spellInfo->Category, time(NULL));

m_GlobalCooldown = spellInfo->StartRecoveryTime;
}

bool Creature::HasCategoryCooldown(uint32 spell_id) const
Expand All @@ -2009,10 +2001,6 @@ bool Creature::HasCategoryCooldown(uint32 spell_id) const
if(!spellInfo)
return false;

// check global cooldown if spell affected by it
if (spellInfo->StartRecoveryCategory > 0 && m_GlobalCooldown > 0)
return true;

CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.find(spellInfo->Category);
return (itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / IN_MILLISECONDS)) > time(NULL));
}
Expand Down
3 changes: 0 additions & 3 deletions src/game/Creature.h
Expand Up @@ -543,7 +543,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
uint32 m_spells[CREATURE_MAX_SPELLS];
CreatureSpellCooldowns m_CreatureSpellCooldowns;
CreatureSpellCooldowns m_CreatureCategoryCooldowns;
uint32 m_GlobalCooldown;

float GetAttackDistance(Unit const* pl) const;

Expand Down Expand Up @@ -612,8 +611,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
void SetSummonPoint(float fX, float fY, float fZ, float fOrient) { m_summonXpoint = fX; m_summonYpoint = fY; m_summonZpoint = fZ; m_summonOrientation = fOrient; }
void GetSummonPoint(float &fX, float &fY, float &fZ, float &fOrient) const { fX = m_summonXpoint; fY = m_summonYpoint; fZ = m_summonZpoint; fOrient = m_summonOrientation; }

uint32 GetGlobalCooldown() const { return m_GlobalCooldown; }

void SetDeadByDefault (bool death_state) { m_isDeadByDefault = death_state; }

void SetActiveObjectState(bool on);
Expand Down
5 changes: 4 additions & 1 deletion src/game/PetAI.cpp
Expand Up @@ -200,7 +200,7 @@ void PetAI::UpdateAI(const uint32 diff)
}

// Autocast (casted only in combat or persistent spells in any state)
if (m_creature->GetGlobalCooldown() == 0 && !m_creature->IsNonMeleeSpellCasted(false))
if (!m_creature->IsNonMeleeSpellCasted(false))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
Expand All @@ -215,6 +215,9 @@ void PetAI::UpdateAI(const uint32 diff)
if (!spellInfo)
continue;

if (m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
continue;

// ignore some combinations of combat state and combat/noncombat spells
if (!inCombat)
{
Expand Down
13 changes: 7 additions & 6 deletions src/game/PetHandler.cpp
Expand Up @@ -170,9 +170,6 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
case ACT_ENABLED: // 0xC1 spell
{
Unit* unit_target = NULL;
if (((Creature*)pet)->GetGlobalCooldown() > 0)
return;

if(guid2)
unit_target = _player->GetMap()->GetUnit(guid2);

Expand All @@ -184,6 +181,9 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
return;
}

if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
return;

for(int i = 0; i < MAX_EFFECT_INDEX;++i)
{
if(spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
Expand Down Expand Up @@ -642,16 +642,17 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
return;
}

if (pet->GetGlobalCooldown() > 0)
return;

SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid);
if (!spellInfo)
{
sLog.outError("WORLD: unknown PET spell id %i", spellid);
return;
}

if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
return;


// do not cast not learned spells
if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
return;
Expand Down
2 changes: 1 addition & 1 deletion src/game/Player.cpp
Expand Up @@ -17797,7 +17797,7 @@ void Player::SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId, Spell
data << GetObjectGuid();
SendDirectMessage(&data);
}
//slot to be excluded while counting

bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot)
{
if(!enchantmentcondition)
Expand Down
4 changes: 4 additions & 0 deletions src/game/Player.h
Expand Up @@ -1487,6 +1487,8 @@ class MANGOS_DLL_SPEC Player : public Unit
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown( uint32 spell_id, Unit* target );

GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }

void RemoveArenaSpellCooldowns();
void RemoveAllSpellCooldown();
void _LoadSpellCooldowns(QueryResult *result);
Expand Down Expand Up @@ -2246,6 +2248,8 @@ class MANGOS_DLL_SPEC Player : public Unit
PlayerSpellMap m_spells;
SpellCooldowns m_spellCooldowns;

GlobalCooldownMgr m_GlobalCooldownMgr;

ActionButtonList m_actionButtons;

float m_auraBaseMod[BASEMOD_END][MOD_END];
Expand Down
62 changes: 62 additions & 0 deletions src/game/Spell.cpp
Expand Up @@ -2306,6 +2306,8 @@ void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura)

// will show cast bar
SendSpellStart();

TriggerGlobalCooldown();
}
// execute triggered without cast time explicitly in call point
else if(m_timer == 0)
Expand All @@ -2327,6 +2329,9 @@ void Spell::cancel()
switch (m_spellState)
{
case SPELL_STATE_PREPARING:
CancelGlobalCooldown();

//(no break)
case SPELL_STATE_DELAYED:
{
SendInterrupted(0);
Expand Down Expand Up @@ -3545,6 +3550,10 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_NOT_READY;
}

// check global cooldown
if (strict && !m_IsTriggeredSpell && HasGlobalCooldown())
return SPELL_FAILED_NOT_READY;

// only allow triggered spells if at an ended battleground
if (!m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER)
if(BattleGround * bg = ((Player*)m_caster)->GetBattleGround())
Expand Down Expand Up @@ -5784,3 +5793,56 @@ WorldObject* Spell::GetCastingObject() const
return m_caster;
}

bool Spell::HasGlobalCooldown()
{
// global cooldown have only player or controlled units
if (m_caster->GetCharmInfo())
return m_caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
return ((Player*)m_caster)->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
else
return false;
}

void Spell::TriggerGlobalCooldown()
{
int32 gcd = m_spellInfo->StartRecoveryTime;
if (!gcd)
return;

// global cooldown can't leave range 1..1.5 secs (if it it)
// exist some spells (mostly not player directly casted) that have < 1 sec and > 1.5 sec global cooldowns
// but its as test show not affected any spell mods.
if (m_spellInfo->StartRecoveryTime >= 1000 && m_spellInfo->StartRecoveryTime <= 1500)
{
// apply haste rating
gcd = int32(float(gcd) * m_caster->GetFloatValue(UNIT_MOD_CAST_SPEED));

if (gcd < 1000)
gcd = 1000;
else if (gcd > 1500)
gcd = 1500;
}

// global cooldown have only player or controlled units
if (m_caster->GetCharmInfo())
m_caster->GetCharmInfo()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
((Player*)m_caster)->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
}

void Spell::CancelGlobalCooldown()
{
if (!m_spellInfo->StartRecoveryTime)
return;

// cancel global cooldown when interrupting current cast
if (m_caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) != this)
return;

// global cooldown have only player or controlled units
if (m_caster->GetCharmInfo())
m_caster->GetCharmInfo()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
((Player*)m_caster)->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
}
5 changes: 5 additions & 0 deletions src/game/Spell.h
Expand Up @@ -315,7 +315,9 @@ class Spell
~Spell();

void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL);

void cancel();

void update(uint32 difftime);
void cast(bool skipCheck = false);
void finish(bool ok = true);
Expand Down Expand Up @@ -446,6 +448,9 @@ class Spell

void CleanupTargetList();
protected:
bool HasGlobalCooldown();
void TriggerGlobalCooldown();
void CancelGlobalCooldown();

void SendLoot(uint64 guid, LootType loottype);
bool IgnoreItemRequirements() const; // some item use spells have unexpected reagent data
Expand Down
25 changes: 25 additions & 0 deletions src/game/Unit.cpp
Expand Up @@ -74,6 +74,9 @@ static bool isNonTriggerAura[TOTAL_AURAS];
// Prepare lists
static bool procPrepared = InitTriggerAuraData();

////////////////////////////////////////////////////////////
// Methods of class MovementInfo

void MovementInfo::Read(ByteBuffer &data)
{
data >> moveFlags;
Expand Down Expand Up @@ -154,6 +157,28 @@ void MovementInfo::Write(ByteBuffer &data) const
}
}

////////////////////////////////////////////////////////////
// Methods of class GlobalCooldownMgr

bool GlobalCooldownMgr::HasGlobalCooldown(SpellEntry const* spellInfo) const
{
GlobalCooldownList::const_iterator itr = m_GlobalCooldowns.find(spellInfo->StartRecoveryCategory);
return itr != m_GlobalCooldowns.end() && itr->second.duration && getMSTimeDiff(itr->second.cast_time, getMSTime()) < itr->second.duration;
}

void GlobalCooldownMgr::AddGlobalCooldown(SpellEntry const* spellInfo, uint32 gcd)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory] = GlobalCooldown(gcd, getMSTime());
}

void GlobalCooldownMgr::CancelGlobalCooldown(SpellEntry const* spellInfo)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory].duration = 0;
}

////////////////////////////////////////////////////////////
// Methods of class Unit

Unit::Unit()
: WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostileRefManager(this)
{
Expand Down
26 changes: 26 additions & 0 deletions src/game/Unit.h
Expand Up @@ -837,6 +837,29 @@ enum CurrentSpellTypes
#define CURRENT_FIRST_NON_MELEE_SPELL 1
#define CURRENT_MAX_SPELL 4

struct GlobalCooldown
{
explicit GlobalCooldown(uint32 _dur = 0, uint32 _time = 0) : duration(_dur), cast_time(_time) {}

uint32 duration;
uint32 cast_time;
};

typedef UNORDERED_MAP<uint32 /*category*/, GlobalCooldown> GlobalCooldownList;

class GlobalCooldownMgr // Shared by Player and CharmInfo
{
public:
GlobalCooldownMgr() {}

public:
bool HasGlobalCooldown(SpellEntry const* spellInfo) const;
void AddGlobalCooldown(SpellEntry const* spellInfo, uint32 gcd);
void CancelGlobalCooldown(SpellEntry const* spellInfo);

private:
GlobalCooldownList m_GlobalCooldowns;
};

enum ActiveStates
{
Expand Down Expand Up @@ -969,6 +992,8 @@ struct CharmInfo
void ToggleCreatureAutocast(uint32 spellid, bool apply);

CharmSpellEntry* GetCharmSpell(uint8 index) { return &(m_charmspells[index]); }

GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
private:

Unit* m_unit;
Expand All @@ -977,6 +1002,7 @@ struct CharmInfo
CommandStates m_CommandState;
ReactStates m_reactState;
uint32 m_petnumber;
GlobalCooldownMgr m_GlobalCooldownMgr;
};

// for clearing special attacks
Expand Down
2 changes: 1 addition & 1 deletion src/shared/revision_nr.h
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "0236"
#define REVISION_NR "0237"
#endif // __REVISION_NR_H__

0 comments on commit 6ba4e25

Please sign in to comment.