Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 5320) +++ src/game/Unit.cpp (working copy) @@ -6388,24 +6388,99 @@ } } + // Common Rules + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + // Don't use Spell Damage, can be overwritten by code Below + if ( spellProto->DmgType != SPELL_DAMAGE_CLASS_MAGIC ) + CastingTime = 0; // Exceptions switch(spellProto->SpellFamilyName) { + case SPELLFAMILY_PALADIN: + // Consecration - 95% of Holy Damage + if((spellProto->SpellFamilyFlags & 0x20LL) && spellProto->SpellIconID == 51 ) + { + DotFactor = 0.95f; + CastingTime = 3500; + } + // Seal of Righteousness - 10.2%/9.8% ( based on weapon type ) of Holy Damage, multiplied by weapon speed + else if((spellProto->SpellFamilyFlags & 0x8000000LL) && spellProto->SpellIconID == 25) + { + Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + float wspeed = GetAttackTime(BASE_ATTACK)/1000; + + if( item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON) + CastingTime = (uint32)wspeed*3500*0.102f; + else + CastingTime = (uint32)wspeed*3500*0.098f; + } + // Seal of Vengeance - 17% per Fully Stacked Tick - 5 Applications + else if ((spellProto->SpellFamilyFlags & 0x80000000000LL) && spellProto->SpellIconID == 2040) + { + DotFactor = 0.136; + CastingTime = 3500; + } + // Seal of Command - 20% of Done Holy Damage, 29% of Taken Holy Damage + else if (spellProto->Id == 20424) + { + CastingTime = 3500; + DoneTotalMod = 0.2f; + TakenTotalMod = 0.29f; + } + // Holy shield - 5% of Holy Damage + else if ((spellProto->SpellFamilyFlags & 0x4000000000LL) && spellProto->SpellIconID == 453) + { + CastingTime = 175; + } + break; case SPELLFAMILY_WARLOCK: - // Life Tap + // Life Tap - 80% of Shadow Damage if((spellProto->SpellFamilyFlags & 0x40000LL) && spellProto->SpellIconID == 208) { - CastingTime = 2800; // 80% from +shadow damage + CastingTime = 2800; DoneTotalMod = 1.0f; TakenTotalMod = 1.0f; } - // Dark Pact + // Dark Pact - 96% of Shadow Damage else if((spellProto->SpellFamilyFlags & 0x80000000LL) && spellProto->SpellIconID == 154 && GetPetGUID()) { - CastingTime = 3360; // 96% from +shadow damage + CastingTime = 3360; DoneTotalMod = 1.0f; TakenTotalMod = 1.0f; } + // Soul Fire - 115% of Fire Damage + else if((spellProto->SpellFamilyFlags & 0x8000000000LL) && spellProto->SpellIconID == 184) + { + CastingTime = 4025; + } + // Death Coil - 21.4% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x80000LL) && spellProto->SpellIconID == 88) + { + CastingTime = 749; + } + // Curse of Agony - 120% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x0000000400LL) && spellProto->SpellIconID == 544) + { + DotFactor = 1.2f; + CastingTime = 3500; + } + // Siphon Life - 100% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x0100000000LL) && spellProto->SpellIconID == 152) + { + DotFactor = 1.0f; + CastingTime = 3500; + } + // Drain Mana - 0% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x10LL) && spellProto->SpellIconID == 548) + { + CastingTime = 0; + } + // Seed of Corruption 122% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x1000000000LL) && spellProto->SpellIconID == 1932 && damagetype == DOT) + { + DotFactor = 1.22f; + CastingTime = 3500; + } break; case SPELLFAMILY_MAGE: // Ice Lance @@ -6415,25 +6490,54 @@ if(pVictim->isFrozen()) // and compensate this for frozen target. TakenTotalMod *= 3.0f; } - // Molten armor - else if (spellProto->SpellFamilyFlags & 0x0000000800000000LL) - CastingTime = 0; + // Pyroblast - 115% of Fire Damage, DoT - 20% of Fire Damage + else if((spellProto->SpellFamilyFlags & 0x400000LL) && spellProto->SpellIconID == 184 ) + { + DotFactor = damagetype == DOT ? 0.2f : 1.0f; + CastingTime = damagetype == DOT ? 3500 : 4025; + } + // Fireball - 100% of Fire Damage, DoT - 0% of Fire Damage + else if((spellProto->SpellFamilyFlags & 0x1LL) && spellProto->SpellIconID == 185) + { + CastingTime = 3500; + DotFactor = damagetype == DOT ? 0 : 1.0f; + } break; case SPELLFAMILY_SHAMAN: - // totem attack + // Totem attack if (spellProto->SpellFamilyFlags & 0x000040000000LL) { - if (spellProto->SpellIconID == 33) // Fire Nova totem attack must be 21.4%(untested) - CastingTime = 749; // ignore CastingTime and use as modifier - else if (spellProto->SpellIconID == 680) // Searing Totem attack 8% - CastingTime = 280; // ignore CastingTime and use as modifier - else if (spellProto->SpellIconID == 37) // Magma totem attack must be 6.67%(untested) - CastingTime = 234; // ignore CastingTimePenalty and use as modifier + // Fire Nova totem - 21.4% of Fire Damage + if (spellProto->SpellIconID == 33) + CastingTime = 749; + // Searing Totem attack - 8% of Fire Damage + else if (spellProto->SpellIconID == 680) + CastingTime = 280; + // Magma totem attack - 6.67% of Fire Damage + else if (spellProto->SpellIconID == 37) + CastingTime = 234; } - // Lighting Shield 33% per charge + // Lighting Shield - 33% of Nature Damage per charge else if (spellProto->SpellFamilyFlags & 000000400LL) - CastingTime = 1155; // ignore CastingTimePenalty and use as modifier + { + CastingTime = 1155; + } break; + case SPELLFAMILY_PRIEST: + // Mana Burn - 0% of Shadow Damage + if((spellProto->SpellFamilyFlags & 0x10LL) && spellProto->SpellIconID == 212 ) + { + CastingTime = 0; + } + // Mind Flay - 59% of Shadow Damage + else if((spellProto->SpellFamilyFlags & 0x800000LL) && spellProto->SpellIconID == 548 ) + { + CastingTime = 3500; + DotFactor = 0.59f; + } + break; + default: + break; } // Level Factor @@ -6680,15 +6784,26 @@ AdvertisedBenefit /= DotTicks; } } - // Exception - switch (spellProto->SpellFamilyName) + + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + // Don't use Spell Damage, can be overwritten by code Below + if ( spellProto->DmgType != SPELL_DAMAGE_CLASS_MAGIC ) + CastingTime = 0; + // Exceptions + switch(spellProto->SpellFamilyName) { case SPELLFAMILY_SHAMAN: - // Healing stream from totem (add 6% per tick from hill bonus owner) - if (spellProto->SpellFamilyFlags & 0x000000002000LL) - CastingTime = 210; // + // Healing stream from totem - 6% of Spell Healing per tick + if (spellProto->SpellFamilyFlags & 0x000000002000LL) + { + CastingTime = 210; + } break; + default: + break; } + + // Level Factor float LvlPenalty = 0.0f; if(spellProto->spellLevel < 20) @@ -8991,3 +9106,81 @@ else ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED,-val,apply); } + +uint32 Unit::GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ) +{ + int32 overTime=0; + bool direct=false; + bool AreaEffect=false; + + for ( uint32 i=0; i<3;i++) + { + switch ( spellProto->Effect[i] ) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_MANA_DRAIN: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_HEAL: + direct = 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 + CastingTime *= 0.95f; + break; + } + default: + break; + } + + switch (spellProto->EffectImplicitTargetA[i]) + { + case TARGET_ALL_AROUND_CASTER: + case TARGET_ALL_PARTY_AROUND_CASTER: + case TARGET_ALL_PARTY: + case TARGET_ALL_ENEMY_IN_AREA: + case TARGET_ALL_ENEMY_IN_AREA_INSTANT: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: + case TARGET_AREAEFFECT_PARTY: + AreaEffect = true; + break; + default: + break; + } + } + + // Combined Spells with Both Over Time and Direct Damage + if ( overTime > 0 && CastingTime > 0 && direct ) + { + // Portion to Over Time + float PtOT = (overTime / 15000.f) / ((overTime / 15000.f) + (CastingTime / 3500.f)); + + if ( damagetype == DOT ) + CastingTime *= PtOT; + else if ( PtOT < 1 ) + CastingTime *= 1 - PtOT; + else + CastingTime = 0; + } + + // Area Effect Spells recieve only half of bonus + if ( AreaEffect ) + CastingTime *= 0.5f; + + return CastingTime; +} Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 5320) +++ src/game/Unit.h (working copy) @@ -962,6 +962,7 @@ int32 SpellBaseHealingBonusForVictim(int32 SchoolMask, Unit *pVictim); uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype); uint32 SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim); + uint32 GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ); bool SpellCriticalBonus(SpellEntry const *spellProto, uint32 *damage, Unit *pVictim); void MeleeDamageBonus(Unit *pVictim, uint32 *damage, WeaponAttackType attType, SpellEntry const *spellProto = NULL); void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); Index: src/shared/Database/DBCfmt.cpp =================================================================== --- src/shared/Database/DBCfmt.cpp (revision 5320) +++ src/shared/Database/DBCfmt.cpp (working copy) @@ -52,7 +52,7 @@ const char SkillLineAbilityfmt[]="xiniixxiixiixxi"; const char SpellCastTimefmt[]="nixx"; const char SpellDurationfmt[]="niii"; -const char SpellEntryfmt[]="niixiiiiiiixixiiiiixxiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiifffixiiissssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiixxfffxxxiii"; +const char SpellEntryfmt[]="niixiiiiiiixixiiiiixxiiiiiiiiiiiiiiiiiiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiifffixiiissssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiixfffxxxiii"; //const char SpellFocusObjectfmt[]="nsxxxxxxxx"; const char SpellItemEnchantmentfmt[]="niiiiiixxxiiissssssssssssssssxiiii"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; Index: src/shared/Database/DBCStructure.h =================================================================== --- src/shared/Database/DBCStructure.h (revision 5320) +++ src/shared/Database/DBCStructure.h (working copy) @@ -495,7 +495,8 @@ uint64 SpellFamilyFlags; // 196+197 uint32 MaxAffectedTargets; // 198 uint32 DmgClass; // 199 - //uint32 unk2[2]; // 200-201 not used + uint32 DmgType; // 200 + //uint32 unk2; // 201 not used float DmgMultiplier[3]; // 202-204 //uint32 unk3[3]; // 205-207 not used null uint32 TotemCategory[2]; // 208-209