diff --git a/.luacheckrc b/.luacheckrc index a2e64414..2a8cb20f 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -2626,6 +2626,7 @@ stds.ecs = { "MainMenuBar", "MapQuestInfoRewardsFrame", "MasterLooterFrame", + "MAX_SPELL_SCHOOLS", "MerchantFrame", "Minimap", "MinimapCluster", diff --git a/Modules/Data/Constants.lua b/Modules/Data/Constants.lua index 353b5aac..cd095430 100755 --- a/Modules/Data/Constants.lua +++ b/Modules/Data/Constants.lua @@ -1,3 +1,8 @@ +-- keep-sorted start case=no +local IsTBC = ECS.IsTBC +local IsWotlk = ECS.IsWotlk +-- keep-started end + ---@class Data local Data = ECSLoader:ImportModule("Data") @@ -21,6 +26,7 @@ Data.WARLOCK = 9 Data.DRUID = 11 Data.Aura = { + -- keep-sorted start block=yes case=no AllowCastingManaRegeneration = { [6117] = (ECS.IsWotlk and 0.5 or 0.3), -- Mage Armor rank 1 [12051] = 1, -- Evocation @@ -79,6 +85,85 @@ Data.Aura = { [17800] = (ECS.IsWotlk and -5 or nil), -- Shadow Mastery 5/5 [22959] = (ECS.IsWotlk and -5 or nil), -- Improved Scorch }, + ---@type table + HitReductionMelee = { + -- keep-sorted start block=yes numeric=yes + [0] = { + -- keep-sorted start numeric=yes + [2651] = (IsTBC and 20 or nil), -- Elune's Grace + [35346] = 50, -- Warp + [50240] = 200, -- Evasive Maneuvers + [54956] = 100, -- Impaling Charge + [59827] = 100, -- Impaling Charge + [445875] = -100, -- Gloom + [455868] = -1, -- Revealed Weakness + [460725] = -100, -- Gloom + -- keep-sorted end + }, + [14] = { + -- keep-sorted start numeric=yes + [46989] = (IsWotlk and 30 or 25), -- Improved Blink + [47000] = (IsWotlk and 15 or 13), -- Improved Blink + -- keep-sorted end + }, + [95] = { + -- keep-sorted start numeric=yes + [50280] = 20, -- Oily Coat + -- keep-sorted end + }, + [127] = { + -- keep-sorted start numeric=yes + [54603] = 25, -- Serpent's Agility + -- keep-sorted end + }, + -- keep-sorted end + }, + HitReductionRanged = { + -- keep-sorted start numeric=yes + [2651] = (IsTBC and 20 or nil), -- Elune's Grace + [26669] = 25, -- Evasion + [46989] = (IsWotlk and 30 or 25), -- Improved Blink + [47000] = (IsWotlk and 15 or 13), -- Improved Blink + [50280] = 20, -- Oily Coat + [54603] = 25, -- Serpent's Agility + [67801] = 100, -- Deterrence + [455868] = -1, -- Revealed Weakness + -- keep-sorted end + }, + ---@type table + HitReductionSpell = { + -- keep-sorted start block=yes numeric=yes + [0] = { + -- keep-sorted start numeric=yes + [50280] = 20, -- Oily Coat + [54603] = 25, -- Serpent's Agility + [56673] = -100, -- Fight Wyrm + [445875] = -100, -- Gloom + [460725] = -100, -- Gloom + -- keep-sorted end + }, + [126] = { + -- keep-sorted start numeric=yes + [31224] = 90, -- Cloak of Shadows + [31965] = -3, -- Spell Debuffs 2 (80) + [39666] = 90, -- Cloak of Shadows + [46989] = (IsWotlk and 30 or 25), -- Improved Blink + [47000] = (IsWotlk and 15 or 13), -- Improved Blink + [50240] = 200, -- Evasive Maneuvers + [65961] = 90, -- Cloak of Shadows + [455868] = -1, -- Revealed Weakness + [462873] = 90, -- Cloak of Shadows + -- keep-sorted end + }, + [127] = { + -- keep-sorted start numeric=yes + [33196] = (IsWotlk and -1 or nil), -- Misery + [33197] = (IsWotlk and -2 or nil), -- Misery + [33198] = (IsWotlk and -1 or nil), -- Misery + -- keep-sorted end + }, + -- keep-sorted end + }, IsFeralForm = { [768] = true, -- Cat Form [5487] = true, -- Bear Form @@ -347,6 +432,7 @@ Data.Aura = { [1227200] = 20, -- Wickedness [1236220] = -50, -- Slow }, + -- keep-sorted end } Data.Enchant = { BlockValue = { @@ -711,6 +797,46 @@ Data.Item = { [234032] = 2, }, } +Data.Talent = { + -- keep-sorted start block=yes + [Data.DEATHKNIGHT] = { + -- keep-sorted start + FRIGID_DREADPLATE = {49186,51108,51109}, + -- keep-sorted end + }, + [Data.HUNTER] = { + -- keep-sorted start + DISPLACEMENT = {34478,34479,34481}, + -- keep-sorted end + }, + [Data.MAGE] = { + -- keep-sorted start + ARCTIC_WINDS = {31674,31675,31676,31677,31678} + -- keep-sorted end + }, + [Data.PALADIN] = { + -- keep-sorted start + BALANCE_OF_POWER = {33592,33596}, + -- keep-sorted end + }, + [Data.PALADIN] = { + -- keep-sorted start + DIVINE_PURPOSE = {31871,31872}, + PURSUIT_OF_JUSTICE = {26022,26023,44414}, + -- keep-sorted end + }, + [Data.ROGUE] = { + -- keep-sorted start + HEIGHTENED_SENSES = {30894,30895}, + -- keep-sorted end + }, + [Data.WARRIOR] = { + -- keep-sorted start + IMPROVED_SPELL_REFLECTION = {59088,59089}, + -- keep-sorted end + }, + -- keep-sorted end +} Data.setNames = { AUGURS_REGALIA = "Augur's Regalia", BLOODSOUL_EMBRACE = "Bloodsoul Embrace", diff --git a/Modules/Data/Defense.lua b/Modules/Data/Defense.lua index 2a1a785b..0b1d5912 100755 --- a/Modules/Data/Defense.lua +++ b/Modules/Data/Defense.lua @@ -1,3 +1,14 @@ +-- keep-sorted start case=no +local band = bit.band +local GetBuffDataByIndex = C_UnitAuras.GetBuffDataByIndex +local GetDebuffDataByIndex = C_UnitAuras.GetDebuffDataByIndex +local IsSpellKnown = C_SpellBook.IsSpellKnown +local IsTBC = ECS.IsTBC +local IsWotlk = ECS.IsWotlk +local MAX_SPELL_SCHOOLS = MAX_SPELL_SCHOOLS +local pairs = pairs +-- keep-sorted end + ---@class Data local Data = ECSLoader:ImportModule("Data") ---@type DataUtils @@ -8,13 +19,23 @@ local Utils = ECSLoader:ImportModule("Utils") -- keep-sorted start case=no local _, _, classId = UnitClass("player") local _Defense = {} +local ARCANE = Data.ARCANE_SCHOOL +local DEATHKNIGHT = Data.DEATHKNIGHT -- Every 25 defense reduce the chance to be critically hit by 1 % local DEFENSE_FOR_CRIT_REDUCTION = 25 local DRUID = Data.DRUID +local FROST = Data.FROST_SCHOOL +local HUNTER = Data.HUNTER +local MAGE = Data.MAGE local MAX_SKILL = (UnitLevel("player")) * 5 +local NATURE = Data.NATURE_SCHOOL +local PALADIN = Data.PALADIN local PRIEST = Data.PRIEST local ROGUE = Data.ROGUE +local SHADOW = Data.SHADOW_SCHOOL +local Talent = Data.Talent local WARLOCK = Data.WARLOCK +local WARRIOR = Data.WARRIOR -- keep-sorted end ---@return number @@ -257,3 +278,120 @@ function _Defense:GetEnchantsBlockValue() end return mod end + +---@return table +function _Defense:GetHitReduction() + local hitReduction = { + spell = {0,0,0,0,0,0,0}, + melee= 0, + ranged = 0 + } + + local i = 1 + repeat + local aura = GetBuffDataByIndex("player", i) + i = i + 1 + if aura and aura.spellId then + hitReduction.melee = hitReduction.melee + (Data.Aura.HitReductionMelee[aura.spellId] or 0) + hitReduction.ranged = hitReduction.ranged + (Data.Aura.HitReductionRanged[aura.spellId] or 0) + + for k,v in pairs(Data.Aura.HitReductionSpell) do + for s=1,MAX_SPELL_SCHOOLS do + if ((k == 0) or band(k,s-1) ~= 0x0) then + hitReduction.spell[s] = hitReduction.spell[s] + (v[aura.spellId] or 0) + end + end + end + end + until (not aura) + i = 1 + repeat + local aura = GetDebuffDataByIndex("player", i) + i = i + 1 + if aura and aura.spellId then + hitReduction.melee = hitReduction.melee + (Data.Aura.HitReductionMelee[aura.spellId] or 0) + hitReduction.ranged = hitReduction.ranged + (Data.Aura.HitReductionRanged[aura.spellId] or 0) + + for k,v in pairs(Data.Aura.HitReductionSpell) do + for s=1,MAX_SPELL_SCHOOLS do + if ((k == 0) or band(k,s-1) ~= 0x0) then + hitReduction.spell[s] = hitReduction.spell[s] + (v[aura.spellId] or 0) + end + end + end + end + until (not aura) + + if IsWotlk then + if IsSpellKnown(20582) then -- Quickness + hitReduction.melee = hitReduction.melee + 2 + hitReduction.ranged = hitReduction.ranged + 2 + end + if IsSpellKnown(822) then -- Magic Resistance + for s=1,MAX_SPELL_SCHOOLS do + if band(126,s-1) ~= 0x0 then + hitReduction.spell[s] = hitReduction.spell[s] + 2 + end + end + end + if IsSpellKnown(20579) then -- Magic Resistance + for s=1,MAX_SPELL_SCHOOLS do + if band(126,s-1) ~= 0x0 then + hitReduction.spell[s] = hitReduction.spell[s] + 2 + end + end + end + hitReduction.spell[ARCANE] = hitReduction.spell[ARCANE] + (IsSpellKnown(20592) and 2 or 0) -- Arcane Resistance + hitReduction.spell[FROST] = hitReduction.spell[FROST] + (IsSpellKnown(20596) and 2 or 0) -- Frost Resistance + hitReduction.spell[NATURE] = hitReduction.spell[NATURE] + (IsSpellKnown(20583) and 2 or 0) -- Nature Resistance + hitReduction.spell[NATURE] = hitReduction.spell[NATURE] + (IsSpellKnown(20551) and 2 or 0) -- Nature Resistance + hitReduction.spell[SHADOW] = hitReduction.spell[SHADOW] + (IsSpellKnown(59535) and 2 or 0) -- Shadow Resistance + hitReduction.spell[SHADOW] = hitReduction.spell[SHADOW] + (IsSpellKnown(59540) and 2 or 0) -- Shadow Resistance + hitReduction.spell[SHADOW] = hitReduction.spell[SHADOW] + (IsSpellKnown(59538) and 2 or 0) -- Shadow Resistance + hitReduction.spell[SHADOW] = hitReduction.spell[SHADOW] + (IsSpellKnown(59221) and 2 or 0) -- Shadow Resistance + hitReduction.spell[SHADOW] = hitReduction.spell[SHADOW] + (IsSpellKnown(59541) and 2 or 0) -- Shadow Resistance + hitReduction.spell[SHADOW] = hitReduction.spell[SHADOW] + (IsSpellKnown(59536) and 2 or 0) -- Shadow Resistance + end + + local spellMod = 0 + if classId == DEATHKNIGHT then + hitReduction.melee = hitReduction.melee + 1 * DataUtils:GetActiveTalentSpell(Talent[DEATHKNIGHT].FRIGID_DREADPLATE) + elseif classId == DRUID then + spellMod = 3 * DataUtils:GetActiveTalentSpell(Talent[DRUID].BALANCE_OF_POWER) -- 126 + elseif classId == HUNTER then + if not ECS.IsClassic then + local mod = 1 * DataUtils:GetActiveTalentSpell(Talent[HUNTER].DISPLACEMENT) + spellMod = mod -- 126 + hitReduction.ranged = hitReduction.ranged + mod + hitReduction.melee = hitReduction.melee + mod + end + elseif classId == MAGE then + if not ECS.IsClassic then + local mod = 1 * DataUtils:GetActiveTalentSpell(Talent[MAGE].ARCTIC_WINDS) + hitReduction.ranged = hitReduction.ranged + mod + hitReduction.melee = hitReduction.melee + mod + end + elseif classId == PALADIN then + if IsTBC then + spellMod = 1 * DataUtils:GetActiveTalentSpell(Talent[PALADIN].PURSUIT_OF_JUSTICE) -- 126 + elseif IsWotlk then + local mod = 2 * DataUtils:GetActiveTalentSpell(Talent[PALADIN].DIVINE_PURPOSE) + spellMod = mod -- 126 + hitReduction.ranged = hitReduction.ranged + mod -- 127 + end + elseif classId == ROGUE then + local mod = 2 * DataUtils:GetActiveTalentSpell(Talent[ROGUE].HEIGHTENED_SENSES) + spellMod = mod -- 126 + hitReduction.ranged = hitReduction.ranged + mod + elseif classId == WARRIOR then + spellMod = 2 * DataUtils:GetActiveTalentSpell(Talent[WARRIOR].IMPROVED_SPELL_REFLECTION) -- 126 + end + + for s=1,MAX_SPELL_SCHOOLS do + if band(126,s-1) ~= 0x0 then + hitReduction.spell[s] = hitReduction.spell[s] + spellMod + end + end + + return hitReduction +end diff --git a/types/types.lua b/types/types.lua index fc872c91..1b35f188 100644 --- a/types/types.lua +++ b/types/types.lua @@ -26,3 +26,5 @@ ---@alias EquipSlot string ---@alias ItemLink string +---@alias Color string +---@alias Bitmask number