Index: game/SpellEffects.cpp =================================================================== --- game/SpellEffects.cpp (revision 5472) +++ game/SpellEffects.cpp (working copy) @@ -1562,6 +1562,7 @@ ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation); } + void Spell::EffectApplyAura(uint32 i) { if(!unitTarget) @@ -1632,56 +1633,25 @@ } // Update aura duration based at diminishingMod - { - //Use Effect mechanic - DiminishingMechanics mech = Unit::Mechanic2DiminishingMechanics(Aur->GetSpellProto()->EffectMechanic[i]); + int32 duration = Aur->GetAuraMaxDuration(); + DiminishingGroup group = unitTarget->GetDRGroupForSpell(m_spellInfo,m_triggeredByAuraSpell); - //Use Spell mechanic - if (mech == DIMINISHING_NONE) - mech = Unit::Mechanic2DiminishingMechanics(Aur->GetSpellProto()->Mechanic); + unitTarget->ApplyDiminishingToDuration(group,duration,caster); - if(mech == DIMINISHING_NONE) - { - switch(m_spellInfo->EffectApplyAuraName[i]) - { - case SPELL_AURA_MOD_CONFUSE: - mech = DIMINISHING_MECHANIC_CONFUSE; break; - case SPELL_AURA_MOD_CHARM: - case SPELL_AURA_MOD_FEAR: - mech = DIMINISHING_MECHANIC_CHARM; break; - case SPELL_AURA_MOD_STUN: - mech = DIMINISHING_MECHANIC_STUN; break; - case SPELL_AURA_MOD_ROOT: - mech = DIMINISHING_MECHANIC_ROOT; break; - case SPELL_AURA_MOD_DECREASE_SPEED: - mech = DIMINISHING_MECHANIC_SNARE; break; - default: break; - } - } + // if Aura removed and deleted, do not continue. + if(duration== 0 && !(Aur->IsPermanent())) + { + delete Aur; + return; + } - // Death Coil and Curse of Exhaustion are not diminished. - if((m_spellInfo->SpellVisual == 64 && m_spellInfo->SpellIconID == 88) || - (m_spellInfo->SpellVisual == 185 && m_spellInfo->SpellIconID == 228)) - mech = DIMINISHING_NONE; - - int32 duration = Aur->GetAuraMaxDuration(); - - unitTarget->ApplyDiminishingToDuration(mech,duration,caster); - - // if Aura removed and deleted, do not continue. - if(duration== 0 && !(Aur->IsPermanent())) - { - delete Aur; - return; - } - - if(duration != Aur->GetAuraMaxDuration()) - { - Aur->SetAuraMaxDuration(duration); - Aur->SetAuraDuration(duration); - } + if(duration != Aur->GetAuraMaxDuration()) + { + Aur->SetAuraMaxDuration(duration); + Aur->SetAuraDuration(duration); } + bool added = unitTarget->AddAura(Aur); // Aura not added and deleted in AddAura call; Index: game/SpellMgr.cpp =================================================================== --- game/SpellMgr.cpp (revision 5472) +++ game/SpellMgr.cpp (working copy) @@ -1657,4 +1657,4 @@ return true; return false; -} +} \ No newline at end of file Index: game/Unit.cpp =================================================================== --- game/Unit.cpp (revision 5472) +++ game/Unit.cpp (working copy) @@ -3983,18 +3983,6 @@ // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) Aura* Aur = i->second; - DiminishingMechanics mech = DIMINISHING_NONE; - if(Aur->GetSpellProto()->Mechanic || Aur->GetSpellProto()->EffectMechanic[Aur->GetEffIndex()]) - { - mech = Unit::Mechanic2DiminishingMechanics(Aur->GetSpellProto()->EffectMechanic[Aur->GetEffIndex()]); - - if (mech == DIMINISHING_NONE) - mech = Unit::Mechanic2DiminishingMechanics(Aur->GetSpellProto()->Mechanic); - - if(mech == DIMINISHING_MECHANIC_STUN || GetTypeId() == TYPEID_PLAYER && mech != DIMINISHING_NONE) - UpdateDiminishingTime(mech); - } - // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura // remove aura from list before to prevent deleting it before m_Auras.erase(i); @@ -8379,45 +8367,168 @@ return duration; } -void Unit::AddDiminishing(DiminishingMechanics mech, uint32 hitTime, uint32 hitCount) + +DiminishingGroup Unit::GetDRGroupForSpell(SpellEntry const* spellproto, bool triggered) { - m_Diminishing.push_back(DiminishingReturn(mech,hitTime,hitCount)); + // Explicit Diminishing Groups + switch(spellproto->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + { + // Polymorph + if ((spellproto->SpellFamilyFlags & 0x1000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) + return DIMINISHING_POLYMORPH; + break; + } + case SPELLFAMILY_ROGUE: + { + // Kidney Shot + if (spellproto->SpellFamilyFlags & 0x200000LL) + return DIMINISHING_KIDNEYSHOT; + // Gouge + else if (spellproto->SpellFamilyFlags & 0x8) + return DIMINISHING_GOUGE; + // Sap + else if (spellproto->SpellFamilyFlags & 0x80) + return DIMINISHING_SAP; + // Blind + else if (spellproto->SpellFamilyFlags & 0x1000000LL) + return DIMINISHING_BLIND_CYCLONE; + break; + } + case SPELLFAMILY_WARLOCK: + { + // Death Coil + if (spellproto->SpellFamilyFlags & 0x80000LL) + return DIMINISHING_DEATHCOIL; + break; + } + case SPELLFAMILY_DRUID: + { + // Cyclone + if (spellproto->SpellFamilyFlags & 0x2000000000LL) + return DIMINISHING_BLIND_CYCLONE; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Hamstring - limit duration to 10s in PvP + if (spellproto->SpellFamilyFlags & 0x2) + return DIMINISHING_HAMSTRING; + break; + } + default: + break; + } + + // Get by mechanic + for (uint8 i=0;i<3;++i) + { + if (spellproto->Mechanic == MECHANIC_STUN ||spellproto->EffectMechanic[i] == MECHANIC_STUN) + return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN; + else if (spellproto->Mechanic == MECHANIC_SLEEP || spellproto->EffectMechanic[i] == MECHANIC_SLEEP) + return DIMINISHING_SLEEP; + else if (spellproto->Mechanic == MECHANIC_ROOT || spellproto->EffectMechanic[i] == MECHANIC_ROOT) + return DIMINISHING_ROOT; + else if (spellproto->Mechanic == MECHANIC_FEAR || spellproto->EffectMechanic[i] == MECHANIC_FEAR) + return DIMINISHING_FEAR; + else if (spellproto->Mechanic == MECHANIC_CHARM || spellproto->EffectMechanic[i] == MECHANIC_CHARM) + return DIMINISHING_CHARM; + else if (spellproto->Mechanic == MECHANIC_SILENCE || spellproto->EffectMechanic[i] == MECHANIC_SILENCE) + return DIMINISHING_SILENCE; + else if (spellproto->Mechanic == MECHANIC_DISARM || spellproto->EffectMechanic[i] == MECHANIC_DISARM) + return DIMINISHING_DISARM; + else if (spellproto->Mechanic == MECHANIC_FREEZE || spellproto->EffectMechanic[i] == MECHANIC_FREEZE) + return DIMINISHING_FREEZE; + else if (spellproto->Mechanic == MECHANIC_KNOCKOUT || spellproto->EffectMechanic[i] == MECHANIC_KNOCKOUT) + return MECHANIC_KNOCKOUT; + } + + return DIMINISHING_NONE; } -DiminishingLevels Unit::GetDiminishing(DiminishingMechanics mech) + +bool Unit::IsDurationLimited(DiminishingGroup group) { + switch(group) + { + case DIMINISHING_CONTROL_STUN: + case DIMINISHING_TRIGGER_STUN: + case DIMINISHING_KIDNEYSHOT: + case DIMINISHING_SLEEP: + case DIMINISHING_ROOT: + case DIMINISHING_FEAR: + case DIMINISHING_CHARM: + case DIMINISHING_POLYMORPH: + case DIMINISHING_SAP: + case DIMINISHING_FREEZE: + case DIMINISHING_KNOCKOUT: + case DIMINISHING_HAMSTRING: + case DIMINISHING_BLIND_CYCLONE: + return true; + } + return false; +} + +DRType Unit::SpellDRType(DiminishingGroup group) +{ + switch(group) + { + case DIMINISHING_BLIND_CYCLONE: + case DIMINISHING_CONTROL_STUN: + case DIMINISHING_TRIGGER_STUN: + case DIMINISHING_KIDNEYSHOT: + return DRTYPE_ALL; + case DIMINISHING_SLEEP: + case DIMINISHING_ROOT: + case DIMINISHING_FEAR: + case DIMINISHING_CHARM: + case DIMINISHING_POLYMORPH: + case DIMINISHING_SAP: + case DIMINISHING_SILENCE: + case DIMINISHING_DISARM: + case DIMINISHING_DEATHCOIL: + case DIMINISHING_GOUGE: + case DIMINISHING_FREEZE: + return DRTYPE_PLAYER; + } + + return DRTYPE_NONE; +} + +void Unit::AddDiminishing(DiminishingGroup group, uint32 hitTime, uint32 hitCount) +{ + m_Diminishing.push_back(DiminishingReturn(group,hitTime,hitCount)); +} + +DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) +{ for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) { - if(i->Mechanic != mech) continue; + if(i->DRGroup != group) continue; if(!i->hitCount) return DIMINISHING_LEVEL_1; if(!i->hitTime) return DIMINISHING_LEVEL_1; // If last spell was casted more than 15 seconds ago - reset the count. - if((getMSTime() - i->hitTime) > 15000) + if((int32(getMSTime()) - int32(i->hitTime)) > 15000) { i->hitCount = DIMINISHING_LEVEL_1; return DIMINISHING_LEVEL_1; } - // or else increase the count. else { - if(i->hitCount > DIMINISHING_LEVEL_2) - { - i->hitCount = DIMINISHING_LEVEL_IMMUNE; - return DIMINISHING_LEVEL_IMMUNE; - } - else return DiminishingLevels(i->hitCount); + return DiminishingLevels(i->hitCount); } } return DIMINISHING_LEVEL_1; } -void Unit::IncrDiminishing(DiminishingMechanics mech, uint32 duration) +void Unit::IncrDiminishing(DiminishingGroup group, uint32 duration) { // Checking for existing in the table bool IsExist = false; for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) { - if(i->Mechanic != mech) + if(i->DRGroup != group) continue; IsExist = true; @@ -8436,61 +8547,16 @@ } if(!IsExist) - AddDiminishing(mech,uint32(getMSTime() + duration),DIMINISHING_LEVEL_2); + AddDiminishing(group,uint32(getMSTime() + duration),DIMINISHING_LEVEL_2); } -void Unit::UpdateDiminishingTime(DiminishingMechanics mech) +void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, Unit* caster) { - // Checking for existing in the table - bool IsExist = false; - for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) - { - if(i->Mechanic != mech) - continue; - - IsExist = true; - i->hitTime = getMSTime(); - break; - } - - if(!IsExist) - AddDiminishing(mech,getMSTime(),DIMINISHING_LEVEL_1); -} - -DiminishingMechanics Unit::Mechanic2DiminishingMechanics(uint32 mech) -{ - switch(mech) - { - case MECHANIC_CHARM: case MECHANIC_FEAR: case MECHANIC_SLEEP: - return DIMINISHING_MECHANIC_CHARM; - - case MECHANIC_CONFUSED: case MECHANIC_KNOCKOUT: case MECHANIC_POLYMORPH: - return DIMINISHING_MECHANIC_CONFUSE; - - case MECHANIC_ROOT: case MECHANIC_FREEZE: - return DIMINISHING_MECHANIC_ROOT; - - case MECHANIC_STUN: - return DIMINISHING_MECHANIC_STUN; - - case MECHANIC_SNARE: - return DIMINISHING_MECHANIC_SNARE; - - case MECHANIC_BANISH: - return DIMINISHING_MECHANIC_BANISH; - default: - break; - } - return DIMINISHING_NONE; -} - -void Unit::ApplyDiminishingToDuration(DiminishingMechanics mech, int32 &duration,Unit* caster) -{ - if(duration == -1 || mech == DIMINISHING_NONE || caster->IsFriendlyTo(this) ) + if(duration == -1 || caster->IsFriendlyTo(this) || group == DIMINISHING_NONE ) return; // Duration of crowd control abilities on pvp target is limited by 10 sec. (2.2.0) - if(duration > 10000) + if(duration > 10000 && IsDurationLimited(group)) { // test pet/charm masters instead pets/charmeds Unit const* targetOwner = GetCharmerOrOwner(); @@ -8505,15 +8571,14 @@ float mod = 1.0f; - // Stun diminishing is applies to mobs too - if(mech == DIMINISHING_MECHANIC_STUN || GetTypeId() == TYPEID_PLAYER) + if((SpellDRType(group) == DRTYPE_PLAYER && GetTypeId() == TYPEID_PLAYER) || SpellDRType(group) == DRTYPE_ALL) { - DiminishingLevels diminish = GetDiminishing(mech); + DiminishingLevels diminish = GetDiminishing(group); switch(diminish) { - case DIMINISHING_LEVEL_1: IncrDiminishing(mech, duration); break; - case DIMINISHING_LEVEL_2: IncrDiminishing(mech, duration); mod = 0.5f; break; - case DIMINISHING_LEVEL_3: IncrDiminishing(mech, duration); mod = 0.25f; break; + case DIMINISHING_LEVEL_1: IncrDiminishing(group, duration); break; + case DIMINISHING_LEVEL_2: IncrDiminishing(group, duration); mod = 0.5f; break; + case DIMINISHING_LEVEL_3: IncrDiminishing(group, duration); mod = 0.25f; break; case DIMINISHING_LEVEL_IMMUNE: mod = 0.0f; break; default: break; } Index: game/Unit.h =================================================================== --- game/Unit.h (revision 5472) +++ game/Unit.h (working copy) @@ -392,15 +392,39 @@ UNIT_FLAG_SHEATHE = 0x40000000 }; -enum DiminishingMechanics +enum DRType { + DRTYPE_NONE = 0, // this spell is not diminished, but may have limited it's duration to 10s + DRTYPE_PLAYER = 1, // this spell is diminished only when applied on players + DRTYPE_ALL = 2 // this spell is diminished in every case +}; + +enum DiminishingGroup +{ + // Common Groups DIMINISHING_NONE = 0, - DIMINISHING_MECHANIC_CONFUSE = 1, // incapacitate, confuse - DIMINISHING_MECHANIC_CHARM = 2, // fear, mind control, sleep - DIMINISHING_MECHANIC_STUN = 3, // stun - DIMINISHING_MECHANIC_ROOT = 4, // roots, freeze - DIMINISHING_MECHANIC_SNARE = 5, // speed reduction (snares) - DIMINISHING_MECHANIC_BANISH = 6 // banish and cyclone + DIMINISHING_CONTROL_STUN = 1, + DIMINISHING_TRIGGER_STUN = 2, + DIMINISHING_SLEEP = 3, + DIMINISHING_ROOT = 4, + DIMINISHING_FEAR = 5, + DIMINISHING_CHARM = 6, + // Mage Specific + DIMINISHING_POLYMORPH = 7, + // Rogue Specific + DIMINISHING_SAP = 8, + DIMINISHING_GOUGE = 9, + DIMINISHING_KIDNEYSHOT = 10, + // Warlock Specific + DIMINISHING_DEATHCOIL = 11, + // Shared Class Specific + DIMINISHING_BLIND_CYCLONE = 12, + DIMINISHING_DISARM = 13, + DIMINISHING_SILENCE = 14, + DIMINISHING_FREEZE = 15, + DIMINISHING_KNOCKOUT = 16, + // Warrior Specific + DIMINISHING_HAMSTRING = 17 }; enum DiminishingLevels @@ -411,11 +435,12 @@ DIMINISHING_LEVEL_IMMUNE = 3 }; + struct DiminishingReturn { - DiminishingReturn(DiminishingMechanics mech, uint32 t, uint32 count) : Mechanic(mech), hitTime(t), hitCount(count) {} + DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) : DRGroup(group), hitTime(t), hitCount(count) {} - DiminishingMechanics Mechanic; + DiminishingGroup DRGroup; uint32 hitTime; uint32 hitCount; }; @@ -548,13 +573,15 @@ void CleanupsBeforeDelete(); // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) - static DiminishingMechanics Mechanic2DiminishingMechanics(uint32 mech); - void AddDiminishing(DiminishingMechanics mech, uint32 hitTime, uint32 hitCount); - DiminishingLevels GetDiminishing(DiminishingMechanics mech); - void IncrDiminishing(DiminishingMechanics mech, uint32 duration); - void UpdateDiminishingTime(DiminishingMechanics mech); - void ApplyDiminishingToDuration(DiminishingMechanics mech, int32& duration,Unit* caster); + void AddDiminishing(DiminishingGroup group, uint32 hitTime, uint32 hitCount); + DiminishingLevels GetDiminishing(DiminishingGroup group); + void IncrDiminishing(DiminishingGroup group, uint32 duration); + void ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster); + static DiminishingGroup GetDRGroupForSpell(SpellEntry const* spellproto, bool triggered); + bool IsDurationLimited(DiminishingGroup group); + DRType SpellDRType(DiminishingGroup group); + virtual void Update( uint32 time ); void setAttackTimer(WeaponAttackType type, uint32 time) { m_attackTimer[type] = time; }