Index: game/SharedDefines.h =================================================================== --- game/SharedDefines.h (revision 5497) +++ game/SharedDefines.h (working copy) @@ -1702,4 +1702,40 @@ AI_REACTION_UNK3 = 3, AI_REACTION_UNK4 = 4 }; + +// Diminishing Stuff, not related to DBC or client +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_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_KIDNEYSHOT = 8, + // Warlock Specific + DIMINISHING_DEATHCOIL = 9, + // Shared Class Specific + DIMINISHING_BLIND_CYCLONE = 10, + DIMINISHING_DISARM = 11, + DIMINISHING_SILENCE = 12, + DIMINISHING_FREEZE = 13, + DIMINISHING_KNOCKOUT = 14, + // Warrior Specific + DIMINISHING_HAMSTRING = 15 +}; + + #endif Index: game/Spell.cpp =================================================================== --- game/Spell.cpp (revision 5497) +++ game/Spell.cpp (working copy) @@ -738,6 +738,11 @@ } } } + // raise diminishing level + DiminishingGroup group = GetDRGroupForSpell(m_spellInfo,m_triggeredByAuraSpell); + if(m_diminishDuration && ((SpellDRType(group) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || SpellDRType(group) == DRTYPE_ALL)) + unit->IncrDiminishing(group, m_diminishDuration); + } void Spell::DoAllEffectOnTarget(GOTargetInfo *target) @@ -1833,6 +1838,9 @@ m_applyMultiplier[j] = (m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_HEAL) && (m_spellInfo->EffectChainTarget[j] > 1); + + // Diminishing + m_diminishDuration = 0; } // process items Index: game/Spell.h =================================================================== --- game/Spell.h (revision 5497) +++ game/Spell.h (working copy) @@ -491,6 +491,8 @@ float m_castOrientation; bool m_IsTriggeredSpell; + int32 m_diminishDuration; + // if need this can be replaced by Aura copy // we can't store original aura link to prevent access to deleted auras // and in same time need aura data and after aura deleting. Index: game/SpellEffects.cpp =================================================================== --- game/SpellEffects.cpp (revision 5497) +++ game/SpellEffects.cpp (working copy) @@ -1652,6 +1652,7 @@ } } + void Spell::EffectApplyAura(uint32 i) { if(!unitTarget) @@ -1722,56 +1723,25 @@ } // Update aura duration based at diminishingMod + int32 duration = Aur->GetAuraMaxDuration(); + DiminishingGroup group = GetDRGroupForSpell(m_spellInfo,m_triggeredByAuraSpell); + m_diminishDuration = duration; + unitTarget->ApplyDiminishingToDuration(group,duration,caster); + + // if Aura removed and deleted, do not continue. + if(duration== 0 && !(Aur->IsPermanent())) { - //Use Effect mechanic - DiminishingMechanics mech = Unit::Mechanic2DiminishingMechanics(Aur->GetSpellProto()->EffectMechanic[i]); + delete Aur; + return; + } - //Use Spell mechanic - if (mech == DIMINISHING_NONE) - mech = Unit::Mechanic2DiminishingMechanics(Aur->GetSpellProto()->Mechanic); - - 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; - } - } - - // 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 5497) +++ game/SpellMgr.cpp (working copy) @@ -1669,3 +1669,123 @@ return false; } + +DiminishingGroup GetDRGroupForSpell(SpellEntry const* spellproto, bool triggered) +{ + // 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; + // 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 DIMINISHING_KNOCKOUT; + } + + return DIMINISHING_NONE; +} + + +bool 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_FREEZE: + case DIMINISHING_KNOCKOUT: + case DIMINISHING_HAMSTRING: + case DIMINISHING_BLIND_CYCLONE: + return true; + } + return false; +} + +DRType 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_SILENCE: + case DIMINISHING_DISARM: + case DIMINISHING_DEATHCOIL: + case DIMINISHING_FREEZE: + return DRTYPE_PLAYER; + } + + return DRTYPE_NONE; +} + Index: game/SpellMgr.h =================================================================== --- game/SpellMgr.h (revision 5497) +++ game/SpellMgr.h (working copy) @@ -307,6 +307,11 @@ return (spellInfo->AttributesEx & 0x44); } +// Diminishing Returns interaction with spells +DiminishingGroup GetDRGroupForSpell(SpellEntry const* spellproto, bool triggered); +bool IsDurationLimited(DiminishingGroup group); +DRType SpellDRType(DiminishingGroup group); + // Spell affects related declarations (accessed using SpellMgr functions) struct SpellAffection { Index: game/Unit.cpp =================================================================== --- game/Unit.cpp (revision 5497) +++ game/Unit.cpp (working copy) @@ -4012,18 +4012,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); @@ -8446,45 +8434,40 @@ return duration; } -void Unit::AddDiminishing(DiminishingMechanics mech, uint32 hitTime, uint32 hitCount) + +void Unit::AddDiminishing(DiminishingGroup group, uint32 hitTime, uint32 hitCount) { - m_Diminishing.push_back(DiminishingReturn(mech,hitTime,hitCount)); + m_Diminishing.push_back(DiminishingReturn(group,hitTime,hitCount)); } -DiminishingLevels Unit::GetDiminishing(DiminishingMechanics mech) +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; @@ -8503,61 +8486,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(); @@ -8572,16 +8510,15 @@ 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_IMMUNE: mod = 0.0f; break; + case DIMINISHING_LEVEL_1: break; + case DIMINISHING_LEVEL_2: mod = 0.5f; break; + case DIMINISHING_LEVEL_3: mod = 0.25f; break; + case DIMINISHING_LEVEL_IMMUNE: mod = 0.0f;break; default: break; } } Index: game/Unit.h =================================================================== --- game/Unit.h (revision 5497) +++ game/Unit.h (working copy) @@ -415,6 +415,7 @@ }; /// Non Player Character flags +/// Non Player Character flags enum NPCFlags { UNIT_NPC_FLAG_NONE = 0x00000000, @@ -446,17 +447,6 @@ UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards }; -enum DiminishingMechanics -{ - 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 -}; - enum DiminishingLevels { DIMINISHING_LEVEL_1 = 0, @@ -465,11 +455,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; }; @@ -602,12 +593,10 @@ 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); virtual void Update( uint32 time );