From 8a5d766c6e6382b8ee095b755034bf91c9cf2af0 Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Sat, 28 Feb 2026 03:34:06 +0100 Subject: [PATCH 1/6] wip --- Modules/Config/DefenseSection.lua | 337 ++++++++++++++++++ Modules/Data/Constants.lua | 43 +++ Modules/Data/DataUtils.lua | 59 ++- Modules/Data/Defense.lua | 171 ++++++++- Modules/Data/ItemSets.lua | 75 +++- Modules/Data/MP5.lua | 72 ++-- .../DefenseConfigTranslations.lua | 120 +++++++ .../i18n/translations/StatTranslations.lua | 120 +++++++ 8 files changed, 913 insertions(+), 84 deletions(-) diff --git a/Modules/Config/DefenseSection.lua b/Modules/Config/DefenseSection.lua index 202a3a54..4d598bae 100755 --- a/Modules/Config/DefenseSection.lua +++ b/Modules/Config/DefenseSection.lua @@ -1,3 +1,9 @@ +local ECSLoader = ECSLoader +local IsClassic = ECS.IsClassic +local IsTBC = ECS.IsTBC +local IsWotlk = ECS.IsWotlk +local UnitClass = UnitClass + ---@class Config local Config = ECSLoader:ImportModule("Config") local _Config = Config.private @@ -8,6 +14,10 @@ local Stats = ECSLoader:ImportModule("Stats") local i18n = ECSLoader:ImportModule("i18n") ---@type DataUtils local DataUtils = ECSLoader:ImportModule("DataUtils") +---@class Data +local Data = ECSLoader:ImportModule("Data") + +local _, _, classId = UnitClass("player") function _Config:LoadDefenseSection() return { @@ -203,6 +213,333 @@ function _Config:LoadDefenseSection() Stats.RebuildStatInfos() end, }, + mechanicResistanceGroup = { + type = "group", + order = 8, + inline = true, + name = function() + return i18n("Mechanic resistance") + end, + args = { + stun = { + type = "toggle", + order = 1, + name = function() + return i18n("Stun") + end, + desc = function() + return i18n("Shows/Hides the resistance to stun mechanics.") + end, + width = 1.5, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.stun.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.stun.display = value + Stats.RebuildStatInfos() + end, + }, + charm = { + type = "toggle", + order = 2, + name = function() + return i18n("Charm") + end, + desc = function() + return i18n("Shows/Hides the resistance to charm mechanics.") + end, + width = 1.5, + hidden = function() + return (IsWotlk or (not classId == Data.WARRIOR)) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.charm.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.charm.display = value + Stats.RebuildStatInfos() + end, + }, + disorient = { + type = "toggle", + order = 3, + name = function() + return i18n("Disorient") + end, + desc = function() + return i18n("Shows/Hides the resistance to disorient mechanics.") + end, + width = 1.5, + hidden = function() + return (IsClassic and not classId == Data.PALADIN) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.disorient.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.disorient.display = value + Stats.RebuildStatInfos() + end, + }, + root = { + type = "toggle", + order = 4, + name = function() + return i18n("Root") + end, + desc = function() + return i18n("Shows/Hides the resistance to root mechanics.") + end, + width = 1.5, + hidden = function() + return IsWotlk or not (IsClassic and classId == Data.HUNTER) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.root.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.root.display = value + Stats.RebuildStatInfos() + end, + }, + snare = { + type = "toggle", + order = 5, + name = function() + return i18n("snare") + end, + desc = function() + return i18n("Shows/Hides the resistance to snare mechanics.") + end, + width = 1.5, + hidden = function() + return IsWotlk or not (IsClassic and classId == Data.HUNTER) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.snare.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.snare.display = value + Stats.RebuildStatInfos() + end, + }, + silence = { + type = "toggle", + order = 6, + name = function() + return i18n("Silence") + end, + desc = function() + return i18n("Shows/Hides the resistance to silence mechanics.") + end, + width = 1.5, + hidden = function() + return not ( + IsClassic or (classId == Data.PRIEST or classId == Data.MAGE or classId == Data.WARLOCK) + ) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.silence.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.silence.display = value + Stats.RebuildStatInfos() + end, + }, + interrupt = { + type = "toggle", + order = 7, + name = function() + return i18n("Interrupt") + end, + desc = function() + return i18n("Shows/Hides the resistance to interrupt mechanics.") + end, + width = 1.5, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.interrupt.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.interrupt.display = value + Stats.RebuildStatInfos() + end, + }, + fleeing = { + type = "toggle", + order = 8, + name = function() + return i18n("Fear") + end, + desc = function() + return i18n("Shows/Hides the resistance to fear.") + end, + width = 1.5, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.fleeing.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.fleeing.display = value + Stats.RebuildStatInfos() + end, + }, + horror = { + type = "toggle", + order = 9, + name = function() + return i18n("Horror") + end, + desc = function() + return i18n("Shows/Hides the resistance to horror mechanics.") + end, + width = 1.5, + hidden = function() + return not IsTBC + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.horror.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.horror.display = value + Stats.RebuildStatInfos() + end, + }, + curse = { + type = "toggle", + order = 10, + name = function() + return i18n("Curse") + end, + desc = function() + return i18n("Shows/Hides the resistance to curses.") + end, + width = 1.5, + hidden = function() + return not (IsTBC and classId == Data.PALADIN) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.curse.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.curse.display = value + Stats.RebuildStatInfos() + end, + }, + disease = { + type = "toggle", + order = 11, + name = function() + return i18n("Disease") + end, + desc = function() + return i18n("Shows/Hides the resistance to diseases.") + end, + width = 1.5, + hidden = function() + return not (IsTBC and classId == Data.PALADIN) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.disease.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.disease.display = value + Stats.RebuildStatInfos() + end, + }, + poison = { + type = "toggle", + order = 12, + name = function() + return i18n("Poison") + end, + desc = function() + return i18n("Shows/Hides the resistance to poisons.") + end, + width = 1.5, + hidden = function() + return not (IsTBC and classId == Data.ROGUE) + end, + disabled = function() + return ( + not ExtendedCharacterStats.profile.defense.display + or not ExtendedCharacterStats.profile.defense.mechanicResistance.display + ) + end, + get = function() + return ExtendedCharacterStats.profile.defense.mechanicResistance.poison.display + end, + set = function(_, value) + ExtendedCharacterStats.profile.defense.mechanicResistance.poison.display = value + Stats.RebuildStatInfos() + end, + }, + }, + }, }, } end diff --git a/Modules/Data/Constants.lua b/Modules/Data/Constants.lua index 7f424a18..4d8264cf 100755 --- a/Modules/Data/Constants.lua +++ b/Modules/Data/Constants.lua @@ -1,3 +1,7 @@ +local ECSLoader = ECSLoader +local IsClassic = ECS.IsClassic +local IsWotlk = ECS.IsWotlk + ---@class Data local Data = ECSLoader:ImportModule("Data") @@ -351,6 +355,10 @@ Data.Aura = { [25894] = (ECS.IsClassic and 1 or nil), -- Greater Blessing of Wisdom rank 1 [25918] = (ECS.IsClassic and 1 or nil), -- Greater Blessing of Wisdom rank 2 }, + ResistanceInterrupt = { + [14743] = IsWotlk and nil or 10, -- Focused Casting + [27828] = IsWotlk and nil or 20, -- Focused Casting + }, SpellCrit = { [24907] = ((not ECS.IsClassic) and 5 or nil), -- Moonkin Aura [29177] = 6, -- Elemental Devastation Rank 2 @@ -519,6 +527,18 @@ Data.Gem = { [41477] = 4, -- Perfect Sundered Dark Jade [42146] = 17, -- Lustrous Dragon's Eye }, + ResistRoot = { + [32195] = (IsWotlk and nil or 5), -- Enigmatic Skyfire Diamond + }, + ResistSnare = { + [32195] = (IsWotlk and nil or 5), -- Enigmatic Skyfire Diamond + }, + ResistStun = { + [25896] = (IsWotlk and nil or 5), -- Powerful Earthstorm Diamond + [32195] = (IsWotlk and nil or 5), -- Enigmatic Skyfire Diamond + [32641] = 5, -- Imbued Unstable Diamond + [32640] = 5, -- Potent Unstable Diamond + } } Data.Item = { IsTimeworn = { @@ -643,6 +663,26 @@ Data.Item = { [234963] = true, [235047] = true, }, + ResistDisorient = { + [30519] = 10, -- Foreman's Reinforced Helmet + }, + ResistFleeing = { + [17759] = (IsWotlk and nil or 1), -- Mark of Resolution + [28428] = 8, -- Lionheart Blade + [28429] = 8, -- Lionheart Champion + [28430] = 8, -- Lionheart Executioner + }, + ResistSilence = { + [18345] = (IsClassic and 5 or nil), -- Murmuring Ring + [19786] = (IsClassic and 7 or nil), -- Voice Amplification Modulator + [21517] = (IsClassic and 10 or nil), -- Gnomish Turban of Psychic Might + [234134] = 10, -- Gnomish Turban of Psychic Might + }, + ResistStun = { + [17759] = (IsWotlk and nil or 1), -- Mark of Resolution + [23838] = 10, -- Foreman's Enchanted Helmet + [30519] = 10, -- Foreman's Reinforced Helmet + }, SpellHaste = { [235874] = 2, [236060] = 2, @@ -788,12 +828,15 @@ Data.Item = { } Data.setNames = { AUGURS_REGALIA = "Augur's Regalia", + BATTLECAST_GARB = "Battlecast Garb", BLOODSOUL_EMBRACE = "Bloodsoul Embrace", DAWN_OF_TRANSCENDENCE = "Dawn of Transcendence", FEL_IRON_CHAIN = "Fel Iron Chain", FREETHINKERS_ARMOR = "Freethinker's Armor", GREEN_DRAGON_MAIL = "Green Dragon Mail", HARUSPEXS_GARB = "Haruspex's Garb", + IRONWEAVE_BATTLESUIT = "Ironweave Battlesuit", + IRONWEAVE_BATTLESUIT_SOD = "Ironweave Battlesuit SoD", LIVING_GREEN_DRAGON_MAIL = "Living Green Dragon Mail", PRIMAL_MOONCLOTH = "Primal Mooncloth", STORMRAGE_RAIMENT = "Stormrage Raiment", diff --git a/Modules/Data/DataUtils.lua b/Modules/Data/DataUtils.lua index ba8acc34..9d76fdd1 100644 --- a/Modules/Data/DataUtils.lua +++ b/Modules/Data/DataUtils.lua @@ -1,10 +1,22 @@ +local ECSLoader = ECSLoader +local floor = math.floor +local GetBuffDataByIndex = C_UnitAuras.GetBuffDataByIndex +local GetInventoryItemLink = GetInventoryItemLink +local GetItemInfo = C_Item.GetItemInfo +local GetRuneForEquipmentSlot = C_Engraving.GetRuneForEquipmentSlot +local IsSoD = ECS.IsSoD +local IsSpellKnown = C_SpellBook.IsSpellKnown +local IsWotlk = ECS.IsWotlk +local match = string.match +local min = math.min +local strsplit = strsplit +local tonumber = tonumber + ---@class DataUtils local DataUtils = ECSLoader:CreateModule("DataUtils") ---@type Data local Data = ECSLoader:ImportModule("Data") -local IsSpellKnown = C_SpellBook.IsSpellKnown - --- Rounds every number down to the given decimal places ---@param num number ---@param decimalPlaces number @@ -14,14 +26,14 @@ function DataUtils:Round(num, decimalPlaces) return 0 end local mult = 10^(decimalPlaces) - return math.floor(num * mult + 0.5) / mult + return floor(num * mult + 0.5) / mult end ---@return boolean function DataUtils:IsShapeshifted() local i = 1 repeat - local aura = C_UnitAuras.GetBuffDataByIndex("player", i) + local aura = GetBuffDataByIndex("player", i) i = i + 1 if aura and aura.spellId then if Data.Aura.IsFeralForm[aura.spellId] then @@ -44,7 +56,7 @@ function DataUtils.GetMissChanceByDifference(weaponSkill, defenseValue) -- For a difference of 11-14 each point in weapon skill is worth 0.4% miss chance reduction local extraWeaponSkillDifference = ((15 - delta) * 0.2) return DataUtils:Round(6 + delta * 0.2 - extraWeaponSkillDifference, 2) - elseif ECS.IsWotlk then + elseif IsWotlk then -- For a difference of 15+ each point in weapon skill is worth 0.2% miss chance reduction return 5 + delta * 0.2 else @@ -58,7 +70,7 @@ end ---@param defenseValue number ---@return number function DataUtils:GetGlancingChanceByDifference(level, weaponSkill, defenseValue) - local glancingChance = 0.1 + (defenseValue - math.min(level*5, weaponSkill)) * 0.02 + local glancingChance = 0.1 + (defenseValue - min(level*5, weaponSkill)) * 0.02 -- Ensure the glancing chance does not exceed 1.0 (100%) if glancingChance > 1.0 then @@ -72,7 +84,7 @@ end ---@return number function DataUtils:GetGlancingDamage(weaponSkill, defenseValue) local difference = defenseValue - weaponSkill - local low = math.min(0.91 ,(1.3 - 0.05 * difference)) + local low = min(0.91 ,(1.3 - 0.05 * difference)) -- Ensure low does not go below 0.01 if low < 0.01 then @@ -107,7 +119,7 @@ end ---@return number|nil function DataUtils:GetEnchantFromItemLink(itemLink) if itemLink then - local _, itemStringLink = C_Item.GetItemInfo(itemLink) + local _, itemStringLink = GetItemInfo(itemLink) if itemStringLink then local _, _, enchant, _ = strsplit(":", itemStringLink, 4) return tonumber(enchant) @@ -120,7 +132,7 @@ end ---@return number|nil function DataUtils.GetRuneForEquipSlot(equipSlot) local slotId, _ = GetInventorySlotInfo(equipSlot) - local runeInfo = C_Engraving.GetRuneForEquipmentSlot(slotId) + local runeInfo = GetRuneForEquipmentSlot(slotId) if runeInfo then return runeInfo.itemEnchantmentID @@ -130,13 +142,13 @@ function DataUtils.GetRuneForEquipSlot(equipSlot) end ---@param itemLink ItemLink ----@return string | nil, string | nil, string | nil +---@return table | nil function DataUtils:GetSocketedGemsFromItemLink(itemLink) if itemLink then - local _, itemStringLink = C_Item.GetItemInfo(itemLink) + local _, itemStringLink = GetItemInfo(itemLink) if itemStringLink then local _, _, gem1, gem2, gem3, _ = strsplit(":", itemStringLink, 6) - return gem1, gem2, gem3 + return {gem1 and tonumber(gem1) or nil, gem2 and tonumber(gem2) or nil, gem3 and tonumber(gem3) or nil} end end return nil @@ -157,7 +169,7 @@ end ---@return number function DataUtils:GetActiveTalentSpell(talentList) for i = #talentList,1,-1 do - if C_SpellBook.IsSpellKnown(talentList[i]) then + if IsSpellKnown(talentList[i]) then return i end end @@ -167,7 +179,7 @@ function DataUtils:GetActiveTalentSpell(talentList) ---@return number function DataUtils:CountTimewornItems() local timeworn = 0 - if ECS.IsSoD then + if IsSoD then for i = 1, 18 do local id, _ = GetInventoryItemID("player", i) if Data.Item.IsTimeworn[id] then @@ -178,4 +190,23 @@ function DataUtils:CountTimewornItems() return timeworn end +---@return number +function DataUtils:GetValueFromAuraTooltip(index, type) + if not ECS.scanningTooltip then + ECS.scanningTooltip = CreateFrame("GameTooltip", "scanningTooltip", nil, "GameTooltipTemplate") + ECS.scanningTooltip:SetOwner(WorldFrame, "ANCHOR_NONE") + end + + ECS.scanningTooltip:ClearLines() + ECS.scanningTooltip:SetUnitAura("player", index, type) + local region = select(5, ECS.scanningTooltip:GetRegions()) + if region and region:GetObjectType() == "FontString" then + local tooltip = region:GetText() + if tooltip then + return tonumber(match(tooltip, "%d[%d,.]*")) + end + end + return 0 +end + return DataUtils diff --git a/Modules/Data/Defense.lua b/Modules/Data/Defense.lua index f9511d57..d368eb34 100755 --- a/Modules/Data/Defense.lua +++ b/Modules/Data/Defense.lua @@ -1,3 +1,22 @@ +local ECSLoader = ECSLoader +local floor = math.floor +local GetBuffDataByIndex = C_UnitAuras.GetBuffDataByIndex +local GetCombatRating = GetCombatRating +local GetCombatRatingBonus = GetCombatRatingBonus +local GetDebuffDataByIndex = C_UnitAuras.GetDebuffDataByIndex +local GetInventoryItemID = GetInventoryItemID +local GetInventoryItemLink = GetInventoryItemLink +local IsClassic = ECS.IsClassic +local IsSoD = ECS.IsSoD +local IsSpellKnown = C_SpellBook.IsSpellKnown +local IsTBC = ECS.IsTBC +local IsWotlk = ECS.IsWotlk +local OffhandHasShield = C_PaperDollInfo.OffhandHasShield +local UnitArmor = UnitArmor +local UnitClass = UnitClass +local UnitDefense = UnitDefense +local UnitLevel = UnitLevel + ---@class Data local Data = ECSLoader:ImportModule("Data") ---@type DataUtils @@ -29,27 +48,27 @@ function _Defense:GetCritReduction() local spellCritReduction = 0 local i = 1 repeat - local aura = C_UnitAuras.GetAuraDataByIndex("player", i, "HELPFUL") + local aura = GetBuffDataByIndex("player", i) i = i + 1 if aura and aura.spellId then buffBonus = buffBonus + (Data.Aura.CritReductionAll[aura.spellId] or 0) meleeCritReduction = meleeCritReduction + (Data.Aura.CritReductionMelee[aura.spellId] or 0) - if ECS.IsWotlk and aura.spellId == 22812 and C_SpellBook.IsSpellKnown(63058) then + if IsWotlk and aura.spellId == 22812 and IsSpellKnown(63058) then buffBonus = buffBonus + 25 -- Glyph of Barkskin end end until (not aura) i = 1 repeat - local aura = C_UnitAuras.GetAuraDataByIndex("player", i, "HARMFUL") + local aura = GetDebuffDataByIndex("player", i) i = i + 1 if aura and aura.spellId then buffBonus = buffBonus + (Data.Aura.CritReductionAll[aura.spellId] or 0) meleeCritReduction = meleeCritReduction + (Data.Aura.CritReductionMelee[aura.spellId] or 0) spellCritReduction = spellCritReduction + (Data.Aura.CritReductionSpell[aura.spellId] or 0) - if ECS.IsWotlk and aura.spellId == 12579 then + if IsWotlk and aura.spellId == 12579 then spellCritReduction = spellCritReduction - 1 * aura.applications -- Winter's Chill - elseif ECS.IsSoD and aura.spellId == 1231399 then -- Legislate + elseif IsSoD and aura.spellId == 1231399 then -- Legislate buffBonus = buffBonus - 3 * aura.applications end end @@ -63,10 +82,10 @@ function _Defense:GetCritReduction() local critReducingFromResilience = GetCombatRatingBonus(15) if classId == Data.DRUID then - local coeff = ECS.IsWotlk and 2 or 1 + local coeff = IsWotlk and 2 or 1 meleeCritReduction = meleeCritReduction + coeff * DataUtils:GetActiveTalentSpell({33853,33855,33856}) -- Survival of the Fittest elseif classId == Data.PRIEST then - if ECS.IsTBC then + if IsTBC then spellCritReduction = spellCritReduction + 2 * DataUtils:GetActiveTalentSpell({14910,33371}) -- shadow resilience end elseif classId == Data.ROGUE then @@ -74,14 +93,14 @@ function _Defense:GetCritReduction() meleeCritReduction = meleeCritReduction + mod rangedCritReduction = rangedCritReduction + mod elseif classId == Data.WARLOCK then - if not ECS.IsClassic then + if not IsClassic then local mod = 1 * DataUtils:GetActiveTalentSpell({30319,30320,30321}) -- Demonic Resilience meleeCritReduction = meleeCritReduction + mod rangedCritReduction = rangedCritReduction + mod end end - if ECS.IsSoD then + if IsSoD then if classId == Data.DRUID or classId == Data.ROGUE then local chestRune = DataUtils.GetRuneForEquipSlot(Utils.CHAR_EQUIP_SLOTS.Chest) if chestRune and (chestRune == 6710 or chestRune == 6972) then @@ -121,10 +140,10 @@ function _Defense:GetEnemyMissChance(enemyLevel) local enemyAttackRating = enemyLevel * 5 local miss - if ECS.IsWotlk then - local defense = math.floor(GetCombatRatingBonus(CR_DEFENSE_SKILL)); - local enemyMissCoef = classId == Data.DRUID and 0.972 or 0.956; -- 0.972 for bears - local baseMissChance = 5 - (enemyAttackRating - select(1, UnitDefense("player"))) * 0.04; -- vs lvl 80 + if IsWotlk then + local defense = floor(GetCombatRatingBonus(CR_DEFENSE_SKILL)) + local enemyMissCoef = classId == Data.DRUID and 0.972 or 0.956 -- 0.972 for bears + local baseMissChance = 5 - (enemyAttackRating - select(1, UnitDefense("player"))) * 0.04 -- vs lvl 80 if defense > 0 then -- avoid possible division by 0 local enemyMissChance = baseMissChance + 1 / (0.0625 + enemyMissCoef / (defense * 0.04)) miss = enemyMissChance @@ -142,7 +161,7 @@ end ---@return number function _Defense:GetBlockChance() local block = 0 - if C_SpellBook.IsSpellKnown(107) and C_PaperDollInfo.OffhandHasShield() then + if IsSpellKnown(107) and OffhandHasShield() then block = GetBlockChance() end return block @@ -151,7 +170,7 @@ end ---@return number function _Defense:GetParryChance() local parry = 0 - if C_SpellBook.IsSpellKnown(3127) or C_SpellBook.IsSpellKnown(18848) or C_SpellBook.IsSpellKnown(3124) then + if IsSpellKnown(3127) or IsSpellKnown(18848) or IsSpellKnown(3124) then parry = GetParryChance() end return parry @@ -160,7 +179,7 @@ end ---@return number function _Defense:GetDodgeChance() local dodge = 0 - if C_SpellBook.IsSpellKnown(81) then + if IsSpellKnown(81) then dodge = GetDodgeChance() end return dodge @@ -211,7 +230,7 @@ end ---@return number function Data:GetBlockValue() local blockValue = 0 - if C_SpellBook.IsSpellKnown(107) and C_PaperDollInfo.OffhandHasShield() then + if IsSpellKnown(107) and OffhandHasShield() then blockValue = blockValue + GetShieldBlock() + _Defense:GetEnchantsBlockValue() end return DataUtils:Round(blockValue, 2) @@ -236,3 +255,121 @@ function _Defense:GetEnchantsBlockValue() end return mod end + +---@return table +function _Defense:GetMechanicResistance() + local resistance = { + ["charm"] = 0, + ["curse"] = 0, + ["disease"] = 0, + ["disorient"] = 0, + ["fleeing"] = 0, + ["horror"] = 0, + ["interrupt"] = 0, + ["poison"] = 0, + ["root"] = 0, + ["silence"] = 0, + ["snare"] = 0, + ["stun"] = 0, + } + + if IsSpellKnown(20573) then -- Hardiness + if IsClassic then + resistance.stun = resistance.stun + 25 + elseif IsTBC then + resistance.stun = resistance.stun + 15 + end + end + + for i = 1, 18 do + local id, _ = GetInventoryItemID("player", i) + resistance.disorient = resistance.disorient + (Data.Item.ResistDisorient[id] or 0) + resistance.fleeing = resistance.fleeing + (Data.Item.ResistFleeing[id] or 0) + resistance.silence = resistance.silence + (Data.Item.ResistSilence[id] or 0) + resistance.stun = resistance.stun + (Data.Item.ResistStun[id] or 0) + + local itemLink = GetInventoryItemLink("player", i) + if itemLink then + -- Check for socketed gems (TODO: check for socket bonus) + local gems = DataUtils:GetSocketedGemsFromItemLink(itemLink) + if gems then + for j = 1, 3 do + if gems[j] then + resistance.root = resistance.root + (Data.Gem.ResistRoot[gems[j]] or 0) + resistance.snare = resistance.snare + (Data.Gem.ResistRoot[gems[j]] or 0) + resistance.stun = resistance.stun + (Data.Gem.ResistStun[gems[j]] or 0) + end + end + end + end + end + + local i = 1 + repeat + local aura = GetBuffDataByIndex("player", i) + i = i + 1 + if aura and aura.spellId then + resistance.interrupt = resistance.interrupt + (Data.Aura.ResistInterrupt[aura.spellId] or 0) + -- if aura.spellId == 19746 then + -- TODO: improved concentration aura + -- resistance.silence = resistance.silence + (IsWotlk and 0 or 15) -- Concentration Aura + -- resistance.interrupt + -- end + end + until not aura + i = 1 + repeat + local aura = GetDebuffDataByIndex("player", i) + i = i + 1 + if aura and aura.spellId then + if aura.spellId == 27182 then -- Nether Affliction + resistance.fleeing = resistance.fleeing - 10 + resistance.horror = resistance.horror - 10 + end + end + until not aura + + if not IsWotlk then + if classId == Data.DRUID then + local mod = 5 * DataUtils:GetActiveTalentSpell({ 33851, 33852, 33957 }) -- Primal Tenacity + resistance.stun = resistance.stun + mod + resistance.fleeing = resistance.fleeing + mod + elseif classId == Data.HUNTER then + local mod = 5 * DataUtils:GetActiveTalentSpell({ 19290, 19294, 24283 }) -- Surefooted + resistance.root = resistance.root + mod + resistance.snare = resistance.snare + mod + elseif classId == Data.PALADIN then + resistance.stun = resistance.stun + 5 * DataUtils:GetActiveTalentSpell({ 31844, 31845 }) -- Stoicism + local mod = 5 * DataUtils:GetActiveTalentSpell({ 9453, 25836 }) -- Unyielding Faith + resistance.disorient = resistance.disorient + mod + resistance.fleeing = resistance.fleeing + mod + mod = 5 * DataUtils:GetActiveTalentSpell({ 31822, 31823, 31824 }) -- Pure of Heart + resistance.curse = resistance.curse + mod + resistance.disease = resistance.disease + mod + elseif classId == Data.PRIEST then + local mod = 3 * DataUtils:GetActiveTalentSpell({ 14522, 14788, 14789, 14790, 14791 }) -- Unbreakable Will + resistance.stun = resistance.stun + mod + resistance.fleeing = resistance.fleeing + mod + resistance.silence = resistance.silence + mod + elseif classId == Data.ROGUE then + resistance.poison = resistance.poison + 15 * DataUtils:GetActiveTalentSpell({ 31226, 31227 }) -- Master Poisoner + local mod = 5 * DataUtils:GetActiveTalentSpell({ 31208, 31209 }) -- Fleet Footed + resistance.root = resistance.root + mod + resistance.snare = resistance.snare + mod + mod = 5 * DataUtils:GetActiveTalentSpell({ 31130, 31131 }) -- Nerves of Steel + resistance.stun = resistance.stun + mod + resistance.fleeing = resistance.fleeing + mod + elseif classId == Data.SHAMAN then + if IsClassic then + local mod = 5 * DataUtils:GetActiveTalentSpell({ 30864, 30865, 30866 }) -- Focused Mind + resistance.interrupt = resistance.interrupt + mod + resistance.silence = resistance.silence + mod + end + elseif classId == Data.WARRIOR then + local mod = 3 * DataUtils:GetActiveTalentSpell({ 12300, 12959, 12960, 12961, 12962 }) -- Iron Will + resistance.stun = resistance.stun + mod + resistance.charm = resistance.charm + mod + end + end + return resistance +end diff --git a/Modules/Data/ItemSets.lua b/Modules/Data/ItemSets.lua index 7e07ffed..58424baf 100755 --- a/Modules/Data/ItemSets.lua +++ b/Modules/Data/ItemSets.lua @@ -1,3 +1,10 @@ +local ECSLoader = ECSLoader +local GetInventoryItemID = GetInventoryItemID +local IsClassic = ECS.IsClassic +local IsSoD = ECS.IsSoD +local IsWotlk = ECS.IsWotlk +local UnitClass = UnitClass + ---@class Data local Data = ECSLoader:ImportModule("Data") @@ -12,6 +19,10 @@ local itemSets = { [19830] = true, [19956] = true }, + [setNames.BATTLECAST_GARB] = { + [24263] = true, + [24267] = true, + }, [setNames.BLOODSOUL_EMBRACE] = { [19690] = true, [19691] = true, @@ -52,6 +63,26 @@ local itemSets = { [19840] = true, [19955] = true, }, + [setNames.IRONWEAVE_BATTLESUIT] = { + [22301] = true, + [22302] = true, + [22303] = true, + [22304] = true, + [22305] = true, + [22306] = true, + [22311] = true, + [22313] = true, + }, + [setNames.IRONWEAVE_BATTLESUIT_SOD] = { + [228066] = true, + [228083] = true, + [228547] = true, + [228596] = true, + [228597] = true, + [228598] = true, + [228681] = true, + [228700] = true, + }, [setNames.LIVING_GREEN_DRAGON_MAIL] = { [227877] = true, [227878] = true, @@ -120,22 +151,38 @@ local itemSets = { }, } +---@return boolean +function Data:HasSetResistInterrupt() + return ((not IsClassic) and Data:IsSetBonusActive(setNames.BATTLECAST_GARB, 2)) +end + +---@return boolean +function Data:HasSetResistSilenceInterrupt() + if classId == Data.PRIEST or classId == Data.MAGE or classId == Data.WARLOCK then + return ( + Data:IsSetBonusActive(setNames.IRONWEAVE_BATTLESUIT, 4) + or (IsSoD and Data:IsSetBonusActive(setNames.IRONWEAVE_BATTLESUIT_SOD, 2)) + ) + end + return false +end + ---@return number function Data:GetSetBonusModifierMP5() local mod = 0 - if (ECS.IsClassic and Data:IsSetBonusActive(setNames.GREEN_DRAGON_MAIL, 3)) then + if (IsClassic and Data:IsSetBonusActive(setNames.GREEN_DRAGON_MAIL, 3)) then mod = mod + 0.15 end - if (ECS.IsClassic and ( + if (IsClassic and ( (classId == Data.DRUID and Data:IsSetBonusActive(setNames.STORMRAGE_RAIMENT, 3)) or (classId == Data.PRIEST and Data:IsSetBonusActive(setNames.VESTMENTS_OF_TRANSCENDENCE, 3)) )) then mod = mod + 0.15 end - if (ECS.IsSoD and Data:IsSetBonusActive(setNames.LIVING_GREEN_DRAGON_MAIL, 3)) then + if (IsSoD and Data:IsSetBonusActive(setNames.LIVING_GREEN_DRAGON_MAIL, 3)) then mod = mod + 0.15 end - if (ECS.IsSoD and Data:IsSetBonusActive(setNames.DAWN_OF_TRANSCENDENCE, 2)) then + if (IsSoD and Data:IsSetBonusActive(setNames.DAWN_OF_TRANSCENDENCE, 2)) then mod = mod + 0.15 end if Data:IsSetBonusActive(setNames.PRIMAL_MOONCLOTH, 3) then @@ -151,32 +198,32 @@ function Data:GetSetBonusValueMP5() (classId == Data.SHAMAN and Data:IsSetBonusActive(setNames.AUGURS_REGALIA, 2)) or (classId == Data.PALADIN and Data:IsSetBonusActive(setNames.FREETHINKERS_ARMOR, 2) ) then - bonus = bonus + (ECS.IsWotlk and 5 or 4) + bonus = bonus + (IsWotlk and 5 or 4) end - if (ECS.IsSoD and Data:IsSetBonusActive(setNames.LIVING_GREEN_DRAGON_MAIL, 2)) then + if (IsSoD and Data:IsSetBonusActive(setNames.LIVING_GREEN_DRAGON_MAIL, 2)) then bonus = bonus + 3 end if Data:IsSetBonusActive(setNames.GREEN_DRAGON_MAIL, 2) then - bonus = bonus + (ECS.IsWotlk and 4 or 3) + bonus = bonus + (IsWotlk and 4 or 3) end - if (not ECS.IsClassic and Data:IsSetBonusActive(setNames.GREEN_DRAGON_MAIL, 3)) then - bonus = bonus + (ECS.IsWotlk and 25 or 20) + if (not IsClassic and Data:IsSetBonusActive(setNames.GREEN_DRAGON_MAIL, 3)) then + bonus = bonus + (IsWotlk and 25 or 20) end - if (not ECS.IsClassic and ( + if (not IsClassic and ( (classId == Data.DRUID and Data:IsSetBonusActive(setNames.STORMRAGE_RAIMENT, 3)) or (classId == Data.PRIEST and Data:IsSetBonusActive(setNames.VESTMENTS_OF_TRANSCENDENCE, 3)) ) ) then - bonus = bonus + (ECS.IsWotlk and 25 or 20) + bonus = bonus + (IsWotlk and 25 or 20) end if Data:IsSetBonusActive(setNames.BLOODSOUL_EMBRACE, 3) then - bonus = bonus + (ECS.IsWotlk and 15 or 12) + bonus = bonus + (IsWotlk and 15 or 12) end if Data:IsSetBonusActive(setNames.FEL_IRON_CHAIN, 4) then - bonus = bonus + (ECS.IsWotlk and 10 or 8) + bonus = bonus + (IsWotlk and 10 or 8) end if Data:IsSetBonusActive(setNames.WINDHAWK_ARMOR, 3) then - bonus = bonus + (ECS.IsWotlk and 10 or 8) + bonus = bonus + (IsWotlk and 10 or 8) end return bonus end diff --git a/Modules/Data/MP5.lua b/Modules/Data/MP5.lua index 5ea8de85..65bba68c 100755 --- a/Modules/Data/MP5.lua +++ b/Modules/Data/MP5.lua @@ -1,3 +1,18 @@ +local ECSLoader = ECSLoader +local GetBuffDataByIndex = C_UnitAuras.GetBuffDataByIndex +local GetDebuffDataByIndex = C_UnitAuras.GetDebuffDataByIndex +local GetInventoryItemLink = GetInventoryItemLink +local GetItemStats = GetItemStats +local GetManaRegen = GetManaRegen +local GetWeaponEnchantInfo = GetWeaponEnchantInfo +local IsSoD = ECS.IsSoD +local IsTBC = ECS.IsTBC +local IsWotlk = ECS.IsWotlk +local min = math.min +local PowerType = Enum.PowerType +local UnitClass = UnitClass +local UnitPowerMax = UnitPowerMax + ---@class Data local Data = ECSLoader:ImportModule("Data") ---@type DataUtils @@ -9,25 +24,6 @@ local _MP5 = {} local _, _, classId = UnitClass("player") ----@return number -function Data:GetValueFromAuraTooltip(index,type) - if not ECS.scanningTooltip then - ECS.scanningTooltip = CreateFrame("GameTooltip", "scanningTooltip", nil, "GameTooltipTemplate") - ECS.scanningTooltip:SetOwner(WorldFrame, "ANCHOR_NONE") - end - - ECS.scanningTooltip:ClearLines() - ECS.scanningTooltip:SetUnitAura("player",index, type) - local region = select(5,ECS.scanningTooltip:GetRegions()) - if region and region:GetObjectType() == "FontString" then - local tooltip = region:GetText() - if tooltip then - return tonumber(string.match(tooltip, '%d[%d,.]*')) - end - end - return 0 -end - -- Get MP5 from items ---@return number function Data:GetMP5FromItems() @@ -52,15 +48,13 @@ function _MP5:GetMP5ValueOnItems() mp5 = mp5 + (Data.Enchant.MP5[enchant] or 0) end -- Check for socketed gems (TODO: check for socket bonus) - local gem1, gem2, gem3 = DataUtils:GetSocketedGemsFromItemLink(itemLink) - if gem1 then - mp5 = mp5 + (Data.Gem.MP5[tonumber(gem1)] or 0) - end - if gem2 then - mp5 = mp5 + (Data.Gem.MP5[tonumber(gem2)] or 0) - end - if gem3 then - mp5 = mp5 + (Data.Gem.MP5[tonumber(gem3)] or 0) + local gems = DataUtils:GetSocketedGemsFromItemLink(itemLink) + if gems then + for j=1,3 do + if gems[j] then + mp5 = mp5 + (Data.Gem.MP5[gems[j]] or 0) + end + end end end end @@ -118,11 +112,11 @@ function Data:GetMP5FromBuffs() local mod = 0 local bonus = 0 local periodic = 0 - local maxmana = UnitPowerMax("player", Enum.PowerType.Mana) + local maxmana = UnitPowerMax("player", PowerType.Mana) local i = 1 repeat - local aura = C_UnitAuras.GetBuffDataByIndex("player", i) + local aura = GetBuffDataByIndex("player", i) if aura and aura.spellId then bonus = bonus + (Data.Aura.MP5[aura.spellId] or 0) bonus = bonus + (Data.Aura.PercentageMp5[aura.spellId] or 0) * maxmana @@ -132,12 +126,12 @@ function Data:GetMP5FromBuffs() bonus = bonus + 15 -- 15 MP5 from Shaman T3 8 piece bonus when Lightning Shield is active end if Data.Aura.MP5Tooltip[aura.spellId] then - bonus = bonus + Data.Aura.MP5Tooltip[aura.spellId] * Data:GetValueFromAuraTooltip(i, "HELPFUL") + bonus = bonus + Data.Aura.MP5Tooltip[aura.spellId] * DataUtils:GetValueFromAuraTooltip(i, "HELPFUL") end if Data.Aura.PeriodicallyGiveManaTooltip[aura.spellId] then - periodic = periodic + Data.Aura.PeriodicallyGiveManaTooltip[aura.spellId] * Data:GetValueFromAuraTooltip(i, "HELPFUL") + periodic = periodic + Data.Aura.PeriodicallyGiveManaTooltip[aura.spellId] * DataUtils:GetValueFromAuraTooltip(i, "HELPFUL") end - if ECS.IsWotlk then + if IsWotlk then if aura.spellId == 64999 then bonus = bonus + 85 * aura.applications -- Meteoric Inspiration end @@ -147,7 +141,7 @@ function Data:GetMP5FromBuffs() until (not aura) i = 1 repeat - local aura = C_UnitAuras.GetDebuffDataByIndex("player", i) + local aura = GetDebuffDataByIndex("player", i) if aura and aura.spellId then bonus = bonus + (Data.Aura.PercentageMp5[aura.spellId] or 0) * maxmana end @@ -160,7 +154,7 @@ end function _MP5.GetMP5FromRunes() local mod = 0 - if (not ECS.IsSoD) then + if (not IsSoD) then return mod end @@ -179,17 +173,17 @@ function _MP5:GetTalentModifier() local mod = 0 if classId == Data.PRIEST then - local coeff = ECS.IsTBC and 0.1 or (ECS.IsWotlk and 0.5/3 or 0.05) + local coeff = IsTBC and 0.1 or (IsWotlk and 0.5/3 or 0.05) mod = mod + coeff * DataUtils:GetActiveTalentSpell({14521,14776,14777}) -- meditation elseif classId == Data.MAGE then - local coeff = ECS.IsTBC and 0.1 or (ECS.IsWotlk and 0.5/3 or 0.05) + local coeff = IsTBC and 0.1 or (IsWotlk and 0.5/3 or 0.05) mod = mod + coeff * DataUtils:GetActiveTalentSpell({14521,18463,18464}) -- arcane meditation - if ECS.IsWotlk then + if IsWotlk then mod = mod + 0.5/3 * DataUtils:GetActiveTalentSpell({34293,34295,34296}) -- pyromaniac end elseif classId == Data.DRUID then - local coeff = ECS.IsTBC and 0.1 or (ECS.IsWotlk and 0.5/3 or 0.05) + local coeff = IsTBC and 0.1 or (IsWotlk and 0.5/3 or 0.05) mod = mod + coeff * DataUtils:GetActiveTalentSpell({17106,17107,17108}) -- intensity/reflection end return mod diff --git a/Modules/i18n/translations/ConfigTranslations/DefenseConfigTranslations.lua b/Modules/i18n/translations/ConfigTranslations/DefenseConfigTranslations.lua index 8d2a36cb..3812b524 100644 --- a/Modules/i18n/translations/ConfigTranslations/DefenseConfigTranslations.lua +++ b/Modules/i18n/translations/ConfigTranslations/DefenseConfigTranslations.lua @@ -182,6 +182,126 @@ local defenseConfigTranslations = { ["esMX"] = false, ["ptBR"] = false }, + ["Shows/Hides the resistance to curses."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to poisons."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to diseases."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to interrupts mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to silence mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to charm mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to disorient mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to root mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to stun mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to horror mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to fear mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, + ["Shows/Hides the resistance to snare mechanics."] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false + }, } for k, v in pairs(defenseConfigTranslations) do diff --git a/Modules/i18n/translations/StatTranslations.lua b/Modules/i18n/translations/StatTranslations.lua index 6bf9140e..cdec7562 100644 --- a/Modules/i18n/translations/StatTranslations.lua +++ b/Modules/i18n/translations/StatTranslations.lua @@ -812,6 +812,126 @@ local statTranslations = { ["esMX"] = "Fallo de las sombras (Niv. + 3)", ["ptBR"] = "Erro de sombra (Nív. + 3)" }, + ["Poison"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Curse"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Disease"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Stun"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Charm"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Snare"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Root"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Disorient"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Interrupt"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Silence"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Horror"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, + ["Fear"] = { + ["enUS"] = true, + ["deDE"] = false, + ["frFR"] = false, + ["zhCN"] = false, + ["ruRU"] = false, + ["esES"] = false, + ["esMX"] = false, + ["ptBR"] = false, + }, } for k, v in pairs(statTranslations) do From 11215e9dd894fb5758db063a8bfb5d7f9c3fe876 Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Sat, 28 Feb 2026 04:13:29 +0100 Subject: [PATCH 2/6] wip --- Modules/Stats.lua | 98 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/Modules/Stats.lua b/Modules/Stats.lua index acac2a0b..620f04ab 100755 --- a/Modules/Stats.lua +++ b/Modules/Stats.lua @@ -1,3 +1,27 @@ +local After = C_Timer.After +local CanDualWield = CanDualWield +local CharacterModelFrame = CharacterModelFrame +local ECSConfigFrame = ECSConfigFrame +local ECSLoader = ECSLoader +local error = error +local ExtendedCharacterStats = ExtendedCharacterStats +local insert = table.insert +local IsClassic = ECS.IsClassic +local IsSoD = ECS.IsSoD +local IsTBC = ECS.IsTBC +local IsWotlk = ECS.IsWotlk +local LeaPlusDB = LeaPlusDB +local OutfitterButton = OutfitterButton +local OutfitterButtonFrame = OutfitterButtonFrame +local OutfitterFrame = OutfitterFrame +local pairs = pairs +local PaperDollItemsFrame = PaperDollItemsFrame +local PawnInitialize = PawnInitialize +local remove = table.remove +local type = type +local UnitClass = UnitClass +local UnitHasMana = UnitHasMana + ------------------------------------------------------------------ -- Modules ------------------------------------------------------------------ @@ -36,6 +60,8 @@ local colors = Utils.colors local framePool = {} local lastYOffset = 20 local engravingFrameHooked = false + +local _, _, classId = UnitClass("player") ------------------------------------------------------------------ @@ -104,9 +130,9 @@ function Stats.CreateWindow() Stats:HideWindow() end - if ECS.IsSoD then + if IsSoD then -- next frame - C_Timer.After(0, function () + After(0, function () if EngravingFrame then if EngravingFrame:IsShown() then mainFrame:ClearAllPoints() @@ -217,24 +243,24 @@ _CreateStatInfos = function() category, category.attackPower, category.crit, - ECS.IsWotlk and category.penetrationRating or nil, - (not ECS.IsClassic) and category.penetration or nil, - (not ECS.IsClassic) and category.expertiseRating or nil, - (not ECS.IsClassic) and category.expertise or nil, - (not ECS.IsClassic) and category.hasteRating or nil, - (not ECS.IsClassic) and category.hasteBonus or nil + IsWotlk and category.penetrationRating or nil, + IsClassic and nil or category.penetration, + IsClassic and nil or category.expertiseRating, + IsClassic and nil or category.expertise, + IsClassic and nil or category.hasteRating, + IsClassic and nil or category.hasteBonus ) if category.display then category = category.hit _CreateStatInfo( category, - (not ECS.IsClassic) and category.rating or nil, + IsClassic and nil or category.rating, category.bonus, category.sameLevel, category.bossLevel ) - if (not ECS.IsWotlk) then + if (not IsWotlk) then category = profile.melee.glance _CreateStatInfo(category, category.sameLevel, category.damageSameLevel, category.bossLevel, category.damageBossLevel) end @@ -253,10 +279,10 @@ _CreateStatInfos = function() category, category.attackPower, category.crit, - ECS.IsWotlk and category.penetrationRating or nil, - (not ECS.IsClassic) and category.penetration or nil, - (not ECS.IsClassic) and category.hasteRating or nil, - (not ECS.IsClassic) and category.hasteBonus or nil, + IsWotlk and category.penetrationRating or nil, + IsClassic and nil or category.penetration, + IsClassic and nil or category.hasteRating, + IsClassic and nil or category.hasteBonus, category.attackSpeed ) @@ -264,7 +290,7 @@ _CreateStatInfos = function() category = category.hit _CreateStatInfo( category, - (not ECS.IsClassic) and category.rating or nil, + IsClassic and nil or category.rating, category.bonus, category.sameLevel, category.bossLevel @@ -281,17 +307,35 @@ _CreateStatInfos = function() category.spellCritReduction, category.avoidance, category.avoidanceBoss, - (not ECS.IsClassic) and category.defenseRating or nil, + IsClassic and nil or category.defenseRating, category.defense, - (not ECS.IsClassic and DataUtils:CanBlock()) and category.blockRating or nil, + (not IsClassic and DataUtils:CanBlock()) and category.blockRating or nil, DataUtils:CanBlock() and category.blockChance or nil, DataUtils:CanBlock() and category.blockValue or nil, - (not ECS.IsClassic and DataUtils:CanParry()) and category.parryRating or nil, + (not IsClassic and DataUtils:CanParry()) and category.parryRating or nil, DataUtils:CanParry() and category.parry or nil, - (not ECS.IsClassic) and category.dodgeRating or nil, + IsClassic and nil or category.dodgeRating, category.dodge or nil, - (not ECS.IsClassic) and category.resilienceRating or nil + IsClassic and nil or category.resilienceRating ) + if category.display then + category = category.mechanicResistance + _CreateStatInfo( + category, + category.stun, + (IsWotlk or (not classId == Data.WARRIOR)) and nil or category.charm, + (IsClassic and not classId == Data.PALADIN) and nil or category.disorient, + (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.root, + (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.snare, + (IsClassic or (classId == Data.PRIEST or classId == Data.MAGE or classId == Data.WARLOCK)) and category.silence or nil, + category.interrupt, + category.fleeing, + IsTBC and category.horror or nil, + (IsTBC and classId == Data.PALADIN) and nil or category.curse, + (IsTBC and classId == Data.PALADIN) and nil or category.disease, + (IsTBC and classId == Data.ROGUE) and nil or category.poison + ) + end if UnitHasMana("player") then category = profile.regen @@ -305,12 +349,12 @@ _CreateStatInfos = function() local spellHit = spell.hit _CreateStatInfo( category, - (not ECS.IsClassic) and category.hasteRating or nil, + IsClassic and nil or category.hasteRating, category.hasteBonus, - (not ECS.IsClassic) and category.penetrationRating or nil, - (not ECS.IsClassic) and category.penetration or nil, + IsClassic and nil or category.penetrationRating, + IsClassic and nil or category.penetration, spellBonus.bonusHealing, - (not ECS.IsClassic) and spellHit.rating or nil, + IsClassic and nil or spellHit.rating, spell.arcane.display and spellBonus.arcaneDmg or nil, spell.arcane.display and spellCrit.display and spellCrit.arcane or nil, spell.arcane.display and spellHit.bonus.display and spellHit.arcaneHitBonus or nil, @@ -360,7 +404,7 @@ _CreateHeader = function(name, displayText, isSubHeader) end lastYOffset = lastYOffset - 20 ---@class StatsHeader - local header = table.remove(framePool) + local header = remove(framePool) if not header then header = _Stats.frame.ScrollChild:CreateFontString(name, "OVERLAY", headerFont) else @@ -385,7 +429,7 @@ _CreateText = function(name, displayText, isSubText) lastYOffset = lastYOffset - 15 ---@class StatsText - local stat = table.remove(framePool) + local stat = remove(framePool) if not stat then stat = _Stats.frame.ScrollChild:CreateFontString(name, "OVERLAY", statFont) else @@ -402,7 +446,7 @@ end ---@param frame StatsHeader|StatsText function Stats:RecycleFrame(frame) frame:Hide() - table.insert(framePool, frame) + insert(framePool, frame) end --- Resets the Y-Offset and rebuilds the displayed frames From 0cb3d05bc4ed8842684843732b568ef0e8d1b72b Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Sat, 28 Feb 2026 04:41:45 +0100 Subject: [PATCH 3/6] wip --- Modules/Data/Data.lua | 13 +++++++++ Modules/Migration.lua | 16 +++++++++++ Modules/Profile.lua | 67 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/Modules/Data/Data.lua b/Modules/Data/Data.lua index 4d1f3fe1..bf6ffcbf 100755 --- a/Modules/Data/Data.lua +++ b/Modules/Data/Data.lua @@ -4,6 +4,7 @@ local Data = ECSLoader:CreateModule("Data") local dataFunctionRefs local playerLevel = UnitLevel("player") local enemyLevel = playerLevel + 3 +local mechanicResistance = Data:GetMechanicResistance() ---@param refName string ---@return number | string @@ -67,6 +68,18 @@ dataFunctionRefs = { ["BlockChance"] = function() return Data:GetBlockChance() end, ["BlockValue"] = function() return Data:GetBlockValue() end, ["ResilienceValue"] = function() return ECS.IsClassic and 0 or Data:GetResilienceRating() end, + ["StunResistance"] = function() return mechanicResistance.stun end, + ["CharmResistance"] = function() return mechanicResistance.charm end, + ["DisorientResistance"] = function() return mechanicResistance.disorient end, + ["RootResistance"] = function() return mechanicResistance.root end, + ["SnareResistance"] = function() return mechanicResistance.snare end, + ["InterruptResistance"] = function() return mechanicResistance.interrupt end, + ["SilenceResistance"] = function() return mechanicResistance.silence end, + ["FleeingResistance"] = function() return mechanicResistance.fleeing end, + ["HorrorResistance"] = function() return mechanicResistance.horror end, + ["DiseaseResistance"] = function() return mechanicResistance.disease end, + ["CurseResistance"] = function() return mechanicResistance.curse end, + ["PoisonResistance"] = function() return mechanicResistance.poison end, -- Spell ["SpellHitRating"] = function() return ECS.IsClassic and 0 or Data:SpellHitRating() end, ["SpellHitBonus"] = function() return Data.SpellHitBonus(Data.HOLY_SCHOOL) end, diff --git a/Modules/Migration.lua b/Modules/Migration.lua index 0f1bf19b..cd1c8f22 100644 --- a/Modules/Migration.lua +++ b/Modules/Migration.lua @@ -15,6 +15,8 @@ function Migration:ToLatestProfileVersion(profileVersion) return end + local defaultProfile = Profile:GetDefaultProfile() + if profileVersion < 24 then ExtendedCharacterStats.profile.defense.resilienceRating = ExtendedCharacterStats.profile.defense.resilience ExtendedCharacterStats.profile.defense.resilience = nil @@ -22,4 +24,18 @@ function Migration:ToLatestProfileVersion(profileVersion) if profileVersion < 25 then ExtendedCharacterStats.profile.defense.resilience = nil end + if profileVersion < 100 then + ExtendedCharacterStats.profile.defense.stunReduction = defaultProfile.profile.defense.stunReduction + ExtendedCharacterStats.profile.defense.snareReduction = defaultProfile.profile.defense.snareReduction + ExtendedCharacterStats.profile.defense.rootReduction = defaultProfile.profile.defense.rootReduction + ExtendedCharacterStats.profile.defense.disorientReduction = defaultProfile.profile.defense.disorientReduction + ExtendedCharacterStats.profile.defense.charmReduction = defaultProfile.profile.defense.charmReduction + ExtendedCharacterStats.profile.defense.horrorReduction = defaultProfile.profile.defense.horrorReduction + ExtendedCharacterStats.profile.defense.fleeingReduction = defaultProfile.profile.defense.fleeingReduction + ExtendedCharacterStats.profile.defense.interruptReduction = defaultProfile.profile.defense.interruptReduction + ExtendedCharacterStats.profile.defense.silenceReduction = defaultProfile.profile.defense.silenceReduction + ExtendedCharacterStats.profile.defense.poisonReduction = defaultProfile.profile.defense.poisonReduction + ExtendedCharacterStats.profile.defense.curseReduction = defaultProfile.profile.defense.curseReduction + ExtendedCharacterStats.profile.defense.diseaseReduction = defaultProfile.profile.defense.diseaseReduction + end end diff --git a/Modules/Profile.lua b/Modules/Profile.lua index 2a2152fe..420eed55 100755 --- a/Modules/Profile.lua +++ b/Modules/Profile.lua @@ -289,6 +289,73 @@ local function GetDefaultStatsProfile() refName = "ResilienceValue", text = "Resilience" }, + ---@type SubCategory + mechanicResistance = { + display = true, + refName = "MechanicResistanceHeader", + text = "Mechanic resistance", + isSubGroup = true, + stun = { + display = true, + refName = "StunResistance", + text = "Stun", + }, + charm = { + display = true, + refName = "CharmResistance", + text = "Charm", + }, + disorient = { + display = true, + refName = "DisorientResistance", + text = "Disorient", + }, + snare = { + display = true, + refName = "SnareResistance", + text = "Snare", + }, + root = { + display = true, + refName = "RootResistance", + text = "Root", + }, + interrupt = { + display = true, + refName = "InterruptResistance", + text = "Interrupt", + }, + silence = { + display = true, + refName = "SilenceResistance", + text = "Silence", + }, + horror = { + display = true, + refName = "HorrorResistance", + text = "Horror", + }, + fleeing = { + display = true, + refName = "FleeingResistance", + text = "Fear", + }, + curse = { + display = true, + refName = "CurseResistance", + text = "Curse", + }, + disease = { + display = true, + refName = "DiseaseResistance", + text = "Disease", + }, + poison = { + display = true, + refName = "PoisonResistance", + text = "Poison", + }, + }, }, regen = { From b49734d139b9c9e2fd058f4b19988cb877c2af6a Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Sat, 28 Feb 2026 04:46:48 +0100 Subject: [PATCH 4/6] wip --- Modules/Config/DefenseSection.lua | 4 ++-- Modules/Stats.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Config/DefenseSection.lua b/Modules/Config/DefenseSection.lua index 4d598bae..8b45d3e9 100755 --- a/Modules/Config/DefenseSection.lua +++ b/Modules/Config/DefenseSection.lua @@ -256,7 +256,7 @@ function _Config:LoadDefenseSection() end, width = 1.5, hidden = function() - return (IsWotlk or (not classId == Data.WARRIOR)) + return (IsWotlk or (not (classId == Data.WARRIOR))) end, disabled = function() return ( @@ -283,7 +283,7 @@ function _Config:LoadDefenseSection() end, width = 1.5, hidden = function() - return (IsClassic and not classId == Data.PALADIN) + return (IsClassic and not (classId == Data.PALADIN)) end, disabled = function() return ( diff --git a/Modules/Stats.lua b/Modules/Stats.lua index 620f04ab..4990543a 100755 --- a/Modules/Stats.lua +++ b/Modules/Stats.lua @@ -323,8 +323,8 @@ _CreateStatInfos = function() _CreateStatInfo( category, category.stun, - (IsWotlk or (not classId == Data.WARRIOR)) and nil or category.charm, - (IsClassic and not classId == Data.PALADIN) and nil or category.disorient, + (IsWotlk or (not (classId == Data.WARRIOR))) and nil or category.charm, + (IsClassic and not (classId == Data.PALADIN)) and nil or category.disorient, (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.root, (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.snare, (IsClassic or (classId == Data.PRIEST or classId == Data.MAGE or classId == Data.WARLOCK)) and category.silence or nil, From 462b8e08d771f64a814f5741390318b9cd3ed100 Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Sat, 28 Feb 2026 04:52:03 +0100 Subject: [PATCH 5/6] wip --- Modules/Config/DefenseSection.lua | 4 ++-- Modules/Data/Defense.lua | 2 +- Modules/Stats.lua | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/Config/DefenseSection.lua b/Modules/Config/DefenseSection.lua index 8b45d3e9..662f1cdd 100755 --- a/Modules/Config/DefenseSection.lua +++ b/Modules/Config/DefenseSection.lua @@ -256,7 +256,7 @@ function _Config:LoadDefenseSection() end, width = 1.5, hidden = function() - return (IsWotlk or (not (classId == Data.WARRIOR))) + return (IsWotlk or (classId ~= Data.WARRIOR)) end, disabled = function() return ( @@ -283,7 +283,7 @@ function _Config:LoadDefenseSection() end, width = 1.5, hidden = function() - return (IsClassic and not (classId == Data.PALADIN)) + return (IsClassic and (classId ~= Data.PALADIN)) end, disabled = function() return ( diff --git a/Modules/Data/Defense.lua b/Modules/Data/Defense.lua index d368eb34..b781a603 100755 --- a/Modules/Data/Defense.lua +++ b/Modules/Data/Defense.lua @@ -257,7 +257,7 @@ function _Defense:GetEnchantsBlockValue() end ---@return table -function _Defense:GetMechanicResistance() +function Data:GetMechanicResistance() local resistance = { ["charm"] = 0, ["curse"] = 0, diff --git a/Modules/Stats.lua b/Modules/Stats.lua index 4990543a..72b9478f 100755 --- a/Modules/Stats.lua +++ b/Modules/Stats.lua @@ -323,8 +323,8 @@ _CreateStatInfos = function() _CreateStatInfo( category, category.stun, - (IsWotlk or (not (classId == Data.WARRIOR))) and nil or category.charm, - (IsClassic and not (classId == Data.PALADIN)) and nil or category.disorient, + (IsWotlk or (classId ~= Data.WARRIOR)) and nil or category.charm, + (IsClassic and (classId ~= Data.PALADIN)) and nil or category.disorient, (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.root, (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.snare, (IsClassic or (classId == Data.PRIEST or classId == Data.MAGE or classId == Data.WARLOCK)) and category.silence or nil, From 65a1dab65c28703a6d61d73867ea4a3e730dab22 Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Mon, 2 Mar 2026 20:09:47 +0100 Subject: [PATCH 6/6] revert --- Modules/Data/Constants.lua | 16 ++++++------- Modules/Stats.lua | 48 +++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Modules/Data/Constants.lua b/Modules/Data/Constants.lua index 4d8264cf..037c79a3 100755 --- a/Modules/Data/Constants.lua +++ b/Modules/Data/Constants.lua @@ -356,8 +356,8 @@ Data.Aura = { [25918] = (ECS.IsClassic and 1 or nil), -- Greater Blessing of Wisdom rank 2 }, ResistanceInterrupt = { - [14743] = IsWotlk and nil or 10, -- Focused Casting - [27828] = IsWotlk and nil or 20, -- Focused Casting + [14743] = (not IsWotlk) and 10 or nil, -- Focused Casting + [27828] = (not IsWotlk) and 20 or nil, -- Focused Casting }, SpellCrit = { [24907] = ((not ECS.IsClassic) and 5 or nil), -- Moonkin Aura @@ -528,14 +528,14 @@ Data.Gem = { [42146] = 17, -- Lustrous Dragon's Eye }, ResistRoot = { - [32195] = (IsWotlk and nil or 5), -- Enigmatic Skyfire Diamond + [32195] = (not IsWotlk) and 5 or nil, -- Enigmatic Skyfire Diamond }, ResistSnare = { - [32195] = (IsWotlk and nil or 5), -- Enigmatic Skyfire Diamond + [32195] = (not IsWotlk) and 5 or nil, -- Enigmatic Skyfire Diamond }, ResistStun = { - [25896] = (IsWotlk and nil or 5), -- Powerful Earthstorm Diamond - [32195] = (IsWotlk and nil or 5), -- Enigmatic Skyfire Diamond + [25896] = (not IsWotlk) and 5 or nil, -- Powerful Earthstorm Diamond + [32195] = (not IsWotlk) and 5 or nil, -- Enigmatic Skyfire Diamond [32641] = 5, -- Imbued Unstable Diamond [32640] = 5, -- Potent Unstable Diamond } @@ -667,7 +667,7 @@ Data.Item = { [30519] = 10, -- Foreman's Reinforced Helmet }, ResistFleeing = { - [17759] = (IsWotlk and nil or 1), -- Mark of Resolution + [17759] = (not IsWotlk) and 1 or nil, -- Mark of Resolution [28428] = 8, -- Lionheart Blade [28429] = 8, -- Lionheart Champion [28430] = 8, -- Lionheart Executioner @@ -679,7 +679,7 @@ Data.Item = { [234134] = 10, -- Gnomish Turban of Psychic Might }, ResistStun = { - [17759] = (IsWotlk and nil or 1), -- Mark of Resolution + [17759] = (not IsWotlk) and 1 or nil, -- Mark of Resolution [23838] = 10, -- Foreman's Enchanted Helmet [30519] = 10, -- Foreman's Reinforced Helmet }, diff --git a/Modules/Stats.lua b/Modules/Stats.lua index 72b9478f..cad00736 100755 --- a/Modules/Stats.lua +++ b/Modules/Stats.lua @@ -244,17 +244,17 @@ _CreateStatInfos = function() category.attackPower, category.crit, IsWotlk and category.penetrationRating or nil, - IsClassic and nil or category.penetration, - IsClassic and nil or category.expertiseRating, - IsClassic and nil or category.expertise, - IsClassic and nil or category.hasteRating, - IsClassic and nil or category.hasteBonus + (not IsClassic) and category.penetration or nil, + (not IsClassic) and category.expertiseRating or nil, + (not IsClassic) and category.expertise or nil, + (not IsClassic) and category.hasteRating or nil, + (not IsClassic) and category.hasteBonus or nil ) if category.display then category = category.hit _CreateStatInfo( category, - IsClassic and nil or category.rating, + (not IsClassic) and category.rating or nil, category.bonus, category.sameLevel, category.bossLevel @@ -280,9 +280,9 @@ _CreateStatInfos = function() category.attackPower, category.crit, IsWotlk and category.penetrationRating or nil, - IsClassic and nil or category.penetration, - IsClassic and nil or category.hasteRating, - IsClassic and nil or category.hasteBonus, + (not IsClassic) and category.penetration or nil, + (not IsClassic) and category.hasteRating or nil, + (not IsClassic) and category.hasteBonus or nil, category.attackSpeed ) @@ -290,7 +290,7 @@ _CreateStatInfos = function() category = category.hit _CreateStatInfo( category, - IsClassic and nil or category.rating, + (not IsClassic) and category.rating or nil, category.bonus, category.sameLevel, category.bossLevel @@ -307,33 +307,33 @@ _CreateStatInfos = function() category.spellCritReduction, category.avoidance, category.avoidanceBoss, - IsClassic and nil or category.defenseRating, + (not IsClassic) and category.defenseRating or nil, category.defense, (not IsClassic and DataUtils:CanBlock()) and category.blockRating or nil, DataUtils:CanBlock() and category.blockChance or nil, DataUtils:CanBlock() and category.blockValue or nil, (not IsClassic and DataUtils:CanParry()) and category.parryRating or nil, DataUtils:CanParry() and category.parry or nil, - IsClassic and nil or category.dodgeRating, + (not IsClassic) and category.dodgeRating or nil, category.dodge or nil, - IsClassic and nil or category.resilienceRating + (not IsClassic) and category.resilienceRating or nil ) if category.display then category = category.mechanicResistance _CreateStatInfo( category, category.stun, - (IsWotlk or (classId ~= Data.WARRIOR)) and nil or category.charm, - (IsClassic and (classId ~= Data.PALADIN)) and nil or category.disorient, - (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.root, - (IsWotlk or not (IsClassic and classId == Data.HUNTER)) and nil or category.snare, + ((not IsWotlk) and (classId == Data.WARRIOR)) and category.charm or nil, + ((not IsClassic) or (classId == Data.PALADIN)) and category.disorient or nil, + ((not IsWotlk) and IsClassic and (classId == Data.HUNTER)) and category.root or nil, + ((not IsWotlk) and IsClassic and (classId == Data.HUNTER)) and category.snare or nil, (IsClassic or (classId == Data.PRIEST or classId == Data.MAGE or classId == Data.WARLOCK)) and category.silence or nil, category.interrupt, category.fleeing, IsTBC and category.horror or nil, - (IsTBC and classId == Data.PALADIN) and nil or category.curse, - (IsTBC and classId == Data.PALADIN) and nil or category.disease, - (IsTBC and classId == Data.ROGUE) and nil or category.poison + (not IsTBC) or (classId ~= Data.PALADIN) and category.curse or nil, + (not IsTBC) or (classId ~= Data.PALADIN) and category.disease or nil, + (not IsTBC) or (classId ~= Data.ROGUE) and category.poison or nil ) end @@ -349,12 +349,12 @@ _CreateStatInfos = function() local spellHit = spell.hit _CreateStatInfo( category, - IsClassic and nil or category.hasteRating, + (not IsClassic) and category.hasteRating or nil, category.hasteBonus, - IsClassic and nil or category.penetrationRating, - IsClassic and nil or category.penetration, + (not IsClassic) and category.penetrationRating or nil, + (not IsClassic) and category.penetration or nil, spellBonus.bonusHealing, - IsClassic and nil or spellHit.rating, + (not IsClassic) and spellHit.rating or nil, spell.arcane.display and spellBonus.arcaneDmg or nil, spell.arcane.display and spellCrit.display and spellCrit.arcane or nil, spell.arcane.display and spellHit.bonus.display and spellHit.arcaneHitBonus or nil,