From 4951f846dd423af54d4cc42d29e72a3d5dba2584 Mon Sep 17 00:00:00 2001 From: nos4r2zod Date: Sat, 15 May 2010 05:23:51 +0400 Subject: [PATCH] [9894] Move GetCastingTimeForBonus and some other code to GetSpellCastTimeForBonus. Important changes: * Chaged way caluclation "-5% of total per any additional effect" to percent apply instead use raw value that correct only for 3500 cast time spells. * GetSpellCastTimeForBonus result now alwasy not applied to creature casted spells Before it not applied only to instant spells. Please test if this ok in all cases. * Leech effect modify spell casting time move into GetCastingTimeForBonus and then called also for melee spells. But only creature spells exist with melee class damage and its not affected by GetCastingTimeForBonus anyway now. Signed-off-by: VladimirMangos --- src/game/SpellMgr.cpp | 101 +++++++++++++++++++ src/game/SpellMgr.h | 1 + src/game/Unit.cpp | 204 +++++++++++---------------------------- src/game/Unit.h | 2 - src/shared/revision_nr.h | 2 +- 5 files changed, 157 insertions(+), 153 deletions(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index fe5a05198..815284c7f 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -95,6 +95,107 @@ uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell) return (castTime > 0) ? uint32(castTime) : 0; } +uint32 GetSpellCastTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype ) +{ + uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); + + if (CastingTime > 7000) CastingTime = 7000; + if (CastingTime < 1500) CastingTime = 1500; + + if(damagetype == DOT && !IsChanneledSpell(spellProto)) + CastingTime = 3500; + + int32 overTime = 0; + uint8 effects = 0; + bool DirectDamage = false; + bool AreaEffect = false; + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + if (IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetA[i])) || IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetB[i]))) + AreaEffect = true; + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + switch (spellProto->Effect[i]) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_POWER_DRAIN: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_HEAL: + DirectDamage = true; + break; + case SPELL_EFFECT_APPLY_AURA: + switch (spellProto->EffectApplyAuraName[i]) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_LEECH: + if ( GetSpellDuration(spellProto) ) + overTime = GetSpellDuration(spellProto); + break; + // Penalty for additional effects + case SPELL_AURA_DUMMY: + ++effects; + break; + case SPELL_AURA_MOD_DECREASE_SPEED: + ++effects; + break; + case SPELL_AURA_MOD_CONFUSE: + case SPELL_AURA_MOD_STUN: + case SPELL_AURA_MOD_ROOT: + // -10% per effect + effects += 2; + break; + default: + break; + } + default: + break; + } + } + + // Combined Spells with Both Over Time and Direct Damage + if (overTime > 0 && CastingTime > 0 && DirectDamage) + { + // mainly for DoTs which are 3500 here otherwise + uint32 OriginalCastTime = GetSpellCastTime(spellProto); + if (OriginalCastTime > 7000) OriginalCastTime = 7000; + if (OriginalCastTime < 1500) OriginalCastTime = 1500; + // Portion to Over Time + float PtOT = (overTime / 15000.0f) / ((overTime / 15000.0f) + (OriginalCastTime / 3500.0f)); + + if (damagetype == DOT) + CastingTime = uint32(CastingTime * PtOT); + else if (PtOT < 1.0f) + CastingTime = uint32(CastingTime * (1 - PtOT)); + else + CastingTime = 0; + } + + // Area Effect Spells receive only half of bonus + if (AreaEffect) + CastingTime /= 2; + + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for(int j = 0; j < MAX_EFFECT_INDEX; ++j) + { + if (spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) + { + CastingTime /= 2; + break; + } + } + + // -5% of total per any additional effect (multiplicative) + for (int i = 0; i < effects; ++i) + CastingTime *= 0.95f; + + return CastingTime; +} + uint16 GetSpellAuraMaxTicks(SpellEntry const* spellInfo) { int32 DotDuration = GetSpellDuration(spellInfo); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index e9b8c5286..b709b7ca5 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -110,6 +110,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId); // Different spell properties inline float GetSpellRadius(SpellRadiusEntry const *radius) { return (radius ? radius->Radius : 0); } uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell = NULL); +uint32 GetSpellCastTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype ); inline float GetSpellMinRange(SpellRangeEntry const *range, bool friendly = false) { if(!range) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 3b3689239..ae2dd8d60 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9187,21 +9187,16 @@ uint32 Unit::SpellDamageBonusDone(Unit *pVictim, SpellEntry const *spellProto, u if (uint16 DotTicks = GetSpellAuraMaxTicks(spellProto)) DoneAdvertisedBenefit = DoneAdvertisedBenefit / DotTicks; } + // Distribute Damage over multiple effects, reduce by AoE - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for(int j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if (spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - (spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH)) - { - CastingTime /= 2; - break; - } - } - DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage); + // Not apply this to creature casted spells + float coeff; + if (GetTypeId()==TYPEID_UNIT && !((Creature*)this)->isPet()) + coeff = 1.0f; + else + coeff = GetSpellCastTimeForBonus(spellProto, damagetype) / 3500.0f; + + DoneTotal += int32(DoneAdvertisedBenefit * coeff * DotFactor * LvlPenalty * SpellModSpellDamage); } float tmpDamage = (int32(pdamage) + DoneTotal * int32(stack)) * DoneTotalMod; @@ -9294,21 +9289,16 @@ uint32 Unit::SpellDamageBonusTaken(Unit *pCaster, SpellEntry const *spellProto, if (uint16 DotTicks = GetSpellAuraMaxTicks(spellProto)) TakenAdvertisedBenefit = TakenAdvertisedBenefit / DotTicks; } + // Distribute Damage over multiple effects, reduce by AoE - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - CastingTime = pCaster->GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for(int j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if (spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - (spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH)) - { - CastingTime /= 2; - break; - } - } - TakenTotal+= int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty); + // Not apply this to creature casted spells + float coeff; + if (pCaster->GetTypeId()==TYPEID_UNIT && !((Creature*)pCaster)->isPet()) + coeff = 1.0f; + else + coeff = GetSpellCastTimeForBonus(spellProto, damagetype) / 3500.0f; + + TakenTotal+= int32(TakenAdvertisedBenefit * coeff * DotFactor * LvlPenalty); } float tmpDamage = (int32(pdamage) + TakenTotal * int32(stack)) * TakenTotalMod; @@ -9744,20 +9734,16 @@ uint32 Unit::SpellHealingBonusDone(Unit *pVictim, SpellEntry const *spellProto, if(DotTicks) DoneAdvertisedBenefit = DoneAdvertisedBenefit / DotTicks; } + // Distribute Damage over multiple effects, reduce by AoE - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for(int j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) - { - CastingTime /= 2; - break; - } - } - DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage * 1.88f); + // Not apply this to creature casted spells + float coeff; + if (GetTypeId()==TYPEID_UNIT && !((Creature*)this)->isPet()) + coeff = 1.0f; + else + coeff = GetSpellCastTimeForBonus(spellProto, damagetype) / 3500.0f; + + DoneTotal += int32(DoneAdvertisedBenefit * coeff * DotFactor * LvlPenalty * SpellModSpellDamage * 1.88f); } // use float as more appropriate for negative values and percent applying @@ -9827,20 +9813,16 @@ uint32 Unit::SpellHealingBonusTaken(Unit *pCaster, SpellEntry const *spellProto, if(DotTicks) TakenAdvertisedBenefit = TakenAdvertisedBenefit / DotTicks; } + // Distribute Damage over multiple effects, reduce by AoE - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - CastingTime = pCaster->GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for(int j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) - { - CastingTime /= 2; - break; - } - } - TakenTotal += int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * 1.88f); + // Not apply this to creature casted spells + float coeff; + if (GetTypeId()==TYPEID_UNIT && !((Creature*)this)->isPet()) + coeff = 1.0f; + else + coeff = GetSpellCastTimeForBonus(spellProto, damagetype) / 3500.0f; + + TakenTotal += int32(TakenAdvertisedBenefit * coeff * DotFactor * LvlPenalty * 1.88f); } AuraList const& mHealingGet= GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED); @@ -10249,10 +10231,16 @@ uint32 Unit::MeleeDamageBonusDone(Unit *pVictim, uint32 pdamage,WeaponAttackType if(DotTicks) DoneFlat = DoneFlat / DotTicks; } + // Distribute Damage over multiple effects, reduce by AoE - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - DoneFlat *= (CastingTime / 3500.0f) * DotFactor * LvlPenalty; + // Not apply this to creature casted spells + float coeff; + if (GetTypeId()==TYPEID_UNIT && !((Creature*)this)->isPet()) + coeff = 1.0f; + else + coeff = GetSpellCastTimeForBonus(spellProto, damagetype) / 3500.0f; + + DoneFlat *= coeff * DotFactor * LvlPenalty; } } // weapon damage based spells @@ -10403,10 +10391,16 @@ uint32 Unit::MeleeDamageBonusTaken(Unit *pCaster, uint32 pdamage,WeaponAttackTyp if(DotTicks) TakenFlat = TakenFlat / DotTicks; } + // Distribute Damage over multiple effects, reduce by AoE - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - CastingTime = pCaster->GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - TakenFlat*= (CastingTime / 3500.0f) * DotFactor * LvlPenalty; + // Not apply this to creature casted spells + float coeff; + if (pCaster->GetTypeId()==TYPEID_UNIT && !((Creature*)pCaster)->isPet()) + coeff = 1.0f; + else + coeff = GetSpellCastTimeForBonus(spellProto, damagetype) / 3500.0f; + + TakenFlat*= coeff * DotFactor * LvlPenalty; } } @@ -13253,96 +13247,6 @@ void Unit::ApplyCastTimePercentMod(float val, bool apply ) ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED,-val,apply); } -uint32 Unit::GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ) -{ - // Not apply this to creature casted spells with casttime==0 - if(CastingTime==0 && GetTypeId()==TYPEID_UNIT && !((Creature*)this)->isPet()) - return 3500; - - if (CastingTime > 7000) CastingTime = 7000; - if (CastingTime < 1500) CastingTime = 1500; - - if(damagetype == DOT && !IsChanneledSpell(spellProto)) - CastingTime = 3500; - - int32 overTime = 0; - uint8 effects = 0; - bool DirectDamage = false; - bool AreaEffect = false; - - for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - switch (spellProto->Effect[i]) - { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_POWER_DRAIN: - case SPELL_EFFECT_HEALTH_LEECH: - case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: - case SPELL_EFFECT_POWER_BURN: - case SPELL_EFFECT_HEAL: - DirectDamage = true; - break; - case SPELL_EFFECT_APPLY_AURA: - switch (spellProto->EffectApplyAuraName[i]) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_PERIODIC_LEECH: - if ( GetSpellDuration(spellProto) ) - overTime = GetSpellDuration(spellProto); - break; - default: - // -5% per additional effect - ++effects; - break; - } - default: - break; - } - - if (IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetA[i])) || IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetB[i]))) - AreaEffect = true; - } - - // Combined Spells with Both Over Time and Direct Damage - if (overTime > 0 && CastingTime > 0 && DirectDamage) - { - // mainly for DoTs which are 3500 here otherwise - uint32 OriginalCastTime = GetSpellCastTime(spellProto); - if (OriginalCastTime > 7000) OriginalCastTime = 7000; - if (OriginalCastTime < 1500) OriginalCastTime = 1500; - // Portion to Over Time - float PtOT = (overTime / 15000.0f) / ((overTime / 15000.0f) + (OriginalCastTime / 3500.0f)); - - if (damagetype == DOT) - CastingTime = uint32(CastingTime * PtOT); - else if (PtOT < 1.0f) - CastingTime = uint32(CastingTime * (1 - PtOT)); - else - CastingTime = 0; - } - - // Area Effect Spells receive only half of bonus - if (AreaEffect) - CastingTime /= 2; - - // -5% of total per any additional effect - for (uint8 i = 0; i < effects; ++i) - { - if (CastingTime > 175) - { - CastingTime -= 175; - } - else - { - CastingTime = 0; - break; - } - } - - return CastingTime; -} - void Unit::UpdateAuraForGroup(uint8 slot) { if(GetTypeId() == TYPEID_PLAYER) diff --git a/src/game/Unit.h b/src/game/Unit.h index bd0593b63..bf255d84d 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1748,8 +1748,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SetContestedPvP(Player *attackedPlayer = NULL); - uint32 GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ); - void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); void ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply); virtual bool IsImmunedToSpell(SpellEntry const* spellInfo); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 871efb5a6..b2b2e4d51 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9893" + #define REVISION_NR "9894" #endif // __REVISION_NR_H__