(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.
This commit is contained in:
NoM0Re
2025-03-31 20:12:10 +02:00
committed by GitHub
parent 1ed2b94c0e
commit 2e2d21e5f3
4 changed files with 212 additions and 56 deletions
+45
View File
@@ -2054,6 +2054,51 @@ function Private.Modernize(data, oldSnapshot)
end end
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()) data.internalVersion = max(data.internalVersion or 0, WeakAuras.InternalVersion())
end end
+25 -16
View File
@@ -575,12 +575,12 @@ function WeakAuras.CheckTalentByIndex(index, extraOption)
return result; return result;
end end
function WeakAuras.CheckClassSpec(class, test) function WeakAuras.CheckClassSpec(specID)
if type(class) == "string" or type(test) == "string" then specID = tonumber(specID)
local spec = WeakAuras.LGT:GetUnitTalentSpec('player') or "" if not specID then return end
return (class .. spec) == test local class = select(2, UnitClass("player")) or ""
end local currentSpec = WeakAuras.LGT:GetUnitTalentSpec("player") or ""
return false return specID and Private.ExecEnv.GetSpecName(specID) == class .. currentSpec
end end
function WeakAuras.CheckNumericIds(loadids, currentId) function WeakAuras.CheckNumericIds(loadids, currentId)
@@ -668,8 +668,23 @@ Private.tinySecondFormat = function(value)
end end
end end
function Private.ExecEnv.GetSpecIcon(classspec) function Private.ExecEnv.GetSpecIcon(specID)
return Private.spec[classspec] or "" 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 end
function Private.ExecEnv.ParseStringCheck(input) function Private.ExecEnv.ParseStringCheck(input)
@@ -800,12 +815,6 @@ function Private.ExecEnv.CheckCombatLogFlagsObjectType(flags, flagToCheck)
return bit.band(flags, bitToCheck) ~= 0; return bit.band(flags, bitToCheck) ~= 0;
end 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) function WeakAuras.IsSpellKnownForLoad(spell, exact)
local result = WeakAuras.IsSpellKnown(spell) local result = WeakAuras.IsSpellKnown(spell)
if exact or result then if exact or result then
@@ -1028,7 +1037,7 @@ Private.load_prototype = {
display = L["Class and Specialization"], display = L["Class and Specialization"],
type = "multiselect", type = "multiselect",
values = "spec_types_all", values = "spec_types_all",
test = "WeakAuras.CheckClassSpec(class, %s)", test = "WeakAuras.CheckClassSpec(%s)",
events = {"UNIT_SPEC_CHANGED_player", "WA_DELAYED_PLAYER_ENTERING_WORLD"}, 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" local class = select(2, UnitClass("player")) or "UNKNOWN"
return ([[ return ([[
local specName = WeakAuras.LGT:GetUnitTalentSpec("player") or "Unknown" 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) local specIcon = Private.ExecEnv.GetSpecIcon(specId)
]]):format(class) ]]):format(class)
end, end,
+141 -39
View File
@@ -3294,105 +3294,207 @@ do
DEATHKNIGHT = { DEATHKNIGHT = {
icon = "Interface\\Icons\\Spell_Deathknight_ClassIcon", icon = "Interface\\Icons\\Spell_Deathknight_ClassIcon",
specs = { specs = {
[L["Unholy"]] = "Interface\\Icons\\Spell_Deathknight_UnholyPresence", [250] = { name = L["Blood"], icon = "Interface\\Icons\\Spell_Deathknight_BloodPresence" },
[L["Frost"]] = "Interface\\Icons\\Spell_Deathknight_FrostPresence", [251] = { name = L["Frost"], icon = "Interface\\Icons\\Spell_Deathknight_FrostPresence" },
[L["Blood"]] = "Interface\\Icons\\Spell_Deathknight_BloodPresence", [252] = { name = L["Unholy"], icon = "Interface\\Icons\\Spell_Deathknight_UnholyPresence" },
} }
}, },
DRUID = { DRUID = {
icon = "Interface\\Icons\\Ability_Druid_Maul", icon = "Interface\\Icons\\Ability_Druid_Maul",
specs = { specs = {
[L["Balance"]] = "Interface\\Icons\\Spell_Nature_StarFall", [102] = { name = L["Balance"], icon = "Interface\\Icons\\Spell_Nature_StarFall" },
[L["Restoration"]] = "Interface\\Icons\\Spell_Nature_HealingTouch", [103] = { name = L["Feral"], icon = "Interface\\Icons\\Ability_Racial_BearForm" },
[L["Feral Combat"]] = "Interface\\Icons\\Ability_Racial_BearForm", [104] = { name = L["Guardian"], icon = "Interface\\Icons\\Ability_Racial_BearForm" },
[L["Guardian"]] = "Interface\\Icons\\Ability_Racial_BearForm", [105] = { name = L["Restoration"], icon = "Interface\\Icons\\Spell_Nature_HealingTouch" },
} }
}, },
HUNTER = { HUNTER = {
icon = "Interface\\Icons\\INV_Weapon_Bow_07", icon = "Interface\\Icons\\INV_Weapon_Bow_07",
specs = { specs = {
[L["Marksmanship"]] = "Interface\\Icons\\Ability_Marksmanship", [253] = { name = L["Beast Mastery"], icon = "Interface\\Icons\\Ability_Hunter_BeastTaming" },
[L["Beast Mastery"]] = "Interface\\Icons\\Ability_Hunter_BeastTaming", [254] = { name = L["Marksmanship"], icon = "Interface\\Icons\\Ability_Marksmanship" },
[L["Survival"]] = "Interface\\Icons\\Ability_Hunter_SwiftStrike", [255] = { name = L["Survival"], icon = "Interface\\Icons\\Ability_Hunter_SwiftStrike" },
} }
}, },
MAGE = { MAGE = {
icon = "Interface\\Icons\\INV_Staff_13", icon = "Interface\\Icons\\INV_Staff_13",
specs = { specs = {
[L["Fire"]] = "Interface\\Icons\\Spell_Fire_FireBolt02", [62] = { name = L["Arcane"], icon = "Interface\\Icons\\Spell_Holy_MagicalSentry" },
[L["Frost"]] = "Interface\\Icons\\Spell_Frost_FrostBolt02", [63] = { name = L["Fire"], icon = "Interface\\Icons\\Spell_Fire_FireBolt02" },
[L["Arcane"]] = "Interface\\Icons\\Spell_Holy_MagicalSentry", [64] = { name = L["Frost"], icon = "Interface\\Icons\\Spell_Frost_FrostBolt02" },
} }
}, },
PALADIN = { PALADIN = {
icon = "Interface\\Icons\\INV_Hammer_01", icon = "Interface\\Icons\\INV_Hammer_01",
specs = { specs = {
[L["Protection"]] = "Interface\\Icons\\Spell_Holy_DevotionAura", [65] = { name = L["Holy"], icon = "Interface\\Icons\\Spell_Holy_HolyBolt" },
[L["Holy"]] = "Interface\\Icons\\Spell_Holy_HolyBolt", [66] = { name = L["Protection"], icon = "Interface\\Icons\\Spell_Holy_DevotionAura" },
[L["Retribution"]] = "Interface\\Icons\\Spell_Holy_AuraOfLight", [70] = { name = L["Retribution"], icon = "Interface\\Icons\\Spell_Holy_AuraOfLight" },
} }
}, },
PRIEST = { PRIEST = {
icon = "Interface\\Icons\\INV_Staff_30", icon = "Interface\\Icons\\INV_Staff_30",
specs = { specs = {
[L["Discipline"]] = "Interface\\Icons\\Spell_Holy_WordFortitude", [256] = { name = L["Discipline"], icon = "Interface\\Icons\\Spell_Holy_WordFortitude" },
[L["Holy"]] = "Interface\\Icons\\Spell_Holy_GuardianSpirit", [257] = { name = L["Holy"], icon = "Interface\\Icons\\Spell_Holy_GuardianSpirit" },
[L["Shadow"]] = "Interface\\Icons\\Spell_Shadow_ShadowWordPain", [258] = { name = L["Shadow"], icon = "Interface\\Icons\\Spell_Shadow_ShadowWordPain" },
} }
}, },
ROGUE = { ROGUE = {
icon = "Interface\\Icons\\INV_ThrowingKnife_04", icon = "Interface\\Icons\\INV_ThrowingKnife_04",
specs = { specs = {
[L["Subtlety"]] = "Interface\\Icons\\Ability_Stealth", [259] = { name = L["Assassination"], icon = "Interface\\Icons\\Ability_Rogue_Eviscerate" },
[L["Combat"]] = "Interface\\Icons\\Ability_BackStab", [260] = { name = L["Combat"], icon = "Interface\\Icons\\Ability_BackStab" },
[L["Assassination"]] = "Interface\\Icons\\Ability_Rogue_Eviscerate", [261] = { name = L["Subtlety"], icon = "Interface\\Icons\\Ability_Stealth" },
} }
}, },
SHAMAN = { SHAMAN = {
icon = "Interface\\Icons\\Spell_Nature_BloodLust", icon = "Interface\\Icons\\Spell_Nature_BloodLust",
specs = { specs = {
[L["Enhancement"]] = "Interface\\Icons\\Spell_Nature_LightningShield", [262] = { name = L["Elemental"], icon = "Interface\\Icons\\Spell_Nature_Lightning" },
[L["Elemental"]] = "Interface\\Icons\\Spell_Nature_Lightning", [263] = { name = L["Enhancement"], icon = "Interface\\Icons\\Spell_Nature_LightningShield" },
[L["Restoration"]] = "Interface\\Icons\\Spell_Nature_MagicImmunity", [264] = { name = L["Restoration"], icon = "Interface\\Icons\\Spell_Nature_MagicImmunity" },
} }
}, },
WARLOCK = { WARLOCK = {
icon = "Interface\\Icons\\Spell_Nature_FaerieFire", icon = "Interface\\Icons\\Spell_Nature_FaerieFire",
specs = { specs = {
[L["Demonology"]] = "Interface\\Icons\\Spell_Shadow_Metamorphosis", [265] = { name = L["Affliction"], icon = "Interface\\Icons\\Spell_Shadow_DeathCoil" },
[L["Affliction"]] = "Interface\\Icons\\Spell_Shadow_DeathCoil", [266] = { name = L["Demonology"], icon = "Interface\\Icons\\Spell_Shadow_Metamorphosis" },
[L["Destruction"]] = "Interface\\Icons\\Spell_Shadow_RainOfFire", [267] = { name = L["Destruction"], icon = "Interface\\Icons\\Spell_Shadow_RainOfFire" },
} }
}, },
WARRIOR = { WARRIOR = {
icon = "Interface\\Icons\\INV_Sword_27", icon = "Interface\\Icons\\INV_Sword_27",
specs = { specs = {
[L["Arms"]] = "Interface\\Icons\\Ability_Rogue_Eviscerate", [71] = { name = L["Arms"], icon = "Interface\\Icons\\Ability_Rogue_Eviscerate" },
[L["Protection"]] = "Interface\\Icons\\INV_Shield_06", [72] = { name = L["Fury"], icon = "Interface\\Icons\\Ability_Warrior_InnerRage" },
[L["Fury"]] = "Interface\\Icons\\Ability_Warrior_InnerRage", [73] = { name = L["Protection"], icon = "Interface\\Icons\\INV_Shield_06" },
} }
}, },
} }
-- Creates the options layout. Due to CUSTOM_CLASS_COLORS, it needs to be created dynamically.
local function createSpecString(class, spec) local function createSpecString(class, specID)
local data = classData[class] local data = classData[class]
if not data then return "" end
local classIcon = data.icon or "Interface\\Icons\\INV_Misc_QuestionMark" 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) 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 end
Private.spec_types_all = {} Private.spec_types_all = {}
Private.spec = {} Private.spec = {}
for class, data in pairs(classData) do for class, data in pairs(classData) do
for specName, specIcon in pairs(data.specs) do for specID in pairs(data.specs) do
local key = class .. specName Private.spec_types_all[specID] = createSpecString(class, specID)
Private.spec_types_all[key] = createSpecString(class, specName)
Private.spec[key] = specIcon
end end
end end
wipe(classData)
end 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 --[=[[ Old unused Talent List
Private.talents_ids = { 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}}, 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}},
+1 -1
View File
@@ -1,6 +1,6 @@
local AddonName, Private = ... local AddonName, Private = ...
local internalVersion = 83 local internalVersion = 83.25
-- Lua APIs -- Lua APIs
local insert = table.insert local insert = table.insert