From 2e2d21e5f37658754a2e214792d87c58f2e82709 Mon Sep 17 00:00:00 2001 From: NoM0Re Date: Mon, 31 Mar 2025 20:12:10 +0200 Subject: [PATCH] (fix/Prototypes) Class&Spec Load/Triggers - Closes #37 Due to an error in the implementation of Class & Spec in Load Conditions and Triggers (Unit Characteristics, Power, Health, Class/Spec, BT2 actualSpec), the system now also applies Retail logic. As a result of this issue, all data has been erased and must be reselected. --- WeakAuras/Modernize.lua | 45 ++++++++++ WeakAuras/Prototypes.lua | 41 +++++---- WeakAuras/Types.lua | 180 ++++++++++++++++++++++++++++++--------- WeakAuras/WeakAuras.lua | 2 +- 4 files changed, 212 insertions(+), 56 deletions(-) diff --git a/WeakAuras/Modernize.lua b/WeakAuras/Modernize.lua index 82e4748..32356bd 100644 --- a/WeakAuras/Modernize.lua +++ b/WeakAuras/Modernize.lua @@ -2054,6 +2054,51 @@ function Private.Modernize(data, oldSnapshot) end end + if data.internalVersion < 83.25 then + -- Due to a Localisation issue and a bad implementation clear out all class/spec triggers that contain strings + local function replaceSpecData(data, field, bt2) + if data[field] then + if bt2 then + for specKey in pairs(data[field]) do + if type(specKey) == "string" then + data[field] = nil + data[bt2] = nil + end + end + return + end + if data[field].multi then + for specKey in pairs(data[field].multi) do + if type(specKey) == "string" then + data[field] = { multi = {} } + data["use_" .. field] = nil + return + end + end + end + if type(data[field].single) == "string" then + data[field] = { multi = {} } + data["use_" .. field] = nil + end + end + end + + if data.load then + replaceSpecData(data.load, "class_and_spec") + end + if data.triggers then + for _, triggerData in ipairs(data.triggers) do + local trigger = triggerData.trigger + if trigger and (trigger.event == "Unit Characteristics" or trigger.event == "Power" or + trigger.event == "Health" or trigger.event == "Class/Spec") then + replaceSpecData(trigger, "specId") + elseif trigger and trigger.type == "aura2" then + replaceSpecData(trigger, "actualSpec", "useActualSpec") + end + end + end + end + data.internalVersion = max(data.internalVersion or 0, WeakAuras.InternalVersion()) end diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 1c3fc68..de40d38 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -575,12 +575,12 @@ function WeakAuras.CheckTalentByIndex(index, extraOption) return result; end -function WeakAuras.CheckClassSpec(class, test) - if type(class) == "string" or type(test) == "string" then - local spec = WeakAuras.LGT:GetUnitTalentSpec('player') or "" - return (class .. spec) == test - end - return false +function WeakAuras.CheckClassSpec(specID) + specID = tonumber(specID) + if not specID then return end + local class = select(2, UnitClass("player")) or "" + local currentSpec = WeakAuras.LGT:GetUnitTalentSpec("player") or "" + return specID and Private.ExecEnv.GetSpecName(specID) == class .. currentSpec end function WeakAuras.CheckNumericIds(loadids, currentId) @@ -668,8 +668,23 @@ Private.tinySecondFormat = function(value) end end -function Private.ExecEnv.GetSpecIcon(classspec) - return Private.spec[classspec] or "" +function Private.ExecEnv.GetSpecIcon(specID) + return specID and Private.specid_to_icon[specID] or "" +end + +function Private.ExecEnv.GetSpecName(specID) + return specID and Private.specid_to_name[specID] or "" +end + +function Private.ExecEnv.GetSpecID(specName) + return specName and Private.specname_to_id[specName] or 0 +end + +function WeakAuras.SpecForUnit(unit) + if not unit then return 0 end + local spec = WeakAuras.LGT:GetUnitTalentSpec(unit) + local class = select(2, UnitClass(unit)) + return (spec and class) and Private.ExecEnv.GetSpecID(class .. spec) or 0 end function Private.ExecEnv.ParseStringCheck(input) @@ -800,12 +815,6 @@ function Private.ExecEnv.CheckCombatLogFlagsObjectType(flags, flagToCheck) return bit.band(flags, bitToCheck) ~= 0; end -function WeakAuras.SpecForUnit(unit) - local spec = WeakAuras.LGT:GetUnitTalentSpec(unit) - local class = select(2, UnitClass(unit)) - return spec and class and (class .. spec) -end - function WeakAuras.IsSpellKnownForLoad(spell, exact) local result = WeakAuras.IsSpellKnown(spell) if exact or result then @@ -1028,7 +1037,7 @@ Private.load_prototype = { display = L["Class and Specialization"], type = "multiselect", values = "spec_types_all", - test = "WeakAuras.CheckClassSpec(class, %s)", + test = "WeakAuras.CheckClassSpec(%s)", events = {"UNIT_SPEC_CHANGED_player", "WA_DELAYED_PLAYER_ENTERING_WORLD"}, }, { @@ -4839,7 +4848,7 @@ Private.event_prototypes = { local class = select(2, UnitClass("player")) or "UNKNOWN" return ([[ local specName = WeakAuras.LGT:GetUnitTalentSpec("player") or "Unknown" - local specId = "%s" .. specName + local specId = Private.ExecEnv.GetSpecID("%s" .. specName) local specIcon = Private.ExecEnv.GetSpecIcon(specId) ]]):format(class) end, diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index 7da2d89..b619267 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -3294,105 +3294,207 @@ do DEATHKNIGHT = { icon = "Interface\\Icons\\Spell_Deathknight_ClassIcon", specs = { - [L["Unholy"]] = "Interface\\Icons\\Spell_Deathknight_UnholyPresence", - [L["Frost"]] = "Interface\\Icons\\Spell_Deathknight_FrostPresence", - [L["Blood"]] = "Interface\\Icons\\Spell_Deathknight_BloodPresence", + [250] = { name = L["Blood"], icon = "Interface\\Icons\\Spell_Deathknight_BloodPresence" }, + [251] = { name = L["Frost"], icon = "Interface\\Icons\\Spell_Deathknight_FrostPresence" }, + [252] = { name = L["Unholy"], icon = "Interface\\Icons\\Spell_Deathknight_UnholyPresence" }, } }, DRUID = { icon = "Interface\\Icons\\Ability_Druid_Maul", specs = { - [L["Balance"]] = "Interface\\Icons\\Spell_Nature_StarFall", - [L["Restoration"]] = "Interface\\Icons\\Spell_Nature_HealingTouch", - [L["Feral Combat"]] = "Interface\\Icons\\Ability_Racial_BearForm", - [L["Guardian"]] = "Interface\\Icons\\Ability_Racial_BearForm", + [102] = { name = L["Balance"], icon = "Interface\\Icons\\Spell_Nature_StarFall" }, + [103] = { name = L["Feral"], icon = "Interface\\Icons\\Ability_Racial_BearForm" }, + [104] = { name = L["Guardian"], icon = "Interface\\Icons\\Ability_Racial_BearForm" }, + [105] = { name = L["Restoration"], icon = "Interface\\Icons\\Spell_Nature_HealingTouch" }, } }, HUNTER = { icon = "Interface\\Icons\\INV_Weapon_Bow_07", specs = { - [L["Marksmanship"]] = "Interface\\Icons\\Ability_Marksmanship", - [L["Beast Mastery"]] = "Interface\\Icons\\Ability_Hunter_BeastTaming", - [L["Survival"]] = "Interface\\Icons\\Ability_Hunter_SwiftStrike", + [253] = { name = L["Beast Mastery"], icon = "Interface\\Icons\\Ability_Hunter_BeastTaming" }, + [254] = { name = L["Marksmanship"], icon = "Interface\\Icons\\Ability_Marksmanship" }, + [255] = { name = L["Survival"], icon = "Interface\\Icons\\Ability_Hunter_SwiftStrike" }, } }, MAGE = { icon = "Interface\\Icons\\INV_Staff_13", specs = { - [L["Fire"]] = "Interface\\Icons\\Spell_Fire_FireBolt02", - [L["Frost"]] = "Interface\\Icons\\Spell_Frost_FrostBolt02", - [L["Arcane"]] = "Interface\\Icons\\Spell_Holy_MagicalSentry", + [62] = { name = L["Arcane"], icon = "Interface\\Icons\\Spell_Holy_MagicalSentry" }, + [63] = { name = L["Fire"], icon = "Interface\\Icons\\Spell_Fire_FireBolt02" }, + [64] = { name = L["Frost"], icon = "Interface\\Icons\\Spell_Frost_FrostBolt02" }, } }, PALADIN = { icon = "Interface\\Icons\\INV_Hammer_01", specs = { - [L["Protection"]] = "Interface\\Icons\\Spell_Holy_DevotionAura", - [L["Holy"]] = "Interface\\Icons\\Spell_Holy_HolyBolt", - [L["Retribution"]] = "Interface\\Icons\\Spell_Holy_AuraOfLight", + [65] = { name = L["Holy"], icon = "Interface\\Icons\\Spell_Holy_HolyBolt" }, + [66] = { name = L["Protection"], icon = "Interface\\Icons\\Spell_Holy_DevotionAura" }, + [70] = { name = L["Retribution"], icon = "Interface\\Icons\\Spell_Holy_AuraOfLight" }, } }, PRIEST = { icon = "Interface\\Icons\\INV_Staff_30", specs = { - [L["Discipline"]] = "Interface\\Icons\\Spell_Holy_WordFortitude", - [L["Holy"]] = "Interface\\Icons\\Spell_Holy_GuardianSpirit", - [L["Shadow"]] = "Interface\\Icons\\Spell_Shadow_ShadowWordPain", + [256] = { name = L["Discipline"], icon = "Interface\\Icons\\Spell_Holy_WordFortitude" }, + [257] = { name = L["Holy"], icon = "Interface\\Icons\\Spell_Holy_GuardianSpirit" }, + [258] = { name = L["Shadow"], icon = "Interface\\Icons\\Spell_Shadow_ShadowWordPain" }, } }, ROGUE = { icon = "Interface\\Icons\\INV_ThrowingKnife_04", specs = { - [L["Subtlety"]] = "Interface\\Icons\\Ability_Stealth", - [L["Combat"]] = "Interface\\Icons\\Ability_BackStab", - [L["Assassination"]] = "Interface\\Icons\\Ability_Rogue_Eviscerate", + [259] = { name = L["Assassination"], icon = "Interface\\Icons\\Ability_Rogue_Eviscerate" }, + [260] = { name = L["Combat"], icon = "Interface\\Icons\\Ability_BackStab" }, + [261] = { name = L["Subtlety"], icon = "Interface\\Icons\\Ability_Stealth" }, } }, SHAMAN = { icon = "Interface\\Icons\\Spell_Nature_BloodLust", specs = { - [L["Enhancement"]] = "Interface\\Icons\\Spell_Nature_LightningShield", - [L["Elemental"]] = "Interface\\Icons\\Spell_Nature_Lightning", - [L["Restoration"]] = "Interface\\Icons\\Spell_Nature_MagicImmunity", + [262] = { name = L["Elemental"], icon = "Interface\\Icons\\Spell_Nature_Lightning" }, + [263] = { name = L["Enhancement"], icon = "Interface\\Icons\\Spell_Nature_LightningShield" }, + [264] = { name = L["Restoration"], icon = "Interface\\Icons\\Spell_Nature_MagicImmunity" }, } }, WARLOCK = { icon = "Interface\\Icons\\Spell_Nature_FaerieFire", specs = { - [L["Demonology"]] = "Interface\\Icons\\Spell_Shadow_Metamorphosis", - [L["Affliction"]] = "Interface\\Icons\\Spell_Shadow_DeathCoil", - [L["Destruction"]] = "Interface\\Icons\\Spell_Shadow_RainOfFire", + [265] = { name = L["Affliction"], icon = "Interface\\Icons\\Spell_Shadow_DeathCoil" }, + [266] = { name = L["Demonology"], icon = "Interface\\Icons\\Spell_Shadow_Metamorphosis" }, + [267] = { name = L["Destruction"], icon = "Interface\\Icons\\Spell_Shadow_RainOfFire" }, } }, WARRIOR = { icon = "Interface\\Icons\\INV_Sword_27", specs = { - [L["Arms"]] = "Interface\\Icons\\Ability_Rogue_Eviscerate", - [L["Protection"]] = "Interface\\Icons\\INV_Shield_06", - [L["Fury"]] = "Interface\\Icons\\Ability_Warrior_InnerRage", + [71] = { name = L["Arms"], icon = "Interface\\Icons\\Ability_Rogue_Eviscerate" }, + [72] = { name = L["Fury"], icon = "Interface\\Icons\\Ability_Warrior_InnerRage" }, + [73] = { name = L["Protection"], icon = "Interface\\Icons\\INV_Shield_06" }, } }, } - - local function createSpecString(class, spec) + -- Creates the options layout. Due to CUSTOM_CLASS_COLORS, it needs to be created dynamically. + local function createSpecString(class, specID) local data = classData[class] + if not data then return "" end local classIcon = data.icon or "Interface\\Icons\\INV_Misc_QuestionMark" - local specIcon = data.specs[spec] or "Interface\\Icons\\INV_Misc_QuestionMark" + local specData = data.specs[specID] or { icon = "Interface\\Icons\\INV_Misc_QuestionMark", name = "Unknown" } local color = WA_GetClassColor(class) - return ("|T%s:0|t |T%s:0|t |c%s%s|r"):format(classIcon, specIcon, color, spec) + return ("|T%s:0|t |T%s:0|t |c%s%s|r"):format(classIcon, specData.icon, color, specData.name) end Private.spec_types_all = {} Private.spec = {} for class, data in pairs(classData) do - for specName, specIcon in pairs(data.specs) do - local key = class .. specName - Private.spec_types_all[key] = createSpecString(class, specName) - Private.spec[key] = specIcon + for specID in pairs(data.specs) do + Private.spec_types_all[specID] = createSpecString(class, specID) end end + wipe(classData) end +Private.specid_to_icon = { + [250] = "Interface\\Icons\\Spell_Deathknight_BloodPresence", + [251] = "Interface\\Icons\\Spell_Deathknight_FrostPresence", + [252] = "Interface\\Icons\\Spell_Deathknight_UnholyPresence", + [102] = "Interface\\Icons\\Spell_Nature_StarFall", + [103] = "Interface\\Icons\\Ability_Racial_BearForm", + [104] = "Interface\\Icons\\Ability_Racial_BearForm", + [105] = "Interface\\Icons\\Spell_Nature_HealingTouch", + [253] = "Interface\\Icons\\Ability_Hunter_BeastTaming", + [254] = "Interface\\Icons\\Ability_Marksmanship", + [255] = "Interface\\Icons\\Ability_Hunter_SwiftStrike", + [62] = "Interface\\Icons\\Spell_Holy_MagicalSentry", + [63] = "Interface\\Icons\\Spell_Fire_FireBolt02", + [64] = "Interface\\Icons\\Spell_Frost_FrostBolt02", + [65] = "Interface\\Icons\\Spell_Holy_HolyBolt", + [66] = "Interface\\Icons\\Spell_Holy_DevotionAura", + [70] = "Interface\\Icons\\Spell_Holy_AuraOfLight", + [256] = "Interface\\Icons\\Spell_Holy_WordFortitude", + [257] = "Interface\\Icons\\Spell_Holy_GuardianSpirit", + [258] = "Interface\\Icons\\Spell_Shadow_ShadowWordPain", + [259] = "Interface\\Icons\\Ability_Rogue_Eviscerate", + [260] = "Interface\\Icons\\Ability_BackStab", + [261] = "Interface\\Icons\\Ability_Stealth", + [262] = "Interface\\Icons\\Spell_Nature_Lightning", + [263] = "Interface\\Icons\\Spell_Nature_LightningShield", + [264] = "Interface\\Icons\\Spell_Nature_MagicImmunity", + [265] = "Interface\\Icons\\Spell_Shadow_DeathCoil", + [266] = "Interface\\Icons\\Spell_Shadow_Metamorphosis", + [267] = "Interface\\Icons\\Spell_Shadow_RainOfFire", + [71] = "Interface\\Icons\\Ability_Rogue_Eviscerate", + [72] = "Interface\\Icons\\Ability_Warrior_InnerRage", + [73] = "Interface\\Icons\\INV_Shield_06", +} + +Private.specname_to_id = { + ["DEATHKNIGHT" .. L["Blood"]] = 250, + ["DEATHKNIGHT" .. L["Frost"]] = 251, + ["DEATHKNIGHT" .. L["Unholy"]] = 252, + ["DRUID" .. L["Balance"]] = 102, + ["DRUID" .. L["Feral"]] = 103, + ["DRUID" .. L["Guardian"]] = 104, + ["DRUID" .. L["Restoration"]] = 105, + ["HUNTER" .. L["Beast Mastery"]] = 253, + ["HUNTER" .. L["Marksmanship"]] = 254, + ["HUNTER" .. L["Survival"]] = 255, + ["MAGE" .. L["Arcane"]] = 62, + ["MAGE" .. L["Fire"]] = 63, + ["MAGE" .. L["Frost"]] = 64, + ["PALADIN" .. L["Holy"]] = 65, + ["PALADIN" .. L["Protection"]] = 66, + ["PALADIN" .. L["Retribution"]] = 70, + ["PRIEST" .. L["Discipline"]] = 256, + ["PRIEST" .. L["Holy"]] = 257, + ["PRIEST" .. L["Shadow"]] = 258, + ["ROGUE" .. L["Assassination"]] = 259, + ["ROGUE" .. L["Combat"]] = 260, + ["ROGUE" .. L["Subtlety"]] = 261, + ["SHAMAN" .. L["Elemental"]] = 262, + ["SHAMAN" .. L["Enhancement"]] = 263, + ["SHAMAN" .. L["Restoration"]] = 264, + ["WARLOCK" .. L["Affliction"]] = 265, + ["WARLOCK" .. L["Demonology"]] = 266, + ["WARLOCK" .. L["Destruction"]] = 267, + ["WARRIOR" .. L["Arms"]] = 71, + ["WARRIOR" .. L["Fury"]] = 72, + ["WARRIOR" .. L["Protection"]] = 73, +} + +Private.specid_to_name = { + [250] = "DEATHKNIGHT" .. L["Blood"], + [251] = "DEATHKNIGHT" .. L["Frost"], + [252] = "DEATHKNIGHT" .. L["Unholy"], + [102] = "DRUID" .. L["Balance"], + [103] = "DRUID" .. L["Feral"], + [104] = "DRUID" .. L["Guardian"], + [105] = "DRUID" .. L["Restoration"], + [253] = "HUNTER" .. L["Beast Mastery"], + [254] = "HUNTER" .. L["Marksmanship"], + [255] = "HUNTER" .. L["Survival"], + [62] = "MAGE" .. L["Arcane"], + [63] = "MAGE" .. L["Fire"], + [64] = "MAGE" .. L["Frost"], + [65] = "PALADIN" .. L["Holy"], + [66] = "PALADIN" .. L["Protection"], + [70] = "PALADIN" .. L["Retribution"], + [256] = "PRIEST" .. L["Discipline"], + [257] = "PRIEST" .. L["Holy"], + [258] = "PRIEST" .. L["Shadow"], + [259] = "ROGUE" .. L["Assassination"], + [260] = "ROGUE" .. L["Combat"], + [261] = "ROGUE" .. L["Subtlety"], + [262] = "SHAMAN" .. L["Elemental"], + [263] = "SHAMAN" .. L["Enhancement"], + [264] = "SHAMAN" .. L["Restoration"], + [265] = "WARLOCK" .. L["Affliction"], + [266] = "WARLOCK" .. L["Demonology"], + [267] = "WARLOCK" .. L["Destruction"], + [71] = "WARRIOR" .. L["Arms"], + [72] = "WARRIOR" .. L["Fury"], + [73] = "WARRIOR" .. L["Protection"], +} + --[=[[ Old unused Talent List Private.talents_ids = { DEATHKNIGHT = {{48979,48997,49182,48978,49004,55107,48982,48987,49467,48985,49145,49015,48977,49006,49005,48988,53137,49027,49016,50365,62905,49018,55233,49189,55050,49023,61154,49028}, {49175,49455,49042,55061,49140,49226,50880,49039,51468,51123,49149,49137,49186,49471,49796,55610,49024,49188,50040,49203,50384,65661,54639,51271,49200,49143,50187,49202,49184}, {51745,48962,55129,49036,48963,49588,48965,49013,51459,49158,49146,49219,55620,49194,49220,49223,55666,49224,49208,52143,66799,51052,50391,63560,49032,49222,49217,51099,55090,50117,49206}}, diff --git a/WeakAuras/WeakAuras.lua b/WeakAuras/WeakAuras.lua index d58338b..faaf64e 100644 --- a/WeakAuras/WeakAuras.lua +++ b/WeakAuras/WeakAuras.lua @@ -1,6 +1,6 @@ local AddonName, Private = ... -local internalVersion = 83 +local internalVersion = 83.25 -- Lua APIs local insert = table.insert