Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
UnitCombatBonus.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battlefield.h"
7#include "BattlefieldMgr.h"
8#include "Battleground.h"
9#include "CellImpl.h"
10#include "Common.h"
11#include "ConditionMgr.h"
12#include "Creature.h"
13#include "CreatureAI.h"
14#include "CreatureAIImpl.h"
15#include "CreatureGroups.h"
16#include "Formulas.h"
17#include "GridNotifiersImpl.h"
18#include "Group.h"
19#include "InstanceSaveMgr.h"
20#include "InstanceScript.h"
21#include "Log.h"
22#include "MapManager.h"
23#include "MovementStructures.h"
24#include "MoveSpline.h"
25#include "ObjectAccessor.h"
26#include "ObjectMgr.h"
27#include "Opcodes.h"
28#include "OutdoorPvP.h"
29#include "PassiveAI.h"
30#include "Pet.h"
31#include "PetAI.h"
32#include "Player.h"
33#include "QuestDef.h"
34#include "ReputationMgr.h"
35#include "Spell.h"
36#include "SpellAuraEffects.h"
37#include "SpellAuras.h"
38#include "SpellInfo.h"
39#include "SpellMgr.h"
40#include "TemporarySummon.h"
41#include "Totem.h"
42#include "Transport.h"
43#include "Unit.h"
44#include "UpdateFieldFlags.h"
45#include "Util.h"
46#include "Vehicle.h"
47#include "World.h"
48#include "WorldPacket.h"
49#include "WorldSession.h"
50
51#include <math.h>
52
53uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) const
54{
55 if (!spellProto || !victim || damagetype == DIRECT_DAMAGE)
56 return pdamage;
57
58 // Some spells don't benefit from done mods
60 return pdamage;
61
62 // small exception for Deep Wounds, can't find any general rule
63 // should ignore ALL damage mods, they already calculated in trigger spell
64 if (spellProto->Id == 12721) // Deep Wounds
65 return pdamage;
66
67 // For totems get damage bonus from owner
69 if (Unit* owner = GetOwner())
70 return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype);
71
72 // Done total percent damage auras
73 float DoneTotalMod = 1.0f;
74 float ApCoeffMod = 1.0f;
75 int32 DoneTotal = 0;
76
77 // Pet damage?
79 DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
80
81 // Some spells don't benefit from pct done mods
83 {
85 for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
86 {
87 if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
88 continue;
89
90 if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
91 {
92 if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
93 AddPct(DoneTotalMod, (*i)->GetAmount());
94 else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
95 AddPct(DoneTotalMod, (*i)->GetAmount());
96 else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
97 AddPct(DoneTotalMod, (*i)->GetAmount());
98 }
99 }
100 }
101
102 uint32 creatureTypeMask = victim->GetCreatureTypeMask();
103 // Add flat bonus from spell damage versus
106 for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
107 if (creatureTypeMask & uint32((*i)->GetMiscValue()))
108 AddPct(DoneTotalMod, (*i)->GetAmount());
109
110 // bonus against aurastate
112 for (AuraEffectList::const_iterator i = mDamageDoneVersusAurastate.begin(); i != mDamageDoneVersusAurastate.end(); ++i)
113 if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())))
114 AddPct(DoneTotalMod, (*i)->GetAmount());
115
116 // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus
118
119 // done scripted mod (take it from owner)
120 Unit const* owner = GetOwner() ? GetOwner() : this;
121 AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
122 for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
123 {
124 if (!(*i)->IsAffectingSpell(spellProto))
125 continue;
126
127 switch ((*i)->GetMiscValue())
128 {
129 case 5481: // Starfire Bonus // 5.4.8
130 {
131 if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0, 0))
132 AddPct(DoneTotalMod, (*i)->GetAmount());
133 break;
134 }
135 }
136 }
137
138 // Custom scripted damage
139 switch (spellProto->SpellFamilyName)
140 {
141 case SPELLFAMILY_MAGE:
142 // Ice Lance
143 if (spellProto->SpellIconID == 186)
144 if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
145 DoneTotalMod *= 2.0f;
146
147 // Torment the weak
148 if (spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_ARCANE)
149 {
150 if (victim->HasAuraWithMechanic((1 << MECHANIC_SNARE) | (1 << MECHANIC_SLOW_ATTACK)))
151 {
153 for (AuraEffectList::const_iterator i = mDumyAuras.begin(); i != mDumyAuras.end(); ++i)
154 {
155 if ((*i)->GetSpellInfo()->SpellIconID == 2215)
156 {
157 AddPct(DoneTotalMod, (*i)->GetAmount());
158 break;
159 }
160 }
161 }
162 }
163 break;
165 // Smite
166 if (spellProto->SpellFamilyFlags[0] & 0x00000080)
167 {
168 // Glyph of Smite
169 if (AuraEffect* aurEff = GetAuraEffect(55692, 0))
171 AddPct(DoneTotalMod, aurEff->GetAmount());
172 }
173 break;
175 // Fire and Brimstone
176 if (spellProto->SpellFamilyFlags[1] & 0x00020040)
178 {
180 for (AuraEffectList::const_iterator i = mDumyAuras.begin(); i != mDumyAuras.end(); ++i)
181 if ((*i)->GetSpellInfo()->SpellIconID == 3173)
182 {
183 AddPct(DoneTotalMod, (*i)->GetAmount());
184 break;
185 }
186 }
187 // Drain Soul - increased damage for targets under 25 % HP
188 if (spellProto->SpellFamilyFlags[0] & 0x00004000)
189 if (HasAura(100001))
190 DoneTotalMod *= 2;
191 // Shadow Bite (30% increase from each dot)
192 if (spellProto->SpellFamilyFlags[1] & 0x00400000 && IsPet())
193 if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID()))
194 AddPct(DoneTotalMod, 30 * count);
195 break;
196 }
197
198 // Done fixed damage bonus auras
199 int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask());
200 // Pets just add their bonus damage to their spell damage
201 // note that their spell damage is just gain of their own auras
203 DoneAdvertisedBenefit += ((Guardian*)this)->GetBonusDamage();
204
205 // Check for table values
206 float coeff = 0;
207 SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
208 if (bonus)
209 {
210 if (damagetype == DOT)
211 {
212 coeff = bonus->dot_damage;
213 if (bonus->ap_dot_bonus > 0)
214 {
217 APbonus += GetTotalAttackPowerValue(attType);
218 DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus);
219 }
220 }
221 else
222 {
223 coeff = bonus->direct_damage;
224 if (bonus->ap_bonus > 0)
225 {
228 APbonus += GetTotalAttackPowerValue(attType);
229 DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
230 }
231 }
232 }
233 // Default calculation
234 if (DoneAdvertisedBenefit)
235 {
236 if (!bonus || coeff < 0)
237 coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
238
239 float factorMod = CalculateLevelPenalty(spellProto) * stack;
240
241 if (Player* modOwner = GetSpellModOwner())
242 {
243 coeff *= 100.0f;
244 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
245 coeff /= 100.0f;
246 }
247 DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
248 }
249
250 float tmpDamage = (int32(pdamage) + DoneTotal) * DoneTotalMod;
251 // apply spellmod to Done damage (flat and pct)
252 if (Player* modOwner = GetSpellModOwner())
253 modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
254
255 return uint32(std::max(tmpDamage, 0.0f));
256}
257
258uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) const
259{
260 if (!spellProto || damagetype == DIRECT_DAMAGE)
261 return pdamage;
262
263 int32 TakenTotal = 0;
264 float TakenTotalMod = 1.0f;
265 float TakenTotalCasterMod = 0.0f;
266
267 // get all auras from caster that allow the spell to ignore resistance (sanctified wrath)
269 for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i)
270 {
271 if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
272 TakenTotalCasterMod += (float((*i)->GetAmount()));
273 }
274
275 // from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
276 // multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085)
278
279 //.. taken pct: dummy auras
281 for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
282 {
283 switch ((*i)->GetSpellInfo()->SpellIconID)
284 {
285 // Cheat Death
286 case 2109:
287 if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
288 {
290 continue;
291 AddPct(TakenTotalMod, (*i)->GetAmount());
292 }
293 break;
294 }
295 }
296
297 // From caster spells
299 for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
300 if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectingSpell(spellProto))
301 AddPct(TakenTotalMod, (*i)->GetAmount());
302
303 // Mod damage from spell mechanic
304 if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask())
305 {
307 for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i)
308 if (mechanicMask & uint32(1 << ((*i)->GetMiscValue())))
309 AddPct(TakenTotalMod, (*i)->GetAmount());
310 }
311
312 int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask());
313
314 // Check for table values
315 float coeff = 0;
316 SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
317 if (bonus)
318 coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
319
320 // Default calculation
321 if (TakenAdvertisedBenefit)
322 {
323 if (!bonus || coeff < 0)
324 coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
325
326 float factorMod = CalculateLevelPenalty(spellProto) * stack;
327 // level penalty still applied on Taken bonus - is it blizzlike?
328 if (Player* modOwner = GetSpellModOwner())
329 {
330 coeff *= 100.0f;
331 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
332 coeff /= 100.0f;
333 }
334 TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
335 }
336
337 float tmpDamage = 0.0f;
338
339 if (TakenTotalCasterMod)
340 {
341 if (TakenTotal < 0)
342 {
343 if (TakenTotalMod < 1)
344 tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenTotal) * TakenTotalMod) + CalculatePct(pdamage, TakenTotalCasterMod));
345 else
346 tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenTotal) + CalculatePct(pdamage, TakenTotalCasterMod)) * TakenTotalMod);
347 }
348 else if (TakenTotalMod < 1)
349 tmpDamage = ((CalculatePct(float(pdamage) + TakenTotal, TakenTotalCasterMod) * TakenTotalMod) + CalculatePct(float(pdamage) + TakenTotal, TakenTotalCasterMod));
350 }
351 if (!tmpDamage)
352 tmpDamage = (float(pdamage) + TakenTotal) * TakenTotalMod;
353
354 return uint32(std::max(tmpDamage, 0.0f));
355}
356
357uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack) const
358{
359 // For totems get healing bonus from owner (statue isn't totem in fact)
361 if (Unit* owner = GetOwner())
362 return owner->SpellHealingBonusDone(victim, spellProto, healamount, damagetype, stack);
363
364 // No bonus healing for potion spells
365 if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
366 return healamount;
367
368 float DoneTotalMod = 1.0f;
369 int32 DoneTotal = 0;
370
371 // Healing done percent
373 for (AuraEffectList::const_iterator i = mHealingDonePct.begin(); i != mHealingDonePct.end(); ++i)
374 AddPct(DoneTotalMod, (*i)->GetAmount());
375
376 // done scripted mod (take it from owner)
377 Unit const* owner = GetOwner() ? GetOwner() : this;
378 AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
379 for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
380 {
381 if (!(*i)->IsAffectingSpell(spellProto))
382 continue;
383 switch ((*i)->GetMiscValue())
384 {
385 case 8477: // Nourish Heal Boost // 5.4.8
386 {
387 int32 stepPercent = (*i)->GetAmount();
388 int32 modPercent = 0;
389 AuraApplicationMap const& victimAuras = victim->GetAppliedAuras();
390 for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
391 {
392 Aura const* aura = itr->second->GetBase();
393 if (aura->GetCasterGUID() != GetGUID())
394 continue;
395 SpellInfo const* m_spell = aura->GetSpellInfo();
396 if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID ||
397 !(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50))
398 continue;
399 modPercent += stepPercent * aura->GetStackAmount();
400 }
401 AddPct(DoneTotalMod, modPercent);
402 break;
403 }
404 default:
405 break;
406 }
407 }
408
409 // Done fixed damage bonus auras
410 int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask());
411
412 // Check for table values
413 SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
414 float coeff = 0;
415 float factorMod = 1.0f;
416 if (bonus)
417 {
418 if (damagetype == DOT)
419 {
420 coeff = bonus->dot_damage;
421 if (bonus->ap_dot_bonus > 0)
422 DoneTotal += int32(bonus->ap_dot_bonus * stack * GetTotalAttackPowerValue(
424 }
425 else
426 {
427 coeff = bonus->direct_damage;
428 if (bonus->ap_bonus > 0)
429 DoneTotal += int32(bonus->ap_bonus * stack * GetTotalAttackPowerValue(
431 }
432 }
433 else
434 {
435 // No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
436 if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
437 return healamount;
438 }
439
440 // Default calculation
441 if (DoneAdvertisedBenefit)
442 {
443 if (!bonus || coeff < 0)
444 coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells)
445
446 factorMod *= CalculateLevelPenalty(spellProto) * stack;
447
448 if (Player* modOwner = GetSpellModOwner())
449 {
450 coeff *= 100.0f;
451 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
452 coeff /= 100.0f;
453 }
454
455 DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
456 }
457
458 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
459 {
460 switch (spellProto->Effects[i].ApplyAuraName)
461 {
462 // Bonus healing does not apply to these spells
465 DoneTotal = 0;
466 break;
467 }
468 if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH)
469 DoneTotal = 0;
470 }
471
472 // use float as more appropriate for negative values and percent applying
473 float heal = float(int32(healamount) + DoneTotal) * DoneTotalMod;
474 // apply spellmod to Done amount
475 if (Player* modOwner = GetSpellModOwner())
476 modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
477
478 return uint32(std::max(heal, 0.0f));
479}
480
481uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack) const
482{
483 float TakenTotalMod = 1.0f;
484
485 // Healing taken percent
487 if (minval)
488 AddPct(TakenTotalMod, minval);
489
491 if (maxval)
492 AddPct(TakenTotalMod, maxval);
493
494 // Tenacity increase healing % taken
495 if (AuraEffect const* Tenacity = GetAuraEffect(58549, 0))
496 AddPct(TakenTotalMod, Tenacity->GetAmount());
497
498 // Healing Done
499 int32 TakenTotal = 0;
500
501 // Taken fixed damage bonus auras
502 int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(spellProto->GetSchoolMask());
503
504 // Nourish cast
505 if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[1] & 0x2000000)
506 {
507 // Rejuvenation, Regrowth, Lifebloom, or Wild Growth
509 // increase healing by 20%
510 TakenTotalMod *= 1.2f;
511 }
512
513 // Check for table values
514 SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
515 float coeff = 0;
516 float factorMod = 1.0f;
517 if (bonus)
518 coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
519 else
520 {
521 // No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
522 if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
523 {
524 healamount = uint32(std::max((float(healamount) * TakenTotalMod), 0.0f));
525 return healamount;
526 }
527 }
528
529 // Default calculation
530 if (TakenAdvertisedBenefit)
531 {
532 if (!bonus || coeff < 0)
533 coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells)
534
535 factorMod *= CalculateLevelPenalty(spellProto) * int32(stack);
536 if (Player* modOwner = GetSpellModOwner())
537 {
538 coeff *= 100.0f;
539 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
540 coeff /= 100.0f;
541 }
542
543 TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
544 }
545
546 if (damagetype == DOT)
547 {
548 // Healing over time taken percent
550 if (val_hot)
551 TakenTotalMod *= (100.0f + val_hot) / 100.0f;
552 }
553
555 for (AuraEffectList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
556 if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectingSpell(spellProto))
557 AddPct(TakenTotalMod, (*i)->GetAmount());
558
559 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
560 {
561 switch (spellProto->Effects[i].ApplyAuraName)
562 {
563 // Bonus healing does not apply to these spells
566 TakenTotal = 0;
567 break;
568 }
569 if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH)
570 TakenTotal = 0;
571 }
572
573 float heal = float(int32(healamount) + TakenTotal) * TakenTotalMod;
574
575 return uint32(std::max(heal, 0.0f));
576}
577
578uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
579{
580 if (!victim || pdamage == 0)
581 return 0;
582
583 uint32 creatureTypeMask = victim->GetCreatureTypeMask();
584
585 // Done fixed damage bonus auras
586 int32 DoneFlatBenefit = 0;
587
588 // ..done
590 for (AuraEffectList::const_iterator i = mDamageDoneCreature.begin(); i != mDamageDoneCreature.end(); ++i)
591 if (creatureTypeMask & uint32((*i)->GetMiscValue()))
592 DoneFlatBenefit += (*i)->GetAmount();
593
594 // ..done
595 // SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage
596
597 // ..done (base at attack power for marked target and base at attack power for creature type)
598 int32 APbonus = 0;
599
600 if (attType == WeaponAttackType::RANGED_ATTACK)
601 {
603
604 // ..done (base at attack power and creature type)
606 for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i)
607 if (creatureTypeMask & uint32((*i)->GetMiscValue()))
608 APbonus += (*i)->GetAmount();
609 }
610 else
611 {
613
614 // ..done (base at attack power and creature type)
616 for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i)
617 if (creatureTypeMask & uint32((*i)->GetMiscValue()))
618 APbonus += (*i)->GetAmount();
619 }
620
621 if (APbonus != 0) // Can be negative
622 {
623 bool normalized = false;
624 if (spellProto)
625 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
627 {
628 normalized = true;
629 break;
630 }
631 DoneFlatBenefit += int32(APbonus / 14.0f * GetAPMultiplier(attType, normalized));
632 }
633
634 // Done total percent damage auras
635 float DoneTotalMod = 1.0f;
636
637 // Some spells don't benefit from pct done mods
638 if (spellProto)
640 {
642 for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
643 {
644 if ((*i)->GetMiscValue() & spellProto->GetSchoolMask() && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_NORMAL))
645 {
646 if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
647 AddPct(DoneTotalMod, (*i)->GetAmount());
648 else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
649 AddPct(DoneTotalMod, (*i)->GetAmount());
650 else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
651 AddPct(DoneTotalMod, (*i)->GetAmount());
652 }
653 }
654 }
655
657 for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
658 if (creatureTypeMask & uint32((*i)->GetMiscValue()))
659 AddPct(DoneTotalMod, (*i)->GetAmount());
660
661 // bonus against aurastate
663 for (AuraEffectList::const_iterator i = mDamageDoneVersusAurastate.begin(); i != mDamageDoneVersusAurastate.end(); ++i)
664 if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())))
665 AddPct(DoneTotalMod, (*i)->GetAmount());
666
667 // Add SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC percent bonus
668 if (spellProto)
670
671 float tmpDamage = float(int32(pdamage) + DoneFlatBenefit) * DoneTotalMod;
672
673 // apply spellmod to Done damage
674 if (spellProto)
675 if (Player* modOwner = GetSpellModOwner())
676 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
677
678 // bonus result can be negative
679 return uint32(std::max(tmpDamage, 0.0f));
680}
681
682uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
683{
684 if (pdamage == 0)
685 return 0;
686
687 int32 TakenFlatBenefit = 0;
688 float TakenTotalCasterMod = 0.0f;
689
690 // get all auras from caster that allow the spell to ignore resistance (sanctified wrath)
691 SpellSchoolMask attackSchoolMask = spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL;
692 AuraEffectList const& IgnoreResistAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
693 for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i)
694 {
695 if ((*i)->GetMiscValue() & attackSchoolMask)
696 TakenTotalCasterMod += (float((*i)->GetAmount()));
697 }
698
699 // ..taken
701 for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i)
702 if ((*i)->GetMiscValue() & attacker->GetMeleeDamageSchoolMask())
703 TakenFlatBenefit += (*i)->GetAmount();
704
705 if (attType != WeaponAttackType::RANGED_ATTACK)
707 else
709
710 // Taken total percent damage auras
711 float TakenTotalMod = 1.0f;
712
713 // ..taken
715
716 // .. taken pct (special attacks)
717 if (spellProto)
718 {
719 // From caster spells
721 for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
722 if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectingSpell(spellProto))
723 AddPct(TakenTotalMod, (*i)->GetAmount());
724
725 // Mod damage from spell mechanic
726 uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask();
727
728 // Shred, Maul - "Effects which increase Bleed damage also increase Shred damage"
729 if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[0] & 0x00008800)
730 mechanicMask |= (1 << MECHANIC_BLEED);
731
732 if (mechanicMask)
733 {
735 for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i)
736 if (mechanicMask & uint32(1 << ((*i)->GetMiscValue())))
737 AddPct(TakenTotalMod, (*i)->GetAmount());
738 }
739 }
740
741 // .. taken pct: dummy auras
743 for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
744 {
745 switch ((*i)->GetSpellInfo()->SpellIconID)
746 {
747 // Cheat Death
748 case 2109:
749 if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
750 {
752 continue;
754 AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
755 }
756 break;
757 }
758 }
759
760 if (attType != WeaponAttackType::RANGED_ATTACK)
761 {
763 for (AuraEffectList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i)
764 AddPct(TakenTotalMod, (*i)->GetAmount());
765 }
766 else
767 {
769 for (AuraEffectList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i)
770 AddPct(TakenTotalMod, (*i)->GetAmount());
771 }
772
773 float tmpDamage = 0.0f;
774
775 if (TakenTotalCasterMod)
776 {
777 if (TakenFlatBenefit < 0)
778 {
779 if (TakenTotalMod < 1)
780 tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) * TakenTotalMod) + CalculatePct(pdamage, TakenTotalCasterMod));
781 else
782 tmpDamage = ((float(CalculatePct(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) + CalculatePct(pdamage, TakenTotalCasterMod)) * TakenTotalMod);
783 }
784 else if (TakenTotalMod < 1)
785 tmpDamage = ((CalculatePct(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod) * TakenTotalMod) + CalculatePct(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod));
786 }
787 if (!tmpDamage)
788 tmpDamage = (float(pdamage) + TakenFlatBenefit) * TakenTotalMod;
789
790 // bonus result can be negative
791 return uint32(std::max(tmpDamage, 0.0f));
792}
793
794float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
795{
796 if (!normalized || GetTypeId() != TypeID::TYPEID_PLAYER)
797 return float(GetAttackTime(attType)) / 1000.0f;
798
799 Item* Weapon = ToPlayer()->GetWeaponForAttack(attType, true);
800 if (!Weapon)
801 return 2.4f; // fist attack
802
803 switch (Weapon->GetTemplate()->InventoryType)
804 {
805 case INVTYPE_2HWEAPON:
806 return 3.3f;
807 case INVTYPE_RANGED:
809 case INVTYPE_THROWN:
810 return 2.8f;
811 case INVTYPE_WEAPON:
814 default:
815 return Weapon->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER ? 1.7f : 2.4f;
816 }
817}
#define MAX_SPELL_EFFECTS
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
@ ITEM_SUBCLASS_WEAPON_DAGGER
@ INVTYPE_RANGED
@ INVTYPE_THROWN
@ INVTYPE_RANGEDRIGHT
@ INVTYPE_WEAPON
@ INVTYPE_WEAPONMAINHAND
@ INVTYPE_WEAPONOFFHAND
@ INVTYPE_2HWEAPON
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
@ SPELL_EFFECT_HEALTH_LEECH
@ SPELL_EFFECT_NORMALIZED_WEAPON_DMG
@ SPELL_DAMAGE_CLASS_NONE
@ SPELL_DAMAGE_CLASS_MELEE
@ SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS
@ SPELL_ATTR3_NO_DONE_BONUS
@ SPELLFAMILY_PRIEST
@ SPELLFAMILY_WARLOCK
@ SPELLFAMILY_MAGE
@ SPELLFAMILY_POTION
@ SPELLFAMILY_DRUID
@ SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK
AuraStateType
@ AURA_STATE_FROZEN
@ AURA_STATE_CONFLAGRATE
@ MECHANIC_SLOW_ATTACK
@ MECHANIC_BLEED
@ MECHANIC_SNARE
SpellSchoolMask
@ SPELL_SCHOOL_MASK_NORMAL
@ SPELL_SCHOOL_MASK_ARCANE
@ SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_MOD_IGNORE_TARGET_RESIST
@ SPELL_AURA_MOD_DAMAGE_DONE_VERSUS
@ SPELL_AURA_PERIODIC_HEALTH_FUNNEL
@ SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS
@ SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN
@ SPELL_AURA_MOD_HEALING_DONE_PERCENT
@ SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS
@ SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
@ SPELL_AURA_MOD_HEALING_RECEIVED
@ SPELL_AURA_MOD_HEALING_PCT
@ SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
@ SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN
@ SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT
@ SPELL_AURA_MOD_DAMAGE_TAKEN
@ SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE
@ SPELL_AURA_MOD_HOT_PCT
@ SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS
@ SPELL_AURA_MOD_DAMAGE_DONE_FOR_MECHANIC
@ SPELL_AURA_MOD_DAMAGE_DONE_CREATURE
@ SPELL_AURA_PERIODIC_LEECH
@ SPELL_AURA_MOD_DAMAGE_FROM_CASTER
@ SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT
@ SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT
@ SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
#define sSpellMgr
Definition SpellMgr.h:744
@ UNIT_MASK_GUARDIAN
Definition Unit.h:807
WeaponAttackType
Definition Unit.h:572
@ SPELLMOD_DAMAGE
Definition Unit.h:73
@ SPELLMOD_DOT
Definition Unit.h:95
@ SPELLMOD_BONUS_MULTIPLIER
Definition Unit.h:97
@ CR_RESILIENCE_PLAYER_DAMAGE_TAKEN
Definition Unit.h:596
DamageEffectType
Definition Unit.h:613
@ DIRECT_DAMAGE
Definition Unit.h:614
@ DOT
Definition Unit.h:616
T AddPct(T &base, U pct)
Definition Util.h:109
T CalculatePct(T base, U pct)
Definition Util.h:103
uint64 GetCasterGUID() const
Definition SpellAuras.h:91
uint8 GetStackAmount() const
Definition SpellAuras.h:133
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:87
float GetSpellDamageMod(int32 Rank) const
Definition Item.h:202
ItemTemplate const * GetTemplate() const
Definition Item.cpp:528
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
TypeID GetTypeId() const
Definition Object.h:131
Creature * ToCreature()
Definition Object.h:207
float GetRatingBonusValue(CombatRating cr) const
Definition Player.cpp:5924
Item * GetWeaponForAttack(WeaponAttackType attackType, bool useable=false) const
uint32 ApplyAuraName
Definition SpellInfo.h:90
SpellEffectInfo Effects[MAX_SPELL_EFFECTS]
Definition SpellInfo.h:255
uint32 Mechanic
Definition SpellInfo.h:163
uint32 Id
Definition SpellInfo.h:160
int32 EquippedItemClass
Definition SpellInfo.h:215
flag128 SpellFamilyFlags
Definition SpellInfo.h:227
uint32 AttributesEx3
Definition SpellInfo.h:167
SpellSchoolMask GetSchoolMask() const
uint32 AttributesEx6
Definition SpellInfo.h:170
uint32 GetAllEffectsMechanicMask() const
uint32 SpellIconID
Definition SpellInfo.h:220
uint32 DmgClass
Definition SpellInfo.h:228
bool IsRangedWeaponSpell() const
uint32 SpellFamilyName
Definition SpellInfo.h:226
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:2243
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=NULL, Unit const *Caster=NULL) const
Unit * GetOwner() const
Definition Unit.cpp:2339
Player * GetSpellModOwner() const
Definition Unit.cpp:5818
std::multimap< uint32, AuraApplication * > AuraApplicationMap
Definition Unit.h:1376
float CalculateDefaultCoefficient(SpellInfo const *spellInfo, DamageEffectType damagetype) const
Definition Unit.cpp:6213
uint32 SpellHealingBonusDone(Unit *victim, SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack=1) const
uint32 MeleeDamageBonusTaken(Unit *attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const *spellProto=NULL)
bool IsPet() const
Definition Unit.h:1511
bool HasAuraWithMechanic(uint32 mechanicMask) const
int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
uint32 SpellHealingBonusTaken(Unit *caster, SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack=1) const
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const
Definition Unit.cpp:3099
int32 GetMaxPositiveAuraModifier(AuraType auratype) const
uint32 MeleeDamageBonusDone(Unit *pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const *spellProto=NULL)
uint32 GetAttackTime(WeaponAttackType att) const
Definition Unit.cpp:4122
uint32 SpellDamageBonusDone(Unit *victim, SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack=1) const
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, uint64 casterGUID=0) const
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const
Definition Unit.cpp:3365
float GetAPMultiplier(WeaponAttackType attType, bool normalized)
Unit(bool isWorldObject)
Definition Unit.cpp:142
int32 GetMaxNegativeAuraModifier(AuraType auratype) const
int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
uint32 SpellDamageBonusTaken(Unit *caster, SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack=1) const
uint32 HasUnitTypeMask(uint32 mask) const
Definition Unit.h:1495
uint64 GetOwnerGUID() const
Definition Unit.h:2050
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
virtual SpellSchoolMask GetMeleeDamageSchoolMask() const
Definition Unit.cpp:5801
int32 GetTotalAuraModifier(AuraType auratype) const
uint32 GetCreatureTypeMask() const
Definition Unit.cpp:4925
AuraApplicationMap & GetAppliedAuras()
Definition Unit.h:2204
std::list< AuraEffect * > AuraEffectList
Definition Unit.h:1383
bool IsTotem() const
Definition Unit.h:1519
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask) const
Definition Unit.cpp:3403
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
Definition Unit.cpp:3055
float CalculateLevelPenalty(SpellInfo const *spellProto) const
float GetTotalAttackPowerValue(WeaponAttackType attType) const
Definition Unit.cpp:5118
uint32 GetDoTsByCaster(uint64 casterGUID) const
uint32 InventoryType
Definition SpellMgr.h:304
float ap_dot_bonus
Definition SpellMgr.h:308
float dot_damage
Definition SpellMgr.h:306
float ap_bonus
Definition SpellMgr.h:307
float direct_damage
Definition SpellMgr.h:305