Index: game/SharedDefines.h =================================================================== --- game/SharedDefines.h (revision 6120) +++ game/SharedDefines.h (working copy) @@ -1926,6 +1926,45 @@ AI_REACTION_UNK4 = 4 }; +// Diminishing Returns Types +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 +}; + +// Diminishing Return Groups +enum DiminishingGroup +{ + // Common Groups + DIMINISHING_NONE = 0, + DIMINISHING_CONTROL_STUN = 1, // Player Controlled stuns + DIMINISHING_TRIGGER_STUN = 2, // By aura proced stuns, usualy chance on hit talents + DIMINISHING_SLEEP = 3, + DIMINISHING_ROOT = 4, // Immobilizing effects + DIMINISHING_FEAR = 5, // Non-warlock fears + DIMINISHING_CHARM = 6, + // Mage Specific + DIMINISHING_POLYMORPH = 7, + // Rogue Specific + DIMINISHING_KIDNEYSHOT = 8, // Kidney Shot is not diminished with Cheap Shot + // Warlock Specific + DIMINISHING_DEATHCOIL = 9, // Death Coil Diminish only with another Death Coil + DIMINISHING_WARLOCK_FEAR = 10, // Also with Sedduction + // Shared Class Specific + DIMINISHING_BLIND_CYCLONE = 11, // From 2.3.0 + DIMINISHING_DISARM = 12, // From 2.3.0 + DIMINISHING_SILENCE = 13, // From 2.3.0 + DIMINISHING_FREEZE = 14, // Hunter's Freezing Trap + DIMINISHING_KNOCKOUT = 15, // Also with Sap, all Knockout mechanics are here + DIMINISHING_BANISH = 16, + // Other + // Don't Diminish, but limit duration to 10s + DIMINISHING_LIMITONLY = 17 +}; + + enum DungeonDifficulties { DIFFICULTY_NORMAL = 0, Index: game/Spell.cpp =================================================================== --- game/Spell.cpp (revision 6120) +++ game/Spell.cpp (working copy) @@ -931,6 +931,13 @@ return; } + // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add + m_diminishGroup = GetDRGroupForSpell(m_spellInfo,m_triggeredByAuraSpell); + m_diminishLevel = unit->GetDiminishing(m_diminishGroup); + // Increase Diminishing on unit, current informations for actualy casts will use values above + if((SpellDRType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || SpellDRType(m_diminishGroup) == DRTYPE_ALL) + unit->IncrDiminishing(m_diminishGroup); + for(uint32 effectNumber=0;effectNumber<3;effectNumber++) { if (effectMask & (1< 1); } + // initialize Diminishing Returns Data + m_diminishLevel = DIMINISHING_LEVEL_1; + m_diminishGroup = DIMINISHING_NONE; + // process items for(std::list::iterator ihit= m_UniqueItemInfo.begin();ihit != m_UniqueItemInfo.end();++ihit) DoAllEffectOnTarget(&(*ihit)); Index: game/Spell.h =================================================================== --- game/Spell.h (revision 6120) +++ game/Spell.h (working copy) @@ -517,6 +517,10 @@ float m_castOrientation; bool m_IsTriggeredSpell; + // this is set in Spell Hit, but used in Apply Aura handler + DiminishingLevels m_diminishLevel; + DiminishingGroup m_diminishGroup; + // 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/SpellAuras.cpp =================================================================== --- game/SpellAuras.cpp (revision 6120) +++ game/SpellAuras.cpp (working copy) @@ -308,7 +308,7 @@ m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS), m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), m_isPersistent(false), m_updated(false), m_removeOnDeath(false), m_isRemovedOnShapeLost(true), m_in_use(false), -m_periodicTimer(0), m_PeriodicEventId(0), m_fearMoveAngle(0) +m_periodicTimer(0), m_PeriodicEventId(0), m_fearMoveAngle(0), m_AuraDRGroup(DIMINISHING_NONE) { assert(target); @@ -977,6 +977,24 @@ m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); } + // get auras with same Diminishing Group + if ( getDiminishGroup() != DIMINISHING_NONE ) + { + bool found = false; + Unit::AuraMap& tAuras = m_target->GetAuras(); + for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();++itr) + { + if ( itr->second->getDiminishGroup() == getDiminishGroup() && itr->second->GetId() != GetId() ) + { + found = true; + break; + } + } + + // nothing more, update + if (!found) + m_target->UpdateDiminishingTime(getDiminishGroup()); + } // reset cooldown state for spells infinity/long aura (it's all self applied (?)) int32 duration = GetSpellDuration(GetSpellProto()); if( caster==m_target && ( duration < 0 || uint32(duration) > GetSpellRecoveryTime(GetSpellProto()) )) Index: game/SpellAuras.h =================================================================== --- game/SpellAuras.h (revision 6120) +++ game/SpellAuras.h (working copy) @@ -282,6 +282,10 @@ // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras void HandleShapeshiftBoosts(bool apply); + // Allow Apply Aura Handler to modify and access m_AuraDRGroup + void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } + DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; } + void PeriodicTick(); void PeriodicDummyTick(); protected: @@ -318,6 +322,7 @@ int32 m_periodicTimer; uint32 m_PeriodicEventId; + DiminishingGroup m_AuraDRGroup; private: void UpdateSlotCounterAndDuration(bool add); void CleanupTriggeredSpells(); Index: game/SpellEffects.cpp =================================================================== --- game/SpellEffects.cpp (revision 6120) +++ game/SpellEffects.cpp (working copy) @@ -1858,56 +1858,23 @@ } } - // Update aura duration based at diminishingMod - { - // Use Effect mechanic - DiminishingMechanics mech = Unit::Mechanic2DiminishingMechanics(Aur->GetSpellProto()->EffectMechanic[i]); + // Now Reduce spell duration using data recieved at spell hit + int32 duration = Aur->GetAuraMaxDuration(); + unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel); + Aur->setDiminishGroup(m_diminishGroup); - // 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 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); + } bool added = unitTarget->AddAura(Aur); Index: game/SpellMgr.cpp =================================================================== --- game/SpellMgr.cpp (revision 6120) +++ game/SpellMgr.cpp (working copy) @@ -1935,3 +1935,132 @@ sLog.outString(); sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count); } + +DiminishingGroup GetDRGroupForSpell(SpellEntry const* spellproto, bool triggered) +{ + // Explicit Diminishing Groups + switch(spellproto->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + { + // Polymorph + if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) + return DIMINISHING_POLYMORPH; + break; + } + case SPELLFAMILY_ROGUE: + { + // Kidney Shot + if (spellproto->SpellFamilyFlags & 0x00000200000LL) + return DIMINISHING_KIDNEYSHOT; + // Blind + else if (spellproto->SpellFamilyFlags & 0x00001000000LL) + return DIMINISHING_BLIND_CYCLONE; + break; + } + case SPELLFAMILY_WARLOCK: + { + // Death Coil + if (spellproto->SpellFamilyFlags & 0x00000080000LL) + return DIMINISHING_DEATHCOIL; + else if (spellproto->SpellFamilyFlags & 0x40840000000LL) + return DIMINISHING_WARLOCK_FEAR; + else if (spellproto->SpellFamilyFlags & 0x00080000000LL) + return DIMINISHING_LIMITONLY; + break; + } + case SPELLFAMILY_DRUID: + { + // Cyclone + if (spellproto->SpellFamilyFlags & 0x02000000000LL) + return DIMINISHING_BLIND_CYCLONE; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Hamstring - limit duration to 10s in PvP + if (spellproto->SpellFamilyFlags & 0x00000000002LL) + return DIMINISHING_LIMITONLY; + 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 || + spellproto->Mechanic == MECHANIC_SAPPED || spellproto->EffectMechanic[i] == MECHANIC_SAPPED) + return DIMINISHING_KNOCKOUT; + else if (spellproto->Mechanic == MECHANIC_BANISH || spellproto->EffectMechanic[i] == MECHANIC_BANISH) + return DIMINISHING_BANISH; + } + + 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_LIMITONLY: + case DIMINISHING_BLIND_CYCLONE: + case DIMINISHING_BANISH: + 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: + case DIMINISHING_BANISH: + case DIMINISHING_WARLOCK_FEAR: + case DIMINISHING_KNOCKOUT: + return DRTYPE_PLAYER; + } + + return DRTYPE_NONE; +} Index: game/SpellMgr.h =================================================================== --- game/SpellMgr.h (revision 6120) +++ game/SpellMgr.h (working copy) @@ -407,6 +407,11 @@ return (1 << dispel); } +// 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 6120) +++ game/Unit.cpp (working copy) @@ -4049,18 +4049,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); @@ -8798,20 +8786,20 @@ return duration; } -void Unit::AddDiminishing(DiminishingMechanics mech, uint32 hitTime, uint32 hitCount) +void Unit::AddDiminishing(DiminishingGroup group, uint32 hitCount, bool active) { - m_Diminishing.push_back(DiminishingReturn(mech,hitTime,hitCount)); + m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),hitCount,active)); } -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(getMSTimeDiff(i->hitTime,getMSTime()) > 15000) + if(!i->active && ((int32(getMSTime()) - int32(i->hitTime)) > 15000)) { i->hitCount = DIMINISHING_LEVEL_1; return DIMINISHING_LEVEL_1; @@ -8819,97 +8807,60 @@ // 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) { // 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; if(i->hitCount < DIMINISHING_LEVEL_IMMUNE) { i->hitCount += 1; - switch(i->hitCount) - { - case DIMINISHING_LEVEL_2: i->hitTime = uint32(getMSTime() + duration); break; - case DIMINISHING_LEVEL_3: i->hitTime = uint32(getMSTime() + duration*0.5); break; - case DIMINISHING_LEVEL_IMMUNE: i->hitTime = uint32(getMSTime() + duration*0.25); break; - default: break; - } - } + i->active = true; + i->hitTime = getMSTime(); + } break; } if(!IsExist) - AddDiminishing(mech,uint32(getMSTime() + duration),DIMINISHING_LEVEL_2); + AddDiminishing(group,DIMINISHING_LEVEL_2,true); } -void Unit::UpdateDiminishingTime(DiminishingMechanics mech) +void Unit::UpdateDiminishingTime(DiminishingGroup group) { // 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; i->hitTime = getMSTime(); + i->active = false; break; } if(!IsExist) - AddDiminishing(mech,getMSTime(),DIMINISHING_LEVEL_1); + AddDiminishing(group,DIMINISHING_LEVEL_1,false); } -DiminishingMechanics Unit::Mechanic2DiminishingMechanics(uint32 mech) +void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster,DiminishingLevels Level) { - 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(); @@ -8925,15 +8876,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 = Level; 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 6120) +++ game/Unit.h (working copy) @@ -461,17 +461,6 @@ MOVEMENTFLAG_UNK3 = 0x40000000 }; -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, @@ -482,11 +471,12 @@ struct DiminishingReturn { - DiminishingReturn(DiminishingMechanics mech, uint32 t, uint32 count) : Mechanic(mech), hitTime(t), hitCount(count) {} + DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count, bool act) : DRGroup(group), hitTime(t), hitCount(count), active(act) {} - DiminishingMechanics Mechanic; + DiminishingGroup DRGroup; uint32 hitTime; uint32 hitCount; + bool active; }; enum MeleeHitOutcome @@ -617,12 +607,11 @@ 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 UpdateDiminishingTime(DiminishingGroup group); + void AddDiminishing(DiminishingGroup group, uint32 hitCount, bool active); + DiminishingLevels GetDiminishing(DiminishingGroup group); + void IncrDiminishing(DiminishingGroup group); + void ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster, DiminishingLevels Level); virtual void Update( uint32 time );