TrinityCore
Loading...
Searching...
No Matches
StatSystem.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Unit.h"
19#include "DB2Stores.h"
20#include "Item.h"
21#include "Player.h"
22#include "Pet.h"
23#include "GameTables.h"
24#include "GameTime.h"
25#include "ObjectMgr.h"
26#include "SharedDefines.h"
27#include "SpellAuras.h"
28#include "SpellAuraEffects.h"
29#include "World.h"
30#include <G3D/g3dmath.h>
31#include <numeric>
32
33inline bool _ModifyUInt32(bool apply, uint32& baseValue, int32& amount)
34{
35 // If amount is negative, change sign and value of apply.
36 if (amount < 0)
37 {
38 apply = !apply;
39 amount = -amount;
40 }
41 if (apply)
42 baseValue += amount;
43 else
44 {
45 // Make sure we do not get uint32 overflow.
46 if (amount > int32(baseValue))
47 amount = baseValue;
48 baseValue -= amount;
49 }
50 return apply;
51}
52
53/*#######################################
54######## ########
55######## UNIT STAT SYSTEM ########
56######## ########
57#######################################*/
58
64
66{
67 float minDamage = 0.0f;
68 float maxDamage = 0.0f;
69
70 CalculateMinMaxDamage(attType, false, true, minDamage, maxDamage);
71
72 switch (attType)
73 {
74 case BASE_ATTACK:
75 default:
78 break;
79 case OFF_ATTACK:
82 break;
83 case RANGED_ATTACK:
86 break;
87 }
88}
89
91{
92 if (power == POWER_MANA)
93 return GetCreateMana();
94
95 if (PowerTypeEntry const* powerType = sDB2Manager.GetPowerTypeEntry(power))
96 return powerType->MaxBasePower;
97
98 return 0;
99}
100
101/*#######################################
102######## ########
103######## PLAYERS STAT SYSTEM ########
104######## ########
105#######################################*/
106
108{
109 // value = (base_value * base_pct) * total_pct + total_value * total_pct
110 float value = GetTotalStatValue(stat);
111
112 SetStat(stat, int32(value));
113 UpdateStatBuffMod(stat);
114
115 if (stat == STAT_STAMINA || stat == STAT_INTELLECT || stat == STAT_STRENGTH)
116 {
117 Pet* pet = GetPet();
118 if (pet)
119 pet->UpdateStats(stat);
120 }
121
122 switch (stat)
123 {
124 case STAT_AGILITY:
127 break;
128 case STAT_STAMINA:
130 break;
131 case STAT_INTELLECT:
133 break;
134 default:
135 break;
136 }
137
138 if (stat == STAT_STRENGTH)
140 else if (stat == STAT_AGILITY)
141 {
144 }
145
146 UpdateArmor();
149 return true;
150}
151
152void Player::ApplySpellPowerBonus(int32 amount, bool apply)
153{
155 return;
156
157 apply = _ModifyUInt32(apply, m_baseSpellPower, amount);
158
159 // For speed just update for client
161 for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
162 ApplyModDamageDonePos(SpellSchools(i), amount, apply);
163
165 {
168 }
169}
170
172{
173 // Magic damage modifiers implemented in Unit::SpellDamageBonusDone
174 // This information for client side use only
175 // Get healing bonus for all schools
177 // Get damage bonus for all schools
179 for (uint16 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
180 {
182 std::accumulate(modDamageAuras.begin(), modDamageAuras.end(), 0, [i](SpellEffectValue negativeMod, AuraEffect const* aurEff)
183 {
184 if (aurEff->GetAmount() < 0 && aurEff->GetMiscValue() & (1 << i))
185 negativeMod += aurEff->GetAmount();
186 return negativeMod;
187 }));
189 SpellBaseDamageBonusDone(SpellSchoolMask(1 << i)) - m_activePlayerData->ModDamageDoneNeg[i]);
190 }
191
193 {
196 }
197}
198
200{
201 for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
202 {
203 float value = GetTotalStatValue(Stats(i));
204 SetStat(Stats(i), int32(value));
206 }
207
208 UpdateArmor();
209 // calls UpdateAttackPowerAndDamage() in UpdateArmor for SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR
212
213 for (Powers power : GetPowerTypes())
214 UpdateMaxPower(power);
215
231
232 return true;
233}
234
236{
237 ApplyModTargetResistance(-amount, apply);
238 m_spellPenetrationItemMod += apply ? amount : -amount;
239}
240
242{
243 if (school > SPELL_SCHOOL_NORMAL)
244 {
246
247 Pet* pet = GetPet();
248 if (pet)
249 pet->UpdateResistances(school);
250 }
251 else
252 UpdateArmor();
253}
254
256{
257 UnitMods unitMod = UNIT_MOD_ARMOR;
258
259 float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor
260 value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent
261
262 // SPELL_AURA_MOD_ARMOR_PCT_FROM_STAT counts as base armor
264 int32 miscValue = aurEff->GetMiscValue();
265 Stats stat = (miscValue != -2) ? Stats(miscValue) : GetPrimaryStat();
266 value += CalculatePct(float(GetStat(stat)), aurEff->GetAmount());
267 return true;
268 });
269
270 float baseValue = value;
271
272 value += GetFlatModifierValue(unitMod, TOTAL_VALUE); // bonus armor from auras and items
273 value *= GetPctModifierValue(unitMod, TOTAL_PCT);
275
276 SetArmor(int32(value), int32(value - baseValue));
277
278 Pet* pet = GetPet();
279 if (pet)
280 pet->UpdateArmor();
281
282 UpdateAttackPowerAndDamage(); // armor dependent auras update for SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR
283}
284
286{
287 // Taken from PaperDollFrame.lua - 6.0.3.19085
288 float ratio = 10.0f;
289 if (GtHpPerStaEntry const* hpBase = sHpPerStaGameTable.GetRow(GetLevel()))
290 ratio = hpBase->Health;
291
292 float stamina = GetStat(STAT_STAMINA);
293
294 return stamina * ratio;
295}
296
298{
299 uint8 primaryStatPriority = [&]() -> uint8
300 {
301 if (ChrSpecializationEntry const* specialization = GetPrimarySpecializationEntry())
302 return specialization->PrimaryStatPriority;
303
304 return sChrClassesStore.AssertEntry(GetClass())->PrimaryStatPriority;
305 }();
306
307 if (primaryStatPriority >= 4)
308 return STAT_STRENGTH;
309
310 if (primaryStatPriority >= 2)
311 return STAT_AGILITY;
312
313 return STAT_INTELLECT;
314}
315
317{
318 UnitMods unitMod = UNIT_MOD_HEALTH;
319
320 float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
321 value *= GetPctModifierValue(unitMod, BASE_PCT);
323 value *= GetPctModifierValue(unitMod, TOTAL_PCT);
324
325 SetMaxHealth((uint32)value);
326}
327
332
337
339{
340 uint32 powerIndex = GetPowerIndex(power);
341 if (powerIndex >= MAX_POWERS_PER_CLASS)
342 return;
343
345
346 float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowerValue(power);
347 value *= GetPctModifierValue(unitMod, BASE_PCT);
348 value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
349 value *= GetPctModifierValue(unitMod, TOTAL_PCT);
350
351 SetMaxPower(power, (int32)std::lroundf(value));
352}
353
355{
356 float val2 = 0.0f;
357 float level = float(GetLevel());
358
359 ChrClassesEntry const* entry = sChrClassesStore.AssertEntry(GetClass());
361
363 {
364 if (!ranged)
365 {
366 float strengthValue = std::max(GetStat(STAT_STRENGTH) * entry->AttackPowerPerStrength, 0.0f);
367 float agilityValue = std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerAgility, 0.0f);
368
370 // Directly taken from client, SHAPESHIFT_FLAG_AP_FROM_STRENGTH ?
371 if (form && form->Flags & 0x20)
372 agilityValue += std::max(GetStat(STAT_AGILITY) * entry->AttackPowerPerStrength, 0.0f);
373
374 val2 = strengthValue + agilityValue;
375 }
376 else
377 val2 = (level + std::max(GetStat(STAT_AGILITY), 0.0f)) * entry->RangedAttackPowerPerAgility;
378 }
379 else
380 {
381 int32 minSpellPower = m_activePlayerData->ModHealingDonePos;
382 for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
383 minSpellPower = std::min(minSpellPower, m_activePlayerData->ModDamageDonePos[i]);
384
385 val2 = CalculatePct(float(minSpellPower), *m_activePlayerData->OverrideAPBySpellPowerPercent);
386 }
387
388 float baseAttackPower = val2;
389 float attackPowerModPos = GetAttackPowerModifierValue(unitMod, AttackPowerModType::FlatPositive);
390 float attackPowerModNeg = GetAttackPowerModifierValue(unitMod, AttackPowerModType::FlatNegative);
391 float attackPowerMultiplier = GetAttackPowerModifierValue(unitMod, AttackPowerModType::Pct) - 1.0f;
392
393 if (ranged)
394 {
395 SetRangedAttackPower(int32(baseAttackPower));
396 SetRangedAttackPowerModPos(int32(attackPowerModPos));
397 SetRangedAttackPowerModNeg(int32(attackPowerModNeg));
398 SetRangedAttackPowerMultiplier(attackPowerMultiplier);
399 }
400 else
401 {
402 SetAttackPower(int32(baseAttackPower));
403 SetAttackPowerModPos(int32(attackPowerModPos));
404 SetAttackPowerModNeg(int32(attackPowerModNeg));
405 SetAttackPowerMultiplier(attackPowerMultiplier);
406 }
407
408 Pet* pet = GetPet(); //update pet's AP
409 Guardian* guardian = GetGuardianPet();
410 //automatically update weapon damage after attack power modification
411 if (ranged)
412 {
414 if (pet && pet->IsHunterPet()) // At ranged attack change for hunter pet
416 }
417 else
418 {
420 if (Item* offhand = GetWeaponForAttack(OFF_ATTACK, true))
421 if (CanDualWield() || offhand->GetTemplate()->HasFlag(ITEM_FLAG3_ALWAYS_ALLOW_DUAL_WIELD))
423
426
427 if (pet && pet->IsPetGhoul()) // At melee attack power change for DK pet
429
430 if (guardian && guardian->IsSpiritWolf()) // At melee attack power change for Shaman feral spirit
431 guardian->UpdateAttackPowerAndDamage();
432 }
433}
434
435void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const
436{
437 UnitMods unitMod;
438
439 switch (attType)
440 {
441 case BASE_ATTACK:
442 default:
443 unitMod = UNIT_MOD_DAMAGE_MAINHAND;
444 break;
445 case OFF_ATTACK:
446 unitMod = UNIT_MOD_DAMAGE_OFFHAND;
447 break;
448 case RANGED_ATTACK:
449 unitMod = UNIT_MOD_DAMAGE_RANGED;
450 break;
451 }
452
453 float attackPowerMod = std::max(GetAPMultiplier(attType, normalized), 0.25f);
454
455 float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType, false) / 3.5f * attackPowerMod;
456 float basePct = GetPctModifierValue(unitMod, BASE_PCT);
457 float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
458 float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
459
460 float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
461 float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
462
463 float versaDmgMod = 1.0f;
464
466
468 if (shapeshift && shapeshift->CombatRoundTime)
469 {
470 weaponMinDamage = weaponMinDamage * shapeshift->CombatRoundTime / 1000.0f / attackPowerMod;
471 weaponMaxDamage = weaponMaxDamage * shapeshift->CombatRoundTime / 1000.0f / attackPowerMod;
472 }
473 else if (!CanUseAttackType(attType)) // check if player not in form but still can't use (disarm case)
474 {
475 // cannot use ranged/off attack, set values to 0
476 if (attType != BASE_ATTACK)
477 {
478 minDamage = 0;
479 maxDamage = 0;
480 return;
481 }
482 weaponMinDamage = BASE_MINDAMAGE;
483 weaponMaxDamage = BASE_MAXDAMAGE;
484 }
485
486 minDamage = ((weaponMinDamage + baseValue) * basePct + totalValue) * totalPct * versaDmgMod;
487 maxDamage = ((weaponMaxDamage + baseValue) * basePct + totalValue) * totalPct * versaDmgMod;
488}
489
491{
492 // No block
493 float value = 0.0f;
494 if (CanBlock())
495 {
496 // Base value
497 value = 5.0f;
498 // Increase from SPELL_AURA_MOD_BLOCK_PERCENT aura
500 // Increase from rating
502
503 if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE))
504 value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_BLOCK) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_BLOCK) : value;
505 }
507}
508
535
548
550{
551 if (!CanUseMastery())
552 {
554 return;
555 }
556
560
562 if (!chrSpec)
563 return;
564
565 for (auto const& [_, aura] : GetOwnedAuras())
566 if (aura->GetCasterGUID() == GetGUID() && aura->GetSpellInfo()->HasAttribute(SPELL_ATTR8_MASTERY_AFFECTS_POINTS))
567 for (AuraEffect* auraEff : aura->GetAuraEffects())
568 if (G3D::fuzzyNe(auraEff->GetSpellEffectInfo().BonusCoefficient, 0.0f))
569 auraEff->RecalculateAmount(this);
570}
571
573{
574 // No proof that CR_VERSATILITY_DAMAGE_DONE is allways = ActivePlayerData::Versatility
576
577 if (GetClass() == CLASS_HUNTER)
579 else
581}
582
595
597{
598 0.9560f, // Warrior
599 0.9560f, // Paladin
600 0.9880f, // Hunter
601 0.9880f, // Rogue
602 0.9830f, // Priest
603 0.9560f, // DK
604 0.9880f, // Shaman
605 0.9830f, // Mage
606 0.9830f, // Warlock
607 0.9830f, // Monk
608 0.9720f, // Druid
609 0.9830f, // Demon Hunter
610 0.9880f, // Evoker
611 1.0f, // Adventurer
612 1.0f, // Traveler
613};
614
615// helper function
616float CalculateDiminishingReturns(float const (&capArray)[MAX_CLASSES], uint8 playerClass, float nonDiminishValue, float diminishValue)
617{
618 // 1 1 k cx
619 // --- = --- + --- <=> x' = --------
620 // x' c x x + ck
621
622 // where:
623 // k is m_diminishing_k for that class
624 // c is capArray for that class
625 // x is chance before DR (diminishValue)
626 // x' is chance after DR (our result)
627
628 uint32 const classIdx = playerClass - 1;
629
630 float const k = m_diminishing_k[classIdx];
631 float const c = capArray[classIdx];
632
633 float result = c * diminishValue / (diminishValue + c * k);
634 result += nonDiminishValue;
635 return result;
636}
637
638constexpr float parry_cap[MAX_CLASSES] =
639{
640 65.631440f, // Warrior
641 65.631440f, // Paladin
642 145.560408f, // Hunter
643 145.560408f, // Rogue
644 0.0f, // Priest
645 65.631440f, // DK
646 145.560408f, // Shaman
647 0.0f, // Mage
648 0.0f, // Warlock
649 90.6425f, // Monk
650 0.0f, // Druid
651 65.631440f, // Demon Hunter
652 0.0f, // Evoker
653 0.0f, // Adventurer
654 0.0f, // Traveler
655};
656
658{
659 // No parry
660 float value = 0.0f;
661 uint32 pclass = GetClass() - 1;
662 if (CanParry() && parry_cap[pclass] > 0.0f)
663 {
664 float nondiminishing = 5.0f;
665 // Parry from rating
666 float diminishing = GetRatingBonusValue(CR_PARRY);
667 // Parry from SPELL_AURA_MOD_PARRY_PERCENT aura
669
670 // apply diminishing formula to diminishing parry chance
671 value = CalculateDiminishingReturns(parry_cap, GetClass(), nondiminishing, diminishing);
672
673 if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE))
674 value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_PARRY) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_PARRY) : value;
675
676 }
678}
679
680constexpr float dodge_cap[MAX_CLASSES] =
681{
682 65.631440f, // Warrior
683 65.631440f, // Paladin
684 145.560408f, // Hunter
685 145.560408f, // Rogue
686 150.375940f, // Priest
687 65.631440f, // DK
688 145.560408f, // Shaman
689 150.375940f, // Mage
690 150.375940f, // Warlock
691 145.560408f, // Monk
692 116.890707f, // Druid
693 145.560408f, // Demon Hunter
694 145.560408f, // Evoker
695 0.0f, // Adventurer
696 0.0f, // Traveler
697};
698
700{
701 float diminishing = 0.0f, nondiminishing = 0.0f;
702 GetDodgeFromAgility(diminishing, nondiminishing);
703 // Dodge from SPELL_AURA_MOD_DODGE_PERCENT aura
705 // Dodge from rating
706 diminishing += GetRatingBonusValue(CR_DODGE);
707
708 // apply diminishing formula to diminishing dodge chance
709 float value = CalculateDiminishingReturns(dodge_cap, GetClass(), nondiminishing, diminishing);
710
711 if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE))
712 value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_DODGE) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_DODGE) : value;
713
715}
716
718{
719 float crit = 5.0f;
720 // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE
722 // Increase crit from SPELL_AURA_MOD_CRIT_PCT
724 // Increase crit from spell crit ratings
726
727 // Store crit value
729}
730
732{
734 for (CorruptionEffectsEntry const* corruptionEffect : sCorruptionEffectsStore)
735 {
737 continue;
738
739 if (effectiveCorruption < corruptionEffect->MinCorruption)
740 {
741 RemoveAura(corruptionEffect->Aura);
742 continue;
743 }
744
745 if (!ConditionMgr::IsPlayerMeetingCondition(this, corruptionEffect->PlayerConditionID))
746 {
747 RemoveAura(corruptionEffect->Aura);
748 continue;
749 }
750
751 CastSpell(this, corruptionEffect->Aura, true);
752 }
753}
754
760
765
770
776
778{
779 if (attack == RANGED_ATTACK)
780 return;
781
783
784 Item const* weapon = GetWeaponForAttack(attack, true);
785 expertise += GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE, [weapon](AuraEffect const* aurEff) -> bool
786 {
787 return aurEff->GetSpellInfo()->IsItemFitToSpellRequirements(weapon);
788 });
789
790 if (expertise < 0)
791 expertise = 0;
792
793 switch (attack)
794 {
795 case BASE_ATTACK:
797 break;
798 case OFF_ATTACK:
800 break;
801 default:
802 break;
803 }
804}
805
806void Player::ApplyManaRegenBonus(int32 amount, bool apply)
807{
808 _ModifyUInt32(apply, m_baseManaRegen, amount);
810}
811
812void Player::ApplyHealthRegenBonus(int32 amount, bool apply)
813{
814 _ModifyUInt32(apply, m_baseHealthRegen, amount);
815}
816
817static constexpr std::array<Optional<Rates>, MAX_POWERS> PowerRegenInfo =
818{
819 RATE_POWER_MANA, // POWER_MANA
820 RATE_POWER_RAGE_LOSS, // POWER_RAGE
821 RATE_POWER_FOCUS, // POWER_FOCUS
822 RATE_POWER_ENERGY, // POWER_ENERGY
823 RATE_POWER_COMBO_POINTS_LOSS, // POWER_COMBO_POINTS
824 std::nullopt, // POWER_RUNES
825 RATE_POWER_RUNIC_POWER_LOSS, // POWER_RUNIC_POWER
826 RATE_POWER_SOUL_SHARDS, // POWER_SOUL_SHARDS
827 RATE_POWER_LUNAR_POWER, // POWER_LUNAR_POWER
828 RATE_POWER_HOLY_POWER, // POWER_HOLY_POWER
829 std::nullopt, // POWER_ALTERNATE_POWER
830 RATE_POWER_MAELSTROM, // POWER_MAELSTROM
831 RATE_POWER_CHI, // POWER_CHI
832 RATE_POWER_INSANITY, // POWER_INSANITY
833 std::nullopt, // POWER_BURNING_EMBERS, Obsolete
834 std::nullopt, // POWER_DEMONIC_FURY, Obsolete
835 RATE_POWER_ARCANE_CHARGES, // POWER_ARCANE_CHARGES
836 RATE_POWER_FURY, // POWER_FURY
837 RATE_POWER_PAIN, // POWER_PAIN
838 RATE_POWER_ESSENCE, // POWER_ESSENCE
839 std::nullopt, // POWER_RUNE_BLOOD
840 std::nullopt, // POWER_RUNE_FROST
841 std::nullopt, // POWER_RUNE_UNHOLY
842 std::nullopt, // POWER_ALTERNATE_QUEST
843 std::nullopt, // POWER_ALTERNATE_ENCOUNTER
844 std::nullopt, // POWER_ALTERNATE_MOUNT
845};
846
848{
849 uint32 powerIndex = GetPowerIndex(power);
850 if (powerIndex >= MAX_POWERS_PER_CLASS)
851 return;
852
853 // TODO: updating haste should update UnitData::PowerRegenFlatModifier for certain power types
854 PowerTypeEntry const* powerType = sDB2Manager.GetPowerTypeEntry(power);
855 if (!powerType)
856 return;
857
858 float result_regen = powerType->RegenPeace; // Out-of-combat / without last mana use effect
859 float result_regen_interrupted = powerType->RegenCombat; // In combat / with last mana use effect
860 float pct_modifier = 1.f; // Config rate or any other modifiers
861 float flat_modifier = 0.f; // other modifiers
862
864 [powerMask = 1 << power](AuraEffect const* preventRegen) { return (preventRegen->GetMiscValue() & powerMask) != 0; }))
865 {
868 return;
869 }
870
871 switch (power)
872 {
873 case POWER_MANA:
874 {
875 // Get base of Mana Pool in sBaseMPGameTable
876 uint32 basemana = 0;
877 sObjectMgr->GetPlayerClassLevelInfo(GetClass(), GetLevel(), basemana);
878 float base_regen = float(basemana) / 100.f;
879
881
882 result_regen += base_regen;
883 result_regen_interrupted += base_regen;
884 break;
885 }
886 default:
887 break;
888 }
889
891 pct_modifier *= sWorld->getRate(*PowerRegenInfo[AsUnderlyingType(power)]); // Config rate
892
893 if (powerType->GetFlags().HasFlag(PowerTypeFlags::RegenAffectedByHaste))
894 pct_modifier /= m_unitData->ModHasteRegen;
895
898
899 result_regen *= pct_modifier;
900 result_regen_interrupted *= pct_modifier;
901
902 result_regen += flat_modifier;
903 result_regen_interrupted += flat_modifier;
904
905 // Unit fields contain an offset relative to the base power regeneration.
906 result_regen -= powerType->RegenPeace;
907 result_regen_interrupted -= powerType->RegenCombat;
908
911}
912
914{
915 uint32 powerIndex = GetPowerIndex(power);
916 if (powerIndex >= MAX_POWERS_PER_CLASS)
917 return 0.f;
918
919 PowerTypeEntry const* powerType = sDB2Manager.GetPowerTypeEntry(power);
920 if (!powerType)
921 return 0.f;
922
924 return 0.f;
925
926 bool interrupted = HasAuraType(SPELL_AURA_INTERRUPT_REGEN) ||
928 IsInCombat();
929
930 float regen = interrupted ? powerType->RegenCombat + m_unitData->PowerRegenInterruptedFlatModifier[powerIndex] : powerType->RegenPeace + m_unitData->PowerRegenFlatModifier[powerIndex];
931
932 return regen;
933}
934
947
960
961/*#######################################
962######## ########
963######## MOBS STAT SYSTEM ########
964######## ########
965#######################################*/
966
968{
969 if (PowerTypeEntry const* powerType = sDB2Manager.GetPowerTypeEntry(power))
970 if (!powerType->GetFlags().HasFlag(PowerTypeFlags::IsUsedByNPCs))
971 return 0;
972
973 return Unit::GetCreatePowerValue(power);
974}
975
977{
978 return true;
979}
980
982{
986
987 for (Powers power : GetPowerTypes())
988 UpdateMaxPower(power);
989
991
992 return true;
993}
994
996{
999 SetArmor(int32(baseValue), int32(value - baseValue));
1000}
1001
1003{
1005 SetMaxHealth(uint32(value));
1006}
1007
1009{
1010 if (power == GetPowerType())
1011 return 0;
1012 switch (power)
1013 {
1014 case POWER_COMBO_POINTS:
1015 return 2;
1017 return 1;
1019 return 3;
1021 return 4;
1023 return 5;
1024 default:
1025 break;
1026 }
1027 return MAX_POWERS_PER_CLASS;
1028}
1029
1031{
1032 return
1033 {
1034 .PowerType =
1035 {
1036 GetPowerType(),
1042 },
1043 .PowerTypeCount = 6
1044 };
1045}
1046
1048{
1049 if (GetPowerIndex(power) >= MAX_POWERS_PER_CLASS)
1050 return;
1051
1053
1054 float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowerValue(power);
1055 value *= GetPctModifierValue(unitMod, BASE_PCT);
1056 value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
1057 value *= GetPctModifierValue(unitMod, TOTAL_PCT);
1058
1059 SetMaxPower(power, (int32)std::lroundf(value));
1060}
1061
1063{
1065
1066 float baseAttackPower = ranged ? m_baseRangedAttackPower : m_baseAttackPower;
1067 float attackPowerModPos = GetAttackPowerModifierValue(unitMod, AttackPowerModType::FlatPositive);
1068 float attackPowerModNeg = GetAttackPowerModifierValue(unitMod, AttackPowerModType::FlatNegative);
1069 float attackPowerMultiplier = GetAttackPowerModifierValue(unitMod, AttackPowerModType::Pct) - 1.0f;
1070
1071 if (ranged)
1072 {
1073 SetRangedAttackPower(int32(baseAttackPower));
1074 SetRangedAttackPowerModPos(int32(attackPowerModPos));
1075 SetRangedAttackPowerModNeg(int32(attackPowerModNeg));
1076 SetRangedAttackPowerMultiplier(attackPowerMultiplier);
1077 }
1078 else
1079 {
1080 SetAttackPower(int32(baseAttackPower));
1081 SetAttackPowerModPos(int32(attackPowerModPos));
1082 SetAttackPowerModNeg(int32(attackPowerModNeg));
1083 SetAttackPowerMultiplier(attackPowerMultiplier);
1084 }
1085
1086 // automatically update weapon damage after attack power modification
1087 if (ranged)
1089 else
1090 {
1093 }
1094}
1095
1096void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage) const
1097{
1098 float variance = 1.0f;
1099 UnitMods unitMod;
1100 switch (attType)
1101 {
1102 case BASE_ATTACK:
1103 default:
1104 variance = GetCreatureTemplate()->BaseVariance;
1105 unitMod = UNIT_MOD_DAMAGE_MAINHAND;
1106 break;
1107 case OFF_ATTACK:
1108 variance = GetCreatureTemplate()->BaseVariance;
1109 unitMod = UNIT_MOD_DAMAGE_OFFHAND;
1110 break;
1111 case RANGED_ATTACK:
1112 variance = GetCreatureTemplate()->RangeVariance;
1113 unitMod = UNIT_MOD_DAMAGE_RANGED;
1114 break;
1115 }
1116
1117 if (attType == OFF_ATTACK && !haveOffhandWeapon())
1118 {
1119 minDamage = 0.0f;
1120 maxDamage = 0.0f;
1121 return;
1122 }
1123
1124 float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
1125 float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
1126
1127 if (!CanUseAttackType(attType)) // disarm case
1128 {
1129 weaponMinDamage = 0.0f;
1130 weaponMaxDamage = 0.0f;
1131 }
1132
1133 float attackPower = GetTotalAttackPowerValue(attType, false);
1134 float attackSpeedMulti = GetAPMultiplier(attType, normalized);
1135 float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + (attackPower / 3.5f) * variance;
1136 float basePct = GetPctModifierValue(unitMod, BASE_PCT) * attackSpeedMulti;
1137 float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
1138 float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
1139 float dmgMultiplier = GetCreatureDifficulty()->DamageModifier; // = DamageModifier * GetDamageMod(rank);
1140
1141 minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
1142 maxDamage = ((weaponMaxDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
1143}
1144
1145/*#######################################
1146######## ########
1147######## PETS STAT SYSTEM ########
1148######## ########
1149#######################################*/
1150
1151#define ENTRY_IMP 416
1152#define ENTRY_VOIDWALKER 1860
1153#define ENTRY_SUCCUBUS 1863
1154#define ENTRY_FELHUNTER 417
1155#define ENTRY_FELGUARD 17252
1156#define ENTRY_WATER_ELEMENTAL 510
1157#define ENTRY_TREANT 1964
1158#define ENTRY_FIRE_ELEMENTAL 15438
1159#define ENTRY_GHOUL 26125
1160#define ENTRY_BLOODWORM 28017
1161
1163{
1164 // value = ((base_value * base_pct) + total_value) * total_pct
1165 float value = GetTotalStatValue(stat);
1166 UpdateStatBuffMod(stat);
1167 float ownersBonus = 0.0f;
1168
1169 Unit* owner = GetOwner();
1170 // Handle Death Knight Glyphs and Talents
1171 float mod = 0.75f;
1172 if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH))
1173 {
1174 if (stat == STAT_STAMINA)
1175 mod = 0.3f; // Default Owner's Stamina scale
1176 else
1177 mod = 0.7f; // Default Owner's Strength scale
1178
1179 ownersBonus = float(owner->GetStat(stat)) * mod;
1180 value += ownersBonus;
1181 }
1182 else if (stat == STAT_STAMINA)
1183 {
1184 ownersBonus = CalculatePct(owner->GetStat(STAT_STAMINA), 30);
1185 value += ownersBonus;
1186 }
1187 //warlock's and mage's pets gain 30% of owner's intellect
1188 else if (stat == STAT_INTELLECT)
1189 {
1190 if (owner->GetClass() == CLASS_WARLOCK || owner->GetClass() == CLASS_MAGE)
1191 {
1192 ownersBonus = CalculatePct(owner->GetStat(stat), 30);
1193 value += ownersBonus;
1194 }
1195 }
1196/*
1197 else if (stat == STAT_STRENGTH)
1198 {
1199 if (IsPetGhoul())
1200 value += float(owner->GetStat(stat)) * 0.3f;
1201 }
1202*/
1203
1204 SetStat(stat, int32(value));
1205 m_statFromOwner[stat] = ownersBonus;
1206 UpdateStatBuffMod(stat);
1207
1208 switch (stat)
1209 {
1211 case STAT_AGILITY: UpdateArmor(); break;
1212 case STAT_STAMINA: UpdateMaxHealth(); break;
1214 default:
1215 break;
1216 }
1217
1218 return true;
1219}
1220
1222{
1224
1225 for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
1226 UpdateStats(Stats(i));
1227
1228 for (Powers power : GetPowerTypes())
1229 UpdateMaxPower(power);
1230
1232
1233 return true;
1234}
1235
1237{
1238 if (school > SPELL_SCHOOL_NORMAL)
1239 {
1241 float bonusValue = GetTotalAuraModValue(UnitMods(UNIT_MOD_RESISTANCE_START + school)) - baseValue;
1242
1243 // hunter and warlock pets gain 40% of owner's resistance
1244 if (IsPet())
1245 {
1246 baseValue += float(CalculatePct(m_owner->GetResistance(SpellSchools(school)), 40));
1247 bonusValue += float(CalculatePct(m_owner->GetBonusResistanceMod(SpellSchools(school)), 40));
1248 }
1249
1250 SetResistance(SpellSchools(school), int32(baseValue));
1251 SetBonusResistanceMod(SpellSchools(school), int32(bonusValue));
1252 }
1253 else
1254 UpdateArmor();
1255}
1256
1258{
1259 float baseValue = 0.0f;
1260 float value = 0.0f;
1261 float bonus_armor = 0.0f;
1262 UnitMods unitMod = UNIT_MOD_ARMOR;
1263
1264 // hunter pets gain 35% of owner's armor value, warlock pets gain 100% of owner's armor
1265 if (IsHunterPet())
1266 bonus_armor = float(CalculatePct(m_owner->GetArmor(), 70));
1267 else if (IsPet())
1268 bonus_armor = m_owner->GetArmor();
1269
1270 value = GetFlatModifierValue(unitMod, BASE_VALUE);
1271 baseValue = value;
1272 value *= GetPctModifierValue(unitMod, BASE_PCT);
1273 value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonus_armor;
1274 value *= GetPctModifierValue(unitMod, TOTAL_PCT);
1275
1276 SetArmor(int32(baseValue), int32(value - baseValue));
1277}
1278
1280{
1281 UnitMods unitMod = UNIT_MOD_HEALTH;
1282 float stamina = GetStat(STAT_STAMINA) - GetCreateStat(STAT_STAMINA);
1283
1284 float multiplicator;
1285 switch (GetEntry())
1286 {
1287 case ENTRY_IMP: multiplicator = 8.4f; break;
1288 case ENTRY_VOIDWALKER: multiplicator = 11.0f; break;
1289 case ENTRY_SUCCUBUS: multiplicator = 9.1f; break;
1290 case ENTRY_FELHUNTER: multiplicator = 9.5f; break;
1291 case ENTRY_FELGUARD: multiplicator = 11.0f; break;
1292 case ENTRY_BLOODWORM: multiplicator = 1.0f; break;
1293 default: multiplicator = 10.0f; break;
1294 }
1295
1296 float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
1297 value *= GetPctModifierValue(unitMod, BASE_PCT);
1298 value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
1299 value *= GetPctModifierValue(unitMod, TOTAL_PCT);
1300
1301 SetMaxHealth((uint32)value);
1302}
1303
1305{
1306 if (GetPowerIndex(power) >= MAX_POWERS_PER_CLASS)
1307 return;
1308
1310
1311 float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowerValue(power);
1312 value *= GetPctModifierValue(unitMod, BASE_PCT);
1313 value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
1314 value *= GetPctModifierValue(unitMod, TOTAL_PCT);
1315
1316 SetMaxPower(power, int32(value));
1317}
1318
1320{
1321 if (ranged)
1322 return;
1323
1324 float val = 0.0f;
1325 float bonusAP = 0.0f;
1327
1328 if (GetEntry() == ENTRY_IMP) // imp's attack power
1329 val = GetStat(STAT_STRENGTH) - 10.0f;
1330 else
1331 val = 2 * GetStat(STAT_STRENGTH) - 20.0f;
1332
1333 Player* owner = GetOwner() ? GetOwner()->ToPlayer() : nullptr;
1334 if (owner)
1335 {
1336 if (IsHunterPet()) //hunter pets benefit from owner's attack power
1337 {
1338 float mod = 1.0f; //Hunter contribution modifier
1339 bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod;
1341 }
1342 else if (IsPetGhoul()) //ghouls benefit from deathknight's attack power (may be summon pet or not)
1343 {
1344 bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * 0.22f;
1346 }
1347 else if (IsSpiritWolf()) //wolf benefit from shaman's attack power
1348 {
1349 float dmg_multiplier = 0.31f;
1350 bonusAP = owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier;
1351 SetBonusDamage(int32(owner->GetTotalAttackPowerValue(BASE_ATTACK) * dmg_multiplier));
1352 }
1353 //demons benefit from warlocks shadow or fire damage
1354 else if (IsPet())
1355 {
1356 int32 fire = owner->m_activePlayerData->ModDamageDonePos[SPELL_SCHOOL_FIRE] - owner->m_activePlayerData->ModDamageDoneNeg[SPELL_SCHOOL_FIRE];
1357 int32 shadow = owner->m_activePlayerData->ModDamageDonePos[SPELL_SCHOOL_SHADOW] - owner->m_activePlayerData->ModDamageDoneNeg[SPELL_SCHOOL_SHADOW];
1358 int32 maximum = (fire > shadow) ? fire : shadow;
1359 if (maximum < 0)
1360 maximum = 0;
1361 SetBonusDamage(int32(maximum * 0.15f));
1362 bonusAP = maximum * 0.57f;
1363 }
1364 //water elementals benefit from mage's frost damage
1365 else if (GetEntry() == ENTRY_WATER_ELEMENTAL)
1366 {
1367 int32 frost = owner->m_activePlayerData->ModDamageDonePos[SPELL_SCHOOL_FROST] - owner->m_activePlayerData->ModDamageDoneNeg[SPELL_SCHOOL_FROST];
1368 if (frost < 0)
1369 frost = 0;
1370 SetBonusDamage(int32(frost * 0.4f));
1371 }
1372 }
1373
1374 float base_attPower = val + bonusAP;
1375 float attPowerModPos = GetAttackPowerModifierValue(unitMod, AttackPowerModType::FlatPositive);
1376 float attPowerModNeg = GetAttackPowerModifierValue(unitMod, AttackPowerModType::FlatNegative);
1377 float attPowerMultiplier = GetAttackPowerModifierValue(unitMod, AttackPowerModType::Pct) - 1.0f;
1378
1379 SetAttackPower(int32(base_attPower));
1380 SetAttackPowerModPos(int32(attPowerModPos));
1381 SetAttackPowerModNeg(int32(attPowerModNeg));
1382 SetAttackPowerMultiplier(attPowerMultiplier);
1383
1384 //automatically update weapon damage after attack power modification
1386}
1387
1389{
1390 if (attType > BASE_ATTACK)
1391 return;
1392
1393 float bonusDamage = 0.0f;
1394 if (Player* playerOwner = m_owner->ToPlayer())
1395 {
1396 //force of nature
1397 if (GetEntry() == ENTRY_TREANT)
1398 {
1399 int32 spellDmg = playerOwner->m_activePlayerData->ModDamageDonePos[SPELL_SCHOOL_NATURE] - playerOwner->m_activePlayerData->ModDamageDoneNeg[SPELL_SCHOOL_NATURE];
1400 if (spellDmg > 0)
1401 bonusDamage = spellDmg * 0.09f;
1402 }
1403 //greater fire elemental
1404 else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
1405 {
1406 int32 spellDmg = playerOwner->m_activePlayerData->ModDamageDonePos[SPELL_SCHOOL_FIRE] - playerOwner->m_activePlayerData->ModDamageDoneNeg[SPELL_SCHOOL_FIRE];
1407 if (spellDmg > 0)
1408 bonusDamage = spellDmg * 0.4f;
1409 }
1410 }
1411
1413
1414 float att_speed = float(GetBaseAttackTime(BASE_ATTACK))/1000.0f;
1415
1416 float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType, false) / 3.5f * att_speed + bonusDamage;
1417 float base_pct = GetPctModifierValue(unitMod, BASE_PCT);
1418 float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE);
1419 float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT);
1420
1421 float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
1422 float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
1423
1424 float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct;
1425 float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct;
1426
1429}
1430
1432{
1433 m_bonusSpellDamage = damage;
1434 if (Player* playerOwner = GetOwner()->ToPlayer())
1435 playerOwner->SetPetSpellPower(damage);
1436}
DB2Storage< ChrClassesEntry > sChrClassesStore("ChrClasses.db2", &ChrClassesLoadInfo::Instance)
DB2Storage< SpellShapeshiftFormEntry > sSpellShapeshiftFormStore("SpellShapeshiftForm.db2", &SpellShapeshiftFormLoadInfo::Instance)
DB2Storage< CorruptionEffectsEntry > sCorruptionEffectsStore("CorruptionEffects.db2", &CorruptionEffectsLoadInfo::Instance)
#define sDB2Manager
Definition DB2Stores.h:579
CorruptionEffectsFlag
Definition DBCEnums.h:462
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
GameTable< GtHpPerStaEntry > sHpPerStaGameTable
@ ITEM_FLAG3_ALWAYS_ALLOW_DUAL_WIELD
#define sObjectMgr
Definition ObjectMgr.h:1873
#define MAX_STATS
#define MAX_POWERS_PER_CLASS
@ CLASS_HUNTER
@ CLASS_WARLOCK
@ CLASS_MAGE
SpellSchoolMask
@ SPELL_SCHOOL_MASK_ALL
WeaponAttackType
@ OFF_ATTACK
@ BASE_ATTACK
@ RANGED_ATTACK
Powers
@ MAX_POWERS
@ POWER_ALTERNATE_POWER
@ POWER_RAGE
@ POWER_RUNIC_POWER
@ POWER_ENERGY
@ POWER_ALTERNATE_QUEST
@ POWER_COMBO_POINTS
@ POWER_MANA
@ POWER_ALTERNATE_MOUNT
@ POWER_ALTERNATE_ENCOUNTER
#define MAX_CLASSES
Stats
@ STAT_INTELLECT
@ STAT_AGILITY
@ STAT_STRENGTH
@ STAT_STAMINA
SpellSchools
@ SPELL_SCHOOL_SHADOW
@ SPELL_SCHOOL_NORMAL
@ SPELL_SCHOOL_NATURE
@ SPELL_SCHOOL_FROST
@ SPELL_SCHOOL_FIRE
@ SPELL_SCHOOL_HOLY
@ MAX_SPELL_SCHOOL
@ SPELL_ATTR8_MASTERY_AFFECTS_POINTS
@ SPELL_AURA_OVERRIDE_ATTACK_POWER_BY_SP_PCT
@ SPELL_AURA_MOD_PARRY_PERCENT
@ SPELL_AURA_MOD_SPELL_HIT_CHANCE
@ SPELL_AURA_MOD_EXPERTISE
@ SPELL_AURA_INTERRUPT_REGEN
@ SPELL_AURA_MOD_POWER_REGEN
@ SPELL_AURA_MOD_HEALING_DONE_PERCENT
@ SPELL_AURA_MOD_ARMOR_PCT_FROM_STAT
@ SPELL_AURA_MOD_BONUS_ARMOR_PCT
@ SPELL_AURA_MOD_SPELL_CRIT_CHANCE
@ SPELL_AURA_MOD_MANA_REGEN_PCT
@ SPELL_AURA_MOD_DODGE_PERCENT
@ SPELL_AURA_MASTERY
@ SPELL_AURA_MOD_CRIT_PCT
@ SPELL_AURA_MOD_VERSATILITY
@ SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT
@ SPELL_AURA_MOD_POWER_REGEN_PERCENT
@ SPELL_AURA_MOD_DAMAGE_DONE
@ SPELL_AURA_PREVENT_REGENERATE_POWER
@ SPELL_AURA_MOD_BLOCK_PERCENT
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
#define ENTRY_FELGUARD
#define ENTRY_FIRE_ELEMENTAL
#define ENTRY_BLOODWORM
#define ENTRY_VOIDWALKER
#define ENTRY_FELHUNTER
constexpr float dodge_cap[MAX_CLASSES]
float CalculateDiminishingReturns(float const (&capArray)[MAX_CLASSES], uint8 playerClass, float nonDiminishValue, float diminishValue)
static constexpr std::array< Optional< Rates >, MAX_POWERS > PowerRegenInfo
constexpr float parry_cap[MAX_CLASSES]
#define ENTRY_TREANT
bool _ModifyUInt32(bool apply, uint32 &baseValue, int32 &amount)
#define ENTRY_WATER_ELEMENTAL
#define ENTRY_SUCCUBUS
float const m_diminishing_k[MAX_CLASSES]
#define ENTRY_IMP
#define BASE_MAXDAMAGE
Definition UnitDefines.h:34
#define BASE_MINDAMAGE
Definition UnitDefines.h:33
@ BASE_VALUE
Definition Unit.h:158
@ TOTAL_VALUE
Definition Unit.h:159
@ FLAT_MOD
Definition Unit.h:244
@ PCT_MOD
Definition Unit.h:245
@ MINDAMAGE
Definition Unit.h:172
@ MAXDAMAGE
Definition Unit.h:173
UnitMods
Definition Unit.h:177
@ UNIT_MOD_DAMAGE_OFFHAND
Definition Unit.h:218
@ UNIT_MOD_ARMOR
Definition Unit.h:210
@ UNIT_MOD_RESISTANCE_START
Definition Unit.h:224
@ UNIT_MOD_HEALTH
Definition Unit.h:183
@ UNIT_MOD_DAMAGE_RANGED
Definition Unit.h:219
@ UNIT_MOD_POWER_START
Definition Unit.h:226
@ UNIT_MOD_DAMAGE_MAINHAND
Definition Unit.h:217
@ OFFHAND_CRIT_PERCENTAGE
Definition Unit.h:237
@ CRIT_PERCENTAGE
Definition Unit.h:235
@ RANGED_CRIT_PERCENTAGE
Definition Unit.h:236
AttackPowerModIndex
Definition Unit.h:250
@ CR_EXPERTISE
Definition Unit.h:354
@ CR_CORRUPTION
Definition Unit.h:342
@ CR_HIT_MELEE
Definition Unit.h:336
@ CR_ARMOR_PENETRATION
Definition Unit.h:355
@ CR_CRIT_MELEE
Definition Unit.h:339
@ CR_CRIT_RANGED
Definition Unit.h:340
@ CR_VERSATILITY_HEALING_DONE
Definition Unit.h:360
@ CR_PARRY
Definition Unit.h:334
@ CR_DODGE
Definition Unit.h:333
@ CR_CORRUPTION_RESISTANCE
Definition Unit.h:343
@ CR_BLOCK
Definition Unit.h:335
@ CR_VERSATILITY_DAMAGE_DONE
Definition Unit.h:359
@ CR_HIT_SPELL
Definition Unit.h:338
@ CR_MASTERY
Definition Unit.h:356
@ CR_CRIT_SPELL
Definition Unit.h:341
@ CR_HIT_RANGED
Definition Unit.h:337
@ TOTAL_PCT
Definition Unit.h:166
@ BASE_PCT
Definition Unit.h:165
T AddPct(T &base, U pct)
Definition Util.h:85
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
T CalculatePct(T base, U pct)
Definition Util.h:72
SpellInfo const * GetSpellInfo() const
int32 GetMiscValue() const
SpellEffectValue GetAmount() const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void SetUpdateFieldValue(UF::UpdateFieldPrivateSetter< T > setter, typename UF::UpdateFieldPrivateSetter< T >::value_type value)
Definition BaseEntity.h:221
void SetUpdateFieldStatValue(UF::UpdateFieldPrivateSetter< T > setter, typename UF::UpdateFieldPrivateSetter< T >::value_type value)
Definition BaseEntity.h:299
UF::UpdateFieldHolder m_values
Definition BaseEntity.h:205
void ApplyModUpdateFieldValue(UF::UpdateFieldPrivateSetter< T > setter, typename UF::UpdateFieldPrivateSetter< T >::value_type mod, bool apply)
Definition BaseEntity.h:306
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
bool UpdateAllStats() override
CreatureDifficulty const * GetCreatureDifficulty() const
Definition Creature.h:276
bool UpdateStats(Stats stat) override
uint32 GetPowerIndex(Powers power) const override
int32 GetCreatePowerValue(Powers power) const override
uint32 m_baseAttackPower
Definition Creature.h:559
void UpdateAttackPowerAndDamage(bool ranged=false) override
void UpdateArmor() override
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:274
ClassPowerTypes GetPowerTypes() const override
void UpdateMaxPower(Powers power) override
uint32 m_baseRangedAttackPower
Definition Creature.h:560
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float &minDamage, float &maxDamage) const override
void UpdateMaxHealth() override
static uint32 GetPowerIndexByClass(Powers power, uint32 classId)
static ClassPowerTypes GetPowerTypesByClass(uint32 classId)
void UpdateResistances(uint32 school) override
void UpdateMaxPower(Powers power) override
void UpdateMaxHealth() override
bool UpdateStats(Stats stat) override
void SetBonusDamage(int32 damage)
int32 m_bonusSpellDamage
float m_statFromOwner[MAX_STATS]
void UpdateDamagePhysical(WeaponAttackType attType) override
void UpdateArmor() override
bool UpdateAllStats() override
void UpdateAttackPowerAndDamage(bool ranged=false) override
Definition Item.h:185
Unit * GetOwner() const
bool IsSpiritWolf() const
Unit *const m_owner
bool IsPetGhoul() const
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Definition Pet.h:40
void UpdateParryPercentage()
void UpdateMastery()
void UpdateArmorPenetration(int32 amount)
void UpdateDodgePercentage()
float GetPowerRegen(Powers power) const
void ApplyModTargetResistance(int32 mod, bool apply)
Definition Player.h:2188
void UpdateMaxPower(Powers power) override
bool CanUseMastery() const
Definition Player.cpp:30527
bool CanParry() const
Definition Player.h:2475
void UpdateCritPercentage(WeaponAttackType attType)
void UpdatePowerRegen(Powers power)
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition Player.h:3048
uint32 GetPowerIndex(Powers power) const override
float GetRatingBonusValue(CombatRating cr) const
Definition Player.cpp:5139
bool CanBlock() const
Definition Player.h:2477
void UpdateVersatilityDamageDone()
void UpdateCorruption()
void UpdateBlockPercentage()
void ApplyModDamageDonePos(SpellSchools school, int32 mod, bool apply)
Definition Player.h:2199
void ApplySpellPenetrationBonus(int32 amount, bool apply)
void UpdateArmor() override
void RecalculateRating(CombatRating cr)
Definition Player.h:2213
Pet * GetPet() const
Definition Player.cpp:22007
bool UpdateStats(Stats stat) override
void _RemoveAllItemMods()
Definition Player.cpp:8853
void _ApplyAllItemMods()
Definition Player.cpp:8893
void UpdateSpellHitChances()
void UpdateExpertise(WeaponAttackType attType)
void _ApplyAllStatBonuses()
float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const
Definition Player.cpp:4974
void ApplyAllAzeriteItemMods(bool apply)
Definition Player.cpp:8960
void UpdateHealingDonePercentMod()
void ApplyManaRegenBonus(int32 amount, bool apply)
void GetDodgeFromAgility(float &diminishing, float &nondiminishing) const
Definition Player.cpp:4998
void SetBaseModPctValue(BaseModGroup modGroup, float val)
Definition Player.cpp:4896
void UpdateResistances(uint32 school) override
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float &minDamage, float &maxDamage) const override
void UpdateSpellDamageAndHealingBonus()
uint32 m_baseSpellPower
Definition Player.h:3242
void UpdateMaxHealth() override
void UpdateMeleeHitChances()
ClassPowerTypes GetPowerTypes() const override
TimePoint m_regenInterruptTimestamp
Definition Player.h:3059
uint32 m_baseHealthRegen
Definition Player.h:3244
void UpdateRangedHitChances()
uint32 m_baseManaRegen
Definition Player.h:3243
void UpdateAllRatings()
Definition Player.cpp:5376
void ApplySpellPowerBonus(int32 amount, bool apply)
void UpdateAllCritPercentages()
bool UpdateAllStats() override
Item * GetWeaponForAttack(WeaponAttackType attackType, bool useable=false) const
Definition Player.cpp:9577
void _RemoveAllStatBonuses()
int32 m_spellPenetrationItemMod
Definition Player.h:3245
Stats GetPrimaryStat() const
void ApplyHealthRegenBonus(int32 amount, bool apply)
void UpdateSpellCritChance()
ChrSpecializationEntry const * GetPrimarySpecializationEntry() const
Definition Player.cpp:30736
float GetHealthBonusFromStamina() const
void UpdateAttackPowerAndDamage(bool ranged=false) override
MutableFieldReference< T, false > ModifyValue(UpdateField< T, BlockBit, Bit >(Derived::*field))
Definition Unit.h:647
float GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const
Definition Unit.cpp:9695
virtual void UpdateResistances(uint32 school)
Definition Unit.cpp:9954
bool IsHunterPet() const
Definition Unit.h:764
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1362
void SetStat(Stats stat, int32 val)
Definition Unit.h:785
float GetTotalAuraModValue(UnitMods unitMod) const
Definition Unit.cpp:9900
float GetTotalStatValue(Stats stat) const
Definition Unit.cpp:9884
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3846
virtual int32 GetCreatePowerValue(Powers power) const
uint8 GetClass() const
Definition Unit.h:776
void SetArmor(int32 val, int32 bonusVal)
Definition Unit.h:787
bool CanUseAttackType(uint8 attacktype) const
Definition Unit.cpp:2594
virtual void UpdateAllResistances()
ShapeshiftForm GetShapeshiftForm() const
Definition Unit.h:1527
std::forward_list< AuraEffect * > AuraEffectList
Definition Unit.h:664
void SetAttackPowerModNeg(int32 attackPowerMod)
Definition Unit.h:1588
bool haveOffhandWeapon() const
Definition Unit.cpp:530
bool IsPet() const
Definition Unit.h:763
Powers GetPowerType() const
Definition Unit.h:823
bool CanDualWield() const
Definition Unit.h:715
uint32 GetBaseAttackTime(WeaponAttackType att) const
Definition Unit.cpp:11007
float m_modRangedHitChance
Definition Unit.h:1538
void SetBonusResistanceMod(SpellSchools school, int32 val)
Definition Unit.h:797
void SetRangedAttackPowerModNeg(int32 attackPowerMod)
Definition Unit.h:1592
void SetRangedAttackPowerModPos(int32 attackPowerMod)
Definition Unit.h:1591
float GetTotalAuraMultiplier(AuraType auraType) const
Definition Unit.cpp:5092
virtual void UpdateDamagePhysical(WeaponAttackType attType)
void _ApplyAllAuraStatMods()
Definition Unit.cpp:4616
void SetRangedAttackPowerMultiplier(float attackPowerMult)
Definition Unit.h:1593
void SetResistance(SpellSchools school, int32 val)
Definition Unit.h:796
float GetTotalAuraMultiplierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5157
float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const
Definition Unit.cpp:10005
uint32 GetCreateHealth() const
Definition Unit.h:1435
float GetTotalAuraModifier(AuraType auraType) const
Definition Unit.cpp:5087
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4832
uint32 GetArmor() const
Definition Unit.h:786
float m_modMeleeHitChance
Definition Unit.h:1537
void _RemoveAllAuraStatMods()
Definition Unit.cpp:4610
float GetAPMultiplier(WeaponAttackType attType, bool normalized) const
Definition Unit.cpp:11122
virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float &minDamage, float &maxDamage) const =0
void SetAttackPower(int32 attackPower)
Definition Unit.h:1586
void SetMaxHealth(uint64 val)
Definition Unit.cpp:10072
float GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5147
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1897
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const
Definition Unit.cpp:7602
float GetTotalAttackPowerValue(WeaponAttackType attType, bool includeWeapon=true) const
Definition Unit.cpp:9975
float GetCreateStat(Stats stat) const
Definition Unit.cpp:5312
int32 GetBonusResistanceMod(SpellSchools school) const
Definition Unit.h:794
float GetAttackPowerModifierValue(AttackPowerModIndex index, AttackPowerModType modifierType) const
Definition Unit.cpp:9790
void SetCanModifyStats(bool modifyStats)
Definition Unit.h:1575
float GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const
Definition Unit.cpp:9684
float GetStat(Stats stat) const
Definition Unit.h:784
void SetMaxPower(Powers power, int32 val)
Definition Unit.cpp:10151
uint32 GetCreateMana() const
Definition Unit.h:1437
void SetRangedAttackPower(int32 attackPower)
Definition Unit.h:1590
int32 GetResistance(SpellSchools school) const
Definition Unit.h:793
float m_modSpellHitChance
Definition Unit.h:1539
Guardian * GetGuardianPet() const
Definition Unit.cpp:6250
void SetAttackPowerMultiplier(float attackPowerMult)
Definition Unit.h:1589
AuraMap & GetOwnedAuras()
Definition Unit.h:1305
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
Definition Unit.cpp:7103
void SetAttackPowerModPos(int32 attackPowerMod)
Definition Unit.h:1587
uint8 GetLevel() const
Definition Unit.h:769
bool IsInCombat() const
Definition Unit.h:1073
void UpdateStatBuffMod(Stats stat)
Definition Unit.cpp:5237
#define sWorld
Definition World.h:919
@ RATE_POWER_CHI
Definition World.h:465
@ RATE_POWER_RUNIC_POWER_LOSS
Definition World.h:460
@ RATE_POWER_RAGE_LOSS
Definition World.h:455
@ RATE_POWER_ENERGY
Definition World.h:457
@ RATE_POWER_MANA
Definition World.h:453
@ RATE_POWER_MAELSTROM
Definition World.h:464
@ RATE_POWER_INSANITY
Definition World.h:466
@ RATE_POWER_FURY
Definition World.h:468
@ RATE_POWER_FOCUS
Definition World.h:456
@ RATE_POWER_ARCANE_CHARGES
Definition World.h:467
@ RATE_POWER_HOLY_POWER
Definition World.h:463
@ RATE_POWER_LUNAR_POWER
Definition World.h:462
@ RATE_POWER_ESSENCE
Definition World.h:470
@ RATE_POWER_SOUL_SHARDS
Definition World.h:461
@ RATE_POWER_PAIN
Definition World.h:469
@ RATE_POWER_COMBO_POINTS_LOSS
Definition World.h:458
@ CONFIG_STATS_LIMITS_DODGE
Definition World.h:216
@ CONFIG_STATS_LIMITS_PARRY
Definition World.h:217
@ CONFIG_STATS_LIMITS_CRIT
Definition World.h:219
@ CONFIG_STATS_LIMITS_BLOCK
Definition World.h:218
@ CONFIG_STATS_LIMITS_ENABLE
Definition World.h:172
TimePoint Now()
Current chrono steady_clock time point.
Definition GameTime.cpp:67
uint8 AttackPowerPerAgility
uint8 RangedAttackPowerPerAgility
uint8 AttackPowerPerStrength
std::array< Powers, MAX_POWERS_PER_CLASS > PowerType
Definition DB2Stores.h:334
int32 RegenInterruptTimeMS
EnumFlag< PowerTypeFlags > GetFlags() const
UpdateField< float, 70, 80 > SpellCritPercentage
UpdateField< float, 70, 72 > BlockPercentage
UpdateField< int32, 70, 87 > Versatility
UpdateField< float, 32, 68 > OffhandExpertise
UpdateField< float, 70, 77 > CritPercentage
UpdateFieldArray< int32, 32, 333, 334 > CombatRatings
UpdateField< int32, 70, 92 > ModHealingDonePos
UpdateField< float, 70, 83 > Mastery
UpdateFieldArray< int32, 7, 272, 280 > ModDamageDoneNeg
UpdateField< float, 70, 73 > DodgePercentage
UpdateField< float, 70, 78 > RangedCritPercentage
UpdateField< float, 70, 79 > OffhandCritPercentage
UpdateFieldArray< int32, 7, 272, 273 > ModDamageDonePos
UpdateFieldArray< float, 7, 272, 294 > ModHealingDonePercent
UpdateField< float, 70, 75 > ParryPercentage
UpdateField< float, 32, 67 > MainhandExpertise
UpdateFieldArray< float, 10, 139, 170 > PowerRegenInterruptedFlatModifier
UpdateFieldArray< float, 10, 139, 160 > PowerRegenFlatModifier
UpdateField< float, 32, 63 > MinDamage
UpdateField< float, 96, 107 > MinRangedDamage
UpdateField< float, 64, 67 > MaxOffHandDamage
UpdateField< float, 64, 65 > MaxDamage
UpdateField< float, 96, 108 > MaxRangedDamage
UpdateField< float, 64, 66 > MinOffHandDamage