From 8a5d766c6e6382b8ee095b755034bf91c9cf2af0 Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Sat, 28 Feb 2026 03:34:06 +0100 Subject: [PATCH 1/7] 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/7] 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/7] 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/7] 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/7] 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/7] 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, From 0ec035fb87b454ee38b59b750523f582cab52a3e Mon Sep 17 00:00:00 2001 From: Alessandro Barbieri Date: Wed, 4 Mar 2026 18:37:23 +0100 Subject: [PATCH 7/7] wip --- Modules/Data/Data.lua | 25 ++++++++++++------------- Modules/Data/Defense.lua | 27 ++++++++++++++------------- types/types.lua | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/Modules/Data/Data.lua b/Modules/Data/Data.lua index bf6ffcbf..1b82f062 100755 --- a/Modules/Data/Data.lua +++ b/Modules/Data/Data.lua @@ -4,7 +4,6 @@ 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 @@ -68,18 +67,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, + ["StunResistance"] = function() return Data:GetMechanicResistance().stun end, + ["CharmResistance"] = function() return Data:GetMechanicResistance().charm end, + ["DisorientResistance"] = function() return Data:GetMechanicResistance().disorient end, + ["RootResistance"] = function() return Data:GetMechanicResistance().root end, + ["SnareResistance"] = function() return Data:GetMechanicResistance().snare end, + ["InterruptResistance"] = function() return Data:GetMechanicResistance().interrupt end, + ["SilenceResistance"] = function() return Data:GetMechanicResistance().silence end, + ["FleeingResistance"] = function() return Data:GetMechanicResistance().fleeing end, + ["HorrorResistance"] = function() return Data:GetMechanicResistance().horror end, + ["DiseaseResistance"] = function() return Data:GetMechanicResistance().disease end, + ["CurseResistance"] = function() return Data:GetMechanicResistance().curse end, + ["PoisonResistance"] = function() return Data:GetMechanicResistance().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/Data/Defense.lua b/Modules/Data/Defense.lua index b781a603..58c18c9f 100755 --- a/Modules/Data/Defense.lua +++ b/Modules/Data/Defense.lua @@ -256,21 +256,22 @@ function _Defense:GetEnchantsBlockValue() return mod end ----@return table +---@return MechanicResistance function Data:GetMechanicResistance() + ---@class MechanicResistance 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, + 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 diff --git a/types/types.lua b/types/types.lua index 48e5fe55..79bce66e 100644 --- a/types/types.lua +++ b/types/types.lua @@ -8,6 +8,20 @@ ---@class Config ---@field private table +---@class MechanicResistance +---@field charm number +---@field curse number +---@field disease number +---@field disorient number +---@field fleeing number +---@field horror number +---@field interrupt number +---@field poison number +---@field root number +---@field silence number +---@field snare number +---@field stun number + ---@class Stats ---@field private table