mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-12-06 02:30:26 -08:00
fix(Core/Spells): Implement TrinityCore spell_group and spell_group_stack_rules (#23346)
Co-authored-by: treeston <treeston.mmoc@gmail.com> Co-authored-by: Trisjdc <trisjdc@gmail.com> Co-authored-by: QAston <none@none> Co-authored-by: ariel- <ariel-@users.noreply.github.com> Co-authored-by: Shauren <shauren.trinity@gmail.com> Co-authored-by: Jelle Meeus <sogladev@gmail.com>
This commit is contained in:
parent
55989205e7
commit
2f7f9bd72f
42 changed files with 1976 additions and 1705 deletions
213
data/sql/updates/pending_db_world/rev_1759840412674707391.sql
Normal file
213
data/sql/updates/pending_db_world/rev_1759840412674707391.sql
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
ALTER TABLE `spell_group` DROP `special_flag`;
|
||||
ALTER TABLE `spell_group` MODIFY COLUMN `spell_id` int;
|
||||
|
||||
-- import from trinitycore
|
||||
DELETE FROM `spell_group`;
|
||||
INSERT INTO `spell_group` (`id`,`spell_id`) VALUES
|
||||
(1, 2367), (1, 2374), (1, 3160), (1, 3164), (1, 7844), (1, 8212), (1, 10667), (1, 10669), (1, 11328), (1, 11334), (1, 11390), (1, 11405), (1, 11406), (1, 11474), (1, 16322), (1, 16323), (1, 16329), (1, 17038), (1, 17537), (1, 17538), (1, 17539), (1, 17626), (1, 17627), (1, 17628), (1, 17629), (1, 21920), (1, 26276), (1, 28486), (1, 28488), (1, 28490), (1, 28491), (1, 28493), (1, 28497), (1, 28501), (1, 28503), (1, 28518), (1, 28519), (1, 28520), (1, 28521), (1, 28540), (1, 33720), (1, 33721), (1, 33726), (1, 38954), (1, 40567), (1, 40568), (1, 40572), (1, 40573), (1, 40575), (1, 40576), (1, 41608), (1, 41609), (1, 41610), (1, 41611), (1, 42735), (1, 45373), (1, 46837), (1, 46839), (1, 53746), (1, 53748), (1, 53749), (1, 53752), (1, 53755), (1, 53758), (1, 53760), (1, 54212), (1, 54452), (1, 54494), (1, 60340), (1, 60341), (1, 60344), (1, 60345), (1, 60346), (1, 62380), (1, 63729), (1, 67016), (1, 67017), (1, 67018),
|
||||
(2, 673), (2, 2378), (2, 2380), (2, 3166), (2, 3219), (2, 3220), (2, 3222), (2, 3223), (2, 3593), (2, 10668), (2, 10692), (2, 10693), (2, 11319), (2, 11348), (2, 11349), (2, 11371), (2, 11396), (2, 15231), (2, 15233), (2, 16321), (2, 16325), (2, 16326), (2, 16327), (2, 17535), (2, 17626), (2, 17627), (2, 17628), (2, 17629), (2, 24361), (2, 24363), (2, 24382), (2, 24383), (2, 24417), (2, 27652), (2, 27653), (2, 28502), (2, 28509), (2, 28514), (2, 28518), (2, 28519), (2, 28520), (2, 28521), (2, 28540), (2, 29348), (2, 39625), (2, 39626), (2, 39627), (2, 39628), (2, 40567), (2, 40568), (2, 40572), (2, 40573), (2, 40575), (2, 40576), (2, 41608), (2, 41609), (2, 41610), (2, 41611), (2, 42735), (2, 46837), (2, 46839), (2, 53747), (2, 53751), (2, 53752), (2, 53755), (2, 53758), (2, 53760), (2, 53763), (2, 53764), (2, 54212), (2, 60343), (2, 60347), (2, 62380), (2, 67016), (2, 67017), (2, 67018),
|
||||
(1001, 18125), (1001, 18141), (1001, 19705), (1001, 19706), (1001, 19708), (1001, 19709), (1001, 19710), (1001, 19711), (1001, 20875), (1001, 23697), (1001, 24799), (1001, 24870), (1001, 25037), (1001, 25694), (1001, 25722), (1001, 25804), (1001, 25941), (1001, 33254), (1001, 33256), (1001, 33257), (1001, 33259), (1001, 33261), (1001, 33263), (1001, 33265), (1001, 33268), (1001, 33272), (1001, 35272), (1001, 40323), (1001, 42293), (1001, 43722), (1001, 43764), (1001, 43771), (1001, 44097), (1001, 44098), (1001, 44099), (1001, 44100), (1001, 44101), (1001, 44102), (1001, 44104), (1001, 44105), (1001, 44106), (1001, 45245), (1001, 45619), (1001, 45694), (1001, 46682), (1001, 46687), (1001, 46899), (1001, 53284), (1001, 57079), (1001, 57097), (1001, 57100), (1001, 57102), (1001, 57107), (1001, 57111), (1001, 57139), (1001, 57286), (1001, 57288), (1001, 57291), (1001, 57294), (1001, 57325), (1001, 57327), (1001, 57329), (1001, 57332), (1001, 57334), (1001, 57356), (1001, 57358), (1001, 57360), (1001, 57363), (1001, 57365), (1001, 57367), (1001, 57371), (1001, 57373), (1001, 57399), (1001, 58468), (1001, 58479), (1001, 59230), (1001, 62349), (1001, 64057), (1001, 65247), (1001, 65365), (1001, 65410), (1001, 65412), (1001, 65414), (1001, 65415), (1001, 65416), (1001, 66623), (1001, 66624), (1001, 69559),
|
||||
(1002, 19740), (1002, 25782), (1002, 56520), -- Blessing of Might
|
||||
(1003, 6673), -- Battle Shout
|
||||
(1004, -1003), (1004, -1002), -- Flap AP Buffs
|
||||
(1005, 19742), (1005, 25894), (1005, 56521), -- Blessing of Wisdom
|
||||
(1006, 20217), (1006, 25898), (1006, 43223), (1006, 56525), (1006, 58054), (1006, 72586), -- All Stats Percentage
|
||||
(1007, 20911), (1007, 25899), -- Blessing of Sanctuary
|
||||
(1008, 23415), (1008, 41450), -- Blessing of Protection
|
||||
(1009, 32770), -- Blessing of Light
|
||||
(1010, -1009), (1010, -1008), (1010, -1007), (1010, -1006), (1010, -1005), (1010, -1002), -- Blessings
|
||||
(1011, -1091), (1011, -1003), -- Warrior Shouts
|
||||
(1012, 55749), -- Acid Spit
|
||||
(1013, 8647), -- Expose Armor
|
||||
(1014, 58567), -- Sunder Armor
|
||||
(1015, -1014), (1015, -1013), (1015, -1012), -- Major Armor Debuffs
|
||||
(1016, 770), (1016, 16857), -- Faerie Fire
|
||||
(1017, 56626), -- Sting
|
||||
(1019, -1063), (1019, -1017), (1019, -1016), -- Minor Armor Debuffs
|
||||
(1020, 55610), -- Icy Talons
|
||||
(1021, 8515), -- Windfury Totem
|
||||
(1022, -1021), (1022, -1020), -- Melee Haste Buffs
|
||||
(1023, 24932), -- Leader of the Pack
|
||||
(1024, 29801), -- Rampage
|
||||
(1025, -1024), (1025, -1023), -- Physical Crit Buffs
|
||||
(1026, 53137), -- Abomination's Might
|
||||
(1027, 19506), -- Trueshot Aura
|
||||
(1028, 30802), -- Unleashed Rage
|
||||
(1029, -1028), (1029, -1027), (1029, -1026), -- Percentage AP Buffs
|
||||
(1030, 33878), -- Mangle (Bear)
|
||||
(1031, 33876), -- Mangle (Cat)
|
||||
(1032, 46856), -- Trauma
|
||||
(1033, -1032), (1033, -1031), (1033, -1030), -- Bleed Debuffs
|
||||
(1034, 24907), -- Moonkin Aura
|
||||
(1035, 51466), -- Elemental Oath
|
||||
(1036, -1035), (1036, -1034), -- Spell Crit Buffs
|
||||
(1037, 12579), (1037, 17794), (1037, 17797), (1037, 17798), (1037, 17799), (1037, 17800), (1037, 22959), -- Spell Crit Debuffs
|
||||
(1038, -1006), (1038, 67480), -- All Stats Percentage with Sanctuary
|
||||
-- 1039-44
|
||||
(1045, 52109), -- Flametongue Totem
|
||||
(1046, 57658), -- Totem of Wrath
|
||||
(1047, 48090), -- Demonic Pact
|
||||
(1048, -1047), (1048, -1046), (1048, -1045), -- Spell Power Buffs
|
||||
-- 1049
|
||||
(1050, 33196), -- Misery
|
||||
(1051, -1050), (1051, -1016), -- Spell Hit Debuffs
|
||||
(1052, 7294), -- Retribution Aura
|
||||
(1053, 63531), -- Sanctified Retribution
|
||||
(1054, -1053), (1054, -1052), (1054, 50170), -- Haste Buffs
|
||||
-- 1055
|
||||
(1056, -1053), (1056, -1052), (1056, 31579), (1056, 75593), -- Damage Done Buffs
|
||||
(1057, 13218), -- Wound Poison
|
||||
(1058, -1057), (1058, 2818), (1058, 3409), (1058, 5760), (1058, 21183), (1058, 30708), -- Crit Taken Debuffs
|
||||
(1059, 89), (1059, 6136), (1059, 6343), (1059, 6360), (1059, 7321), (1059, 8042), (1059, 16914), (1059, 20005), (1059, 27648), (1059, 51693), (1059, 55095), (1059, 58179), (1059, 68055), -- Attack Speed Debuffs
|
||||
(1060, 3043), (1060, 5570), -- Hit Chance Debuffs
|
||||
(1061, -1057), (1061, 12294), (1061, 19434), (1061, 56112), -- Healing Taken Debuffs
|
||||
(1062, -1063), (1062, 67), (1062, 99), (1062, 1160), -- AP Debuffs
|
||||
(1063, 702), -- Curse of Weakness
|
||||
(1064, 8076), -- Strength of Earth
|
||||
(1065, 57330), -- Horn of Winter
|
||||
(1066, 8118), -- Strength Scroll
|
||||
(1067, 8115), -- Agility Scroll
|
||||
(1068, 8096), -- Intellect Scroll
|
||||
(1069, 8099), -- Stamina Scroll
|
||||
(1070, 8112), -- Spirit Scroll
|
||||
(1071, 8091), -- Armor Scroll
|
||||
(1072, 1459), -- Arcane Intellect
|
||||
(1073, 54424), -- Fel Intelligence
|
||||
(1074, 1243), -- Power Word: Fortitude
|
||||
(1075, 21562), -- Prayer of Fortitude
|
||||
(1076, 14752), -- Divine Spirit
|
||||
(1077, 27681), -- Prayer of Spirit
|
||||
(1078, 1126), -- Mark of the Wild
|
||||
(1079, 21849), -- Gift of the Wild
|
||||
(1080, 23028), -- Arcane Brilliance
|
||||
(1081, 61024), -- Dalaran Intellect
|
||||
(1082, 61316), -- Dalaran Brilliance
|
||||
(1083, -1082), (1083, -1081), (1083, -1080), (1083, -1072), (1083, -1068), -- Mage Intellect Buffs
|
||||
(1084, -1075), (1084, -1074), (1084, -1069), (1084, 72590), -- Priest Stamina Buffs
|
||||
(1085, -1077), (1085, -1076), (1085, -1070), -- Priest Spirit Buffs
|
||||
(1086, -1071), (1086, 8072), -- Armor Buffs
|
||||
(1087, -1071), (1087, -1070), (1087, -1069), (1087, -1068), (1087, -1067), (1087, -1066),-- Scrolls
|
||||
(1088, -1065), (1088, -1064), -- Strength and Agility Buffs
|
||||
(1091, 469), -- Commanding Shout
|
||||
(1092, 6307), -- Blood Pact
|
||||
(1093, -1092), (1093, -1091), -- HP Buffs
|
||||
(1094, 34123), (1094, 63514), -- Healing Taken Buffs
|
||||
(1095, 14893), (1095, 16177), -- Physical Taken Buffs
|
||||
(1096, 1714), (1096, 5760), (1096, 31589), -- Cast Time Debuffs
|
||||
(1097, 122), (1097, 33395), (1097, 55080), -- Frost Novas
|
||||
(1098, 976), (1098, 27683), -- Shadow Protection
|
||||
(1099, 348), (1099, 30108), -- Immolate and Unstable Affliction
|
||||
(1100, 604), (1100, 1008), -- Dampen/Amplify Magic
|
||||
(1101, 1490), (1101, 51726), (1101, 60431), -- Spell Damage Taken Debuffs
|
||||
(1102, 40055), (1102, 40165), (1102, 40166), (1102, 40167), -- Introspection
|
||||
(1103, 40623), (1103, 40625), (1103, 40626), -- Apexis Movement Speed
|
||||
(1104, 12880), (1104, 57514), (1104, 57518), -- Warrior Enrages
|
||||
(1105, -1005), (1105, 5677), -- MP5 Buffs
|
||||
(1106, 6562), (1106, 28878), -- Heroic Presence
|
||||
(1107, 12042), (1107, 12292), (1107, 31884), (1107, 34471), (1107, 49016), (1107, 57933), -- Temporary Damage Increases
|
||||
(1108, 30069), (1108, 58684), -- Phys Damage Taken Debuffs
|
||||
(1110, 74826), (1110, 74827), (1110, 74828), (1110, 74829), (1110, 74830), (1110, 74831), (1110, 74832), (1110, 74833), (1110, 74834), (1110, 74835), (1110, 74836), -- Corporeality
|
||||
(1111, 62727), (1111, 63438), (1111, 63439), (1111, 63440), (1111, 63441), (1111, 63442), (1111, 63443), (1111, 63444), (1111, 63445), (1111, 63446), -- Champion's Pennant
|
||||
(1112, 8219), (1112, 8220), (1112, 8221), (1112, 8222), -- Flip Out
|
||||
-- 1116-20
|
||||
(1121, 3671), (1121, 3672), (1121, 3673), -- Elemental Slave Buffs
|
||||
(1122, 2825), (1122, 10060), (1122, 32182), -- Temporary Haste Buffs
|
||||
(1123, 10060), (1123, 12042), -- Power Infusion and Arcane Power
|
||||
(1124, -1085), (1124, -1073), -- Intellect Buffs
|
||||
(1125, -1083), (1125, -1073), -- Spirit Buffs
|
||||
|
||||
-- values missing from trinitycore
|
||||
(1, 33053), -- Crawdad Flask
|
||||
(1001, 5020), (1001, 5021), (1001, 5257), (1001, 6114), (1001, 15852), (1001, 18191), (1001, 18192), (1001, 18193), (1001, 18194), (1001, 18222), (1001, 22730), (1001, 22789), (1001, 25661), (1001, 37058), (1001, 43730), -- More Foods
|
||||
(1006, 26393), -- Elune's Blessing
|
||||
(1062, 24423), -- Demoralizing Screech
|
||||
(1019, 50274), -- Spore Cloud
|
||||
(1022, 23060), -- Battle Squawk
|
||||
-- (1058, 45176), -- Server Side Master Poisoner (is it needed?)
|
||||
(1084, 23947), (1084, 23948), -- NPC Power Word Fortitude
|
||||
(1096, 35387), -- Poison Spit
|
||||
(1096, 58604), -- Lava Breath
|
||||
(1089, -1079), (1089, -1078), (1089, 72588), (1089, 16878), (1089, 24752), (1089, 39233), -- Mark of the Wild
|
||||
(1107, 48391), -- Owlkin Frenzy
|
||||
(1090, 7481), (1090, 7483), (1090, 7484), -- Howling Rage
|
||||
(1113, 467), -- Thorns
|
||||
(1114, 70233), (1114, 70234), (1114, 70235), (1114, 70242), (1114, 70243), (1114, 70244), -- Perfumes/Colognes
|
||||
(1115, 46302), -- K'iru's Song of Victory
|
||||
(1126, -1115), (1126, -1084), -- Stamina Buffs
|
||||
(1124, -1115); -- Intellect Buffs
|
||||
|
||||
DELETE FROM `spell_group_stack_rules`;
|
||||
INSERT INTO `spell_group_stack_rules` (`group_id`,`stack_rule`, `description`) VALUES
|
||||
(1, 1,'Battle Elixir'),
|
||||
(2, 1, 'Guardian Elixir'),
|
||||
(1001, 1, 'Well Fed'),
|
||||
(1002, 4, 'Blessing of Might'),
|
||||
(1003, 4, 'Battle Shout'),
|
||||
(1004, 4, 'Flat AP Buffs'),
|
||||
(1005, 4, 'Blessing of Wisdom'),
|
||||
(1006, 1, 'All Stats Percentage'),
|
||||
(1007, 1, 'Blessing of Sanctuary'),
|
||||
(1008, 1, 'Blessing of Protection'),
|
||||
(1009, 1, 'Blessing of Light'),
|
||||
(1010, 2, 'Blessings'),
|
||||
(1011, 2, 'Warrior Shouts'),
|
||||
(1015, 3, 'Major Armor Debuffs'),
|
||||
(1016, 4, 'Faerie Fire'),
|
||||
(1019, 3, 'Minor Armor Debuffs'),
|
||||
(1022, 3, 'Melee Haste Buffs'),
|
||||
(1023, 4, 'Leader of the Pack'),
|
||||
(1024, 4, 'Rampage'),
|
||||
(1025, 3, 'Physical Crit Buffs'),
|
||||
(1029, 1, 'Percentage AP Buffs'),
|
||||
(1033, 1, 'Bleed Debuffs'),
|
||||
(1036, 4, 'Spell Crit Buffs'),
|
||||
(1037, 3, 'Spell Crit Debuffs'),
|
||||
(1038, 3, 'All Stats Percentage with Sanctuary'),
|
||||
(1046, 4, 'Totem of Wrath'),
|
||||
(1048, 4, 'Spell Power Buffs'),
|
||||
(1051, 3, 'Spell Hit Debuffs'),
|
||||
(1054, 3, 'Haste Buffs'),
|
||||
(1056, 3, 'Damage Done Buffs'),
|
||||
(1058, 3, 'Poisons'),
|
||||
(1059, 3, 'Attack Speed Debuffs'),
|
||||
(1060, 3, 'Hit Chance Debuffs'),
|
||||
(1061, 4, 'Healing Taken Debuffs'),
|
||||
(1062, 4, 'AP Debuffs'),
|
||||
(1083, 4, 'Single Intellect Buffs'),
|
||||
(1084, 4, 'Single Stamina Buffs'),
|
||||
(1085, 4, 'Single Spirit Buffs'),
|
||||
(1086, 4, 'Armor Buffs'),
|
||||
(1087, 4, 'Scrolls'),
|
||||
(1088, 4, 'Strength and Agility Buffs'),
|
||||
(1091, 0, 'Commanding Shout'),
|
||||
(1092, 0, 'Blood Pact'),
|
||||
(1093, 4, 'Flat HP Buffs'),
|
||||
(1094, 3, 'Healing Taken Buffs'),
|
||||
(1095, 4, 'Physical Taken Buffs'),
|
||||
(1096, 4, 'Cast Time Debuffs'),
|
||||
(1097, 1, 'Frost Novals'),
|
||||
(1098, 4, 'Shadow Protection'),
|
||||
(1099, 2, 'Immolate and Unstable Affliction'),
|
||||
(1100, 1, 'Dampen/Amplify Magic'),
|
||||
(1101, 3, 'Spell Damage Taken Debuffs'),
|
||||
(1104, 1, 'Warrior Enrages'),
|
||||
(1105, 3, 'MP5 Buffs'),
|
||||
(1106, 1, 'Heroic Presence'),
|
||||
(1107, 4, 'Temporary Damage Increases'),
|
||||
(1108, 4, 'Phys Damage Taken Debuffs'),
|
||||
(1110, 1, 'Corporeality'),
|
||||
(1111, 1, 'Champion''s Pennants'),
|
||||
(1112, 1, 'Flip Out'),
|
||||
(1121, 1, 'Elemental Slave Buffs'),
|
||||
(1122, 4, 'Temporary Haste Buffs'),
|
||||
(1123, 1, 'Power Infusion and Arcane Power'),
|
||||
(1124, 3, 'Intellect Buffs'),
|
||||
(1125, 3, 'Spirit Buffs'),
|
||||
|
||||
-- additions
|
||||
(1089, 4, 'Mark of the Wild'),
|
||||
(1113, 4, 'Thorns'),
|
||||
(1126, 3, 'Stamina Buffs');
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` IN (18735, 56246, 56247);
|
||||
INSERT INTO `spell_script_names` VALUES (18735, 'spell_warl_voidwalker_pet_passive');
|
||||
|
|
@ -47,15 +47,6 @@ AC_COMMON_API Optional<int32> MoneyStringToMoney(std::string_view moneyString);
|
|||
std::string secsToTimeString(uint64 timeInSecs, bool shortText = false);
|
||||
uint32 TimeStringToSecs(const std::string& timestring);
|
||||
|
||||
inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
|
||||
{
|
||||
if (val == -100.0f) // prevent set var to zero
|
||||
{
|
||||
val = -99.99f;
|
||||
}
|
||||
var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
|
||||
}
|
||||
|
||||
// Percentage calculation
|
||||
template <class T, class U>
|
||||
inline T CalculatePct(T base, U pct)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "PoolMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellAuraDefines.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "TemporarySummon.h"
|
||||
|
|
@ -601,13 +602,13 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
|
|||
SetMeleeDamageSchool(SpellSchools(cInfo->dmgschool));
|
||||
CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(GetLevel(), cInfo->unit_class);
|
||||
float armor = stats->GenerateArmor(cInfo);
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, armor);
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE]));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST]));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW]));
|
||||
SetModifierValue(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE]));
|
||||
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor);
|
||||
SetStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_HOLY]));
|
||||
SetStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FIRE]));
|
||||
SetStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_NATURE]));
|
||||
SetStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_FROST]));
|
||||
SetStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_SHADOW]));
|
||||
SetStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(cInfo->resistance[SPELL_SCHOOL_ARCANE]));
|
||||
|
||||
SetCanModifyStats(true);
|
||||
UpdateAllStats();
|
||||
|
|
@ -1017,10 +1018,7 @@ void Creature::Regenerate(Powers power)
|
|||
}
|
||||
|
||||
// Apply modifiers (if any).
|
||||
AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
|
||||
for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
|
||||
if (Powers((*i)->GetMiscValue()) == power)
|
||||
AddPct(addvalue, (*i)->GetAmount());
|
||||
addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, power);
|
||||
|
||||
addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power) * (power == POWER_FOCUS ? PET_FOCUS_REGEN_INTERVAL.count() : CREATURE_REGEN_INTERVAL) / (5 * IN_MILLISECONDS);
|
||||
|
||||
|
|
@ -1056,9 +1054,7 @@ void Creature::RegenerateHealth()
|
|||
}
|
||||
|
||||
// Apply modifiers (if any).
|
||||
AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT);
|
||||
for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
|
||||
AddPct(addvalue, (*i)->GetAmount());
|
||||
addvalue *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT);
|
||||
|
||||
addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_REGEN) * CREATURE_REGEN_INTERVAL / (5 * IN_MILLISECONDS);
|
||||
|
||||
|
|
@ -1558,8 +1554,8 @@ void Creature::SelectLevel(bool changelevel)
|
|||
|
||||
/// @todo: set UNIT_FIELD_POWER*, for some creature class case (energy, etc)
|
||||
|
||||
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
|
||||
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana);
|
||||
SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
|
||||
SetStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, (float)mana);
|
||||
|
||||
// damage
|
||||
|
||||
|
|
@ -1577,8 +1573,8 @@ void Creature::SelectLevel(bool changelevel)
|
|||
SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage);
|
||||
SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
|
||||
|
||||
SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
|
||||
SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
|
||||
SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
|
||||
SetStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
|
||||
|
||||
sScriptMgr->OnCreatureSelectLevel(cInfo, this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -815,13 +815,6 @@ void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply)
|
|||
SetFloatValue(index, cur);
|
||||
}
|
||||
|
||||
void Object::ApplyPercentModFloatValue(uint16 index, float val, bool apply)
|
||||
{
|
||||
float value = GetFloatValue(index);
|
||||
ApplyPercentModFloatVar(value, val, apply);
|
||||
SetFloatValue(index, value);
|
||||
}
|
||||
|
||||
void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
|
||||
{
|
||||
float cur = GetFloatValue(index);
|
||||
|
|
|
|||
|
|
@ -165,7 +165,6 @@ public:
|
|||
void ApplyModUInt64Value(uint16 index, int32 val, bool apply);
|
||||
void ApplyModPositiveFloatValue(uint16 index, float val, bool apply);
|
||||
void ApplyModSignedFloatValue(uint16 index, float val, bool apply);
|
||||
void ApplyPercentModFloatValue(uint16 index, float val, bool apply);
|
||||
|
||||
void SetFlag(uint16 index, uint32 newFlag);
|
||||
void RemoveFlag(uint16 index, uint32 oldFlag);
|
||||
|
|
|
|||
|
|
@ -1075,7 +1075,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
|||
SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool));
|
||||
}
|
||||
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
|
||||
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
|
||||
|
||||
uint32 attackTime = BASE_ATTACK_TIME;
|
||||
if (!owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET) && cinfo->BaseAttackTime >= 1000)
|
||||
|
|
@ -1094,7 +1094,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
|||
// xinef: hunter pets should not inherit template resistances
|
||||
if (!IsHunterPet())
|
||||
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
|
||||
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i]));
|
||||
SetStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i]));
|
||||
|
||||
//health, mana, armor and resistance
|
||||
PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel);
|
||||
|
|
@ -1111,15 +1111,15 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
|||
}
|
||||
|
||||
SetCreateHealth(pInfo->health*factorHealth);
|
||||
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)pInfo->health);
|
||||
SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)pInfo->health);
|
||||
if (petType != HUNTER_PET) //hunter pet use focus
|
||||
{
|
||||
SetCreateMana(pInfo->mana);
|
||||
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)pInfo->mana);
|
||||
SetStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, (float)pInfo->mana);
|
||||
}
|
||||
|
||||
if (pInfo->armor > 0)
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
|
||||
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
|
||||
|
||||
for (uint8 stat = 0; stat < MAX_STATS; ++stat)
|
||||
SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
|
||||
|
|
@ -1138,9 +1138,9 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
|||
}
|
||||
|
||||
SetCreateHealth(std::max<uint32>(1, stats->BaseHealth[cinfo->expansion]*factorHealth));
|
||||
SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, GetCreateHealth());
|
||||
SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, GetCreateHealth());
|
||||
SetCreateMana(stats->BaseMana * factorMana);
|
||||
SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, GetCreateMana());
|
||||
SetStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, GetCreateMana());
|
||||
|
||||
// xinef: added some multipliers so debuffs can affect pets in any way...
|
||||
SetCreateStat(STAT_STRENGTH, 22);
|
||||
|
|
@ -1174,24 +1174,6 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
|||
|
||||
switch (GetEntry())
|
||||
{
|
||||
case NPC_FELGUARD:
|
||||
{
|
||||
// xinef: Glyph of Felguard, so ugly im crying... no appropriate spell
|
||||
if (AuraEffect* aurEff = owner->GetAuraEffectDummy(SPELL_GLYPH_OF_FELGUARD))
|
||||
{
|
||||
HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), true);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case NPC_VOIDWALKER:
|
||||
{
|
||||
if (AuraEffect* aurEff = owner->GetAuraEffectDummy(SPELL_GLYPH_OF_VOIDWALKER))
|
||||
{
|
||||
HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_PCT, aurEff->GetAmount(), true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NPC_WATER_ELEMENTAL_PERM:
|
||||
{
|
||||
AddAura(SPELL_PET_AVOIDANCE, this);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "Pet.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellAuraDefines.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
|
||||
// KillRewarder incapsulates logic of rewarding player upon kill with:
|
||||
|
|
@ -162,9 +163,7 @@ void KillRewarder::_RewardXP(Player* player, float rate)
|
|||
if (xp)
|
||||
{
|
||||
// 4.2.2. Apply auras modifying rewarded XP (SPELL_AURA_MOD_XP_PCT).
|
||||
Unit::AuraEffectList const& auras = player->GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT);
|
||||
for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
|
||||
AddPct(xp, (*i)->GetAmount());
|
||||
xp *= player->GetTotalAuraMultiplier(SPELL_AURA_MOD_XP_PCT);
|
||||
|
||||
// 4.2.3. Give XP to player.
|
||||
sScriptMgr->OnPlayerGiveXP(player, xp, _victim, PlayerXPSource::XPSOURCE_KILL);
|
||||
|
|
|
|||
|
|
@ -69,8 +69,10 @@
|
|||
#include "Realm.h"
|
||||
#include "ReputationMgr.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuraDefines.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellMgr.h"
|
||||
|
|
@ -312,8 +314,8 @@ Player::Player(WorldSession* session): Unit(), m_mover(this)
|
|||
|
||||
for (uint8 i = 0; i < BASEMOD_END; ++i)
|
||||
{
|
||||
m_auraBaseMod[i][FLAT_MOD] = 0.0f;
|
||||
m_auraBaseMod[i][PCT_MOD] = 1.0f;
|
||||
m_auraBaseFlatMod[i] = 0.0f;
|
||||
m_auraBasePctMod[i] = 1.0f;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < MAX_COMBAT_RATING; i++)
|
||||
|
|
@ -831,9 +833,7 @@ int32 Player::getMaxTimer(MirrorTimerType timer)
|
|||
if (!IsAlive() || HasWaterBreathingAura() || GetSession()->GetSecurity() >= AccountTypes(sWorld->getIntConfig(CONFIG_DISABLE_BREATHING)))
|
||||
return DISABLED_MIRROR_TIMER;
|
||||
int32 UnderWaterTime = sWorld->getIntConfig(CONFIG_WATER_BREATH_TIMER);
|
||||
AuraEffectList const& mModWaterBreathing = GetAuraEffectsByType(SPELL_AURA_MOD_WATER_BREATHING);
|
||||
for (AuraEffectList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i)
|
||||
AddPct(UnderWaterTime, (*i)->GetAmount());
|
||||
UnderWaterTime *= GetTotalAuraMultiplier(SPELL_AURA_MOD_WATER_BREATHING);
|
||||
return UnderWaterTime;
|
||||
}
|
||||
case FIRE_TIMER:
|
||||
|
|
@ -1922,10 +1922,7 @@ void Player::Regenerate(Powers power)
|
|||
// Mana regen calculated in Player::UpdateManaRegen(), energy regen calculated in Player::UpdateEnergyRegen()
|
||||
if (power != POWER_MANA && power != POWER_ENERGY)
|
||||
{
|
||||
AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
|
||||
for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
|
||||
if (Powers((*i)->GetMiscValue()) == power)
|
||||
AddPct(addvalue, (*i)->GetAmount());
|
||||
addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, power);
|
||||
|
||||
// Butchery requires combat for this effect
|
||||
if (power != POWER_RUNIC_POWER || IsInCombat())
|
||||
|
|
@ -2008,11 +2005,7 @@ void Player::RegenerateHealth()
|
|||
addvalue *= 1.33f;
|
||||
}
|
||||
|
||||
AuraEffectList const& mModHealthRegenPct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT);
|
||||
for (AuraEffectList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i)
|
||||
{
|
||||
AddPct(addvalue, (*i)->GetAmount());
|
||||
}
|
||||
addvalue *= GetTotalAuraMultiplier(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT);
|
||||
|
||||
if (!IsInCombat())
|
||||
{
|
||||
|
|
@ -2666,14 +2659,14 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
|||
|
||||
// set armor (resistance 0) to original value (create_agility*2)
|
||||
SetArmor(int32(m_createStats[STAT_AGILITY] * 2));
|
||||
SetResistanceBuffMods(SpellSchools(0), true, 0.0f);
|
||||
SetResistanceBuffMods(SpellSchools(0), false, 0.0f);
|
||||
SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + AsUnderlyingType(SPELL_SCHOOL_NORMAL), 0.0f);
|
||||
SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + AsUnderlyingType(SPELL_SCHOOL_NORMAL), 0.0f);
|
||||
// set other resistance to original value (0)
|
||||
for (uint8 i = 1; i < MAX_SPELL_SCHOOL; ++i)
|
||||
{
|
||||
SetResistance(SpellSchools(i), 0);
|
||||
SetResistanceBuffMods(SpellSchools(i), true, 0.0f);
|
||||
SetResistanceBuffMods(SpellSchools(i), false, 0.0f);
|
||||
SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + i, 0.0f);
|
||||
SetFloatValue(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + i, 0.0f);
|
||||
}
|
||||
|
||||
SetUInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, 0);
|
||||
|
|
@ -5012,24 +5005,107 @@ void Player::ClearChannelWatch()
|
|||
(*itr)->RemoveWatching(this);
|
||||
}
|
||||
|
||||
void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply)
|
||||
void Player::HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply)
|
||||
{
|
||||
if (modGroup >= BASEMOD_END)
|
||||
{
|
||||
LOG_ERROR("entities.player", "ERROR in HandleBaseModValue(): non existed BaseModGroup!");
|
||||
LOG_ERROR("entities.player", "Player::HandleBaseModFlatValue: Invalid BaseModGroup/BaseModType ({}/{}) for player '{}' ({})",
|
||||
modGroup, FLAT_MOD, GetName(), GetGUID().ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (modType)
|
||||
m_auraBaseFlatMod[modGroup] += apply ? amount : -amount;
|
||||
UpdateBaseModGroup(modGroup);
|
||||
}
|
||||
|
||||
void Player::ApplyBaseModPctValue(BaseModGroup modGroup, float pct)
|
||||
{
|
||||
if (modGroup >= BASEMOD_END)
|
||||
{
|
||||
case FLAT_MOD:
|
||||
m_auraBaseMod[modGroup][modType] += apply ? amount : -amount;
|
||||
LOG_ERROR("entities.player", "Player::ApplyBaseModPctValue: Invalid BaseModGroup/BaseModType ({}/{}) for player '{}' ({})",
|
||||
modGroup, PCT_MOD, GetName(), GetGUID().ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
m_auraBasePctMod[modGroup] += CalculatePct(1.0f, pct);
|
||||
UpdateBaseModGroup(modGroup);
|
||||
}
|
||||
|
||||
void Player::SetBaseModFlatValue(BaseModGroup modGroup, float val)
|
||||
{
|
||||
if (m_auraBaseFlatMod[modGroup] == val)
|
||||
return;
|
||||
|
||||
m_auraBaseFlatMod[modGroup] = val;
|
||||
UpdateBaseModGroup(modGroup);
|
||||
}
|
||||
|
||||
void Player::SetBaseModPctValue(BaseModGroup modGroup, float val)
|
||||
{
|
||||
if (m_auraBasePctMod[modGroup] == val)
|
||||
return;
|
||||
|
||||
m_auraBasePctMod[modGroup] = val;
|
||||
UpdateBaseModGroup(modGroup);
|
||||
}
|
||||
|
||||
void Player::UpdateDamageDoneMods(WeaponAttackType attackType, int32 skipEnchantSlot /*= -1*/)
|
||||
{
|
||||
Unit::UpdateDamageDoneMods(attackType, skipEnchantSlot);
|
||||
|
||||
UnitMods unitMod;
|
||||
switch (attackType)
|
||||
{
|
||||
case BASE_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_MAINHAND;
|
||||
break;
|
||||
case PCT_MOD:
|
||||
ApplyPercentModFloatVar(m_auraBaseMod[modGroup][modType], amount, apply);
|
||||
case OFF_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_OFFHAND;
|
||||
break;
|
||||
case RANGED_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_RANGED;
|
||||
break;
|
||||
default:
|
||||
ABORT();
|
||||
break;
|
||||
}
|
||||
|
||||
float amount = 0.0f;
|
||||
Item* item = GetWeaponForAttack(attackType, true);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
for (uint8 slot = 0; slot < MAX_ENCHANTMENT_SLOT; ++slot)
|
||||
{
|
||||
if (skipEnchantSlot == slot)
|
||||
continue;
|
||||
|
||||
SpellItemEnchantmentEntry const* enchantmentEntry = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(EnchantmentSlot(slot)));
|
||||
if (!enchantmentEntry)
|
||||
continue;
|
||||
|
||||
for (uint8 i = 0; i < MAX_SPELL_ITEM_ENCHANTMENT_EFFECTS; ++i)
|
||||
{
|
||||
switch (enchantmentEntry->type[i])
|
||||
{
|
||||
case ITEM_ENCHANTMENT_TYPE_DAMAGE:
|
||||
amount += enchantmentEntry->amount[i];
|
||||
break;
|
||||
case ITEM_ENCHANTMENT_TYPE_TOTEM:
|
||||
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_ABILITY))
|
||||
amount += enchantmentEntry->amount[i] * item->GetTemplate()->Delay / 1000.0f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HandleStatFlatModifier(unitMod, TOTAL_VALUE, amount, true);
|
||||
}
|
||||
|
||||
void Player::UpdateBaseModGroup(BaseModGroup modGroup)
|
||||
{
|
||||
if (!CanModifyStats())
|
||||
return;
|
||||
|
||||
|
|
@ -5060,10 +5136,7 @@ float Player::GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
if (modType == PCT_MOD && m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f)
|
||||
return 0.0f;
|
||||
|
||||
return m_auraBaseMod[modGroup][modType];
|
||||
return (modType == FLAT_MOD ? m_auraBaseFlatMod[modGroup] : m_auraBasePctMod[modGroup]);
|
||||
}
|
||||
|
||||
float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
|
||||
|
|
@ -5074,15 +5147,15 @@ float Player::GetTotalBaseModValue(BaseModGroup modGroup) const
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
if (m_auraBaseMod[modGroup][PCT_MOD] <= 0.0f)
|
||||
if (m_auraBasePctMod[modGroup] <= 0.0f)
|
||||
return 0.0f;
|
||||
|
||||
return m_auraBaseMod[modGroup][FLAT_MOD] * m_auraBaseMod[modGroup][PCT_MOD];
|
||||
return m_auraBaseFlatMod[modGroup] * m_auraBasePctMod[modGroup];
|
||||
}
|
||||
|
||||
uint32 Player::GetShieldBlockValue() const
|
||||
{
|
||||
float value = (m_auraBaseMod[SHIELD_BLOCK_VALUE][FLAT_MOD] + GetStat(STAT_STRENGTH) * 0.5f - 10) * m_auraBaseMod[SHIELD_BLOCK_VALUE][PCT_MOD];
|
||||
float value = (m_auraBaseFlatMod[SHIELD_BLOCK_VALUE] + GetStat(STAT_STRENGTH) * 0.5f - 10) * m_auraBasePctMod[SHIELD_BLOCK_VALUE];
|
||||
|
||||
value = (value < 0) ? 0 : value;
|
||||
|
||||
|
|
@ -5151,7 +5224,7 @@ void Player::GetDodgeFromAgility(float& diminishing, float& nondiminishing)
|
|||
return;
|
||||
|
||||
/// @todo: research if talents/effects that increase total agility by x% should increase non-diminishing part
|
||||
float base_agility = GetCreateStat(STAT_AGILITY) * m_auraModifiersGroup[UNIT_MOD_STAT_START + static_cast<uint16>(STAT_AGILITY)][BASE_PCT];
|
||||
float base_agility = GetCreateStat(STAT_AGILITY) * GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + AsUnderlyingType(STAT_AGILITY)), BASE_PCT);
|
||||
float bonus_agility = GetStat(STAT_AGILITY) - base_agility;
|
||||
|
||||
// calculate diminishing (green in char screen) and non-diminishing (white) contribution
|
||||
|
|
@ -6574,20 +6647,22 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
|
|||
|
||||
LOG_DEBUG("entities.player", "applying mods for item {} ", item->GetGUID().ToString());
|
||||
|
||||
WeaponAttackType attacktype = Player::GetAttackBySlot(slot);
|
||||
|
||||
if (item->HasSocket()) //only (un)equipping of items with sockets can influence metagems, so no need to waste time with normal items
|
||||
CorrectMetaGemEnchants(slot, apply);
|
||||
|
||||
if (attacktype < MAX_ATTACK)
|
||||
_ApplyWeaponDependentAuraMods(item, attacktype, apply);
|
||||
|
||||
_ApplyItemBonuses(proto, slot, apply);
|
||||
|
||||
if (slot == EQUIPMENT_SLOT_RANGED)
|
||||
_ApplyAmmoBonuses();
|
||||
|
||||
ApplyItemEquipSpell(item, apply);
|
||||
|
||||
ApplyItemDependentAuras(item, apply);
|
||||
|
||||
WeaponAttackType const attackType = Player::GetAttackBySlot(slot);
|
||||
if (attackType != MAX_ATTACK)
|
||||
UpdateWeaponDependentAuras(attackType);
|
||||
|
||||
ApplyEnchantment(item, apply);
|
||||
|
||||
LOG_DEBUG("entities.player.items", "_ApplyItemMods complete.");
|
||||
|
|
@ -6658,30 +6733,30 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
|||
switch (statType)
|
||||
{
|
||||
case ITEM_MOD_MANA:
|
||||
HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_HEALTH: // modify HP
|
||||
HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_AGILITY: // modify agility
|
||||
HandleStatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
|
||||
ApplyStatBuffMod(STAT_AGILITY, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, BASE_VALUE, float(val), apply);
|
||||
UpdateStatBuffMod(STAT_AGILITY);
|
||||
break;
|
||||
case ITEM_MOD_STRENGTH: //modify strength
|
||||
HandleStatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
|
||||
ApplyStatBuffMod(STAT_STRENGTH, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, BASE_VALUE, float(val), apply);
|
||||
UpdateStatBuffMod(STAT_STRENGTH);
|
||||
break;
|
||||
case ITEM_MOD_INTELLECT: //modify intellect
|
||||
HandleStatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
|
||||
ApplyStatBuffMod(STAT_INTELLECT, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, BASE_VALUE, float(val), apply);
|
||||
UpdateStatBuffMod(STAT_INTELLECT);
|
||||
break;
|
||||
case ITEM_MOD_SPIRIT: //modify spirit
|
||||
HandleStatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply);
|
||||
ApplyStatBuffMod(STAT_SPIRIT, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_SPIRIT, BASE_VALUE, float(val), apply);
|
||||
UpdateStatBuffMod(STAT_SPIRIT);
|
||||
break;
|
||||
case ITEM_MOD_STAMINA: //modify stamina
|
||||
HandleStatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
|
||||
ApplyStatBuffMod(STAT_STAMINA, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, BASE_VALUE, float(val), apply);
|
||||
UpdateStatBuffMod(STAT_STAMINA);
|
||||
break;
|
||||
case ITEM_MOD_DEFENSE_SKILL_RATING:
|
||||
ApplyRatingMod(CR_DEFENSE_SKILL, int32(val), apply);
|
||||
|
|
@ -6770,11 +6845,11 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
|||
ApplyRatingMod(CR_EXPERTISE, int32(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_ATTACK_POWER:
|
||||
HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
|
||||
HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
|
||||
break;
|
||||
case ITEM_MOD_RANGED_ATTACK_POWER:
|
||||
HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply);
|
||||
break;
|
||||
// case ITEM_MOD_FERAL_ATTACK_POWER:
|
||||
// ApplyFeralAPBonus(int32(val), apply);
|
||||
|
|
@ -6795,7 +6870,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
|||
ApplySpellPenetrationBonus(val, apply);
|
||||
break;
|
||||
case ITEM_MOD_BLOCK_VALUE:
|
||||
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(val), apply);
|
||||
HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(val), apply);
|
||||
break;
|
||||
/// @deprecated item mods
|
||||
case ITEM_MOD_SPELL_HEALING_DONE:
|
||||
|
|
@ -6825,7 +6900,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
|||
|
||||
if (armor)
|
||||
{
|
||||
UnitModifierType modType = TOTAL_VALUE;
|
||||
UnitModifierFlatType modType = TOTAL_VALUE;
|
||||
if (proto->Class == ITEM_CLASS_ARMOR)
|
||||
{
|
||||
switch (proto->SubClass)
|
||||
|
|
@ -6839,33 +6914,33 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
|||
break;
|
||||
}
|
||||
}
|
||||
HandleStatModifier(UNIT_MOD_ARMOR, modType, float(armor), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ARMOR, modType, float(armor), apply);
|
||||
}
|
||||
|
||||
// Add armor bonus from ArmorDamageModifier if > 0
|
||||
if (proto->ArmorDamageModifier > 0 && sScriptMgr->OnPlayerCanArmorDamageModifier(this))
|
||||
HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(proto->ArmorDamageModifier), apply);
|
||||
|
||||
if (proto->Block)
|
||||
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply);
|
||||
HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(proto->Block), apply);
|
||||
|
||||
if (proto->HolyRes)
|
||||
HandleStatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(proto->HolyRes), apply);
|
||||
|
||||
if (proto->FireRes)
|
||||
HandleStatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(proto->FireRes), apply);
|
||||
|
||||
if (proto->NatureRes)
|
||||
HandleStatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_RESISTANCE_NATURE, BASE_VALUE, float(proto->NatureRes), apply);
|
||||
|
||||
if (proto->FrostRes)
|
||||
HandleStatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_RESISTANCE_FROST, BASE_VALUE, float(proto->FrostRes), apply);
|
||||
|
||||
if (proto->ShadowRes)
|
||||
HandleStatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_RESISTANCE_SHADOW, BASE_VALUE, float(proto->ShadowRes), apply);
|
||||
|
||||
if (proto->ArcaneRes)
|
||||
HandleStatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_RESISTANCE_ARCANE, BASE_VALUE, float(proto->ArcaneRes), apply);
|
||||
|
||||
WeaponAttackType attType = Player::GetAttackBySlot(slot);
|
||||
if (attType != MAX_ATTACK)
|
||||
|
|
@ -7036,6 +7111,84 @@ void Player::UpdateItemObtainSpells(Item* item, uint8 bag, uint8 slot)
|
|||
ApplyItemObtainSpells(item, true);
|
||||
}
|
||||
|
||||
// this one rechecks weapon auras and stores them in BaseModGroup container
|
||||
// needed for things like axe specialization applying only to axe weapons in case of dual-wield
|
||||
void Player::UpdateWeaponDependentCritAuras(WeaponAttackType attackType)
|
||||
{
|
||||
BaseModGroup modGroup;
|
||||
switch (attackType)
|
||||
{
|
||||
case BASE_ATTACK:
|
||||
modGroup = CRIT_PERCENTAGE;
|
||||
break;
|
||||
case OFF_ATTACK:
|
||||
modGroup = OFFHAND_CRIT_PERCENTAGE;
|
||||
break;
|
||||
case RANGED_ATTACK:
|
||||
modGroup = RANGED_CRIT_PERCENTAGE;
|
||||
break;
|
||||
default:
|
||||
ABORT();
|
||||
break;
|
||||
}
|
||||
|
||||
float amount = 0.0f;
|
||||
amount += GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT, std::bind(&Unit::CheckAttackFitToAuraRequirement, this, attackType, std::placeholders::_1));
|
||||
|
||||
// these auras don't have item requirement (only Combat Expertise in 3.3.5a)
|
||||
amount += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT);
|
||||
|
||||
SetBaseModFlatValue(modGroup, amount);
|
||||
}
|
||||
|
||||
void Player::UpdateAllWeaponDependentCritAuras()
|
||||
{
|
||||
for (uint8 i = BASE_ATTACK; i < MAX_ATTACK; ++i)
|
||||
UpdateWeaponDependentCritAuras(WeaponAttackType(i));
|
||||
}
|
||||
|
||||
void Player::UpdateWeaponDependentAuras(WeaponAttackType attackType)
|
||||
{
|
||||
UpdateWeaponDependentCritAuras(attackType);
|
||||
UpdateDamageDoneMods(attackType);
|
||||
UpdateDamagePctDoneMods(attackType);
|
||||
}
|
||||
|
||||
void Player::ApplyItemDependentAuras(Item* item, bool apply)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
PlayerSpellMap const& spells = GetSpellMap();
|
||||
for (auto itr = spells.begin(); itr != spells.end(); ++itr)
|
||||
{
|
||||
if (itr->second->State == PLAYERSPELL_REMOVED)
|
||||
continue;
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
|
||||
if (!spellInfo || !spellInfo->IsPassive() || spellInfo->EquippedItemClass < 0)
|
||||
continue;
|
||||
|
||||
if (!HasAura(itr->first) && HasItemFitToSpellRequirements(spellInfo))
|
||||
AddAura(itr->first, this); // no SMSG_SPELL_GO in sniff found
|
||||
}
|
||||
}
|
||||
else
|
||||
RemoveItemDependentAurasAndCasts(item);
|
||||
}
|
||||
|
||||
bool Player::CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const
|
||||
{
|
||||
SpellInfo const* spellInfo = aurEff->GetSpellInfo();
|
||||
if (spellInfo->EquippedItemClass == -1)
|
||||
return true;
|
||||
|
||||
Item* item = GetWeaponForAttack(attackType, true);
|
||||
if (!item || !item->IsFitToSpellRequirements(spellInfo))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SpellSchoolMask Player::GetMeleeDamageSchoolMask(WeaponAttackType attackType /*= BASE_ATTACK*/, uint8 damageIndex /*= 0*/) const
|
||||
{
|
||||
if (Item const* weapon = GetWeaponForAttack(attackType, true))
|
||||
|
|
@ -7046,110 +7199,6 @@ SpellSchoolMask Player::GetMeleeDamageSchoolMask(WeaponAttackType attackType /*=
|
|||
return SPELL_SCHOOL_MASK_NORMAL;
|
||||
}
|
||||
|
||||
void Player::_ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply)
|
||||
{
|
||||
AuraEffectList const& auraCritList = GetAuraEffectsByType(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT);
|
||||
for (AuraEffectList::const_iterator itr = auraCritList.begin(); itr != auraCritList.end(); ++itr)
|
||||
_ApplyWeaponDependentAuraCritMod(item, attackType, *itr, apply);
|
||||
|
||||
AuraEffectList const& auraDamageFlatList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
|
||||
for (AuraEffectList::const_iterator itr = auraDamageFlatList.begin(); itr != auraDamageFlatList.end(); ++itr)
|
||||
_ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply);
|
||||
|
||||
AuraEffectList const& auraDamagePctList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
|
||||
for (AuraEffectList::const_iterator itr = auraDamagePctList.begin(); itr != auraDamagePctList.end(); ++itr)
|
||||
_ApplyWeaponDependentAuraDamageMod(item, attackType, *itr, apply);
|
||||
}
|
||||
|
||||
void Player::_ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
|
||||
{
|
||||
// don't apply mod if item is broken or cannot be used
|
||||
if (item->IsBroken() || !CanUseAttackType(attackType))
|
||||
return;
|
||||
|
||||
// generic not weapon specific case processes in aura code
|
||||
if (aura->GetSpellInfo()->EquippedItemClass == -1)
|
||||
return;
|
||||
|
||||
if (!sScriptMgr->OnPlayerCanApplyWeaponDependentAuraDamageMod(this, item, attackType, aura, apply))
|
||||
return;
|
||||
|
||||
BaseModGroup mod = BASEMOD_END;
|
||||
switch (attackType)
|
||||
{
|
||||
case BASE_ATTACK:
|
||||
mod = CRIT_PERCENTAGE;
|
||||
break;
|
||||
case OFF_ATTACK:
|
||||
mod = OFFHAND_CRIT_PERCENTAGE;
|
||||
break;
|
||||
case RANGED_ATTACK:
|
||||
mod = RANGED_CRIT_PERCENTAGE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
|
||||
HandleBaseModValue(mod, FLAT_MOD, float (aura->GetAmount()), apply);
|
||||
}
|
||||
|
||||
void Player::_ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply)
|
||||
{
|
||||
// don't apply mod if item is broken or cannot be used
|
||||
if (item->IsBroken() || !CanUseAttackType(attackType))
|
||||
return;
|
||||
|
||||
// ignore spell mods for not wands
|
||||
if ((aura->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) == 0 && (getClassMask() & CLASSMASK_WAND_USERS) == 0)
|
||||
return;
|
||||
|
||||
// generic not weapon specific case processes in aura code
|
||||
if (aura->GetSpellInfo()->EquippedItemClass == -1)
|
||||
return;
|
||||
|
||||
UnitMods unitMod = UNIT_MOD_END;
|
||||
switch (attackType)
|
||||
{
|
||||
case BASE_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_MAINHAND;
|
||||
break;
|
||||
case OFF_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_OFFHAND;
|
||||
break;
|
||||
case RANGED_ATTACK:
|
||||
unitMod = UNIT_MOD_DAMAGE_RANGED;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
UnitModifierType unitModType = TOTAL_VALUE;
|
||||
switch (aura->GetAuraType())
|
||||
{
|
||||
case SPELL_AURA_MOD_DAMAGE_DONE:
|
||||
unitModType = TOTAL_VALUE;
|
||||
break;
|
||||
case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE:
|
||||
unitModType = TOTAL_PCT;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->IsFitToSpellRequirements(aura->GetSpellInfo()))
|
||||
{
|
||||
HandleStatModifier(unitMod, unitModType, float(aura->GetAmount()), apply);
|
||||
if (unitModType == TOTAL_VALUE)
|
||||
{
|
||||
if (aura->GetAmount() > 0)
|
||||
ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, aura->GetAmount(), apply);
|
||||
else
|
||||
ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, aura->GetAmount(), apply);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Player::ApplyItemEquipSpell(Item* item, bool apply, bool form_change)
|
||||
{
|
||||
if (!item)
|
||||
|
|
@ -7464,12 +7513,6 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!spellInfo->CheckElixirStacking(this))
|
||||
{
|
||||
Spell::SendCastResult(this, spellInfo, cast_count, SPELL_FAILED_AURA_BOUNCED);
|
||||
continue;
|
||||
}
|
||||
|
||||
Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE);
|
||||
spell->m_CastItem = item;
|
||||
spell->m_cast_count = cast_count; // set count of casts
|
||||
|
|
@ -7578,10 +7621,7 @@ void Player::_RemoveAllItemMods()
|
|||
if (!proto)
|
||||
continue;
|
||||
|
||||
WeaponAttackType attacktype = Player::GetAttackBySlot(i);
|
||||
if (attacktype < MAX_ATTACK)
|
||||
_ApplyWeaponDependentAuraMods(m_items[i], attacktype, false);
|
||||
|
||||
ApplyItemDependentAuras(m_items[i], false);
|
||||
_ApplyItemBonuses(proto, i, false);
|
||||
|
||||
if (i == EQUIPMENT_SLOT_RANGED)
|
||||
|
|
@ -7607,12 +7647,13 @@ void Player::_ApplyAllItemMods()
|
|||
if (!proto)
|
||||
continue;
|
||||
|
||||
WeaponAttackType attacktype = Player::GetAttackBySlot(i);
|
||||
if (attacktype < MAX_ATTACK)
|
||||
_ApplyWeaponDependentAuraMods(m_items[i], attacktype, true);
|
||||
|
||||
ApplyItemDependentAuras(m_items[i], false);
|
||||
_ApplyItemBonuses(proto, i, true);
|
||||
|
||||
WeaponAttackType const attackType = Player::GetAttackBySlot(i);
|
||||
if (attackType != MAX_ATTACK)
|
||||
UpdateWeaponDependentAuras(attackType);
|
||||
|
||||
if (i == EQUIPMENT_SLOT_RANGED)
|
||||
_ApplyAmmoBonuses();
|
||||
}
|
||||
|
|
@ -12583,9 +12624,9 @@ void Player::RemoveItemDependentAurasAndCasts(Item* pItem)
|
|||
{
|
||||
Aura* aura = itr->second;
|
||||
|
||||
// skip passive (passive item dependent spells work in another way) and not self applied auras
|
||||
// skip not self applied auras
|
||||
SpellInfo const* spellInfo = aura->GetSpellInfo();
|
||||
if (aura->IsPassive() || aura->GetCasterGUID() != GetGUID())
|
||||
if (aura->GetCasterGUID() != GetGUID())
|
||||
{
|
||||
++itr;
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -1334,7 +1334,7 @@ public:
|
|||
{
|
||||
return StoreItem(dest, pItem, update);
|
||||
}
|
||||
void RemoveItem(uint8 bag, uint8 slot, bool update, bool swap = false);
|
||||
void RemoveItem(uint8 bag, uint8 slot, bool update);
|
||||
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update);
|
||||
// in trade, auction, guild bank, mail....
|
||||
void MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool update, bool in_characterInventoryDB = false);
|
||||
|
|
@ -2187,11 +2187,19 @@ public:
|
|||
[[nodiscard]] bool CanTameExoticPets() const { return IsGameMaster() || HasAuraType(SPELL_AURA_ALLOW_TAME_PET_TYPE); }
|
||||
|
||||
void SetRegularAttackTime();
|
||||
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; }
|
||||
void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply);
|
||||
|
||||
void HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply);
|
||||
void ApplyBaseModPctValue(BaseModGroup modGroup, float pct);
|
||||
|
||||
void SetBaseModFlatValue(BaseModGroup modGroup, float val);
|
||||
void SetBaseModPctValue(BaseModGroup modGroup, float val);
|
||||
|
||||
void UpdateDamageDoneMods(WeaponAttackType attackType, int32 skipEnchantSlot = -1) override;
|
||||
void UpdateBaseModGroup(BaseModGroup modGroup);
|
||||
|
||||
[[nodiscard]] float GetBaseModValue(BaseModGroup modGroup, BaseModType modType) const;
|
||||
[[nodiscard]] float GetTotalBaseModValue(BaseModGroup modGroup) const;
|
||||
[[nodiscard]] float GetTotalPercentageModValue(BaseModGroup modGroup) const { return m_auraBaseMod[modGroup][FLAT_MOD] + m_auraBaseMod[modGroup][PCT_MOD]; }
|
||||
|
||||
void _ApplyAllStatBonuses();
|
||||
void _RemoveAllStatBonuses();
|
||||
|
||||
|
|
@ -2203,9 +2211,13 @@ public:
|
|||
|
||||
SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType attackType = BASE_ATTACK, uint8 damageIndex = 0) const override;
|
||||
|
||||
void _ApplyWeaponDependentAuraMods(Item* item, WeaponAttackType attackType, bool apply);
|
||||
void _ApplyWeaponDependentAuraCritMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
|
||||
void _ApplyWeaponDependentAuraDamageMod(Item* item, WeaponAttackType attackType, AuraEffect const* aura, bool apply);
|
||||
void UpdateWeaponDependentAuras(WeaponAttackType attackType);
|
||||
void ApplyItemDependentAuras(Item* item, bool apply);
|
||||
|
||||
bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect const* aurEff) const override;
|
||||
|
||||
void UpdateWeaponDependentCritAuras(WeaponAttackType attackType);
|
||||
void UpdateAllWeaponDependentCritAuras();
|
||||
|
||||
void _ApplyItemMods(Item* item, uint8 slot, bool apply);
|
||||
void _RemoveAllItemMods();
|
||||
|
|
@ -2829,7 +2841,8 @@ protected:
|
|||
|
||||
ActionButtonList m_actionButtons;
|
||||
|
||||
float m_auraBaseMod[BASEMOD_END][MOD_END];
|
||||
float m_auraBaseFlatMod[BASEMOD_END];
|
||||
float m_auraBasePctMod[BASEMOD_END];
|
||||
int32 m_baseRatingValue[MAX_COMBAT_RATING];
|
||||
uint32 m_baseSpellPower;
|
||||
uint32 m_baseSpellDamage;
|
||||
|
|
|
|||
|
|
@ -1405,9 +1405,7 @@ uint32 Player::CalculateQuestRewardXP(Quest const* quest)
|
|||
uint32 xp = uint32(quest->XPValue(GetLevel()) * GetQuestRate(quest->IsDFQuest()));
|
||||
|
||||
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
|
||||
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
|
||||
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
|
||||
AddPct(xp, (*i)->GetAmount());
|
||||
xp *= GetTotalAuraMultiplier(SPELL_AURA_MOD_XP_QUEST_PCT);
|
||||
|
||||
return xp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
#include "StringConvert.h"
|
||||
#include "Tokenize.h"
|
||||
#include "Transport.h"
|
||||
#include "Unit.h"
|
||||
#include "UpdateFieldFlags.h"
|
||||
#include "Util.h"
|
||||
#include "World.h"
|
||||
|
|
@ -2896,7 +2897,7 @@ void Player::VisualizeItem(uint8 slot, Item* pItem)
|
|||
pItem->SetState(ITEM_CHANGED, this);
|
||||
}
|
||||
|
||||
void Player::RemoveItem(uint8 bag, uint8 slot, bool update, bool swap)
|
||||
void Player::RemoveItem(uint8 bag, uint8 slot, bool update)
|
||||
{
|
||||
// note: removeitem does not actually change the item
|
||||
// it only takes the item out of storage temporarily
|
||||
|
|
@ -2931,12 +2932,6 @@ void Player::RemoveItem(uint8 bag, uint8 slot, bool update, bool swap)
|
|||
// remove item dependent auras and casts (only weapon and armor slots)
|
||||
if (slot < INVENTORY_SLOT_BAG_END && slot < EQUIPMENT_SLOT_END)
|
||||
{
|
||||
// Xinef: Ensure that this function is called for places with swap=true
|
||||
if (!swap)
|
||||
{
|
||||
RemoveItemDependentAurasAndCasts(pItem);
|
||||
}
|
||||
|
||||
// remove held enchantments, update expertise
|
||||
if (slot == EQUIPMENT_SLOT_MAINHAND)
|
||||
{
|
||||
|
|
@ -3071,9 +3066,6 @@ void Player::DestroyItem(uint8 bag, uint8 slot, bool update)
|
|||
|
||||
if (slot < EQUIPMENT_SLOT_END)
|
||||
{
|
||||
// remove item dependent auras and casts (only weapon and armor slots)
|
||||
RemoveItemDependentAurasAndCasts(pItem);
|
||||
|
||||
// update expertise and armor penetration - passive auras may need it
|
||||
switch (slot)
|
||||
{
|
||||
|
|
@ -3865,8 +3857,8 @@ void Player::SwapItem(uint16 src, uint16 dst)
|
|||
}
|
||||
|
||||
// now do moves, remove...
|
||||
RemoveItem(dstbag, dstslot, false, true);
|
||||
RemoveItem(srcbag, srcslot, false, true);
|
||||
RemoveItem(dstbag, dstslot, false);
|
||||
RemoveItem(srcbag, srcslot, false);
|
||||
|
||||
// add to dest
|
||||
if (IsInventoryPos(dst))
|
||||
|
|
@ -4355,13 +4347,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||
// processed in Player::CastItemCombatSpell
|
||||
break;
|
||||
case ITEM_ENCHANTMENT_TYPE_DAMAGE:
|
||||
if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
|
||||
HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
|
||||
HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
else if (item->GetSlot() == EQUIPMENT_SLOT_RANGED)
|
||||
HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
{
|
||||
WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot());
|
||||
if (attackType != MAX_ATTACK)
|
||||
UpdateDamageDoneMods(attackType, apply ? -1 : slot);
|
||||
break;
|
||||
}
|
||||
case ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL:
|
||||
if (enchant_spell_id)
|
||||
{
|
||||
|
|
@ -4412,7 +4403,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||
}
|
||||
}
|
||||
|
||||
HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply);
|
||||
HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + enchant_spell_id), TOTAL_VALUE, float(enchant_amount), apply);
|
||||
break;
|
||||
case ITEM_ENCHANTMENT_TYPE_STAT:
|
||||
{
|
||||
|
|
@ -4439,36 +4430,36 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||
{
|
||||
case ITEM_MOD_MANA:
|
||||
LOG_DEBUG("entities.player.items", "+ {} MANA", enchant_amount);
|
||||
HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_MANA, BASE_VALUE, float(enchant_amount), apply);
|
||||
break;
|
||||
case ITEM_MOD_HEALTH:
|
||||
LOG_DEBUG("entities.player.items", "+ {} HEALTH", enchant_amount);
|
||||
HandleStatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, float(enchant_amount), apply);
|
||||
break;
|
||||
case ITEM_MOD_AGILITY:
|
||||
LOG_DEBUG("entities.player.items", "+ {} AGILITY", enchant_amount);
|
||||
HandleStatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
ApplyStatBuffMod(STAT_AGILITY, (float)enchant_amount, apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_AGILITY, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
UpdateStatBuffMod(STAT_AGILITY);
|
||||
break;
|
||||
case ITEM_MOD_STRENGTH:
|
||||
LOG_DEBUG("entities.player.items", "+ {} STRENGTH", enchant_amount);
|
||||
HandleStatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
ApplyStatBuffMod(STAT_STRENGTH, (float)enchant_amount, apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_STRENGTH, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
UpdateStatBuffMod(STAT_STRENGTH);
|
||||
break;
|
||||
case ITEM_MOD_INTELLECT:
|
||||
LOG_DEBUG("entities.player.items", "+ {} INTELLECT", enchant_amount);
|
||||
HandleStatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
ApplyStatBuffMod(STAT_INTELLECT, (float)enchant_amount, apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_INTELLECT, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
UpdateStatBuffMod(STAT_INTELLECT);
|
||||
break;
|
||||
case ITEM_MOD_SPIRIT:
|
||||
LOG_DEBUG("entities.player.items", "+ {} SPIRIT", enchant_amount);
|
||||
HandleStatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
ApplyStatBuffMod(STAT_SPIRIT, (float)enchant_amount, apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_SPIRIT, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
UpdateStatBuffMod(STAT_SPIRIT);
|
||||
break;
|
||||
case ITEM_MOD_STAMINA:
|
||||
LOG_DEBUG("entities.player.items", "+ {} STAMINA", enchant_amount);
|
||||
HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
ApplyStatBuffMod(STAT_STAMINA, (float)enchant_amount, apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
UpdateStatBuffMod(STAT_STAMINA);
|
||||
break;
|
||||
case ITEM_MOD_DEFENSE_SKILL_RATING:
|
||||
ApplyRatingMod(CR_DEFENSE_SKILL, enchant_amount, apply);
|
||||
|
|
@ -4579,12 +4570,12 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||
LOG_DEBUG("entities.player.items", "+ {} EXPERTISE", enchant_amount);
|
||||
break;
|
||||
case ITEM_MOD_ATTACK_POWER:
|
||||
HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
LOG_DEBUG("entities.player.items", "+ {} ATTACK_POWER", enchant_amount);
|
||||
break;
|
||||
case ITEM_MOD_RANGED_ATTACK_POWER:
|
||||
HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply);
|
||||
LOG_DEBUG("entities.player.items", "+ {} RANGED_ATTACK_POWER", enchant_amount);
|
||||
break;
|
||||
// case ITEM_MOD_FERAL_ATTACK_POWER:
|
||||
|
|
@ -4612,7 +4603,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||
LOG_DEBUG("entities.player.items", "+ {} SPELL_PENETRATION", enchant_amount);
|
||||
break;
|
||||
case ITEM_MOD_BLOCK_VALUE:
|
||||
HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(enchant_amount), apply);
|
||||
HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(enchant_amount), apply);
|
||||
LOG_DEBUG("entities.player.items", "+ {} BLOCK_VALUE", enchant_amount);
|
||||
break;
|
||||
/// @deprecated item mods
|
||||
|
|
@ -4631,20 +4622,9 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||
}
|
||||
case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon
|
||||
{
|
||||
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_ABILITY))
|
||||
{
|
||||
float addValue = 0.0f;
|
||||
if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
|
||||
{
|
||||
addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f);
|
||||
HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, addValue, apply);
|
||||
}
|
||||
else if (item->GetSlot() == EQUIPMENT_SLOT_OFFHAND)
|
||||
{
|
||||
addValue = float(enchant_amount * item->GetTemplate()->Delay / 1000.0f);
|
||||
HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, addValue, apply);
|
||||
}
|
||||
}
|
||||
WeaponAttackType const attackType = Player::GetAttackBySlot(item->GetSlot());
|
||||
if (attackType != MAX_ATTACK)
|
||||
UpdateDamageDoneMods(attackType);
|
||||
break;
|
||||
}
|
||||
case ITEM_ENCHANTMENT_TYPE_USE_SPELL:
|
||||
|
|
|
|||
|
|
@ -701,7 +701,7 @@ void Player::UpdateRating(CombatRating cr)
|
|||
|
||||
void Player::UpdateAllRatings()
|
||||
{
|
||||
for (int cr = 0; cr < MAX_COMBAT_RATING; ++cr)
|
||||
for (uint cr = 0; cr < MAX_COMBAT_RATING; ++cr)
|
||||
UpdateRating(CombatRating(cr));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ void Player::UpdateSpellDamageAndHealingBonus()
|
|||
|
||||
bool Player::UpdateAllStats()
|
||||
{
|
||||
for (int8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
|
||||
for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i)
|
||||
{
|
||||
float value = GetTotalStatValue(Stats(i));
|
||||
SetStat(Stats(i), int32(value));
|
||||
|
|
@ -247,9 +247,9 @@ void Player::UpdateResistances(uint32 school)
|
|||
float value = 0.0f;
|
||||
UnitMods unitMod = UnitMods(UNIT_MOD_RESISTANCE_START + school);
|
||||
|
||||
value = GetModifierValue(unitMod, BASE_VALUE);
|
||||
value *= GetModifierValue(unitMod, BASE_PCT);
|
||||
value += GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
value = GetFlatModifierValue(unitMod, BASE_VALUE);
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
|
||||
AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT);
|
||||
for(AuraEffectList::const_iterator i = mResbyIntellect.begin(); i != mResbyIntellect.end(); ++i)
|
||||
|
|
@ -258,7 +258,7 @@ void Player::UpdateResistances(uint32 school)
|
|||
value += int32(GetStat(Stats((*i)->GetMiscValueB())) * (*i)->GetAmount() / 100.0f);
|
||||
}
|
||||
|
||||
value *= GetModifierValue(unitMod, TOTAL_PCT);
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
SetResistance(SpellSchools(school), int32(value));
|
||||
}
|
||||
|
|
@ -270,10 +270,10 @@ void Player::UpdateArmor()
|
|||
{
|
||||
UnitMods unitMod = UNIT_MOD_ARMOR;
|
||||
|
||||
float value = GetModifierValue(unitMod, BASE_VALUE); // base armor (from items)
|
||||
value *= GetModifierValue(unitMod, BASE_PCT); // armor percent from items
|
||||
float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor (from items)
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent from items
|
||||
value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
|
||||
value += GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
|
||||
//add dynamic flat mods
|
||||
AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT);
|
||||
|
|
@ -283,7 +283,7 @@ void Player::UpdateArmor()
|
|||
value += CalculatePct(GetStat(Stats((*i)->GetMiscValueB())), (*i)->GetAmount());
|
||||
}
|
||||
|
||||
value *= GetModifierValue(unitMod, TOTAL_PCT);
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
SetArmor(int32(value));
|
||||
|
||||
|
|
@ -314,10 +314,10 @@ void Player::UpdateMaxHealth()
|
|||
{
|
||||
UnitMods unitMod = UNIT_MOD_HEALTH;
|
||||
|
||||
float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
|
||||
value *= GetModifierValue(unitMod, BASE_PCT);
|
||||
value += GetModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina();
|
||||
value *= GetModifierValue(unitMod, TOTAL_PCT);
|
||||
float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreateHealth();
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + GetHealthBonusFromStamina();
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
sScriptMgr->OnPlayerAfterUpdateMaxHealth(this, value);
|
||||
SetMaxHealth((uint32)value);
|
||||
|
|
@ -329,10 +329,10 @@ void Player::UpdateMaxPower(Powers power)
|
|||
|
||||
float bonusPower = (power == POWER_MANA && GetCreatePowers(power) > 0) ? GetManaBonusFromIntellect() : 0;
|
||||
|
||||
float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
|
||||
value *= GetModifierValue(unitMod, BASE_PCT);
|
||||
value += GetModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
|
||||
value *= GetModifierValue(unitMod, TOTAL_PCT);
|
||||
float value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power);
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + bonusPower;
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
sScriptMgr->OnPlayerAfterUpdateMaxPower(this, power, value);
|
||||
SetMaxPower(power, uint32(value));
|
||||
|
|
@ -487,10 +487,10 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
|||
}
|
||||
}
|
||||
|
||||
SetModifierValue(unitMod, BASE_VALUE, val2);
|
||||
SetStatFlatModifier(unitMod, BASE_VALUE, val2);
|
||||
|
||||
float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
|
||||
float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
|
||||
float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
|
||||
//add dynamic flat mods
|
||||
if (ranged)
|
||||
|
|
@ -514,7 +514,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
|||
attPowerMod += int32(GetArmor() / (*iter)->GetAmount());
|
||||
}
|
||||
|
||||
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
|
||||
float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
|
||||
|
||||
sScriptMgr->OnPlayerAfterUpdateAttackPowerAndDamage(this, level, base_attPower, attPowerMod, attPowerMultiplier, ranged);
|
||||
SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field
|
||||
|
|
@ -576,10 +576,10 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
|
|||
|
||||
float attackSpeedMod = GetAPMultiplier(attType, normalized);
|
||||
|
||||
float baseValue = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod;
|
||||
float basePct = GetModifierValue(unitMod, BASE_PCT);
|
||||
float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
|
||||
float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * attackSpeedMod;
|
||||
float basePct = GetPctModifierValue(unitMod, BASE_PCT);
|
||||
float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
|
||||
|
||||
float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
|
||||
float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
|
||||
|
|
@ -681,7 +681,8 @@ void Player::UpdateCritPercentage(WeaponAttackType attType)
|
|||
break;
|
||||
}
|
||||
|
||||
float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr);
|
||||
// flat = bonus from crit auras, pct = bonus from agility, combat rating = mods from items
|
||||
float value = GetBaseModValue(modGroup, FLAT_MOD) + GetBaseModValue(modGroup, PCT_MOD) + GetRatingBonusValue(cr);
|
||||
// Modify crit from weapon skill and maximized defense skill of same level victim difference
|
||||
value += (int32(GetWeaponSkillValue(attType)) - int32(GetMaxSkillValueForLevel())) * 0.04f;
|
||||
|
||||
|
|
@ -698,9 +699,9 @@ void Player::UpdateAllCritPercentages()
|
|||
{
|
||||
float value = GetMeleeCritFromAgility();
|
||||
|
||||
SetBaseModValue(CRIT_PERCENTAGE, PCT_MOD, value);
|
||||
SetBaseModValue(OFFHAND_CRIT_PERCENTAGE, PCT_MOD, value);
|
||||
SetBaseModValue(RANGED_CRIT_PERCENTAGE, PCT_MOD, value);
|
||||
SetBaseModPctValue(CRIT_PERCENTAGE, value);
|
||||
SetBaseModPctValue(OFFHAND_CRIT_PERCENTAGE, value);
|
||||
SetBaseModPctValue(RANGED_CRIT_PERCENTAGE, value);
|
||||
|
||||
UpdateCritPercentage(BASE_ATTACK);
|
||||
UpdateCritPercentage(OFF_ATTACK);
|
||||
|
|
@ -849,7 +850,7 @@ void Player::UpdateSpellCritChance(uint32 school)
|
|||
// Crit from Intellect
|
||||
crit += GetSpellCritFromIntellect();
|
||||
// Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE
|
||||
crit += GetTotalAuraModifierAreaExclusive(SPELL_AURA_MOD_SPELL_CRIT_CHANCE);
|
||||
crit += GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE);
|
||||
// Increase crit from SPELL_AURA_MOD_CRIT_PCT
|
||||
crit += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT);
|
||||
// Increase crit by school from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
|
||||
|
|
@ -900,16 +901,11 @@ void Player::UpdateExpertise(WeaponAttackType attack)
|
|||
|
||||
Item* weapon = GetWeaponForAttack(attack, true);
|
||||
|
||||
AuraEffectList const& expAuras = GetAuraEffectsByType(SPELL_AURA_MOD_EXPERTISE);
|
||||
for (AuraEffectList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr)
|
||||
expertise += GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE, [weapon](AuraEffect const* aurEff)
|
||||
{
|
||||
// item neutral spell
|
||||
if ((*itr)->GetSpellInfo()->EquippedItemClass == -1)
|
||||
expertise += (*itr)->GetAmount();
|
||||
// item dependent spell
|
||||
else if (weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellInfo()))
|
||||
expertise += (*itr)->GetAmount();
|
||||
}
|
||||
return aurEff->GetSpellInfo()->EquippedItemClass == -1 || // item neutral spell
|
||||
(weapon && weapon->IsFitToSpellRequirements(aurEff->GetSpellInfo())); // item dependent spell
|
||||
});
|
||||
|
||||
if (expertise < 0)
|
||||
expertise = 0;
|
||||
|
|
@ -1100,9 +1096,9 @@ void Creature::UpdateAttackPowerAndDamage(bool ranged)
|
|||
indexMulti = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
|
||||
}
|
||||
|
||||
float baseAttackPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
|
||||
float attackPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float attackPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
|
||||
float baseAttackPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
|
||||
float attackPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
float attackPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
|
||||
|
||||
SetInt32Value(index, uint32(baseAttackPower)); // UNIT_FIELD_(RANGED)_ATTACK_POWER
|
||||
SetInt32Value(indexMod, uint32(attackPowerMod)); // UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS
|
||||
|
|
@ -1166,10 +1162,10 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized,
|
|||
|
||||
float attackPower = GetTotalAttackPowerValue(attType);
|
||||
float attackSpeedMulti = GetAPMultiplier(attType, normalized);
|
||||
float baseValue = GetModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f) * variance;
|
||||
float basePct = GetModifierValue(unitMod, BASE_PCT) * attackSpeedMulti;
|
||||
float totalValue = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float totalPct = addTotalPct ? GetModifierValue(unitMod, TOTAL_PCT) : 1.0f;
|
||||
float baseValue = GetFlatModifierValue(unitMod, BASE_VALUE) + (attackPower / 14.0f) * variance;
|
||||
float basePct = GetPctModifierValue(unitMod, BASE_PCT) * attackSpeedMulti;
|
||||
float totalValue = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
float totalPct = addTotalPct ? GetPctModifierValue(unitMod, TOTAL_PCT) : 1.0f;
|
||||
float dmgMultiplier = GetCreatureTemplate()->DamageModifier; // = DamageModifier * _GetDamageMod(rank);
|
||||
|
||||
minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
|
||||
|
|
@ -1233,11 +1229,11 @@ bool Guardian::UpdateAllStats()
|
|||
|
||||
void Guardian::UpdateArmor()
|
||||
{
|
||||
float value = GetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE);
|
||||
value *= GetModifierValue(UNIT_MOD_ARMOR, BASE_PCT);
|
||||
float value = GetFlatModifierValue(UNIT_MOD_ARMOR, BASE_VALUE);
|
||||
value *= GetPctModifierValue(UNIT_MOD_ARMOR, BASE_PCT);
|
||||
value += std::max<float>(GetStat(STAT_AGILITY) - GetCreateStat(STAT_AGILITY), 0.0f) * 2.0f;
|
||||
value += GetModifierValue(UNIT_MOD_ARMOR, TOTAL_VALUE);
|
||||
value *= GetModifierValue(UNIT_MOD_ARMOR, TOTAL_PCT);
|
||||
value += GetFlatModifierValue(UNIT_MOD_ARMOR, TOTAL_VALUE);
|
||||
value *= GetPctModifierValue(UNIT_MOD_ARMOR, TOTAL_PCT);
|
||||
SetArmor(int32(value));
|
||||
}
|
||||
|
||||
|
|
@ -1278,10 +1274,10 @@ void Guardian::UpdateMaxHealth()
|
|||
break;
|
||||
}
|
||||
|
||||
float value = GetModifierValue(unitMod, BASE_VALUE);// xinef: Do NOT add base health TWICE + GetCreateHealth();
|
||||
value *= GetModifierValue(unitMod, BASE_PCT);
|
||||
value += GetModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
|
||||
value *= GetModifierValue(unitMod, TOTAL_PCT);
|
||||
float value = GetFlatModifierValue(unitMod, BASE_VALUE);// xinef: Do NOT add base health TWICE + GetCreateHealth();
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + stamina * multiplicator;
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
SetMaxHealth((uint32)value);
|
||||
}
|
||||
|
|
@ -1311,11 +1307,11 @@ void Guardian::UpdateMaxPower(Powers power)
|
|||
break;
|
||||
}
|
||||
|
||||
// xinef: Do NOT add base mana TWICE
|
||||
float value = GetModifierValue(unitMod, BASE_VALUE) + (power != POWER_MANA ? GetCreatePowers(power) : 0);
|
||||
value *= GetModifierValue(unitMod, BASE_PCT);
|
||||
value += GetModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator;
|
||||
value *= GetModifierValue(unitMod, TOTAL_PCT);
|
||||
// Do NOT add base mana TWICE
|
||||
float value = GetFlatModifierValue(unitMod, BASE_VALUE) + (power != POWER_MANA ? GetCreatePowers(power) : 0);
|
||||
value *= GetPctModifierValue(unitMod, BASE_PCT);
|
||||
value += GetFlatModifierValue(unitMod, TOTAL_VALUE) + addValue * multiplicator;
|
||||
value *= GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
SetMaxPower(power, uint32(value));
|
||||
}
|
||||
|
|
@ -1335,12 +1331,12 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged)
|
|||
else
|
||||
val = 2 * GetStat(STAT_STRENGTH) - 20.0f;
|
||||
|
||||
SetModifierValue(unitMod, BASE_VALUE, val);
|
||||
SetStatFlatModifier(unitMod, BASE_VALUE, val);
|
||||
|
||||
//in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
|
||||
float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT);
|
||||
float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f;
|
||||
float base_attPower = GetFlatModifierValue(unitMod, BASE_VALUE) * GetPctModifierValue(unitMod, BASE_PCT);
|
||||
float attPowerMod = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
float attPowerMultiplier = GetPctModifierValue(unitMod, TOTAL_PCT) - 1.0f;
|
||||
|
||||
//UNIT_FIELD_(RANGED)_ATTACK_POWER field
|
||||
SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower);
|
||||
|
|
@ -1362,10 +1358,10 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType)
|
|||
|
||||
float att_speed = float(GetAttackTime(BASE_ATTACK)) / 1000.0f;
|
||||
|
||||
float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed;
|
||||
float base_pct = GetModifierValue(unitMod, BASE_PCT);
|
||||
float total_value = GetModifierValue(unitMod, TOTAL_VALUE);
|
||||
float total_pct = GetModifierValue(unitMod, TOTAL_PCT);
|
||||
float base_value = GetFlatModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType) / 14.0f * att_speed;
|
||||
float base_pct = GetPctModifierValue(unitMod, BASE_PCT);
|
||||
float total_value = GetFlatModifierValue(unitMod, TOTAL_VALUE);
|
||||
float total_pct = GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
|
||||
float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE);
|
||||
float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -123,13 +123,18 @@ enum HitInfo
|
|||
HITINFO_FAKE_DAMAGE = 0x01000000 // enables damage animation even if no damage done, set only if no damage
|
||||
};
|
||||
|
||||
enum UnitModifierType
|
||||
enum UnitModifierFlatType
|
||||
{
|
||||
BASE_VALUE = 0,
|
||||
BASE_PCT = 1,
|
||||
TOTAL_VALUE = 2,
|
||||
TOTAL_PCT = 3,
|
||||
MODIFIER_TYPE_END = 4
|
||||
TOTAL_VALUE = 1,
|
||||
MODIFIER_TYPE_FLAT_END = 3
|
||||
};
|
||||
|
||||
enum UnitModifierPctType
|
||||
{
|
||||
BASE_PCT = 0,
|
||||
TOTAL_PCT = 1,
|
||||
MODIFIER_TYPE_PCT_END = 2
|
||||
};
|
||||
|
||||
enum WeaponDamageRange
|
||||
|
|
@ -1050,16 +1055,32 @@ public:
|
|||
for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(static_cast<uint16>(UNIT_FIELD_NEGSTAT0) + i, 0);
|
||||
}
|
||||
|
||||
bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply);
|
||||
void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; }
|
||||
[[nodiscard]] float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const;
|
||||
bool HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply);
|
||||
void ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float amount);
|
||||
|
||||
void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val);
|
||||
void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val);
|
||||
|
||||
[[nodiscard]] float GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType) const;
|
||||
[[nodiscard]] float GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType) const;
|
||||
|
||||
void UpdateUnitMod(UnitMods unitMod);
|
||||
|
||||
// only players have item requirements
|
||||
[[nodiscard]] virtual bool CheckAttackFitToAuraRequirement(WeaponAttackType /*attackType*/, AuraEffect const* /*aurEff*/) const { return true; }
|
||||
|
||||
virtual void UpdateDamageDoneMods(WeaponAttackType attackType, int32 skipEnchantSlot = -1);
|
||||
void UpdateAllDamageDoneMods();
|
||||
|
||||
void UpdateDamagePctDoneMods(WeaponAttackType attackType);
|
||||
void UpdateAllDamagePctDoneMods();
|
||||
|
||||
[[nodiscard]] float GetTotalStatValue(Stats stat, float additionalValue = 0.0f) const;
|
||||
|
||||
void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; }
|
||||
[[nodiscard]] bool CanModifyStats() const { return m_canModifyStats; }
|
||||
|
||||
void ApplyStatBuffMod(Stats stat, float val, bool apply) { ApplyModSignedFloatValue((val > 0 ? static_cast<uint16>(UNIT_FIELD_POSSTAT0) + stat : static_cast<uint16>(UNIT_FIELD_NEGSTAT0) + stat), val, apply); }
|
||||
void ApplyStatPercentBuffMod(Stats stat, float val, bool apply);
|
||||
void UpdateStatBuffMod(Stats stat);
|
||||
|
||||
// Unit level methods
|
||||
[[nodiscard]] uint8 GetLevel() const { return uint8(GetUInt32Value(UNIT_FIELD_LEVEL)); }
|
||||
|
|
@ -1104,7 +1125,6 @@ public:
|
|||
void SetMaxPower(Powers power, uint32 val);
|
||||
|
||||
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate = true);
|
||||
int32 ModifyPowerPct(Powers power, float pct, bool apply = true);
|
||||
|
||||
void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker);
|
||||
|
||||
|
|
@ -1159,13 +1179,9 @@ public:
|
|||
[[nodiscard]] uint32 GetResistance(SpellSchoolMask mask) const;
|
||||
[[nodiscard]] uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_RESISTANCES) + school); }
|
||||
static float GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim);
|
||||
[[nodiscard]] float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school); }
|
||||
|
||||
void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(static_cast<uint16>(UNIT_FIELD_RESISTANCES) + school, val); }
|
||||
void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school, val); }
|
||||
|
||||
void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModSignedFloatValue(positive ? static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school, val, apply); }
|
||||
void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE) + school : static_cast<uint16>(UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE) + + school, val, apply); }
|
||||
void UpdateResistanceBuffModsMod(SpellSchools school);
|
||||
|
||||
//////////// Need triage ////////////////
|
||||
uint16 GetMaxSkillValueForLevel(Unit const* target = nullptr) const { return (target ? getLevelForTarget(target) : GetLevel()) * 5; }
|
||||
|
|
@ -1319,6 +1335,10 @@ public:
|
|||
|
||||
void SetAuraStack(uint32 spellId, Unit* target, uint32 stack);
|
||||
|
||||
int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool checkMiscValue = false, int32 miscValue = 0) const;
|
||||
bool IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications = false);
|
||||
bool IsHighestExclusiveAuraEffect(SpellInfo const* spellInfo, AuraType auraType, int32 effectAmount, uint8 auraEffectMask, bool removeOtherAuraApplications = false);
|
||||
|
||||
// aura apply/remove helpers - you should better not use these
|
||||
Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount = nullptr, Item* castItem = nullptr, ObjectGuid casterGUID = ObjectGuid::Empty, bool periodicReset = false);
|
||||
void _AddAura(UnitAura* aura, Unit* caster);
|
||||
|
|
@ -1328,7 +1348,7 @@ public:
|
|||
void _UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMode);
|
||||
void _UnapplyAura(AuraApplication* aurApp, AuraRemoveMode removeMode);
|
||||
void _RemoveNoStackAuraApplicationsDueToAura(Aura* aura);
|
||||
void _RemoveNoStackAurasDueToAura(Aura* aura);
|
||||
void _RemoveNoStackAurasDueToAura(Aura* aura, bool owned);
|
||||
bool _IsNoStackAuraDueToAura(Aura* appliedAura, Aura* existingAura) const;
|
||||
void _RegisterAuraEffect(AuraEffect* aurEff, bool apply);
|
||||
|
||||
|
|
@ -1474,15 +1494,19 @@ public:
|
|||
uint32 GetDiseasesByCaster(ObjectGuid casterGUID, uint8 mode = 0);
|
||||
[[nodiscard]] uint32 GetDoTsByCaster(ObjectGuid casterGUID) const;
|
||||
|
||||
[[nodiscard]] int32 GetTotalAuraModifierAreaExclusive(AuraType auratype) const;
|
||||
[[nodiscard]] int32 GetTotalAuraModifier(AuraType auratype) const;
|
||||
[[nodiscard]] float GetTotalAuraMultiplier(AuraType auratype) const;
|
||||
int32 GetMaxPositiveAuraModifier(AuraType auratype);
|
||||
[[nodiscard]] int32 GetMaxPositiveAuraModifier(AuraType auratype) const;
|
||||
[[nodiscard]] int32 GetMaxNegativeAuraModifier(AuraType auratype) const;
|
||||
|
||||
[[nodiscard]] int32 GetTotalAuraModifier(AuraType auratype, std::function<bool(AuraEffect const*)> const& predicate) const;
|
||||
[[nodiscard]] float GetTotalAuraMultiplier(AuraType auraType, std::function<bool(AuraEffect const*)> const& predicate) const;
|
||||
[[nodiscard]] int32 GetMaxPositiveAuraModifier(AuraType auraType, std::function<bool(AuraEffect const*)> const& predicate) const;
|
||||
[[nodiscard]] int32 GetMaxNegativeAuraModifier(AuraType auraType, std::function<bool(AuraEffect const*)> const& predicate) const;
|
||||
|
||||
[[nodiscard]] int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
|
||||
[[nodiscard]] float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const;
|
||||
int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, const AuraEffect* except = nullptr) const;
|
||||
[[nodiscard]] int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, const AuraEffect* except = nullptr) const;
|
||||
[[nodiscard]] int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
|
||||
|
||||
[[nodiscard]] int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
|
||||
|
|
@ -1581,7 +1605,6 @@ public:
|
|||
int32 HealBySpell(HealInfo& healInfo, bool critical = false);
|
||||
|
||||
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask);
|
||||
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask);
|
||||
float SpellPctHealingModsDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype);
|
||||
uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint8 effIndex, float TotalMod = 0.0f, uint32 stack = 1);
|
||||
uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1);
|
||||
|
|
@ -2132,7 +2155,8 @@ protected:
|
|||
AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove
|
||||
uint32 m_interruptMask;
|
||||
|
||||
float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
|
||||
float m_auraFlatModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_FLAT_END];
|
||||
float m_auraPctModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_PCT_END];
|
||||
float m_weaponDamage[MAX_ATTACK][MAX_WEAPON_DAMAGE_RANGE][MAX_ITEM_PROTO_DAMAGES];
|
||||
bool m_canModifyStats;
|
||||
VisibleAuraMap m_visibleAuras;
|
||||
|
|
|
|||
|
|
@ -256,8 +256,8 @@ void WorldSession::HandleAutoEquipItemOpcode(WorldPackets::Item::AutoEquipItem&
|
|||
}
|
||||
|
||||
// now do moves, remove...
|
||||
_player->RemoveItem(dstbag, dstslot, true, true);
|
||||
_player->RemoveItem(packet.SourceBag, packet.SourceSlot, true, true);
|
||||
_player->RemoveItem(dstbag, dstslot, true);
|
||||
_player->RemoveItem(packet.SourceBag, packet.SourceSlot, true);
|
||||
|
||||
// add to dest
|
||||
_player->EquipItem(dest, pSrcItem, true);
|
||||
|
|
|
|||
|
|
@ -24,16 +24,6 @@ void ScriptMgr::OnCalcMaxDuration(Aura const* aura, int32& maxDuration)
|
|||
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_CALC_MAX_DURATION, script->OnCalcMaxDuration(aura, maxDuration));
|
||||
}
|
||||
|
||||
bool ScriptMgr::CanModAuraEffectDamageDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(AllSpellScript, ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_DAMAGE_DONE, !script->CanModAuraEffectDamageDone(auraEff, target, aurApp, mode, apply));
|
||||
}
|
||||
|
||||
bool ScriptMgr::CanModAuraEffectModDamagePercentDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(AllSpellScript, ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_MOD_DAMAGE_PERCENT_DONE, !script->CanModAuraEffectModDamagePercentDone(auraEff, target, aurApp, mode, apply));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnSpellCheckCast(Spell* spell, bool strict, SpellCastResult& res)
|
||||
{
|
||||
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_SPELL_CHECK_CAST, script->OnSpellCheckCast(spell, strict, res));
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@
|
|||
enum AllSpellHook
|
||||
{
|
||||
ALLSPELLHOOK_ON_CALC_MAX_DURATION,
|
||||
ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_DAMAGE_DONE,
|
||||
ALLSPELLHOOK_CAN_MOD_AURA_EFFECT_MOD_DAMAGE_PERCENT_DONE,
|
||||
ALLSPELLHOOK_ON_SPELL_CHECK_CAST,
|
||||
ALLSPELLHOOK_CAN_PREPARE,
|
||||
ALLSPELLHOOK_CAN_SCALING_EVERYTHING,
|
||||
|
|
@ -56,10 +54,6 @@ public:
|
|||
// Calculate max duration in applying aura
|
||||
virtual void OnCalcMaxDuration(Aura const* /*aura*/, int32& /*maxDuration*/) { }
|
||||
|
||||
[[nodiscard]] virtual bool CanModAuraEffectDamageDone(AuraEffect const* /*auraEff*/, Unit* /*target*/, AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) { return true; }
|
||||
|
||||
[[nodiscard]] virtual bool CanModAuraEffectModDamagePercentDone(AuraEffect const* /*auraEff*/, Unit* /*target*/, AuraApplication const* /*aurApp*/, uint8 /*mode*/, bool /*apply*/) { return true; }
|
||||
|
||||
virtual void OnSpellCheckCast(Spell* /*spell*/, bool /*strict*/, SpellCastResult& /*res*/) { }
|
||||
|
||||
[[nodiscard]] virtual bool CanPrepare(Spell* /*spell*/, SpellCastTargets const* /*targets*/, AuraEffect const* /*triggeredByAura*/) { return true; }
|
||||
|
|
|
|||
|
|
@ -84,21 +84,6 @@ bool ScriptMgr::IfNormalReaction(Unit const* unit, Unit const* target, Reputatio
|
|||
CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IF_NORMAL_REACTION, !script->IfNormalReaction(unit, target, repRank));
|
||||
}
|
||||
|
||||
bool ScriptMgr::IsNeedModSpellDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IS_NEEDMOD_SPELL_DAMAGE_PERCENT, !script->IsNeedModSpellDamagePercent(unit, auraEff, doneTotalMod, spellProto));
|
||||
}
|
||||
|
||||
bool ScriptMgr::IsNeedModMeleeDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IS_NEEDMOD_MELEE_DAMAGE_PERCENT, !script->IsNeedModMeleeDamagePercent(unit, auraEff, doneTotalMod, spellProto));
|
||||
}
|
||||
|
||||
bool ScriptMgr::IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_IS_NEEDMOD_HEAL_PERCENT, !script->IsNeedModHealPercent(unit, auraEff, doneTotalMod, spellProto));
|
||||
}
|
||||
|
||||
bool ScriptMgr::CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(UnitScript, UNITHOOK_CAN_SET_PHASE_MASK, !script->CanSetPhaseMask(unit, newPhaseMask, update));
|
||||
|
|
|
|||
|
|
@ -33,9 +33,6 @@ enum UnitHook
|
|||
UNITHOOK_ON_AURA_APPLY,
|
||||
UNITHOOK_ON_AURA_REMOVE,
|
||||
UNITHOOK_IF_NORMAL_REACTION,
|
||||
UNITHOOK_IS_NEEDMOD_SPELL_DAMAGE_PERCENT,
|
||||
UNITHOOK_IS_NEEDMOD_MELEE_DAMAGE_PERCENT,
|
||||
UNITHOOK_IS_NEEDMOD_HEAL_PERCENT,
|
||||
UNITHOOK_CAN_SET_PHASE_MASK,
|
||||
UNITHOOK_IS_CUSTOM_BUILD_VALUES_UPDATE,
|
||||
UNITHOOK_SHOULD_TRACK_VALUES_UPDATE_POS_BY_INDEX,
|
||||
|
|
@ -89,12 +86,6 @@ public:
|
|||
|
||||
[[nodiscard]] virtual bool IfNormalReaction(Unit const* /*unit*/, Unit const* /*target*/, ReputationRank& /*repRank*/) { return true; }
|
||||
|
||||
[[nodiscard]] virtual bool IsNeedModSpellDamagePercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; }
|
||||
|
||||
[[nodiscard]] virtual bool IsNeedModMeleeDamagePercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; }
|
||||
|
||||
[[nodiscard]] virtual bool IsNeedModHealPercent(Unit const* /*unit*/, AuraEffect* /*auraEff*/, float& /*doneTotalMod*/, SpellInfo const* /*spellProto*/) { return true; }
|
||||
|
||||
[[nodiscard]] virtual bool CanSetPhaseMask(Unit const* /*unit*/, uint32 /*newPhaseMask*/, bool /*update*/) { return true; }
|
||||
|
||||
[[nodiscard]] virtual bool IsCustomBuildValuesUpdate(Unit const* /*unit*/, uint8 /*updateType*/, ByteBuffer& /*fieldBuffer*/, Player const* /*target*/, uint16 /*index*/) { return false; }
|
||||
|
|
|
|||
|
|
@ -546,9 +546,6 @@ public: /* UnitScript */
|
|||
void OnAuraApply(Unit* /*unit*/, Aura* /*aura*/);
|
||||
void OnAuraRemove(Unit* unit, AuraApplication* aurApp, AuraRemoveMode mode);
|
||||
bool IfNormalReaction(Unit const* unit, Unit const* target, ReputationRank& repRank);
|
||||
bool IsNeedModSpellDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
|
||||
bool IsNeedModMeleeDamagePercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
|
||||
bool IsNeedModHealPercent(Unit const* unit, AuraEffect* auraEff, float& doneTotalMod, SpellInfo const* spellProto);
|
||||
bool CanSetPhaseMask(Unit const* unit, uint32 newPhaseMask, bool update);
|
||||
bool IsCustomBuildValuesUpdate(Unit const* unit, uint8 updateType, ByteBuffer& fieldBuffer, Player const* target, uint16 index);
|
||||
bool ShouldTrackValuesUpdatePosByIndex(Unit const* unit, uint8 updateType, uint16 index);
|
||||
|
|
@ -606,8 +603,6 @@ public: /* Arena Team Script */
|
|||
|
||||
public: /* SpellSC */
|
||||
void OnCalcMaxDuration(Aura const* aura, int32& maxDuration);
|
||||
bool CanModAuraEffectDamageDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply);
|
||||
bool CanModAuraEffectModDamagePercentDone(AuraEffect const* auraEff, Unit* target, AuraApplication const* aurApp, uint8 mode, bool apply);
|
||||
void OnSpellCheckCast(Spell* spell, bool strict, SpellCastResult& res);
|
||||
bool CanPrepare(Spell* spell, SpellCastTargets const* targets, AuraEffect const* triggeredByAura);
|
||||
bool CanScalingEverything(Spell* spell);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS] =
|
|||
&AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
|
||||
&AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
|
||||
&AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
|
||||
&AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
|
||||
&AuraEffect::HandleShieldBlockValuePercent, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
|
||||
&AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
|
||||
&AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAggroRange
|
||||
&AuraEffect::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
|
||||
|
|
@ -393,7 +393,6 @@ AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32* baseAmount, Unit* cast
|
|||
m_amount = CalculateAmount(caster);
|
||||
m_casterLevel = caster ? caster->GetLevel() : 0;
|
||||
m_applyResilience = caster && caster->CanApplyResilience();
|
||||
m_auraGroup = sSpellMgr->GetSpellGroup(GetId());
|
||||
|
||||
CalculateSpellMod();
|
||||
|
||||
|
|
@ -3000,14 +2999,17 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode,
|
|||
// Handle damage modification, shapeshifted druids are not affected
|
||||
if (target->IsPlayer() && (!target->IsInFeralForm() || target->GetShapeshiftForm() == FORM_GHOSTWOLF))
|
||||
{
|
||||
if (Item* pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
|
||||
Player* player = target->ToPlayer();
|
||||
if (Item* pItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
|
||||
{
|
||||
WeaponAttackType attacktype = Player::GetAttackBySlot(slot);
|
||||
WeaponAttackType attackType = Player::GetAttackBySlot(slot);
|
||||
|
||||
if (attacktype < MAX_ATTACK)
|
||||
player->ApplyItemDependentAuras(pItem, !apply);
|
||||
if (attackType < MAX_ATTACK)
|
||||
{
|
||||
target->ToPlayer()->_ApplyWeaponDamage(slot, pItem->GetTemplate(), nullptr, !apply);
|
||||
target->ToPlayer()->_ApplyWeaponDependentAuraMods(pItem, attacktype, !apply);
|
||||
player->_ApplyWeaponDamage(slot, pItem->GetTemplate(), nullptr, !apply);
|
||||
if (!apply) // apply case already handled on item dependent aura removal (if any)
|
||||
player->UpdateWeaponDependentAuras(attackType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3439,9 +3441,17 @@ void AuraEffect::HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool
|
|||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
|
||||
for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
|
||||
if (GetMiscValue() & (1 << i))
|
||||
ApplyPercentModFloatVar(target->m_threatModifier[i], float(GetAmount()), apply);
|
||||
{
|
||||
if (apply)
|
||||
AddPct(target->m_threatModifier[i], GetAmount());
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, 1 << i);
|
||||
target->m_threatModifier[i] = amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
|
@ -4318,7 +4328,7 @@ void AuraEffect::HandleAuraModResistanceExclusive(AuraApplication const* aurApp,
|
|||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
|
||||
for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
|
||||
{
|
||||
if (GetMiscValue() & int32(1 << x))
|
||||
{
|
||||
|
|
@ -4326,9 +4336,9 @@ void AuraEffect::HandleAuraModResistanceExclusive(AuraApplication const* aurApp,
|
|||
if (amount < GetAmount())
|
||||
{
|
||||
float value = float(GetAmount() - amount);
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, value, apply);
|
||||
if (target->IsPlayer())
|
||||
target->ApplyResistanceBuffModsMod(SpellSchools(x), aurApp->IsPositive(), value, apply);
|
||||
target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, value, apply);
|
||||
if (target->IsPlayer() || target->IsPet())
|
||||
target->UpdateResistanceBuffModsMod(SpellSchools(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4345,9 +4355,9 @@ void AuraEffect::HandleAuraModResistance(AuraApplication const* aurApp, uint8 mo
|
|||
{
|
||||
if (GetMiscValue() & int32(1 << x))
|
||||
{
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
|
||||
if (target->IsPlayer() || target->IsPet())
|
||||
target->ApplyResistanceBuffModsMod(SpellSchools(x), GetAmount() > 0, (float)GetAmount(), apply);
|
||||
target->UpdateResistanceBuffModsMod(SpellSchools(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4358,32 +4368,39 @@ void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const* aurApp, u
|
|||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
|
||||
for (uint8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
|
||||
{
|
||||
if (GetMiscValue() & int32(1 << x))
|
||||
{
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply);
|
||||
if (apply)
|
||||
target->ApplyStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()));
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_BASE_RESISTANCE_PCT, 1 << x);
|
||||
target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
void AuraEffect::HandleModResistancePercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
{
|
||||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
|
||||
for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
|
||||
{
|
||||
if (GetMiscValue() & int32(1 << i))
|
||||
{
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
|
||||
float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_RESISTANCE_PCT, 1 << i);
|
||||
if (target->GetPctModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT) == amount)
|
||||
continue;
|
||||
|
||||
target->SetStatPctModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, amount);
|
||||
if (target->IsPlayer() || target->IsPet())
|
||||
{
|
||||
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), true, (float)GetAmount(), apply);
|
||||
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i), false, (float)GetAmount(), apply);
|
||||
}
|
||||
target->UpdateResistanceBuffModsMod(SpellSchools(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4398,7 +4415,7 @@ void AuraEffect::HandleModBaseResistance(AuraApplication const* aurApp, uint8 mo
|
|||
{
|
||||
if (GetMiscValue() & (1 << i))
|
||||
{
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4430,23 +4447,28 @@ void AuraEffect::HandleAuraModStat(AuraApplication const* aurApp, uint8 mode, bo
|
|||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
if (GetMiscValue() < -2 || GetMiscValue() > 4)
|
||||
{
|
||||
LOG_ERROR("spells.aura.effect", "WARNING: Spell {} effect {} has an unsupported misc value ({}) for SPELL_AURA_MOD_STAT ", GetId(), GetEffIndex(), GetMiscValue());
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_STAT, true, GetMiscValue());
|
||||
if (std::abs(spellGroupVal) >= std::abs(GetAmount()))
|
||||
return;
|
||||
|
||||
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
|
||||
{
|
||||
// -1 or -2 is all stats (misc < -2 checked in function beginning)
|
||||
if (GetMiscValue() < 0 || GetMiscValue() == i)
|
||||
{
|
||||
//target->ApplyStatMod(Stats(i), m_amount, apply);
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
|
||||
if (spellGroupVal)
|
||||
target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), !apply);
|
||||
|
||||
target->HandleStatFlatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
|
||||
if (target->IsPlayer() || target->IsPet())
|
||||
target->ApplyStatBuffMod(Stats(i), (float)GetAmount(), apply);
|
||||
target->UpdateStatBuffMod(Stats(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4470,8 +4492,16 @@ void AuraEffect::HandleModPercentStat(AuraApplication const* aurApp, uint8 mode,
|
|||
|
||||
for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
|
||||
{
|
||||
if (GetMiscValue() == i || GetMiscValue() == -1)
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply);
|
||||
if (apply)
|
||||
target->ApplyStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(GetAmount()));
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_PERCENT_STAT, [i](AuraEffect const* aurEff)
|
||||
{
|
||||
return (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1);
|
||||
});
|
||||
target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4549,7 +4579,7 @@ void AuraEffect::HandleModHealingDone(AuraApplication const* aurApp, uint8 mode,
|
|||
target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
{
|
||||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
|
@ -4565,39 +4595,22 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
|
|||
// save current health state
|
||||
float healthPct = target->GetHealthPct();
|
||||
bool alive = target->IsAlive();
|
||||
float value = GetAmount();
|
||||
|
||||
if (GetId() == 67480) // xinef: hack fix for blessing of sanctuary stats stack with blessing of kings...
|
||||
{
|
||||
if (value) // not turned off
|
||||
value = 10.0f;
|
||||
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
|
||||
{
|
||||
if (i == STAT_STRENGTH || i == STAT_STAMINA)
|
||||
{
|
||||
if (apply && (target->IsPlayer() || target->IsPet()))
|
||||
target->ApplyStatPercentBuffMod(Stats(i), value, apply);
|
||||
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, value, apply);
|
||||
|
||||
if (!apply && (target->IsPlayer() || target->IsPet()))
|
||||
target->ApplyStatPercentBuffMod(Stats(i), value, apply);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
|
||||
{
|
||||
if (GetMiscValue() == i || GetMiscValue() == -1)
|
||||
{
|
||||
if (apply && (target->IsPlayer() || target->IsPet()))
|
||||
target->ApplyStatPercentBuffMod(Stats(i), value, apply);
|
||||
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, [i](AuraEffect const* aurEff)
|
||||
{
|
||||
return (aurEff->GetMiscValue() == i || aurEff->GetMiscValue() == -1);
|
||||
});
|
||||
|
||||
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, value, apply);
|
||||
if (target->GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT) == amount)
|
||||
continue;
|
||||
|
||||
if (!apply && (target->IsPlayer() || target->IsPet()))
|
||||
target->ApplyStatPercentBuffMod(Stats(i), value, apply);
|
||||
target->SetStatPctModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, amount);
|
||||
if (target->IsPlayer() || target->IsPet())
|
||||
target->UpdateStatBuffMod(Stats(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4693,7 +4706,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
|
|||
|
||||
if (apply)
|
||||
{
|
||||
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->ModifyHealth(GetAmount());
|
||||
}
|
||||
else
|
||||
|
|
@ -4702,7 +4715,7 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
|
|||
target->ModifyHealth(-GetAmount());
|
||||
else
|
||||
target->SetHealth(1);
|
||||
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4716,7 +4729,7 @@ void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const* aurApp, u
|
|||
uint32 oldhealth = target->GetHealth();
|
||||
double healthPercentage = (double)oldhealth / (double)target->GetMaxHealth();
|
||||
|
||||
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
|
||||
// refresh percentage
|
||||
if (oldhealth > 0)
|
||||
|
|
@ -4746,7 +4759,7 @@ void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const* aurApp, uint
|
|||
|
||||
UnitMods unitMod = UnitMods(static_cast<uint16>(UNIT_MOD_POWER_START) + PowerType);
|
||||
|
||||
target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
|
@ -4765,17 +4778,16 @@ void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const* aurAp
|
|||
// return;
|
||||
|
||||
UnitMods unitMod = UnitMods(static_cast<uint16>(UNIT_MOD_POWER_START) + PowerType);
|
||||
float amount = float(GetAmount());
|
||||
|
||||
if (apply)
|
||||
{
|
||||
target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply);
|
||||
target->ModifyPowerPct(PowerType, amount, apply);
|
||||
float amount = float(GetAmount());
|
||||
target->ApplyStatPctModifier(unitMod, TOTAL_PCT, amount);
|
||||
}
|
||||
else
|
||||
{
|
||||
target->ModifyPowerPct(PowerType, amount, apply);
|
||||
target->HandleStatModifier(unitMod, TOTAL_PCT, amount, apply);
|
||||
float amount = target->GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT, GetMiscValue());
|
||||
target->SetStatPctModifier(unitMod, TOTAL_PCT, amount);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4788,7 +4800,14 @@ void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const* aurAp
|
|||
|
||||
// Unit will keep hp% after MaxHealth being modified if unit is alive.
|
||||
float percent = target->GetHealthPct();
|
||||
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply);
|
||||
|
||||
if (apply)
|
||||
target->ApplyStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()));
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT);
|
||||
target->SetStatPctModifier(UNIT_MOD_HEALTH, TOTAL_PCT, amount);
|
||||
}
|
||||
|
||||
// Xinef: pct was rounded down and could "kill" creature by setting its health to 0 making npc zombie
|
||||
if (target->IsAlive())
|
||||
|
|
@ -4803,7 +4822,13 @@ void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurA
|
|||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply);
|
||||
if (apply)
|
||||
target->ApplyStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()));
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_BASE_HEALTH_PCT);
|
||||
target->SetStatPctModifier(UNIT_MOD_HEALTH, BASE_PCT, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
|
@ -4857,34 +4882,17 @@ void AuraEffect::HandleAuraModRegenInterrupt(AuraApplication const* aurApp, uint
|
|||
HandleModManaRegen(aurApp, mode, apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
{
|
||||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
Player* target = aurApp->GetTarget()->ToPlayer();
|
||||
|
||||
if (!target->IsPlayer())
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < MAX_ATTACK; ++i)
|
||||
if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
|
||||
target->ToPlayer()->_ApplyWeaponDependentAuraCritMod(pItem, WeaponAttackType(i), this, apply);
|
||||
|
||||
// mods must be applied base at equipped weapon class and subclass comparison
|
||||
// with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
|
||||
// GetMiscValue() comparison with item generated damage types
|
||||
|
||||
if (GetSpellInfo()->EquippedItemClass == -1)
|
||||
{
|
||||
target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
|
||||
target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
|
||||
target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
|
||||
}
|
||||
else
|
||||
{
|
||||
// done in Player::_ApplyWeaponDependentAuraMods
|
||||
}
|
||||
target->UpdateAllWeaponDependentCritAuras();
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModHitChance(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
|
@ -4960,9 +4968,7 @@ void AuraEffect::HandleAuraModCritPct(AuraApplication const* aurApp, uint8 mode,
|
|||
return;
|
||||
}
|
||||
|
||||
target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
|
||||
target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
|
||||
target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
|
||||
target->ToPlayer()->UpdateAllWeaponDependentCritAuras();
|
||||
|
||||
// included in Player::UpdateSpellCritChance calculation
|
||||
target->ToPlayer()->UpdateAllSpellCritChances();
|
||||
|
|
@ -4986,6 +4992,13 @@ void AuraEffect::HandleModCastingSpeed(AuraApplication const* aurApp, uint8 mode
|
|||
return;
|
||||
}
|
||||
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, GetAuraType());
|
||||
if (std::abs(spellGroupVal) >= std::abs(GetAmount()))
|
||||
return;
|
||||
|
||||
if (spellGroupVal)
|
||||
target->ApplyCastTimePercentMod(float(spellGroupVal), !apply);
|
||||
|
||||
target->ApplyCastTimePercentMod((float)GetAmount(), apply);
|
||||
}
|
||||
|
||||
|
|
@ -5007,6 +5020,17 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo
|
|||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MELEE_SLOW);
|
||||
if (std::abs(spellGroupVal) >= std::abs(GetAmount()))
|
||||
return;
|
||||
|
||||
if (spellGroupVal)
|
||||
{
|
||||
target->ApplyCastTimePercentMod(float(spellGroupVal), !apply);
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply);
|
||||
target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(spellGroupVal), !apply);
|
||||
}
|
||||
|
||||
target->ApplyCastTimePercentMod(float(GetAmount()), apply);
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
|
||||
|
|
@ -5031,7 +5055,15 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod
|
|||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_MELEE_HASTE);
|
||||
if (std::abs(spellGroupVal) >= std::abs(GetAmount()))
|
||||
return;
|
||||
|
||||
if (spellGroupVal)
|
||||
{
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply);
|
||||
}
|
||||
target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply);
|
||||
target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply);
|
||||
}
|
||||
|
|
@ -5105,7 +5137,7 @@ void AuraEffect::HandleAuraModAttackPower(AuraApplication const* aurApp, uint8 m
|
|||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
|
@ -5118,7 +5150,7 @@ void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const* aurApp, u
|
|||
if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0)
|
||||
return;
|
||||
|
||||
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
|
@ -5129,7 +5161,13 @@ void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const* aurApp,
|
|||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
|
||||
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()), apply);
|
||||
if (apply)
|
||||
target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()));
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_ATTACK_POWER_PCT);
|
||||
target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, amount);
|
||||
}
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
|
@ -5143,7 +5181,13 @@ void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const* au
|
|||
return;
|
||||
|
||||
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
|
||||
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply);
|
||||
if (apply)
|
||||
target->ApplyStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()));
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT);
|
||||
target->SetStatPctModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, amount);
|
||||
}
|
||||
}
|
||||
|
||||
void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
|
|
@ -5184,85 +5228,25 @@ void AuraEffect::HandleModDamageDone(AuraApplication const* aurApp, uint8 mode,
|
|||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
// apply item specific bonuses for already equipped weapon
|
||||
if (target->IsPlayer())
|
||||
{
|
||||
for (int i = 0; i < MAX_ATTACK; ++i)
|
||||
if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
|
||||
target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply);
|
||||
}
|
||||
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
|
||||
target->UpdateAllDamageDoneMods();
|
||||
|
||||
// GetMiscValue() is bitmask of spell schools
|
||||
// 1 (0-bit) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
|
||||
// 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
|
||||
// 127 - full bitmask any damages
|
||||
//
|
||||
// mods must be applied base at equipped weapon class and subclass comparison
|
||||
// with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
|
||||
// GetMiscValue() comparison with item generated damage types
|
||||
|
||||
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0 && sScriptMgr->CanModAuraEffectDamageDone(this, target, aurApp, mode, apply))
|
||||
{
|
||||
// apply generic physical damage bonuses including wand case
|
||||
if (GetSpellInfo()->EquippedItemClass == -1 || !target->IsPlayer())
|
||||
{
|
||||
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
|
||||
|
||||
if (target->IsPlayer())
|
||||
{
|
||||
if (GetAmount() > 0)
|
||||
target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, GetAmount(), apply);
|
||||
else
|
||||
target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG, GetAmount(), apply);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// done in Player::_ApplyWeaponDependentAuraMods
|
||||
}
|
||||
}
|
||||
|
||||
// Skip non magic case for Speedup
|
||||
if ((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0)
|
||||
return;
|
||||
|
||||
if (GetSpellInfo()->EquippedItemClass != -1 || GetSpellInfo()->EquippedItemInventoryTypeMask != 0)
|
||||
{
|
||||
// wand magic case (skip generic to all item spell bonuses)
|
||||
// done in Player::_ApplyWeaponDependentAuraMods
|
||||
|
||||
// Skip item specific requirements for not wand magic damage
|
||||
return;
|
||||
}
|
||||
|
||||
// Magic damage modifiers implemented in Unit::SpellDamageBonus
|
||||
// Magic damage modifiers implemented in Unit::SpellBaseDamageBonus
|
||||
// This information for client side use only
|
||||
if (target->IsPlayer())
|
||||
{
|
||||
if (GetAmount() > 0)
|
||||
{
|
||||
for (uint32 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
|
||||
{
|
||||
if ((GetMiscValue() & (1 << i)) != 0)
|
||||
target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + i, GetAmount(), apply);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
|
||||
{
|
||||
if ((GetMiscValue() & (1 << i)) != 0)
|
||||
target->ApplyModInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + i, GetAmount(), apply);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 baseField = GetAmount() >= 0 ? PLAYER_FIELD_MOD_DAMAGE_DONE_POS : PLAYER_FIELD_MOD_DAMAGE_DONE_NEG;
|
||||
for (uint16 i = 0; i < MAX_SPELL_SCHOOL; ++i)
|
||||
if (GetMiscValue() & (1 << i))
|
||||
target->ApplyModUInt32Value(baseField + i, GetAmount(), apply);
|
||||
|
||||
if (Guardian* pet = target->ToPlayer()->GetGuardianPet())
|
||||
pet->UpdateAttackPowerAndDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
{
|
||||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
|
@ -5271,39 +5255,32 @@ void AuraEffect::HandleModDamagePercentDone(AuraApplication const* aurApp, uint8
|
|||
if (!target)
|
||||
return;
|
||||
|
||||
if (!sScriptMgr->CanModAuraEffectModDamagePercentDone(this, target, aurApp, mode, apply))
|
||||
return;
|
||||
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
|
||||
target->UpdateAllDamagePctDoneMods();
|
||||
|
||||
if (target->IsPlayer())
|
||||
{
|
||||
for (int i = 0; i < MAX_ATTACK; ++i)
|
||||
if (Item* item = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), false))
|
||||
target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(item, WeaponAttackType(i), this, apply);
|
||||
}
|
||||
|
||||
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) && (GetSpellInfo()->EquippedItemClass == -1 || !target->IsPlayer()))
|
||||
{
|
||||
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
|
||||
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
|
||||
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
|
||||
|
||||
if (target->IsPlayer())
|
||||
target->ToPlayer()->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT, float (GetAmount()), apply);
|
||||
}
|
||||
else
|
||||
{
|
||||
// done in Player::_ApplyWeaponDependentAuraMods for SPELL_SCHOOL_MASK_NORMAL && EquippedItemClass != -1 and also for wand case
|
||||
for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
|
||||
{
|
||||
if (GetMiscValue() & (1 << i))
|
||||
{
|
||||
// only aura type modifying PLAYER_FIELD_MOD_DAMAGE_DONE_PCT
|
||||
float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, 1 << i);
|
||||
target->SetFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT + i, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
|
||||
{
|
||||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
|
||||
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
|
||||
// also handles spell group stacks
|
||||
target->UpdateDamagePctDoneMods(OFF_ATTACK);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
|
|
@ -5311,14 +5288,29 @@ void AuraEffect::HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mod
|
|||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
||||
Unit* target = aurApp->GetTarget();
|
||||
Player* target = aurApp->GetTarget()->ToPlayer();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
BaseModType modType = FLAT_MOD;
|
||||
if (GetAuraType() == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
|
||||
modType = PCT_MOD;
|
||||
target->HandleBaseModFlatValue(SHIELD_BLOCK_VALUE, float(GetAmount()), apply);
|
||||
}
|
||||
|
||||
if (target->IsPlayer())
|
||||
target->ToPlayer()->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetAmount()), apply);
|
||||
void AuraEffect::HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
{
|
||||
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
|
||||
return;
|
||||
|
||||
Player* target = aurApp->GetTarget()->ToPlayer();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (apply)
|
||||
target->ApplyBaseModPctValue(SHIELD_BLOCK_VALUE, float(GetAmount()));
|
||||
else
|
||||
{
|
||||
float amount = target->GetTotalAuraMultiplier(SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT);
|
||||
target->SetBaseModPctValue(SHIELD_BLOCK_VALUE, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************/
|
||||
|
|
|
|||
|
|
@ -112,8 +112,6 @@ public:
|
|||
float GetPctMods() const { return m_pctMods; }
|
||||
void SetPctMods(float pctMods) { m_pctMods = pctMods; }
|
||||
|
||||
// xinef: stacking
|
||||
uint32 GetAuraGroup() const { return m_auraGroup; }
|
||||
int32 GetOldAmount() const { return m_oldAmount; }
|
||||
void SetOldAmount(int32 amount) { m_oldAmount = amount; }
|
||||
void SetEnabled(bool enabled) { m_isAuraEnabled = enabled; }
|
||||
|
|
@ -131,8 +129,6 @@ private:
|
|||
float m_critChance;
|
||||
float m_pctMods;
|
||||
|
||||
// xinef: stacking
|
||||
uint32 m_auraGroup;
|
||||
int32 m_oldAmount;
|
||||
bool m_isAuraEnabled;
|
||||
// xinef: channel information for channel triggering
|
||||
|
|
@ -299,6 +295,7 @@ public:
|
|||
void HandleModDamagePercentDone(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleModOffhandDamagePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleShieldBlockValue(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleShieldBlockValuePercent(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
// power cost
|
||||
void HandleModPowerCostPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleModPowerCost(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
|
|
|
|||
|
|
@ -181,67 +181,6 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply)
|
|||
// Remove all triggered by aura spells vs unlimited duration
|
||||
aurEff->CleanupTriggeredSpells(GetTarget());
|
||||
}
|
||||
|
||||
// Stacking!
|
||||
if (uint32 groupId = aurEff->GetAuraGroup())
|
||||
{
|
||||
SpellGroupStackFlags sFlag = sSpellMgr->GetGroupStackFlags(groupId);
|
||||
if (!aurEff->IsPeriodic() && (sFlag & SPELL_GROUP_STACK_FLAG_EFFECT_EXCLUSIVE))
|
||||
{
|
||||
AuraApplication* strongestApp = apply ? this : nullptr;
|
||||
AuraEffect* strongestEff = apply ? aurEff : nullptr;
|
||||
int32 amount = apply ? std::abs(aurEff->GetAmount()) : 0;
|
||||
Unit* target = GetTarget();
|
||||
Unit::AuraEffectList const& auraList = target->GetAuraEffectsByType(aurEff->GetAuraType());
|
||||
for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter)
|
||||
{
|
||||
if ((*iter)->GetAuraGroup() != groupId || (*iter) == strongestEff || (*iter)->GetBase()->IsRemoved())
|
||||
continue;
|
||||
|
||||
// xinef: skip different misc values
|
||||
if (aurEff->GetAuraType() != SPELL_AURA_230 /*SPELL_AURA_MOD_INCREASE_HEALTH_2*/ && aurEff->GetAuraType() != SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK &&
|
||||
aurEff->GetMiscValue() != (*iter)->GetMiscValue())
|
||||
continue;
|
||||
|
||||
// xinef: should not happen
|
||||
AuraApplication* aurApp = (*iter)->GetBase()->GetApplicationOfTarget(target->GetGUID());
|
||||
if (!aurApp)
|
||||
continue;
|
||||
|
||||
if (amount < std::abs((*iter)->GetForcedAmount()))
|
||||
{
|
||||
// xinef: if we have strongest aura and it is active, turn it off
|
||||
// xinef: otherwise just save new aura;
|
||||
if (strongestApp && strongestEff && strongestApp->IsActive(strongestEff->GetEffIndex()))
|
||||
{
|
||||
strongestEff->HandleEffect(strongestApp, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, false);
|
||||
if (!strongestEff->GetSpellInfo()->HasAreaAuraEffect())
|
||||
strongestEff->SetEnabled(false);
|
||||
strongestApp->SetDisableMask(strongestEff->GetEffIndex());
|
||||
}
|
||||
strongestApp = aurApp;
|
||||
strongestEff = (*iter);
|
||||
amount = std::abs((*iter)->GetAmount());
|
||||
}
|
||||
// xinef: itered aura is weaker, deactivate if active
|
||||
else if (aurApp->IsActive((*iter)->GetEffIndex()))
|
||||
{
|
||||
(*iter)->HandleEffect(aurApp, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, false);
|
||||
if (!(*iter)->GetSpellInfo()->HasAreaAuraEffect())
|
||||
(*iter)->SetEnabled(false);
|
||||
aurApp->SetDisableMask((*iter)->GetEffIndex());
|
||||
}
|
||||
}
|
||||
|
||||
// xinef: if we have new strongest aura, and it is not active
|
||||
if (strongestApp && strongestEff && !strongestApp->IsActive(strongestEff->GetEffIndex()))
|
||||
{
|
||||
strongestApp->RemoveDisableMask(strongestEff->GetEffIndex());
|
||||
strongestEff->SetEnabled(true);
|
||||
strongestEff->HandleEffect(strongestApp, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
SetNeedClientUpdate();
|
||||
}
|
||||
|
||||
|
|
@ -661,6 +600,9 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
|
|||
if (!itr->second || itr->first->IsImmunedToSpell(GetSpellInfo()) || !CanBeAppliedOn(itr->first))
|
||||
addUnit = false;
|
||||
|
||||
if (addUnit && !itr->first->IsHighestExclusiveAura(this, true))
|
||||
addUnit = false;
|
||||
|
||||
if (addUnit)
|
||||
{
|
||||
// persistent area aura does not hit flying targets
|
||||
|
|
@ -684,7 +626,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
|
|||
for (Unit::AuraApplicationMap::iterator iter = itr->first->GetAppliedAuras().begin(); iter != itr->first->GetAppliedAuras().end(); ++iter)
|
||||
{
|
||||
Aura const* aura = iter->second->GetBase();
|
||||
if (!CanStackWith(aura, false))
|
||||
if (!CanStackWith(aura))
|
||||
{
|
||||
addUnit = false;
|
||||
break;
|
||||
|
|
@ -1069,6 +1011,16 @@ void Aura::RefreshSpellMods()
|
|||
player->RestoreAllSpellMods(0, this);
|
||||
}
|
||||
|
||||
bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const
|
||||
{
|
||||
uint32 count = 0;
|
||||
for (SpellEffectInfo const& spellEffectInfo : GetSpellInfo()->GetEffects())
|
||||
if (HasEffect(spellEffectInfo.EffectIndex) && spellEffectInfo.ApplyAuraName == auraType)
|
||||
++count;
|
||||
|
||||
return count > 1;
|
||||
}
|
||||
|
||||
bool Aura::IsArea() const
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
|
|
@ -1589,7 +1541,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
|
|||
// Alchemy: Mixology
|
||||
if (caster && caster->HasAura(53042) && caster->IsPlayer() && !caster->ToPlayer()->GetSession()->PlayerLoading())
|
||||
{
|
||||
if (sSpellMgr->GetSpellGroup(GetId()) == 1) /*Elixirs*/
|
||||
if (sSpellMgr->IsSpellMemberOfSpellGroup(GetId(), SPELL_GROUP_ELIXIR_BATTLE) || sSpellMgr->IsSpellMemberOfSpellGroup(GetId(), SPELL_GROUP_ELIXIR_GUARDIAN))
|
||||
{
|
||||
if (caster->HasSpell(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell))
|
||||
{
|
||||
|
|
@ -2018,7 +1970,7 @@ bool Aura::IsAuraStronger(Aura const* newAura) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Aura::CanStackWith(Aura const* existingAura, bool remove) const
|
||||
bool Aura::CanStackWith(Aura const* existingAura) const
|
||||
{
|
||||
// Can stack with self
|
||||
if (this == existingAura)
|
||||
|
|
@ -2056,47 +2008,19 @@ bool Aura::CanStackWith(Aura const* existingAura, bool remove) const
|
|||
return false;
|
||||
|
||||
// check spell group stack rules
|
||||
// xinef: this assures us that both spells are in same group!
|
||||
SpellGroupStackFlags stackFlags = sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo, remove, IsArea());
|
||||
if (stackFlags)
|
||||
switch (sSpellMgr->CheckSpellGroupStackRules(m_spellInfo, existingSpellInfo))
|
||||
{
|
||||
// xinef: same caster rule is bounded by spellfamily
|
||||
if (sameCaster && m_spellInfo->SpellFamilyName == existingSpellInfo->SpellFamilyName &&
|
||||
(stackFlags & SPELL_GROUP_STACK_FLAG_NOT_SAME_CASTER))
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE:
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST: // if it reaches this point, existing aura is lower/equal
|
||||
return false;
|
||||
|
||||
// xinef: normal exclusive stacking, remove if auras are equal by effects
|
||||
if (stackFlags & SPELL_GROUP_STACK_FLAG_EXCLUSIVE)
|
||||
{
|
||||
if (GetSpellInfo()->IsAuraEffectEqual(existingSpellInfo) || GetSpellInfo()->IsRankOf(existingSpellInfo))
|
||||
{
|
||||
if (remove)
|
||||
return IsAuraStronger(existingAura);
|
||||
else
|
||||
return existingAura->IsAuraStronger(this);
|
||||
}
|
||||
}
|
||||
|
||||
// xinef: check priority before effect mask
|
||||
SpellGroupSpecialFlags thisAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(GetId());
|
||||
SpellGroupSpecialFlags existingAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(existingSpellInfo->Id);
|
||||
if (thisAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && thisAuraFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 &&
|
||||
existingAuraFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && existingAuraFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4)
|
||||
{
|
||||
if (thisAuraFlag < existingAuraFlag)
|
||||
{
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER:
|
||||
if (sameCaster)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// xinef: forced strongest aura in group by flag
|
||||
if (stackFlags & SPELL_GROUP_STACK_FLAG_FORCED_STRONGEST)
|
||||
return !remove;
|
||||
if (stackFlags & SPELL_GROUP_STACK_FLAG_FORCED_WEAKEST)
|
||||
return remove;
|
||||
|
||||
// xinef: forced return, handle all cases using available flags!
|
||||
return !(stackFlags & SPELL_GROUP_STACK_FLAG_NEVER_STACK);
|
||||
break;
|
||||
case SPELL_GROUP_STACK_RULE_DEFAULT:
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_spellInfo->SpellFamilyName != existingSpellInfo->SpellFamilyName)
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ public:
|
|||
|
||||
uint8 GetCasterLevel() const { return m_casterLevel; }
|
||||
|
||||
bool HasMoreThanOneEffectForType(AuraType auraType) const;
|
||||
bool IsArea() const;
|
||||
bool IsPassive() const;
|
||||
bool IsDeathPersistent() const;
|
||||
|
|
@ -188,7 +189,7 @@ public:
|
|||
void HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, bool apply, bool onReapply);
|
||||
bool CanBeAppliedOn(Unit* target);
|
||||
bool CheckAreaTarget(Unit* target);
|
||||
bool CanStackWith(Aura const* checkAura, bool remove) const;
|
||||
bool CanStackWith(Aura const* existingAura) const;
|
||||
bool IsAuraStronger(Aura const* newAura) const;
|
||||
|
||||
// Proc system
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include "ArenaSpectator.h"
|
||||
#include "BattlefieldMgr.h"
|
||||
#include "Battleground.h"
|
||||
#include "BattlegroundIC.h"
|
||||
#include "CharmInfo.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Common.h"
|
||||
|
|
@ -33,7 +32,6 @@
|
|||
#include "InstanceScript.h"
|
||||
#include "Log.h"
|
||||
#include "LootMgr.h"
|
||||
#include "MapMgr.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
|
|
@ -41,6 +39,7 @@
|
|||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "SpellAuraDefines.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
|
|
@ -1240,11 +1239,7 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge
|
|||
// Other special target selection goes here
|
||||
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
|
||||
{
|
||||
Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
|
||||
for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
|
||||
if ((*j)->IsAffectedOnSpell(m_spellInfo))
|
||||
maxTargets += (*j)->GetAmount();
|
||||
|
||||
maxTargets += m_caster->GetTotalAuraModifierByAffectMask(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS, m_spellInfo);
|
||||
Acore::Containers::RandomResize(targets, maxTargets);
|
||||
}
|
||||
|
||||
|
|
@ -1327,11 +1322,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
|
|||
// Other special target selection goes here
|
||||
if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
|
||||
{
|
||||
Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS);
|
||||
for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
|
||||
if ((*j)->IsAffectedOnSpell(m_spellInfo))
|
||||
maxTargets += (*j)->GetAmount();
|
||||
|
||||
maxTargets += m_caster->GetTotalAuraModifierByAffectMask(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS, m_spellInfo);
|
||||
Acore::Containers::RandomResize(targets, maxTargets);
|
||||
}
|
||||
|
||||
|
|
@ -6076,6 +6067,8 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
}
|
||||
}
|
||||
|
||||
uint8 approximateAuraEffectMask = 0;
|
||||
uint8 nonAuraEffectMask = 0;
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
// for effects of spells that have only one target
|
||||
|
|
@ -6561,6 +6554,11 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_spellInfo->Effects[i].IsAura())
|
||||
approximateAuraEffectMask |= 1 << i;
|
||||
else if (m_spellInfo->Effects[i].IsEffect())
|
||||
nonAuraEffectMask |= 1 << i;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
|
|
@ -6723,6 +6721,13 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// check if target already has the same type, but more powerful aura
|
||||
if (!nonAuraEffectMask && (approximateAuraEffectMask & (1 << i)) && !m_spellInfo->IsTargetingArea())
|
||||
if (Unit* target = m_targets.GetUnitTarget())
|
||||
if (!target->IsHighestExclusiveAuraEffect(m_spellInfo, AuraType(m_spellInfo->Effects[i].ApplyAuraName),
|
||||
m_spellInfo->Effects[i].CalcValue(m_caster, &m_spellValue->EffectBasePoints[i]), approximateAuraEffectMask, false))
|
||||
return SPELL_FAILED_AURA_BOUNCED;
|
||||
}
|
||||
|
||||
// check trade slot case (last, for allow catch any another cast problems)
|
||||
|
|
@ -6973,26 +6978,35 @@ bool Spell::CanAutoCast(Unit* target)
|
|||
{
|
||||
ObjectGuid targetguid = target->GetGUID();
|
||||
|
||||
for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
||||
for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects())
|
||||
{
|
||||
if (m_spellInfo->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA)
|
||||
if (!spellEffectInfo.IsAura())
|
||||
continue;
|
||||
|
||||
AuraType const& auraType = spellEffectInfo.ApplyAuraName;
|
||||
Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(auraType);
|
||||
for (Unit::AuraEffectList::const_iterator auraIt = auras.begin(); auraIt != auras.end(); ++auraIt)
|
||||
{
|
||||
if (m_spellInfo->StackAmount <= 1)
|
||||
{
|
||||
if (target->HasAuraEffect(m_spellInfo->Id, j))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AuraEffect* aureff = target->GetAuraEffect(m_spellInfo->Id, j))
|
||||
if (aureff->GetBase()->GetStackAmount() >= m_spellInfo->StackAmount)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (m_spellInfo->Effects[j].IsAreaAuraEffect())
|
||||
{
|
||||
if (target->HasAuraEffect(m_spellInfo->Id, j))
|
||||
if (GetSpellInfo()->Id == (*auraIt)->GetSpellInfo()->Id)
|
||||
return false;
|
||||
|
||||
switch (sSpellMgr->CheckSpellGroupStackRules(GetSpellInfo(), (*auraIt)->GetSpellInfo()))
|
||||
{
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE:
|
||||
return false;
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER:
|
||||
if (GetCaster() == (*auraIt)->GetCaster())
|
||||
return false;
|
||||
break;
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT: // this one has further checks, but i don't think they're necessary for autocast logic
|
||||
case SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST:
|
||||
if (abs(spellEffectInfo.BasePoints) <= abs((*auraIt)->GetAmount()))
|
||||
return false;
|
||||
break;
|
||||
case SPELL_GROUP_STACK_RULE_DEFAULT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1952,13 +1952,10 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
|
|||
Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
|
||||
for (Unit::AuraApplicationMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
|
||||
{
|
||||
SpellGroupSpecialFlags sFlag = sSpellMgr->GetSpellGroupSpecialFlags(itr->second->GetBase()->GetId());
|
||||
if (!guardianFound)
|
||||
if (sFlag & SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN)
|
||||
guardianFound = true;
|
||||
if (!battleFound)
|
||||
if (sFlag & SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE)
|
||||
battleFound = true;
|
||||
if (!guardianFound && sSpellMgr->IsSpellMemberOfSpellGroup(itr->second->GetBase()->GetId(), SPELL_GROUP_ELIXIR_GUARDIAN))
|
||||
guardianFound = true;
|
||||
if (!battleFound && sSpellMgr->IsSpellMemberOfSpellGroup(itr->second->GetBase()->GetId(), SPELL_GROUP_ELIXIR_BATTLE))
|
||||
battleFound = true;
|
||||
if (battleFound && guardianFound)
|
||||
break;
|
||||
}
|
||||
|
|
@ -1966,9 +1963,9 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
|
|||
// get all available elixirs by mask and spell level
|
||||
std::set<uint32> availableElixirs;
|
||||
if (!guardianFound)
|
||||
sSpellMgr->GetSetOfSpellsInSpellGroupWithFlag(1, SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN, availableElixirs);
|
||||
sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_GUARDIAN, availableElixirs);
|
||||
if (!battleFound)
|
||||
sSpellMgr->GetSetOfSpellsInSpellGroupWithFlag(1, SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE, availableElixirs);
|
||||
sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, availableElixirs);
|
||||
for (std::set<uint32>::iterator itr = availableElixirs.begin(); itr != availableElixirs.end();)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(*itr);
|
||||
|
|
@ -3598,7 +3595,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
|
|||
unitMod = UNIT_MOD_DAMAGE_RANGED;
|
||||
break;
|
||||
}
|
||||
float weapon_total_pct = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
|
||||
float weapon_total_pct = m_caster->GetPctModifierValue(unitMod, TOTAL_PCT);
|
||||
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
|
||||
spell_bonus = int32(spell_bonus * weapon_total_pct);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,9 +326,9 @@ std::array<SpellImplicitTargetInfo::StaticData, TOTAL_SPELL_TARGETS> SpellImplic
|
|||
SpellEffectInfo::SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex)
|
||||
{
|
||||
_spellInfo = spellInfo;
|
||||
_effIndex = effIndex;
|
||||
EffectIndex = effIndex;
|
||||
Effect = spellEntry->Effect[effIndex];
|
||||
ApplyAuraName = spellEntry->EffectApplyAuraName[effIndex];
|
||||
ApplyAuraName = AuraType(spellEntry->EffectApplyAuraName[effIndex]);
|
||||
Amplitude = spellEntry->EffectAmplitude[effIndex];
|
||||
DieSides = spellEntry->EffectDieSides[effIndex];
|
||||
RealPointsPerLevel = spellEntry->EffectRealPointsPerLevel[effIndex];
|
||||
|
|
@ -456,7 +456,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
|
|||
value += PointsPerComboPoint * comboPoints;
|
||||
}
|
||||
|
||||
value = caster->ApplyEffectModifiers(_spellInfo, _effIndex, value);
|
||||
value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value);
|
||||
|
||||
// amount multiplication based on caster's level
|
||||
if (!caster->IsControlledByPlayer() &&
|
||||
|
|
@ -501,7 +501,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
|
|||
break;
|
||||
}
|
||||
|
||||
if ((sSpellMgr->GetSpellInfo(_spellInfo->Effects[_effIndex].TriggerSpell) && sSpellMgr->GetSpellInfo(_spellInfo->Effects[_effIndex].TriggerSpell)->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL)) && _spellInfo->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL))
|
||||
if ((sSpellMgr->GetSpellInfo(_spellInfo->Effects[EffectIndex].TriggerSpell) && sSpellMgr->GetSpellInfo(_spellInfo->Effects[EffectIndex].TriggerSpell)->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL)) && _spellInfo->HasAttribute(SPELL_ATTR0_SCALES_WITH_CREATURE_LEVEL))
|
||||
canEffectScale = false;
|
||||
|
||||
if (canEffectScale)
|
||||
|
|
@ -1579,122 +1579,6 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
|
|||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
bool SpellInfo::IsStrongerAuraActive(Unit const* caster, Unit const* target) const
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
// xinef: check spell group
|
||||
uint32 groupId = sSpellMgr->GetSpellGroup(Id);
|
||||
if (!groupId)
|
||||
return false;
|
||||
|
||||
SpellGroupSpecialFlags sFlag = sSpellMgr->GetSpellGroupSpecialFlags(Id);
|
||||
if (sFlag & SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_CHECK)
|
||||
return false;
|
||||
|
||||
for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
// xinef: Skip Empty effects
|
||||
if (!Effects[i].IsEffect())
|
||||
continue;
|
||||
|
||||
// xinef: if non-aura effect is preset - return false
|
||||
if (!Effects[i].IsAura())
|
||||
return false;
|
||||
|
||||
// xinef: aura is periodic - return false
|
||||
if (Effects[i].Amplitude)
|
||||
return false;
|
||||
|
||||
// xinef: exclude dummy auras
|
||||
if (Effects[i].ApplyAuraName == SPELL_AURA_DUMMY)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
// xinef: skip non-aura efects
|
||||
if (!Effects[i].IsAura())
|
||||
return false;
|
||||
|
||||
Unit::AuraEffectList const& auraList = target->GetAuraEffectsByType((AuraType)Effects[i].ApplyAuraName);
|
||||
for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter)
|
||||
{
|
||||
// xinef: aura is not groupped or in different group
|
||||
uint32 auraGroup = (*iter)->GetAuraGroup();
|
||||
if (!auraGroup || auraGroup != groupId)
|
||||
continue;
|
||||
|
||||
if (IsRankOf((*iter)->GetSpellInfo()) && (sFlag & SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_SAME_SPELL))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// xinef: check priority before effect mask
|
||||
if (sFlag >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && sFlag <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4)
|
||||
{
|
||||
SpellGroupSpecialFlags sFlagCurr = sSpellMgr->GetSpellGroupSpecialFlags((*iter)->GetId());
|
||||
if (sFlagCurr >= SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 && sFlagCurr <= SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 && sFlagCurr < sFlag)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// xinef: check aura effect equal auras only, some auras have different effects on different ranks - check rank also
|
||||
if (!IsAuraEffectEqual((*iter)->GetSpellInfo()) && !IsRankOf((*iter)->GetSpellInfo()))
|
||||
continue;
|
||||
|
||||
// xinef: misc value mismatches
|
||||
// xinef: commented, checked above
|
||||
//if (Effects[i].MiscValue != (*iter)->GetMiscValue())
|
||||
// continue;
|
||||
|
||||
// xinef: should not happen, or effect is not active - stronger one is present
|
||||
AuraApplication* aurApp = (*iter)->GetBase()->GetApplicationOfTarget(target->GetGUID());
|
||||
if (!aurApp || !aurApp->IsActive((*iter)->GetEffIndex()))
|
||||
continue;
|
||||
|
||||
// xinef: assume that all spells are either positive or negative, otherwise they should not be in one group
|
||||
// xinef: take custom values into account
|
||||
|
||||
int32 basePoints = Effects[i].BasePoints;
|
||||
int32 duration = GetMaxDuration();
|
||||
|
||||
// xinef: should have the same id, can be different if spell is triggered
|
||||
// xinef: have to fix spell mods for triggered spell, turn off current spellmodtakingspell for preparing and restore after
|
||||
if (Player const* player = caster->GetSpellModOwner())
|
||||
if (player->m_spellModTakingSpell && player->m_spellModTakingSpell->m_spellInfo->Id == Id)
|
||||
basePoints = player->m_spellModTakingSpell->GetSpellValue()->EffectBasePoints[i];
|
||||
|
||||
int32 curValue = std::abs(Effects[i].CalcValue(caster, &basePoints));
|
||||
int32 auraValue = (sFlag & SPELL_GROUP_SPECIAL_FLAG_BASE_AMOUNT_CHECK) ?
|
||||
std::abs((*iter)->GetSpellInfo()->Effects[(*iter)->GetEffIndex()].CalcValue((*iter)->GetCaster())) :
|
||||
std::abs((*iter)->GetAmount());
|
||||
|
||||
// xinef: for same spells, divide amount by stack amount
|
||||
if (Id == (*iter)->GetId())
|
||||
auraValue /= (*iter)->GetBase()->GetStackAmount();
|
||||
|
||||
if (curValue < auraValue)
|
||||
return true;
|
||||
|
||||
// xinef: little hack, if current spell is the same as aura spell, asume it is not stronger
|
||||
// xinef: if values are the same, duration mods should be taken into account but they are almost always passive
|
||||
if (curValue == auraValue)
|
||||
{
|
||||
if (Id == (*iter)->GetId())
|
||||
continue;
|
||||
if (!(*iter)->GetBase()->IsPassive() && duration < (*iter)->GetBase()->GetDuration())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpellInfo::IsAuraEffectEqual(SpellInfo const* otherSpellInfo) const
|
||||
{
|
||||
uint8 matchCount = 0;
|
||||
|
|
@ -1938,10 +1822,6 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
|
|||
if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW))
|
||||
return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED;
|
||||
|
||||
// xinef: check if stronger aura is active
|
||||
if (IsStrongerAuraActive(caster, unitTarget))
|
||||
return SPELL_FAILED_AURA_BOUNCED;
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2316,6 +2196,8 @@ SpellSpecificType SpellInfo::LoadSpellSpecific() const
|
|||
case SPELL_AURA_TRACK_RESOURCES:
|
||||
case SPELL_AURA_TRACK_STEALTHED:
|
||||
return SPELL_SPECIFIC_TRACKER;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2399,6 +2281,8 @@ uint32 SpellInfo::GetMaxTicks() const
|
|||
if (Effects[x].Amplitude != 0)
|
||||
return DotDuration / Effects[x].Amplitude;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2889,50 +2773,3 @@ void SpellInfo::_UnloadImplicitTargetConditionLists()
|
|||
delete cur;
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellInfo::CheckElixirStacking(Unit const* caster) const
|
||||
{
|
||||
if (!caster)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// xinef: check spell group
|
||||
uint32 groupId = sSpellMgr->GetSpellGroup(Id);
|
||||
if (groupId != SPELL_GROUP_GUARDIAN_AND_BATTLE_ELIXIRS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SpellGroupSpecialFlags sFlag = sSpellMgr->GetSpellGroupSpecialFlags(Id);
|
||||
for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
|
||||
{
|
||||
if (!Effects[i].IsAura())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Unit::AuraApplicationMap const& Auras = caster->GetAppliedAuras();
|
||||
for (Unit::AuraApplicationMap::const_iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
|
||||
{
|
||||
// xinef: aura is not groupped or in different group
|
||||
uint32 auraGroup = sSpellMgr->GetSpellGroup(itr->first);
|
||||
if (auraGroup != groupId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cannot apply guardian/battle elixir if flask is present
|
||||
if (sFlag == SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE || sFlag == SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN)
|
||||
{
|
||||
SpellGroupSpecialFlags sAuraFlag = sSpellMgr->GetSpellGroupSpecialFlags(itr->first);
|
||||
if ((sAuraFlag & SPELL_GROUP_SPECIAL_FLAG_FLASK) == SPELL_GROUP_SPECIAL_FLAG_FLASK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,10 +248,10 @@ private:
|
|||
class SpellEffectInfo
|
||||
{
|
||||
SpellInfo const* _spellInfo;
|
||||
uint8 _effIndex;
|
||||
public:
|
||||
uint8 EffectIndex;
|
||||
uint32 Effect;
|
||||
uint32 ApplyAuraName;
|
||||
AuraType ApplyAuraName;
|
||||
uint32 Amplitude;
|
||||
int32 DieSides;
|
||||
float RealPointsPerLevel;
|
||||
|
|
@ -272,7 +272,7 @@ public:
|
|||
flag96 SpellClassMask;
|
||||
std::list<Condition*>* ImplicitTargetConditions;
|
||||
|
||||
SpellEffectInfo() : _spellInfo(nullptr), _effIndex(0), Effect(0), ApplyAuraName(0), Amplitude(0), DieSides(0),
|
||||
SpellEffectInfo() : _spellInfo(nullptr), EffectIndex(0), Effect(0), ApplyAuraName(SPELL_AURA_NONE), Amplitude(0), DieSides(0),
|
||||
RealPointsPerLevel(0), BasePoints(0), PointsPerComboPoint(0), ValueMultiplier(0), DamageMultiplier(0),
|
||||
BonusMultiplier(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), RadiusEntry(nullptr), ChainTarget(0),
|
||||
ItemType(0), TriggerSpell(0), ImplicitTargetConditions(nullptr) {}
|
||||
|
|
@ -482,8 +482,6 @@ public:
|
|||
SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = nullptr) const;
|
||||
bool CheckTargetCreatureType(Unit const* target) const;
|
||||
|
||||
// xinef: aura stacking
|
||||
bool IsStrongerAuraActive(Unit const* caster, Unit const* target) const;
|
||||
bool IsAuraEffectEqual(SpellInfo const* otherSpellInfo) const;
|
||||
bool ValidateAttribute6SpellDamageMods(Unit const* caster, const AuraEffect* auraEffect, bool isDot) const;
|
||||
|
||||
|
|
@ -539,8 +537,6 @@ public:
|
|||
// unloading helpers
|
||||
void _UnloadImplicitTargetConditionLists();
|
||||
|
||||
bool CheckElixirStacking(Unit const* caster) const;
|
||||
|
||||
private:
|
||||
std::array<SpellEffectInfo, MAX_SPELL_EFFECTS>& _GetEffects() { return Effects; }
|
||||
SpellEffectInfo& _GetEffect(SpellEffIndex index) { ASSERT(index < Effects.size()); return Effects[index]; }
|
||||
|
|
|
|||
|
|
@ -570,14 +570,6 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||
spellInfo->AttributesEx3 |= SPELL_ATTR3_SUPPRESS_CASTER_PROCS;
|
||||
});
|
||||
|
||||
// Blessing of sanctuary stats
|
||||
ApplySpellFix({ 67480 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->Effects[EFFECT_0].MiscValue = -1;
|
||||
spellInfo->SpellFamilyName = SPELLFAMILY_UNK1; // allows stacking
|
||||
spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_DUMMY; // just a marker
|
||||
});
|
||||
|
||||
ApplySpellFix({
|
||||
6940, // Hand of Sacrifice
|
||||
64205 // Divine Sacrifice
|
||||
|
|
|
|||
|
|
@ -18,12 +18,9 @@
|
|||
#include "SpellMgr.h"
|
||||
#include "BattlefieldMgr.h"
|
||||
#include "BattlegroundIC.h"
|
||||
#include "BattlegroundMgr.h"
|
||||
#include "Chat.h"
|
||||
#include "DBCStores.h"
|
||||
#include "GameGraveyard.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "MapMgr.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
|
|
@ -648,82 +645,143 @@ SpellTargetPosition const* SpellMgr::GetSpellTargetPosition(uint32 spell_id, Spe
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
SpellGroupStackFlags SpellMgr::GetGroupStackFlags(uint32 groupid) const
|
||||
SpellSpellGroupMapBounds SpellMgr::GetSpellSpellGroupMapBounds(uint32 spell_id) const
|
||||
{
|
||||
SpellGroupStackMap::const_iterator itr = mSpellGroupStackMap.find(groupid);
|
||||
if (itr != mSpellGroupStackMap.end())
|
||||
spell_id = GetFirstSpellInChain(spell_id);
|
||||
return mSpellSpellGroup.equal_range(spell_id);
|
||||
}
|
||||
|
||||
bool SpellMgr::IsSpellMemberOfSpellGroup(uint32 spell_id, SpellGroup group_id) const
|
||||
{
|
||||
SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds(spell_id);
|
||||
for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second; ++itr)
|
||||
{
|
||||
if (itr->second == group_id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SpellGroupSpellMapBounds SpellMgr::GetSpellGroupSpellMapBounds(SpellGroup group_id) const
|
||||
{
|
||||
return mSpellGroupSpell.equal_range(group_id);
|
||||
}
|
||||
|
||||
void SpellMgr::GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells) const
|
||||
{
|
||||
std::set<SpellGroup> usedGroups;
|
||||
GetSetOfSpellsInSpellGroup(group_id, foundSpells, usedGroups);
|
||||
}
|
||||
|
||||
void SpellMgr::GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells, std::set<SpellGroup>& usedGroups) const
|
||||
{
|
||||
if (usedGroups.find(group_id) != usedGroups.end())
|
||||
return;
|
||||
usedGroups.insert(group_id);
|
||||
|
||||
SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds(group_id);
|
||||
for (SpellGroupSpellMap::const_iterator itr = groupSpell.first; itr != groupSpell.second; ++itr)
|
||||
{
|
||||
if (itr->second < 0)
|
||||
{
|
||||
SpellGroup currGroup = (SpellGroup)abs(itr->second);
|
||||
GetSetOfSpellsInSpellGroup(currGroup, foundSpells, usedGroups);
|
||||
}
|
||||
else
|
||||
{
|
||||
foundSpells.insert(itr->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SpellMgr::AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, uint32 auraType, int32 amount, std::map<SpellGroup, int32>& groups) const
|
||||
{
|
||||
uint32 spellId = spellInfo->GetFirstRankSpell()->Id;
|
||||
auto spellGroupBounds = GetSpellSpellGroupMapBounds(spellId);
|
||||
// Find group with SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT if it belongs to one
|
||||
for (auto itr = spellGroupBounds.first; itr != spellGroupBounds.second; ++itr)
|
||||
{
|
||||
SpellGroup group = itr->second;
|
||||
auto found = mSpellSameEffectStack.find(group);
|
||||
if (found != mSpellSameEffectStack.end())
|
||||
{
|
||||
// check auraTypes
|
||||
if (!found->second.count(auraType))
|
||||
continue;
|
||||
|
||||
// Put the highest amount in the map
|
||||
auto groupItr = groups.find(group);
|
||||
if (groupItr == groups.end())
|
||||
groups.emplace(group, amount);
|
||||
else
|
||||
{
|
||||
int32 curr_amount = groups[group];
|
||||
// Take absolute value because this also counts for the highest negative aura
|
||||
if (std::abs(curr_amount) < std::abs(amount))
|
||||
groupItr->second = amount;
|
||||
}
|
||||
// return because a spell should be in only one SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group per auraType
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Not in a SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group, so return false
|
||||
return false;
|
||||
}
|
||||
|
||||
SpellGroupStackRule SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const
|
||||
{
|
||||
ASSERT(spellInfo1);
|
||||
ASSERT(spellInfo2);
|
||||
|
||||
uint32 spell_id1 = spellInfo1->GetFirstRankSpell()->Id;
|
||||
uint32 spell_id2 = spellInfo2->GetFirstRankSpell()->Id;
|
||||
|
||||
// find SpellGroups which are common for both spells
|
||||
SpellSpellGroupMapBounds spellGroup1 = GetSpellSpellGroupMapBounds(spell_id1);
|
||||
std::set<SpellGroup> groups;
|
||||
for (SpellSpellGroupMap::const_iterator itr = spellGroup1.first; itr != spellGroup1.second; ++itr)
|
||||
{
|
||||
if (IsSpellMemberOfSpellGroup(spell_id2, itr->second))
|
||||
{
|
||||
bool add = true;
|
||||
SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds(itr->second);
|
||||
for (SpellGroupSpellMap::const_iterator itr2 = groupSpell.first; itr2 != groupSpell.second; ++itr2)
|
||||
{
|
||||
if (itr2->second < 0)
|
||||
{
|
||||
SpellGroup currGroup = (SpellGroup)abs(itr2->second);
|
||||
if (IsSpellMemberOfSpellGroup(spell_id1, currGroup) && IsSpellMemberOfSpellGroup(spell_id2, currGroup))
|
||||
{
|
||||
add = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (add)
|
||||
groups.insert(itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
SpellGroupStackRule rule = SPELL_GROUP_STACK_RULE_DEFAULT;
|
||||
|
||||
for (std::set<SpellGroup>::iterator itr = groups.begin(); itr!= groups.end(); ++itr)
|
||||
{
|
||||
SpellGroupStackMap::const_iterator found = mSpellGroupStack.find(*itr);
|
||||
if (found != mSpellGroupStack.end())
|
||||
rule = found->second;
|
||||
if (rule)
|
||||
break;
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
|
||||
SpellGroupStackRule SpellMgr::GetSpellGroupStackRule(SpellGroup group) const
|
||||
{
|
||||
SpellGroupStackMap::const_iterator itr = mSpellGroupStack.find(group);
|
||||
if (itr != mSpellGroupStack.end())
|
||||
return itr->second;
|
||||
|
||||
return SPELL_GROUP_STACK_FLAG_NONE;
|
||||
}
|
||||
|
||||
uint32 SpellMgr::GetSpellGroup(uint32 spell_id) const
|
||||
{
|
||||
uint32 first_rank = GetFirstSpellInChain(spell_id);
|
||||
SpellGroupMap::const_iterator itr = mSpellGroupMap.find(first_rank);
|
||||
if (itr != mSpellGroupMap.end())
|
||||
return itr->second.groupId;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SpellGroupSpecialFlags SpellMgr::GetSpellGroupSpecialFlags(uint32 spell_id) const
|
||||
{
|
||||
uint32 first_rank = GetFirstSpellInChain(spell_id);
|
||||
SpellGroupMap::const_iterator itr = mSpellGroupMap.find(first_rank);
|
||||
if (itr != mSpellGroupMap.end())
|
||||
return itr->second.specialFlags;
|
||||
|
||||
return SPELL_GROUP_SPECIAL_FLAG_NONE;
|
||||
}
|
||||
|
||||
SpellGroupStackFlags SpellMgr::CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2, bool remove, bool areaAura) const
|
||||
{
|
||||
uint32 spellid_1 = spellInfo1->GetFirstRankSpell()->Id;
|
||||
uint32 spellid_2 = spellInfo2->GetFirstRankSpell()->Id;
|
||||
|
||||
uint32 groupId = GetSpellGroup(spellid_1);
|
||||
|
||||
SpellGroupSpecialFlags flag1 = GetSpellGroupSpecialFlags(spellid_1);
|
||||
|
||||
// xinef: dunno why i added this
|
||||
if (spellid_1 == spellid_2 && remove && !areaAura)
|
||||
{
|
||||
if (flag1 & SPELL_GROUP_SPECIAL_FLAG_SAME_SPELL_CHECK)
|
||||
{
|
||||
return SPELL_GROUP_STACK_FLAG_EXCLUSIVE;
|
||||
}
|
||||
|
||||
return SPELL_GROUP_STACK_FLAG_NONE;
|
||||
}
|
||||
|
||||
if (groupId > 0 && groupId == GetSpellGroup(spellid_2))
|
||||
{
|
||||
SpellGroupSpecialFlags flag2 = GetSpellGroupSpecialFlags(spellid_2);
|
||||
SpellGroupStackFlags additionFlag = SPELL_GROUP_STACK_FLAG_NONE;
|
||||
// xinef: first flags are used for elixir stacking rules
|
||||
if (flag1 & SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX && flag2 & SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX)
|
||||
{
|
||||
if (flag1 & flag2)
|
||||
return SPELL_GROUP_STACK_FLAG_NEVER_STACK;
|
||||
}
|
||||
// xinef: check only flag1 (new spell)
|
||||
else if (flag1 & SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST)
|
||||
additionFlag = SPELL_GROUP_STACK_FLAG_FORCED_STRONGEST;
|
||||
else if (flag2 & SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST)
|
||||
additionFlag = SPELL_GROUP_STACK_FLAG_FORCED_WEAKEST;
|
||||
|
||||
return SpellGroupStackFlags(GetGroupStackFlags(groupId) | additionFlag);
|
||||
}
|
||||
|
||||
return SPELL_GROUP_STACK_FLAG_NONE;
|
||||
}
|
||||
|
||||
void SpellMgr::GetSetOfSpellsInSpellGroupWithFlag(uint32 group_id, SpellGroupSpecialFlags flag, std::set<uint32>& availableElixirs) const
|
||||
{
|
||||
for (SpellGroupMap::const_iterator itr = mSpellGroupMap.begin(); itr != mSpellGroupMap.end(); ++itr)
|
||||
if (itr->second.groupId == group_id && itr->second.specialFlags == flag)
|
||||
availableElixirs.insert(itr->first); // insert spell id
|
||||
return SPELL_GROUP_STACK_RULE_DEFAULT;
|
||||
}
|
||||
|
||||
SpellProcEventEntry const* SpellMgr::GetSpellProcEvent(uint32 spellId) const
|
||||
|
|
@ -1627,10 +1685,11 @@ void SpellMgr::LoadSpellGroups()
|
|||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
mSpellGroupMap.clear(); // need for reload case
|
||||
mSpellSpellGroup.clear(); // need for reload case
|
||||
mSpellGroupSpell.clear();
|
||||
|
||||
// 0 1 2
|
||||
QueryResult result = WorldDatabase.Query("SELECT id, spell_id, special_flag FROM spell_group");
|
||||
// 0 1
|
||||
QueryResult result = WorldDatabase.Query("SELECT id, spell_id FROM spell_group");
|
||||
if (!result)
|
||||
{
|
||||
LOG_WARN("server.loading", ">> Loaded 0 spell group definitions. DB table `spell_group` is empty.");
|
||||
|
|
@ -1638,48 +1697,68 @@ void SpellMgr::LoadSpellGroups()
|
|||
return;
|
||||
}
|
||||
|
||||
std::set<uint32> groups;
|
||||
uint32 count = 0;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 group_id = fields[0].Get<uint32>();
|
||||
int32 spell_id = fields[1].Get<uint32>();
|
||||
SpellGroupSpecialFlags specialFlag = (SpellGroupSpecialFlags)fields[2].Get<uint32>();
|
||||
SpellInfo const* spellInfo = GetSpellInfo(spell_id);
|
||||
|
||||
if (!spellInfo)
|
||||
if (group_id <= SPELL_GROUP_DB_RANGE_MIN && group_id >= SPELL_GROUP_CORE_RANGE_MAX)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` does not exist", spell_id);
|
||||
continue;
|
||||
}
|
||||
else if (spellInfo->GetRank() > 1)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` is not first rank of spell", spell_id);
|
||||
LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group` is in core range, but is not defined in core!", group_id);
|
||||
continue;
|
||||
}
|
||||
int32 spell_id = fields[1].Get<int32>();
|
||||
|
||||
if (mSpellGroupMap.find(spell_id) != mSpellGroupMap.end())
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` has more than one group", spell_id);
|
||||
continue;
|
||||
}
|
||||
groups.insert(group_id);
|
||||
mSpellGroupSpell.emplace(SpellGroup(group_id), spell_id);
|
||||
|
||||
if (specialFlag >= SPELL_GROUP_SPECIAL_FLAG_MAX)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` has invalid special flag!", spell_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
SpellStackInfo ssi;
|
||||
ssi.groupId = group_id;
|
||||
ssi.specialFlags = specialFlag;
|
||||
mSpellGroupMap[spell_id] = ssi;
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} Spell Group Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
for (auto itr = mSpellGroupSpell.begin(); itr!= mSpellGroupSpell.end();)
|
||||
{
|
||||
if (itr->second < 0)
|
||||
{
|
||||
if (groups.find(abs(itr->second)) == groups.end())
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group` does not exist", abs(itr->second));
|
||||
itr = mSpellGroupSpell.erase(itr);
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
else
|
||||
{
|
||||
SpellInfo const* spellInfo = GetSpellInfo(itr->second);
|
||||
if (!spellInfo)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` does not exist", itr->second);
|
||||
itr = mSpellGroupSpell.erase(itr);
|
||||
}
|
||||
else if (spellInfo->GetRank() > 1)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Spell {} listed in `spell_group` is not first rank of spell.", itr->second);
|
||||
itr = mSpellGroupSpell.erase(itr);
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto groupItr = groups.begin(); groupItr != groups.end(); ++groupItr)
|
||||
{
|
||||
std::set<uint32> spells;
|
||||
GetSetOfSpellsInSpellGroup(SpellGroup(*groupItr), spells);
|
||||
|
||||
for (auto spellItr = spells.begin(); spellItr != spells.end(); ++spellItr)
|
||||
{
|
||||
++count;
|
||||
mSpellSpellGroup.emplace(*spellItr, SpellGroup(*groupItr));
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} spell group Definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
|
|
@ -1687,7 +1766,10 @@ void SpellMgr::LoadSpellGroupStackRules()
|
|||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
mSpellGroupStackMap.clear(); // need for reload case
|
||||
mSpellGroupStack.clear(); // need for reload case
|
||||
mSpellSameEffectStack.clear();
|
||||
|
||||
std::vector<uint32> sameEffectGroups;
|
||||
|
||||
// 0 1
|
||||
QueryResult result = WorldDatabase.Query("SELECT group_id, stack_rule FROM spell_group_stack_rules");
|
||||
|
|
@ -1705,32 +1787,132 @@ void SpellMgr::LoadSpellGroupStackRules()
|
|||
|
||||
uint32 group_id = fields[0].Get<uint32>();
|
||||
uint8 stack_rule = fields[1].Get<int8>();
|
||||
if (stack_rule >= SPELL_GROUP_STACK_FLAG_MAX)
|
||||
if (stack_rule >= SPELL_GROUP_STACK_RULE_MAX)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SpellGroupStackRule {} listed in `spell_group_stack_rules` does not exist", stack_rule);
|
||||
LOG_ERROR("sql.sql", "SpellGroupStackRule {} listed in `spell_group_stack_rules` does not exist.", stack_rule);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool present = false;
|
||||
for (SpellGroupMap::const_iterator itr = mSpellGroupMap.begin(); itr != mSpellGroupMap.end(); ++itr)
|
||||
if (itr->second.groupId == group_id)
|
||||
{
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!present)
|
||||
auto bounds = GetSpellGroupSpellMapBounds((SpellGroup)group_id);
|
||||
if (bounds.first == bounds.second)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group_stack_rules` does not exist", group_id);
|
||||
LOG_ERROR("sql.sql", "SpellGroup id {} listed in `spell_group_stack_rules` does not exist.", group_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
mSpellGroupStackMap[group_id] = (SpellGroupStackFlags)stack_rule;
|
||||
mSpellGroupStack.emplace(SpellGroup(group_id), SpellGroupStackRule(stack_rule));
|
||||
|
||||
// different container for same effect stack rules, need to check effect types
|
||||
if (stack_rule == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT)
|
||||
sameEffectGroups.push_back(group_id);
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} Spell Group Stack Rules in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", ">> Loaded {} spell group stack rules in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
|
||||
count = 0;
|
||||
oldMSTime = getMSTime();
|
||||
|
||||
for (uint32 group_id : sameEffectGroups)
|
||||
{
|
||||
std::set<uint32> spellIds;
|
||||
GetSetOfSpellsInSpellGroup(SpellGroup(group_id), spellIds);
|
||||
|
||||
std::unordered_set<uint32> auraTypes;
|
||||
|
||||
// we have to 'guess' what effect this group corresponds to
|
||||
{
|
||||
std::unordered_multiset<uint32 /*auraName*/> frequencyContainer;
|
||||
|
||||
// only waylay for the moment (shared group)
|
||||
std::vector<std::vector<uint32 /*auraName*/>> const SubGroups =
|
||||
{
|
||||
{ SPELL_AURA_MOD_MELEE_HASTE, SPELL_AURA_MOD_MELEE_RANGED_HASTE, SPELL_AURA_MOD_RANGED_HASTE }
|
||||
};
|
||||
|
||||
for (uint32 spellId : spellIds)
|
||||
{
|
||||
SpellInfo const* spellInfo = AssertSpellInfo(spellId);
|
||||
for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
|
||||
{
|
||||
if (!spellEffectInfo.IsAura())
|
||||
continue;
|
||||
|
||||
uint32 auraName = spellEffectInfo.ApplyAuraName;
|
||||
for (std::vector<uint32> const& subGroup : SubGroups)
|
||||
{
|
||||
if (std::find(subGroup.begin(), subGroup.end(), auraName) != subGroup.end())
|
||||
{
|
||||
// count as first aura
|
||||
auraName = subGroup.front();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frequencyContainer.insert(auraName);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 auraType = 0;
|
||||
size_t auraTypeCount = 0;
|
||||
for (uint32 auraName : frequencyContainer)
|
||||
{
|
||||
size_t currentCount = frequencyContainer.count(auraName);
|
||||
if (currentCount > auraTypeCount)
|
||||
{
|
||||
auraType = auraName;
|
||||
auraTypeCount = currentCount;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<uint32> const& subGroup : SubGroups)
|
||||
{
|
||||
if (auraType == subGroup.front())
|
||||
{
|
||||
auraTypes.insert(subGroup.begin(), subGroup.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (auraTypes.empty())
|
||||
auraTypes.insert(auraType);
|
||||
}
|
||||
|
||||
// re-check spells against guessed group
|
||||
for (uint32 spellId : spellIds)
|
||||
{
|
||||
SpellInfo const* spellInfo = AssertSpellInfo(spellId);
|
||||
|
||||
bool found = false;
|
||||
while (spellInfo)
|
||||
{
|
||||
for (uint32 auraType : auraTypes)
|
||||
{
|
||||
if (spellInfo->HasAura(AuraType(auraType)))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
break;
|
||||
|
||||
spellInfo = spellInfo->GetNextRankSpell();
|
||||
}
|
||||
|
||||
// not found either, log error
|
||||
if (!found)
|
||||
LOG_ERROR("sql.sql", "SpellId {} listed in `spell_group` with stack rule 3 does not share aura assigned for group {}", spellId, group_id);
|
||||
}
|
||||
|
||||
mSpellSameEffectStack[SpellGroup(group_id)] = auraTypes;
|
||||
++count;
|
||||
}
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT stack rules in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server.loading", " ");
|
||||
}
|
||||
|
||||
|
|
@ -2920,6 +3102,8 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
|
|||
case SPELL_AURA_WATER_BREATHING:
|
||||
spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (spellInfo->Effects[j].ApplyAuraName)
|
||||
|
|
@ -3494,6 +3678,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
|
|||
if (triggerSpell->AttributesCu & SPELL_ATTR0_CU_BINARY_SPELL)
|
||||
allNonBinary = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
// For static or at-server-startup loaded spell data
|
||||
|
||||
#include "Common.h"
|
||||
#include "Log.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "Unit.h"
|
||||
|
|
@ -330,56 +329,49 @@ struct SpellBonusEntry
|
|||
|
||||
typedef std::unordered_map<uint32, SpellBonusEntry> SpellBonusMap;
|
||||
|
||||
enum SpellGroupSpecialFlags
|
||||
enum SpellGroup
|
||||
{
|
||||
SPELL_GROUP_SPECIAL_FLAG_NONE = 0x000,
|
||||
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE = 0x001,
|
||||
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN = 0x002,
|
||||
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_UNSTABLE = 0x004,
|
||||
SPELL_GROUP_SPECIAL_FLAG_ELIXIR_SHATTRATH = 0x008,
|
||||
SPELL_GROUP_SPECIAL_FLAG_STACK_EXCLUSIVE_MAX = 0x00F,
|
||||
SPELL_GROUP_SPECIAL_FLAG_FORCED_STRONGEST = 0x010, // xinef: specially helpful flag if some spells have different auras, but only one should be present
|
||||
SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_CHECK = 0x020,
|
||||
SPELL_GROUP_SPECIAL_FLAG_BASE_AMOUNT_CHECK = 0x040,
|
||||
SPELL_GROUP_SPECIAL_FLAG_PRIORITY1 = 0x100,
|
||||
SPELL_GROUP_SPECIAL_FLAG_PRIORITY2 = 0x200,
|
||||
SPELL_GROUP_SPECIAL_FLAG_PRIORITY3 = 0x400,
|
||||
SPELL_GROUP_SPECIAL_FLAG_PRIORITY4 = 0x800,
|
||||
SPELL_GROUP_SPECIAL_FLAG_SAME_SPELL_CHECK = 0x1000,
|
||||
SPELL_GROUP_SPECIAL_FLAG_SKIP_STRONGER_SAME_SPELL = 0x2000,
|
||||
SPELL_GROUP_SPECIAL_FLAG_MAX = 0x4000,
|
||||
|
||||
SPELL_GROUP_SPECIAL_FLAG_FLASK = SPELL_GROUP_SPECIAL_FLAG_ELIXIR_BATTLE | SPELL_GROUP_SPECIAL_FLAG_ELIXIR_GUARDIAN
|
||||
SPELL_GROUP_NONE = 0,
|
||||
SPELL_GROUP_ELIXIR_BATTLE = 1,
|
||||
SPELL_GROUP_ELIXIR_GUARDIAN = 2,
|
||||
SPELL_GROUP_CORE_RANGE_MAX = 3
|
||||
};
|
||||
|
||||
enum SpellGroupStackFlags
|
||||
namespace std
|
||||
{
|
||||
SPELL_GROUP_STACK_FLAG_NONE = 0x00,
|
||||
SPELL_GROUP_STACK_FLAG_EXCLUSIVE = 0x01,
|
||||
SPELL_GROUP_STACK_FLAG_NOT_SAME_CASTER = 0x02,
|
||||
SPELL_GROUP_STACK_FLAG_FLAGGED = 0x04, // xinef: just a marker
|
||||
SPELL_GROUP_STACK_FLAG_NEVER_STACK = 0x08,
|
||||
SPELL_GROUP_STACK_FLAG_EFFECT_EXCLUSIVE = 0x10,
|
||||
SPELL_GROUP_STACK_FLAG_MAX = 0x20,
|
||||
template<>
|
||||
struct hash<SpellGroup>
|
||||
{
|
||||
size_t operator()(SpellGroup const& group) const
|
||||
{
|
||||
return hash<uint32>()(uint32(group));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Internal use
|
||||
SPELL_GROUP_STACK_FLAG_FORCED_STRONGEST = 0x100,
|
||||
SPELL_GROUP_STACK_FLAG_FORCED_WEAKEST = 0x200,
|
||||
#define SPELL_GROUP_DB_RANGE_MIN 1000
|
||||
|
||||
// spell_id, group_id
|
||||
typedef std::unordered_multimap<uint32, SpellGroup> SpellSpellGroupMap;
|
||||
typedef std::pair<SpellSpellGroupMap::const_iterator, SpellSpellGroupMap::const_iterator> SpellSpellGroupMapBounds;
|
||||
|
||||
// group_id, spell_id
|
||||
typedef std::unordered_multimap<SpellGroup, int32> SpellGroupSpellMap;
|
||||
typedef std::pair<SpellGroupSpellMap::const_iterator, SpellGroupSpellMap::const_iterator> SpellGroupSpellMapBounds;
|
||||
|
||||
enum SpellGroupStackRule
|
||||
{
|
||||
SPELL_GROUP_STACK_RULE_DEFAULT,
|
||||
SPELL_GROUP_STACK_RULE_EXCLUSIVE,
|
||||
SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER,
|
||||
SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT,
|
||||
SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST,
|
||||
SPELL_GROUP_STACK_RULE_MAX
|
||||
};
|
||||
|
||||
enum SpellGroupIDs
|
||||
{
|
||||
SPELL_GROUP_GUARDIAN_AND_BATTLE_ELIXIRS = 1
|
||||
};
|
||||
typedef std::unordered_map<SpellGroup, SpellGroupStackRule> SpellGroupStackMap;
|
||||
|
||||
struct SpellStackInfo
|
||||
{
|
||||
uint32 groupId;
|
||||
SpellGroupSpecialFlags specialFlags;
|
||||
};
|
||||
// spell_id, group_id
|
||||
typedef std::map<uint32, SpellStackInfo> SpellGroupMap;
|
||||
typedef std::map<uint32, SpellGroupStackFlags> SpellGroupStackMap;
|
||||
typedef std::unordered_map<SpellGroup, std::unordered_set<uint32 /*auraName*/>> SameEffectStackMap;
|
||||
|
||||
struct SpellThreatEntry
|
||||
{
|
||||
|
|
@ -679,12 +671,18 @@ public:
|
|||
// Spell target coordinates
|
||||
[[nodiscard]] SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id, SpellEffIndex effIndex) const;
|
||||
|
||||
// Spell Groups
|
||||
[[nodiscard]] uint32 GetSpellGroup(uint32 spellid) const;
|
||||
[[nodiscard]] SpellGroupSpecialFlags GetSpellGroupSpecialFlags(uint32 spell_id) const;
|
||||
[[nodiscard]] SpellGroupStackFlags GetGroupStackFlags(uint32 groupid) const;
|
||||
SpellGroupStackFlags CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2, bool remove, bool areaAura) const;
|
||||
void GetSetOfSpellsInSpellGroupWithFlag(uint32 group_id, SpellGroupSpecialFlags flag, std::set<uint32>& availableElixirs) const;
|
||||
// Spell Groups table
|
||||
SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const;
|
||||
bool IsSpellMemberOfSpellGroup(uint32 spell_id, SpellGroup group_id) const;
|
||||
|
||||
SpellGroupSpellMapBounds GetSpellGroupSpellMapBounds(SpellGroup group_id) const;
|
||||
void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells) const;
|
||||
void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells, std::set<SpellGroup>& usedGroups) const;
|
||||
|
||||
// Spell Group Stack Rules table
|
||||
bool AddSameEffectStackRuleSpellGroups(SpellInfo const* spellInfo, uint32 auraType, int32 amount, std::map<SpellGroup, int32>& groups) const;
|
||||
SpellGroupStackRule CheckSpellGroupStackRules(SpellInfo const* spellInfo1, SpellInfo const* spellInfo2) const;
|
||||
SpellGroupStackRule GetSpellGroupStackRule(SpellGroup group_id) const;
|
||||
|
||||
// Spell proc event table
|
||||
[[nodiscard]] SpellProcEventEntry const* GetSpellProcEvent(uint32 spellId) const;
|
||||
|
|
@ -798,8 +796,10 @@ private:
|
|||
SpellRequiredMap mSpellReq;
|
||||
SpellLearnSkillMap mSpellLearnSkills;
|
||||
SpellTargetPositionMap mSpellTargetPositions;
|
||||
SpellGroupMap mSpellGroupMap;
|
||||
SpellGroupStackMap mSpellGroupStackMap;
|
||||
SpellSpellGroupMap mSpellSpellGroup;
|
||||
SpellGroupSpellMap mSpellGroupSpell;
|
||||
SpellGroupStackMap mSpellGroupStack;
|
||||
SameEffectStackMap mSpellSameEffectStack;
|
||||
SpellProcEventMap mSpellProcEventMap;
|
||||
SpellProcMap mSpellProcMap;
|
||||
SpellBonusMap mSpellBonusMap;
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ Position const PosMoveOnSpawn[1] =
|
|||
{ -11561.9f, -1627.868f, 41.29941f, 0.0f }
|
||||
};
|
||||
|
||||
// hack
|
||||
float const DamageIncrease = 35.0f;
|
||||
float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f;
|
||||
|
||||
class boss_arlokk : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
|
@ -90,7 +94,7 @@ public:
|
|||
void Reset() override
|
||||
{
|
||||
if (events.IsInPhase(PHASE_TWO))
|
||||
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
|
||||
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack
|
||||
_Reset();
|
||||
_summonCountA = 0;
|
||||
_summonCountB = 0;
|
||||
|
|
@ -253,7 +257,7 @@ public:
|
|||
events.ScheduleEvent(EVENT_RAVAGE, 10s, 14s, 0, PHASE_TWO);
|
||||
events.ScheduleEvent(EVENT_TRANSFORM_BACK, 30s, 40s, 0, PHASE_TWO);
|
||||
events.SetPhase(PHASE_TWO);
|
||||
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true); // hack
|
||||
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); // hack
|
||||
break;
|
||||
case EVENT_RAVAGE:
|
||||
DoCastVictim(SPELL_RAVAGE, true);
|
||||
|
|
@ -265,7 +269,7 @@ public:
|
|||
DoCast(me, SPELL_VANISH_VISUAL);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_DAGGER));
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(WEAPON_DAGGER));
|
||||
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false); // hack
|
||||
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease); // hack
|
||||
events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 4s, 7s, 0, PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_GOUGE, 12s, 15s, 0, PHASE_ONE);
|
||||
events.ScheduleEvent(EVENT_TRANSFORM, 30s, 0, PHASE_ONE);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ enum Misc
|
|||
GO_SPIDER_EGGS = 179985,
|
||||
};
|
||||
|
||||
// hack
|
||||
float const DamageIncrease = 35.0f;
|
||||
float const DamageDecrease = 100.f / (1.f + DamageIncrease / 100.f) - 100.f;
|
||||
|
||||
// High Priestess Mar'li (14510)
|
||||
struct boss_marli : public BossAI
|
||||
{
|
||||
|
|
@ -84,7 +88,7 @@ public:
|
|||
if (_phase == PHASE_SPIDER)
|
||||
{
|
||||
me->RemoveAura(SPELL_SPIDER_FORM);
|
||||
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false);
|
||||
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease);
|
||||
_phase = PHASE_TROLL;
|
||||
}
|
||||
|
||||
|
|
@ -143,7 +147,7 @@ private:
|
|||
me->RemoveAura(SPELL_SPIDER_FORM);
|
||||
DoCastSelf(SPELL_TRANSFORM_BACK, true);
|
||||
Talk(SAY_TRANSFORM_BACK);
|
||||
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, false);
|
||||
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageDecrease);
|
||||
|
||||
scheduler.CancelGroup(PHASE_SPIDER);
|
||||
}
|
||||
|
|
@ -186,7 +190,7 @@ private:
|
|||
|
||||
Talk(SAY_TRANSFORM);
|
||||
DoCastSelf(SPELL_SPIDER_FORM, true);
|
||||
me->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, 35.0f, true);
|
||||
me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease);
|
||||
|
||||
scheduler.Schedule(5s, PHASE_SPIDER, [this](TaskContext context)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2037,7 +2037,7 @@ public:
|
|||
npc_toc_enh_shamanAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_MELEE)
|
||||
{
|
||||
SetEquipmentSlots(false, 51803, 48013, EQUIP_NO_CHANGE);
|
||||
me->SetModifierValue(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f);
|
||||
me->SetStatPctModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f);
|
||||
me->UpdateDamagePhysical(OFF_ATTACK);
|
||||
|
||||
events.Reset();
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ struct boss_twin_valkyrAI : public ScriptedAI
|
|||
{
|
||||
pInstance = pCreature->GetInstanceScript();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetModifierValue(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f);
|
||||
me->SetStatPctModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, 1.0f);
|
||||
me->UpdateDamagePhysical(OFF_ATTACK);
|
||||
LastSynchroHP = (int32)me->GetMaxHealth();
|
||||
SpecialMask = 0;
|
||||
|
|
|
|||
|
|
@ -271,12 +271,12 @@ class spell_astromancer_solarian_transform : public AuraScript
|
|||
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetUnitOwner()->HandleStatModifier(UnitMods(UNIT_MOD_ARMOR), TOTAL_PCT, 400.0f, true);
|
||||
GetUnitOwner()->ApplyStatPctModifier(UNIT_MOD_ARMOR, TOTAL_PCT, 400.0f);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetUnitOwner()->HandleStatModifier(UnitMods(UNIT_MOD_ARMOR), TOTAL_PCT, 400.0f, false);
|
||||
GetUnitOwner()->ApplyStatPctModifier(UnitMods(UNIT_MOD_ARMOR), TOTAL_PCT, -80.0f);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ struct npc_pet_hunter_snake_trap : public ScriptedAI
|
|||
|
||||
uint32 health = uint32(107 * (me->GetLevel() - 40) * 0.025f);
|
||||
me->SetCreateHealth(health);
|
||||
me->SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
|
||||
me->SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
|
||||
me->SetMaxHealth(health);
|
||||
|
||||
//Add delta to make them not all hit the same time
|
||||
|
|
|
|||
|
|
@ -174,8 +174,8 @@ class spell_dk_raise_ally : public SpellScript
|
|||
if (pInfo) // exist in DB
|
||||
{
|
||||
ghoul->SetCreateHealth(pInfo->health);
|
||||
ghoul->SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, pInfo->health);
|
||||
ghoul->SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
|
||||
ghoul->SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, pInfo->health);
|
||||
ghoul->SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
|
||||
for (uint8 stat = 0; stat < MAX_STATS; ++stat)
|
||||
ghoul->SetCreateStat(Stats(stat), float(pInfo->stats[stat]));
|
||||
}
|
||||
|
|
@ -194,9 +194,9 @@ class spell_dk_raise_ally : public SpellScript
|
|||
|
||||
// DK Ghoul haste refresh
|
||||
float val = (GetCaster()->m_modAttackSpeedPct[BASE_ATTACK] - 1.0f) * 100.0f;
|
||||
val *= 2000.0f + 2000.0f * ((100.0f + val) / 100.0f);
|
||||
ghoul->m_modAttackSpeedPct[BASE_ATTACK] = GetCaster()->m_modAttackSpeedPct[BASE_ATTACK];
|
||||
ghoul->SetFloatValue(UNIT_FIELD_BASEATTACKTIME, 2000.0f);
|
||||
ghoul->ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME, val, true); // we want to reduce attack time
|
||||
ghoul->SetFloatValue(UNIT_FIELD_BASEATTACKTIME, val);
|
||||
|
||||
// Strength + Stamina
|
||||
for (uint8 i = STAT_STRENGTH; i <= STAT_STAMINA; ++i)
|
||||
|
|
@ -223,20 +223,20 @@ class spell_dk_raise_ally : public SpellScript
|
|||
value = float(GetCaster()->GetStat(stat)) * mod;
|
||||
value = ghoul->GetTotalStatValue(stat, value);
|
||||
ghoul->SetStat(stat, int32(value));
|
||||
ghoul->ApplyStatBuffMod(stat, value, true);
|
||||
ghoul->UpdateStatBuffMod(stat);
|
||||
}
|
||||
|
||||
// Attack Power
|
||||
ghoul->SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, 589 + ghoul->GetStat(STAT_STRENGTH) + ghoul->GetStat(STAT_AGILITY));
|
||||
ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT));
|
||||
ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE));
|
||||
ghoul->SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, ghoul->GetModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_PCT) - 1.0f);
|
||||
ghoul->SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, 589 + ghoul->GetStat(STAT_STRENGTH) + ghoul->GetStat(STAT_AGILITY));
|
||||
ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)ghoul->GetFlatModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * ghoul->GetPctModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT));
|
||||
ghoul->SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)ghoul->GetFlatModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE));
|
||||
ghoul->SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, ghoul->GetPctModifierValue(UNIT_MOD_ATTACK_POWER, TOTAL_PCT) - 1.0f);
|
||||
|
||||
// Health
|
||||
ghoul->SetModifierValue(UNIT_MOD_HEALTH, TOTAL_VALUE, (ghoul->GetStat(STAT_STAMINA) - ghoul->GetCreateStat(STAT_STAMINA)) * 10.0f);
|
||||
ghoul->SetStatFlatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, (ghoul->GetStat(STAT_STAMINA) - ghoul->GetCreateStat(STAT_STAMINA)) * 10.0f);
|
||||
|
||||
// Power Energy
|
||||
ghoul->SetModifierValue(UnitMods(UNIT_MOD_POWER_START + static_cast<uint8>(POWER_ENERGY)), BASE_VALUE, ghoul->GetCreatePowers(POWER_ENERGY));
|
||||
ghoul->SetStatFlatModifier(UnitMods(UNIT_MOD_POWER_START + static_cast<uint8>(POWER_ENERGY)), BASE_VALUE, ghoul->GetCreatePowers(POWER_ENERGY));
|
||||
ghoul->UpdateAllStats();
|
||||
ghoul->SetFullHealth();
|
||||
|
||||
|
|
|
|||
|
|
@ -473,11 +473,7 @@ class spell_pal_blessing_of_sanctuary : public AuraScript
|
|||
{
|
||||
Unit* target = GetTarget();
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
// xinef: hack
|
||||
int32 value = 9;
|
||||
caster->CastCustomSpell(target, SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF, &value, &value, 0, true);
|
||||
}
|
||||
caster->CastSpell(target, SPELL_PALADIN_BLESSING_OF_SANCTUARY_BUFF, true);
|
||||
}
|
||||
|
||||
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "AreaDefines.h"
|
||||
#include "CreatureScript.h"
|
||||
#include "Pet.h"
|
||||
#include "PetDefines.h"
|
||||
#include "Player.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellInfo.h"
|
||||
|
|
@ -25,6 +26,8 @@
|
|||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "Unit.h"
|
||||
#include "Util.h"
|
||||
/*
|
||||
* Scripts for spells with SPELLFAMILY_WARLOCK and SPELLFAMILY_GENERIC spells used by warlock players.
|
||||
* Ordered alphabetically using scriptname.
|
||||
|
|
@ -73,6 +76,7 @@ enum WarlockSpells
|
|||
SPELL_WARLOCK_EYE_OF_KILROGG_FLY = 58083,
|
||||
SPELL_WARLOCK_PET_VOID_STAR_TALISMAN = 37386, // Void Star Talisman
|
||||
SPELL_WARLOCK_DEMONIC_PACT_PROC = 48090,
|
||||
SPELL_WARLOCK_GLYPH_OF_VOIDWALKER = 56247,
|
||||
};
|
||||
|
||||
enum WarlockSpellIcons
|
||||
|
|
@ -292,7 +296,7 @@ class spell_warl_generic_scaling : public AuraScript
|
|||
|
||||
void CalculateResistanceAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
// xinef: pet inherits 40% of resistance from owner and 35% of armor
|
||||
// pet inherits 40% of resistance from owner and 35% of armor
|
||||
if (Unit* owner = GetUnitOwner()->GetOwner())
|
||||
{
|
||||
SpellSchoolMask schoolMask = SpellSchoolMask(aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].MiscValue);
|
||||
|
|
@ -308,7 +312,7 @@ class spell_warl_generic_scaling : public AuraScript
|
|||
|
||||
void CalculateStatAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
// xinef: by default warlock pet inherits 75% of stamina and 30% of intellect
|
||||
// by default warlock pet inherits 75% of stamina and 30% of intellect
|
||||
if (Unit* owner = GetUnitOwner()->GetOwner())
|
||||
{
|
||||
Stats stat = Stats(aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].MiscValue);
|
||||
|
|
@ -317,21 +321,33 @@ class spell_warl_generic_scaling : public AuraScript
|
|||
}
|
||||
}
|
||||
|
||||
void CalculateAPAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
void CalculateAPAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
// xinef: by default warlock pet inherits 57% of max(SP FIRE, SP SHADOW) as AP
|
||||
if (Unit* owner = GetUnitOwner()->GetOwner())
|
||||
if (Unit* pet = GetUnitOwner())
|
||||
{
|
||||
int32 fire = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE);
|
||||
int32 shadow = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW);
|
||||
int32 maximum = (fire > shadow) ? fire : shadow;
|
||||
amount = CalculatePct(std::max<int32>(0, maximum), 57);
|
||||
// by default warlock pet inherits 57% of max(SP FIRE, SP SHADOW) as AP
|
||||
if (Unit* owner = pet->GetOwner())
|
||||
{
|
||||
int32 fire = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE);
|
||||
int32 shadow = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW);
|
||||
int32 maximum = (fire > shadow) ? fire : shadow;
|
||||
amount = CalculatePct(std::max<int32>(0, maximum), 57);
|
||||
|
||||
// Glyph of felguard, 99% sure this is a HACK
|
||||
if (pet->GetEntry() == NPC_FELGUARD)
|
||||
{
|
||||
if (AuraEffect* glyph = owner->GetAuraEffect(SPELL_GLYPH_OF_FELGUARD, EFFECT_0))
|
||||
{
|
||||
amount += CalculatePct(pet->GetTotalAuraModValue(UNIT_MOD_ATTACK_POWER) - aurEff->GetAmount() + amount, glyph->GetAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalculateSPAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
// xinef: by default warlock pet inherits 15% of max(SP FIRE, SP SHADOW) as SP
|
||||
// by default warlock pet inherits 15% of max(SP FIRE, SP SHADOW) as SP
|
||||
if (Unit* owner = GetUnitOwner()->GetOwner())
|
||||
{
|
||||
int32 fire = owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE);
|
||||
|
|
@ -339,7 +355,7 @@ class spell_warl_generic_scaling : public AuraScript
|
|||
int32 maximum = (fire > shadow) ? fire : shadow;
|
||||
amount = CalculatePct(std::max<int32>(0, maximum), 15);
|
||||
|
||||
// xinef: Update appropriate player field
|
||||
// Update appropriate player field
|
||||
if (owner->IsPlayer())
|
||||
owner->SetUInt32Value(PLAYER_PET_SPELL_POWER, (uint32)amount);
|
||||
}
|
||||
|
|
@ -1370,81 +1386,27 @@ class spell_warl_shadowburn : public AuraScript
|
|||
}
|
||||
};
|
||||
|
||||
class spell_warl_glyph_of_felguard : public AuraScript
|
||||
class spell_warl_voidwalker_pet_passive : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_warl_glyph_of_felguard);
|
||||
PrepareAuraScript(spell_warl_voidwalker_pet_passive);
|
||||
|
||||
void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
if (Player* player = GetCaster()->ToPlayer())
|
||||
{
|
||||
if (Pet* pet = player->GetPet())
|
||||
{
|
||||
if (pet->GetEntry() == NPC_FELGUARD)
|
||||
{
|
||||
pet->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ValidateSpellInfo({ SPELL_WARLOCK_GLYPH_OF_VOIDWALKER });
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
void CalculateAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
if (Player* player = GetCaster()->ToPlayer())
|
||||
{
|
||||
if (Pet* pet = player->GetPet())
|
||||
{
|
||||
if (pet->GetEntry() == NPC_FELGUARD)
|
||||
{
|
||||
pet->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, aurEff->GetAmount(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Unit* pet = GetUnitOwner())
|
||||
if (pet->IsPet())
|
||||
if (Unit* owner = pet->ToPet()->GetOwner())
|
||||
if (AuraEffect* aurEff = owner->GetAuraEffect(SPELL_WARLOCK_GLYPH_OF_VOIDWALKER, EFFECT_0))
|
||||
amount += aurEff->GetAmount();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_warl_glyph_of_felguard::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_warl_glyph_of_felguard::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_warl_glyph_of_voidwalker : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_warl_glyph_of_voidwalker);
|
||||
|
||||
void HandleApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* player = GetCaster()->ToPlayer())
|
||||
{
|
||||
if (Pet* pet = player->GetPet())
|
||||
{
|
||||
if (pet->GetEntry() == NPC_VOIDWALKER)
|
||||
{
|
||||
pet->HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_PCT, aurEff->GetAmount(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* player = GetCaster()->ToPlayer())
|
||||
{
|
||||
if (Pet* pet = player->GetPet())
|
||||
{
|
||||
if (pet->GetEntry() == NPC_VOIDWALKER)
|
||||
{
|
||||
pet->HandleStatModifier(UNIT_MOD_STAT_STAMINA, TOTAL_PCT, aurEff->GetAmount(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_warl_glyph_of_voidwalker::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_warl_glyph_of_voidwalker::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_voidwalker_pet_passive::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1529,7 +1491,6 @@ void AddSC_warlock_spell_scripts()
|
|||
RegisterSpellScript(spell_warl_unstable_affliction);
|
||||
RegisterSpellScript(spell_warl_drain_soul);
|
||||
RegisterSpellScript(spell_warl_shadowburn);
|
||||
RegisterSpellScript(spell_warl_glyph_of_felguard);
|
||||
RegisterSpellScript(spell_warl_glyph_of_voidwalker);
|
||||
RegisterSpellScript(spell_warl_voidwalker_pet_passive);
|
||||
RegisterSpellScript(spell_warl_demonic_pact_aura);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1208,8 +1208,7 @@ struct ItemRandomPropertiesEntry
|
|||
{
|
||||
uint32 ID; // 0
|
||||
//char const* InternalName; // 1
|
||||
std::array<uint32, MAX_ITEM_ENCHANTMENT_EFFECTS> Enchantment; // 2-4
|
||||
//std::array<uint32, 2> UnusedEnchantment; // 5-6
|
||||
std::array<uint32, MAX_ITEM_ENCHANTMENT_EFFECTS> Enchantment; // 2-6
|
||||
std::array<char const*, 16> Name; // 7-22
|
||||
//uint32 Name_lang_mask; // 23
|
||||
};
|
||||
|
|
@ -1220,10 +1219,8 @@ struct ItemRandomSuffixEntry
|
|||
std::array<char const*, 16> Name; // 1-16
|
||||
//uint32 Name_lang_mask; // 17
|
||||
//char const* InternalName; // 18
|
||||
std::array<uint32, MAX_ITEM_ENCHANTMENT_EFFECTS> Enchantment; // 19-21
|
||||
//std::array<uint32, 2> UnusedEnchantment; // 22-23
|
||||
std::array<uint32, MAX_ITEM_ENCHANTMENT_EFFECTS> AllocationPct; // 24-26
|
||||
//std::array<uint32, 2> UnusedAllocationPct; // 27-28
|
||||
std::array<uint32, MAX_ITEM_ENCHANTMENT_EFFECTS> Enchantment; // 19-23
|
||||
std::array<uint32, MAX_ITEM_ENCHANTMENT_EFFECTS> AllocationPct; // 24-28
|
||||
};
|
||||
|
||||
#define MAX_ITEM_SET_ITEMS 10
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue